L'Oréal Capabilities

Naftiko 0.5 capability definitions for L'Oréal - 107 capabilities showing integration workflows and service orchestrations.

Sort
Expand

Fetches marketing campaign attribution data from Adobe Analytics for a given campaign and date range.

naftiko: "0.5"
info:
  label: "Adobe Analytics Campaign Attribution"
  description: "Fetches marketing campaign attribution data from Adobe Analytics for a given campaign and date range."
  tags:
    - marketing
    - analytics
    - adobe-analytics
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: digital-analytics
      port: 8080
      tools:
        - name: get-campaign-attribution
          description: "Pull campaign attribution metrics from Adobe Analytics including visits, conversions, and revenue attributed to a campaign."
          inputParameters:
            - name: campaign_id
              type: string
              description: "Adobe Analytics campaign tracking code."
            - name: date_from
              type: string
              description: "Start date in YYYY-MM-DD format."
            - name: date_to
              type: string
              description: "End date in YYYY-MM-DD format."
          call: adobe.get-report
          with:
            rsid: "lorealproduction"
            campaign_id: "{{campaign_id}}"
            dateFrom: "{{date_from}}"
            dateTo: "{{date_to}}"
          outputParameters:
            - name: visits
              type: string
              mapping: "$.report.data.visits"
            - name: conversions
              type: string
              mapping: "$.report.data.conversions"
            - name: revenue
              type: string
              mapping: "$.report.data.revenue"
  consumes:
    - type: http
      namespace: adobe
      baseUri: "https://analytics.adobe.io/api/loreal"
      authentication:
        type: bearer
        token: "$secrets.adobe_analytics_token"
      resources:
        - name: reports
          path: "/reports"
          operations:
            - name: get-report
              method: POST

Uses Anthropic Claude to classify and summarize incoming customer complaints from Salesforce Service Cloud, then routes them to the appropriate ServiceNow queue.

naftiko: "0.5"
info:
  label: "AI-Assisted Customer Complaint Triage"
  description: "Uses Anthropic Claude to classify and summarize incoming customer complaints from Salesforce Service Cloud, then routes them to the appropriate ServiceNow queue."
  tags:
    - customer-support
    - ai
    - salesforce
    - servicenow
    - anthropic
capability:
  exposes:
    - type: mcp
      namespace: cx-ops
      port: 8080
      tools:
        - name: triage-customer-complaint
          description: "Given a Salesforce Service Cloud case ID, retrieve case details, use Anthropic Claude to classify severity and summarize the complaint, then create a routed ServiceNow incident with the summary."
          inputParameters:
            - name: case_id
              type: string
              description: "Salesforce Service Cloud case record ID."
          steps:
            - name: get-case
              type: call
              call: salesforce.get-case
              with:
                case_id: "{{case_id}}"
            - name: classify-complaint
              type: call
              call: anthropic.create-message
              with:
                model: "claude-3-5-sonnet-20241022"
                prompt: "Classify and summarize this customer complaint for routing: {{get-case.Description}}"
            - name: create-incident
              type: call
              call: servicenow.create-incident
              with:
                short_description: "Customer complaint: {{get-case.Subject}}"
                description: "AI summary: {{classify-complaint.content}}"
                category: "customer_complaint"
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: cases
          path: "/sobjects/Case/{{case_id}}"
          inputParameters:
            - name: case_id
              in: path
          operations:
            - name: get-case
              method: GET
    - type: http
      namespace: anthropic
      baseUri: "https://api.anthropic.com/v1"
      authentication:
        type: apikey
        key: "x-api-key"
        value: "$secrets.anthropic_api_key"
        placement: header
      resources:
        - name: messages
          path: "/messages"
          operations:
            - name: create-message
              method: POST
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.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

Checks Azure Active Directory group memberships for a user to validate access rights and role assignments.

naftiko: "0.5"
info:
  label: "Azure AD User Group Membership Check"
  description: "Checks Azure Active Directory group memberships for a user to validate access rights and role assignments."
  tags:
    - security
    - identity
    - azure-active-directory
    - access
capability:
  exposes:
    - type: mcp
      namespace: identity
      port: 8080
      tools:
        - name: check-group-membership
          description: "List Azure AD group memberships for a user. Returns group names and IDs for access validation."
          inputParameters:
            - name: user_upn
              type: string
              description: "User principal name (email) in Azure AD."
          call: azuread.get-member-of
          with:
            upn: "{{user_upn}}"
          outputParameters:
            - name: groups
              type: string
              mapping: "$.value"
  consumes:
    - type: http
      namespace: azuread
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: member-of
          path: "/users/{{upn}}/memberOf"
          inputParameters:
            - name: upn
              in: path
          operations:
            - name: get-member-of
              method: GET

Handles release approvals by checking Azure DevOps pipeline status, validating change requests in ServiceNow, and notifying the release team via Teams.

naftiko: "0.5"
info:
  label: "Azure DevOps Release Approval Handler"
  description: "Handles release approvals by checking Azure DevOps pipeline status, validating change requests in ServiceNow, and notifying the release team via Teams."
  tags:
    - operations
    - devops
    - azure-devops
    - servicenow
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: release-management
      port: 8080
      tools:
        - name: handle-release-approval
          description: "Handle a release approval by validating pipeline status, checking change management records, and notifying the team."
          inputParameters:
            - name: pipeline_id
              type: string
              description: "Azure DevOps pipeline ID."
            - name: change_request
              type: string
              description: "ServiceNow change request number."
          steps:
            - name: get-pipeline
              type: call
              call: azuredevops.get-pipeline-run
              with:
                pipeline_id: "{{pipeline_id}}"
            - name: validate-change
              type: call
              call: servicenow.get-change-request
              with:
                number: "{{change_request}}"
            - name: notify-team
              type: call
              call: msteams.send-message
              with:
                channel_id: "release-management"
                text: "Release ready: Pipeline {{pipeline_id}} ({{get-pipeline.status}}). Change {{change_request}}: {{validate-change.approval_status}}."
  consumes:
    - type: http
      namespace: azuredevops
      baseUri: "https://dev.azure.com/loreal"
      authentication:
        type: bearer
        token: "$secrets.azure_devops_token"
      resources:
        - name: pipelines
          path: "/_apis/pipelines/{{pipeline_id}}/runs"
          inputParameters:
            - name: pipeline_id
              in: path
          operations:
            - name: get-pipeline-run
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: changes
          path: "/table/change_request/{{number}}"
          inputParameters:
            - name: number
              in: path
          operations:
            - name: get-change-request
              method: GET
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Generates beauty advisor performance metrics by pulling sales data from Salesforce, attendance from Workday, and refreshing the Power BI performance dashboard.

naftiko: "0.5"
info:
  label: "Beauty Advisor Performance Dashboard"
  description: "Generates beauty advisor performance metrics by pulling sales data from Salesforce, attendance from Workday, and refreshing the Power BI performance dashboard."
  tags:
    - sales
    - hr
    - salesforce
    - workday
    - power-bi
capability:
  exposes:
    - type: mcp
      namespace: retail-performance
      port: 8080
      tools:
        - name: generate-advisor-dashboard
          description: "Generate beauty advisor performance metrics combining sales achievements with workforce data."
          inputParameters:
            - name: region
              type: string
              description: "Sales region code."
            - name: period
              type: string
              description: "Reporting period in YYYY-MM format."
          steps:
            - name: get-sales
              type: call
              call: salesforce.get-advisor-sales
              with:
                region: "{{region}}"
                period: "{{period}}"
            - name: get-attendance
              type: call
              call: workday.get-attendance
              with:
                region: "{{region}}"
                period: "{{period}}"
            - name: refresh-dashboard
              type: call
              call: powerbi.refresh-dataset
              with:
                datasetId: "beauty-advisor-performance"
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: reports
          path: "/analytics/reports"
          operations:
            - name: get-advisor-sales
              method: POST
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: attendance
          path: "/loreal/attendance"
          operations:
            - name: get-attendance
              method: GET
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: datasets
          path: "/datasets/{{datasetId}}/refreshes"
          inputParameters:
            - name: datasetId
              in: path
          operations:
            - name: refresh-dataset
              method: POST

Coordinates brand ambassador events by creating a Salesforce campaign, setting up attendee registration in Google Forms, and notifying event coordinators via Teams.

naftiko: "0.5"
info:
  label: "Brand Ambassador Event Coordinator"
  description: "Coordinates brand ambassador events by creating a Salesforce campaign, setting up attendee registration in Google Forms, and notifying event coordinators via Teams."
  tags:
    - marketing
    - events
    - salesforce
    - google-forms
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: event-management
      port: 8080
      tools:
        - name: coordinate-ambassador-event
          description: "Coordinate a brand ambassador event by setting up campaign tracking, registration, and team notification."
          inputParameters:
            - name: event_name
              type: string
              description: "Name of the event."
            - name: brand
              type: string
              description: "Brand name."
            - name: event_date
              type: string
              description: "Event date."
            - name: location
              type: string
              description: "Event location."
          steps:
            - name: create-campaign
              type: call
              call: salesforce.create-campaign
              with:
                Name: "{{event_name}}"
                Type: "Ambassador Event"
                Brand__c: "{{brand}}"
                StartDate: "{{event_date}}"
            - name: notify-coordinators
              type: call
              call: msteams.send-message
              with:
                channel_id: "brand-events"
                text: "Event created: {{event_name}} for {{brand}} on {{event_date}} at {{location}}. Campaign ID: {{create-campaign.id}}."
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: campaigns
          path: "/sobjects/Campaign"
          operations:
            - name: create-campaign
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Monitors brand sentiment via Snowflake social listening data, creates a Salesforce case for negative trends, and posts an alert to the brand management Teams channel.

naftiko: "0.5"
info:
  label: "Brand Sentiment Monitoring Responder"
  description: "Monitors brand sentiment via Snowflake social listening data, creates a Salesforce case for negative trends, and posts an alert to the brand management Teams channel."
  tags:
    - marketing
    - social
    - snowflake
    - salesforce
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: brand-monitoring
      port: 8080
      tools:
        - name: respond-to-sentiment
          description: "Monitor brand sentiment and respond to negative trends by creating a case and alerting the team."
          inputParameters:
            - name: brand_name
              type: string
              description: "Brand name to monitor."
            - name: threshold
              type: number
              description: "Negative sentiment threshold percentage."
          steps:
            - name: get-sentiment
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "SOCIAL_ANALYTICS_WH"
                query: "SELECT sentiment_score, negative_pct, volume FROM brand_sentiment WHERE brand='{{brand_name}}' AND date=CURRENT_DATE()"
            - name: create-case
              type: call
              call: salesforce.create-case
              with:
                Subject: "Negative sentiment alert: {{brand_name}}"
                Description: "Negative sentiment at {{get-sentiment.negative_pct}}% (threshold: {{threshold}}%). Volume: {{get-sentiment.volume}} mentions."
                Priority: "High"
            - name: alert-team
              type: call
              call: msteams.send-message
              with:
                channel_id: "brand-management"
                text: "SENTIMENT ALERT: {{brand_name}} negative sentiment at {{get-sentiment.negative_pct}}%. Case: {{create-case.CaseNumber}}."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: cases
          path: "/sobjects/Case"
          operations:
            - name: create-case
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

On a GitHub Actions pipeline failure on a protected branch, creates a Jira bug, posts a Datadog event marker, and alerts the engineering Teams channel.

naftiko: "0.5"
info:
  label: "CI/CD Pipeline Failure Response"
  description: "On a GitHub Actions pipeline failure on a protected branch, creates a Jira bug, posts a Datadog event marker, and alerts the engineering Teams channel."
  tags:
    - devops
    - cicd
    - github
    - jira
    - datadog
capability:
  exposes:
    - type: mcp
      namespace: devops
      port: 8080
      tools:
        - name: handle-pipeline-failure
          description: "Given a GitHub Actions pipeline failure event, create a Jira bug in the engineering project, post a Datadog deployment event, and alert the engineering Teams channel with full context."
          inputParameters:
            - name: repo
              type: string
              description: "GitHub repository full name (org/repo)."
            - name: branch
              type: string
              description: "Branch name where the failure occurred."
            - name: workflow_run_id
              type: string
              description: "GitHub Actions workflow run ID."
            - name: commit_sha
              type: string
              description: "Git commit SHA that triggered the pipeline."
          steps:
            - name: create-bug
              type: call
              call: jira.create-issue
              with:
                project_key: "ENG"
                issuetype: "Bug"
                summary: "[CI Failure] {{repo}} / {{branch}}"
                description: "Workflow run {{workflow_run_id}} failed on commit {{commit_sha}}"
            - name: post-event
              type: call
              call: datadog.create-event
              with:
                title: "CI failure: {{repo}}"
                text: "Branch {{branch}} pipeline failed. Jira: {{create-bug.key}}"
                alert_type: "error"
            - name: alert-team
              type: call
              call: msteams.post-channel-message
              with:
                channel_id: "engineering-alerts"
                text: "Pipeline failure: {{repo}} | Branch: {{branch}} | Jira: {{create-bug.key}} | Run: {{workflow_run_id}}"
  consumes:
    - type: http
      namespace: jira
      baseUri: "https://loreal.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: datadog
      baseUri: "https://api.datadoghq.com/api/v1"
      authentication:
        type: apikey
        key: "DD-API-KEY"
        value: "$secrets.datadog_api_key"
        placement: header
      resources:
        - name: events
          path: "/events"
          operations:
            - name: create-event
              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/engineering/channels/{{channel_id}}/messages"
          inputParameters:
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Orchestrates clinical trial data collection by pulling trial metadata from Jira, collecting results from Snowflake, and storing the summary report in SharePoint.

naftiko: "0.5"
info:
  label: "Clinical Trial Data Collection Orchestrator"
  description: "Orchestrates clinical trial data collection by pulling trial metadata from Jira, collecting results from Snowflake, and storing the summary report in SharePoint."
  tags:
    - r-and-d
    - quality
    - jira
    - snowflake
    - sharepoint
capability:
  exposes:
    - type: mcp
      namespace: clinical-trials
      port: 8080
      tools:
        - name: collect-trial-data
          description: "Collect and organize clinical trial data from multiple sources into a structured report."
          inputParameters:
            - name: trial_id
              type: string
              description: "Clinical trial identifier."
            - name: phase
              type: string
              description: "Trial phase (e.g., Phase I, Phase II)."
          steps:
            - name: get-trial-metadata
              type: call
              call: jira.get-issue
              with:
                issue_key: "{{trial_id}}"
            - name: get-trial-results
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "RD_ANALYTICS_WH"
                query: "SELECT subject_count, adverse_events, efficacy_score FROM clinical_results WHERE trial_id='{{trial_id}}' AND phase='{{phase}}'"
            - name: store-report
              type: call
              call: sharepoint.upload-file
              with:
                site: "rd-clinical-trials"
                folder: "{{trial_id}}"
                filename: "{{trial_id}}-{{phase}}-results.json"
                content: "{{get-trial-results.data}}"
  consumes:
    - type: http
      namespace: jira
      baseUri: "https://loreal.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
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: files
          path: "/sites/{{site}}/drive/root:/{{folder}}/{{filename}}:/content"
          inputParameters:
            - name: site
              in: path
            - name: folder
              in: path
            - name: filename
              in: path
          operations:
            - name: upload-file
              method: PUT

Queries AWS Cost Explorer for spend anomalies exceeding a threshold and creates a Jira task and a Datadog event to track remediation.

naftiko: "0.5"
info:
  label: "Cloud Cost Anomaly Detection"
  description: "Queries AWS Cost Explorer for spend anomalies exceeding a threshold and creates a Jira task and a Datadog event to track remediation."
  tags:
    - cloud
    - finops
    - aws
    - datadog
    - jira
capability:
  exposes:
    - type: mcp
      namespace: cloud-finops
      port: 8080
      tools:
        - name: handle-cost-anomaly
          description: "Given an AWS account ID and spend threshold, query Cost Explorer for anomalies, create a Jira tracking ticket, and post a Datadog event. Use when automated cost alerts fire."
          inputParameters:
            - name: account_id
              type: string
              description: "AWS account ID to check for spend anomalies."
            - name: threshold_usd
              type: number
              description: "Anomaly threshold in USD. Anomalies above this value are reported."
            - name: date_from
              type: string
              description: "Start date for the cost lookback period in YYYY-MM-DD format."
          steps:
            - name: get-anomalies
              type: call
              call: aws-cost.get-anomalies
              with:
                accountId: "{{account_id}}"
                threshold: "{{threshold_usd}}"
                startDate: "{{date_from}}"
            - name: create-task
              type: call
              call: jira.create-issue
              with:
                project_key: "CLOUD"
                issuetype: "Task"
                summary: "Cost anomaly detected on AWS account {{account_id}}"
                description: "Anomaly details: {{get-anomalies.summary}}"
            - name: post-event
              type: call
              call: datadog.create-event
              with:
                title: "AWS cost anomaly: {{account_id}}"
                text: "Threshold {{threshold_usd}} USD exceeded. Jira: {{create-task.key}}"
                alert_type: "warning"
  consumes:
    - type: http
      namespace: aws-cost
      baseUri: "https://ce.us-east-1.amazonaws.com"
      authentication:
        type: bearer
        token: "$secrets.aws_cost_explorer_token"
      resources:
        - name: anomalies
          path: "/GetAnomalies"
          operations:
            - name: get-anomalies
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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: datadog
      baseUri: "https://api.datadoghq.com/api/v1"
      authentication:
        type: apikey
        key: "DD-API-KEY"
        value: "$secrets.datadog_api_key"
        placement: header
      resources:
        - name: events
          path: "/events"
          operations:
            - name: create-event
              method: POST

Compiles competitive intelligence by querying Circana market data from Snowflake, pulling brand share trends, and distributing a digest via Teams and Salesforce.

naftiko: "0.5"
info:
  label: "Competitive Market Intelligence Digest"
  description: "Compiles competitive intelligence by querying Circana market data from Snowflake, pulling brand share trends, and distributing a digest via Teams and Salesforce."
  tags:
    - marketing
    - analytics
    - snowflake
    - microsoft-teams
    - salesforce
capability:
  exposes:
    - type: mcp
      namespace: market-intelligence
      port: 8080
      tools:
        - name: generate-competitive-digest
          description: "Generate a competitive market intelligence digest by combining market share data with brand performance and distributing to stakeholders."
          inputParameters:
            - name: category
              type: string
              description: "Product category (e.g., skincare, haircare)."
            - name: period
              type: string
              description: "Reporting period in YYYY-MM format."
          steps:
            - name: get-market-data
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "MARKET_ANALYTICS_WH"
                query: "SELECT brand, market_share_pct, share_change_pct FROM circana_market_data WHERE category='{{category}}' AND period='{{period}}' ORDER BY market_share_pct DESC"
            - name: update-sf-report
              type: call
              call: salesforce.update-market-report
              with:
                category: "{{category}}"
                period: "{{period}}"
                data: "{{get-market-data.data}}"
            - name: post-digest
              type: call
              call: msteams.send-message
              with:
                channel_id: "market-intelligence"
                text: "Market Intelligence Digest - {{category}} ({{period}}): Top brand share {{get-market-data.top_brand}} at {{get-market-data.top_share}}%."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: reports
          path: "/sobjects/Market_Report__c"
          operations:
            - name: update-market-report
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Aggregates consumer product reviews from Snowflake, identifies trending complaints, and creates Jira tasks for product teams while posting a summary to Teams.

naftiko: "0.5"
info:
  label: "Consumer Review Analysis Pipeline"
  description: "Aggregates consumer product reviews from Snowflake, identifies trending complaints, and creates Jira tasks for product teams while posting a summary to Teams."
  tags:
    - marketing
    - quality
    - snowflake
    - jira
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: consumer-insights
      port: 8080
      tools:
        - name: analyze-consumer-reviews
          description: "Analyze consumer reviews to identify trending complaints and route actionable items to product teams."
          inputParameters:
            - name: product_line
              type: string
              description: "Product line to analyze."
            - name: period_days
              type: number
              description: "Number of days to look back."
          steps:
            - name: get-reviews
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "CONSUMER_ANALYTICS_WH"
                query: "SELECT complaint_topic, count, avg_rating FROM review_analysis WHERE product_line='{{product_line}}' AND review_date >= DATEADD(day, -{{period_days}}, CURRENT_DATE()) ORDER BY count DESC LIMIT 10"
            - name: create-product-tasks
              type: call
              call: jira.create-issue
              with:
                project_key: "PROD"
                issuetype: "Task"
                summary: "Consumer review trends: {{product_line}} (last {{period_days}} days)"
                description: "Top complaint topics: {{get-reviews.data}}. Average rating: {{get-reviews.avg_rating}}."
            - name: post-summary
              type: call
              call: msteams.send-message
              with:
                channel_id: "product-insights"
                text: "Review analysis for {{product_line}}: Top issues identified. Jira: {{create-product-tasks.key}}."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Initiates a quality audit for a contract manufacturer by pulling supplier data from SAP Ariba, creating a Jira audit task, and sharing the audit checklist via SharePoint.

naftiko: "0.5"
info:
  label: "Contract Manufacturer Quality Audit Workflow"
  description: "Initiates a quality audit for a contract manufacturer by pulling supplier data from SAP Ariba, creating a Jira audit task, and sharing the audit checklist via SharePoint."
  tags:
    - quality
    - procurement
    - sap
    - jira
    - sharepoint
capability:
  exposes:
    - type: mcp
      namespace: quality-audit
      port: 8080
      tools:
        - name: initiate-cm-audit
          description: "Start a contract manufacturer quality audit by gathering supplier data, creating an audit task, and sharing the checklist."
          inputParameters:
            - name: supplier_id
              type: string
              description: "SAP Ariba supplier ID."
            - name: audit_type
              type: string
              description: "Type of audit: routine, for-cause, pre-approval."
          steps:
            - name: get-supplier
              type: call
              call: ariba.get-supplier
              with:
                supplier_id: "{{supplier_id}}"
            - name: create-audit-task
              type: call
              call: jira.create-issue
              with:
                project_key: "QAUDIT"
                issuetype: "Task"
                summary: "CM Quality Audit: {{get-supplier.name}} ({{audit_type}})"
                description: "Audit type: {{audit_type}}. Supplier: {{get-supplier.name}}. Location: {{get-supplier.address}}."
            - name: share-checklist
              type: call
              call: sharepoint.copy-template
              with:
                template: "quality-audit-checklist-{{audit_type}}"
                destination: "audits/{{supplier_id}}"
                name: "audit-{{supplier_id}}-checklist"
  consumes:
    - type: http
      namespace: ariba
      baseUri: "https://openapi.ariba.com/api/supplier-management/v1"
      authentication:
        type: bearer
        token: "$secrets.ariba_token"
      resources:
        - name: suppliers
          path: "/suppliers/{{supplier_id}}"
          inputParameters:
            - name: supplier_id
              in: path
          operations:
            - name: get-supplier
              method: GET
    - type: http
      namespace: jira
      baseUri: "https://loreal.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: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: files
          path: "/sites/quality/drive/items"
          operations:
            - name: copy-template
              method: POST

Tracks regulatory submission status by querying Jira for submission tasks, checking document completeness in SharePoint, and updating the compliance dashboard in Power BI.

naftiko: "0.5"
info:
  label: "Cosmetics Regulatory Submission Tracker"
  description: "Tracks regulatory submission status by querying Jira for submission tasks, checking document completeness in SharePoint, and updating the compliance dashboard in Power BI."
  tags:
    - regulatory
    - quality
    - jira
    - sharepoint
    - power-bi
