Sanofi Capabilities

Naftiko 0.5 capability definitions for Sanofi - 100 capabilities showing integration workflows and service orchestrations.

Sort
Expand

When Datadog detects API rate limit breaches, creates a Jira investigation ticket, logs the event in Snowflake, and alerts the platform engineering team via Teams.

naftiko: "0.5"
info:
  label: "API Gateway Rate Limit Breach Handler"
  description: "When Datadog detects API rate limit breaches, creates a Jira investigation ticket, logs the event in Snowflake, and alerts the platform engineering team via Teams."
  tags:
    - platform-engineering
    - datadog
    - jira
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: platform-api-health
      port: 8080
      tools:
        - name: handle-rate-limit-breach
          description: "Handle API rate limit breach: create Jira ticket, log event, and alert platform team."
          inputParameters:
            - name: api_name
              in: body
              type: string
              description: "The API name that breached rate limits."
            - name: client_id
              in: body
              type: string
              description: "The client ID that exceeded the limit."
          steps:
            - name: get-breach-details
              type: call
              call: "datadog.get-events"
              with:
                tags: "api:{{api_name}},client:{{client_id}}"
            - name: create-ticket
              type: call
              call: "jira.create-issue"
              with:
                project: "PLATFORM"
                summary: "API rate limit breach: {{api_name}} by {{client_id}}"
                issue_type: "Task"
            - name: log-event
              type: call
              call: "snowflake.run-query"
              with:
                statement: "INSERT INTO platform.rate_limit_breaches (api_name, client_id, ticket_key, detected_at) VALUES ('{{api_name}}', '{{client_id}}', '{{create-ticket.key}}', CURRENT_TIMESTAMP())"
            - name: alert-platform
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.platform_team_id"
                channel_id: "$secrets.platform_channel_id"
                body: "Rate limit breach: {{api_name}} by client {{client_id}}. Jira: {{create-ticket.key}}."
  consumes:
    - type: http
      namespace: datadog
      baseUri: "https://api.datadoghq.com/api/v1"
      authentication:
        type: apiKey
        key: "$secrets.datadog_api_key"
      resources:
        - name: events
          path: "/events"
          operations:
            - name: get-events
              method: GET
    - type: http
      namespace: jira
      baseUri: "https://sanofi.atlassian.net/rest/api/3"
      authentication:
        type: basic
        username: "$secrets.jira_user"
        password: "$secrets.jira_api_token"
      resources:
        - name: issues
          path: "/issue"
          operations:
            - name: create-issue
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Audits Microsoft Entra conditional access policies, compares against compliance baselines in Snowflake, and creates a ServiceNow audit finding for any deviations.

naftiko: "0.5"
info:
  label: "Azure AD Conditional Access Policy Audit"
  description: "Audits Microsoft Entra conditional access policies, compares against compliance baselines in Snowflake, and creates a ServiceNow audit finding for any deviations."
  tags:
    - security
    - identity
    - microsoft-entra
    - snowflake
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: security-identity-audit
      port: 8080
      tools:
        - name: audit-conditional-access
          description: "Audit conditional access policies: pull Entra policies, compare baselines, and log findings."
          inputParameters:
            - name: policy_scope
              in: body
              type: string
              description: "The scope of policies to audit (e.g., all, gxp, corporate)."
          steps:
            - name: get-policies
              type: call
              call: "msgraph.get-ca-policies"
              with:
                scope: "{{policy_scope}}"
            - name: get-baselines
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT policy_name, required_controls FROM security.ca_policy_baselines WHERE scope='{{policy_scope}}'"
            - name: create-audit-finding
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "Conditional access policy audit: {{policy_scope}} scope"
                category: "security_audit"
                assigned_group: "Identity_Security"
  consumes:
    - type: http
      namespace: msgraph
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: ca-policies
          path: "/identity/conditionalAccess/policies"
          operations:
            - name: get-ca-policies
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST

Retrieves month-to-date cost for a specified Azure resource group, used for cloud FinOps reporting and budget tracking.

naftiko: "0.5"
info:
  label: "Azure Resource Group Cost Lookup"
  description: "Retrieves month-to-date cost for a specified Azure resource group, used for cloud FinOps reporting and budget tracking."
  tags:
    - finops
    - microsoft-azure
capability:
  exposes:
    - type: mcp
      namespace: finops-cloud
      port: 8080
      tools:
        - name: get-resource-group-cost
          description: "Look up Azure month-to-date cost for a resource group. Returns total cost and currency."
          inputParameters:
            - name: resource_group
              in: body
              type: string
              description: "The Azure resource group name."
          call: "azure-cost.get-cost"
          with:
            resource_group: "{{resource_group}}"
          outputParameters:
            - name: total_cost
              type: string
              mapping: "$.properties.rows[0][0]"
            - name: currency
              type: string
              mapping: "$.properties.rows[0][1]"
  consumes:
    - type: http
      namespace: azure-cost
      baseUri: "https://management.azure.com"
      authentication:
        type: bearer
        token: "$secrets.azure_mgmt_token"
      resources:
        - name: cost-query
          path: "/subscriptions/$secrets.azure_subscription_id/resourceGroups/{{resource_group}}/providers/Microsoft.CostManagement/query"
          inputParameters:
            - name: resource_group
              in: path
          operations:
            - name: get-cost
              method: POST

Checks the Azure Recovery Services vault for failed or missed VM backups and creates a ServiceNow alert for any failures found in the Sanofi production subscription.

naftiko: "0.5"
info:
  label: "Azure VM Backup Verification"
  description: "Checks the Azure Recovery Services vault for failed or missed VM backups and creates a ServiceNow alert for any failures found in the Sanofi production subscription."
  tags:
    - cloud
    - azure
    - servicenow
    - backup
    - operations
capability:
  exposes:
    - type: mcp
      namespace: cloud-backup
      port: 8080
      tools:
        - name: verify-vm-backups
          description: "Check the Azure Recovery Services vault for failed or missed VM backup jobs in the past 24 hours and create a ServiceNow incident for each failure."
          inputParameters:
            - name: subscription_id
              in: body
              type: string
              description: "The Azure subscription ID to check for backup failures."
            - name: vault_name
              in: body
              type: string
              description: "The Azure Recovery Services vault name."
            - name: resource_group
              in: body
              type: string
              description: "The Azure resource group containing the vault."
          steps:
            - name: get-backup-jobs
              type: call
              call: "azure-backup.list-backup-jobs"
              with:
                subscriptionId: "{{subscription_id}}"
                vaultName: "{{vault_name}}"
                resourceGroup: "{{resource_group}}"
            - name: create-alert
              type: call
              call: "servicenow-backup.create-incident"
              with:
                short_description: "Azure VM backup failure in vault {{vault_name}}"
                description: "Failed jobs: {{get-backup-jobs.failedJobs}}"
                urgency: "2"
  consumes:
    - type: http
      namespace: azure-backup
      baseUri: "https://management.azure.com"
      authentication:
        type: bearer
        token: "$secrets.azure_token"
      resources:
        - name: backup-jobs
          path: "/subscriptions/{{subscriptionId}}/resourceGroups/{{resourceGroup}}/providers/Microsoft.RecoveryServices/vaults/{{vaultName}}/backupJobs"
          inputParameters:
            - name: subscriptionId
              in: path
            - name: resourceGroup
              in: path
            - name: vaultName
              in: path
          operations:
            - name: list-backup-jobs
              method: GET
    - type: http
      namespace: servicenow-backup
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST

Monitors data freshness for Power BI reports by checking Snowflake pipeline timestamps, verifying refresh status in Power BI, and alerting the BI team via Teams if data is stale.

naftiko: "0.5"
info:
  label: "BI Report Data Freshness Monitor"
  description: "Monitors data freshness for Power BI reports by checking Snowflake pipeline timestamps, verifying refresh status in Power BI, and alerting the BI team via Teams if data is stale."
  tags:
    - analytics
    - snowflake
    - power-bi
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: analytics-freshness
      port: 8080
      tools:
        - name: monitor-data-freshness
          description: "Monitor BI data freshness: check pipeline timestamps, verify refresh status, and alert on staleness."
          inputParameters:
            - name: dataset_id
              in: body
              type: string
              description: "The Power BI dataset ID."
            - name: pipeline_name
              in: body
              type: string
              description: "The Snowflake pipeline name."
          steps:
            - name: check-pipeline
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT last_run_at, status FROM data_ops.pipeline_runs WHERE pipeline_name='{{pipeline_name}}' ORDER BY last_run_at DESC LIMIT 1"
            - name: check-refresh
              type: call
              call: "powerbi.get-refresh-history"
              with:
                dataset_id: "{{dataset_id}}"
            - name: alert-bi-team
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.bi_team_id"
                channel_id: "$secrets.bi_channel_id"
                body: "Data freshness check for dataset {{dataset_id}}: Pipeline {{pipeline_name}} last ran at {{check-pipeline.last_run_at}}. Power BI refresh status: {{check-refresh.status}}."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: refresh-history
          path: "/datasets/{{dataset_id}}/refreshes"
          inputParameters:
            - name: dataset_id
              in: path
          operations:
            - name: get-refresh-history
              method: GET
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Integrates biomarker assay results by loading data into Snowflake from lab systems, updating the clinical database status in Veeva Vault, and notifying the biostatistics team via Teams.

naftiko: "0.5"
info:
  label: "Clinical Biomarker Data Integration"
  description: "Integrates biomarker assay results by loading data into Snowflake from lab systems, updating the clinical database status in Veeva Vault, and notifying the biostatistics team via Teams."
  tags:
    - clinical
    - research
    - snowflake
    - veeva
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: clinical-biomarker
      port: 8080
      tools:
        - name: integrate-biomarker-data
          description: "Integrate biomarker data: load to Snowflake, update Veeva status, and notify biostatistics."
          inputParameters:
            - name: study_id
              in: body
              type: string
              description: "The clinical study ID."
            - name: assay_batch_id
              in: body
              type: string
              description: "The assay batch identifier."
          steps:
            - name: load-assay-results
              type: call
              call: "snowflake.run-query"
              with:
                statement: "INSERT INTO clinical.biomarker_results (study_id, assay_batch_id, loaded_at) VALUES ('{{study_id}}', '{{assay_batch_id}}', CURRENT_TIMESTAMP())"
            - name: update-vault-status
              type: call
              call: "veeva-vault.update-document"
              with:
                doc_id: "{{assay_batch_id}}"
                status: "data_loaded"
            - name: notify-biostats
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.biostats_team_id"
                channel_id: "$secrets.biostats_channel_id"
                body: "Biomarker data loaded for study {{study_id}}, batch {{assay_batch_id}}. Ready for analysis."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: documents
          path: "/objects/documents/{{doc_id}}"
          inputParameters:
            - name: doc_id
              in: path
          operations:
            - name: update-document
              method: PUT
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Validates clinical trial data lock readiness by running quality checks in Snowflake, verifying edit checks in Veeva Vault, and generating a lock-readiness report posted to Teams.

naftiko: "0.5"
info:
  label: "Clinical Data Lock Validation"
  description: "Validates clinical trial data lock readiness by running quality checks in Snowflake, verifying edit checks in Veeva Vault, and generating a lock-readiness report posted to Teams."
  tags:
    - clinical
    - data-management
    - snowflake
    - veeva
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: clinical-data-lock
      port: 8080
      tools:
        - name: validate-data-lock
          description: "Validate clinical data lock readiness: run quality checks, verify edit checks, and generate report."
          inputParameters:
            - name: trial_id
              in: body
              type: string
              description: "The clinical trial ID."
            - name: database_name
              in: body
              type: string
              description: "The clinical database name."
          steps:
            - name: run-quality-checks
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT check_name, status, error_count FROM clinical.data_quality_checks WHERE trial_id='{{trial_id}}' AND database_name='{{database_name}}'"
            - name: verify-edit-checks
              type: call
              call: "veeva-vault.query-documents"
              with:
                query: "SELECT id, status__v FROM documents WHERE trial_id__v='{{trial_id}}' AND type__v='edit_check_report'"
            - name: post-report
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.clinical_dm_team_id"
                channel_id: "$secrets.clinical_dm_channel_id"
                body: "Data lock validation for trial {{trial_id}}, database {{database_name}}: quality checks and edit checks completed. Review results for lock readiness."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: query
          path: "/query"
          operations:
            - name: query-documents
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Tracks clinical trial site activation by checking Veeva Vault for regulatory documents, verifying site readiness in Snowflake, and updating the project manager via Teams.

naftiko: "0.5"
info:
  label: "Clinical Site Activation Tracker"
  description: "Tracks clinical trial site activation by checking Veeva Vault for regulatory documents, verifying site readiness in Snowflake, and updating the project manager via Teams."
  tags:
    - clinical
    - veeva
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: clinical-site-mgmt
      port: 8080
      tools:
        - name: check-site-activation
          description: "Check site activation readiness: verify regulatory documents in Veeva, check site milestones in Snowflake, and notify the project manager."
          inputParameters:
            - name: site_id
              in: body
              type: string
              description: "The clinical trial site identifier."
            - name: trial_id
              in: body
              type: string
              description: "The clinical trial ID."
          steps:
            - name: check-regulatory-docs
              type: call
              call: "veeva-vault.query-documents"
              with:
                query: "SELECT id, status__v FROM documents WHERE site_id__v = '{{site_id}}' AND type__v = 'regulatory_essential'"
            - name: check-milestones
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT milestone_name, status FROM clinical.site_milestones WHERE site_id = '{{site_id}}' AND trial_id = '{{trial_id}}'"
            - name: notify-pm
              type: call
              call: "msteams.post-message"
              with:
                recipient: "$secrets.clinical_pm_email"
                message: "Site {{site_id}} for trial {{trial_id}}: regulatory docs checked, milestones reviewed. Ready for activation assessment."
  consumes:
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: query
          path: "/query"
          operations:
            - name: query-documents
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST

When an adverse event is logged in Veeva Vault, creates a safety case in the pharmacovigilance system, notifies the medical safety officer via Teams, and updates the clinical trial tracker in Snowflake.

naftiko: "0.5"
info:
  label: "Clinical Trial Adverse Event Reporting"
  description: "When an adverse event is logged in Veeva Vault, creates a safety case in the pharmacovigilance system, notifies the medical safety officer via Teams, and updates the clinical trial tracker in Snowflake."
  tags:
    - clinical
    - pharmacovigilance
    - veeva
    - microsoft-teams
    - snowflake
capability:
  exposes:
    - type: mcp
      namespace: clinical-safety
      port: 8080
      tools:
        - name: report-adverse-event
          description: "Orchestrate adverse event reporting: retrieve event details from Veeva Vault, create a safety case, notify the medical officer, and log in Snowflake."
          inputParameters:
            - name: event_id
              in: body
              type: string
              description: "The Veeva Vault adverse event document ID."
            - name: trial_id
              in: body
              type: string
              description: "The clinical trial identifier."
          steps:
            - name: get-event
              type: call
              call: "veeva-vault.get-document"
              with:
                doc_id: "{{event_id}}"
            - name: create-safety-case
              type: call
              call: "veeva-vault.create-document"
              with:
                type: "safety_case"
                trial_id: "{{trial_id}}"
                source_event: "{{event_id}}"
                severity: "{{get-event.severity__v}}"
            - name: notify-safety-officer
              type: call
              call: "msteams.post-message"
              with:
                recipient: "{{get-event.safety_officer_email}}"
                message: "Adverse event {{event_id}} reported for trial {{trial_id}} with severity {{get-event.severity__v}}. Safety case {{create-safety-case.id}} created."
            - name: log-to-snowflake
              type: call
              call: "snowflake.run-query"
              with:
                statement: "INSERT INTO clinical.adverse_events (event_id, trial_id, severity, case_id, reported_at) VALUES ('{{event_id}}', '{{trial_id}}', '{{get-event.severity__v}}', '{{create-safety-case.id}}', CURRENT_TIMESTAMP())"
  consumes:
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: documents
          path: "/objects/documents/{{doc_id}}"
          inputParameters:
            - name: doc_id
              in: path
          operations:
            - name: get-document
              method: GET
            - name: create-document
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST

Queries Veeva Vault for clinical trial data completeness issues and posts a data quality digest to the clinical data management team channel in Teams.

naftiko: "0.5"
info:
  label: "Clinical Trial Data Quality Check"
  description: "Queries Veeva Vault for clinical trial data completeness issues and posts a data quality digest to the clinical data management team channel in Teams."
  tags:
    - clinical
    - veeva
    - microsoft-teams
    - data-quality
    - pharma
capability:
  exposes:
    - type: mcp
      namespace: clinical-data-ops
      port: 8080
      tools:
        - name: check-trial-data-quality
          description: "Given a Veeva Vault study ID, retrieve data entry completeness metrics and post a quality digest to the clinical data management Teams channel."
          inputParameters:
            - name: study_id
              in: body
              type: string
              description: "The Veeva Vault clinical study ID to check."
            - name: cutoff_date
              in: body
              type: string
              description: "The data cutoff date for the quality check in YYYY-MM-DD format."
          steps:
            - name: get-study-metrics
              type: call
              call: "veeva-cdm.get-study-metrics"
              with:
                study_id: "{{study_id}}"
                cutoff: "{{cutoff_date}}"
            - name: post-digest
              type: call
              call: "msteams-cdm.post-message"
              with:
                channel: "clinical-data-management"
                message: "Data quality digest for study {{study_id}} (cutoff: {{cutoff_date}}): Completeness={{get-study-metrics.completeness}}%, Open queries={{get-study-metrics.openQueries}}"
  consumes:
    - type: http
      namespace: veeva-cdm
      baseUri: "https://sanofi.veevavault.com/api/v21.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_token"
      resources:
        - name: study-metrics
          path: "/objects/studies/{{study_id}}/metrics"
          inputParameters:
            - name: study_id
              in: path
          operations:
            - name: get-study-metrics
              method: GET
    - type: http
      namespace: msteams-cdm
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Generates patient enrollment analytics by pulling data from Snowflake, refreshing the Power BI enrollment dashboard, and posting a summary to the clinical ops Teams channel.

naftiko: "0.5"
info:
  label: "Clinical Trial Patient Enrollment Dashboard"
  description: "Generates patient enrollment analytics by pulling data from Snowflake, refreshing the Power BI enrollment dashboard, and posting a summary to the clinical ops Teams channel."
  tags:
    - clinical
    - analytics
    - snowflake
    - power-bi
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: clinical-enrollment
      port: 8080
      tools:
        - name: refresh-enrollment-dashboard
          description: "Refresh enrollment dashboard: pull Snowflake data, refresh Power BI, and post summary."
          inputParameters:
            - name: trial_id
              in: body
              type: string
              description: "The clinical trial ID."
          steps:
            - name: get-enrollment-data
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT site_id, enrolled_count, target_count, enrollment_rate FROM clinical.patient_enrollment WHERE trial_id='{{trial_id}}'"
            - name: refresh-powerbi
              type: call
              call: "powerbi.trigger-refresh"
              with:
                dataset_id: "$secrets.enrollment_dataset_id"
            - name: post-summary
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.clinical_ops_team_id"
                channel_id: "$secrets.clinical_ops_channel_id"
                body: "Enrollment dashboard refreshed for trial {{trial_id}}. Check Power BI for updated site-level metrics."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: dataset-refresh
          path: "/datasets/{{dataset_id}}/refreshes"
          inputParameters:
            - name: dataset_id
              in: path
          operations:
            - name: trigger-refresh
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

When AWS spend anomalies exceed the configured threshold, creates a ServiceNow change request to investigate and notifies the cloud FinOps team in Teams.

naftiko: "0.5"
info:
  label: "Cloud Cost Anomaly Alert"
  description: "When AWS spend anomalies exceed the configured threshold, creates a ServiceNow change request to investigate and notifies the cloud FinOps team in Teams."
  tags:
    - cloud
    - finops
    - aws
    - servicenow
    - microsoft-teams
    - cost-management
capability:
  exposes:
    - type: mcp
      namespace: cloud-finops
      port: 8080
      tools:
        - name: handle-cost-anomaly
          description: "Given an AWS account ID, service name, and anomaly amount, create a ServiceNow investigation request and alert the FinOps team in Teams."
          inputParameters:
            - name: account_id
              in: body
              type: string
              description: "The AWS account ID where the cost anomaly was detected."
            - name: service_name
              in: body
              type: string
              description: "The AWS service with anomalous spend."
            - name: anomaly_amount
              in: body
              type: number
              description: "The unexpected spend amount in USD."
          steps:
            - name: create-change
              type: call
              call: "servicenow-cost.create-change"
              with:
                short_description: "AWS cost anomaly: ${{anomaly_amount}} on {{service_name}} in account {{account_id}}"
                category: "cloud_finops"
                priority: "2"
            - name: notify-finops
              type: call
              call: "msteams-cost.post-message"
              with:
                channel: "cloud-cost-ops"
                message: "Cost anomaly: {{service_name}} in {{account_id}} — ${{anomaly_amount}} | SNOW: {{create-change.number}}"
  consumes:
    - type: http
      namespace: servicenow-cost
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: changes
          path: "/table/change_request"
          operations:
            - name: create-change
              method: POST
    - type: http
      namespace: msteams-cost
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Realigns sales territories by updating Veeva CRM assignments, syncing changes to Snowflake analytics, and notifying field managers via Teams.

naftiko: "0.5"
info:
  label: "Commercial Field Force Territory Realignment"
  description: "Realigns sales territories by updating Veeva CRM assignments, syncing changes to Snowflake analytics, and notifying field managers via Teams."
  tags:
    - commercial
    - veeva
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: commercial-territory
      port: 8080
      tools:
        - name: realign-territory
          description: "Realign a sales territory: update Veeva CRM, sync to Snowflake, and notify field managers."
          inputParameters:
            - name: rep_id
              in: body
              type: string
              description: "The sales representative ID."
            - name: new_territory
              in: body
              type: string
              description: "The new territory code."
          steps:
            - name: update-crm
              type: call
              call: "veeva-crm.update-territory"
              with:
                rep_id: "{{rep_id}}"
                territory: "{{new_territory}}"
            - name: sync-analytics
              type: call
              call: "snowflake.run-query"
              with:
                statement: "UPDATE commercial.territory_assignments SET territory_code='{{new_territory}}', updated_at=CURRENT_TIMESTAMP() WHERE rep_id='{{rep_id}}'"
            - name: notify-manager
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.commercial_team_id"
                channel_id: "$secrets.commercial_channel_id"
                body: "Territory realignment: Rep {{rep_id}} reassigned to territory {{new_territory}}."
  consumes:
    - type: http
      namespace: veeva-crm
      baseUri: "https://sanofi.veevanetwork.com/api/v1"
      authentication:
        type: bearer
        token: "$secrets.veeva_crm_token"
      resources:
        - name: territory-assignments
          path: "/territories/{{rep_id}}"
          inputParameters:
            - name: rep_id
              in: path
          operations:
            - name: update-territory
              method: PUT
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Collects audit evidence by gathering control test results from ServiceNow, pulling supporting data from Snowflake, and assembling the evidence package in SharePoint.

naftiko: "0.5"
info:
  label: "Compliance Audit Evidence Collector"
  description: "Collects audit evidence by gathering control test results from ServiceNow, pulling supporting data from Snowflake, and assembling the evidence package in SharePoint."
  tags:
    - compliance
    - audit
    - servicenow
    - snowflake
    - sharepoint
capability:
  exposes:
    - type: mcp
      namespace: compliance-audit
      port: 8080
      tools:
        - name: collect-audit-evidence
          description: "Collect audit evidence: gather control results, pull data, and assemble evidence package."
          inputParameters:
            - name: audit_id
              in: body
              type: string
              description: "The audit identifier."
            - name: control_id
              in: body
              type: string
              description: "The control identifier."
          steps:
            - name: get-control-results
              type: call
              call: "servicenow.get-control-test"
              with:
                audit_id: "{{audit_id}}"
                control_id: "{{control_id}}"
            - name: get-supporting-data
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT evidence_type, description, collected_at FROM compliance.audit_evidence WHERE audit_id='{{audit_id}}' AND control_id='{{control_id}}'"
            - name: upload-to-sharepoint
              type: call
              call: "sharepoint.upload-file"
              with:
                site_id: "$secrets.audit_site_id"
                folder: "{{audit_id}}/{{control_id}}"
                file_name: "evidence_package.json"
  consumes:
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: control-tests
          path: "/table/sn_compliance_control_test"
          operations:
            - name: get-control-test
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: drive-items
          path: "/sites/{{site_id}}/drive/items"
          inputParameters:
            - name: site_id
              in: path
          operations:
            - name: upload-file
              method: PUT

Retrieves the title and body content of a Confluence page by page ID, for knowledge management and documentation queries.

naftiko: "0.5"
info:
  label: "Confluence Page Content Lookup"
  description: "Retrieves the title and body content of a Confluence page by page ID, for knowledge management and documentation queries."
  tags:
    - knowledge-management
    - confluence
capability:
  exposes:
    - type: mcp
      namespace: km-docs
      port: 8080
      tools:
        - name: get-page-content
          description: "Look up a Confluence page by ID. Returns the page title and body content."
          inputParameters:
            - name: page_id
              in: body
              type: string
              description: "The Confluence page ID."
          call: "confluence.get-page"
          with:
            page_id: "{{page_id}}"
          outputParameters:
            - name: title
              type: string
              mapping: "$.title"
            - name: body
              type: string
              mapping: "$.body.storage.value"
  consumes:
    - type: http
      namespace: confluence
      baseUri: "https://sanofi.atlassian.net/wiki/rest/api"
      authentication:
        type: basic
        username: "$secrets.confluence_user"
        password: "$secrets.confluence_api_token"
      resources:
        - name: pages
          path: "/content/{{page_id}}?expand=body.storage"
          inputParameters:
            - name: page_id
              in: path
          operations:
            - name: get-page
              method: GET

Reviews contract manufacturer quality by pulling batch data from SAP QM, checking quality KPIs in Snowflake, and creating a review report in ServiceNow.

naftiko: "0.5"
info:
  label: "Contract Manufacturer Quality Review"
  description: "Reviews contract manufacturer quality by pulling batch data from SAP QM, checking quality KPIs in Snowflake, and creating a review report in ServiceNow."
  tags:
    - quality
    - manufacturing
    - sap
    - snowflake
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: quality-cmo-review
      port: 8080
      tools:
        - name: review-cmo-quality
          description: "Review CMO quality: pull batch data, check KPIs, and create review report."
          inputParameters:
            - name: vendor_id
              in: body
              type: string
              description: "The contract manufacturer vendor ID."
            - name: review_period
              in: body
              type: string
              description: "The review period."
          steps:
            - name: get-batch-data
              type: call
              call: "sap-qm.get-vendor-lots"
              with:
                vendor_id: "{{vendor_id}}"
                period: "{{review_period}}"
            - name: get-quality-kpis
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT rejection_rate, deviation_count, otif_score FROM quality.cmo_kpis WHERE vendor_id='{{vendor_id}}' AND period='{{review_period}}'"
            - name: create-review-report
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "CMO quality review: vendor {{vendor_id}} for {{review_period}}"
                category: "quality_review"
                assigned_group: "Quality_Operations"
  consumes:
    - type: http
      namespace: sap-qm
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_INSPECTIONLOT_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: inspection-lots
          path: "/A_InspectionLot"
          operations:
            - name: get-vendor-lots
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST

When a Databricks job fails, retrieves error logs, creates a Jira ticket for the data engineering team, and posts a failure alert to the data ops Teams channel.

naftiko: "0.5"
info:
  label: "Data Pipeline Failure Recovery Orchestrator"
  description: "When a Databricks job fails, retrieves error logs, creates a Jira ticket for the data engineering team, and posts a failure alert to the data ops Teams channel."
  tags:
    - data-engineering
    - databricks
    - jira
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: data-ops-recovery
      port: 8080
      tools:
        - name: handle-pipeline-failure
          description: "Handle data pipeline failure: get error logs, create Jira ticket, and alert data ops."
          inputParameters:
            - name: run_id
              in: body
              type: string
              description: "The failed Databricks job run ID."
            - name: job_name
              in: body
              type: string
              description: "The Databricks job name."
          steps:
            - name: get-run-details
              type: call
              call: "databricks.get-run"
              with:
                run_id: "{{run_id}}"
            - name: create-jira-ticket
              type: call
              call: "jira.create-issue"
              with:
                project: "DATAENG"
                summary: "Pipeline failure: {{job_name}} (run {{run_id}})"
                description: "State: {{get-run-details.state.result_state}}. Error: {{get-run-details.state.state_message}}"
                issue_type: "Bug"
            - name: alert-data-ops
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.dataops_team_id"
                channel_id: "$secrets.dataops_channel_id"
                body: "Pipeline {{job_name}} failed. Run ID: {{run_id}}. Jira: {{create-jira-ticket.key}}."
  consumes:
    - type: http
      namespace: databricks
      baseUri: "https://sanofi.cloud.databricks.com/api/2.1"
      authentication:
        type: bearer
        token: "$secrets.databricks_token"
      resources:
        - name: job-runs
          path: "/jobs/runs/get"
          operations:
            - name: get-run
              method: GET
    - type: http
      namespace: jira
      baseUri: "https://sanofi.atlassian.net/rest/api/3"
      authentication:
        type: basic
        username: "$secrets.jira_user"
        password: "$secrets.jira_api_token"
      resources:
        - name: issues
          path: "/issue"
          operations:
            - name: create-issue
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Checks the status of a Databricks job run by run ID, returning state, start time, and duration for data pipeline monitoring.

naftiko: "0.5"
info:
  label: "Databricks Job Run Status Lookup"
  description: "Checks the status of a Databricks job run by run ID, returning state, start time, and duration for data pipeline monitoring."
  tags:
    - data-engineering
    - databricks
capability:
  exposes:
    - type: mcp
      namespace: data-pipeline
      port: 8080
      tools:
        - name: get-job-run-status
          description: "Check status of a Databricks job run by run ID. Returns state, start time, and execution duration."
          inputParameters:
            - name: run_id
              in: body
              type: string
              description: "The Databricks job run ID."
          call: "databricks.get-run"
          with:
            run_id: "{{run_id}}"
          outputParameters:
            - name: state
              type: string
              mapping: "$.state.life_cycle_state"
            - name: start_time
              type: string
              mapping: "$.start_time"
            - name: duration_ms
              type: integer
              mapping: "$.execution_duration"
  consumes:
    - type: http
      namespace: databricks
      baseUri: "https://sanofi.cloud.databricks.com/api/2.1"
      authentication:
        type: bearer
        token: "$secrets.databricks_token"
      resources:
        - name: job-runs
          path: "/jobs/runs/get"
          operations:
            - name: get-run
              method: GET

When a Datadog critical monitor fires for Sanofi infrastructure, automatically creates a P1 ServiceNow incident and notifies the IT operations team in Teams.

naftiko: "0.5"
info:
  label: "Datadog Alert to ServiceNow Incident"
  description: "When a Datadog critical monitor fires for Sanofi infrastructure, automatically creates a P1 ServiceNow incident and notifies the IT operations team in Teams."
  tags:
    - itsm
    - observability
    - datadog
    - servicenow
    - microsoft-teams
    - incident-response
capability:
  exposes:
    - type: mcp
      namespace: itsm-alerting
      port: 8080
      tools:
        - name: handle-datadog-alert
          description: "Given a Datadog monitor ID, name, and alert body, create a P1 ServiceNow incident and notify the IT operations team in Teams."
          inputParameters:
            - name: monitor_id
              in: body
              type: string
              description: "The Datadog monitor ID that fired."
            - name: monitor_name
              in: body
              type: string
              description: "The human-readable name of the Datadog monitor."
            - name: alert_body
              in: body
              type: string
              description: "The alert message body from Datadog."
          steps:
            - name: create-incident
              type: call
              call: "servicenow-dd.create-incident"
              with:
                short_description: "Datadog Alert: {{monitor_name}}"
                description: "{{alert_body}}"
                urgency: "1"
                impact: "1"
            - name: notify-it-ops
              type: call
              call: "msteams-dd.post-message"
              with:
                channel: "it-incidents"
                message: "P1 Incident: {{monitor_name}} | SNOW: {{create-incident.number}} | Monitor: {{monitor_id}}"
  consumes:
    - type: http
      namespace: servicenow-dd
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST
    - type: http
      namespace: msteams-dd
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Queries Datadog for the current health status of a monitored service, returning overall state and last check timestamp.

naftiko: "0.5"
info:
  label: "Datadog Service Status Check"
  description: "Queries Datadog for the current health status of a monitored service, returning overall state and last check timestamp."
  tags:
    - observability
    - datadog
capability:
  exposes:
    - type: mcp
      namespace: observability-health
      port: 8080
      tools:
        - name: get-service-status
          description: "Check the health status of a Datadog-monitored service by service name. Returns current state and last evaluation time."
          inputParameters:
            - name: service_name
              in: body
              type: string
              description: "The Datadog service name."
          call: "datadog.get-monitor-status"
          with:
            service: "{{service_name}}"
          outputParameters:
            - name: status
              type: string
              mapping: "$.overall_state"
            - name: last_check
              type: string
              mapping: "$.overall_state_modified"
  consumes:
    - type: http
      namespace: datadog
      baseUri: "https://api.datadoghq.com/api/v1"
      authentication:
        type: apiKey
        key: "$secrets.datadog_api_key"
      resources:
        - name: monitors
          path: "/monitor"
          operations:
            - name: get-monitor-status
              method: GET

Retrieves SLO compliance burn rates from Datadog across Sanofi's digital platforms and posts a weekly digest to the engineering leadership channel in Teams.

naftiko: "0.5"
info:
  label: "Datadog SLO Compliance Digest"
  description: "Retrieves SLO compliance burn rates from Datadog across Sanofi's digital platforms and posts a weekly digest to the engineering leadership channel in Teams."
  tags:
    - observability
    - datadog
    - microsoft-teams
    - slo
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: observability-reporting
      port: 8080
      tools:
        - name: digest-slo-compliance
          description: "Retrieve active SLO compliance percentages from Datadog filtered by team tag and post a weekly digest to the Teams engineering leadership channel."
          inputParameters:
            - name: slo_tag
              in: body
              type: string
              description: "A Datadog tag to filter SLOs by (e.g., team:digital-health)."
          steps:
            - name: get-slos
              type: call
              call: "datadog-slo.list-slos"
              with:
                tags_query: "{{slo_tag}}"
            - name: post-digest
              type: call
              call: "msteams-slo.post-message"
              with:
                channel: "engineering-leadership"
                message: "Weekly SLO digest for {{slo_tag}}: {{get-slos.summary}}"
  consumes:
    - type: http
      namespace: datadog-slo
      baseUri: "https://api.datadoghq.com/api/v1"
      authentication:
        type: apikey
        key: "DD-API-KEY"
        value: "$secrets.datadog_api_key"
        placement: header
      resources:
        - name: slos
          path: "/slo"
          operations:
            - name: list-slos
              method: GET
    - type: http
      namespace: msteams-slo
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Syncs digital marketing campaign performance from HubSpot to Snowflake analytics, refreshes the Power BI marketing dashboard, and posts highlights to the marketing Teams channel.

naftiko: "0.5"
info:
  label: "Digital Marketing Campaign Performance Sync"
  description: "Syncs digital marketing campaign performance from HubSpot to Snowflake analytics, refreshes the Power BI marketing dashboard, and posts highlights to the marketing Teams channel."
  tags:
    - marketing
    - hubspot
    - snowflake
    - power-bi
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: marketing-analytics
      port: 8080
      tools:
        - name: sync-campaign-performance
          description: "Sync campaign performance: pull HubSpot data, load to Snowflake, refresh dashboard, and notify marketing."
          inputParameters:
            - name: campaign_id
              in: body
              type: string
              description: "The HubSpot campaign ID."
          steps:
            - name: get-campaign-data
              type: call
              call: "hubspot.get-campaign"
              with:
                campaign_id: "{{campaign_id}}"
            - name: load-to-snowflake
              type: call
              call: "snowflake.run-query"
              with:
                statement: "INSERT INTO marketing.campaign_metrics (campaign_id, impressions, clicks, conversions, synced_at) VALUES ('{{campaign_id}}', '{{get-campaign-data.counters.impressions}}', '{{get-campaign-data.counters.clicks}}', '{{get-campaign-data.counters.conversions}}', CURRENT_TIMESTAMP())"
            - name: refresh-dashboard
              type: call
              call: "powerbi.trigger-refresh"
              with:
                dataset_id: "$secrets.marketing_dataset_id"
            - name: notify-marketing
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.marketing_team_id"
                channel_id: "$secrets.marketing_channel_id"
                body: "Campaign {{campaign_id}} metrics synced. Dashboard refreshing."
  consumes:
    - type: http
      namespace: hubspot
      baseUri: "https://api.hubapi.com"
      authentication:
        type: bearer
        token: "$secrets.hubspot_token"
      resources:
        - name: campaigns
          path: "/marketing/v3/campaigns/{{campaign_id}}"
          inputParameters:
            - name: campaign_id
              in: path
          operations:
            - name: get-campaign
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: dataset-refresh
          path: "/datasets/{{dataset_id}}/refreshes"
          inputParameters:
            - name: dataset_id
              in: path
          operations:
            - name: trigger-refresh
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Orchestrates batch release by pulling QC results from SAP QM, checking compliance in Veeva Vault, notifying QA via Teams, and updating the batch record in Snowflake.

naftiko: "0.5"
info:
  label: "Drug Product Batch Release Workflow"
  description: "Orchestrates batch release by pulling QC results from SAP QM, checking compliance in Veeva Vault, notifying QA via Teams, and updating the batch record in Snowflake."
  tags:
    - manufacturing
    - quality
    - sap
    - veeva
    - microsoft-teams
    - snowflake
capability:
  exposes:
    - type: mcp
      namespace: mfg-batch-release
      port: 8080
      tools:
        - name: release-batch
          description: "Orchestrate drug product batch release: pull QC results, verify compliance documents, notify QA team, and update analytics."
          inputParameters:
            - name: batch_number
              in: body
              type: string
              description: "The manufacturing batch number."
            - name: material_number
              in: body
              type: string
              description: "The SAP material number for the drug product."
          steps:
            - name: get-qc-results
              type: call
              call: "sap-qm.get-inspection-lot"
              with:
                batch: "{{batch_number}}"
                material: "{{material_number}}"
            - name: check-compliance-doc
              type: call
              call: "veeva-vault.get-document"
              with:
                doc_id: "{{get-qc-results.compliance_doc_id}}"
            - name: notify-qa
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.qa_team_id"
                channel_id: "$secrets.qa_channel_id"
                body: "Batch {{batch_number}} QC complete. Status: {{get-qc-results.inspection_result}}. Compliance doc: {{check-compliance-doc.status__v}}."
            - name: update-analytics
              type: call
              call: "snowflake.run-query"
              with:
                statement: "UPDATE manufacturing.batch_records SET qc_status='{{get-qc-results.inspection_result}}', released_at=CURRENT_TIMESTAMP() WHERE batch_number='{{batch_number}}'"
  consumes:
    - type: http
      namespace: sap-qm
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_INSPECTIONLOT_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: inspection-lots
          path: "/A_InspectionLot"
          operations:
            - name: get-inspection-lot
              method: GET
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: documents
          path: "/objects/documents/{{doc_id}}"
          inputParameters:
            - name: doc_id
              in: path
          operations:
            - name: get-document
              method: GET
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST

Generates periodic safety update reports by pulling aggregate data from Snowflake, creating the report document in Veeva Vault, and notifying the drug safety team via Teams.