capability:
  exposes:
    - type: mcp
      namespace: regulatory-ops
      port: 8080
      tools:
        - name: track-regulatory-submission
          description: "Track the status of a cosmetics regulatory submission across project management, document storage, and reporting systems."
          inputParameters:
            - name: submission_id
              type: string
              description: "Jira issue key for the regulatory submission."
          steps:
            - name: get-submission-status
              type: call
              call: jira.get-issue
              with:
                issue_key: "{{submission_id}}"
            - name: check-documents
              type: call
              call: sharepoint.list-folder
              with:
                site: "regulatory-submissions"
                folder: "{{submission_id}}"
            - name: refresh-dashboard
              type: call
              call: powerbi.refresh-dataset
              with:
                datasetId: "regulatory-compliance-tracker"
  consumes:
    - type: http
      namespace: jira
      baseUri: "https://loreal.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
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: folders
          path: "/sites/{{site}}/drive/root:/{{folder}}:/children"
          inputParameters:
            - name: site
              in: path
            - name: folder
              in: path
          operations:
            - name: list-folder
              method: GET
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: datasets
          path: "/datasets/{{datasetId}}/refreshes"
          inputParameters:
            - name: datasetId
              in: path
          operations:
            - name: refresh-dataset
              method: POST

Routes a customer complaint from Zendesk to a quality investigation by looking up the product batch in SAP, creating a Jira investigation ticket, and updating the Zendesk ticket.

naftiko: "0.5"
info:
  label: "Customer Complaint to Quality Investigation"
  description: "Routes a customer complaint from Zendesk to a quality investigation by looking up the product batch in SAP, creating a Jira investigation ticket, and updating the Zendesk ticket."
  tags:
    - quality
    - customer-service
    - zendesk
    - sap
    - jira
capability:
  exposes:
    - type: mcp
      namespace: complaint-quality
      port: 8080
      tools:
        - name: route-complaint-to-quality
          description: "Route a customer complaint to the quality team by tracing the product batch and creating an investigation ticket."
          inputParameters:
            - name: ticket_id
              type: string
              description: "Zendesk complaint ticket ID."
            - name: batch_number
              type: string
              description: "Product batch number from the complaint."
            - name: material_number
              type: string
              description: "Product material number."
          steps:
            - name: get-ticket
              type: call
              call: zendesk.get-ticket
              with:
                ticket_id: "{{ticket_id}}"
            - name: trace-batch
              type: call
              call: sap.get-batch
              with:
                batch: "{{batch_number}}"
                material: "{{material_number}}"
            - name: create-investigation
              type: call
              call: jira.create-issue
              with:
                project_key: "QUAL"
                issuetype: "Bug"
                summary: "Customer complaint investigation: batch {{batch_number}}"
                description: "Complaint: {{get-ticket.subject}}. Batch produced at {{trace-batch.plant}} on {{trace-batch.production_date}}."
            - name: update-ticket
              type: call
              call: zendesk.update-ticket
              with:
                ticket_id: "{{ticket_id}}"
                comment: "Quality investigation opened: {{create-investigation.key}}. Our quality team is reviewing batch {{batch_number}}."
  consumes:
    - type: http
      namespace: zendesk
      baseUri: "https://loreal.zendesk.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.zendesk_token"
      resources:
        - name: tickets
          path: "/tickets/{{ticket_id}}"
          inputParameters:
            - name: ticket_id
              in: path
          operations:
            - name: get-ticket
              method: GET
            - name: update-ticket
              method: PUT
    - type: http
      namespace: sap
      baseUri: "https://loreal-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: "/A_Batch"
          operations:
            - name: get-batch
              method: GET
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

Queries Datadog APM for application latency percentiles over a time window for a specified service.

naftiko: "0.5"
info:
  label: "Datadog Application Latency Report"
  description: "Queries Datadog APM for application latency percentiles over a time window for a specified service."
  tags:
    - operations
    - monitoring
    - datadog
    - performance
capability:
  exposes:
    - type: mcp
      namespace: observability
      port: 8080
      tools:
        - name: get-latency-report
          description: "Fetch p50, p95, and p99 latency metrics from Datadog APM for a given service over a specified time range."
          inputParameters:
            - name: service_name
              type: string
              description: "Datadog APM service name."
            - name: time_from
              type: string
              description: "Start timestamp in epoch seconds."
            - name: time_to
              type: string
              description: "End timestamp in epoch seconds."
          call: datadog.query-timeseries
          with:
            query: "avg:trace.servlet.request.duration{service:{{service_name}}}"
            from: "{{time_from}}"
            to: "{{time_to}}"
          outputParameters:
            - name: p50_ms
              type: string
              mapping: "$.series[0].pointlist[0][1]"
            - name: p95_ms
              type: string
              mapping: "$.series[1].pointlist[0][1]"
            - name: p99_ms
              type: string
              mapping: "$.series[2].pointlist[0][1]"
  consumes:
    - type: http
      namespace: datadog
      baseUri: "https://api.datadoghq.com/api/v1"
      authentication:
        type: apikey
        key: "DD-API-KEY"
        value: "$secrets.datadog_api_key"
        placement: header
      resources:
        - name: query
          path: "/query"
          operations:
            - name: query-timeseries
              method: GET

When a Datadog monitor fires a critical alert, creates a ServiceNow incident, assigns an on-call engineer via PagerDuty, and notifies the ops Teams channel.

naftiko: "0.5"
info:
  label: "Datadog Infrastructure Alert Response"
  description: "When a Datadog monitor fires a critical alert, creates a ServiceNow incident, assigns an on-call engineer via PagerDuty, and notifies the ops Teams channel."
  tags:
    - itsm
    - observability
    - datadog
    - servicenow
    - pagerduty
capability:
  exposes:
    - type: mcp
      namespace: infra-ops
      port: 8080
      tools:
        - name: handle-infrastructure-alert
          description: "Given a Datadog monitor alert ID and severity, create a ServiceNow incident, trigger a PagerDuty incident to page on-call, and post context to the ops Teams channel."
          inputParameters:
            - name: monitor_id
              type: string
              description: "Datadog monitor ID that triggered the alert."
            - name: severity
              type: string
              description: "Alert severity: critical, warning, or info."
            - name: affected_service
              type: string
              description: "Name of the affected service or host."
          steps:
            - name: get-monitor
              type: call
              call: datadog.get-monitor
              with:
                monitor_id: "{{monitor_id}}"
            - name: create-incident
              type: call
              call: servicenow.create-incident
              with:
                short_description: "Infrastructure alert: {{affected_service}} — {{severity}}"
                urgency: "1"
                impact: "1"
                description: "Datadog monitor {{monitor_id}}: {{get-monitor.message}}"
            - name: page-oncall
              type: call
              call: pagerduty.create-incident
              with:
                title: "Infrastructure alert: {{affected_service}}"
                service_id: "$secrets.pagerduty_infra_service_id"
                body: "ServiceNow: {{create-incident.number}} | Monitor: {{monitor_id}}"
  consumes:
    - type: http
      namespace: datadog
      baseUri: "https://api.datadoghq.com/api/v1"
      authentication:
        type: apikey
        key: "DD-API-KEY"
        value: "$secrets.datadog_api_key"
        placement: header
      resources:
        - name: monitors
          path: "/monitor/{{monitor_id}}"
          inputParameters:
            - name: monitor_id
              in: path
          operations:
            - name: get-monitor
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.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: pagerduty
      baseUri: "https://api.pagerduty.com"
      authentication:
        type: apikey
        key: "Authorization"
        value: "$secrets.pagerduty_token"
        placement: header
      resources:
        - name: incidents
          path: "/incidents"
          operations:
            - name: create-incident
              method: POST

Fetches SLO compliance data from Datadog for all production services and publishes a weekly compliance report to SharePoint and the engineering Teams channel.

naftiko: "0.5"
info:
  label: "Datadog SLO Compliance Report"
  description: "Fetches SLO compliance data from Datadog for all production services and publishes a weekly compliance report to SharePoint and the engineering Teams channel."
  tags:
    - observability
    - slo
    - datadog
    - reporting
    - sharepoint
capability:
  exposes:
    - type: mcp
      namespace: slo-reporting
      port: 8080
      tools:
        - name: publish-slo-report
          description: "Fetch weekly SLO compliance metrics for all production services from Datadog and upload the formatted report to SharePoint, then post a summary to the engineering Teams channel."
          inputParameters:
            - name: teams_channel_id
              type: string
              description: "Teams channel ID for the engineering team."
            - name: sharepoint_site_id
              type: string
              description: "SharePoint site ID to upload the report to."
          steps:
            - name: get-slos
              type: call
              call: datadog.list-slos
              with:
                tags: "env:production"
            - name: upload-report
              type: call
              call: sharepoint.upload-file
              with:
                site_id: "{{sharepoint_site_id}}"
                folder_path: "SLOReports/weekly"
                content: "{{get-slos.data}}"
            - name: post-summary
              type: call
              call: msteams.post-channel-message
              with:
                channel_id: "{{teams_channel_id}}"
                text: "Weekly SLO report published: {{get-slos.complianceCount}} services meeting targets. Report: {{upload-report.sharepoint_url}}"
  consumes:
    - type: http
      namespace: datadog
      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"
          inputParameters:
            - name: tags
              in: query
          operations:
            - name: list-slos
              method: GET
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: files
          path: "/sites/{{site_id}}/drive/items/root:/{{folder_path}}:/children"
          inputParameters:
            - name: site_id
              in: path
            - name: folder_path
              in: path
          operations:
            - name: upload-file
              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/engineering/channels/{{channel_id}}/messages"
          inputParameters:
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Pulls demand forecast data from Snowflake, checks current inventory in SAP, and creates or adjusts planned production orders to meet projected demand.

naftiko: "0.5"
info:
  label: "Demand Forecast to Production Planning Sync"
  description: "Pulls demand forecast data from Snowflake, checks current inventory in SAP, and creates or adjusts planned production orders to meet projected demand."
  tags:
    - supply-chain
    - manufacturing
    - snowflake
    - sap
    - planning
capability:
  exposes:
    - type: mcp
      namespace: demand-planning
      port: 8080
      tools:
        - name: sync-demand-to-production
          description: "Synchronize demand forecasts with production planning by querying forecast data, checking inventory, and creating planned orders in SAP."
          inputParameters:
            - name: product_category
              type: string
              description: "Product category for demand forecast."
            - name: planning_horizon_weeks
              type: number
              description: "Number of weeks for the planning horizon."
            - name: plant_code
              type: string
              description: "SAP plant code."
          steps:
            - name: get-forecast
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "DEMAND_PLANNING_WH"
                query: "SELECT sku, forecasted_units FROM demand_forecast WHERE category='{{product_category}}' AND weeks_ahead<={{planning_horizon_weeks}}"
            - name: check-inventory
              type: call
              call: sap.get-plant-stock
              with:
                plant: "{{plant_code}}"
                category: "{{product_category}}"
            - name: create-planned-orders
              type: call
              call: sap.create-planned-order
              with:
                plant: "{{plant_code}}"
                forecast_data: "{{get-forecast.data}}"
                current_stock: "{{check-inventory.stock_levels}}"
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: sap
      baseUri: "https://loreal-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-plant-stock
              method: GET
        - name: planned-orders
          path: "/A_PlannedOrder"
          operations:
            - name: create-planned-order
              method: POST

Monitors product pricing across e-commerce channels by querying Snowflake pricing data, comparing against MAP policy, and creating Salesforce cases for violations.

naftiko: "0.5"
info:
  label: "Digital Shelf Price Monitor"
  description: "Monitors product pricing across e-commerce channels by querying Snowflake pricing data, comparing against MAP policy, and creating Salesforce cases for violations."
  tags:
    - ecommerce
    - sales
    - snowflake
    - salesforce
    - pricing
capability:
  exposes:
    - type: mcp
      namespace: pricing-ops
      port: 8080
      tools:
        - name: monitor-digital-pricing
          description: "Monitor digital shelf pricing for MAP violations by comparing current prices against policy and flagging violations."
          inputParameters:
            - name: brand
              type: string
              description: "Brand name to monitor."
            - name: marketplace
              type: string
              description: "E-commerce marketplace (e.g., amazon, walmart)."
          steps:
            - name: get-prices
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "ECOM_ANALYTICS_WH"
                query: "SELECT sku, current_price, map_price, retailer FROM digital_shelf_prices WHERE brand='{{brand}}' AND marketplace='{{marketplace}}' AND current_price < map_price"
            - name: create-violation-cases
              type: call
              call: salesforce.create-case
              with:
                Subject: "MAP violation: {{brand}} on {{marketplace}}"
                Description: "{{get-prices.violation_count}} SKUs priced below MAP on {{marketplace}}."
                Priority: "High"
                Type: "MAP Violation"
            - name: notify-team
              type: call
              call: msteams.send-message
              with:
                channel_id: "pricing-compliance"
                text: "MAP Alert: {{get-prices.violation_count}} violations for {{brand}} on {{marketplace}}. Case: {{create-violation-cases.CaseNumber}}."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: cases
          path: "/sobjects/Case"
          operations:
            - name: create-case
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Processes DTC product returns by updating the Salesforce case, creating a return goods receipt in SAP, and issuing a refund notification via email.

naftiko: "0.5"
info:
  label: "Direct-to-Consumer Returns Processing"
  description: "Processes DTC product returns by updating the Salesforce case, creating a return goods receipt in SAP, and issuing a refund notification via email."
  tags:
    - ecommerce
    - supply-chain
    - salesforce
    - sap
    - customer-service
capability:
  exposes:
    - type: mcp
      namespace: dtc-returns
      port: 8080
      tools:
        - name: process-dtc-return
          description: "Process a direct-to-consumer product return across CRM, ERP, and customer notification systems."
          inputParameters:
            - name: case_id
              type: string
              description: "Salesforce case ID for the return."
            - name: order_number
              type: string
              description: "Original SAP sales order number."
            - name: reason
              type: string
              description: "Return reason code."
          steps:
            - name: update-case
              type: call
              call: salesforce.update-case
              with:
                case_id: "{{case_id}}"
                Status: "In Progress"
                Return_Reason__c: "{{reason}}"
            - name: create-return-order
              type: call
              call: sap.create-return-order
              with:
                reference_order: "{{order_number}}"
                reason: "{{reason}}"
            - name: send-notification
              type: call
              call: msgraph.send-mail
              with:
                to: "{{update-case.contact_email}}"
                subject: "Return processed: {{order_number}}"
                body: "Your return has been processed. Return reference: {{create-return-order.return_number}}. Refund will be issued within 5-7 business days."
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: cases
          path: "/sobjects/Case/{{case_id}}"
          inputParameters:
            - name: case_id
              in: path
          operations:
            - name: update-case
              method: PATCH
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_RETURNS_DELIVERY_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: returns
          path: "/A_ReturnsDeliveryHeader"
          operations:
            - name: create-return-order
              method: POST
    - type: http
      namespace: msgraph
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: mail
          path: "/me/sendMail"
          operations:
            - name: send-mail
              method: POST

Tracks e-commerce order fulfillment by querying Salesforce for order status, checking SAP warehouse picking status, and updating the customer via Zendesk.

naftiko: "0.5"
info:
  label: "E-commerce Order Fulfillment Tracker"
  description: "Tracks e-commerce order fulfillment by querying Salesforce for order status, checking SAP warehouse picking status, and updating the customer via Zendesk."
  tags:
    - ecommerce
    - supply-chain
    - salesforce
    - sap
    - zendesk
capability:
  exposes:
    - type: mcp
      namespace: ecom-fulfillment
      port: 8080
      tools:
        - name: track-fulfillment
          description: "Track an e-commerce order through fulfillment by checking CRM status, warehouse picking, and updating the customer ticket."
          inputParameters:
            - name: order_id
              type: string
              description: "Salesforce order ID."
            - name: ticket_id
              type: string
              description: "Zendesk ticket ID for customer inquiry."
          steps:
            - name: get-order
              type: call
              call: salesforce.get-order
              with:
                order_id: "{{order_id}}"
            - name: check-picking
              type: call
              call: sap.get-delivery-status
              with:
                sales_order: "{{get-order.sap_order_number}}"
            - name: update-ticket
              type: call
              call: zendesk.update-ticket
              with:
                ticket_id: "{{ticket_id}}"
                comment: "Order {{order_id}} status: {{get-order.status}}. Warehouse picking: {{check-picking.picking_status}}. Estimated ship: {{check-picking.ship_date}}."
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: orders
          path: "/sobjects/Order/{{order_id}}"
          inputParameters:
            - name: order_id
              in: path
          operations:
            - name: get-order
              method: GET
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_OUTBOUND_DELIVERY_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: deliveries
          path: "/A_OutbDeliveryHeader"
          operations:
            - name: get-delivery-status
              method: GET
    - type: http
      namespace: zendesk
      baseUri: "https://loreal.zendesk.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.zendesk_token"
      resources:
        - name: tickets
          path: "/tickets/{{ticket_id}}"
          inputParameters:
            - name: ticket_id
              in: path
          operations:
            - name: update-ticket
              method: PUT

Generates a personalized learning path by pulling employee skills from Workday, matching with available courses in Pluralsight, and creating a development plan in Jira.

naftiko: "0.5"
info:
  label: "Employee Learning Path Generator"
  description: "Generates a personalized learning path by pulling employee skills from Workday, matching with available courses in Pluralsight, and creating a development plan in Jira."
  tags:
    - hr
    - training
    - workday
    - pluralsight
    - jira
capability:
  exposes:
    - type: mcp
      namespace: hr-learning
      port: 8080
      tools:
        - name: generate-learning-path
          description: "Create a personalized learning path by assessing current skills and matching with available training courses."
          inputParameters:
            - name: employee_id
              type: string
              description: "Workday employee ID."
            - name: target_role
              type: string
              description: "Target role for development."
          steps:
            - name: get-skills
              type: call
              call: workday.get-worker-skills
              with:
                worker_id: "{{employee_id}}"
            - name: find-courses
              type: call
              call: pluralsight.search-courses
              with:
                role: "{{target_role}}"
                exclude_skills: "{{get-skills.current_skills}}"
            - name: create-plan
              type: call
              call: jira.create-issue
              with:
                project_key: "LEARN"
                issuetype: "Task"
                summary: "Learning path: {{target_role}} for employee {{employee_id}}"
                description: "Recommended courses: {{find-courses.course_list}}. Skill gaps: {{find-courses.gap_count}}."
  consumes:
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: skills
          path: "/loreal/workers/{{worker_id}}/skills"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-worker-skills
              method: GET
    - type: http
      namespace: pluralsight
      baseUri: "https://api.pluralsight.com/api/v1"
      authentication:
        type: bearer
        token: "$secrets.pluralsight_token"
      resources:
        - name: courses
          path: "/courses/search"
          operations:
            - name: search-courses
              method: GET
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

When an employee separation is recorded in Workday, revokes Okta access, closes open ServiceNow tickets, and notifies the manager via Teams.

naftiko: "0.5"
info:
  label: "Employee Offboarding Workflow"
  description: "When an employee separation is recorded in Workday, revokes Okta access, closes open ServiceNow tickets, and notifies the manager via Teams."
  tags:
    - hr
    - offboarding
    - workday
    - okta
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: hr-offboarding
      port: 8080
      tools:
        - name: trigger-offboarding
          description: "Given a Workday employee ID, revoke Okta SSO access, deactivate Microsoft 365 account, close open ServiceNow tickets, and notify the manager via Teams."
          inputParameters:
            - name: employee_id
              type: string
              description: "Workday worker ID of the departing employee."
            - name: last_day
              type: string
              description: "Last working day in YYYY-MM-DD format."
          steps:
            - name: get-worker
              type: call
              call: workday.get-worker
              with:
                worker_id: "{{employee_id}}"
            - name: deactivate-okta
              type: call
              call: okta.deactivate-user
              with:
                user_id: "{{get-worker.work_email}}"
            - name: disable-m365
              type: call
              call: msgraph.update-user
              with:
                user_id: "{{get-worker.work_email}}"
                accountEnabled: "false"
            - name: notify-manager
              type: call
              call: msteams.send-message
              with:
                recipient_upn: "{{get-worker.manager_email}}"
                text: "Offboarding complete for {{get-worker.full_name}} (last day: {{last_day}}). All system access has been revoked."
  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: "/loreal/workers/{{worker_id}}"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-worker
              method: GET
    - type: http
      namespace: okta
      baseUri: "https://loreal.okta.com/api/v1"
      authentication:
        type: apikey
        key: "Authorization"
        value: "$secrets.okta_api_token"
        placement: header
      resources:
        - name: users
          path: "/users/{{user_id}}/lifecycle/deactivate"
          inputParameters:
            - name: user_id
              in: path
          operations:
            - name: deactivate-user
              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/{{user_id}}"
          inputParameters:
            - name: user_id
              in: path
          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: chats
          path: "/chats"
          operations:
            - name: send-message
              method: POST

Syncs Facebook lead gen ad form submissions to Salesforce leads, enriches with ZoomInfo data, and notifies the sales team via Teams.

naftiko: "0.5"
info:
  label: "Facebook Ad to Salesforce Lead Sync"
  description: "Syncs Facebook lead gen ad form submissions to Salesforce leads, enriches with ZoomInfo data, and notifies the sales team via Teams."
  tags:
    - marketing
    - sales
    - facebook
    - salesforce
    - zoominfo
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: lead-management
      port: 8080
      tools:
        - name: sync-fb-leads
          description: "Sync Facebook lead ad submissions to Salesforce with enrichment and team notification."
          inputParameters:
            - name: form_id
              type: string
              description: "Facebook lead form ID."
            - name: campaign_id
              type: string
              description: "Salesforce campaign ID for attribution."
          steps:
            - name: get-leads
              type: call
              call: facebook.get-lead-forms
              with:
                form_id: "{{form_id}}"
            - name: enrich-leads
              type: call
              call: zoominfo.enrich-contact
              with:
                email: "{{get-leads.email}}"
            - name: create-sf-lead
              type: call
              call: salesforce.create-lead
              with:
                Email: "{{get-leads.email}}"
                FirstName: "{{get-leads.first_name}}"
                LastName: "{{get-leads.last_name}}"
                Company: "{{enrich-leads.company}}"
                Title: "{{enrich-leads.title}}"
                CampaignId: "{{campaign_id}}"
            - name: notify-sales
              type: call
              call: msteams.send-message
              with:
                channel_id: "sales-leads"
                text: "New lead from Facebook: {{get-leads.first_name}} {{get-leads.last_name}} at {{enrich-leads.company}}. SF Lead: {{create-sf-lead.id}}."
  consumes:
    - type: http
      namespace: facebook
      baseUri: "https://graph.facebook.com/v18.0"
      authentication:
        type: bearer
        token: "$secrets.meta_token"
      resources:
        - name: leads
          path: "/{{form_id}}/leads"
          inputParameters:
            - name: form_id
              in: path
          operations:
            - name: get-lead-forms
              method: GET
    - type: http
      namespace: zoominfo
      baseUri: "https://api.zoominfo.com/enrich"
      authentication:
        type: bearer
        token: "$secrets.zoominfo_token"
      resources:
        - name: contacts
          path: "/contact"
          operations:
            - name: enrich-contact
              method: POST
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: leads
          path: "/sobjects/Lead"
          operations:
            - name: create-lead
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Tracks fragrance stability testing by pulling test schedules from Jira, querying lab results from Snowflake, and storing completed reports in SharePoint.