naftiko: "0.5"
info:
  label: "Drug Safety Periodic Report Generation"
  description: "Generates periodic safety update reports by pulling aggregate data from Snowflake, creating the report document in Veeva Vault, and notifying the drug safety team via Teams."
  tags:
    - pharmacovigilance
    - snowflake
    - veeva
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: pv-periodic-report
      port: 8080
      tools:
        - name: generate-safety-report
          description: "Generate periodic safety report: aggregate data, create Veeva document, and notify safety team."
          inputParameters:
            - name: product_name
              in: body
              type: string
              description: "The drug product name."
            - name: report_period
              in: body
              type: string
              description: "The reporting period (e.g., 2026-Q1)."
          steps:
            - name: aggregate-safety-data
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT event_type, COUNT(*) as event_count, severity FROM pv.adverse_events WHERE product_name='{{product_name}}' AND report_period='{{report_period}}' GROUP BY event_type, severity"
            - name: create-report-doc
              type: call
              call: "veeva-vault.create-document"
              with:
                type: "periodic_safety_report"
                product: "{{product_name}}"
                period: "{{report_period}}"
            - name: notify-safety-team
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.pv_team_id"
                channel_id: "$secrets.pv_channel_id"
                body: "Periodic safety report for {{product_name}} ({{report_period}}) generated. Document ID: {{create-report-doc.id}}."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: documents
          path: "/objects/documents"
          operations:
            - name: create-document
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

When an employee departure is recorded in Workday, disables the Microsoft 365 account, revokes SAP access, and notifies the IT security team in Teams.

naftiko: "0.5"
info:
  label: "Employee Offboarding Workflow"
  description: "When an employee departure is recorded in Workday, disables the Microsoft 365 account, revokes SAP access, and notifies the IT security team in Teams."
  tags:
    - hr
    - offboarding
    - workday
    - microsoft-365
    - sap
    - microsoft-teams
    - identity
capability:
  exposes:
    - type: mcp
      namespace: hr-offboarding
      port: 8080
      tools:
        - name: trigger-offboarding
          description: "Given a Workday employee ID and termination date, disable the Microsoft 365 account, lock SAP credentials, and alert the IT security team in Teams."
          inputParameters:
            - name: employee_id
              in: body
              type: string
              description: "The Workday worker ID of the departing employee."
            - name: termination_date
              in: body
              type: string
              description: "The employee's last working day in YYYY-MM-DD format."
          steps:
            - name: get-employee
              type: call
              call: "workday-off.get-worker"
              with:
                worker_id: "{{employee_id}}"
            - name: disable-m365
              type: call
              call: "msgraph-off.disable-user"
              with:
                userPrincipalName: "{{get-employee.workEmail}}"
            - name: lock-sap-user
              type: call
              call: "sap-off.lock-user"
              with:
                userId: "{{get-employee.sapUserId}}"
            - name: notify-security
              type: call
              call: "msteams-off.post-message"
              with:
                channel: "it-security-alerts"
                message: "Offboarding complete for {{get-employee.displayName}} ({{termination_date}}). M365 disabled, SAP locked."
  consumes:
    - type: http
      namespace: workday-off
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: workers
          path: "/sanofi/workers/{{worker_id}}"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-worker
              method: GET
    - type: http
      namespace: msgraph-off
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: users
          path: "/users/{{userPrincipalName}}"
          inputParameters:
            - name: userPrincipalName
              in: path
          operations:
            - name: disable-user
              method: PATCH
    - type: http
      namespace: sap-off
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_USERACCOUNT_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: user-accounts
          path: "/A_UserAccount('{{userId}}')"
          inputParameters:
            - name: userId
              in: path
          operations:
            - name: lock-user
              method: POST
    - type: http
      namespace: msteams-off
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

When an employee transfers departments in Workday, updates their cost center in SAP, reassigns ServiceNow groups, and notifies both old and new managers via Teams.

naftiko: "0.5"
info:
  label: "Employee Transfer Cross-System Update"
  description: "When an employee transfers departments in Workday, updates their cost center in SAP, reassigns ServiceNow groups, and notifies both old and new managers via Teams."
  tags:
    - hr
    - workday
    - sap
    - servicenow
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: hr-transfer
      port: 8080
      tools:
        - name: process-transfer
          description: "Process employee department transfer: update SAP cost center, reassign ServiceNow groups, and notify managers."
          inputParameters:
            - name: worker_id
              in: body
              type: string
              description: "The Workday worker ID."
            - name: new_department
              in: body
              type: string
              description: "The new department name."
            - name: new_cost_center
              in: body
              type: string
              description: "The new SAP cost center."
          steps:
            - name: get-employee
              type: call
              call: "workday.get-worker"
              with:
                worker_id: "{{worker_id}}"
            - name: update-cost-center
              type: call
              call: "sap-hr.update-cost-center"
              with:
                employee_id: "{{get-employee.sapEmployeeId}}"
                cost_center: "{{new_cost_center}}"
            - name: update-servicenow-group
              type: call
              call: "servicenow.update-user"
              with:
                user_name: "{{get-employee.workEmail}}"
                department: "{{new_department}}"
            - name: notify-managers
              type: call
              call: "msteams.post-message"
              with:
                recipient: "{{get-employee.manager.email}}"
                message: "{{get-employee.displayName}} has transferred to {{new_department}}. SAP cost center updated to {{new_cost_center}}."
  consumes:
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: workers
          path: "/sanofi/workers/{{worker_id}}"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-worker
              method: GET
    - type: http
      namespace: sap-hr
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_BUSINESS_PARTNER"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: employees
          path: "/A_BusinessPartner"
          operations:
            - name: update-cost-center
              method: PATCH
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: users
          path: "/table/sys_user"
          operations:
            - name: update-user
              method: PATCH
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST

Reviews enterprise software license utilization by pulling usage data from Microsoft Entra, comparing against entitlements in Snowflake, and creating optimization recommendations in ServiceNow.

naftiko: "0.5"
info:
  label: "Enterprise License Optimization Review"
  description: "Reviews enterprise software license utilization by pulling usage data from Microsoft Entra, comparing against entitlements in Snowflake, and creating optimization recommendations in ServiceNow."
  tags:
    - finops
    - identity
    - microsoft-entra
    - snowflake
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: finops-license
      port: 8080
      tools:
        - name: review-license-utilization
          description: "Review license utilization: pull usage data, compare entitlements, and create optimization tickets."
          inputParameters:
            - name: application_name
              in: body
              type: string
              description: "The enterprise application name."
          steps:
            - name: get-usage-data
              type: call
              call: "msgraph.get-app-usage"
              with:
                app_name: "{{application_name}}"
            - name: compare-entitlements
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT licensed_count, active_users, utilization_pct FROM finops.license_entitlements WHERE application_name='{{application_name}}'"
            - name: create-optimization-ticket
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "License optimization: {{application_name}}"
                category: "finops_license"
                assigned_group: "IT_Asset_Management"
  consumes:
    - type: http
      namespace: msgraph
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: app-usage
          path: "/reports/getOffice365ActiveUserDetail"
          operations:
            - name: get-app-usage
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST

Handles EHS incidents by creating a record in ServiceNow, logging details in Snowflake for trend analysis, and alerting the EHS team via Teams.

naftiko: "0.5"
info:
  label: "Environmental Health Safety Incident Handler"
  description: "Handles EHS incidents by creating a record in ServiceNow, logging details in Snowflake for trend analysis, and alerting the EHS team via Teams."
  tags:
    - ehs
    - servicenow
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: ehs-incident
      port: 8080
      tools:
        - name: handle-ehs-incident
          description: "Handle EHS incident: create ServiceNow record, log to Snowflake, and alert EHS team."
          inputParameters:
            - name: incident_type
              in: body
              type: string
              description: "Type of EHS incident."
            - name: location
              in: body
              type: string
              description: "Facility location."
            - name: description
              in: body
              type: string
              description: "Incident description."
          steps:
            - name: create-ehs-record
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "EHS incident: {{incident_type}} at {{location}}"
                category: "ehs"
                description: "{{description}}"
            - name: log-to-analytics
              type: call
              call: "snowflake.run-query"
              with:
                statement: "INSERT INTO ehs.incidents (type, location, description, ticket_number, reported_at) VALUES ('{{incident_type}}', '{{location}}', '{{description}}', '{{create-ehs-record.number}}', CURRENT_TIMESTAMP())"
            - name: alert-ehs-team
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.ehs_team_id"
                channel_id: "$secrets.ehs_channel_id"
                body: "EHS incident reported at {{location}}: {{incident_type}}. Ticket: {{create-ehs-record.number}}."
  consumes:
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Automates period-end close by pulling trial balance from SAP, comparing against Snowflake analytics, and posting the reconciliation summary to the finance Teams channel.

naftiko: "0.5"
info:
  label: "Financial Period Close Reconciliation"
  description: "Automates period-end close by pulling trial balance from SAP, comparing against Snowflake analytics, and posting the reconciliation summary to the finance Teams channel."
  tags:
    - finance
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: finance-close
      port: 8080
      tools:
        - name: reconcile-period-close
          description: "Reconcile financial period close: pull SAP trial balance, compare with Snowflake, and notify finance."
          inputParameters:
            - name: fiscal_period
              in: body
              type: string
              description: "The fiscal period (e.g., 2026-03)."
            - name: company_code
              in: body
              type: string
              description: "The SAP company code."
          steps:
            - name: get-trial-balance
              type: call
              call: "sap-fi.get-trial-balance"
              with:
                period: "{{fiscal_period}}"
                company_code: "{{company_code}}"
            - name: get-analytics-totals
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT account_group, SUM(amount) as total FROM finance.gl_entries WHERE period = '{{fiscal_period}}' GROUP BY account_group"
            - name: post-reconciliation
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.finance_team_id"
                channel_id: "$secrets.finance_channel_id"
                body: "Period {{fiscal_period}} reconciliation complete for company code {{company_code}}. SAP trial balance and Snowflake analytics compared."
  consumes:
    - type: http
      namespace: sap-fi
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_JOURNALENTRYITEMBASIC_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: journal-entries
          path: "/A_JournalEntryItemBasic"
          operations:
            - name: get-trial-balance
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

When a GitHub release is published, creates a ServiceNow change record with release notes, links the CI, and notifies the release management channel in Teams.

naftiko: "0.5"
info:
  label: "GitHub Release to ServiceNow Change Record"
  description: "When a GitHub release is published, creates a ServiceNow change record with release notes, links the CI, and notifies the release management channel in Teams."
  tags:
    - devops
    - github
    - servicenow
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: devops-release
      port: 8080
      tools:
        - name: process-release
          description: "Process a GitHub release: create ServiceNow change record and notify release management."
          inputParameters:
            - name: repo_name
              in: body
              type: string
              description: "The GitHub repository (org/repo)."
            - name: release_tag
              in: body
              type: string
              description: "The release tag name."
          steps:
            - name: get-release
              type: call
              call: "github.get-release"
              with:
                repo: "{{repo_name}}"
                tag: "{{release_tag}}"
            - name: create-change-record
              type: call
              call: "servicenow.create-change"
              with:
                short_description: "Release {{release_tag}} for {{repo_name}}"
                description: "{{get-release.body}}"
                category: "software_release"
            - name: notify-release-mgmt
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.release_team_id"
                channel_id: "$secrets.release_channel_id"
                body: "Release {{release_tag}} for {{repo_name}} published. Change record: {{create-change-record.number}}."
  consumes:
    - type: http
      namespace: github
      baseUri: "https://api.github.com"
      authentication:
        type: bearer
        token: "$secrets.github_token"
      resources:
        - name: releases
          path: "/repos/{{repo}}/releases/tags/{{tag}}"
          inputParameters:
            - name: repo
              in: path
            - name: tag
              in: path
          operations:
            - name: get-release
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: change-requests
          path: "/table/change_request"
          operations:
            - name: create-change
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Checks whether branch protection rules are enabled on the main branch of a GitHub repository, returning required reviews and status checks.

naftiko: "0.5"
info:
  label: "GitHub Repository Branch Protection Check"
  description: "Checks whether branch protection rules are enabled on the main branch of a GitHub repository, returning required reviews and status checks."
  tags:
    - devops
    - github
capability:
  exposes:
    - type: mcp
      namespace: devops-compliance
      port: 8080
      tools:
        - name: check-branch-protection
          description: "Check branch protection settings for the main branch of a GitHub repo. Returns required reviewers and status check enforcement."
          inputParameters:
            - name: repo_name
              in: body
              type: string
              description: "The GitHub repository name (org/repo)."
          call: "github.get-branch-protection"
          with:
            repo: "{{repo_name}}"
          outputParameters:
            - name: required_reviews
              type: integer
              mapping: "$.required_pull_request_reviews.required_approving_review_count"
            - name: enforce_status_checks
              type: boolean
              mapping: "$.required_status_checks.strict"
  consumes:
    - type: http
      namespace: github
      baseUri: "https://api.github.com"
      authentication:
        type: bearer
        token: "$secrets.github_token"
      resources:
        - name: branch-protection
          path: "/repos/{{repo}}/branches/main/protection"
          inputParameters:
            - name: repo
              in: path
          operations:
            - name: get-branch-protection
              method: GET

Performs periodic GxP system access reviews by pulling user lists from Microsoft Entra, cross-referencing with Workday active employees, and creating ServiceNow tasks for orphaned accounts.

naftiko: "0.5"
info:
  label: "GxP System Access Review Workflow"
  description: "Performs periodic GxP system access reviews by pulling user lists from Microsoft Entra, cross-referencing with Workday active employees, and creating ServiceNow tasks for orphaned accounts."
  tags:
    - compliance
    - gxp
    - microsoft-entra
    - workday
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: compliance-access-review
      port: 8080
      tools:
        - name: review-gxp-access
          description: "Review GxP system access: pull Entra users, validate against Workday, and create tasks for orphaned accounts."
          inputParameters:
            - name: application_id
              in: body
              type: string
              description: "The Microsoft Entra application ID for the GxP system."
          steps:
            - name: get-app-users
              type: call
              call: "msgraph.get-app-users"
              with:
                app_id: "{{application_id}}"
            - name: validate-employees
              type: call
              call: "workday.get-active-workers"
              with:
                department: "all"
            - name: create-review-task
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "GxP access review: orphaned accounts found for app {{application_id}}"
                category: "compliance_review"
                assigned_group: "GxP_Compliance"
  consumes:
    - type: http
      namespace: msgraph
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: app-role-assignments
          path: "/servicePrincipals/{{app_id}}/appRoleAssignedTo"
          inputParameters:
            - name: app_id
              in: path
          operations:
            - name: get-app-users
              method: GET
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: workers
          path: "/sanofi/workers"
          operations:
            - name: get-active-workers
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST

Validates healthcare professional engagements by checking Veeva CRM interaction records, verifying compliance limits in Snowflake, and logging the audit trail in ServiceNow.

naftiko: "0.5"
info:
  label: "HCP Engagement Compliance Orchestrator"
  description: "Validates healthcare professional engagements by checking Veeva CRM interaction records, verifying compliance limits in Snowflake, and logging the audit trail in ServiceNow."
  tags:
    - compliance
    - commercial
    - veeva
    - snowflake
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: compliance-hcp
      port: 8080
      tools:
        - name: validate-hcp-engagement
          description: "Validate HCP engagement compliance: check CRM records, verify spend limits, and log audit trail."
          inputParameters:
            - name: hcp_id
              in: body
              type: string
              description: "The healthcare professional ID."
            - name: engagement_type
              in: body
              type: string
              description: "Type of engagement (e.g., advisory_board, speaker_program)."
          steps:
            - name: get-interactions
              type: call
              call: "veeva-crm.get-interactions"
              with:
                hcp_id: "{{hcp_id}}"
                type: "{{engagement_type}}"
            - name: check-spend-limits
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT SUM(amount) as total_spend, max_annual_limit FROM compliance.hcp_spend_tracking WHERE hcp_id='{{hcp_id}}' AND year=YEAR(CURRENT_DATE()) GROUP BY max_annual_limit"
            - name: log-audit
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "HCP engagement compliance check: {{hcp_id}} - {{engagement_type}}"
                category: "compliance_audit"
                assigned_group: "Compliance_Team"
  consumes:
    - type: http
      namespace: veeva-crm
      baseUri: "https://sanofi.veevanetwork.com/api/v1"
      authentication:
        type: bearer
        token: "$secrets.veeva_crm_token"
      resources:
        - name: interactions
          path: "/interactions"
          operations:
            - name: get-interactions
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST

Plans infrastructure capacity by pulling Datadog metrics, comparing against thresholds in Snowflake, and creating ServiceNow capacity requests for over-utilized resources.

naftiko: "0.5"
info:
  label: "IT Infrastructure Capacity Planning"
  description: "Plans infrastructure capacity by pulling Datadog metrics, comparing against thresholds in Snowflake, and creating ServiceNow capacity requests for over-utilized resources."
  tags:
    - infrastructure
    - datadog
    - snowflake
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: infra-capacity
      port: 8080
      tools:
        - name: plan-capacity
          description: "Plan infrastructure capacity: pull metrics, compare thresholds, and create capacity requests."
          inputParameters:
            - name: service_name
              in: body
              type: string
              description: "The service name to evaluate."
          steps:
            - name: get-metrics
              type: call
              call: "datadog.get-metrics"
              with:
                service: "{{service_name}}"
                metric: "system.cpu.user"
            - name: check-thresholds
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT cpu_threshold, memory_threshold FROM infrastructure.capacity_thresholds WHERE service_name='{{service_name}}'"
            - name: create-capacity-request
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "Capacity planning: {{service_name}} approaching resource limits"
                category: "infrastructure_capacity"
                assigned_group: "Cloud_Infrastructure"
  consumes:
    - type: http
      namespace: datadog
      baseUri: "https://api.datadoghq.com/api/v1"
      authentication:
        type: apiKey
        key: "$secrets.datadog_api_key"
      resources:
        - name: metrics
          path: "/query"
          operations:
            - name: get-metrics
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST

When a critical vulnerability is detected, creates a ServiceNow security incident, assigns it to the responsible team based on CMDB ownership, and alerts the security channel in Teams.

naftiko: "0.5"
info:
  label: "IT Security Vulnerability Remediation"
  description: "When a critical vulnerability is detected, creates a ServiceNow security incident, assigns it to the responsible team based on CMDB ownership, and alerts the security channel in Teams."
  tags:
    - security
    - servicenow
    - microsoft-teams
    - datadog
capability:
  exposes:
    - type: mcp
      namespace: security-vuln
      port: 8080
      tools:
        - name: remediate-vulnerability
          description: "Orchestrate vulnerability remediation: look up asset owner in CMDB, create security incident, and alert the security team."
          inputParameters:
            - name: cve_id
              in: body
              type: string
              description: "The CVE identifier."
            - name: asset_tag
              in: body
              type: string
              description: "The affected asset tag."
          steps:
            - name: get-asset-owner
              type: call
              call: "servicenow.get-ci"
              with:
                sysparm_query: "asset_tag={{asset_tag}}"
            - name: create-security-incident
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "Critical vulnerability {{cve_id}} on {{asset_tag}}"
                category: "security"
                assigned_group: "{{get-asset-owner.support_group}}"
                priority: "1"
            - name: alert-security-channel
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.security_team_id"
                channel_id: "$secrets.security_channel_id"
                body: "CRITICAL: {{cve_id}} detected on {{asset_tag}}. Incident {{create-security-incident.number}} created and assigned to {{get-asset-owner.support_group}}."
  consumes:
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: cmdb-ci
          path: "/table/cmdb_ci"
          operations:
            - name: get-ci
              method: GET
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Retrieves the current status, assignee, and priority of a Jira issue by key, for project tracking and developer inquiries.

naftiko: "0.5"
info:
  label: "Jira Issue Status Lookup"
  description: "Retrieves the current status, assignee, and priority of a Jira issue by key, for project tracking and developer inquiries."
  tags:
    - project-management
    - jira
capability:
  exposes:
    - type: mcp
      namespace: pm-tracking
      port: 8080
      tools:
        - name: get-issue-status
          description: "Look up a Jira issue by key. Returns current status, assignee, and priority."
          inputParameters:
            - name: issue_key
              in: body
              type: string
              description: "The Jira issue key (e.g., PROJ-1234)."
          call: "jira.get-issue"
          with:
            issue_key: "{{issue_key}}"
          outputParameters:
            - name: status
              type: string
              mapping: "$.fields.status.name"
            - name: assignee
              type: string
              mapping: "$.fields.assignee.displayName"
            - name: priority
              type: string
              mapping: "$.fields.priority.name"
  consumes:
    - type: http
      namespace: jira
      baseUri: "https://sanofi.atlassian.net/rest/api/3"
      authentication:
        type: basic
        username: "$secrets.jira_user"
        password: "$secrets.jira_api_token"
      resources:
        - name: issues
          path: "/issue/{{issue_key}}"
          inputParameters:
            - name: issue_key
              in: path
          operations:
            - name: get-issue
              method: GET