naftiko: "0.5"
info:
  label: "Fragrance Stability Test Tracker"
  description: "Tracks fragrance stability testing by pulling test schedules from Jira, querying lab results from Snowflake, and storing completed reports in SharePoint."
  tags:
    - r-and-d
    - quality
    - jira
    - snowflake
    - sharepoint
capability:
  exposes:
    - type: mcp
      namespace: rd-stability
      port: 8080
      tools:
        - name: track-stability-test
          description: "Track fragrance stability tests by correlating schedules with lab results and archiving reports."
          inputParameters:
            - name: test_id
              type: string
              description: "Jira stability test ticket key."
          steps:
            - name: get-schedule
              type: call
              call: jira.get-issue
              with:
                issue_key: "{{test_id}}"
            - name: get-results
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "RD_ANALYTICS_WH"
                query: "SELECT test_point, color_delta, odor_score, viscosity FROM stability_results WHERE test_id='{{test_id}}' ORDER BY test_point"
            - name: archive-report
              type: call
              call: sharepoint.upload-file
              with:
                site: "rd-stability"
                folder: "completed-tests"
                filename: "{{test_id}}-stability-report.json"
  consumes:
    - type: http
      namespace: jira
      baseUri: "https://loreal.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
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: files
          path: "/sites/rd-stability/drive/root:/{{folder}}/{{filename}}:/content"
          operations:
            - name: upload-file
              method: PUT

When a GitHub release is published, generates AI-assisted release notes using Anthropic Claude and posts them to the engineering Teams channel and Confluence.

naftiko: "0.5"
info:
  label: "GitHub Deployment Release Notes"
  description: "When a GitHub release is published, generates AI-assisted release notes using Anthropic Claude and posts them to the engineering Teams channel and Confluence."
  tags:
    - devops
    - github
    - anthropic
    - confluence
    - release-management
capability:
  exposes:
    - type: mcp
      namespace: release-ops
      port: 8080
      tools:
        - name: publish-release-notes
          description: "Given a GitHub release tag and repository, fetch the commit log, generate polished release notes using Anthropic Claude, and publish to Confluence and the engineering Teams channel."
          inputParameters:
            - name: repo_owner
              type: string
              description: "GitHub organization or owner name."
            - name: repo_name
              type: string
              description: "GitHub repository name."
            - name: tag
              type: string
              description: "Release tag name (e.g., v1.4.0)."
            - name: teams_channel_id
              type: string
              description: "Teams channel ID for engineering announcements."
          steps:
            - name: get-release
              type: call
              call: github.get-release
              with:
                owner: "{{repo_owner}}"
                repo: "{{repo_name}}"
                tag: "{{tag}}"
            - name: generate-notes
              type: call
              call: anthropic.create-message
              with:
                model: "claude-3-5-sonnet-20241022"
                prompt: "Generate professional release notes from these commits: {{get-release.body}}"
            - name: publish-to-confluence
              type: call
              call: confluence.create-page
              with:
                space_key: "ENG"
                title: "Release Notes {{tag}} — {{repo_name}}"
                content: "{{generate-notes.content}}"
            - name: notify-team
              type: call
              call: msteams.post-channel-message
              with:
                channel_id: "{{teams_channel_id}}"
                text: "Release {{tag}} published for {{repo_name}}. Confluence: {{publish-to-confluence.url}}"
  consumes:
    - type: http
      namespace: github
      baseUri: "https://api.github.com"
      authentication:
        type: bearer
        token: "$secrets.github_token"
      resources:
        - name: releases
          path: "/repos/{{owner}}/{{repo}}/releases/tags/{{tag}}"
          inputParameters:
            - name: owner
              in: path
            - name: repo
              in: path
            - name: tag
              in: path
          operations:
            - name: get-release
              method: GET
    - type: http
      namespace: anthropic
      baseUri: "https://api.anthropic.com/v1"
      authentication:
        type: apikey
        key: "x-api-key"
        value: "$secrets.anthropic_api_key"
        placement: header
      resources:
        - name: messages
          path: "/messages"
          operations:
            - name: create-message
              method: POST
    - type: http
      namespace: confluence
      baseUri: "https://loreal.atlassian.net/wiki/rest/api"
      authentication:
        type: basic
        username: "$secrets.jira_user"
        password: "$secrets.jira_api_token"
      resources:
        - name: pages
          path: "/content"
          operations:
            - name: create-page
              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/engineering/channels/{{channel_id}}/messages"
          inputParameters:
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Triggers a GitHub Advanced Security scan on a repository, checks Dependabot alerts, and creates Jira issues for critical vulnerabilities.

naftiko: "0.5"
info:
  label: "GitHub Repository Security Scan"
  description: "Triggers a GitHub Advanced Security scan on a repository, checks Dependabot alerts, and creates Jira issues for critical vulnerabilities."
  tags:
    - security
    - devops
    - github
    - jira
    - vulnerability-management
capability:
  exposes:
    - type: mcp
      namespace: security-ops
      port: 8080
      tools:
        - name: scan-repo-vulnerabilities
          description: "Given a GitHub repository, retrieve critical Dependabot and code scanning alerts, then create Jira security issues for each critical finding. Use during security review cycles or on-demand."
          inputParameters:
            - name: repo_owner
              type: string
              description: "GitHub organization or owner name."
            - name: repo_name
              type: string
              description: "GitHub repository name."
          steps:
            - name: get-dependabot-alerts
              type: call
              call: github.list-dependabot-alerts
              with:
                owner: "{{repo_owner}}"
                repo: "{{repo_name}}"
                severity: "critical"
            - name: create-security-issue
              type: call
              call: jira.create-issue
              with:
                project_key: "SEC"
                issuetype: "Bug"
                summary: "Critical vulnerability in {{repo_owner}}/{{repo_name}}"
                description: "Dependabot alerts: {{get-dependabot-alerts.count}} critical findings. Repo: {{repo_owner}}/{{repo_name}}"
  consumes:
    - type: http
      namespace: github
      baseUri: "https://api.github.com"
      authentication:
        type: bearer
        token: "$secrets.github_token"
      resources:
        - name: dependabot-alerts
          path: "/repos/{{owner}}/{{repo}}/dependabot/alerts"
          inputParameters:
            - name: owner
              in: path
            - name: repo
              in: path
            - name: severity
              in: query
          operations:
            - name: list-dependabot-alerts
              method: GET
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

Retrieves e-commerce conversion funnel metrics from Google Analytics for a specific brand property.

naftiko: "0.5"
info:
  label: "Google Analytics E-commerce Funnel Report"
  description: "Retrieves e-commerce conversion funnel metrics from Google Analytics for a specific brand property."
  tags:
    - marketing
    - analytics
    - google-analytics
    - ecommerce
capability:
  exposes:
    - type: mcp
      namespace: web-analytics
      port: 8080
      tools:
        - name: get-ecommerce-funnel
          description: "Fetch e-commerce funnel data from Google Analytics including sessions, add-to-cart rate, checkout rate, and purchase conversion rate."
          inputParameters:
            - name: property_id
              type: string
              description: "Google Analytics 4 property ID."
            - name: date_from
              type: string
              description: "Start date in YYYY-MM-DD format."
            - name: date_to
              type: string
              description: "End date in YYYY-MM-DD format."
          call: ga.run-report
          with:
            property: "{{property_id}}"
            dateRanges_startDate: "{{date_from}}"
            dateRanges_endDate: "{{date_to}}"
          outputParameters:
            - name: sessions
              type: string
              mapping: "$.rows[0].metricValues[0].value"
            - name: add_to_cart_rate
              type: string
              mapping: "$.rows[0].metricValues[1].value"
            - name: purchase_rate
              type: string
              mapping: "$.rows[0].metricValues[2].value"
  consumes:
    - type: http
      namespace: ga
      baseUri: "https://analyticsdata.googleapis.com/v1beta"
      authentication:
        type: bearer
        token: "$secrets.google_analytics_token"
      resources:
        - name: reports
          path: "/properties/{{property}}/runReport"
          inputParameters:
            - name: property
              in: path
          operations:
            - name: run-report
              method: POST

Retrieves the current live container version from Google Tag Manager for a brand website property.

naftiko: "0.5"
info:
  label: "Google Tag Manager Container Version Lookup"
  description: "Retrieves the current live container version from Google Tag Manager for a brand website property."
  tags:
    - marketing
    - analytics
    - google-tag-manager
    - web
capability:
  exposes:
    - type: mcp
      namespace: tag-management
      port: 8080
      tools:
        - name: get-container-version
          description: "Fetch the current live GTM container version including tag count, trigger count, and publish date."
          inputParameters:
            - name: account_id
              type: string
              description: "GTM account ID."
            - name: container_id
              type: string
              description: "GTM container ID."
          call: gtm.get-live-version
          with:
            accountId: "{{account_id}}"
            containerId: "{{container_id}}"
          outputParameters:
            - name: version_id
              type: string
              mapping: "$.containerVersionId"
            - name: tag_count
              type: string
              mapping: "$.tag.length"
            - name: publish_date
              type: string
              mapping: "$.fingerprint"
  consumes:
    - type: http
      namespace: gtm
      baseUri: "https://www.googleapis.com/tagmanager/v2"
      authentication:
        type: bearer
        token: "$secrets.google_gtm_token"
      resources:
        - name: versions
          path: "/accounts/{{accountId}}/containers/{{containerId}}/versions/live"
          inputParameters:
            - name: accountId
              in: path
            - name: containerId
              in: path
          operations:
            - name: get-live-version
              method: GET

Pulls influencer campaign spend from Salesforce, engagement data from Instagram, and sales lift from Snowflake to calculate ROI and post results to Teams.

naftiko: "0.5"
info:
  label: "Influencer Campaign ROI Analyzer"
  description: "Pulls influencer campaign spend from Salesforce, engagement data from Instagram, and sales lift from Snowflake to calculate ROI and post results to Teams."
  tags:
    - marketing
    - social
    - salesforce
    - instagram
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: influencer-analytics
      port: 8080
      tools:
        - name: analyze-influencer-roi
          description: "Calculate influencer campaign ROI by combining spend data, engagement metrics, and sales lift, then post the summary to Teams."
          inputParameters:
            - name: campaign_id
              type: string
              description: "Salesforce campaign ID for the influencer program."
            - name: ig_account_id
              type: string
              description: "Instagram business account ID."
            - name: date_from
              type: string
              description: "Start date in YYYY-MM-DD format."
            - name: date_to
              type: string
              description: "End date in YYYY-MM-DD format."
          steps:
            - name: get-spend
              type: call
              call: salesforce.get-campaign
              with:
                campaign_id: "{{campaign_id}}"
            - name: get-engagement
              type: call
              call: instagram.get-insights
              with:
                ig_user_id: "{{ig_account_id}}"
                since: "{{date_from}}"
                until: "{{date_to}}"
            - name: get-sales-lift
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "MARKETING_ANALYTICS_WH"
                query: "SELECT sales_lift_pct FROM influencer_attribution WHERE campaign_id='{{campaign_id}}'"
            - name: post-results
              type: call
              call: msteams.send-message
              with:
                channel_id: "influencer-marketing"
                text: "Influencer ROI for {{campaign_id}}: Spend ${{get-spend.actual_cost}}, Engagement {{get-engagement.total_interactions}}, Sales lift {{get-sales-lift.sales_lift_pct}}%."
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: campaigns
          path: "/sobjects/Campaign/{{campaign_id}}"
          inputParameters:
            - name: campaign_id
              in: path
          operations:
            - name: get-campaign
              method: GET
    - type: http
      namespace: instagram
      baseUri: "https://graph.facebook.com/v18.0"
      authentication:
        type: bearer
        token: "$secrets.meta_token"
      resources:
        - name: insights
          path: "/{{ig_user_id}}/insights"
          inputParameters:
            - name: ig_user_id
              in: path
          operations:
            - name: get-insights
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-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: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Assesses ingredient safety by pulling INCI data from SharePoint, checking regulatory status in Snowflake, and creating a Jira review ticket for the toxicology team.

naftiko: "0.5"
info:
  label: "Ingredient Safety Assessment Workflow"
  description: "Assesses ingredient safety by pulling INCI data from SharePoint, checking regulatory status in Snowflake, and creating a Jira review ticket for the toxicology team."
  tags:
    - r-and-d
    - quality
    - regulatory
    - sharepoint
    - snowflake
    - jira
capability:
  exposes:
    - type: mcp
      namespace: ingredient-safety
      port: 8080
      tools:
        - name: assess-ingredient-safety
          description: "Conduct an ingredient safety assessment by gathering INCI data, checking regulatory status, and routing for toxicology review."
          inputParameters:
            - name: ingredient_name
              type: string
              description: "INCI ingredient name."
            - name: concentration_pct
              type: number
              description: "Proposed concentration percentage."
          steps:
            - name: get-inci-docs
              type: call
              call: sharepoint.search-docs
              with:
                query: "{{ingredient_name}} safety INCI"
                site: "rd-safety"
            - name: check-regulatory
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "REGULATORY_WH"
                query: "SELECT status, max_concentration, restricted_markets FROM ingredient_regulatory WHERE inci_name='{{ingredient_name}}'"
            - name: create-review
              type: call
              call: jira.create-issue
              with:
                project_key: "SAFETY"
                issuetype: "Task"
                summary: "Ingredient safety review: {{ingredient_name}} at {{concentration_pct}}%"
                description: "Regulatory status: {{check-regulatory.status}}. Max allowed: {{check-regulatory.max_concentration}}%. Documents found: {{get-inci-docs.count}}."
  consumes:
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: search
          path: "/sites/rd-safety/drive/root/search"
          operations:
            - name: search-docs
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

Fetches engagement metrics for a brand Instagram account over a date range including likes, comments, and follower growth.

naftiko: "0.5"
info:
  label: "Instagram Brand Engagement Lookup"
  description: "Fetches engagement metrics for a brand Instagram account over a date range including likes, comments, and follower growth."
  tags:
    - marketing
    - social
    - instagram
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: social-analytics
      port: 8080
      tools:
        - name: get-instagram-engagement
          description: "Retrieve Instagram engagement metrics for a brand account including total likes, comments, shares, and follower delta."
          inputParameters:
            - name: account_id
              type: string
              description: "Instagram business account ID."
            - name: date_from
              type: string
              description: "Start date in YYYY-MM-DD format."
            - name: date_to
              type: string
              description: "End date in YYYY-MM-DD format."
          call: instagram.get-insights
          with:
            ig_user_id: "{{account_id}}"
            since: "{{date_from}}"
            until: "{{date_to}}"
          outputParameters:
            - name: total_likes
              type: string
              mapping: "$.data[0].values[0].value"
            - name: total_comments
              type: string
              mapping: "$.data[1].values[0].value"
            - name: follower_count
              type: string
              mapping: "$.data[2].values[0].value"
  consumes:
    - type: http
      namespace: instagram
      baseUri: "https://graph.facebook.com/v18.0"
      authentication:
        type: bearer
        token: "$secrets.meta_token"
      resources:
        - name: insights
          path: "/{{ig_user_id}}/insights"
          inputParameters:
            - name: ig_user_id
              in: path
            - name: since
              in: query
            - name: until
              in: query
          operations:
            - name: get-insights
              method: GET

Submits a vendor invoice to SAP Ariba for three-way match validation, creates an approval task in ServiceNow, and notifies the approver via Teams.

naftiko: "0.5"
info:
  label: "Invoice Processing and Approval"
  description: "Submits a vendor invoice to SAP Ariba for three-way match validation, creates an approval task in ServiceNow, and notifies the approver via Teams."
  tags:
    - finance
    - procurement
    - sap-ariba
    - servicenow
    - approval
capability:
  exposes:
    - type: mcp
      namespace: finance-ops
      port: 8080
      tools:
        - name: process-invoice
          description: "Given a vendor invoice number and amount, submit it to SAP Ariba for three-way match, create a ServiceNow approval task, and notify the finance approver via Teams."
          inputParameters:
            - name: invoice_number
              type: string
              description: "Vendor invoice number."
            - name: vendor_id
              type: string
              description: "SAP vendor ID."
            - name: amount
              type: number
              description: "Invoice total amount."
            - name: approver_upn
              type: string
              description: "UPN (email) of the finance approver in Microsoft 365."
          steps:
            - name: submit-invoice
              type: call
              call: sap-ariba.create-invoice
              with:
                invoiceNumber: "{{invoice_number}}"
                vendorId: "{{vendor_id}}"
                totalAmount: "{{amount}}"
            - name: create-approval-task
              type: call
              call: servicenow.create-task
              with:
                short_description: "Invoice approval required: {{invoice_number}}"
                assigned_to: "{{approver_upn}}"
                description: "Ariba invoice ID: {{submit-invoice.invoiceId}}"
            - name: notify-approver
              type: call
              call: msteams.send-message
              with:
                recipient_upn: "{{approver_upn}}"
                text: "Invoice {{invoice_number}} for {{amount}} requires your approval. ServiceNow task: {{create-approval-task.number}}"
  consumes:
    - type: http
      namespace: sap-ariba
      baseUri: "https://openapi.ariba.com/api/invoice/v1"
      authentication:
        type: bearer
        token: "$secrets.ariba_token"
      resources:
        - name: invoices
          path: "/invoices"
          operations:
            - name: create-invoice
              method: POST
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: tasks
          path: "/table/sc_task"
          operations:
            - name: create-task
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: chats
          path: "/chats"
          operations:
            - name: send-message
              method: POST

Searches Jira for open quality defect issues in a project and returns defect counts by priority.

naftiko: "0.5"
info:
  label: "Jira Quality Defect Lookup"
  description: "Searches Jira for open quality defect issues in a project and returns defect counts by priority."
  tags:
    - quality
    - project-management
    - jira
    - defects
capability:
  exposes:
    - type: mcp
      namespace: quality-tracking
      port: 8080
      tools:
        - name: get-quality-defects
          description: "Search Jira for open quality defects in a project. Returns issue count grouped by priority."
          inputParameters:
            - name: project_key
              type: string
              description: "Jira project key for the quality project."
          call: jira.search-issues
          with:
            jql: "project={{project_key}} AND type=Bug AND status!=Done"
          outputParameters:
            - name: total
              type: string
              mapping: "$.total"
            - name: issues
              type: string
              mapping: "$.issues"
  consumes:
    - type: http
      namespace: jira
      baseUri: "https://loreal.atlassian.net/rest/api/3"
      authentication:
        type: basic
        username: "$secrets.jira_user"
        password: "$secrets.jira_api_token"
      resources:
        - name: search
          path: "/search"
          operations:
            - name: search-issues
              method: POST

Aggregates completed story points from the last Jira sprint and posts a velocity digest to the engineering Teams channel.

naftiko: "0.5"
info:
  label: "Jira Sprint Velocity Digest"
  description: "Aggregates completed story points from the last Jira sprint and posts a velocity digest to the engineering Teams channel."
  tags:
    - devops
    - project-management
    - jira
    - microsoft-teams
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: agile-reporting
      port: 8080
      tools:
        - name: digest-sprint-velocity
          description: "Given a Jira board ID and sprint ID, fetch completed issues and story points, then post a velocity summary to the engineering Teams channel."
          inputParameters:
            - name: board_id
              type: string
              description: "Jira board ID."
            - name: sprint_id
              type: string
              description: "Jira sprint ID to summarize."
            - name: teams_channel_id
              type: string
              description: "Teams channel ID for the engineering team."
          steps:
            - name: get-sprint-issues
              type: call
              call: jira.get-sprint-issues
              with:
                boardId: "{{board_id}}"
                sprintId: "{{sprint_id}}"
            - name: post-digest
              type: call
              call: msteams.post-channel-message
              with:
                channel_id: "{{teams_channel_id}}"
                text: "Sprint {{sprint_id}} complete — {{get-sprint-issues.totalPoints}} story points delivered across {{get-sprint-issues.issueCount}} issues."
  consumes:
    - type: http
      namespace: jira
      baseUri: "https://loreal.atlassian.net/rest/api/3"
      authentication:
        type: basic
        username: "$secrets.jira_user"
        password: "$secrets.jira_api_token"
      resources:
        - name: sprint-issues
          path: "/board/{{boardId}}/sprint/{{sprintId}}/issue"
          inputParameters:
            - name: boardId
              in: path
            - name: sprintId
              in: path
          operations:
            - name: get-sprint-issues
              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/engineering/channels/{{channel_id}}/messages"
          inputParameters:
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Publishes a sponsored content post to a L'Oréal LinkedIn brand page and records the post ID in Salesforce for attribution tracking.

naftiko: "0.5"
info:
  label: "LinkedIn Brand Campaign Publisher"
  description: "Publishes a sponsored content post to a L'Oréal LinkedIn brand page and records the post ID in Salesforce for attribution tracking."
  tags:
    - marketing
    - social
    - linkedin
    - salesforce
    - content
capability:
  exposes:
    - type: mcp
      namespace: social-publishing
      port: 8080
      tools:
        - name: publish-linkedin-post
          description: "Given post copy, image URL, and a Salesforce campaign ID, publish a LinkedIn sponsored content post on the brand page and log the post ID back to the Salesforce campaign record."
          inputParameters:
            - name: org_urn
              type: string
              description: "LinkedIn organization URN for the brand page."
            - name: post_text
              type: string
              description: "Post copy text to publish."
            - name: image_url
              type: string
              description: "URL of the image asset to attach."
            - name: campaign_id
              type: string
              description: "Salesforce campaign record ID for attribution."
          steps:
            - name: publish-post
              type: call
              call: linkedin.create-post
              with:
                author: "{{org_urn}}"
                commentary: "{{post_text}}"
                content_url: "{{image_url}}"
            - name: update-campaign
              type: call
              call: salesforce.update-campaign
              with:
                campaign_id: "{{campaign_id}}"
                LinkedIn_Post_ID__c: "{{publish-post.id}}"
  consumes:
    - type: http
      namespace: linkedin
      baseUri: "https://api.linkedin.com/v2"
      authentication:
        type: bearer
        token: "$secrets.linkedin_token"
      resources:
        - name: posts
          path: "/posts"
          operations:
            - name: create-post
              method: POST
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: campaigns
          path: "/sobjects/Campaign/{{campaign_id}}"
          inputParameters:
            - name: campaign_id
              in: path
          operations:
            - name: update-campaign
              method: PATCH

Enriches the talent pipeline by pulling open requisitions from Workday, matching with LinkedIn talent pool data, and creating sourcing tasks in Jira.

naftiko: "0.5"
info:
  label: "LinkedIn Talent Pipeline Enrichment"
  description: "Enriches the talent pipeline by pulling open requisitions from Workday, matching with LinkedIn talent pool data, and creating sourcing tasks in Jira."
  tags:
    - hr
    - recruiting
    - workday
    - linkedin
    - jira