Tracks lab instrument calibration schedules by querying SAP PM for upcoming calibrations, creating ServiceNow work orders, and notifying the lab manager via Teams.

naftiko: "0.5"
info:
  label: "Lab Instrument Calibration Tracking"
  description: "Tracks lab instrument calibration schedules by querying SAP PM for upcoming calibrations, creating ServiceNow work orders, and notifying the lab manager via Teams."
  tags:
    - quality
    - manufacturing
    - sap
    - servicenow
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: quality-calibration
      port: 8080
      tools:
        - name: track-calibration
          description: "Track upcoming instrument calibrations: query SAP PM, create work orders, and notify lab manager."
          inputParameters:
            - name: plant
              in: body
              type: string
              description: "The SAP plant code."
            - name: days_ahead
              in: body
              type: integer
              description: "Number of days to look ahead."
          steps:
            - name: get-upcoming-calibrations
              type: call
              call: "sap-pm.get-maintenance-orders"
              with:
                plant: "{{plant}}"
                order_type: "calibration"
            - name: create-work-order
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "Lab instrument calibration due at plant {{plant}}"
                category: "lab_calibration"
                assigned_group: "Lab_Maintenance"
            - name: notify-lab-manager
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.lab_team_id"
                channel_id: "$secrets.lab_channel_id"
                body: "Upcoming calibrations at plant {{plant}}: work order {{create-work-order.number}} created."
  consumes:
    - type: http
      namespace: sap-pm
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_MAINTENANCEORDER"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: maintenance-orders
          path: "/MaintenanceOrder"
          operations:
            - name: get-maintenance-orders
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Tracks mandatory training compliance by pulling completion data from Workday Learning, comparing against requirements in Snowflake, and notifying managers of non-compliant employees via Teams.

naftiko: "0.5"
info:
  label: "Learning Management Training Compliance Tracker"
  description: "Tracks mandatory training compliance by pulling completion data from Workday Learning, comparing against requirements in Snowflake, and notifying managers of non-compliant employees via Teams."
  tags:
    - hr
    - compliance
    - workday
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: hr-training-compliance
      port: 8080
      tools:
        - name: track-training-compliance
          description: "Track training compliance: pull completions, compare requirements, and notify managers."
          inputParameters:
            - name: department
              in: body
              type: string
              description: "The department to check."
            - name: training_code
              in: body
              type: string
              description: "The mandatory training course code."
          steps:
            - name: get-completions
              type: call
              call: "workday.get-training-completions"
              with:
                department: "{{department}}"
                course_code: "{{training_code}}"
            - name: check-requirements
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT employee_id, due_date FROM hr.training_requirements WHERE department='{{department}}' AND course_code='{{training_code}}' AND completed=false"
            - name: notify-managers
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.hr_team_id"
                channel_id: "$secrets.hr_compliance_channel_id"
                body: "Training compliance check for {{training_code}} in {{department}}: review non-compliant employees."
  consumes:
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: training
          path: "/sanofi/learning/completions"
          operations:
            - name: get-training-completions
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Retrieves approved job requisition details from Workday and publishes the role to LinkedIn, enabling faster candidate sourcing for Sanofi positions.

naftiko: "0.5"
info:
  label: "LinkedIn Job Posting Publication"
  description: "Retrieves approved job requisition details from Workday and publishes the role to LinkedIn, enabling faster candidate sourcing for Sanofi positions."
  tags:
    - hr
    - recruiting
    - linkedin
    - workday
    - talent-acquisition
capability:
  exposes:
    - type: mcp
      namespace: hr-recruiting
      port: 8080
      tools:
        - name: publish-job-to-linkedin
          description: "Given a Workday job requisition ID, fetch its approved details and publish a structured job posting to Sanofi's LinkedIn company page."
          inputParameters:
            - name: requisition_id
              in: body
              type: string
              description: "The Workday job requisition ID to publish."
            - name: linkedin_company_id
              in: body
              type: string
              description: "Sanofi's LinkedIn company page ID."
          steps:
            - name: get-requisition
              type: call
              call: "workday-jobs.get-job-requisition"
              with:
                requisition_id: "{{requisition_id}}"
            - name: post-job
              type: call
              call: "linkedin-jobs.create-job-posting"
              with:
                companyId: "{{linkedin_company_id}}"
                title: "{{get-requisition.jobTitle}}"
                description: "{{get-requisition.jobDescription}}"
                location: "{{get-requisition.location}}"
  consumes:
    - type: http
      namespace: workday-jobs
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: job-requisitions
          path: "/sanofi/jobRequisitions/{{requisition_id}}"
          inputParameters:
            - name: requisition_id
              in: path
          operations:
            - name: get-job-requisition
              method: GET
    - type: http
      namespace: linkedin-jobs
      baseUri: "https://api.linkedin.com/v2"
      authentication:
        type: bearer
        token: "$secrets.linkedin_token"
      resources:
        - name: job-postings
          path: "/jobPostings"
          operations:
            - name: create-job-posting
              method: POST

Sources candidates from LinkedIn Recruiter, creates candidate profiles in Workday Recruiting, and notifies hiring managers via Teams.

naftiko: "0.5"
info:
  label: "LinkedIn Talent Pipeline to Workday"
  description: "Sources candidates from LinkedIn Recruiter, creates candidate profiles in Workday Recruiting, and notifies hiring managers via Teams."
  tags:
    - hr
    - recruiting
    - linkedin
    - workday
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: hr-recruiting
      port: 8080
      tools:
        - name: pipeline-candidate
          description: "Pipeline a LinkedIn candidate: source profile, create Workday candidate, and notify hiring manager."
          inputParameters:
            - name: linkedin_profile_url
              in: body
              type: string
              description: "The LinkedIn profile URL."
            - name: job_requisition_id
              in: body
              type: string
              description: "The Workday job requisition ID."
          steps:
            - name: get-linkedin-profile
              type: call
              call: "linkedin.get-profile"
              with:
                profile_url: "{{linkedin_profile_url}}"
            - name: create-candidate
              type: call
              call: "workday.create-candidate"
              with:
                name: "{{get-linkedin-profile.fullName}}"
                email: "{{get-linkedin-profile.emailAddress}}"
                requisition_id: "{{job_requisition_id}}"
            - name: notify-hiring-manager
              type: call
              call: "msteams.post-message"
              with:
                recipient: "$secrets.hiring_manager_email"
                message: "New candidate {{get-linkedin-profile.fullName}} added to requisition {{job_requisition_id}} from LinkedIn."
  consumes:
    - type: http
      namespace: linkedin
      baseUri: "https://api.linkedin.com/v2"
      authentication:
        type: bearer
        token: "$secrets.linkedin_token"
      resources:
        - name: profiles
          path: "/people/{{profile_url}}"
          inputParameters:
            - name: profile_url
              in: path
          operations:
            - name: get-profile
              method: GET
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: candidates
          path: "/sanofi/recruiting/candidates"
          operations:
            - name: create-candidate
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST

Initiates a deviation investigation by creating a quality event in Veeva Vault, pulling batch parameters from SAP, and assigning a CAPA to the quality team via ServiceNow.

naftiko: "0.5"
info:
  label: "Manufacturing Deviation Investigation Workflow"
  description: "Initiates a deviation investigation by creating a quality event in Veeva Vault, pulling batch parameters from SAP, and assigning a CAPA to the quality team via ServiceNow."
  tags:
    - manufacturing
    - quality
    - veeva
    - sap
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: mfg-quality
      port: 8080
      tools:
        - name: investigate-deviation
          description: "Orchestrate deviation investigation: create quality event, retrieve batch data, and assign CAPA."
          inputParameters:
            - name: batch_number
              in: body
              type: string
              description: "The batch number with the deviation."
            - name: deviation_description
              in: body
              type: string
              description: "Description of the deviation."
          steps:
            - name: create-quality-event
              type: call
              call: "veeva-vault.create-document"
              with:
                type: "quality_event"
                batch_number: "{{batch_number}}"
                description: "{{deviation_description}}"
            - name: get-batch-params
              type: call
              call: "sap-qm.get-inspection-lot"
              with:
                batch: "{{batch_number}}"
            - name: create-capa
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "CAPA required: Deviation on batch {{batch_number}}"
                category: "quality_capa"
                assigned_group: "QA_Investigations"
                description: "{{deviation_description}}. Quality event: {{create-quality-event.id}}."
  consumes:
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: documents
          path: "/objects/documents"
          operations:
            - name: create-document
              method: POST
    - type: http
      namespace: sap-qm
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_INSPECTIONLOT_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: inspection-lots
          path: "/A_InspectionLot"
          operations:
            - name: get-inspection-lot
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST

Processes drug pricing updates by retrieving current pricing from SAP SD, updating reference prices in Snowflake, and notifying the market access team via Teams.

naftiko: "0.5"
info:
  label: "Market Access Pricing Update Workflow"
  description: "Processes drug pricing updates by retrieving current pricing from SAP SD, updating reference prices in Snowflake, and notifying the market access team via Teams."
  tags:
    - commercial
    - market-access
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: commercial-pricing
      port: 8080
      tools:
        - name: update-pricing
          description: "Update drug pricing: get SAP pricing, update Snowflake reference tables, and notify market access."
          inputParameters:
            - name: material_number
              in: body
              type: string
              description: "The SAP material number for the drug product."
            - name: new_price
              in: body
              type: string
              description: "The new list price."
            - name: market
              in: body
              type: string
              description: "The market/country code."
          steps:
            - name: get-current-pricing
              type: call
              call: "sap-sd.get-pricing"
              with:
                material: "{{material_number}}"
                market: "{{market}}"
            - name: update-reference-price
              type: call
              call: "snowflake.run-query"
              with:
                statement: "UPDATE commercial.reference_pricing SET price='{{new_price}}', effective_date=CURRENT_DATE(), previous_price='{{get-current-pricing.list_price}}' WHERE material='{{material_number}}' AND market='{{market}}'"
            - name: notify-market-access
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.market_access_team_id"
                channel_id: "$secrets.market_access_channel_id"
                body: "Pricing update for {{material_number}} in {{market}}: {{get-current-pricing.list_price}} -> {{new_price}}."
  consumes:
    - type: http
      namespace: sap-sd
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_SLSPRICINGCONDITIONRECORD_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: pricing-conditions
          path: "/A_SlsPrcgCndnRecdValidity"
          operations:
            - name: get-pricing
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Processes master data change requests by validating against SAP MDG rules, creating a ServiceNow approval workflow, and logging the change in Snowflake.

naftiko: "0.5"
info:
  label: "Master Data Governance Change Request"
  description: "Processes master data change requests by validating against SAP MDG rules, creating a ServiceNow approval workflow, and logging the change in Snowflake."
  tags:
    - data-governance
    - sap
    - servicenow
    - snowflake
capability:
  exposes:
    - type: mcp
      namespace: mdg-change
      port: 8080
      tools:
        - name: process-mdg-change
          description: "Process master data change: validate SAP rules, create approval workflow, and log change."
          inputParameters:
            - name: entity_type
              in: body
              type: string
              description: "The master data entity type (material, vendor, customer)."
            - name: entity_id
              in: body
              type: string
              description: "The entity identifier."
            - name: change_description
              in: body
              type: string
              description: "Description of the requested change."
          steps:
            - name: validate-entity
              type: call
              call: "sap-mdg.validate-change"
              with:
                entity_type: "{{entity_type}}"
                entity_id: "{{entity_id}}"
            - name: create-approval
              type: call
              call: "servicenow.create-change"
              with:
                short_description: "MDG change: {{entity_type}} {{entity_id}}"
                description: "{{change_description}}"
                category: "master_data"
            - name: log-change
              type: call
              call: "snowflake.run-query"
              with:
                statement: "INSERT INTO governance.mdg_changes (entity_type, entity_id, description, approval_ticket, requested_at) VALUES ('{{entity_type}}', '{{entity_id}}', '{{change_description}}', '{{create-approval.number}}', CURRENT_TIMESTAMP())"
  consumes:
    - type: http
      namespace: sap-mdg
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_BUSINESS_PARTNER"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: validation
          path: "/A_BusinessPartner"
          operations:
            - name: validate-change
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: change-requests
          path: "/table/change_request"
          operations:
            - name: create-change
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST

Tracks medical publication milestones by querying Veeva Vault for manuscript status, updating Snowflake tracking tables, and alerting the medical affairs team via Teams.

naftiko: "0.5"
info:
  label: "Medical Affairs Publication Tracker"
  description: "Tracks medical publication milestones by querying Veeva Vault for manuscript status, updating Snowflake tracking tables, and alerting the medical affairs team via Teams."
  tags:
    - medical-affairs
    - veeva
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: medaffairs-pubs
      port: 8080
      tools:
        - name: track-publication
          description: "Track publication progress: check Veeva Vault manuscript status, update Snowflake tracker, and notify medical affairs."
          inputParameters:
            - name: manuscript_id
              in: body
              type: string
              description: "The Veeva Vault manuscript document ID."
          steps:
            - name: get-manuscript
              type: call
              call: "veeva-vault.get-document"
              with:
                doc_id: "{{manuscript_id}}"
            - name: update-tracker
              type: call
              call: "snowflake.run-query"
              with:
                statement: "UPDATE medical_affairs.publication_tracker SET status='{{get-manuscript.status__v}}', updated_at=CURRENT_TIMESTAMP() WHERE manuscript_id='{{manuscript_id}}'"
            - name: notify-team
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.medaffairs_team_id"
                channel_id: "$secrets.medaffairs_channel_id"
                body: "Manuscript {{manuscript_id}} status: {{get-manuscript.status__v}}. Tracker updated."
  consumes:
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: documents
          path: "/objects/documents/{{doc_id}}"
          inputParameters:
            - name: doc_id
              in: path
          operations:
            - name: get-document
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Assigns the appropriate Microsoft 365 license SKU to a newly provisioned Sanofi employee in Microsoft Entra ID based on their role and department.

naftiko: "0.5"
info:
  label: "Microsoft Entra User License Assignment"
  description: "Assigns the appropriate Microsoft 365 license SKU to a newly provisioned Sanofi employee in Microsoft Entra ID based on their role and department."
  tags:
    - identity
    - microsoft-365
    - azure
    - hr
    - license-management
capability:
  exposes:
    - type: mcp
      namespace: identity-licensing
      port: 8080
      tools:
        - name: assign-user-license
          description: "Given a user principal name and Microsoft 365 license SKU ID, assign the license in Entra ID. Use after provisioning a new Sanofi employee account."
          inputParameters:
            - name: user_upn
              in: body
              type: string
              description: "The UPN of the newly provisioned employee (e.g., firstname.lastname@sanofi.com)."
            - name: sku_id
              in: body
              type: string
              description: "The Microsoft 365 license SKU GUID to assign."
          call: "msgraph-lic.assign-license"
          with:
            userPrincipalName: "{{user_upn}}"
            skuId: "{{sku_id}}"
          outputParameters:
            - name: assigned_licenses
              type: array
              mapping: "$.assignedLicenses"
  consumes:
    - type: http
      namespace: msgraph-lic
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: user-licenses
          path: "/users/{{userPrincipalName}}/assignLicense"
          inputParameters:
            - name: userPrincipalName
              in: path
          operations:
            - name: assign-license
              method: POST

Retrieves user account status from Microsoft Entra ID by UPN, returning account enabled state, last sign-in, and assigned licenses.

naftiko: "0.5"
info:
  label: "Microsoft Entra User Status Lookup"
  description: "Retrieves user account status from Microsoft Entra ID by UPN, returning account enabled state, last sign-in, and assigned licenses."
  tags:
    - identity
    - microsoft-entra
capability:
  exposes:
    - type: mcp
      namespace: identity-mgmt
      port: 8080
      tools:
        - name: get-user-status
          description: "Look up a Microsoft Entra user by UPN. Returns account enabled flag, last sign-in time, and license assignments."
          inputParameters:
            - name: user_principal_name
              in: body
              type: string
              description: "The user principal name (email)."
          call: "msgraph.get-user"
          with:
            upn: "{{user_principal_name}}"
          outputParameters:
            - name: account_enabled
              type: boolean
              mapping: "$.accountEnabled"
            - name: last_sign_in
              type: string
              mapping: "$.signInActivity.lastSignInDateTime"
  consumes:
    - type: http
      namespace: msgraph
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: users
          path: "/users/{{upn}}"
          inputParameters:
            - name: upn
              in: path
          operations:
            - name: get-user
              method: GET

Posts a message to a specified Microsoft Teams channel, used for automated notifications and alerts.

naftiko: "0.5"
info:
  label: "Microsoft Teams Channel Message Post"
  description: "Posts a message to a specified Microsoft Teams channel, used for automated notifications and alerts."
  tags:
    - collaboration
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: collab-messaging
      port: 8080
      tools:
        - name: post-channel-message
          description: "Post a message to a Microsoft Teams channel. Provide team ID, channel ID, and message body."
          inputParameters:
            - name: team_id
              in: body
              type: string
              description: "The Microsoft Teams team ID."
            - name: channel_id
              in: body
              type: string
              description: "The Teams channel ID."
            - name: message
              in: body
              type: string
              description: "The message content to post."
          call: "msteams.post-channel-message"
          with:
            team_id: "{{team_id}}"
            channel_id: "{{channel_id}}"
            body: "{{message}}"
          outputParameters:
            - name: message_id
              type: string
              mapping: "$.id"
  consumes:
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

When a new employee is created in Workday, opens a ServiceNow onboarding ticket, provisions Microsoft 365 access, and sends a Teams welcome message to kick off the onboarding journey.

naftiko: "0.5"
info:
  label: "New Hire Onboarding Orchestrator"
  description: "When a new employee is created in Workday, opens a ServiceNow onboarding ticket, provisions Microsoft 365 access, and sends a Teams welcome message to kick off the onboarding journey."
  tags:
    - hr
    - onboarding
    - workday
    - servicenow
    - microsoft-teams
    - microsoft-365
capability:
  exposes:
    - type: mcp
      namespace: hr-onboarding
      port: 8080
      tools:
        - name: trigger-onboarding
          description: "Given a Workday employee ID and start date, orchestrate the full onboarding sequence: create a ServiceNow IT ticket, provision Microsoft 365, and send a Teams welcome message."
          inputParameters:
            - name: employee_id
              in: body
              type: string
              description: "The Workday worker ID for the new hire."
            - name: start_date
              in: body
              type: string
              description: "The employee's start date in YYYY-MM-DD format."
            - name: department
              in: body
              type: string
              description: "The department the new hire is joining."
          steps:
            - name: get-employee
              type: call
              call: "workday.get-worker"
              with:
                worker_id: "{{employee_id}}"
            - name: create-ticket
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "New hire onboarding: {{get-employee.displayName}}"
                category: "hr_onboarding"
                assigned_group: "IT_Onboarding"
            - name: provision-m365
              type: call
              call: "msgraph.create-user"
              with:
                displayName: "{{get-employee.displayName}}"
                userPrincipalName: "{{get-employee.workEmail}}"
                department: "{{department}}"
            - name: send-welcome
              type: call
              call: "msteams.post-message"
              with:
                recipient: "{{get-employee.workEmail}}"
                message: "Welcome to Sanofi, {{get-employee.firstName}}! Your IT ticket is {{create-ticket.number}}."
  consumes:
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: workers
          path: "/sanofi/workers/{{worker_id}}"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-worker
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST
    - type: http
      namespace: msgraph
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: users
          path: "/users"
          operations:
            - name: create-user
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST

Runs safety signal detection queries in Snowflake, creates a safety review record in Veeva Vault, and escalates findings to the pharmacovigilance team via Teams.