capability:
  exposes:
    - type: mcp
      namespace: talent-acquisition
      port: 8080
      tools:
        - name: enrich-talent-pipeline
          description: "Enrich the talent pipeline by matching open positions with LinkedIn talent data and creating sourcing tasks."
          inputParameters:
            - name: department
              type: string
              description: "Department for open requisitions."
          steps:
            - name: get-requisitions
              type: call
              call: workday.get-open-positions
              with:
                department: "{{department}}"
            - name: search-talent
              type: call
              call: linkedin.search-candidates
              with:
                skills: "{{get-requisitions.required_skills}}"
                location: "{{get-requisitions.location}}"
            - name: create-sourcing-tasks
              type: call
              call: jira.create-issue
              with:
                project_key: "RECRUIT"
                issuetype: "Task"
                summary: "Talent sourcing: {{department}} ({{get-requisitions.count}} open roles)"
                description: "LinkedIn talent pool: {{search-talent.candidate_count}} matches. Top skills in demand: {{get-requisitions.top_skills}}."
  consumes:
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: positions
          path: "/loreal/jobRequisitions"
          operations:
            - name: get-open-positions
              method: GET
    - type: http
      namespace: linkedin
      baseUri: "https://api.linkedin.com/v2"
      authentication:
        type: bearer
        token: "$secrets.linkedin_token"
      resources:
        - name: talent
          path: "/talentPool"
          operations:
            - name: search-candidates
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

When a manufacturing line goes down, creates a ServiceNow incident, updates the production order status in SAP, and alerts the plant operations team via Teams.

naftiko: "0.5"
info:
  label: "Manufacturing Downtime Incident Handler"
  description: "When a manufacturing line goes down, creates a ServiceNow incident, updates the production order status in SAP, and alerts the plant operations team via Teams."
  tags:
    - manufacturing
    - operations
    - servicenow
    - sap
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: mfg-ops
      port: 8080
      tools:
        - name: handle-downtime
          description: "Orchestrate the response to a manufacturing line downtime event by creating an incident, updating SAP, and notifying operations."
          inputParameters:
            - name: production_line
              type: string
              description: "Manufacturing production line identifier."
            - name: plant_code
              type: string
              description: "SAP plant code."
            - name: reason
              type: string
              description: "Reason for downtime."
          steps:
            - name: create-incident
              type: call
              call: servicenow.create-incident
              with:
                short_description: "Line down: {{production_line}} at plant {{plant_code}}"
                category: "manufacturing"
                urgency: "1"
                description: "Production line {{production_line}} is down. Reason: {{reason}}."
            - name: update-sap-order
              type: call
              call: sap.update-production-status
              with:
                plant: "{{plant_code}}"
                line: "{{production_line}}"
                status: "INTERRUPTED"
            - name: alert-ops
              type: call
              call: msteams.send-message
              with:
                channel_id: "plant-operations"
                text: "LINE DOWN: {{production_line}} at {{plant_code}}. Reason: {{reason}}. Incident: {{create-incident.number}}."
  consumes:
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.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: sap
      baseUri: "https://loreal-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"
          operations:
            - name: update-production-status
              method: PATCH
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Coordinates a marketing campaign launch by creating a Salesforce campaign, scheduling Meta Ads, and notifying the marketing team via Teams.

naftiko: "0.5"
info:
  label: "Marketing Campaign Launch Coordinator"
  description: "Coordinates a marketing campaign launch by creating a Salesforce campaign, scheduling Meta Ads, and notifying the marketing team via Teams."
  tags:
    - marketing
    - campaigns
    - salesforce
    - meta
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: campaign-ops
      port: 8080
      tools:
        - name: launch-campaign
          description: "Orchestrate a marketing campaign launch by creating the Salesforce campaign record, activating Meta ad sets, and sending a Teams notification."
          inputParameters:
            - name: campaign_name
              type: string
              description: "Name of the marketing campaign."
            - name: brand
              type: string
              description: "Brand name (e.g., Lancôme, Maybelline)."
            - name: start_date
              type: string
              description: "Campaign start date in YYYY-MM-DD format."
            - name: budget_usd
              type: number
              description: "Total campaign budget in USD."
          steps:
            - name: create-sf-campaign
              type: call
              call: salesforce.create-campaign
              with:
                Name: "{{campaign_name}}"
                Brand__c: "{{brand}}"
                StartDate: "{{start_date}}"
                BudgetedCost: "{{budget_usd}}"
                Status: "Planned"
            - name: activate-meta-ads
              type: call
              call: meta.update-campaign-status
              with:
                campaign_name: "{{campaign_name}}"
                status: "ACTIVE"
            - name: notify-team
              type: call
              call: msteams.send-message
              with:
                channel_id: "marketing-launches"
                text: "Campaign '{{campaign_name}}' for {{brand}} launched. SF ID: {{create-sf-campaign.id}}. Budget: ${{budget_usd}}. Start: {{start_date}}."
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: campaigns
          path: "/sobjects/Campaign"
          operations:
            - name: create-campaign
              method: POST
    - type: http
      namespace: meta
      baseUri: "https://graph.facebook.com/v18.0"
      authentication:
        type: bearer
        token: "$secrets.meta_token"
      resources:
        - name: campaigns
          path: "/campaigns"
          operations:
            - name: update-campaign-status
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Aggregates campaign performance metrics from Salesforce Marketing Cloud and publishes a daily digest to a Microsoft Teams channel.

naftiko: "0.5"
info:
  label: "Marketing Campaign Performance Digest"
  description: "Aggregates campaign performance metrics from Salesforce Marketing Cloud and publishes a daily digest to a Microsoft Teams channel."
  tags:
    - marketing
    - reporting
    - salesforce
    - microsoft-teams
    - digest
capability:
  exposes:
    - type: mcp
      namespace: marketing-reporting
      port: 8080
      tools:
        - name: digest-campaign-performance
          description: "Fetch top campaign performance metrics from Salesforce Marketing Cloud for a given date range and post a formatted summary to the marketing Teams channel."
          inputParameters:
            - name: date_from
              type: string
              description: "Start date for the reporting period in YYYY-MM-DD format."
            - name: date_to
              type: string
              description: "End date for the reporting period in YYYY-MM-DD format."
            - name: teams_channel_id
              type: string
              description: "Microsoft Teams channel ID to post the digest to."
          steps:
            - name: get-campaigns
              type: call
              call: sfmc.list-campaigns
              with:
                dateFrom: "{{date_from}}"
                dateTo: "{{date_to}}"
            - name: post-digest
              type: call
              call: msteams.post-channel-message
              with:
                channel_id: "{{teams_channel_id}}"
                text: "Marketing Campaign Digest ({{date_from}} to {{date_to}}): {{get-campaigns.summary}}"
  consumes:
    - type: http
      namespace: sfmc
      baseUri: "https://api.salesforce.com/marketing/v1"
      authentication:
        type: bearer
        token: "$secrets.sfmc_token"
      resources:
        - name: campaigns
          path: "/campaigns"
          inputParameters:
            - name: dateFrom
              in: query
            - name: dateTo
              in: query
          operations:
            - name: list-campaigns
              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

Generates a media mix optimization report by pulling spend data from Meta and Google Ads via Snowflake, correlating with sales, and refreshing the Power BI dashboard.

naftiko: "0.5"
info:
  label: "Media Mix Optimization Report Generator"
  description: "Generates a media mix optimization report by pulling spend data from Meta and Google Ads via Snowflake, correlating with sales, and refreshing the Power BI dashboard."
  tags:
    - marketing
    - analytics
    - snowflake
    - power-bi
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: media-planning
      port: 8080
      tools:
        - name: generate-media-mix-report
          description: "Generate a media mix optimization report combining multi-channel spend with sales outcomes."
          inputParameters:
            - name: brand
              type: string
              description: "Brand name."
            - name: date_from
              type: string
              description: "Start date."
            - name: date_to
              type: string
              description: "End date."
          steps:
            - name: get-media-data
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "MARKETING_ANALYTICS_WH"
                query: "SELECT channel, spend, impressions, conversions, roas FROM media_mix WHERE brand='{{brand}}' AND date BETWEEN '{{date_from}}' AND '{{date_to}}' GROUP BY channel"
            - name: refresh-dashboard
              type: call
              call: powerbi.refresh-dataset
              with:
                datasetId: "media-mix-optimization"
            - name: post-summary
              type: call
              call: msteams.send-message
              with:
                channel_id: "media-planning"
                text: "Media mix report ready for {{brand}} ({{date_from}} to {{date_to}}). Best ROAS channel: {{get-media-data.top_channel}}."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: datasets
          path: "/datasets/{{datasetId}}/refreshes"
          inputParameters:
            - name: datasetId
              in: path
          operations:
            - name: refresh-dataset
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Retrieves ad campaign performance metrics from Meta Ads Manager for a given campaign and date range.

naftiko: "0.5"
info:
  label: "Meta Ad Campaign Performance Lookup"
  description: "Retrieves ad campaign performance metrics from Meta Ads Manager for a given campaign and date range."
  tags:
    - marketing
    - social
    - meta
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: meta-ads
      port: 8080
      tools:
        - name: get-campaign-insights
          description: "Fetch Meta Ads campaign insights including impressions, reach, clicks, and spend for a given campaign ID and date range. Use for paid social performance reviews."
          inputParameters:
            - name: campaign_id
              type: string
              description: "Meta Ads campaign ID."
            - name: date_from
              type: string
              description: "Start date in YYYY-MM-DD format."
            - name: date_to
              type: string
              description: "End date in YYYY-MM-DD format."
          call: meta.get-campaign-insights
          with:
            campaign_id: "{{campaign_id}}"
            date_preset: "custom"
            time_range_since: "{{date_from}}"
            time_range_until: "{{date_to}}"
          outputParameters:
            - name: impressions
              type: string
              mapping: "$.data[0].impressions"
            - name: reach
              type: string
              mapping: "$.data[0].reach"
            - name: clicks
              type: string
              mapping: "$.data[0].clicks"
            - name: spend
              type: string
              mapping: "$.data[0].spend"
  consumes:
    - type: http
      namespace: meta
      baseUri: "https://graph.facebook.com/v18.0"
      authentication:
        type: bearer
        token: "$secrets.meta_token"
      resources:
        - name: campaign-insights
          path: "/{{campaign_id}}/insights"
          inputParameters:
            - name: campaign_id
              in: path
            - name: date_preset
              in: query
            - name: time_range_since
              in: query
            - name: time_range_until
              in: query
          operations:
            - name: get-campaign-insights
              method: GET

When a new hire is created in Workday, opens a ServiceNow onboarding ticket, provisions a Microsoft 365 account, and sends a Teams welcome message.

naftiko: "0.5"
info:
  label: "New Hire Onboarding Orchestrator"
  description: "When a new hire is created in Workday, opens a ServiceNow onboarding ticket, provisions a Microsoft 365 account, and sends a Teams welcome message."
  tags:
    - hr
    - onboarding
    - workday
    - servicenow
    - microsoft-teams
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 across ServiceNow ticketing, Microsoft Graph account provisioning, and Teams welcome notification."
          inputParameters:
            - name: employee_id
              type: string
              description: "Workday worker ID for the new hire."
            - name: start_date
              type: string
              description: "Employee start date in YYYY-MM-DD format."
            - name: department
              type: string
              description: "Department name for the new hire, used to assign the correct onboarding group."
          steps:
            - name: get-worker
              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-worker.full_name}}"
                category: "hr_onboarding"
                assignment_group: "IT_Onboarding"
            - name: provision-account
              type: call
              call: msgraph.create-user
              with:
                displayName: "{{get-worker.full_name}}"
                mail: "{{get-worker.work_email}}"
                department: "{{department}}"
            - name: send-welcome
              type: call
              call: msteams.send-message
              with:
                recipient_upn: "{{get-worker.work_email}}"
                text: "Welcome to L'Oréal, {{get-worker.first_name}}! Your onboarding 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: "/loreal/workers/{{worker_id}}"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-worker
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.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: chats
          path: "/chats"
          operations:
            - name: send-message
              method: POST

Coordinates a new market launch by creating Jira epic with subtasks, setting up Salesforce territory records, and notifying the regional team via Teams.

naftiko: "0.5"
info:
  label: "New Market Launch Checklist Coordinator"
  description: "Coordinates a new market launch by creating Jira epic with subtasks, setting up Salesforce territory records, and notifying the regional team via Teams."
  tags:
    - sales
    - marketing
    - jira
    - salesforce
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: market-launch
      port: 8080
      tools:
        - name: coordinate-market-launch
          description: "Coordinate the launch of products in a new market by creating project tasks, setting up CRM territories, and notifying regional teams."
          inputParameters:
            - name: market_name
              type: string
              description: "Name of the new market (e.g., Vietnam, Colombia)."
            - name: brand
              type: string
              description: "Brand being launched."
            - name: launch_date
              type: string
              description: "Target launch date."
          steps:
            - name: create-epic
              type: call
              call: jira.create-issue
              with:
                project_key: "LAUNCH"
                issuetype: "Epic"
                summary: "New market launch: {{brand}} in {{market_name}}"
                description: "Target launch: {{launch_date}}. Brand: {{brand}}."
            - name: setup-territory
              type: call
              call: salesforce.create-territory
              with:
                Name: "{{market_name}} - {{brand}}"
                Territory_Type__c: "New Market"
                Launch_Date__c: "{{launch_date}}"
            - name: notify-regional
              type: call
              call: msteams.send-message
              with:
                channel_id: "international-launches"
                text: "New market launch initiated: {{brand}} in {{market_name}}. Target: {{launch_date}}. Epic: {{create-epic.key}}."
  consumes:
    - type: http
      namespace: jira
      baseUri: "https://loreal.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: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: territories
          path: "/sobjects/Territory__c"
          operations:
            - name: create-territory
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

When an R&D formulation is submitted, retrieves the bill of materials from SAP, checks regulatory compliance documents in SharePoint, and creates a review task in Jira.

naftiko: "0.5"
info:
  label: "New Product Formulation Review Workflow"
  description: "When an R&D formulation is submitted, retrieves the bill of materials from SAP, checks regulatory compliance documents in SharePoint, and creates a review task in Jira."
  tags:
    - r-and-d
    - quality
    - sap
    - sharepoint
    - jira
capability:
  exposes:
    - type: mcp
      namespace: rd-formulation
      port: 8080
      tools:
        - name: initiate-formulation-review
          description: "Orchestrate a new product formulation review by pulling the BOM, checking regulatory docs, and creating a review task."
          inputParameters:
            - name: material_number
              type: string
              description: "SAP material number for the new formulation."
            - name: plant_code
              type: string
              description: "SAP plant code."
            - name: formulation_name
              type: string
              description: "Name of the new formulation."
          steps:
            - name: get-bom
              type: call
              call: sap.get-bom
              with:
                material: "{{material_number}}"
                plant: "{{plant_code}}"
            - name: check-regulatory
              type: call
              call: sharepoint.search-docs
              with:
                query: "{{formulation_name}} regulatory INCI"
                site: "regulatory-affairs"
            - name: create-review-task
              type: call
              call: jira.create-issue
              with:
                project_key: "RND"
                issuetype: "Task"
                summary: "Formulation review: {{formulation_name}}"
                description: "BOM contains {{get-bom.component_count}} components. Regulatory docs found: {{check-regulatory.result_count}}."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_BILL_OF_MATERIAL_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: bom
          path: "/MaterialBOM"
          operations:
            - name: get-bom
              method: GET
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: search
          path: "/sites/regulatory-affairs/drive/root/search"
          operations:
            - name: search-docs
              method: GET
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

Onboards a new SKU by creating the material master in SAP, setting up the Salesforce product record, and notifying the supply chain team via Teams.

naftiko: "0.5"
info:
  label: "New SKU Listing Onboarding Workflow"
  description: "Onboards a new SKU by creating the material master in SAP, setting up the Salesforce product record, and notifying the supply chain team via Teams."
  tags:
    - supply-chain
    - sales
    - sap
    - salesforce
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: sku-management
      port: 8080
      tools:
        - name: onboard-new-sku
          description: "Orchestrate the onboarding of a new SKU across ERP, CRM, and notification systems."
          inputParameters:
            - name: sku_name
              type: string
              description: "Product name for the new SKU."
            - name: brand
              type: string
              description: "Brand name."
            - name: category
              type: string
              description: "Product category."
            - name: unit_cost
              type: number
              description: "Unit cost in USD."
          steps:
            - name: create-material
              type: call
              call: sap.create-material
              with:
                description: "{{sku_name}}"
                material_group: "{{category}}"
                brand: "{{brand}}"
                standard_price: "{{unit_cost}}"
            - name: create-sf-product
              type: call
              call: salesforce.create-product
              with:
                Name: "{{sku_name}}"
                ProductCode: "{{create-material.material_number}}"
                Family: "{{category}}"
                IsActive: true
            - name: notify-supply-chain
              type: call
              call: msteams.send-message
              with:
                channel_id: "supply-chain-ops"
                text: "New SKU onboarded: {{sku_name}} ({{create-material.material_number}}). Brand: {{brand}}. Category: {{category}}."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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"
          operations:
            - name: create-material
              method: POST
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: products
          path: "/sobjects/Product2"
          operations:
            - name: create-product
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

When an access request is approved in ServiceNow, provisions the requested Okta group membership and confirms via Teams.

naftiko: "0.5"
info:
  label: "Okta Access Request Provisioning"
  description: "When an access request is approved in ServiceNow, provisions the requested Okta group membership and confirms via Teams."
  tags:
    - identity
    - security
    - okta
    - servicenow
    - access-management
capability:
  exposes:
    - type: mcp
      namespace: identity-ops
      port: 8080
      tools:
        - name: provision-access
          description: "Given an approved ServiceNow access request ticket, assign the user to the corresponding Okta group and update the ticket status to resolved. Use for access provisioning automation."
          inputParameters:
            - name: snow_ticket_id
              type: string
              description: "ServiceNow request ticket sys_id."
            - name: user_email
              type: string
              description: "User email address to provision access for."
            - name: okta_group_id
              type: string
              description: "Okta group ID to assign the user to."
          steps:
            - name: add-to-group
              type: call
              call: okta.add-user-to-group
              with:
                groupId: "{{okta_group_id}}"
                userId: "{{user_email}}"
            - name: resolve-ticket
              type: call
              call: servicenow.update-request
              with:
                sys_id: "{{snow_ticket_id}}"
                state: "3"
                close_notes: "Access provisioned to Okta group {{okta_group_id}}"
            - name: notify-user
              type: call
              call: msteams.send-message
              with:
                recipient_upn: "{{user_email}}"
                text: "Your access request has been fulfilled. You now have access to the requested resources (Okta group: {{okta_group_id}})."
  consumes:
    - type: http
      namespace: okta
      baseUri: "https://loreal.okta.com/api/v1"
      authentication:
        type: apikey
        key: "Authorization"
        value: "$secrets.okta_api_token"
        placement: header
      resources:
        - name: group-members
          path: "/groups/{{groupId}}/users/{{userId}}"
          inputParameters:
            - name: groupId
              in: path
            - name: userId
              in: path
          operations:
            - name: add-user-to-group
              method: PUT
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: requests
          path: "/table/sc_request/{{sys_id}}"
          inputParameters:
            - name: sys_id
              in: path
          operations:
            - name: update-request
              method: PATCH
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: chats
          path: "/chats"
          operations:
            - name: send-message
              method: POST

Handles contractor access expiry by checking Okta account status, verifying contract end dates in Workday, and creating deprovisioning tasks in ServiceNow.

naftiko: "0.5"
info:
  label: "Okta Contractor Access Expiry Handler"
  description: "Handles contractor access expiry by checking Okta account status, verifying contract end dates in Workday, and creating deprovisioning tasks in ServiceNow."
  tags:
    - security
    - identity
    - okta
    - workday
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: access-lifecycle
      port: 8080
      tools:
        - name: handle-contractor-expiry
          description: "Handle contractor access expiry by verifying employment status and creating deprovisioning tasks."
          inputParameters:
            - name: contractor_email
              type: string
              description: "Contractor email address."
          steps:
            - name: get-okta-status
              type: call
              call: okta.get-user
              with:
                email: "{{contractor_email}}"
            - name: check-workday
              type: call
              call: workday.get-worker-by-email
              with:
                email: "{{contractor_email}}"
            - name: create-deprovision-task
              type: call
              call: servicenow.create-task
              with:
                short_description: "Contractor access expiry: {{contractor_email}}"
                description: "Okta status: {{get-okta-status.status}}. Workday end date: {{check-workday.contract_end_date}}. Deprovisioning required."
                category: "identity_management"
  consumes:
    - type: http
      namespace: okta
      baseUri: "https://loreal.okta.com/api/v1"
      authentication:
        type: bearer
        token: "$secrets.okta_api_token"
      resources:
        - name: users
          path: "/users/{{email}}"
          inputParameters:
            - name: email
              in: path
          operations:
            - name: get-user
              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: "/loreal/workers"
          operations:
            - name: get-worker-by-email
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: tasks
          path: "/table/sc_task"
          operations:
            - name: create-task
              method: POST

Audits privileged access by pulling Okta admin role assignments, cross-referencing with Workday employment status, and creating a ServiceNow review task for stale accounts.

naftiko: "0.5"
info:
  label: "Okta Privileged Access Audit Workflow"
  description: "Audits privileged access by pulling Okta admin role assignments, cross-referencing with Workday employment status, and creating a ServiceNow review task for stale accounts."
  tags:
    - security
    - identity
    - okta
    - workday
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: security-audit
      port: 8080
      tools:
        - name: audit-privileged-access
          description: "Audit privileged Okta accounts by verifying employment status and flagging stale or orphaned admin accounts."
          inputParameters:
            - name: role_type
              type: string
              description: "Okta admin role type to audit (e.g., SUPER_ADMIN, ORG_ADMIN)."
          steps:
            - name: get-admin-users
              type: call
              call: okta.list-role-assignments
              with:
                role_type: "{{role_type}}"
            - name: check-employment
              type: call
              call: workday.get-active-workers
              with:
                email_list: "{{get-admin-users.emails}}"
            - name: create-review
              type: call
              call: servicenow.create-task
              with:
                short_description: "Privileged access audit: {{role_type}} role"
                description: "Total admins: {{get-admin-users.count}}. Inactive employees with admin access: {{check-employment.stale_count}}."
                category: "security"
  consumes:
    - type: http
      namespace: okta
      baseUri: "https://loreal.okta.com/api/v1"
      authentication:
        type: bearer
        token: "$secrets.okta_api_token"
      resources:
        - name: roles
          path: "/users"
          operations:
            - name: list-role-assignments
              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: "/loreal/workers"
          operations:
            - name: get-active-workers
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: tasks
          path: "/table/sc_task"
          operations:
            - name: create-task
              method: POST

Checks packaging materials against sustainability requirements by querying SAP BOM data, verifying compliance in Snowflake, and creating a Jira task for non-compliant items.

naftiko: "0.5"
info:
  label: "Packaging Sustainability Compliance Checker"
  description: "Checks packaging materials against sustainability requirements by querying SAP BOM data, verifying compliance in Snowflake, and creating a Jira task for non-compliant items."
  tags:
    - sustainability
    - quality
    - sap
    - snowflake
    - jira
capability:
  exposes:
    - type: mcp
      namespace: sustainability
      port: 8080
      tools:
        - name: check-packaging-compliance
          description: "Verify packaging sustainability compliance by cross-referencing BOM materials with sustainability standards and flagging non-compliant components."
          inputParameters:
            - name: material_number
              type: string
              description: "SAP material number for the packaged product."
            - name: plant_code
              type: string
              description: "SAP plant code."
          steps:
            - name: get-packaging-bom
              type: call
              call: sap.get-bom
              with:
                material: "{{material_number}}"
                plant: "{{plant_code}}"
            - name: check-compliance
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "SUSTAINABILITY_WH"
                query: "SELECT material_id, recyclable_pct, compliant FROM packaging_sustainability WHERE material_id IN ({{get-packaging-bom.component_ids}})"
            - name: create-task
              type: call
              call: jira.create-issue
              with:
                project_key: "SUSTAIN"
                issuetype: "Task"
                summary: "Packaging compliance review: {{material_number}}"
                description: "Non-compliant components found: {{check-compliance.non_compliant_count}}. Review required."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_BILL_OF_MATERIAL_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: bom
          path: "/MaterialBOM"
          operations:
            - name: get-bom
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