naftiko: "0.5"
info:
  label: "Pharmacovigilance Signal Detection Alert"
  description: "Runs safety signal detection queries in Snowflake, creates a safety review record in Veeva Vault, and escalates findings to the pharmacovigilance team via Teams."
  tags:
    - pharmacovigilance
    - snowflake
    - veeva
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: pv-signal-detection
      port: 8080
      tools:
        - name: detect-safety-signal
          description: "Detect safety signals: query adverse event data, create review record, and escalate to PV team."
          inputParameters:
            - name: product_name
              in: body
              type: string
              description: "The drug product name."
            - name: signal_type
              in: body
              type: string
              description: "The type of safety signal to detect."
          steps:
            - name: run-signal-query
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT event_type, COUNT(*) as cnt FROM pv.adverse_events WHERE product_name='{{product_name}}' AND reported_date > DATEADD(month, -3, CURRENT_DATE()) GROUP BY event_type HAVING cnt > 10"
            - name: create-review-record
              type: call
              call: "veeva-vault.create-document"
              with:
                type: "safety_signal_review"
                product: "{{product_name}}"
                signal_type: "{{signal_type}}"
            - name: escalate-to-pv
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.pv_team_id"
                channel_id: "$secrets.pv_channel_id"
                body: "Safety signal detected for {{product_name}}. Signal type: {{signal_type}}. Review record: {{create-review-record.id}}."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: documents
          path: "/objects/documents"
          operations:
            - name: create-document
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Checks the last refresh status of a Power BI dataset, returning completion time and success or failure state.

naftiko: "0.5"
info:
  label: "Power BI Dataset Refresh Status"
  description: "Checks the last refresh status of a Power BI dataset, returning completion time and success or failure state."
  tags:
    - analytics
    - power-bi
capability:
  exposes:
    - type: mcp
      namespace: analytics-refresh
      port: 8080
      tools:
        - name: get-dataset-refresh-status
          description: "Check the last refresh status of a Power BI dataset. Returns refresh time and status."
          inputParameters:
            - name: dataset_id
              in: body
              type: string
              description: "The Power BI dataset ID."
          call: "powerbi.get-refresh-history"
          with:
            dataset_id: "{{dataset_id}}"
          outputParameters:
            - name: status
              type: string
              mapping: "$.value[0].status"
            - name: end_time
              type: string
              mapping: "$.value[0].endTime"
  consumes:
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: refresh-history
          path: "/datasets/{{dataset_id}}/refreshes"
          inputParameters:
            - name: dataset_id
              in: path
          operations:
            - name: get-refresh-history
              method: GET

Triggers a Power BI dataset refresh for the Sanofi financial KPI dashboard and notifies the finance team in Teams when data is ready.

naftiko: "0.5"
info:
  label: "Power BI Financial Dashboard Refresh"
  description: "Triggers a Power BI dataset refresh for the Sanofi financial KPI dashboard and notifies the finance team in Teams when data is ready."
  tags:
    - finance
    - analytics
    - power-bi
    - microsoft-teams
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: finance-reporting
      port: 8080
      tools:
        - name: refresh-financial-dashboard
          description: "Trigger a Power BI dataset refresh for the financial KPI dashboard and notify the finance team in Teams upon completion."
          inputParameters:
            - name: dataset_id
              in: body
              type: string
              description: "The Power BI dataset ID for the financial dashboard."
            - name: workspace_id
              in: body
              type: string
              description: "The Power BI workspace (group) ID containing the dataset."
          steps:
            - name: trigger-refresh
              type: call
              call: "powerbi.refresh-dataset"
              with:
                groupId: "{{workspace_id}}"
                datasetId: "{{dataset_id}}"
            - name: notify-finance
              type: call
              call: "msteams-pbi.post-message"
              with:
                channel: "finance-analytics"
                message: "Power BI financial dashboard refresh triggered for dataset {{dataset_id}}. Updated data will be available shortly."
  consumes:
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: dataset-refreshes
          path: "/groups/{{groupId}}/datasets/{{datasetId}}/refreshes"
          inputParameters:
            - name: groupId
              in: path
            - name: datasetId
              in: path
          operations:
            - name: refresh-dataset
              method: POST
    - type: http
      namespace: msteams-pbi
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Converts an approved SAP Ariba requisition into a SAP S/4HANA purchase order, assigns the vendor, and sends a confirmation to the requestor via Teams.

naftiko: "0.5"
info:
  label: "Procurement Requisition to PO Workflow"
  description: "Converts an approved SAP Ariba requisition into a SAP S/4HANA purchase order, assigns the vendor, and sends a confirmation to the requestor via Teams."
  tags:
    - procurement
    - sap-ariba
    - sap
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: procurement-req-to-po
      port: 8080
      tools:
        - name: convert-requisition-to-po
          description: "Convert an approved Ariba requisition to a SAP PO, assign vendor, and confirm with requestor."
          inputParameters:
            - name: requisition_id
              in: body
              type: string
              description: "The SAP Ariba requisition ID."
          steps:
            - name: get-requisition
              type: call
              call: "ariba.get-requisition"
              with:
                req_id: "{{requisition_id}}"
            - name: create-po
              type: call
              call: "sap-po.create-po"
              with:
                vendor: "{{get-requisition.supplier.id}}"
                material: "{{get-requisition.lineItems[0].material}}"
                quantity: "{{get-requisition.lineItems[0].quantity}}"
                plant: "{{get-requisition.deliverTo.plant}}"
            - name: notify-requestor
              type: call
              call: "msteams.post-message"
              with:
                recipient: "{{get-requisition.requester.email}}"
                message: "Your requisition {{requisition_id}} has been converted to PO {{create-po.PurchaseOrder}}."
  consumes:
    - type: http
      namespace: ariba
      baseUri: "https://openapi.ariba.com/api/procurement/v1"
      authentication:
        type: bearer
        token: "$secrets.ariba_token"
      resources:
        - name: requisitions
          path: "/requisitions/{{req_id}}"
          inputParameters:
            - name: req_id
              in: path
          operations:
            - name: get-requisition
              method: GET
    - type: http
      namespace: sap-po
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/MM_PUR_PO_MAINT_V2_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: purchase-orders
          path: "/A_PurchaseOrder"
          operations:
            - name: create-po
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST

Tracks patent filing status by querying Snowflake IP databases, updating Veeva Vault document metadata, and notifying the IP legal team via Teams.

naftiko: "0.5"
info:
  label: "R&D Patent Filing Status Tracker"
  description: "Tracks patent filing status by querying Snowflake IP databases, updating Veeva Vault document metadata, and notifying the IP legal team via Teams."
  tags:
    - research
    - legal
    - snowflake
    - veeva
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: rd-ip-tracking
      port: 8080
      tools:
        - name: track-patent-filing
          description: "Track patent filing status: query IP database, update document metadata, and notify legal team."
          inputParameters:
            - name: patent_id
              in: body
              type: string
              description: "The patent application identifier."
          steps:
            - name: get-filing-status
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT filing_date, jurisdiction, status, examiner_notes FROM ip.patent_filings WHERE patent_id='{{patent_id}}'"
            - name: update-vault-doc
              type: call
              call: "veeva-vault.update-document"
              with:
                doc_id: "{{patent_id}}"
                status: "{{get-filing-status.status}}"
            - name: notify-ip-team
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.ip_team_id"
                channel_id: "$secrets.ip_channel_id"
                body: "Patent {{patent_id}} filing update: Status is {{get-filing-status.status}}."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: documents
          path: "/objects/documents/{{doc_id}}"
          inputParameters:
            - name: doc_id
              in: path
          operations:
            - name: update-document
              method: PUT
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Refreshes real-world evidence datasets by triggering Databricks ETL pipelines, validating data quality in Snowflake, and notifying the RWE team via Teams.

naftiko: "0.5"
info:
  label: "Real World Evidence Data Refresh"
  description: "Refreshes real-world evidence datasets by triggering Databricks ETL pipelines, validating data quality in Snowflake, and notifying the RWE team via Teams."
  tags:
    - research
    - data-engineering
    - databricks
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: rwe-data-refresh
      port: 8080
      tools:
        - name: refresh-rwe-data
          description: "Refresh RWE data: trigger Databricks pipeline, validate quality, and notify team."
          inputParameters:
            - name: dataset_name
              in: body
              type: string
              description: "The RWE dataset name."
          steps:
            - name: trigger-etl
              type: call
              call: "databricks.run-job"
              with:
                job_name: "rwe_{{dataset_name}}_refresh"
            - name: validate-quality
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT check_name, status FROM rwe.data_quality_checks WHERE dataset_name='{{dataset_name}}' ORDER BY run_date DESC LIMIT 10"
            - name: notify-rwe-team
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.rwe_team_id"
                channel_id: "$secrets.rwe_channel_id"
                body: "RWE dataset {{dataset_name}} refresh triggered. Databricks job: {{trigger-etl.run_id}}. Quality validation in progress."
  consumes:
    - type: http
      namespace: databricks
      baseUri: "https://sanofi.cloud.databricks.com/api/2.1"
      authentication:
        type: bearer
        token: "$secrets.databricks_token"
      resources:
        - name: jobs
          path: "/jobs/run-now"
          operations:
            - name: run-job
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Assembles a regulatory submission package by collecting documents from Veeva Vault, generating a compliance checklist from Snowflake, and posting the submission summary to the regulatory team's Teams channel.

naftiko: "0.5"
info:
  label: "Regulatory Submission Document Assembly"
  description: "Assembles a regulatory submission package by collecting documents from Veeva Vault, generating a compliance checklist from Snowflake, and posting the submission summary to the regulatory team's Teams channel."
  tags:
    - regulatory
    - veeva
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: regulatory-submission
      port: 8080
      tools:
        - name: assemble-submission
          description: "Assemble a regulatory submission: collect Veeva Vault documents, generate compliance checklist, and notify the regulatory team."
          inputParameters:
            - name: submission_id
              in: body
              type: string
              description: "The regulatory submission identifier."
            - name: product_name
              in: body
              type: string
              description: "The drug product name."
          steps:
            - name: get-submission-docs
              type: call
              call: "veeva-vault.query-documents"
              with:
                query: "SELECT id, name__v, status__v FROM documents WHERE submission_id__v = '{{submission_id}}'"
            - name: get-checklist
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT requirement, status FROM regulatory.submission_checklist WHERE submission_id = '{{submission_id}}'"
            - name: notify-regulatory-team
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.regulatory_team_id"
                channel_id: "$secrets.regulatory_channel_id"
                body: "Submission {{submission_id}} for {{product_name}} assembled. {{get-submission-docs.responseDetails.total}} documents collected."
  consumes:
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: query
          path: "/query"
          operations:
            - name: query-documents
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Retrieves contract details from SAP Ariba by contract ID, returning effective dates, supplier name, and contract value.

naftiko: "0.5"
info:
  label: "SAP Ariba Contract Detail Lookup"
  description: "Retrieves contract details from SAP Ariba by contract ID, returning effective dates, supplier name, and contract value."
  tags:
    - procurement
    - sap-ariba
capability:
  exposes:
    - type: mcp
      namespace: procurement-contracts
      port: 8080
      tools:
        - name: get-contract-detail
          description: "Look up a SAP Ariba contract by ID. Returns effective date, expiry date, supplier, and total contract value."
          inputParameters:
            - name: contract_id
              in: body
              type: string
              description: "The SAP Ariba contract ID."
          call: "ariba.get-contract"
          with:
            contract_id: "{{contract_id}}"
          outputParameters:
            - name: effective_date
              type: string
              mapping: "$.effectiveDate"
            - name: expiry_date
              type: string
              mapping: "$.expirationDate"
            - name: supplier
              type: string
              mapping: "$.supplier.name"
            - name: contract_value
              type: string
              mapping: "$.amount.value"
  consumes:
    - type: http
      namespace: ariba
      baseUri: "https://openapi.ariba.com/api/contract-compliance/v1"
      authentication:
        type: bearer
        token: "$secrets.ariba_token"
      resources:
        - name: contracts
          path: "/contracts/{{contract_id}}"
          inputParameters:
            - name: contract_id
              in: path
          operations:
            - name: get-contract
              method: GET

Queries SAP Ariba for supplier contracts expiring within 90 days and notifies the procurement team in Teams to initiate renewal processes.

naftiko: "0.5"
info:
  label: "SAP Ariba Contract Expiry Alert"
  description: "Queries SAP Ariba for supplier contracts expiring within 90 days and notifies the procurement team in Teams to initiate renewal processes."
  tags:
    - procurement
    - sap-ariba
    - microsoft-teams
    - contract-management
    - alerts
capability:
  exposes:
    - type: mcp
      namespace: procurement-contracts
      port: 8080
      tools:
        - name: alert-expiring-contracts
          description: "Query SAP Ariba for contracts expiring within the specified threshold and notify the procurement team in Teams. Use for proactive supplier contract renewal."
          inputParameters:
            - name: days_threshold
              in: body
              type: integer
              description: "Number of days ahead to check for contract expiry (e.g., 90)."
          steps:
            - name: get-contracts
              type: call
              call: "ariba-exp.get-expiring-contracts"
              with:
                expiryDays: "{{days_threshold}}"
            - name: notify-procurement
              type: call
              call: "msteams-proc.post-message"
              with:
                channel: "procurement-ops"
                message: "Contracts expiring within {{days_threshold}} days in SAP Ariba: {{get-contracts.summary}}. Please initiate renewal."
  consumes:
    - type: http
      namespace: ariba-exp
      baseUri: "https://openapi.ariba.com/api/contract/v1"
      authentication:
        type: apikey
        key: "APIKey"
        value: "$secrets.ariba_api_key"
        placement: header
      resources:
        - name: contracts
          path: "/contracts"
          operations:
            - name: get-expiring-contracts
              method: GET
    - type: http
      namespace: msteams-proc
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

When a supplier invoice is received in SAP Ariba, validates it against the matched PO in SAP S/4HANA and posts it for payment if within tolerance.

naftiko: "0.5"
info:
  label: "SAP Ariba Invoice Approval and Posting"
  description: "When a supplier invoice is received in SAP Ariba, validates it against the matched PO in SAP S/4HANA and posts it for payment if within tolerance."
  tags:
    - finance
    - procurement
    - sap-ariba
    - sap
    - invoice
    - approval
capability:
  exposes:
    - type: mcp
      namespace: finance-invoicing
      port: 8080
      tools:
        - name: process-invoice
          description: "Given an SAP Ariba invoice ID, fetch details, validate against the SAP S/4HANA PO, and post for payment if within the approved tolerance threshold."
          inputParameters:
            - name: invoice_id
              in: body
              type: string
              description: "The SAP Ariba invoice ID to process."
            - name: tolerance_pct
              in: body
              type: number
              description: "Acceptable variance percentage between invoice and PO amount (e.g., 2.0)."
          steps:
            - name: get-invoice
              type: call
              call: "ariba-inv.get-invoice"
              with:
                invoice_id: "{{invoice_id}}"
            - name: get-po
              type: call
              call: "sap-inv.get-po"
              with:
                po_number: "{{get-invoice.purchaseOrderId}}"
            - name: post-payment
              type: call
              call: "sap-inv.post-invoice"
              with:
                po_number: "{{get-invoice.purchaseOrderId}}"
                invoice_amount: "{{get-invoice.totalAmount}}"
                vendor_id: "{{get-po.vendorId}}"
  consumes:
    - type: http
      namespace: ariba-inv
      baseUri: "https://openapi.ariba.com/api/invoice/v1"
      authentication:
        type: apikey
        key: "APIKey"
        value: "$secrets.ariba_api_key"
        placement: header
      resources:
        - name: invoices
          path: "/invoices/{{invoice_id}}"
          inputParameters:
            - name: invoice_id
              in: path
          operations:
            - name: get-invoice
              method: GET
    - type: http
      namespace: sap-inv
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/MM_PUR_PO_MAINT_V2_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: purchase-orders
          path: "/A_PurchaseOrder('{{po_number}}')"
          inputParameters:
            - name: po_number
              in: path
          operations:
            - name: get-po
              method: GET
              outputRawFormat: xml
        - name: invoice-postings
          path: "/A_SupplierInvoice"
          operations:
            - name: post-invoice
              method: POST

Generates batch traceability reports by querying SAP for batch genealogy, enriching with quality data from Snowflake, and posting the report to the quality team via Teams.

naftiko: "0.5"
info:
  label: "SAP Batch Traceability Report"
  description: "Generates batch traceability reports by querying SAP for batch genealogy, enriching with quality data from Snowflake, and posting the report to the quality team via Teams."
  tags:
    - quality
    - manufacturing
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: quality-traceability
      port: 8080
      tools:
        - name: generate-traceability-report
          description: "Generate batch traceability report: query SAP genealogy, enrich with quality data, and post report."
          inputParameters:
            - name: batch_number
              in: body
              type: string
              description: "The batch number to trace."
            - name: material_number
              in: body
              type: string
              description: "The SAP material number."
          steps:
            - name: get-batch-genealogy
              type: call
              call: "sap-qm.get-batch-where-used"
              with:
                batch: "{{batch_number}}"
                material: "{{material_number}}"
            - name: get-quality-data
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT test_name, result, specification FROM quality.batch_test_results WHERE batch_number='{{batch_number}}'"
            - name: post-report
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.quality_team_id"
                channel_id: "$secrets.quality_channel_id"
                body: "Batch traceability report for {{batch_number}} (material {{material_number}}) generated. Genealogy and quality data compiled."
  consumes:
    - type: http
      namespace: sap-qm
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_BATCH_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: batches
          path: "/Batch"
          operations:
            - name: get-batch-where-used
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Retrieves pending SAP Concur expense reports above threshold and routes each to the employee's manager in Teams for one-click review and approval.

naftiko: "0.5"
info:
  label: "SAP Concur Expense Report Approval Routing"
  description: "Retrieves pending SAP Concur expense reports above threshold and routes each to the employee's manager in Teams for one-click review and approval."
  tags:
    - finance
    - expense-management
    - sap-concur
    - microsoft-teams
    - approval
capability:
  exposes:
    - type: mcp
      namespace: finance-expenses
      port: 8080
      tools:
        - name: route-expense-approval
          description: "Given an SAP Concur expense report ID and approver email, retrieve report details and send an approval notification to the manager in Teams."
          inputParameters:
            - name: report_id
              in: body
              type: string
              description: "The SAP Concur expense report ID to route for approval."
            - name: approver_email
              in: body
              type: string
              description: "The Teams UPN of the approving manager."
          steps:
            - name: get-report
              type: call
              call: "concur.get-expense-report"
              with:
                report_id: "{{report_id}}"
            - name: notify-approver
              type: call
              call: "msteams-expense.post-message"
              with:
                recipient: "{{approver_email}}"
                message: "Expense report {{report_id}} from {{get-report.employeeName}} — Total: {{get-report.total}} {{get-report.currency}}. Please review in Concur."
  consumes:
    - type: http
      namespace: concur
      baseUri: "https://www.concursolutions.com/api/v3.0"
      authentication:
        type: bearer
        token: "$secrets.concur_token"
      resources:
        - name: expense-reports
          path: "/expense/reportdigests/{{report_id}}"
          inputParameters:
            - name: report_id
              in: path
          operations:
            - name: get-expense-report
              method: GET
    - type: http
      namespace: msteams-expense
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST

Reviews a SAP Concur travel request against corporate travel policy in Snowflake, flags exceptions, and routes non-compliant requests to the travel manager via Teams.

naftiko: "0.5"
info:
  label: "SAP Concur Travel Request Compliance Check"
  description: "Reviews a SAP Concur travel request against corporate travel policy in Snowflake, flags exceptions, and routes non-compliant requests to the travel manager via Teams."
  tags:
    - travel
    - sap-concur
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: travel-compliance
      port: 8080
      tools:
        - name: check-travel-compliance
          description: "Check travel request compliance: get request details from Concur, validate against policy, and flag exceptions."
          inputParameters:
            - name: request_id
              in: body
              type: string
              description: "The SAP Concur travel request ID."
          steps:
            - name: get-request
              type: call
              call: "concur.get-travel-request"
              with:
                request_id: "{{request_id}}"
            - name: check-policy
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT max_daily_hotel, max_flight_class FROM corporate.travel_policy WHERE region = '{{get-request.region}}'"
            - name: notify-travel-manager
              type: call
              call: "msteams.post-message"
              with:
                recipient: "$secrets.travel_manager_email"
                message: "Travel request {{request_id}} for {{get-request.traveler_name}} reviewed. Destination: {{get-request.destination}}. Policy check complete."
  consumes:
    - type: http
      namespace: concur
      baseUri: "https://us.api.concursolutions.com/api/v3.0"
      authentication:
        type: bearer
        token: "$secrets.concur_token"
      resources:
        - name: travel-requests
          path: "/travelrequest/requests/{{request_id}}"
          inputParameters:
            - name: request_id
              in: path
          operations:
            - name: get-travel-request
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST

Retrieves budget allocation and current spend for a SAP S/4HANA cost center, used for finance and planning inquiries.

naftiko: "0.5"
info:
  label: "SAP Cost Center Budget Lookup"
  description: "Retrieves budget allocation and current spend for a SAP S/4HANA cost center, used for finance and planning inquiries."
  tags:
    - finance
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: finance-budget
      port: 8080
      tools:
        - name: get-cost-center-budget
          description: "Look up budget vs. actual spend for a SAP cost center. Returns allocated budget, actual spend, and remaining balance."
          inputParameters:
            - name: cost_center
              in: body
              type: string
              description: "The SAP cost center ID."
            - name: fiscal_year
              in: body
              type: string
              description: "Fiscal year in YYYY format."
          call: "sap-fi.get-cost-center"
          with:
            cost_center: "{{cost_center}}"
            fiscal_year: "{{fiscal_year}}"
          outputParameters:
            - name: allocated_budget
              type: string
              mapping: "$.d.PlannedAmount"
            - name: actual_spend
              type: string
              mapping: "$.d.ActualAmount"
            - name: remaining
              type: string
              mapping: "$.d.RemainingBudget"
  consumes:
    - type: http
      namespace: sap-fi
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_COSTCENTER_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: cost-centers
          path: "/A_CostCenter(CostCenter='{{cost_center}}',FiscalYear='{{fiscal_year}}')"
          inputParameters:
            - name: cost_center
              in: path
            - name: fiscal_year
              in: path
          operations:
            - name: get-cost-center
              method: GET

Checks SAP S/4HANA for the goods receipt status of a purchase order, returning posting date and quantity received.

naftiko: "0.5"
info:
  label: "SAP Goods Receipt Status Lookup"
  description: "Checks SAP S/4HANA for the goods receipt status of a purchase order, returning posting date and quantity received."
  tags:
    - supply-chain
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: scm-receiving
      port: 8080
      tools:
        - name: get-goods-receipt-status
          description: "Look up goods receipt status for a SAP purchase order. Returns posting date, received quantity, and delivery status."
          inputParameters:
            - name: po_number
              in: body
              type: string
              description: "The SAP purchase order number."
          call: "sap-gr.get-receipt"
          with:
            po_number: "{{po_number}}"
          outputParameters:
            - name: posting_date
              type: string
              mapping: "$.d.PostingDate"
            - name: quantity_received
              type: string
              mapping: "$.d.QuantityInEntryUnit"
            - name: delivery_completed
              type: boolean
              mapping: "$.d.DeliveryCompleted"
  consumes:
    - type: http
      namespace: sap-gr
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_MATERIAL_DOCUMENT_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: material-documents
          path: "/A_MaterialDocumentHeader"
          operations:
            - name: get-receipt
              method: GET

Reconciles intercompany billing by comparing SAP S/4HANA company codes, posting variances to Snowflake, and notifying the finance controller via Teams.

naftiko: "0.5"
info:
  label: "SAP Intercompany Billing Reconciliation"
  description: "Reconciles intercompany billing by comparing SAP S/4HANA company codes, posting variances to Snowflake, and notifying the finance controller via Teams."
  tags:
    - finance
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: finance-interco
      port: 8080
      tools:
        - name: reconcile-intercompany
          description: "Reconcile intercompany billing: compare SAP balances, log variances, and notify controller."
          inputParameters:
            - name: sending_company
              in: body
              type: string
              description: "The sending SAP company code."
            - name: receiving_company
              in: body
              type: string
              description: "The receiving SAP company code."
            - name: period
              in: body
              type: string
              description: "The fiscal period."
          steps:
            - name: get-sending-balance
              type: call
              call: "sap-fi.get-interco-balance"
              with:
                company_code: "{{sending_company}}"
                partner: "{{receiving_company}}"
                period: "{{period}}"
            - name: get-receiving-balance
              type: call
              call: "sap-fi.get-interco-balance"
              with:
                company_code: "{{receiving_company}}"
                partner: "{{sending_company}}"
                period: "{{period}}"
            - name: log-variance
              type: call
              call: "snowflake.run-query"
              with:
                statement: "INSERT INTO finance.interco_reconciliation (sending, receiving, period, variance, reconciled_at) VALUES ('{{sending_company}}', '{{receiving_company}}', '{{period}}', '{{get-sending-balance.amount}}', CURRENT_TIMESTAMP())"
            - name: notify-controller
              type: call
              call: "msteams.post-message"
              with:
                recipient: "$secrets.finance_controller_email"
                message: "Intercompany reconciliation complete: {{sending_company}} vs {{receiving_company}} for period {{period}}."
  consumes:
    - type: http
      namespace: sap-fi
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_JOURNALENTRYITEMBASIC_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: journal-entries
          path: "/A_JournalEntryItemBasic"
          operations:
            - name: get-interco-balance
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST

Retrieves SAP S/4HANA material master data by material number, returning description, base unit, material group, and plant availability.

naftiko: "0.5"
info:
  label: "SAP Material Master Lookup"
  description: "Retrieves SAP S/4HANA material master data by material number, returning description, base unit, material group, and plant availability."
  tags:
    - supply-chain
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: scm-material
      port: 8080
      tools:
        - name: get-material-master
          description: "Look up a SAP material master record by material number. Returns description, base unit, material group, and plant data."
          inputParameters:
            - name: material_number
              in: body
              type: string
              description: "The SAP material number."
          call: "sap-mm.get-material"
          with:
            material_number: "{{material_number}}"
          outputParameters:
            - name: description
              type: string
              mapping: "$.d.MaterialDescription"
            - name: base_unit
              type: string
              mapping: "$.d.BaseUnit"
            - name: material_group
              type: string
              mapping: "$.d.MaterialGroup"
  consumes:
    - type: http
      namespace: sap-mm
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_PRODUCT_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: materials
          path: "/A_Product('{{material_number}}')"
          inputParameters:
            - name: material_number
              in: path
          operations:
            - name: get-material
              method: GET

Retrieves a SAP plant maintenance order by number, returning equipment details, work center, and order status for manufacturing operations.

naftiko: "0.5"
info:
  label: "SAP Plant Maintenance Order Lookup"
  description: "Retrieves a SAP plant maintenance order by number, returning equipment details, work center, and order status for manufacturing operations."
  tags:
    - manufacturing
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: mfg-maintenance
      port: 8080
      tools:
        - name: get-maintenance-order
          description: "Look up a SAP plant maintenance order. Returns equipment, work center, priority, and status."
          inputParameters:
            - name: order_number
              in: body
              type: string
              description: "The SAP maintenance order number."
          call: "sap-pm.get-order"
          with:
            order_number: "{{order_number}}"
          outputParameters:
            - name: equipment
              type: string
              mapping: "$.d.Equipment"
            - name: work_center
              type: string
              mapping: "$.d.MainWorkCenter"
            - name: status
              type: string
              mapping: "$.d.OrderStatus"
  consumes:
    - type: http
      namespace: sap-pm
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_MAINTENANCEORDER"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: maintenance-orders
          path: "/MaintenanceOrder('{{order_number}}')"
          inputParameters:
            - name: order_number
              in: path
          operations:
            - name: get-order
              method: GET

Optimizes production scheduling by pulling current orders from SAP PP, analyzing capacity in Snowflake, and updating the manufacturing team via Teams.

naftiko: "0.5"
info:
  label: "SAP Production Order Scheduling Optimizer"
  description: "Optimizes production scheduling by pulling current orders from SAP PP, analyzing capacity in Snowflake, and updating the manufacturing team via Teams."
  tags:
    - manufacturing
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: mfg-scheduling
      port: 8080
      tools:
        - name: optimize-schedule
          description: "Optimize production scheduling: pull SAP orders, analyze capacity, and update team."
          inputParameters:
            - name: plant
              in: body
              type: string
              description: "The SAP plant code."
            - name: production_line
              in: body
              type: string
              description: "The production line identifier."
          steps:
            - name: get-production-orders
              type: call
              call: "sap-pp.get-orders"
              with:
                plant: "{{plant}}"
                production_line: "{{production_line}}"
            - name: analyze-capacity
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT available_hours, utilization_pct FROM manufacturing.capacity WHERE plant='{{plant}}' AND line='{{production_line}}'"
            - name: notify-mfg-team
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.mfg_team_id"
                channel_id: "$secrets.mfg_channel_id"
                body: "Production schedule optimized for plant {{plant}}, line {{production_line}}. Capacity utilization analyzed."
  consumes:
    - type: http
      namespace: sap-pp
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_PRODUCTION_ORDER_2_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: production-orders
          path: "/A_ProductionOrder_2"
          operations:
            - name: get-orders
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Retrieves a SAP S/4HANA purchase order by number, returning header status, vendor details, and total amount for procurement and finance review.

naftiko: "0.5"
info:
  label: "SAP Purchase Order Lookup"
  description: "Retrieves a SAP S/4HANA purchase order by number, returning header status, vendor details, and total amount for procurement and finance review."
  tags:
    - finance
    - procurement
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: erp-procurement
      port: 8080
      tools:
        - name: get-purchase-order
          description: "Look up a SAP S/4HANA purchase order by PO number. Returns overall status, vendor name, total amount, and currency. Use for procurement approval or spend visibility."
          inputParameters:
            - name: po_number
              in: body
              type: string
              description: "The SAP purchase order number (e.g., 4500098765)."
          call: "sap-po.get-po"
          with:
            po_number: "{{po_number}}"
          outputParameters:
            - name: status
              type: string
              mapping: "$.d.OverallStatus"
            - name: vendor
              type: string
              mapping: "$.d.Supplier.CompanyName"
            - name: total_amount
              type: string
              mapping: "$.d.TotalAmount"
            - name: currency
              type: string
              mapping: "$.d.TransactionCurrency"
  consumes:
    - type: http
      namespace: sap-po
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/MM_PUR_PO_MAINT_V2_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: purchase-orders
          path: "/A_PurchaseOrder('{{po_number}}')"
          inputParameters:
            - name: po_number
              in: path
          operations:
            - name: get-po
              method: GET
              outputRawFormat: xml

Pulls cost center budget and actual spend from SAP S/4HANA for a specified fiscal period and posts a variance summary to the finance leadership channel in Teams.

naftiko: "0.5"
info:
  label: "SAP S/4HANA Budget vs Actuals Report"
  description: "Pulls cost center budget and actual spend from SAP S/4HANA for a specified fiscal period and posts a variance summary to the finance leadership channel in Teams."
  tags:
    - finance
    - sap
    - microsoft-teams
    - reporting
    - budget
capability:
  exposes:
    - type: mcp
      namespace: finance-budget
      port: 8080
      tools:
        - name: report-budget-variance
          description: "Given an SAP cost center and fiscal period, retrieve budget vs. actuals from SAP S/4HANA and post a variance digest to the finance Teams channel."
          inputParameters:
            - name: cost_center
              in: body
              type: string
              description: "The SAP cost center ID (e.g., CC2001)."
            - name: fiscal_period
              in: body
              type: string
              description: "The fiscal period in YYYYMM format (e.g., 202503)."
          steps:
            - name: get-actuals
              type: call
              call: "sap-budget.get-cost-center-actuals"
              with:
                costCenter: "{{cost_center}}"
                fiscalPeriod: "{{fiscal_period}}"
            - name: post-report
              type: call
              call: "msteams-budget.post-message"
              with:
                channel: "finance-leadership"
                message: "Budget vs Actuals for {{cost_center}} ({{fiscal_period}}): Budget={{get-actuals.budget}}, Actual={{get-actuals.actual}}, Variance={{get-actuals.variance}}"
  consumes:
    - type: http
      namespace: sap-budget
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_COSTCENTER_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: cost-center-actuals
          path: "/A_CostCenter('{{costCenter}}')"
          inputParameters:
            - name: costCenter
              in: path
          operations:
            - name: get-cost-center-actuals
              method: GET
              outputRawFormat: xml
    - type: http
      namespace: msteams-budget
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Promotes SAP transport requests through landscapes by verifying approvals in ServiceNow, executing the transport in SAP, and logging the promotion in Snowflake for audit.

naftiko: "0.5"
info:
  label: "SAP Transport Request Promotion Workflow"
  description: "Promotes SAP transport requests through landscapes by verifying approvals in ServiceNow, executing the transport in SAP, and logging the promotion in Snowflake for audit."
  tags:
    - devops
    - sap
    - servicenow
    - snowflake
capability:
  exposes:
    - type: mcp
      namespace: sap-transport
      port: 8080
      tools:
        - name: promote-transport
          description: "Promote SAP transport: verify approval, execute transport, and log for audit."
          inputParameters:
            - name: transport_number
              in: body
              type: string
              description: "The SAP transport request number."
            - name: target_system
              in: body
              type: string
              description: "The target SAP system (QAS, PRD)."
          steps:
            - name: verify-approval
              type: call
              call: "servicenow.get-change"
              with:
                transport: "{{transport_number}}"
            - name: execute-transport
              type: call
              call: "sap-basis.import-transport"
              with:
                transport: "{{transport_number}}"
                target: "{{target_system}}"
            - name: log-promotion
              type: call
              call: "snowflake.run-query"
              with:
                statement: "INSERT INTO sap_ops.transport_promotions (transport_number, target_system, approval_ticket, promoted_at) VALUES ('{{transport_number}}', '{{target_system}}', '{{verify-approval.number}}', CURRENT_TIMESTAMP())"
  consumes:
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: change-requests
          path: "/table/change_request"
          operations:
            - name: get-change
              method: GET
    - type: http
      namespace: sap-basis
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_TRANSPORT_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: transports
          path: "/TransportRequest"
          operations:
            - name: import-transport
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST

Retrieves SAP S/4HANA vendor master record details for a given vendor ID, surfacing payment terms, compliance flags, and company information.

naftiko: "0.5"
info:
  label: "SAP Vendor Master Data Lookup"
  description: "Retrieves SAP S/4HANA vendor master record details for a given vendor ID, surfacing payment terms, compliance flags, and company information."
  tags:
    - finance
    - procurement
    - sap
    - vendor-management
capability:
  exposes:
    - type: mcp
      namespace: erp-vendor
      port: 8080
      tools:
        - name: get-vendor-record
          description: "Look up a SAP S/4HANA vendor master record by vendor ID. Returns company name, payment terms, and compliance status. Use before approving new supplier engagements."
          inputParameters:
            - name: vendor_id
              in: body
              type: string
              description: "The SAP vendor (supplier) ID to look up."
          call: "sap-vendor.get-vendor"
          with:
            vendor_id: "{{vendor_id}}"
          outputParameters:
            - name: company_name
              type: string
              mapping: "$.d.BusinessPartnerFullName"
            - name: payment_terms
              type: string
              mapping: "$.d.PaymentTerms"
            - name: currency
              type: string
              mapping: "$.d.Currency"
  consumes:
    - type: http
      namespace: sap-vendor
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_BUSINESS_PARTNER"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: vendors
          path: "/A_Supplier('{{vendor_id}}')"
          inputParameters:
            - name: vendor_id
              in: path
          operations:
            - name: get-vendor
              method: GET
              outputRawFormat: xml

Orchestrates inter-plant stock transfers by creating transfer orders in SAP, updating inventory projections in Snowflake, and notifying warehouse managers via Teams.

naftiko: "0.5"
info:
  label: "SAP Warehouse Stock Transfer Orchestrator"
  description: "Orchestrates inter-plant stock transfers by creating transfer orders in SAP, updating inventory projections in Snowflake, and notifying warehouse managers via Teams."
  tags:
    - supply-chain
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: scm-stock-transfer
      port: 8080
      tools:
        - name: transfer-stock
          description: "Orchestrate stock transfer: create SAP transfer order, update projections, and notify managers."
          inputParameters:
            - name: material_number
              in: body
              type: string
              description: "The SAP material number."
            - name: source_plant
              in: body
              type: string
              description: "The source plant code."
            - name: target_plant
              in: body
              type: string
              description: "The target plant code."
            - name: quantity
              in: body
              type: string
              description: "The transfer quantity."
          steps:
            - name: create-transfer-order
              type: call
              call: "sap-mm.create-transfer"
              with:
                material: "{{material_number}}"
                source: "{{source_plant}}"
                target: "{{target_plant}}"
                quantity: "{{quantity}}"
            - name: update-projections
              type: call
              call: "snowflake.run-query"
              with:
                statement: "UPDATE supply_chain.inventory_projections SET projected_qty=projected_qty-{{quantity}} WHERE material='{{material_number}}' AND plant='{{source_plant}}'"
            - name: notify-managers
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.warehouse_team_id"
                channel_id: "$secrets.warehouse_channel_id"
                body: "Stock transfer initiated: {{quantity}} units of {{material_number}} from {{source_plant}} to {{target_plant}}. Transfer order: {{create-transfer-order.order_id}}."
  consumes:
    - type: http
      namespace: sap-mm
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_STOCK_TRANSFER_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: transfers
          path: "/StockTransferOrder"
          operations:
            - name: create-transfer
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Advances a ServiceNow change request to CAB approval state and notifies the requester in Teams with review timeline and next steps.

naftiko: "0.5"
info:
  label: "ServiceNow Change Request Approval"
  description: "Advances a ServiceNow change request to CAB approval state and notifies the requester in Teams with review timeline and next steps."
  tags:
    - itsm
    - change-management
    - servicenow
    - microsoft-teams
    - approval
capability:
  exposes:
    - type: mcp
      namespace: itsm-change
      port: 8080
      tools:
        - name: submit-change-for-approval
          description: "Given a ServiceNow change request number, advance it to CAB approval state and notify the requester in Teams."
          inputParameters:
            - name: change_number
              in: body
              type: string
              description: "The ServiceNow change request number (e.g., CHG0099887)."
            - name: requester_email
              in: body
              type: string
              description: "The Teams UPN of the change requester."
          steps:
            - name: get-change
              type: call
              call: "servicenow-chg.get-change"
              with:
                number: "{{change_number}}"
            - name: submit-approval
              type: call
              call: "servicenow-chg.update-change"
              with:
                sys_id: "{{get-change.sys_id}}"
                state: "approval"
            - name: notify-requester
              type: call
              call: "msteams-chg.post-message"
              with:
                recipient: "{{requester_email}}"
                message: "Your change request {{change_number}} has been submitted for CAB approval."
  consumes:
    - type: http
      namespace: servicenow-chg
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: changes
          path: "/table/change_request"
          operations:
            - name: get-change
              method: GET
            - name: update-change
              method: PATCH
    - type: http
      namespace: msteams-chg
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST

Retrieves a configuration item from the ServiceNow CMDB by asset tag, returning owner, status, and location.

naftiko: "0.5"
info:
  label: "ServiceNow CMDB Asset Lookup"
  description: "Retrieves a configuration item from the ServiceNow CMDB by asset tag, returning owner, status, and location."
  tags:
    - it-asset-management
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: itsm-cmdb
      port: 8080
      tools:
        - name: get-cmdb-asset
          description: "Look up a ServiceNow CMDB configuration item by asset tag. Returns owner, operational status, and physical location."
          inputParameters:
            - name: asset_tag
              in: body
              type: string
              description: "The asset tag identifier."
          call: "servicenow.get-ci"
          with:
            sysparm_query: "asset_tag={{asset_tag}}"
          outputParameters:
            - name: owner
              type: string
              mapping: "$.result[0].owned_by.display_value"
            - name: status
              type: string
              mapping: "$.result[0].operational_status"
            - name: location
              type: string
              mapping: "$.result[0].location.display_value"
  consumes:
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: cmdb-ci
          path: "/table/cmdb_ci"
          operations:
            - name: get-ci
              method: GET

Returns the current state, priority, assignment group, and short description of a ServiceNow incident by number for rapid triage.

naftiko: "0.5"
info:
  label: "ServiceNow Incident Status Lookup"
  description: "Returns the current state, priority, assignment group, and short description of a ServiceNow incident by number for rapid triage."
  tags:
    - itsm
    - servicenow
    - triage
    - operations
capability:
  exposes:
    - type: mcp
      namespace: itsm-lookup
      port: 8080
      tools:
        - name: get-incident-status
          description: "Given a ServiceNow incident number, return its current state, priority, assignment group, and description. Use for rapid triage or pre-war-room briefing."
          inputParameters:
            - name: incident_number
              in: body
              type: string
              description: "The ServiceNow incident number (e.g., INC0123456)."
          call: "servicenow-lookup.get-incident"
          with:
            number: "{{incident_number}}"
          outputParameters:
            - name: state
              type: string
              mapping: "$.result[0].state"
            - name: priority
              type: string
              mapping: "$.result[0].priority"
            - name: assignment_group
              type: string
              mapping: "$.result[0].assignment_group.display_value"
            - name: short_description
              type: string
              mapping: "$.result[0].short_description"
  consumes:
    - type: http
      namespace: servicenow-lookup
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: get-incident
              method: GET

Searches ServiceNow knowledge base by keyword, returning matching articles with titles, summaries, and links for employee self-service.

naftiko: "0.5"
info:
  label: "ServiceNow Knowledge Article Lookup"
  description: "Searches ServiceNow knowledge base by keyword, returning matching articles with titles, summaries, and links for employee self-service."
  tags:
    - it-service-management
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: itsm-knowledge
      port: 8080
      tools:
        - name: search-knowledge-articles
          description: "Search ServiceNow knowledge base articles by keyword. Returns matching article titles, short descriptions, and URLs."
          inputParameters:
            - name: query
              in: body
              type: string
              description: "The search keyword or phrase."
          call: "servicenow.search-kb"
          with:
            sysparm_query: "short_descriptionLIKE{{query}}"
          outputParameters:
            - name: articles
              type: array
              mapping: "$.result"
  consumes:
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: knowledge-articles
          path: "/table/kb_knowledge"
          operations:
            - name: search-kb
              method: GET

Lists documents in a SharePoint document library by site and library name, returning file names, sizes, and last modified dates.

naftiko: "0.5"
info:
  label: "SharePoint Document Library Listing"
  description: "Lists documents in a SharePoint document library by site and library name, returning file names, sizes, and last modified dates."
  tags:
    - collaboration
    - sharepoint
capability:
  exposes:
    - type: mcp
      namespace: collab-docs
      port: 8080
      tools:
        - name: list-documents
          description: "List files in a SharePoint document library. Returns file names, sizes, and last modified dates."
          inputParameters:
            - name: site_id
              in: body
              type: string
              description: "The SharePoint site ID."
            - name: library_name
              in: body
              type: string
              description: "The document library name."
          call: "sharepoint.list-items"
          with:
            site_id: "{{site_id}}"
            library: "{{library_name}}"
          outputParameters:
            - name: files
              type: array
              mapping: "$.value"
  consumes:
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: drive-items
          path: "/sites/{{site_id}}/drives"
          inputParameters:
            - name: site_id
              in: path
          operations:
            - name: list-items
              method: GET

Identifies SOPs due for periodic review in SharePoint, creates review tasks in Jira, and notifies document owners via Teams.

naftiko: "0.5"
info:
  label: "SharePoint SOP Review Reminder"
  description: "Identifies SOPs due for periodic review in SharePoint, creates review tasks in Jira, and notifies document owners via Teams."
  tags:
    - quality
    - compliance
    - sharepoint
    - jira
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: quality-sop-review
      port: 8080
      tools:
        - name: trigger-sop-review
          description: "Trigger SOP review cycle: find due SOPs in SharePoint, create Jira tasks, and notify owners."
          inputParameters:
            - name: site_id
              in: body
              type: string
              description: "The SharePoint site ID containing SOPs."
          steps:
            - name: get-due-sops
              type: call
              call: "sharepoint.list-items"
              with:
                site_id: "{{site_id}}"
                filter: "reviewDueDate le today"
            - name: create-review-task
              type: call
              call: "jira.create-issue"
              with:
                project: "QUALITY"
                summary: "SOP periodic review due"
                issue_type: "Task"
            - name: notify-owners
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.quality_team_id"
                channel_id: "$secrets.quality_channel_id"
                body: "SOP review cycle initiated. Review tasks created in Jira. Please check your assignments."
  consumes:
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: drive-items
          path: "/sites/{{site_id}}/drives"
          inputParameters:
            - name: site_id
              in: path
          operations:
            - name: list-items
              method: GET
    - type: http
      namespace: jira
      baseUri: "https://sanofi.atlassian.net/rest/api/3"
      authentication:
        type: basic
        username: "$secrets.jira_user"
        password: "$secrets.jira_api_token"
      resources:
        - name: issues
          path: "/issue"
          operations:
            - name: create-issue
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Queries Snowflake for recent pipeline execution failures and posts a health digest to the data engineering channel in Microsoft Teams.

naftiko: "0.5"
info:
  label: "Snowflake Data Pipeline Health Check"
  description: "Queries Snowflake for recent pipeline execution failures and posts a health digest to the data engineering channel in Microsoft Teams."
  tags:
    - data
    - snowflake
    - microsoft-teams
    - monitoring
    - analytics
capability:
  exposes:
    - type: mcp
      namespace: data-ops
      port: 8080
      tools:
        - name: check-pipeline-health
          description: "Query Snowflake task execution history for failures or delays in the past 24 hours and post a pipeline health summary to the data engineering Teams channel."
          inputParameters:
            - name: database
              in: body
              type: string
              description: "The Snowflake database to check pipeline health for."
            - name: hours_back
              in: body
              type: integer
              description: "Number of hours of task history to review (e.g., 24)."
          steps:
            - name: get-task-history
              type: call
              call: "snowflake-ops.query-task-history"
              with:
                database: "{{database}}"
                hoursBack: "{{hours_back}}"
            - name: post-summary
              type: call
              call: "msteams-data.post-message"
              with:
                channel: "data-engineering"
                message: "Snowflake pipeline health for {{database}} (last {{hours_back}}h): {{get-task-history.summary}}"
  consumes:
    - type: http
      namespace: snowflake-ops
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: task-history
          path: "/databases/{{database}}/tasks/history"
          inputParameters:
            - name: database
              in: path
          operations:
            - name: query-task-history
              method: GET
    - type: http
      namespace: msteams-data
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Grants Snowflake data sharing access by validating the request in ServiceNow, executing the share command in Snowflake, and logging the grant in the governance audit trail.

naftiko: "0.5"
info:
  label: "Snowflake Data Sharing Access Grant"
  description: "Grants Snowflake data sharing access by validating the request in ServiceNow, executing the share command in Snowflake, and logging the grant in the governance audit trail."
  tags:
    - data-governance
    - snowflake
    - servicenow
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: data-sharing
      port: 8080
      tools:
        - name: grant-data-share
          description: "Grant data share access: validate request, execute share, and log for governance."
          inputParameters:
            - name: share_name
              in: body
              type: string
              description: "The Snowflake share name."
            - name: consumer_account
              in: body
              type: string
              description: "The consumer Snowflake account."
            - name: approval_ticket
              in: body
              type: string
              description: "The ServiceNow approval ticket number."
          steps:
            - name: validate-approval
              type: call
              call: "servicenow.get-change"
              with:
                number: "{{approval_ticket}}"
            - name: execute-share
              type: call
              call: "snowflake.run-query"
              with:
                statement: "ALTER SHARE {{share_name}} ADD ACCOUNTS = {{consumer_account}}"
            - name: log-governance
              type: call
              call: "snowflake.run-query"
              with:
                statement: "INSERT INTO governance.data_sharing_log (share_name, consumer_account, approval_ticket, granted_at) VALUES ('{{share_name}}', '{{consumer_account}}', '{{approval_ticket}}', CURRENT_TIMESTAMP())"
            - name: notify-governance
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.governance_team_id"
                channel_id: "$secrets.governance_channel_id"
                body: "Data share {{share_name}} granted to {{consumer_account}}. Approval: {{approval_ticket}}."
  consumes:
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: change-requests
          path: "/table/change_request"
          operations:
            - name: get-change
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Identifies the slowest-running Snowflake queries in the past 24 hours and posts an optimization digest to the data engineering channel in Teams.

naftiko: "0.5"
info:
  label: "Snowflake Query Performance Digest"
  description: "Identifies the slowest-running Snowflake queries in the past 24 hours and posts an optimization digest to the data engineering channel in Teams."
  tags:
    - data
    - snowflake
    - microsoft-teams
    - performance
    - analytics
capability:
  exposes:
    - type: mcp
      namespace: data-performance
      port: 8080
      tools:
        - name: digest-slow-queries
          description: "Query Snowflake's query history to identify the 10 slowest-running queries in the last 24 hours and post an optimization digest to the data engineering Teams channel."
          inputParameters:
            - name: warehouse
              in: body
              type: string
              description: "The Snowflake virtual warehouse to analyze query performance for."
          steps:
            - name: get-slow-queries
              type: call
              call: "snowflake-perf.query-history"
              with:
                warehouse: "{{warehouse}}"
            - name: post-digest
              type: call
              call: "msteams-perf.post-message"
              with:
                channel: "data-engineering"
                message: "Top slow queries in warehouse {{warehouse}} (last 24h): {{get-slow-queries.summary}}"
  consumes:
    - type: http
      namespace: snowflake-perf
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: query-history
          path: "/warehouses/{{warehouse}}/queries"
          inputParameters:
            - name: warehouse
              in: path
          operations:
            - name: query-history
              method: GET
    - type: http
      namespace: msteams-perf
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Queries Snowflake to return the row count for a specified table, used for data pipeline validation and monitoring.

naftiko: "0.5"
info:
  label: "Snowflake Table Row Count Check"
  description: "Queries Snowflake to return the row count for a specified table, used for data pipeline validation and monitoring."
  tags:
    - data-engineering
    - snowflake
capability:
  exposes:
    - type: mcp
      namespace: data-quality
      port: 8080
      tools:
        - name: get-table-row-count
          description: "Query Snowflake for the row count of a given table. Use for data pipeline completeness checks."
          inputParameters:
            - name: table_name
              in: body
              type: string
              description: "Fully qualified Snowflake table name (database.schema.table)."
          call: "snowflake.run-query"
          with:
            statement: "SELECT COUNT(*) AS row_count FROM {{table_name}}"
          outputParameters:
            - name: row_count
              type: integer
              mapping: "$.data[0][0]"
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST

Assesses supplier risk by pulling vendor data from SAP, checking compliance scores in Snowflake, and creating risk review tickets in ServiceNow.

naftiko: "0.5"
info:
  label: "Supplier Risk Assessment Orchestrator"
  description: "Assesses supplier risk by pulling vendor data from SAP, checking compliance scores in Snowflake, and creating risk review tickets in ServiceNow."
  tags:
    - procurement
    - risk-management
    - sap
    - snowflake
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: procurement-risk
      port: 8080
      tools:
        - name: assess-supplier-risk
          description: "Assess supplier risk: get vendor data, check compliance scores, and create risk review."
          inputParameters:
            - name: vendor_id
              in: body
              type: string
              description: "The SAP vendor ID."
          steps:
            - name: get-vendor-data
              type: call
              call: "sap-mm.get-vendor"
              with:
                vendor_id: "{{vendor_id}}"
            - name: get-compliance-score
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT risk_score, last_audit_date, compliance_status FROM procurement.supplier_risk WHERE vendor_id='{{vendor_id}}'"
            - name: create-risk-review
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "Supplier risk review: {{get-vendor-data.CompanyName}} ({{vendor_id}})"
                category: "supplier_risk"
                assigned_group: "Procurement_Risk"
  consumes:
    - type: http
      namespace: sap-mm
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_BUSINESS_PARTNER"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: vendors
          path: "/A_BusinessPartner('{{vendor_id}}')"
          inputParameters:
            - name: vendor_id
              in: path
          operations:
            - name: get-vendor
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST

Monitors SAP inventory levels, triggers a purchase requisition when stock falls below threshold, and alerts the supply chain team via Teams.

naftiko: "0.5"
info:
  label: "Supply Chain Inventory Reorder Trigger"
  description: "Monitors SAP inventory levels, triggers a purchase requisition when stock falls below threshold, and alerts the supply chain team via Teams."
  tags:
    - supply-chain
    - sap
    - sap-ariba
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: scm-reorder
      port: 8080
      tools:
        - name: trigger-reorder
          description: "Check inventory levels and trigger reorder if below threshold."
          inputParameters:
            - name: material_number
              in: body
              type: string
              description: "The SAP material number."
            - name: plant
              in: body
              type: string
              description: "The SAP plant code."
          steps:
            - name: check-inventory
              type: call
              call: "sap-mm.get-stock"
              with:
                material: "{{material_number}}"
                plant: "{{plant}}"
            - name: create-requisition
              type: call
              call: "ariba.create-requisition"
              with:
                material: "{{material_number}}"
                quantity: "{{check-inventory.reorder_quantity}}"
                plant: "{{plant}}"
            - name: notify-supply-chain
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.scm_team_id"
                channel_id: "$secrets.scm_channel_id"
                body: "Reorder triggered for material {{material_number}} at plant {{plant}}. Requisition {{create-requisition.id}} created."
  consumes:
    - type: http
      namespace: sap-mm
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_MATERIAL_STOCK_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: stock
          path: "/A_MatlStkInAcctMod"
          operations:
            - name: get-stock
              method: GET
    - type: http
      namespace: ariba
      baseUri: "https://openapi.ariba.com/api/procurement/v1"
      authentication:
        type: bearer
        token: "$secrets.ariba_token"
      resources:
        - name: requisitions
          path: "/requisitions"
          operations:
            - name: create-requisition
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Handles temperature excursions in vaccine cold chain by logging the event in SAP QM, creating a quality deviation in Veeva Vault, and alerting supply chain quality via Teams.

naftiko: "0.5"
info:
  label: "Vaccine Cold Chain Temperature Excursion Handler"
  description: "Handles temperature excursions in vaccine cold chain by logging the event in SAP QM, creating a quality deviation in Veeva Vault, and alerting supply chain quality via Teams."
  tags:
    - supply-chain
    - quality
    - sap
    - veeva
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: scm-cold-chain
      port: 8080
      tools:
        - name: handle-temperature-excursion
          description: "Handle cold chain temperature excursion: log in SAP, create deviation, and alert quality team."
          inputParameters:
            - name: shipment_id
              in: body
              type: string
              description: "The shipment identifier."
            - name: max_temperature
              in: body
              type: string
              description: "The maximum recorded temperature."
            - name: location
              in: body
              type: string
              description: "The location where excursion occurred."
          steps:
            - name: log-excursion
              type: call
              call: "sap-qm.create-notification"
              with:
                type: "temperature_excursion"
                shipment: "{{shipment_id}}"
                temperature: "{{max_temperature}}"
                location: "{{location}}"
            - name: create-deviation
              type: call
              call: "veeva-vault.create-document"
              with:
                type: "quality_deviation"
                description: "Temperature excursion on shipment {{shipment_id}} at {{location}}. Max temp: {{max_temperature}}"
            - name: alert-quality
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.scm_quality_team_id"
                channel_id: "$secrets.scm_quality_channel_id"
                body: "ALERT: Temperature excursion on shipment {{shipment_id}} at {{location}}. Max temp: {{max_temperature}}. SAP notification: {{log-excursion.notification_id}}. Deviation: {{create-deviation.id}}."
  consumes:
    - type: http
      namespace: sap-qm
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_QUALITYNOTIFICATION_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: notifications
          path: "/QualityNotification"
          operations:
            - name: create-notification
              method: POST
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: documents
          path: "/objects/documents"
          operations:
            - name: create-document
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Retrieves healthcare professional account details from Veeva CRM by account ID, returning specialty, address, and territory.

naftiko: "0.5"
info:
  label: "Veeva CRM Account Detail Lookup"
  description: "Retrieves healthcare professional account details from Veeva CRM by account ID, returning specialty, address, and territory."
  tags:
    - commercial
    - veeva
capability:
  exposes:
    - type: mcp
      namespace: commercial-crm
      port: 8080
      tools:
        - name: get-hcp-account
          description: "Look up a Veeva CRM HCP account by ID. Returns specialty, primary address, and territory assignment."
          inputParameters:
            - name: account_id
              in: body
              type: string
              description: "The Veeva CRM account ID."
          call: "veeva-crm.get-account"
          with:
            account_id: "{{account_id}}"
          outputParameters:
            - name: specialty
              type: string
              mapping: "$.Specialty_1_vod__c"
            - name: address
              type: string
              mapping: "$.Primary_Address_vod__c"
            - name: territory
              type: string
              mapping: "$.Territory_vod__c"
  consumes:
    - type: http
      namespace: veeva-crm
      baseUri: "https://sanofi.veevanetwork.com/api/v1"
      authentication:
        type: bearer
        token: "$secrets.veeva_crm_token"
      resources:
        - name: accounts
          path: "/accounts/{{account_id}}"
          inputParameters:
            - name: account_id
              in: path
          operations:
            - name: get-account
              method: GET

When a sales territory is reorganized, updates Veeva CRM account assignments for the affected medical representatives and notifies the commercial ops team in Teams.

naftiko: "0.5"
info:
  label: "Veeva CRM Territory Assignment Update"
  description: "When a sales territory is reorganized, updates Veeva CRM account assignments for the affected medical representatives and notifies the commercial ops team in Teams."
  tags:
    - crm
    - veeva
    - microsoft-teams
    - sales-ops
    - pharma
    - territory-management
capability:
  exposes:
    - type: mcp
      namespace: crm-territory
      port: 8080
      tools:
        - name: update-territory-assignment
          description: "Given a Veeva CRM territory ID and new representative ID, update all account assignments in the territory and notify the commercial operations team in Teams."
          inputParameters:
            - name: territory_id
              in: body
              type: string
              description: "The Veeva CRM territory ID being reassigned."
            - name: new_rep_id
              in: body
              type: string
              description: "The Veeva CRM user ID of the new medical representative."
            - name: effective_date
              in: body
              type: string
              description: "The effective date of the territory change in YYYY-MM-DD format."
          steps:
            - name: get-territory
              type: call
              call: "veeva-crm.get-territory"
              with:
                territory_id: "{{territory_id}}"
            - name: update-assignment
              type: call
              call: "veeva-crm.update-territory-rep"
              with:
                territory_id: "{{territory_id}}"
                rep_id: "{{new_rep_id}}"
                effectiveDate: "{{effective_date}}"
            - name: notify-commercial-ops
              type: call
              call: "msteams-crm.post-message"
              with:
                channel: "commercial-operations"
                message: "Territory {{territory_id}} ({{get-territory.name}}) reassigned to rep {{new_rep_id}} effective {{effective_date}}."
  consumes:
    - type: http
      namespace: veeva-crm
      baseUri: "https://sanofi.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.veeva_crm_token"
      resources:
        - name: territories
          path: "/sobjects/Territory2/{{territory_id}}"
          inputParameters:
            - name: territory_id
              in: path
          operations:
            - name: get-territory
              method: GET
            - name: update-territory-rep
              method: PATCH
    - type: http
      namespace: msteams-crm
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Manages promotional material review by checking document status in Veeva Vault, verifying compliance claims in Snowflake, and routing approval notifications via Teams.

naftiko: "0.5"
info:
  label: "Veeva PromoMats Review and Approval"
  description: "Manages promotional material review by checking document status in Veeva Vault, verifying compliance claims in Snowflake, and routing approval notifications via Teams."
  tags:
    - commercial
    - compliance
    - veeva
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: commercial-promomats
      port: 8080
      tools:
        - name: review-promomat
          description: "Review promotional material: check Veeva status, verify claims, and route approval."
          inputParameters:
            - name: document_id
              in: body
              type: string
              description: "The Veeva Vault promotional material document ID."
          steps:
            - name: get-promomat
              type: call
              call: "veeva-vault.get-document"
              with:
                doc_id: "{{document_id}}"
            - name: verify-claims
              type: call
              call: "snowflake.run-query"
              with:
                statement: "SELECT claim_text, approved, reference_id FROM commercial.promomat_claims WHERE document_id='{{document_id}}'"
            - name: route-approval
              type: call
              call: "msteams.post-message"
              with:
                recipient: "{{get-promomat.reviewer_email}}"
                message: "Promotional material {{document_id}} ready for review. Status: {{get-promomat.status__v}}. Claims verification complete."
  consumes:
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: documents
          path: "/objects/documents/{{doc_id}}"
          inputParameters:
            - name: doc_id
              in: path
          operations:
            - name: get-document
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST

When a clinical document is approved in Veeva Vault, retrieves its metadata and posts a Teams notification to the regulatory affairs team to initiate submission workflows.

naftiko: "0.5"
info:
  label: "Veeva Vault Clinical Document Submission"
  description: "When a clinical document is approved in Veeva Vault, retrieves its metadata and posts a Teams notification to the regulatory affairs team to initiate submission workflows."
  tags:
    - regulatory
    - veeva
    - microsoft-teams
    - clinical-operations
    - pharma
capability:
  exposes:
    - type: mcp
      namespace: regulatory-submissions
      port: 8080
      tools:
        - name: notify-document-approval
          description: "Given a Veeva Vault document ID, retrieve its approval status and metadata, then notify the regulatory affairs team in Teams to proceed with submission activities."
          inputParameters:
            - name: document_id
              in: body
              type: string
              description: "The Veeva Vault document ID that has been approved."
            - name: submission_type
              in: body
              type: string
              description: "The regulatory submission type (e.g., IND, NDA, MAA)."
          steps:
            - name: get-document
              type: call
              call: "veeva.get-document"
              with:
                doc_id: "{{document_id}}"
            - name: notify-reg-affairs
              type: call
              call: "msteams-reg.post-message"
              with:
                channel: "regulatory-affairs"
                message: "Document {{document_id}} ({{get-document.name}}) approved in Veeva. Submission type: {{submission_type}}. Please initiate filing workflow."
  consumes:
    - type: http
      namespace: veeva
      baseUri: "https://sanofi.veevavault.com/api/v21.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_token"
      resources:
        - name: documents
          path: "/objects/documents/{{doc_id}}"
          inputParameters:
            - name: doc_id
              in: path
          operations:
            - name: get-document
              method: GET
    - type: http
      namespace: msteams-reg
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Retrieves clinical trial milestone status from Veeva Vault for a given study, returning milestone completion dates, upcoming deadlines, and at-risk indicators.

naftiko: "0.5"
info:
  label: "Veeva Vault Clinical Trial Milestone Tracker"
  description: "Retrieves clinical trial milestone status from Veeva Vault for a given study, returning milestone completion dates, upcoming deadlines, and at-risk indicators."
  tags:
    - clinical-trials
    - veeva
    - regulatory
    - milestones
capability:
  exposes:
    - type: mcp
      namespace: vault-milestones
      port: 8080
      tools:
        - name: get-trial-milestones
          description: "Look up clinical trial milestone status for a study by study number in Veeva Vault."
          inputParameters:
            - name: study_number
              in: body
              type: string
              description: "The clinical study number."
          call: "veeva.get-milestones"
          with:
            study_number: "{{study_number}}"
          outputParameters:
            - name: milestones
              type: array
              mapping: "$.data"
            - name: at_risk_count
              type: number
              mapping: "$.summary.atRiskCount"
            - name: next_deadline
              type: string
              mapping: "$.summary.nextDeadline"
  consumes:
    - type: http
      namespace: veeva
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: milestones
          path: "/query?q=SELECT+milestone_name__v,+status__v,+planned_date__v,+actual_date__v+FROM+study_milestone__v+WHERE+study__vr.name__v='{{study_number}}'"
          inputParameters:
            - name: study_number
              in: query
          operations:
            - name: get-milestones
              method: GET

Retrieves the lifecycle status of a document in Veeva Vault by document ID, returning current state, owner, and last modified date.

naftiko: "0.5"
info:
  label: "Veeva Vault Document Status Lookup"
  description: "Retrieves the lifecycle status of a document in Veeva Vault by document ID, returning current state, owner, and last modified date."
  tags:
    - regulatory
    - veeva
capability:
  exposes:
    - type: mcp
      namespace: regulatory-docs
      port: 8080
      tools:
        - name: get-document-status
          description: "Look up a Veeva Vault document status by document ID. Returns lifecycle state, owner, and last modification timestamp."
          inputParameters:
            - name: document_id
              in: body
              type: string
              description: "The Veeva Vault document ID."
          call: "veeva-vault.get-document"
          with:
            doc_id: "{{document_id}}"
          outputParameters:
            - name: status
              type: string
              mapping: "$.document.status__v"
            - name: owner
              type: string
              mapping: "$.document.owner__v"
            - name: last_modified
              type: string
              mapping: "$.document.modified_date__v"
  consumes:
    - type: http
      namespace: veeva-vault
      baseUri: "https://sanofi.veevavault.com/api/v24.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_vault_token"
      resources:
        - name: documents
          path: "/objects/documents/{{doc_id}}"
          inputParameters:
            - name: doc_id
              in: path
          operations:
            - name: get-document
              method: GET

Retrieves the current regulatory submission status for a given dossier from Veeva Vault, returning lifecycle state, country, and last update date.

naftiko: "0.5"
info:
  label: "Veeva Vault Regulatory Submission Status Lookup"
  description: "Retrieves the current regulatory submission status for a given dossier from Veeva Vault, returning lifecycle state, country, and last update date."
  tags:
    - regulatory
    - veeva
    - pharma
    - compliance
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: regulatory-lookup
      port: 8080
      tools:
        - name: get-submission-status
          description: "Look up the regulatory submission status for a Veeva Vault dossier by ID. Returns lifecycle state, target country, and last modified date. Use for regulatory timeline tracking."
          inputParameters:
            - name: dossier_id
              in: body
              type: string
              description: "The Veeva Vault dossier document ID."
          call: "veeva-reg.get-submission"
          with:
            doc_id: "{{dossier_id}}"
          outputParameters:
            - name: lifecycle_state
              type: string
              mapping: "$.data[0].lifecycle_state__v"
            - name: country
              type: string
              mapping: "$.data[0].country__v"
            - name: last_modified
              type: string
              mapping: "$.data[0].modified_date__v"
  consumes:
    - type: http
      namespace: veeva-reg
      baseUri: "https://sanofi.veevavault.com/api/v21.1"
      authentication:
        type: bearer
        token: "$secrets.veeva_token"
      resources:
        - name: submissions
          path: "/objects/documents/{{doc_id}}"
          inputParameters:
            - name: doc_id
              in: path
          operations:
            - name: get-submission
              method: GET

Performs automated three-way matching of a vendor invoice against the SAP purchase order and goods receipt, then routes discrepancies to ServiceNow for resolution.

naftiko: "0.5"
info:
  label: "Vendor Invoice Three-Way Match"
  description: "Performs automated three-way matching of a vendor invoice against the SAP purchase order and goods receipt, then routes discrepancies to ServiceNow for resolution."
  tags:
    - finance
    - procurement
    - sap
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: finance-ap
      port: 8080
      tools:
        - name: three-way-match
          description: "Perform three-way match for a vendor invoice: retrieve PO, check goods receipt, compare amounts, and create a ServiceNow ticket if discrepancies exist."
          inputParameters:
            - name: invoice_number
              in: body
              type: string
              description: "The vendor invoice number."
            - name: po_number
              in: body
              type: string
              description: "The SAP purchase order number."
          steps:
            - name: get-po
              type: call
              call: "sap-po.get-po"
              with:
                po_number: "{{po_number}}"
            - name: get-receipt
              type: call
              call: "sap-gr.get-receipt"
              with:
                po_number: "{{po_number}}"
            - name: get-invoice
              type: call
              call: "sap-fi.get-invoice"
              with:
                invoice_number: "{{invoice_number}}"
            - name: create-discrepancy-ticket
              type: call
              call: "servicenow.create-incident"
              with:
                short_description: "Invoice {{invoice_number}} three-way match discrepancy for PO {{po_number}}"
                category: "finance_ap"
                assigned_group: "AP_Resolution"
  consumes:
    - type: http
      namespace: sap-po
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/MM_PUR_PO_MAINT_V2_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: purchase-orders
          path: "/A_PurchaseOrder('{{po_number}}')"
          inputParameters:
            - name: po_number
              in: path
          operations:
            - name: get-po
              method: GET
    - type: http
      namespace: sap-gr
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_MATERIAL_DOCUMENT_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: material-documents
          path: "/A_MaterialDocumentHeader"
          operations:
            - name: get-receipt
              method: GET
    - type: http
      namespace: sap-fi
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_SUPPLIERINVOICE_PROCESS_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: invoices
          path: "/A_SupplierInvoice('{{invoice_number}}')"
          inputParameters:
            - name: invoice_number
              in: path
          operations:
            - name: get-invoice
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://sanofi.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: incidents
          path: "/table/incident"
          operations:
            - name: create-incident
              method: POST

Syncs benefits enrollment data from Workday to the insurance carrier via SAP, updates tracking in Snowflake, and confirms enrollment to the employee via Teams.

naftiko: "0.5"
info:
  label: "Workday Benefits Enrollment Sync"
  description: "Syncs benefits enrollment data from Workday to the insurance carrier via SAP, updates tracking in Snowflake, and confirms enrollment to the employee via Teams."
  tags:
    - hr
    - benefits
    - workday
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: hr-benefits
      port: 8080
      tools:
        - name: sync-benefits-enrollment
          description: "Sync benefits enrollment: extract from Workday, send to carrier, update tracking, and confirm."
          inputParameters:
            - name: worker_id
              in: body
              type: string
              description: "The Workday worker ID."
            - name: plan_code
              in: body
              type: string
              description: "The benefits plan code."
          steps:
            - name: get-enrollment
              type: call
              call: "workday.get-benefits-enrollment"
              with:
                worker_id: "{{worker_id}}"
                plan: "{{plan_code}}"
            - name: send-to-carrier
              type: call
              call: "sap-hr.submit-benefits"
              with:
                employee_id: "{{get-enrollment.sapId}}"
                plan: "{{plan_code}}"
                coverage_level: "{{get-enrollment.coverageLevel}}"
            - name: update-tracking
              type: call
              call: "snowflake.run-query"
              with:
                statement: "INSERT INTO hr.benefits_enrollment_log (worker_id, plan_code, coverage_level, synced_at) VALUES ('{{worker_id}}', '{{plan_code}}', '{{get-enrollment.coverageLevel}}', CURRENT_TIMESTAMP())"
            - name: confirm-enrollment
              type: call
              call: "msteams.post-message"
              with:
                recipient: "{{get-enrollment.email}}"
                message: "Your benefits enrollment for plan {{plan_code}} has been synced successfully."
  consumes:
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: benefits
          path: "/sanofi/workers/{{worker_id}}/benefits"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-benefits-enrollment
              method: GET
    - type: http
      namespace: sap-hr
      baseUri: "https://sanofi-s4.sap.com/sap/opu/odata/sap/API_BUSINESS_PARTNER"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: benefits
          path: "/A_BusinessPartner"
          operations:
            - name: submit-benefits
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST

Retrieves base pay, bonus target, and pay grade for a Workday employee by worker ID, for total rewards inquiries.

naftiko: "0.5"
info:
  label: "Workday Compensation Detail Lookup"
  description: "Retrieves base pay, bonus target, and pay grade for a Workday employee by worker ID, for total rewards inquiries."
  tags:
    - hr
    - compensation
    - workday
capability:
  exposes:
    - type: mcp
      namespace: hr-compensation
      port: 8080
      tools:
        - name: get-compensation
          description: "Look up Workday compensation details by worker ID. Returns base pay, bonus target percentage, and pay grade."
          inputParameters:
            - name: worker_id
              in: body
              type: string
              description: "The Workday worker ID."
          call: "workday.get-compensation"
          with:
            worker_id: "{{worker_id}}"
          outputParameters:
            - name: base_pay
              type: string
              mapping: "$.compensation.basePay"
            - name: bonus_target
              type: string
              mapping: "$.compensation.bonusTarget"
            - name: pay_grade
              type: string
              mapping: "$.compensation.payGrade"
  consumes:
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: compensation
          path: "/sanofi/workers/{{worker_id}}/compensation"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-compensation
              method: GET

Retrieves an employee profile from Workday by worker ID, returning name, department, job title, and manager for HR inquiries.

naftiko: "0.5"
info:
  label: "Workday Employee Profile Lookup"
  description: "Retrieves an employee profile from Workday by worker ID, returning name, department, job title, and manager for HR inquiries."
  tags:
    - hr
    - workday
capability:
  exposes:
    - type: mcp
      namespace: hr-employee
      port: 8080
      tools:
        - name: get-employee-profile
          description: "Look up a Workday employee profile by worker ID. Returns display name, department, job title, and manager. Use for HR data inquiries."
          inputParameters:
            - name: worker_id
              in: body
              type: string
              description: "The Workday worker ID."
          call: "workday.get-worker"
          with:
            worker_id: "{{worker_id}}"
          outputParameters:
            - name: display_name
              type: string
              mapping: "$.worker.displayName"
            - name: department
              type: string
              mapping: "$.worker.department"
            - name: job_title
              type: string
              mapping: "$.worker.jobTitle"
            - name: manager
              type: string
              mapping: "$.worker.manager.displayName"
  consumes:
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: workers
          path: "/sanofi/workers/{{worker_id}}"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-worker
              method: GET

Captures a point-in-time headcount snapshot from Workday, loads it into Snowflake for trend analysis, and generates a Power BI dashboard refresh with summary posted to Teams.

naftiko: "0.5"
info:
  label: "Workday Headcount Planning Snapshot"
  description: "Captures a point-in-time headcount snapshot from Workday, loads it into Snowflake for trend analysis, and generates a Power BI dashboard refresh with summary posted to Teams."
  tags:
    - hr
    - workforce-planning
    - workday
    - snowflake
    - power-bi
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: hr-workforce-planning
      port: 8080
      tools:
        - name: capture-headcount-snapshot
          description: "Capture headcount snapshot: pull from Workday, load to Snowflake, refresh Power BI, and notify HR."
          inputParameters:
            - name: snapshot_date
              in: body
              type: string
              description: "The snapshot date in YYYY-MM-DD format."
          steps:
            - name: get-headcount
              type: call
              call: "workday.get-headcount"
              with:
                effective_date: "{{snapshot_date}}"
            - name: load-to-snowflake
              type: call
              call: "snowflake.run-query"
              with:
                statement: "INSERT INTO hr.headcount_snapshots (snapshot_date, total_headcount, captured_at) VALUES ('{{snapshot_date}}', '{{get-headcount.total}}', CURRENT_TIMESTAMP())"
            - name: refresh-dashboard
              type: call
              call: "powerbi.trigger-refresh"
              with:
                dataset_id: "$secrets.headcount_dataset_id"
            - name: notify-hr
              type: call
              call: "msteams.post-channel-message"
              with:
                team_id: "$secrets.hr_team_id"
                channel_id: "$secrets.hr_channel_id"
                body: "Headcount snapshot for {{snapshot_date}}: {{get-headcount.total}} employees. Dashboard refreshing."
  consumes:
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: headcount
          path: "/sanofi/workers"
          operations:
            - name: get-headcount
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://sanofi.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: run-query
              method: POST
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: dataset-refresh
          path: "/datasets/{{dataset_id}}/refreshes"
          inputParameters:
            - name: dataset_id
              in: path
          operations:
            - name: trigger-refresh
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Exports current active headcount by department and cost center from Workday for quarterly financial planning and workforce reporting.

naftiko: "0.5"
info:
  label: "Workday Payroll Headcount Snapshot"
  description: "Exports current active headcount by department and cost center from Workday for quarterly financial planning and workforce reporting."
  tags:
    - hr
    - finance
    - workday
    - reporting
    - headcount
capability:
  exposes:
    - type: mcp
      namespace: hr-reporting
      port: 8080
      tools:
        - name: get-headcount-snapshot
          description: "Returns active headcount grouped by department and cost center from Workday. Use for quarterly planning, budgeting, or workforce analytics."
          call: "workday-hc.get-workers"
          outputParameters:
            - name: employees
              type: array
              mapping: "$.data"
              items:
                - name: employee_id
                  type: string
                  mapping: "$.workdayId"
                - name: full_name
                  type: string
                  mapping: "$.name"
                - name: department
                  type: string
                  mapping: "$.department"
                - name: cost_center
                  type: string
                  mapping: "$.costCenter"
  consumes:
    - type: http
      namespace: workday-hc
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: workers-export
          path: "/sanofi/workers"
          operations:
            - name: get-workers
              method: GET

When an employee's role changes in Workday, updates Microsoft Entra ID group memberships and notifies IT of any elevated permissions requiring security review.

naftiko: "0.5"
info:
  label: "Workday Role Change Access Sync"
  description: "When an employee's role changes in Workday, updates Microsoft Entra ID group memberships and notifies IT of any elevated permissions requiring security review."
  tags:
    - hr
    - identity
    - workday
    - microsoft-365
    - microsoft-teams
    - access-management
    - role-change
capability:
  exposes:
    - type: mcp
      namespace: hr-access-sync
      port: 8080
      tools:
        - name: sync-role-change-access
          description: "Given a Workday employee ID and new role, update Microsoft Entra ID group memberships and notify the IT access review team in Teams."
          inputParameters:
            - name: employee_id
              in: body
              type: string
              description: "The Workday worker ID of the employee whose role changed."
            - name: new_role
              in: body
              type: string
              description: "The new job title or role name."
            - name: old_role
              in: body
              type: string
              description: "The previous job title or role name."
          steps:
            - name: get-employee
              type: call
              call: "workday-role.get-worker"
              with:
                worker_id: "{{employee_id}}"
            - name: update-groups
              type: call
              call: "msgraph-role.update-member-groups"
              with:
                userId: "{{get-employee.entraObjectId}}"
                newRole: "{{new_role}}"
            - name: notify-it
              type: call
              call: "msteams-role.post-message"
              with:
                channel: "it-access-reviews"
                message: "Role change: {{get-employee.displayName}} moved from {{old_role}} to {{new_role}}. Entra groups updated. Review if privileged access changed."
  consumes:
    - type: http
      namespace: workday-role
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: workers
          path: "/sanofi/workers/{{worker_id}}"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-worker
              method: GET
    - type: http
      namespace: msgraph-role
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: user-groups
          path: "/users/{{userId}}/memberOf"
          inputParameters:
            - name: userId
              in: path
          operations:
            - name: update-member-groups
              method: POST
    - type: http
      namespace: msteams-role
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/{{team_id}}/channels/{{channel_id}}/messages"
          inputParameters:
            - name: team_id
              in: path
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

When a time-off request is submitted in Workday, notifies the employee's manager in Microsoft Teams so they can plan coverage proactively.

naftiko: "0.5"
info:
  label: "Workday Time-Off Request Manager Notification"
  description: "When a time-off request is submitted in Workday, notifies the employee's manager in Microsoft Teams so they can plan coverage proactively."
  tags:
    - hr
    - workday
    - microsoft-teams
    - leave-management
capability:
  exposes:
    - type: mcp
      namespace: hr-leave
      port: 8080
      tools:
        - name: notify-timeoff-request
          description: "Given a Workday time-off request ID, retrieve the request details and send a notification to the manager in Teams."
          inputParameters:
            - name: request_id
              in: body
              type: string
              description: "The Workday time-off request ID."
          steps:
            - name: get-request
              type: call
              call: "workday-leave.get-timeoff-request"
              with:
                request_id: "{{request_id}}"
            - name: notify-manager
              type: call
              call: "msteams-leave.post-message"
              with:
                recipient: "{{get-request.managerEmail}}"
                message: "{{get-request.employeeName}} has submitted a time-off request from {{get-request.startDate}} to {{get-request.endDate}}. Please review in Workday."
  consumes:
    - type: http
      namespace: workday-leave
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: timeoff-requests
          path: "/sanofi/timeOffRequests/{{request_id}}"
          inputParameters:
            - name: request_id
              in: path
          operations:
            - name: get-timeoff-request
              method: GET
    - type: http
      namespace: msteams-leave
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/chats/{{chat_id}}/messages"
          inputParameters:
            - name: chat_id
              in: path
          operations:
            - name: post-message
              method: POST