Retrieves current headcount by department and cost center from Workday for payroll planning and cost allocation reporting.

naftiko: "0.5"
info:
  label: "Payroll Headcount Snapshot"
  description: "Retrieves current headcount by department and cost center from Workday for payroll planning and cost allocation reporting."
  tags:
    - hr
    - finance
    - payroll
    - workday
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: hr-finance
      port: 8080
      tools:
        - name: get-headcount-by-department
          description: "Returns a list of active employees grouped by department and cost center with employment type. Use for headcount planning, budgeting, and HR cost reporting."
          call: workday.headcount-export
          outputParameters:
            - name: employees
              type: array
              mapping: "$.data"
              items:
                - name: employee_id
                  type: string
                  mapping: "$.id"
                - name: full_name
                  type: string
                  mapping: "$.fullName"
                - name: department
                  type: string
                  mapping: "$.department"
                - name: cost_center
                  type: string
                  mapping: "$.costCenter"
  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-export
          path: "/loreal/workers"
          operations:
            - name: headcount-export
              method: GET

Monitors manufacturing plant energy consumption by querying Snowflake IoT data, comparing against targets, and creating a ServiceNow task for anomalies.

naftiko: "0.5"
info:
  label: "Plant Energy Consumption Monitor"
  description: "Monitors manufacturing plant energy consumption by querying Snowflake IoT data, comparing against targets, and creating a ServiceNow task for anomalies."
  tags:
    - manufacturing
    - sustainability
    - snowflake
    - servicenow
    - iot
capability:
  exposes:
    - type: mcp
      namespace: energy-monitoring
      port: 8080
      tools:
        - name: monitor-energy-consumption
          description: "Monitor plant energy consumption against targets and flag anomalies for investigation."
          inputParameters:
            - name: plant_code
              type: string
              description: "SAP plant code."
            - name: date
              type: string
              description: "Date to check in YYYY-MM-DD format."
          steps:
            - name: get-consumption
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "IOT_ANALYTICS_WH"
                query: "SELECT kwh_actual, kwh_target, variance_pct FROM plant_energy WHERE plant='{{plant_code}}' AND date='{{date}}'"
            - name: create-anomaly-task
              type: call
              call: servicenow.create-task
              with:
                short_description: "Energy anomaly: plant {{plant_code}} on {{date}}"
                description: "Actual: {{get-consumption.kwh_actual}} kWh. Target: {{get-consumption.kwh_target}} kWh. Variance: {{get-consumption.variance_pct}}%."
                category: "facilities"
            - name: notify-team
              type: call
              call: msteams.send-message
              with:
                channel_id: "plant-sustainability"
                text: "Energy alert for {{plant_code}}: {{get-consumption.variance_pct}}% over target on {{date}}."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: tasks
          path: "/table/sc_task"
          operations:
            - name: create-task
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Triggers a refresh of a Power BI brand sales dashboard dataset and returns the refresh status.

naftiko: "0.5"
info:
  label: "Power BI Brand Sales Dashboard Refresh"
  description: "Triggers a refresh of a Power BI brand sales dashboard dataset and returns the refresh status."
  tags:
    - analytics
    - reporting
    - power-bi
    - sales
capability:
  exposes:
    - type: mcp
      namespace: bi-reporting
      port: 8080
      tools:
        - name: refresh-brand-dashboard
          description: "Trigger a dataset refresh for a Power BI brand sales dashboard and return the resulting refresh status."
          inputParameters:
            - name: dataset_id
              type: string
              description: "Power BI dataset ID for the brand sales dashboard."
          call: powerbi.refresh-dataset
          with:
            datasetId: "{{dataset_id}}"
          outputParameters:
            - name: refresh_id
              type: string
              mapping: "$.id"
            - name: status
              type: string
              mapping: "$.status"
  consumes:
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: datasets
          path: "/datasets/{{datasetId}}/refreshes"
          inputParameters:
            - name: datasetId
              in: path
          operations:
            - name: refresh-dataset
              method: POST

Triggers a Power BI dataset refresh on schedule and posts completion status to the analytics Teams channel.

naftiko: "0.5"
info:
  label: "Power BI Report Refresh Trigger"
  description: "Triggers a Power BI dataset refresh on schedule and posts completion status to the analytics Teams channel."
  tags:
    - data
    - analytics
    - power-bi
    - microsoft-teams
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: bi-reporting
      port: 8080
      tools:
        - name: trigger-dataset-refresh
          description: "Trigger a Power BI dataset refresh for a given workspace and dataset, then post completion status to the analytics Teams channel. Use for scheduled BI refresh orchestration."
          inputParameters:
            - name: workspace_id
              type: string
              description: "Power BI workspace (group) ID."
            - name: dataset_id
              type: string
              description: "Power BI dataset ID to refresh."
            - name: teams_channel_id
              type: string
              description: "Teams channel ID to notify on completion."
          steps:
            - name: refresh-dataset
              type: call
              call: powerbi.trigger-refresh
              with:
                workspaceId: "{{workspace_id}}"
                datasetId: "{{dataset_id}}"
            - name: notify-team
              type: call
              call: msteams.post-message
              with:
                channel_id: "{{teams_channel_id}}"
                text: "Power BI dataset {{dataset_id}} refresh triggered successfully in workspace {{workspace_id}}."
  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/{{workspaceId}}/datasets/{{datasetId}}/refreshes"
          inputParameters:
            - name: workspaceId
              in: path
            - name: datasetId
              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/analytics/channels/{{channel_id}}/messages"
          inputParameters:
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Analyzes product costing variances by comparing SAP standard costs with actual production costs from Snowflake and creating a finance review task in Jira.

naftiko: "0.5"
info:
  label: "Product Costing Variance Analyzer"
  description: "Analyzes product costing variances by comparing SAP standard costs with actual production costs from Snowflake and creating a finance review task in Jira."
  tags:
    - finance
    - manufacturing
    - sap
    - snowflake
    - jira
capability:
  exposes:
    - type: mcp
      namespace: cost-analytics
      port: 8080
      tools:
        - name: analyze-costing-variance
          description: "Analyze product costing variances between standard and actual costs and route significant variances for review."
          inputParameters:
            - name: material_number
              type: string
              description: "SAP material number."
            - name: period
              type: string
              description: "Costing period in YYYY-MM format."
          steps:
            - name: get-standard-cost
              type: call
              call: sap.get-material-cost
              with:
                material: "{{material_number}}"
            - name: get-actual-cost
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "FINANCE_WH"
                query: "SELECT actual_cost_per_unit, total_production_cost FROM production_costs WHERE material='{{material_number}}' AND period='{{period}}'"
            - name: create-review
              type: call
              call: jira.create-issue
              with:
                project_key: "FIN"
                issuetype: "Task"
                summary: "Costing variance review: {{material_number}} ({{period}})"
                description: "Standard cost: {{get-standard-cost.standard_price}}. Actual: {{get-actual-cost.actual_cost_per_unit}}. Variance: needs review."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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}}')"
          inputParameters:
            - name: material
              in: path
          operations:
            - name: get-material-cost
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

Assembles a product launch briefing by pulling campaign assets from Adobe Creative Cloud and distributing the package to brand teams via SharePoint and Teams.

naftiko: "0.5"
info:
  label: "Product Launch Content Briefing"
  description: "Assembles a product launch briefing by pulling campaign assets from Adobe Creative Cloud and distributing the package to brand teams via SharePoint and Teams."
  tags:
    - marketing
    - content
    - adobe
    - sharepoint
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: content-ops
      port: 8080
      tools:
        - name: assemble-launch-briefing
          description: "Given a product launch ID, retrieve approved creative assets from Adobe Experience Manager, upload them to a SharePoint brand folder, and notify the brand team via Teams."
          inputParameters:
            - name: launch_id
              type: string
              description: "Internal product launch ID."
            - name: brand_name
              type: string
              description: "Brand name (e.g., Lancôme, Maybelline) for folder routing."
            - name: teams_channel_id
              type: string
              description: "Teams channel ID for the brand team notification."
          steps:
            - name: get-assets
              type: call
              call: aem.list-assets
              with:
                launchId: "{{launch_id}}"
                brand: "{{brand_name}}"
            - name: upload-to-sharepoint
              type: call
              call: sharepoint.upload-file
              with:
                site_id: "brand_launches"
                folder_path: "Launches/{{brand_name}}/{{launch_id}}"
                content: "{{get-assets.packageUrl}}"
            - name: notify-team
              type: call
              call: msteams.post-channel-message
              with:
                channel_id: "{{teams_channel_id}}"
                text: "Launch briefing ready for {{brand_name}} ({{launch_id}}). Assets: {{upload-to-sharepoint.sharepoint_url}}"
  consumes:
    - type: http
      namespace: aem
      baseUri: "https://author.loreal.adobecqms.net/api/assets"
      authentication:
        type: basic
        username: "$secrets.aem_user"
        password: "$secrets.aem_password"
      resources:
        - name: assets
          path: "/loreal/launches/{{launchId}}"
          inputParameters:
            - name: launchId
              in: path
          operations:
            - name: list-assets
              method: GET
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: files
          path: "/sites/{{site_id}}/drive/items/root:/{{folder_path}}:/children"
          inputParameters:
            - name: site_id
              in: path
            - name: folder_path
              in: path
          operations:
            - name: upload-file
              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/brand/channels/{{channel_id}}/messages"
          inputParameters:
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

When a quality issue is detected, traces the affected batch in SAP, creates a ServiceNow incident, notifies the quality team via Teams, and opens a Jira investigation ticket.

naftiko: "0.5"
info:
  label: "Product Recall Investigation Orchestrator"
  description: "When a quality issue is detected, traces the affected batch in SAP, creates a ServiceNow incident, notifies the quality team via Teams, and opens a Jira investigation ticket."
  tags:
    - quality
    - supply-chain
    - sap
    - servicenow
    - microsoft-teams
    - jira
capability:
  exposes:
    - type: mcp
      namespace: quality-ops
      port: 8080
      tools:
        - name: investigate-recall
          description: "Orchestrate a product recall investigation by tracing the batch, creating an incident, notifying the quality team, and opening a tracking ticket."
          inputParameters:
            - name: batch_number
              type: string
              description: "Affected product batch number."
            - name: material_number
              type: string
              description: "SAP material number of the affected product."
            - name: severity
              type: string
              description: "Severity level: critical, high, medium, low."
          steps:
            - name: trace-batch
              type: call
              call: sap.get-batch-details
              with:
                batch: "{{batch_number}}"
                material: "{{material_number}}"
            - name: create-incident
              type: call
              call: servicenow.create-incident
              with:
                short_description: "Product recall investigation: batch {{batch_number}}"
                category: "quality"
                urgency: "{{severity}}"
                description: "Batch {{batch_number}} produced at {{trace-batch.plant}}. Investigation required."
            - name: notify-team
              type: call
              call: msteams.send-message
              with:
                channel_id: "quality-alerts"
                text: "RECALL ALERT: Batch {{batch_number}} under investigation. Incident: {{create-incident.number}}. Severity: {{severity}}."
            - name: create-jira-ticket
              type: call
              call: jira.create-issue
              with:
                project_key: "QUAL"
                issuetype: "Task"
                summary: "Recall investigation: {{material_number}} batch {{batch_number}}"
                description: "ServiceNow incident: {{create-incident.number}}. Plant: {{trace-batch.plant}}."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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: "/A_Batch"
          operations:
            - name: get-batch-details
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.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: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

Orchestrates the release of a production batch by verifying quality inspection results in SAP QM, updating the batch status, and notifying the logistics team via Teams.

naftiko: "0.5"
info:
  label: "Production Batch Release Workflow"
  description: "Orchestrates the release of a production batch by verifying quality inspection results in SAP QM, updating the batch status, and notifying the logistics team via Teams."
  tags:
    - manufacturing
    - quality
    - sap
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: batch-release
      port: 8080
      tools:
        - name: release-production-batch
          description: "Release a production batch after quality verification by checking inspection results, updating batch status, and notifying logistics."
          inputParameters:
            - name: batch_number
              type: string
              description: "Production batch number."
            - name: material_number
              type: string
              description: "SAP material number."
          steps:
            - name: check-inspection
              type: call
              call: sap.get-inspection-result
              with:
                batch: "{{batch_number}}"
                material: "{{material_number}}"
            - name: release-batch
              type: call
              call: sap.update-batch-status
              with:
                batch: "{{batch_number}}"
                material: "{{material_number}}"
                status: "RELEASED"
            - name: notify-logistics
              type: call
              call: msteams.send-message
              with:
                channel_id: "logistics-ops"
                text: "Batch {{batch_number}} ({{material_number}}) released for distribution. Inspection: {{check-inspection.usage_decision}}."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_INSPECTIONLOT_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: inspections
          path: "/A_InspectionLot"
          operations:
            - name: get-inspection-result
              method: GET
            - name: update-batch-status
              method: PATCH
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Reviews the R&D patent portfolio by querying SharePoint for patent documents, pulling innovation metrics from Snowflake, and creating a review summary in Jira.

naftiko: "0.5"
info:
  label: "R&D Patent Portfolio Review"
  description: "Reviews the R&D patent portfolio by querying SharePoint for patent documents, pulling innovation metrics from Snowflake, and creating a review summary in Jira."
  tags:
    - r-and-d
    - innovation
    - sharepoint
    - snowflake
    - jira
capability:
  exposes:
    - type: mcp
      namespace: rd-innovation
      port: 8080
      tools:
        - name: review-patent-portfolio
          description: "Review the patent portfolio by pulling documents, analyzing metrics, and creating a summary task."
          inputParameters:
            - name: technology_area
              type: string
              description: "Technology area for patent review."
            - name: review_year
              type: string
              description: "Year for the review."
          steps:
            - name: get-patents
              type: call
              call: sharepoint.search-docs
              with:
                query: "patent {{technology_area}} {{review_year}}"
                site: "rd-innovation"
            - name: get-metrics
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "RD_ANALYTICS_WH"
                query: "SELECT patent_count, pending_count, granted_count FROM patent_metrics WHERE tech_area='{{technology_area}}' AND year='{{review_year}}'"
            - name: create-review
              type: call
              call: jira.create-issue
              with:
                project_key: "RND"
                issuetype: "Task"
                summary: "Patent portfolio review: {{technology_area}} ({{review_year}})"
                description: "Total patents: {{get-metrics.patent_count}}. Pending: {{get-metrics.pending_count}}. Granted: {{get-metrics.granted_count}}. Documents found: {{get-patents.count}}."
  consumes:
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: search
          path: "/sites/rd-innovation/drive/root/search"
          operations:
            - name: search-docs
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

When inventory drops below threshold, checks SAP stock levels, identifies affected production orders, and creates a procurement request in SAP Ariba.

naftiko: "0.5"
info:
  label: "Raw Material Shortage Alert Handler"
  description: "When inventory drops below threshold, checks SAP stock levels, identifies affected production orders, and creates a procurement request in SAP Ariba."
  tags:
    - supply-chain
    - procurement
    - sap
    - manufacturing
capability:
  exposes:
    - type: mcp
      namespace: supply-ops
      port: 8080
      tools:
        - name: handle-material-shortage
          description: "Respond to a raw material shortage by checking stock, identifying impacted orders, and triggering a procurement request."
          inputParameters:
            - name: material_number
              type: string
              description: "SAP material number for the raw material."
            - name: plant_code
              type: string
              description: "SAP plant code."
            - name: reorder_quantity
              type: number
              description: "Quantity to reorder."
          steps:
            - name: check-stock
              type: call
              call: sap.get-stock
              with:
                material: "{{material_number}}"
                plant: "{{plant_code}}"
            - name: get-affected-orders
              type: call
              call: sap.get-dependent-orders
              with:
                material: "{{material_number}}"
                plant: "{{plant_code}}"
            - name: create-requisition
              type: call
              call: ariba.create-requisition
              with:
                material: "{{material_number}}"
                quantity: "{{reorder_quantity}}"
                plant: "{{plant_code}}"
                justification: "Stock below threshold. Current: {{check-stock.unrestricted_qty}}. Affected orders: {{get-affected-orders.count}}."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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
        - name: orders
          path: "/A_ProductionOrder"
          operations:
            - name: get-dependent-orders
              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

Audits retail planogram compliance by pulling store visit data from Salesforce, checking compliance metrics in Snowflake, and creating follow-up tasks in Jira.

naftiko: "0.5"
info:
  label: "Retail Planogram Compliance Audit"
  description: "Audits retail planogram compliance by pulling store visit data from Salesforce, checking compliance metrics in Snowflake, and creating follow-up tasks in Jira."
  tags:
    - sales
    - retail
    - salesforce
    - snowflake
    - jira
capability:
  exposes:
    - type: mcp
      namespace: retail-compliance
      port: 8080
      tools:
        - name: audit-planogram-compliance
          description: "Audit retail planogram compliance by combining store visit data with compliance metrics."
          inputParameters:
            - name: region
              type: string
              description: "Sales region."
            - name: audit_week
              type: string
              description: "Audit week in YYYY-WW format."
          steps:
            - name: get-visits
              type: call
              call: salesforce.get-store-visits
              with:
                region: "{{region}}"
                week: "{{audit_week}}"
            - name: get-compliance
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "RETAIL_ANALYTICS_WH"
                query: "SELECT store_id, planogram_score, oos_count FROM planogram_compliance WHERE region='{{region}}' AND week='{{audit_week}}'"
            - name: create-followups
              type: call
              call: jira.create-issue
              with:
                project_key: "RETAIL"
                issuetype: "Task"
                summary: "Planogram compliance follow-up: {{region}} week {{audit_week}}"
                description: "Stores audited: {{get-visits.store_count}}. Average compliance: {{get-compliance.avg_score}}%. Below threshold: {{get-compliance.below_threshold_count}}."
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: visits
          path: "/sobjects/Store_Visit__c"
          operations:
            - name: get-store-visits
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

Retrieves retail account data from Salesforce, pulls shelf compliance scores from Snowflake, and creates a follow-up task in Jira for the field sales team.

naftiko: "0.5"
info:
  label: "Retail Shelf Audit Orchestrator"
  description: "Retrieves retail account data from Salesforce, pulls shelf compliance scores from Snowflake, and creates a follow-up task in Jira for the field sales team."
  tags:
    - sales
    - retail
    - salesforce
    - snowflake
    - jira
capability:
  exposes:
    - type: mcp
      namespace: retail-ops
      port: 8080
      tools:
        - name: run-shelf-audit
          description: "Orchestrate a retail shelf audit by pulling account data, checking compliance scores, and creating follow-up tasks."
          inputParameters:
            - name: account_id
              type: string
              description: "Salesforce retail account ID."
            - name: audit_period
              type: string
              description: "Audit period in YYYY-MM format."
          steps:
            - name: get-account
              type: call
              call: salesforce.get-account
              with:
                account_id: "{{account_id}}"
            - name: get-compliance
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "RETAIL_ANALYTICS_WH"
                query: "SELECT compliance_score, oos_rate FROM shelf_audit WHERE account_id='{{account_id}}' AND period='{{audit_period}}'"
            - name: create-followup
              type: call
              call: jira.create-issue
              with:
                project_key: "RETAIL"
                issuetype: "Task"
                summary: "Shelf audit follow-up: {{get-account.name}} - {{audit_period}}"
                description: "Compliance score: {{get-compliance.compliance_score}}%. OOS rate: {{get-compliance.oos_rate}}%."
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: accounts
          path: "/sobjects/Account/{{account_id}}"
          inputParameters:
            - name: account_id
              in: path
          operations:
            - name: get-account
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

When a new lead is created in Salesforce, enriches the record with company data from ZoomInfo and updates the lead score.

naftiko: "0.5"
info:
  label: "Salesforce Lead Enrichment"
  description: "When a new lead is created in Salesforce, enriches the record with company data from ZoomInfo and updates the lead score."
  tags:
    - crm
    - sales
    - salesforce
    - zoominfo
    - lead-enrichment
capability:
  exposes:
    - type: mcp
      namespace: crm
      port: 8080
      tools:
        - name: enrich-lead
          description: "Given a Salesforce lead ID, fetch company firmographic data from ZoomInfo and write enriched fields back to the Salesforce lead record. Use when a new lead lacks company details."
          inputParameters:
            - name: lead_id
              type: string
              description: "Salesforce lead record ID (18-character Salesforce ID)."
          steps:
            - name: get-lead
              type: call
              call: salesforce.get-lead
              with:
                lead_id: "{{lead_id}}"
            - name: enrich-company
              type: call
              call: zoominfo.search-company
              with:
                company_name: "{{get-lead.Company}}"
                domain: "{{get-lead.Website}}"
            - name: update-lead
              type: call
              call: salesforce-update.update-lead
              with:
                lead_id: "{{lead_id}}"
                NumberOfEmployees: "{{enrich-company.employeeCount}}"
                AnnualRevenue: "{{enrich-company.revenue}}"
                Industry: "{{enrich-company.industry}}"
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: leads
          path: "/sobjects/Lead/{{lead_id}}"
          inputParameters:
            - name: lead_id
              in: path
          operations:
            - name: get-lead
              method: GET
    - type: http
      namespace: zoominfo
      baseUri: "https://api.zoominfo.com/search"
      authentication:
        type: bearer
        token: "$secrets.zoominfo_token"
      resources:
        - name: companies
          path: "/company"
          operations:
            - name: search-company
              method: POST
    - type: http
      namespace: salesforce-update
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: leads
          path: "/sobjects/Lead/{{lead_id}}"
          inputParameters:
            - name: lead_id
              in: path
          operations:
            - name: update-lead
              method: PATCH

When a Salesforce opportunity advances to Closed Won, triggers a Workday cost center allocation update and notifies sales leadership via Teams.

naftiko: "0.5"
info:
  label: "Salesforce Opportunity Stage Sync"
  description: "When a Salesforce opportunity advances to Closed Won, triggers a Workday cost center allocation update and notifies sales leadership via Teams."
  tags:
    - crm
    - sales
    - salesforce
    - workday
    - finance
capability:
  exposes:
    - type: mcp
      namespace: sales-ops
      port: 8080
      tools:
        - name: sync-opportunity-close
          description: "Given a Salesforce opportunity ID in Closed Won status, fetch opportunity details, update the associated Workday cost center budget, and post a win notification to the sales leadership Teams channel."
          inputParameters:
            - name: opportunity_id
              type: string
              description: "Salesforce opportunity record ID."
            - name: teams_channel_id
              type: string
              description: "Teams channel ID for sales leadership notifications."
          steps:
            - name: get-opportunity
              type: call
              call: salesforce.get-opportunity
              with:
                opportunity_id: "{{opportunity_id}}"
            - name: update-budget
              type: call
              call: workday.update-cost-center
              with:
                cost_center: "{{get-opportunity.CostCenter__c}}"
                amount: "{{get-opportunity.Amount}}"
            - name: post-win
              type: call
              call: msteams.post-channel-message
              with:
                channel_id: "{{teams_channel_id}}"
                text: "New win: {{get-opportunity.Name}} — {{get-opportunity.Amount}} {{get-opportunity.CurrencyIsoCode}}"
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: opportunities
          path: "/sobjects/Opportunity/{{opportunity_id}}"
          inputParameters:
            - name: opportunity_id
              in: path
          operations:
            - name: get-opportunity
              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: cost-centers
          path: "/loreal/costCenters/{{cost_center}}"
          inputParameters:
            - name: cost_center
              in: path
          operations:
            - name: update-cost-center
              method: PATCH
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: channel-messages
          path: "/teams/sales/channels/{{channel_id}}/messages"
          inputParameters:
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Retrieves retail account details from Salesforce including account health score, open opportunities, and last order date.

naftiko: "0.5"
info:
  label: "Salesforce Retail Account Lookup"
  description: "Retrieves retail account details from Salesforce including account health score, open opportunities, and last order date."
  tags:
    - sales
    - retail
    - salesforce
    - crm
capability:
  exposes:
    - type: mcp
      namespace: crm-retail
      port: 8080
      tools:
        - name: get-retail-account
          description: "Look up a retail account in Salesforce by account ID. Returns health score, open opportunity count, and last order date."
          inputParameters:
            - name: account_id
              type: string
              description: "Salesforce account ID."
          call: salesforce.get-account
          with:
            account_id: "{{account_id}}"
          outputParameters:
            - name: account_name
              type: string
              mapping: "$.Name"
            - name: health_score
              type: string
              mapping: "$.Health_Score__c"
            - name: open_opportunities
              type: string
              mapping: "$.Open_Opportunity_Count__c"
            - name: last_order_date
              type: string
              mapping: "$.Last_Order_Date__c"
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: accounts
          path: "/sobjects/Account/{{account_id}}"
          inputParameters:
            - name: account_id
              in: path
          operations:
            - name: get-account
              method: GET

Processes a salon professional order by creating a Salesforce order, triggering SAP sales order creation, and sending an order confirmation via email through Microsoft Graph.

naftiko: "0.5"
info:
  label: "Salon Professional Order Processing"
  description: "Processes a salon professional order by creating a Salesforce order, triggering SAP sales order creation, and sending an order confirmation via email through Microsoft Graph."
  tags:
    - sales
    - supply-chain
    - salesforce
    - sap
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: salon-sales
      port: 8080
      tools:
        - name: process-salon-order
          description: "Process a salon professional order by creating CRM and ERP records and sending confirmation."
          inputParameters:
            - name: salon_account_id
              type: string
              description: "Salesforce salon account ID."
            - name: product_list
              type: string
              description: "JSON array of products and quantities."
          steps:
            - name: create-sf-order
              type: call
              call: salesforce.create-order
              with:
                AccountId: "{{salon_account_id}}"
                Status: "Draft"
                products: "{{product_list}}"
            - name: create-sap-order
              type: call
              call: sap.create-sales-order
              with:
                customer: "{{salon_account_id}}"
                items: "{{product_list}}"
                sf_reference: "{{create-sf-order.id}}"
            - name: send-confirmation
              type: call
              call: msgraph.send-mail
              with:
                to: "{{create-sf-order.contact_email}}"
                subject: "Order confirmation: {{create-sf-order.OrderNumber}}"
                body: "Your order {{create-sf-order.OrderNumber}} has been placed. SAP reference: {{create-sap-order.order_number}}."
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: orders
          path: "/sobjects/Order"
          operations:
            - name: create-order
              method: POST
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_SALES_ORDER_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: sales-orders
          path: "/A_SalesOrder"
          operations:
            - name: create-sales-order
              method: POST
    - type: http
      namespace: msgraph
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: mail
          path: "/me/sendMail"
          operations:
            - name: send-mail
              method: POST

Registers a new supplier in SAP Ariba, creates a vendor master record in SAP S/4HANA, and notifies the procurement team via Teams.

naftiko: "0.5"
info:
  label: "SAP Ariba Supplier Onboarding"
  description: "Registers a new supplier in SAP Ariba, creates a vendor master record in SAP S/4HANA, and notifies the procurement team via Teams."
  tags:
    - procurement
    - sap-ariba
    - sap
    - supplier-management
capability:
  exposes:
    - type: mcp
      namespace: procurement-ops
      port: 8080
      tools:
        - name: onboard-supplier
          description: "Given supplier details, register the supplier in SAP Ariba sourcing, create the corresponding vendor master in SAP S/4HANA, and notify the procurement manager via Teams."
          inputParameters:
            - name: supplier_name
              type: string
              description: "Legal name of the supplier company."
            - name: supplier_country
              type: string
              description: "Two-letter ISO country code for the supplier."
            - name: procurement_manager_upn
              type: string
              description: "UPN of the procurement manager for Teams notification."
          steps:
            - name: register-in-ariba
              type: call
              call: sap-ariba.create-supplier
              with:
                supplierName: "{{supplier_name}}"
                country: "{{supplier_country}}"
            - name: create-vendor-master
              type: call
              call: sap.create-vendor
              with:
                vendorName: "{{supplier_name}}"
                country: "{{supplier_country}}"
                aribaId: "{{register-in-ariba.supplierId}}"
            - name: notify-manager
              type: call
              call: msteams.send-message
              with:
                recipient_upn: "{{procurement_manager_upn}}"
                text: "Supplier {{supplier_name}} onboarded. Ariba ID: {{register-in-ariba.supplierId}}, SAP Vendor: {{create-vendor-master.vendorId}}"
  consumes:
    - type: http
      namespace: sap-ariba
      baseUri: "https://openapi.ariba.com/api/supplier/v1"
      authentication:
        type: bearer
        token: "$secrets.ariba_token"
      resources:
        - name: suppliers
          path: "/suppliers"
          operations:
            - name: create-supplier
              method: POST
    - type: http
      namespace: sap
      baseUri: "https://loreal-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"
          operations:
            - name: create-vendor
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: chats
          path: "/chats"
          operations:
            - name: send-message
              method: POST

Traces a product batch through SAP to retrieve raw material origins, production dates, and distribution records.

naftiko: "0.5"
info:
  label: "SAP Batch Traceability Lookup"
  description: "Traces a product batch through SAP to retrieve raw material origins, production dates, and distribution records."
  tags:
    - quality
    - supply-chain
    - sap
    - traceability
capability:
  exposes:
    - type: mcp
      namespace: erp-traceability
      port: 8080
      tools:
        - name: trace-batch
          description: "Trace a product batch in SAP to identify raw material lots, production facility, and shipment records. Use for recall investigations or quality audits."
          inputParameters:
            - name: batch_number
              type: string
              description: "SAP batch number to trace."
            - name: material_number
              type: string
              description: "SAP material number."
          call: sap.get-batch-trace
          with:
            batch: "{{batch_number}}"
            material: "{{material_number}}"
          outputParameters:
            - name: production_plant
              type: string
              mapping: "$.d.ProductionPlant"
            - name: production_date
              type: string
              mapping: "$.d.ManufactureDate"
            - name: raw_material_lots
              type: string
              mapping: "$.d.ComponentBatches"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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: "/A_Batch(Material='{{material}}',Batch='{{batch}}')"
          inputParameters:
            - name: material
              in: path
            - name: batch
              in: path
          operations:
            - name: get-batch-trace
              method: GET

Retrieves the bill of materials for a finished product from SAP including component materials, quantities, and alternates.

naftiko: "0.5"
info:
  label: "SAP Bill of Materials Lookup"
  description: "Retrieves the bill of materials for a finished product from SAP including component materials, quantities, and alternates."
  tags:
    - manufacturing
    - r-and-d
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: erp-engineering
      port: 8080
      tools:
        - name: get-bom
          description: "Retrieve bill of materials from SAP for a material number. Returns component list with quantities and item categories."
          inputParameters:
            - name: material_number
              type: string
              description: "SAP finished product material number."
            - name: plant_code
              type: string
              description: "SAP plant code."
          call: sap.get-bom
          with:
            material: "{{material_number}}"
            plant: "{{plant_code}}"
          outputParameters:
            - name: bom_number
              type: string
              mapping: "$.d.BillOfMaterial"
            - name: components
              type: string
              mapping: "$.d.to_BillOfMaterialItem.results"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_BILL_OF_MATERIAL_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: bom
          path: "/MaterialBOM(Material='{{material}}',Plant='{{plant}}')"
          inputParameters:
            - name: material
              in: path
            - name: plant
              in: path
          operations:
            - name: get-bom
              method: GET

Extracts budget vs. actuals data from SAP S/4HANA by cost center and publishes the variance report to Power BI and SharePoint.

naftiko: "0.5"
info:
  label: "SAP Budget Variance Report"
  description: "Extracts budget vs. actuals data from SAP S/4HANA by cost center and publishes the variance report to Power BI and SharePoint."
  tags:
    - finance
    - erp
    - sap
    - power-bi
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: finance-reporting
      port: 8080
      tools:
        - name: publish-budget-variance
          description: "Given a fiscal period and cost center, extract budget vs. actuals from SAP S/4HANA, push the data to a Power BI dataset, and upload a summary report to SharePoint."
          inputParameters:
            - name: fiscal_period
              type: string
              description: "Fiscal period in YYYYMM format (e.g., 202603)."
            - name: cost_center
              type: string
              description: "SAP cost center code."
          steps:
            - name: get-variance-data
              type: call
              call: sap.get-cost-center-actuals
              with:
                fiscalPeriod: "{{fiscal_period}}"
                costCenter: "{{cost_center}}"
            - name: push-to-powerbi
              type: call
              call: powerbi.push-rows
              with:
                datasetId: "$secrets.powerbi_budget_dataset_id"
                tableName: "BudgetVariance"
                rows: "{{get-variance-data.rows}}"
            - name: upload-report
              type: call
              call: sharepoint.upload-file
              with:
                site_id: "finance_reports"
                folder_path: "BudgetVariance/{{fiscal_period}}"
                content: "{{get-variance-data.summary}}"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/YY1_COSTCENTERACTUALS_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: cost-center-actuals
          path: "/CostCenterActuals"
          inputParameters:
            - name: fiscalPeriod
              in: query
            - name: costCenter
              in: query
          operations:
            - name: get-cost-center-actuals
              method: GET
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: dataset-rows
          path: "/datasets/{{datasetId}}/tables/{{tableName}}/rows"
          inputParameters:
            - name: datasetId
              in: path
            - name: tableName
              in: path
          operations:
            - name: push-rows
              method: POST
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: files
          path: "/sites/{{site_id}}/drive/items/root:/{{folder_path}}:/children"
          inputParameters:
            - name: site_id
              in: path
            - name: folder_path
              in: path
          operations:
            - name: upload-file
              method: POST

Retrieves pending expense reports from SAP Concur, validates against policy thresholds, and routes high-value reports for manager approval via Teams.

naftiko: "0.5"
info:
  label: "SAP Concur Expense Report Approval"
  description: "Retrieves pending expense reports from SAP Concur, validates against policy thresholds, and routes high-value reports for manager approval via Teams."
  tags:
    - finance
    - expense-management
    - sap-concur
    - microsoft-teams
    - approval
capability:
  exposes:
    - type: mcp
      namespace: expense-ops
      port: 8080
      tools:
        - name: review-pending-expenses
          description: "Fetch pending expense reports from SAP Concur for a given cost center. Flag reports exceeding the policy threshold and send approval requests to the submitter's manager via Teams."
          inputParameters:
            - name: cost_center
              type: string
              description: "Cost center code to retrieve pending expenses for."
            - name: threshold_eur
              type: number
              description: "Policy threshold in EUR above which manager approval is required."
          steps:
            - name: get-reports
              type: call
              call: concur.list-expense-reports
              with:
                costCenter: "{{cost_center}}"
                approvalStatus: "pending"
            - name: notify-manager
              type: call
              call: msteams.send-message
              with:
                recipient_upn: "{{get-reports.managerEmail}}"
                text: "Expense reports pending your approval for cost center {{cost_center}}. Reports above {{threshold_eur}} EUR require your review."
  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/reports"
          inputParameters:
            - name: costCenter
              in: query
            - name: approvalStatus
              in: query
          operations:
            - name: list-expense-reports
              method: GET
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: chats
          path: "/chats"
          operations:
            - name: send-message
              method: POST

Monitors cost center budget consumption by pulling actuals from SAP, comparing with plan data in Snowflake, and alerting budget owners via Teams when thresholds are exceeded.

naftiko: "0.5"
info:
  label: "SAP Cost Center Budget Monitor"
  description: "Monitors cost center budget consumption by pulling actuals from SAP, comparing with plan data in Snowflake, and alerting budget owners via Teams when thresholds are exceeded."
  tags:
    - finance
    - operations
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: budget-monitoring
      port: 8080
      tools:
        - name: monitor-budget
          description: "Monitor cost center budget consumption and alert when spending exceeds thresholds."
          inputParameters:
            - name: cost_center
              type: string
              description: "SAP cost center ID."
            - name: period
              type: string
              description: "Fiscal period in YYYY-MM format."
            - name: threshold_pct
              type: number
              description: "Alert threshold as percentage of budget consumed."
          steps:
            - name: get-actuals
              type: call
              call: sap.get-cost-center-actuals
              with:
                cost_center: "{{cost_center}}"
                period: "{{period}}"
            - name: get-plan
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "FINANCE_WH"
                query: "SELECT planned_amount, consumed_pct FROM budget_plan WHERE cost_center='{{cost_center}}' AND period='{{period}}'"
            - name: alert-owner
              type: call
              call: msteams.send-message
              with:
                channel_id: "finance-budget"
                text: "Budget alert for {{cost_center}} ({{period}}): Actual spend {{get-actuals.total_amount}}. Plan: {{get-plan.planned_amount}}. Consumed: {{get-plan.consumed_pct}}%."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_OPLACCTGDOCITEMCUBE_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: actuals
          path: "/A_OperationalAcctgDocItemCube"
          operations:
            - name: get-cost-center-actuals
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-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: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Processes credit memos by validating the original invoice in SAP, creating the credit memo, and updating the Salesforce account with the credit balance.

naftiko: "0.5"
info:
  label: "SAP Credit Memo Processing Workflow"
  description: "Processes credit memos by validating the original invoice in SAP, creating the credit memo, and updating the Salesforce account with the credit balance."
  tags:
    - finance
    - sales
    - sap
    - salesforce
capability:
  exposes:
    - type: mcp
      namespace: finance-ar
      port: 8080
      tools:
        - name: process-credit-memo
          description: "Process a credit memo by validating the original invoice, creating the credit document, and updating the customer account."
          inputParameters:
            - name: invoice_number
              type: string
              description: "Original SAP invoice number."
            - name: credit_amount
              type: number
              description: "Credit amount to issue."
            - name: reason
              type: string
              description: "Reason for credit memo."
          steps:
            - name: validate-invoice
              type: call
              call: sap.get-invoice
              with:
                invoice_number: "{{invoice_number}}"
            - name: create-credit-memo
              type: call
              call: sap.create-credit-memo
              with:
                reference_invoice: "{{invoice_number}}"
                amount: "{{credit_amount}}"
                reason: "{{reason}}"
            - name: update-sf-account
              type: call
              call: salesforce.update-account
              with:
                account_id: "{{validate-invoice.customer_id}}"
                Credit_Balance__c: "{{credit_amount}}"
                Last_Credit_Memo__c: "{{create-credit-memo.document_number}}"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_BILLING_DOCUMENT_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: billing
          path: "/A_BillingDocument"
          operations:
            - name: get-invoice
              method: GET
            - name: create-credit-memo
              method: POST
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: accounts
          path: "/sobjects/Account/{{account_id}}"
          inputParameters:
            - name: account_id
              in: path
          operations:
            - name: update-account
              method: PATCH

Analyzes customer return patterns by pulling return data from SAP, correlating with quality data in Snowflake, and creating improvement tasks in Jira.

naftiko: "0.5"
info:
  label: "SAP Customer Returns Analysis"
  description: "Analyzes customer return patterns by pulling return data from SAP, correlating with quality data in Snowflake, and creating improvement tasks in Jira."
  tags:
    - quality
    - sales
    - sap
    - snowflake
    - jira
capability:
  exposes:
    - type: mcp
      namespace: returns-analytics
      port: 8080
      tools:
        - name: analyze-customer-returns
          description: "Analyze customer return patterns to identify quality issues and create improvement actions."
          inputParameters:
            - name: material_number
              type: string
              description: "SAP material number."
            - name: period
              type: string
              description: "Analysis period in YYYY-QN format."
          steps:
            - name: get-returns
              type: call
              call: sap.get-return-orders
              with:
                material: "{{material_number}}"
                period: "{{period}}"
            - name: get-quality-data
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "QUALITY_WH"
                query: "SELECT return_reason, count, pct_of_sales FROM return_analysis WHERE material='{{material_number}}' AND period='{{period}}'"
            - name: create-improvement
              type: call
              call: jira.create-issue
              with:
                project_key: "QUAL"
                issuetype: "Task"
                summary: "Returns analysis: {{material_number}} ({{period}})"
                description: "Return count: {{get-returns.count}}. Top reason: {{get-quality-data.top_reason}}. Rate: {{get-quality-data.return_rate}}%."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_RETURNS_DELIVERY_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: returns
          path: "/A_ReturnsDeliveryHeader"
          operations:
            - name: get-return-orders
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

Orchestrates the monthly financial close by running SAP period close tasks, validating balances in Snowflake, and posting completion status to the finance Teams channel.

naftiko: "0.5"
info:
  label: "SAP Financial Period Close Orchestrator"
  description: "Orchestrates the monthly financial close by running SAP period close tasks, validating balances in Snowflake, and posting completion status to the finance Teams channel."
  tags:
    - finance
    - operations
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: finance-close
      port: 8080
      tools:
        - name: orchestrate-period-close
          description: "Orchestrate the monthly financial period close process across ERP validation, data reconciliation, and team notification."
          inputParameters:
            - name: period
              type: string
              description: "Fiscal period in YYYY-MM format."
            - name: company_code
              type: string
              description: "SAP company code."
          steps:
            - name: check-open-items
              type: call
              call: sap.get-open-items
              with:
                company_code: "{{company_code}}"
                period: "{{period}}"
            - name: validate-balances
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "FINANCE_WH"
                query: "SELECT account, gl_balance, sub_ledger_balance, variance FROM balance_reconciliation WHERE company_code='{{company_code}}' AND period='{{period}}' AND variance != 0"
            - name: post-status
              type: call
              call: msteams.send-message
              with:
                channel_id: "finance-close"
                text: "Period close {{period}} for {{company_code}}: Open items: {{check-open-items.count}}. Balance variances: {{validate-balances.variance_count}}."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_OPLACCTGDOCITEMCUBE_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: items
          path: "/A_OperationalAcctgDocItemCube"
          operations:
            - name: get-open-items
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-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: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Confirms goods receipt in SAP S/4HANA for a given purchase order, returning receipt status and quantity received.

naftiko: "0.5"
info:
  label: "SAP Goods Receipt Confirmation"
  description: "Confirms goods receipt in SAP S/4HANA for a given purchase order, returning receipt status and quantity received."
  tags:
    - supply-chain
    - manufacturing
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: erp-logistics
      port: 8080
      tools:
        - name: confirm-goods-receipt
          description: "Confirm goods receipt against a purchase order in SAP. Returns receipt document number, quantity received, and posting date."
          inputParameters:
            - name: po_number
              type: string
              description: "SAP purchase order number."
            - name: plant_code
              type: string
              description: "SAP plant code where goods are received."
          call: sap.post-goods-receipt
          with:
            po_number: "{{po_number}}"
            plant: "{{plant_code}}"
          outputParameters:
            - name: receipt_doc
              type: string
              mapping: "$.d.MaterialDocumentNumber"
            - name: quantity
              type: string
              mapping: "$.d.QuantityReceived"
            - name: posting_date
              type: string
              mapping: "$.d.PostingDate"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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: post-goods-receipt
              method: POST

Checks hazardous material compliance for shipping by querying SAP material safety data, validating against regulations in Snowflake, and creating a ServiceNow task for non-compliance.

naftiko: "0.5"
info:
  label: "SAP Hazardous Material Compliance Check"
  description: "Checks hazardous material compliance for shipping by querying SAP material safety data, validating against regulations in Snowflake, and creating a ServiceNow task for non-compliance."
  tags:
    - quality
    - regulatory
    - sap
    - snowflake
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: hazmat-compliance
      port: 8080
      tools:
        - name: check-hazmat-compliance
          description: "Verify hazardous material compliance for a shipment by checking safety data and regulatory requirements."
          inputParameters:
            - name: material_number
              type: string
              description: "SAP material number."
            - name: destination_country
              type: string
              description: "Destination country code."
          steps:
            - name: get-safety-data
              type: call
              call: sap.get-material-safety
              with:
                material: "{{material_number}}"
            - name: check-regulations
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "REGULATORY_WH"
                query: "SELECT regulation, compliant, required_docs FROM hazmat_regulations WHERE un_number='{{get-safety-data.un_number}}' AND country='{{destination_country}}'"
            - name: create-task
              type: call
              call: servicenow.create-task
              with:
                short_description: "Hazmat compliance: {{material_number}} to {{destination_country}}"
                description: "UN number: {{get-safety-data.un_number}}. Compliance status: {{check-regulations.compliant}}."
                category: "regulatory"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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}}')/to_ProductSafetyData"
          inputParameters:
            - name: material
              in: path
          operations:
            - name: get-material-safety
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: tasks
          path: "/table/sc_task"
          operations:
            - name: create-task
              method: POST

Creates an intercompany stock transfer in SAP between plants, updates the receiving plant inventory forecast in Snowflake, and notifies both plant teams via Teams.

naftiko: "0.5"
info:
  label: "SAP Intercompany Transfer Order Workflow"
  description: "Creates an intercompany stock transfer in SAP between plants, updates the receiving plant inventory forecast in Snowflake, and notifies both plant teams via Teams."
  tags:
    - supply-chain
    - logistics
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: intercompany-logistics
      port: 8080
      tools:
        - name: create-intercompany-transfer
          description: "Create an intercompany stock transfer between plants, update forecasts, and notify plant teams."
          inputParameters:
            - name: material_number
              type: string
              description: "SAP material number."
            - name: source_plant
              type: string
              description: "Source plant code."
            - name: target_plant
              type: string
              description: "Target plant code."
            - name: quantity
              type: number
              description: "Transfer quantity."
          steps:
            - name: create-transfer
              type: call
              call: sap.create-stock-transfer
              with:
                material: "{{material_number}}"
                from_plant: "{{source_plant}}"
                to_plant: "{{target_plant}}"
                quantity: "{{quantity}}"
            - name: update-forecast
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "SUPPLY_CHAIN_WH"
                query: "CALL update_plant_forecast('{{target_plant}}', '{{material_number}}', {{quantity}})"
            - name: notify-plants
              type: call
              call: msteams.send-message
              with:
                channel_id: "supply-chain-ops"
                text: "Intercompany transfer {{create-transfer.document_number}}: {{quantity}} units of {{material_number}} from {{source_plant}} to {{target_plant}}."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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: "/A_StockTransfer"
          operations:
            - name: create-stock-transfer
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-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: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Creates a plant maintenance order in SAP based on a ServiceNow request, assigns technicians, and notifies the maintenance team via Teams.

naftiko: "0.5"
info:
  label: "SAP Maintenance Order Creation Workflow"
  description: "Creates a plant maintenance order in SAP based on a ServiceNow request, assigns technicians, and notifies the maintenance team via Teams."
  tags:
    - manufacturing
    - operations
    - sap
    - servicenow
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: plant-maintenance
      port: 8080
      tools:
        - name: create-maintenance-order
          description: "Create a maintenance order from a ServiceNow request, assign resources, and notify the team."
          inputParameters:
            - name: snow_ticket
              type: string
              description: "ServiceNow request number."
            - name: equipment_id
              type: string
              description: "SAP equipment ID."
            - name: priority
              type: string
              description: "Maintenance priority: emergency, high, normal, low."
          steps:
            - name: get-request
              type: call
              call: servicenow.get-request
              with:
                number: "{{snow_ticket}}"
            - name: create-order
              type: call
              call: sap.create-maintenance-order
              with:
                equipment: "{{equipment_id}}"
                priority: "{{priority}}"
                description: "{{get-request.short_description}}"
            - name: notify-team
              type: call
              call: msteams.send-message
              with:
                channel_id: "maintenance-ops"
                text: "Maintenance order {{create-order.order_number}} created for equipment {{equipment_id}}. Priority: {{priority}}. Source: {{snow_ticket}}."
  consumes:
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: requests
          path: "/table/sc_request/{{number}}"
          inputParameters:
            - name: number
              in: path
          operations:
            - name: get-request
              method: GET
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_MAINTENANCEORDER_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: orders
          path: "/MaintenanceOrder"
          operations:
            - name: create-maintenance-order
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Checks current material stock levels in SAP for a given material and plant, returning available and unrestricted quantities.

naftiko: "0.5"
info:
  label: "SAP Material Stock Level Check"
  description: "Checks current material stock levels in SAP for a given material and plant, returning available and unrestricted quantities."
  tags:
    - supply-chain
    - inventory
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: erp-inventory
      port: 8080
      tools:
        - name: check-stock-level
          description: "Query SAP for current stock level of a material at a specific plant. Returns unrestricted use, quality inspection, and blocked stock quantities."
          inputParameters:
            - name: material_number
              type: string
              description: "SAP material number."
            - name: plant_code
              type: string
              description: "SAP plant code."
          call: sap.get-stock
          with:
            material: "{{material_number}}"
            plant: "{{plant_code}}"
          outputParameters:
            - name: unrestricted_qty
              type: string
              mapping: "$.d.MatlWrhsStkQtyInMatlBaseUnit"
            - name: quality_inspection_qty
              type: string
              mapping: "$.d.QualityInspectionStockQty"
            - name: blocked_qty
              type: string
              mapping: "$.d.BlockedStockQty"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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(Material='{{material}}',Plant='{{plant}}')"
          inputParameters:
            - name: material
              in: path
            - name: plant
              in: path
          operations:
            - name: get-stock
              method: GET

Generates a plant maintenance schedule report by pulling upcoming maintenance orders from SAP, enriching with equipment history from Snowflake, and posting to Teams.

naftiko: "0.5"
info:
  label: "SAP Plant Maintenance Schedule Report"
  description: "Generates a plant maintenance schedule report by pulling upcoming maintenance orders from SAP, enriching with equipment history from Snowflake, and posting to Teams."
  tags:
    - manufacturing
    - operations
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: maintenance-reporting
      port: 8080
      tools:
        - name: generate-maintenance-report
          description: "Generate a maintenance schedule report combining upcoming orders with equipment history."
          inputParameters:
            - name: plant_code
              type: string
              description: "SAP plant code."
            - name: weeks_ahead
              type: number
              description: "Number of weeks to look ahead."
          steps:
            - name: get-schedule
              type: call
              call: sap.get-maintenance-orders
              with:
                plant: "{{plant_code}}"
                horizon_weeks: "{{weeks_ahead}}"
            - name: get-equipment-history
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "MANUFACTURING_WH"
                query: "SELECT equipment_id, mtbf_hours, last_failure_date FROM equipment_history WHERE plant='{{plant_code}}' AND equipment_id IN ({{get-schedule.equipment_ids}})"
            - name: post-report
              type: call
              call: msteams.send-message
              with:
                channel_id: "maintenance-planning"
                text: "Maintenance schedule for {{plant_code}} (next {{weeks_ahead}} weeks): {{get-schedule.order_count}} orders. Equipment at risk: {{get-equipment-history.at_risk_count}}."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_MAINTENANCEORDER_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: orders
          path: "/MaintenanceOrder"
          operations:
            - name: get-maintenance-orders
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-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: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Retrieves the current status and progress of a manufacturing production order from SAP S/4HANA.

naftiko: "0.5"
info:
  label: "SAP Production Order Status Lookup"
  description: "Retrieves the current status and progress of a manufacturing production order from SAP S/4HANA."
  tags:
    - manufacturing
    - production
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: erp-manufacturing
      port: 8080
      tools:
        - name: get-production-order
          description: "Look up a production order in SAP by order number. Returns status, planned quantity, confirmed quantity, and target completion date."
          inputParameters:
            - name: order_number
              type: string
              description: "SAP production order number."
          call: sap.get-production-order
          with:
            order_number: "{{order_number}}"
          outputParameters:
            - name: status
              type: string
              mapping: "$.d.ManufacturingOrderStatus"
            - name: planned_qty
              type: string
              mapping: "$.d.TotalPlannedQuantity"
            - name: confirmed_qty
              type: string
              mapping: "$.d.TotalConfirmedYieldQuantity"
            - name: target_end_date
              type: string
              mapping: "$.d.MfgOrderPlannedEndDate"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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('{{order_number}}')"
          inputParameters:
            - name: order_number
              in: path
          operations:
            - name: get-production-order
              method: GET

Optimizes production scheduling by pulling demand signals from Snowflake, checking plant capacity in SAP, and creating optimized schedule proposals in Jira.

naftiko: "0.5"
info:
  label: "SAP Production Scheduling Optimizer"
  description: "Optimizes production scheduling by pulling demand signals from Snowflake, checking plant capacity in SAP, and creating optimized schedule proposals in Jira."
  tags:
    - manufacturing
    - supply-chain
    - snowflake
    - sap
    - jira
capability:
  exposes:
    - type: mcp
      namespace: production-planning
      port: 8080
      tools:
        - name: optimize-production-schedule
          description: "Optimize production scheduling by balancing demand signals with plant capacity constraints."
          inputParameters:
            - name: plant_code
              type: string
              description: "SAP plant code."
            - name: planning_period
              type: string
              description: "Planning period in YYYY-WW format."
          steps:
            - name: get-demand
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "DEMAND_PLANNING_WH"
                query: "SELECT sku, required_units, priority FROM demand_signals WHERE plant='{{plant_code}}' AND week='{{planning_period}}'"
            - name: get-capacity
              type: call
              call: sap.get-plant-capacity
              with:
                plant: "{{plant_code}}"
                period: "{{planning_period}}"
            - name: create-schedule
              type: call
              call: jira.create-issue
              with:
                project_key: "PROD"
                issuetype: "Task"
                summary: "Production schedule: {{plant_code}} week {{planning_period}}"
                description: "Demand: {{get-demand.total_units}} units across {{get-demand.sku_count}} SKUs. Available capacity: {{get-capacity.available_hours}} hours."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: sap
      baseUri: "https://loreal-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: capacity
          path: "/A_ProductionOrderCapacity"
          operations:
            - name: get-plant-capacity
              method: GET
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

Analyzes production yield by comparing planned vs actual output in SAP, identifying waste trends in Snowflake, and creating improvement tasks in Jira.

naftiko: "0.5"
info:
  label: "SAP Production Yield Analysis"
  description: "Analyzes production yield by comparing planned vs actual output in SAP, identifying waste trends in Snowflake, and creating improvement tasks in Jira."
  tags:
    - manufacturing
    - quality
    - sap
    - snowflake
    - jira
capability:
  exposes:
    - type: mcp
      namespace: production-analytics
      port: 8080
      tools:
        - name: analyze-production-yield
          description: "Analyze production yield to identify waste and efficiency improvement opportunities."
          inputParameters:
            - name: production_line
              type: string
              description: "Production line identifier."
            - name: plant_code
              type: string
              description: "SAP plant code."
            - name: period
              type: string
              description: "Analysis period in YYYY-MM format."
          steps:
            - name: get-yield-data
              type: call
              call: sap.get-production-confirmations
              with:
                plant: "{{plant_code}}"
                line: "{{production_line}}"
                period: "{{period}}"
            - name: get-waste-trends
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "MANUFACTURING_WH"
                query: "SELECT waste_category, waste_pct, trend FROM production_waste WHERE line='{{production_line}}' AND plant='{{plant_code}}' AND period='{{period}}'"
            - name: create-improvement
              type: call
              call: jira.create-issue
              with:
                project_key: "MFG"
                issuetype: "Task"
                summary: "Yield improvement: {{production_line}} at {{plant_code}} ({{period}})"
                description: "Yield: {{get-yield-data.yield_pct}}%. Top waste: {{get-waste-trends.top_category}} at {{get-waste-trends.top_pct}}%."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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: confirmations
          path: "/A_ProdnOrdConf2"
          operations:
            - name: get-production-confirmations
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

Looks up a purchase order in SAP S/4HANA by PO number and returns header status, vendor, and total value.

naftiko: "0.5"
info:
  label: "SAP Purchase Order Lookup"
  description: "Looks up a purchase order in SAP S/4HANA by PO number and returns header status, vendor, and total value."
  tags:
    - finance
    - procurement
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: erp
      port: 8080
      tools:
        - name: get-purchase-order
          description: "Look up an SAP purchase order by PO number. Returns header status, vendor name, total value, and currency. Use for procurement approval workflows and spend visibility."
          inputParameters:
            - name: po_number
              type: string
              description: "SAP purchase order number (10-digit numeric string)."
          call: sap.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_value
              type: string
              mapping: "$.d.TotalAmount"
            - name: currency
              type: string
              mapping: "$.d.TransactionCurrency"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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

Retrieves quality inspection lot details from SAP QM for a given batch or material to check inspection status and results.

naftiko: "0.5"
info:
  label: "SAP Quality Inspection Lot Lookup"
  description: "Retrieves quality inspection lot details from SAP QM for a given batch or material to check inspection status and results."
  tags:
    - quality
    - manufacturing
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: erp-quality
      port: 8080
      tools:
        - name: get-inspection-lot
          description: "Look up a quality inspection lot in SAP by material number and batch. Returns inspection status, usage decision, and defect count."
          inputParameters:
            - name: material_number
              type: string
              description: "SAP material number."
            - name: batch
              type: string
              description: "Batch number for the material."
          call: sap.get-inspection-lot
          with:
            material: "{{material_number}}"
            batch: "{{batch}}"
          outputParameters:
            - name: inspection_lot
              type: string
              mapping: "$.d.InspectionLot"
            - name: status
              type: string
              mapping: "$.d.InspectionLotStatus"
            - name: usage_decision
              type: string
              mapping: "$.d.UsageDecision"
            - name: defect_count
              type: string
              mapping: "$.d.NumberOfDefects"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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"
          inputParameters:
            - name: material
              in: query
            - name: batch
              in: query
          operations:
            - name: get-inspection-lot
              method: GET

Tracks outbound shipments by querying SAP delivery documents, checking carrier status, and updating the Salesforce order with tracking information.

naftiko: "0.5"
info:
  label: "SAP Transport Shipment Tracker"
  description: "Tracks outbound shipments by querying SAP delivery documents, checking carrier status, and updating the Salesforce order with tracking information."
  tags:
    - supply-chain
    - logistics
    - sap
    - salesforce
capability:
  exposes:
    - type: mcp
      namespace: logistics-tracking
      port: 8080
      tools:
        - name: track-shipment
          description: "Track an outbound shipment by pulling delivery data from SAP and updating the CRM order record."
          inputParameters:
            - name: delivery_number
              type: string
              description: "SAP outbound delivery number."
            - name: sf_order_id
              type: string
              description: "Salesforce order ID."
          steps:
            - name: get-delivery
              type: call
              call: sap.get-delivery
              with:
                delivery: "{{delivery_number}}"
            - name: update-order
              type: call
              call: salesforce.update-order
              with:
                order_id: "{{sf_order_id}}"
                Tracking_Number__c: "{{get-delivery.tracking_number}}"
                Carrier__c: "{{get-delivery.carrier}}"
                Ship_Date__c: "{{get-delivery.actual_ship_date}}"
            - name: notify-customer
              type: call
              call: salesforce.send-notification
              with:
                order_id: "{{sf_order_id}}"
                message: "Your order has shipped via {{get-delivery.carrier}}. Tracking: {{get-delivery.tracking_number}}."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_OUTBOUND_DELIVERY_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: deliveries
          path: "/A_OutbDeliveryHeader('{{delivery}}')"
          inputParameters:
            - name: delivery
              in: path
          operations:
            - name: get-delivery
              method: GET
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: orders
          path: "/sobjects/Order/{{order_id}}"
          inputParameters:
            - name: order_id
              in: path
          operations:
            - name: update-order
              method: PATCH
            - name: send-notification
              method: POST

Retrieves vendor master data from SAP S/4HANA including payment terms, contact details, and compliance status.

naftiko: "0.5"
info:
  label: "SAP Vendor Master Lookup"
  description: "Retrieves vendor master data from SAP S/4HANA including payment terms, contact details, and compliance status."
  tags:
    - procurement
    - supply-chain
    - sap
    - erp
capability:
  exposes:
    - type: mcp
      namespace: erp-procurement
      port: 8080
      tools:
        - name: get-vendor
          description: "Look up vendor master record in SAP by vendor number. Returns company name, payment terms, and purchasing organization data."
          inputParameters:
            - name: vendor_number
              type: string
              description: "SAP vendor account number."
          call: sap.get-vendor
          with:
            vendor: "{{vendor_number}}"
          outputParameters:
            - name: vendor_name
              type: string
              mapping: "$.d.SupplierName"
            - name: payment_terms
              type: string
              mapping: "$.d.PaymentTerms"
            - name: purchasing_org
              type: string
              mapping: "$.d.PurchasingOrganization"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_BUSINESS_PARTNER"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: suppliers
          path: "/A_Supplier('{{vendor}}')"
          inputParameters:
            - name: vendor
              in: path
          operations:
            - name: get-vendor
              method: GET

Posts a warehouse transfer between storage locations in SAP, updates inventory visibility in Snowflake, and sends a confirmation to the warehouse team via Teams.

naftiko: "0.5"
info:
  label: "SAP Warehouse Transfer Posting"
  description: "Posts a warehouse transfer between storage locations in SAP, updates inventory visibility in Snowflake, and sends a confirmation to the warehouse team via Teams."
  tags:
    - supply-chain
    - logistics
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: warehouse-ops
      port: 8080
      tools:
        - name: post-warehouse-transfer
          description: "Post a warehouse transfer between storage locations and update visibility systems."
          inputParameters:
            - name: material_number
              type: string
              description: "SAP material number."
            - name: from_location
              type: string
              description: "Source storage location."
            - name: to_location
              type: string
              description: "Target storage location."
            - name: quantity
              type: number
              description: "Transfer quantity."
          steps:
            - name: post-transfer
              type: call
              call: sap.post-transfer
              with:
                material: "{{material_number}}"
                from_sloc: "{{from_location}}"
                to_sloc: "{{to_location}}"
                quantity: "{{quantity}}"
            - name: update-visibility
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "SUPPLY_CHAIN_WH"
                query: "CALL update_inventory_visibility('{{material_number}}', '{{to_location}}', {{quantity}})"
            - name: confirm
              type: call
              call: msteams.send-message
              with:
                channel_id: "warehouse-ops"
                text: "Transfer complete: {{quantity}} units of {{material_number}} from {{from_location}} to {{to_location}}. Doc: {{post-transfer.document_number}}."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_MATERIAL_DOCUMENT_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: transfers
          path: "/A_MaterialDocumentHeader"
          operations:
            - name: post-transfer
              method: POST
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-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: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Creates a ServiceNow change request for a planned infrastructure change, routes it to the CAB approver, and notifies the requester via Teams on approval.

naftiko: "0.5"
info:
  label: "ServiceNow Change Request Approval"
  description: "Creates a ServiceNow change request for a planned infrastructure change, routes it to the CAB approver, and notifies the requester via Teams on approval."
  tags:
    - itsm
    - change-management
    - servicenow
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: itsm
      port: 8080
      tools:
        - name: create-change-request
          description: "Given a change description, risk level, and implementation date, create a ServiceNow change request, assign it to the CAB, and notify the requester via Teams when created."
          inputParameters:
            - name: short_description
              type: string
              description: "Brief description of the infrastructure change."
            - name: risk
              type: string
              description: "Risk level: low, medium, or high."
            - name: implementation_date
              type: string
              description: "Planned implementation date in YYYY-MM-DD format."
            - name: requester_upn
              type: string
              description: "UPN of the change requester for Teams notification."
          steps:
            - name: create-change
              type: call
              call: servicenow.create-change
              with:
                short_description: "{{short_description}}"
                risk: "{{risk}}"
                start_date: "{{implementation_date}}"
                assignment_group: "CAB"
            - name: notify-requester
              type: call
              call: msteams.send-message
              with:
                recipient_upn: "{{requester_upn}}"
                text: "Change request {{create-change.number}} created and assigned to CAB for review. Risk: {{risk}}, Date: {{implementation_date}}"
  consumes:
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.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
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: chats
          path: "/chats"
          operations:
            - name: send-message
              method: POST

Retrieves IT asset details from ServiceNow CMDB by asset tag or serial number.

naftiko: "0.5"
info:
  label: "ServiceNow IT Asset Lookup"
  description: "Retrieves IT asset details from ServiceNow CMDB by asset tag or serial number."
  tags:
    - operations
    - it-asset
    - servicenow
    - cmdb
capability:
  exposes:
    - type: mcp
      namespace: it-assets
      port: 8080
      tools:
        - name: get-asset
          description: "Look up an IT asset in ServiceNow CMDB by asset tag. Returns asset name, status, assigned user, and warranty expiration."
          inputParameters:
            - name: asset_tag
              type: string
              description: "ServiceNow asset tag identifier."
          call: servicenow.get-asset
          with:
            asset_tag: "{{asset_tag}}"
          outputParameters:
            - name: name
              type: string
              mapping: "$.result.name"
            - name: status
              type: string
              mapping: "$.result.install_status"
            - name: assigned_to
              type: string
              mapping: "$.result.assigned_to.display_value"
            - name: warranty_expiry
              type: string
              mapping: "$.result.warranty_expiration"
  consumes:
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.service-now.com/api/now"
      authentication:
        type: basic
        username: "$secrets.servicenow_user"
        password: "$secrets.servicenow_password"
      resources:
        - name: assets
          path: "/table/alm_hardware"
          inputParameters:
            - name: asset_tag
              in: query
          operations:
            - name: get-asset
              method: GET

Searches SharePoint for regulatory compliance documents matching a keyword and returns document titles, URLs, and last modified dates.

naftiko: "0.5"
info:
  label: "SharePoint Regulatory Document Search"
  description: "Searches SharePoint for regulatory compliance documents matching a keyword and returns document titles, URLs, and last modified dates."
  tags:
    - quality
    - regulatory
    - sharepoint
    - documents
capability:
  exposes:
    - type: mcp
      namespace: doc-management
      port: 8080
      tools:
        - name: search-regulatory-docs
          description: "Search SharePoint regulatory library for documents matching a keyword. Returns title, URL, and last modified date."
          inputParameters:
            - name: keyword
              type: string
              description: "Search keyword for regulatory documents."
            - name: site_id
              type: string
              description: "SharePoint site ID for the regulatory library."
          call: sharepoint.search
          with:
            siteId: "{{site_id}}"
            queryText: "{{keyword}}"
          outputParameters:
            - name: results
              type: string
              mapping: "$.value"
  consumes:
    - type: http
      namespace: sharepoint
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: search
          path: "/sites/{{siteId}}/drive/root/search(q='{{queryText}}')"
          inputParameters:
            - name: siteId
              in: path
            - name: queryText
              in: path
          operations:
            - name: search
              method: GET

Executes a consumer analytics query in Snowflake and returns aggregated purchase behavior data for a product category.

naftiko: "0.5"
info:
  label: "Snowflake Consumer Insights Query"
  description: "Executes a consumer analytics query in Snowflake and returns aggregated purchase behavior data for a product category."
  tags:
    - analytics
    - marketing
    - snowflake
    - data
capability:
  exposes:
    - type: mcp
      namespace: consumer-analytics
      port: 8080
      tools:
        - name: query-consumer-insights
          description: "Query Snowflake consumer analytics warehouse for purchase frequency, basket size, and brand affinity by product category."
          inputParameters:
            - name: category
              type: string
              description: "Product category to analyze (e.g., skincare, haircare)."
            - name: region
              type: string
              description: "Market region code."
          call: snowflake.execute-query
          with:
            warehouse: "CONSUMER_ANALYTICS_WH"
            query: "SELECT * FROM consumer_insights WHERE category='{{category}}' AND region='{{region}}'"
          outputParameters:
            - name: avg_basket_size
              type: string
              mapping: "$.data[0].avg_basket_size"
            - name: purchase_frequency
              type: string
              mapping: "$.data[0].purchase_frequency"
            - name: brand_affinity_score
              type: string
              mapping: "$.data[0].brand_affinity"
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST

Checks Snowflake data pipeline task status and query failure counts, then creates a Jira issue and alerts Teams if thresholds are exceeded.

naftiko: "0.5"
info:
  label: "Snowflake Data Pipeline Health Check"
  description: "Checks Snowflake data pipeline task status and query failure counts, then creates a Jira issue and alerts Teams if thresholds are exceeded."
  tags:
    - data
    - analytics
    - snowflake
    - jira
    - monitoring
capability:
  exposes:
    - type: mcp
      namespace: data-ops
      port: 8080
      tools:
        - name: check-pipeline-health
          description: "Query Snowflake for failed tasks and long-running queries in the past N hours. If failures exceed the threshold, create a Jira issue and alert the data engineering Teams channel."
          inputParameters:
            - name: database
              type: string
              description: "Snowflake database name to check."
            - name: hours_back
              type: integer
              description: "Number of hours to look back for failures (e.g. 4)."
            - name: failure_threshold
              type: integer
              description: "Number of failures above which an alert is created."
          steps:
            - name: get-task-history
              type: call
              call: snowflake.query-task-history
              with:
                database: "{{database}}"
                hoursBack: "{{hours_back}}"
            - name: create-issue
              type: call
              call: jira.create-issue
              with:
                project_key: "DATA"
                issuetype: "Bug"
                summary: "Snowflake pipeline failures detected in {{database}}"
                description: "Failed tasks in last {{hours_back}}h: {{get-task-history.failureCount}}"
            - name: alert-team
              type: call
              call: msteams.post-channel-message
              with:
                channel_id: "data-engineering-alerts"
                text: "Pipeline alert: {{get-task-history.failureCount}} failures in {{database}} (last {{hours_back}}h). Jira: {{create-issue.key}}"
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: task-history
          path: "/databases/{{database}}/schemas/information_schema/tasks"
          inputParameters:
            - name: database
              in: path
          operations:
            - name: query-task-history
              method: GET
    - type: http
      namespace: jira
      baseUri: "https://loreal.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/data/channels/{{channel_id}}/messages"
          inputParameters:
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Pulls engagement metrics from LinkedIn and Meta for L'Oréal brand accounts and posts a weekly summary to a Teams channel.

naftiko: "0.5"
info:
  label: "Social Media Performance Report"
  description: "Pulls engagement metrics from LinkedIn and Meta for L'Oréal brand accounts and posts a weekly summary to a Teams channel."
  tags:
    - marketing
    - social
    - linkedin
    - meta
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: social-reporting
      port: 8080
      tools:
        - name: digest-social-performance
          description: "Fetch weekly post engagement metrics from LinkedIn and Meta brand pages and post a combined summary to the specified Teams channel. Use for weekly brand performance reviews."
          inputParameters:
            - name: linkedin_org_id
              type: string
              description: "LinkedIn organization URN for the brand page."
            - name: meta_page_id
              type: string
              description: "Meta (Facebook) page ID for the brand."
            - name: teams_channel_id
              type: string
              description: "Microsoft Teams channel ID to post the report to."
          steps:
            - name: get-linkedin-stats
              type: call
              call: linkedin.get-org-stats
              with:
                org_id: "{{linkedin_org_id}}"
            - name: get-meta-stats
              type: call
              call: meta.get-page-insights
              with:
                page_id: "{{meta_page_id}}"
            - name: post-report
              type: call
              call: msteams.post-message
              with:
                channel_id: "{{teams_channel_id}}"
                text: "Weekly Social Report — LinkedIn impressions: {{get-linkedin-stats.impressionCount}}, Meta reach: {{get-meta-stats.reach}}"
  consumes:
    - type: http
      namespace: linkedin
      baseUri: "https://api.linkedin.com/v2"
      authentication:
        type: bearer
        token: "$secrets.linkedin_token"
      resources:
        - name: org-stats
          path: "/organizationalEntityShareStatistics"
          inputParameters:
            - name: org_id
              in: query
          operations:
            - name: get-org-stats
              method: GET
    - type: http
      namespace: meta
      baseUri: "https://graph.facebook.com/v18.0"
      authentication:
        type: bearer
        token: "$secrets.meta_token"
      resources:
        - name: page-insights
          path: "/{{page_id}}/insights"
          inputParameters:
            - name: page_id
              in: path
          operations:
            - name: get-page-insights
              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/marketing/channels/{{channel_id}}/messages"
          inputParameters:
            - name: channel_id
              in: path
          operations:
            - name: post-message
              method: POST

Pulls supplier delivery and quality data from SAP Ariba, enriches with Snowflake analytics, and posts the scorecard summary to a Teams channel.

naftiko: "0.5"
info:
  label: "Supplier Performance Scorecard Generator"
  description: "Pulls supplier delivery and quality data from SAP Ariba, enriches with Snowflake analytics, and posts the scorecard summary to a Teams channel."
  tags:
    - procurement
    - supply-chain
    - sap
    - snowflake
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: procurement-analytics
      port: 8080
      tools:
        - name: generate-supplier-scorecard
          description: "Generate a supplier performance scorecard by combining SAP Ariba delivery data with Snowflake quality analytics and posting results to Teams."
          inputParameters:
            - name: supplier_id
              type: string
              description: "SAP Ariba supplier ID."
            - name: period
              type: string
              description: "Reporting period in YYYY-QN format (e.g., 2026-Q1)."
          steps:
            - name: get-delivery-metrics
              type: call
              call: ariba.get-supplier-performance
              with:
                supplier_id: "{{supplier_id}}"
                period: "{{period}}"
            - name: get-quality-metrics
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "PROCUREMENT_WH"
                query: "SELECT defect_rate, return_rate FROM supplier_quality WHERE supplier_id='{{supplier_id}}' AND period='{{period}}'"
            - name: post-scorecard
              type: call
              call: msteams.send-message
              with:
                channel_id: "procurement-reviews"
                text: "Supplier {{supplier_id}} scorecard for {{period}}: On-time delivery {{get-delivery-metrics.on_time_rate}}%, Defect rate {{get-quality-metrics.defect_rate}}%."
  consumes:
    - type: http
      namespace: ariba
      baseUri: "https://openapi.ariba.com/api/supplier-management/v1"
      authentication:
        type: bearer
        token: "$secrets.ariba_token"
      resources:
        - name: performance
          path: "/suppliers/{{supplier_id}}/performance"
          inputParameters:
            - name: supplier_id
              in: path
          operations:
            - name: get-supplier-performance
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-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: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Assesses supply chain risk by analyzing supplier concentration in Snowflake, checking SAP Ariba supplier status, and posting risk alerts to Teams.

naftiko: "0.5"
info:
  label: "Supply Chain Risk Assessment Workflow"
  description: "Assesses supply chain risk by analyzing supplier concentration in Snowflake, checking SAP Ariba supplier status, and posting risk alerts to Teams."
  tags:
    - supply-chain
    - procurement
    - snowflake
    - sap
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: supply-risk
      port: 8080
      tools:
        - name: assess-supply-chain-risk
          description: "Assess supply chain risk by analyzing supplier concentration and geopolitical exposure."
          inputParameters:
            - name: material_group
              type: string
              description: "SAP material group to assess."
          steps:
            - name: get-concentration
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "SUPPLY_CHAIN_WH"
                query: "SELECT supplier_id, spend_share_pct, country, risk_score FROM supplier_concentration WHERE material_group='{{material_group}}' ORDER BY spend_share_pct DESC"
            - name: get-supplier-status
              type: call
              call: ariba.get-supplier-risk
              with:
                material_group: "{{material_group}}"
            - name: post-alert
              type: call
              call: msteams.send-message
              with:
                channel_id: "supply-chain-risk"
                text: "Supply chain risk for {{material_group}}: Top supplier share {{get-concentration.top_share}}%. High-risk suppliers: {{get-supplier-status.high_risk_count}}."
  consumes:
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: ariba
      baseUri: "https://openapi.ariba.com/api/supplier-management/v1"
      authentication:
        type: bearer
        token: "$secrets.ariba_token"
      resources:
        - name: risk
          path: "/suppliers/risk"
          operations:
            - name: get-supplier-risk
              method: GET
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Triggers a Terraform Cloud workspace run to provision or update infrastructure, then posts run status to the DevOps Teams channel and creates a Jira tracking task.

naftiko: "0.5"
info:
  label: "Terraform Cloud Infrastructure Provisioning"
  description: "Triggers a Terraform Cloud workspace run to provision or update infrastructure, then posts run status to the DevOps Teams channel and creates a Jira tracking task."
  tags:
    - cloud
    - devops
    - terraform
    - jira
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: infra-provisioning
      port: 8080
      tools:
        - name: trigger-terraform-run
          description: "Given a Terraform Cloud workspace ID, trigger a new plan-and-apply run, create a Jira task to track the provisioning change, and post status to the DevOps Teams channel."
          inputParameters:
            - name: workspace_id
              type: string
              description: "Terraform Cloud workspace ID."
            - name: message
              type: string
              description: "Commit message or description of the infrastructure change."
            - name: teams_channel_id
              type: string
              description: "Teams channel ID for DevOps notifications."
          steps:
            - name: create-run
              type: call
              call: terraform.create-run
              with:
                workspaceId: "{{workspace_id}}"
                message: "{{message}}"
            - name: create-task
              type: call
              call: jira.create-issue
              with:
                project_key: "CLOUD"
                issuetype: "Task"
                summary: "Terraform run: {{message}}"
                description: "Workspace: {{workspace_id}} | Run ID: {{create-run.runId}}"
            - name: notify-team
              type: call
              call: msteams.post-channel-message
              with:
                channel_id: "{{teams_channel_id}}"
                text: "Terraform run triggered: {{message}} | Workspace: {{workspace_id}} | Jira: {{create-task.key}}"
  consumes:
    - type: http
      namespace: terraform
      baseUri: "https://app.terraform.io/api/v2"
      authentication:
        type: bearer
        token: "$secrets.terraform_token"
      resources:
        - name: runs
          path: "/runs"
          operations:
            - name: create-run
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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/devops/channels/{{channel_id}}/messages"
          inputParameters:
            - name: channel_id
              in: path
          operations:
            - name: post-channel-message
              method: POST

Pulls trade promotion data from Salesforce, correlates with actual sales from Snowflake, and generates an effectiveness report posted to Power BI and Teams.

naftiko: "0.5"
info:
  label: "Trade Promotion Effectiveness Report"
  description: "Pulls trade promotion data from Salesforce, correlates with actual sales from Snowflake, and generates an effectiveness report posted to Power BI and Teams."
  tags:
    - sales
    - marketing
    - salesforce
    - snowflake
    - power-bi
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: trade-analytics
      port: 8080
      tools:
        - name: generate-tpe-report
          description: "Generate a trade promotion effectiveness report by combining promotion data with sales results and publishing to Power BI."
          inputParameters:
            - name: promotion_id
              type: string
              description: "Salesforce trade promotion ID."
            - name: date_from
              type: string
              description: "Promotion start date."
            - name: date_to
              type: string
              description: "Promotion end date."
          steps:
            - name: get-promotion
              type: call
              call: salesforce.get-promotion
              with:
                promotion_id: "{{promotion_id}}"
            - name: get-sales-data
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "SALES_ANALYTICS_WH"
                query: "SELECT sum(revenue) as actual_revenue, sum(units) as actual_units FROM pos_sales WHERE promotion_id='{{promotion_id}}' AND sale_date BETWEEN '{{date_from}}' AND '{{date_to}}'"
            - name: refresh-report
              type: call
              call: powerbi.refresh-dataset
              with:
                datasetId: "trade-promotion-effectiveness"
            - name: notify-team
              type: call
              call: msteams.send-message
              with:
                channel_id: "trade-marketing"
                text: "TPE Report ready for promotion {{promotion_id}}: Actual revenue ${{get-sales-data.actual_revenue}} vs planned ${{get-promotion.planned_revenue}}."
  consumes:
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: promotions
          path: "/sobjects/Trade_Promotion__c/{{promotion_id}}"
          inputParameters:
            - name: promotion_id
              in: path
          operations:
            - name: get-promotion
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: datasets
          path: "/datasets/{{datasetId}}/refreshes"
          inputParameters:
            - name: datasetId
              in: path
          operations:
            - name: refresh-dataset
              method: POST
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST

Performs a three-way match between SAP purchase order, goods receipt, and vendor invoice, flagging discrepancies and routing to accounts payable via ServiceNow.

naftiko: "0.5"
info:
  label: "Vendor Invoice Three-Way Match"
  description: "Performs a three-way match between SAP purchase order, goods receipt, and vendor invoice, flagging discrepancies and routing to accounts payable via ServiceNow."
  tags:
    - finance
    - procurement
    - sap
    - servicenow
capability:
  exposes:
    - type: mcp
      namespace: ap-automation
      port: 8080
      tools:
        - name: three-way-match
          description: "Perform a three-way match for a vendor invoice by comparing PO, goods receipt, and invoice amounts, then routing exceptions."
          inputParameters:
            - name: invoice_number
              type: string
              description: "Vendor invoice number."
            - name: po_number
              type: string
              description: "SAP purchase order number."
          steps:
            - name: get-po
              type: call
              call: sap.get-purchase-order
              with:
                po_number: "{{po_number}}"
            - name: get-receipt
              type: call
              call: sap.get-goods-receipt
              with:
                po_number: "{{po_number}}"
            - name: get-invoice
              type: call
              call: sap.get-invoice
              with:
                invoice_number: "{{invoice_number}}"
            - name: create-exception
              type: call
              call: servicenow.create-incident
              with:
                short_description: "Invoice mismatch: {{invoice_number}} vs PO {{po_number}}"
                category: "accounts_payable"
                description: "PO amount: {{get-po.total_value}}. Receipt qty: {{get-receipt.quantity}}. Invoice amount: {{get-invoice.amount}}."
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-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: get-purchase-order
              method: GET
            - name: get-goods-receipt
              method: GET
            - name: get-invoice
              method: GET
    - type: http
      namespace: servicenow
      baseUri: "https://loreal.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

Analyzes warehouse utilization by querying SAP warehouse data, pulling demand forecasts from Snowflake, and generating a capacity report in Power BI.

naftiko: "0.5"
info:
  label: "Warehouse Capacity Planning Orchestrator"
  description: "Analyzes warehouse utilization by querying SAP warehouse data, pulling demand forecasts from Snowflake, and generating a capacity report in Power BI."
  tags:
    - supply-chain
    - logistics
    - sap
    - snowflake
    - power-bi
capability:
  exposes:
    - type: mcp
      namespace: warehouse-planning
      port: 8080
      tools:
        - name: plan-warehouse-capacity
          description: "Analyze warehouse capacity by combining current utilization with demand forecasts and refreshing the capacity planning dashboard."
          inputParameters:
            - name: warehouse_id
              type: string
              description: "SAP warehouse number."
            - name: planning_weeks
              type: number
              description: "Number of weeks to forecast."
          steps:
            - name: get-utilization
              type: call
              call: sap.get-warehouse-stock
              with:
                warehouse: "{{warehouse_id}}"
            - name: get-forecast
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "SUPPLY_CHAIN_WH"
                query: "SELECT week, forecasted_pallets FROM warehouse_demand_forecast WHERE warehouse_id='{{warehouse_id}}' AND weeks_ahead<={{planning_weeks}}"
            - name: refresh-dashboard
              type: call
              call: powerbi.refresh-dataset
              with:
                datasetId: "warehouse-capacity-planning"
  consumes:
    - type: http
      namespace: sap
      baseUri: "https://loreal-s4.sap.com/sap/opu/odata/sap/API_WAREHOUSE_STOCK_SRV"
      authentication:
        type: basic
        username: "$secrets.sap_user"
        password: "$secrets.sap_password"
      resources:
        - name: stock
          path: "/A_WarehouseStock"
          operations:
            - name: get-warehouse-stock
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: datasets
          path: "/datasets/{{datasetId}}/refreshes"
          inputParameters:
            - name: datasetId
              in: path
          operations:
            - name: refresh-dataset
              method: POST

Pulls current compensation data for an employee from Workday including base pay, bonus eligibility, and pay grade.

naftiko: "0.5"
info:
  label: "Workday Compensation Review Snapshot"
  description: "Pulls current compensation data for an employee from Workday including base pay, bonus eligibility, and pay grade."
  tags:
    - hr
    - compensation
    - workday
    - reporting
capability:
  exposes:
    - type: mcp
      namespace: hr-compensation
      port: 8080
      tools:
        - name: get-compensation-snapshot
          description: "Retrieve compensation details for a Workday employee including base salary, bonus target, and pay grade."
          inputParameters:
            - name: employee_id
              type: string
              description: "Workday employee ID."
          call: workday.get-compensation
          with:
            worker_id: "{{employee_id}}"
          outputParameters:
            - name: base_salary
              type: string
              mapping: "$.compensation.base_pay"
            - name: bonus_target
              type: string
              mapping: "$.compensation.bonus_target_percent"
            - name: pay_grade
              type: string
              mapping: "$.compensation.pay_grade"
  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: "/loreal/workers/{{worker_id}}/compensation"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-compensation
              method: GET

Generates workforce diversity metrics by pulling demographic data from Workday, enriching with analytics from Snowflake, and refreshing the Power BI diversity dashboard.

naftiko: "0.5"
info:
  label: "Workday Diversity Metrics Report Generator"
  description: "Generates workforce diversity metrics by pulling demographic data from Workday, enriching with analytics from Snowflake, and refreshing the Power BI diversity dashboard."
  tags:
    - hr
    - analytics
    - workday
    - snowflake
    - power-bi
capability:
  exposes:
    - type: mcp
      namespace: hr-analytics
      port: 8080
      tools:
        - name: generate-diversity-report
          description: "Generate workforce diversity metrics combining HR data with analytics and publishing to the dashboard."
          inputParameters:
            - name: business_unit
              type: string
              description: "Business unit for the report."
            - name: period
              type: string
              description: "Reporting period in YYYY-QN format."
          steps:
            - name: get-demographics
              type: call
              call: workday.get-demographics
              with:
                business_unit: "{{business_unit}}"
            - name: get-analytics
              type: call
              call: snowflake.execute-query
              with:
                warehouse: "HR_ANALYTICS_WH"
                query: "SELECT gender_pct, ethnicity_pct, leadership_diversity FROM diversity_metrics WHERE bu='{{business_unit}}' AND period='{{period}}'"
            - name: refresh-dashboard
              type: call
              call: powerbi.refresh-dataset
              with:
                datasetId: "diversity-inclusion-dashboard"
  consumes:
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: demographics
          path: "/loreal/workers/demographics"
          operations:
            - name: get-demographics
              method: GET
    - type: http
      namespace: snowflake
      baseUri: "https://loreal.snowflakecomputing.com/api/v2"
      authentication:
        type: bearer
        token: "$secrets.snowflake_token"
      resources:
        - name: statements
          path: "/statements"
          operations:
            - name: execute-query
              method: POST
    - type: http
      namespace: powerbi
      baseUri: "https://api.powerbi.com/v1.0/myorg"
      authentication:
        type: bearer
        token: "$secrets.powerbi_token"
      resources:
        - name: datasets
          path: "/datasets/{{datasetId}}/refreshes"
          inputParameters:
            - name: datasetId
              in: path
          operations:
            - name: refresh-dataset
              method: POST

Creates a new job requisition in Workday when a headcount request is approved and opens the corresponding Jira ticket for the recruiting team.

naftiko: "0.5"
info:
  label: "Workday Open Position Requisition"
  description: "Creates a new job requisition in Workday when a headcount request is approved and opens the corresponding Jira ticket for the recruiting team."
  tags:
    - hr
    - recruiting
    - workday
    - jira
capability:
  exposes:
    - type: mcp
      namespace: talent-acquisition
      port: 8080
      tools:
        - name: open-job-requisition
          description: "Given headcount request details, create a job requisition in Workday Recruiting and open a Jira ticket in the TA board to track sourcing progress."
          inputParameters:
            - name: job_title
              type: string
              description: "Job title for the open position."
            - name: department
              type: string
              description: "Department requesting the headcount."
            - name: hiring_manager_id
              type: string
              description: "Workday worker ID of the hiring manager."
          steps:
            - name: create-requisition
              type: call
              call: workday.create-job-requisition
              with:
                jobTitle: "{{job_title}}"
                department: "{{department}}"
                hiringManagerId: "{{hiring_manager_id}}"
            - name: create-ta-ticket
              type: call
              call: jira.create-issue
              with:
                project_key: "TA"
                issuetype: "Task"
                summary: "Recruit for: {{job_title}} ({{department}})"
                description: "Workday requisition: {{create-requisition.requisitionId}}"
  consumes:
    - type: http
      namespace: workday
      baseUri: "https://wd2-impl-services1.workday.com/ccx/api/v1"
      authentication:
        type: bearer
        token: "$secrets.workday_token"
      resources:
        - name: job-requisitions
          path: "/loreal/jobRequisitions"
          operations:
            - name: create-job-requisition
              method: POST
    - type: http
      namespace: jira
      baseUri: "https://loreal.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

When an employee changes roles in Workday, updates their Okta group assignments, adjusts Microsoft 365 license, and notifies the employee and manager via Teams.

naftiko: "0.5"
info:
  label: "Workday Role Change Provisioning"
  description: "When an employee changes roles in Workday, updates their Okta group assignments, adjusts Microsoft 365 license, and notifies the employee and manager via Teams."
  tags:
    - hr
    - identity
    - workday
    - okta
    - access-management
capability:
  exposes:
    - type: mcp
      namespace: hr-identity
      port: 8080
      tools:
        - name: sync-role-change
          description: "Given a Workday employee ID and new role details, update Okta group memberships to reflect the new role, adjust Microsoft 365 license tier, and notify both the employee and their new manager via Teams."
          inputParameters:
            - name: employee_id
              type: string
              description: "Workday worker ID."
            - name: new_role
              type: string
              description: "New job role or title."
            - name: okta_new_group_id
              type: string
              description: "Okta group ID for the new role."
            - name: okta_old_group_id
              type: string
              description: "Okta group ID of the previous role to remove."
          steps:
            - name: get-worker
              type: call
              call: workday.get-worker
              with:
                worker_id: "{{employee_id}}"
            - name: remove-old-group
              type: call
              call: okta.remove-user-from-group
              with:
                groupId: "{{okta_old_group_id}}"
                userId: "{{get-worker.work_email}}"
            - name: add-new-group
              type: call
              call: okta.add-user-to-group
              with:
                groupId: "{{okta_new_group_id}}"
                userId: "{{get-worker.work_email}}"
            - name: notify-employee
              type: call
              call: msteams.send-message
              with:
                recipient_upn: "{{get-worker.work_email}}"
                text: "Your role has been updated to {{new_role}}. System access has been adjusted accordingly."
  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: "/loreal/workers/{{worker_id}}"
          inputParameters:
            - name: worker_id
              in: path
          operations:
            - name: get-worker
              method: GET
    - type: http
      namespace: okta
      baseUri: "https://loreal.okta.com/api/v1"
      authentication:
        type: apikey
        key: "Authorization"
        value: "$secrets.okta_api_token"
        placement: header
      resources:
        - name: group-members
          path: "/groups/{{groupId}}/users/{{userId}}"
          inputParameters:
            - name: groupId
              in: path
            - name: userId
              in: path
          operations:
            - name: remove-user-from-group
              method: DELETE
            - name: add-user-to-group
              method: PUT
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: chats
          path: "/chats"
          operations:
            - name: send-message
              method: POST

Pulls YouTube channel analytics, compares with campaign targets in Salesforce, and posts a performance digest to the marketing Teams channel.

naftiko: "0.5"
info:
  label: "YouTube Brand Channel Performance Digest"
  description: "Pulls YouTube channel analytics, compares with campaign targets in Salesforce, and posts a performance digest to the marketing Teams channel."
  tags:
    - marketing
    - social
    - youtube
    - salesforce
    - microsoft-teams
capability:
  exposes:
    - type: mcp
      namespace: video-analytics
      port: 8080
      tools:
        - name: generate-youtube-digest
          description: "Generate a YouTube brand channel performance digest by combining analytics with campaign targets."
          inputParameters:
            - name: channel_id
              type: string
              description: "YouTube channel ID."
            - name: campaign_id
              type: string
              description: "Salesforce campaign ID."
          steps:
            - name: get-channel-stats
              type: call
              call: youtube.get-channel-analytics
              with:
                channel_id: "{{channel_id}}"
            - name: get-campaign-targets
              type: call
              call: salesforce.get-campaign
              with:
                campaign_id: "{{campaign_id}}"
            - name: post-digest
              type: call
              call: msteams.send-message
              with:
                channel_id: "marketing-digital"
                text: "YouTube digest: Views {{get-channel-stats.views}}, Subs {{get-channel-stats.subscribers}}. Target views: {{get-campaign-targets.video_target}}."
  consumes:
    - type: http
      namespace: youtube
      baseUri: "https://www.googleapis.com/youtube/v3"
      authentication:
        type: bearer
        token: "$secrets.google_youtube_token"
      resources:
        - name: analytics
          path: "/channels"
          operations:
            - name: get-channel-analytics
              method: GET
    - type: http
      namespace: salesforce
      baseUri: "https://loreal.my.salesforce.com/services/data/v58.0"
      authentication:
        type: bearer
        token: "$secrets.salesforce_token"
      resources:
        - name: campaigns
          path: "/sobjects/Campaign/{{campaign_id}}"
          inputParameters:
            - name: campaign_id
              in: path
          operations:
            - name: get-campaign
              method: GET
    - type: http
      namespace: msteams
      baseUri: "https://graph.microsoft.com/v1.0"
      authentication:
        type: bearer
        token: "$secrets.msgraph_token"
      resources:
        - name: messages
          path: "/teams/channels/messages"
          operations:
            - name: send-message
              method: POST