From 008d12200abc1adac471ea7211204b7aa39b7e59 Mon Sep 17 00:00:00 2001 From: gokul-aot Date: Thu, 9 Jul 2026 20:31:46 +0530 Subject: [PATCH] Add mcp-builder YAML configs for Slack and Salesforce Signed-off-by: gokul-aot --- mcp-builder-files/salesforce.yaml | 319 ++++++++++++++++++++ mcp-builder-files/salesforce_openapi.yaml | 351 ++++++++++++++++++++++ mcp-builder-files/slack.yaml | 114 +++++++ mcp-builder-files/slack_openapi.yaml | 168 +++++++++++ 4 files changed, 952 insertions(+) create mode 100644 mcp-builder-files/salesforce.yaml create mode 100644 mcp-builder-files/salesforce_openapi.yaml create mode 100644 mcp-builder-files/slack.yaml create mode 100644 mcp-builder-files/slack_openapi.yaml diff --git a/mcp-builder-files/salesforce.yaml b/mcp-builder-files/salesforce.yaml new file mode 100644 index 0000000..496be12 --- /dev/null +++ b/mcp-builder-files/salesforce.yaml @@ -0,0 +1,319 @@ +## +## SPDX-FileCopyrightText: 2026 AOT Technologies +## SPDX-License-Identifier: Apache-2.0 +## + +version: "1" + +server: + name: salesforce + description: "Salesforce MCP server for Lead and Contact CRUD via REST API" + +spec: + source: "e2e/fixtures/real/salesforce_openapi.yaml" + format: openapi3 + base_url: "https://orgfarm-2dddaa3446-dev-ed.develop.my.salesforce.com" + total_endpoints: 8 + scoped_endpoints: 8 + +workflows: + - "Sales reps create and qualify new leads in the CRM" + - "CRM users read and update contact records tied to accounts" + - "Admins delete stale leads or contacts by record ID" + +groups: + - name: leads + description: "Lead record creation, retrieval, update, and deletion" + tools: + - tool_name: create_lead + endpoint: POST /services/data/v58.0/sobjects/Lead + description: > + Create a new Lead in Salesforce. Requires LastName and Company. + Returns the new record ID on success. Use Salesforce API field names + (e.g. LastName, Company, Email) in the request body. + response_kind: json + parameters: + - name: LastName + description: "Lead last name (required by Salesforce)." + required: true + location: body + - name: Company + description: "Company name for the lead (required by Salesforce)." + required: true + location: body + - name: FirstName + description: "Lead first name." + required: false + location: body + - name: Title + description: "Job title." + required: false + location: body + - name: Email + description: "Email address." + required: false + location: body + - name: Phone + description: "Primary phone number." + required: false + location: body + - name: MobilePhone + description: "Mobile phone number." + required: false + location: body + - name: Street + description: "Street address." + required: false + location: body + - name: City + description: "City." + required: false + location: body + - name: State + description: "State or province." + required: false + location: body + - name: PostalCode + description: "Postal or ZIP code." + required: false + location: body + - name: Country + description: "Country." + required: false + location: body + - name: Description + description: "Free-text description of the lead." + required: false + location: body + - name: LeadSource + description: "Source of the lead (e.g. Web, Phone Inquiry)." + required: false + location: body + - name: Status + description: "Lead status (e.g. Open - Not Contacted)." + required: false + location: body + - name: Rating + description: "Lead rating (e.g. Hot, Warm, Cold)." + required: false + location: body + - name: Website + description: "Company or personal website URL." + required: false + location: body + - name: NumberOfEmployees + description: "Number of employees at the company." + required: false + location: body + - name: Industry + description: "Industry sector." + required: false + location: body + - name: AnnualRevenue + description: "Annual revenue for the company." + required: false + location: body + hints: + - "Instance URL is org-specific — configure at deploy time." + - "Field names must use Salesforce API names (PascalCase)." + + - tool_name: read_lead + endpoint: GET /services/data/v58.0/sobjects/Lead/{id} + description: > + Retrieve a Lead record by Salesforce ID. Returns all accessible + field values for the lead. Record IDs are 15 or 18 alphanumeric + characters. + response_kind: json + parameters: + - name: id + description: "Salesforce Lead record ID (15 or 18 alphanumeric characters)." + required: true + location: path + hints: + - "Record ID format: 15 or 18 alphanumeric characters." + + - tool_name: update_lead + endpoint: PATCH /services/data/v58.0/sobjects/Lead/{id} + description: > + Update fields on an existing Lead. Provide at least one field to + change. Uses Salesforce API field names (FirstName, LastName, + Company, Email). + response_kind: json + parameters: + - name: id + description: "Salesforce Lead record ID to update." + required: true + location: path + - name: FirstName + description: "Updated first name." + required: false + location: body + - name: LastName + description: "Updated last name." + required: false + location: body + - name: Company + description: "Updated company name." + required: false + location: body + - name: Email + description: "Updated email address." + required: false + location: body + hints: + - "At least one body field must be provided for the update." + - "Returns 204 No Content on success when no body is returned." + + - tool_name: delete_lead + endpoint: DELETE /services/data/v58.0/sobjects/Lead/{id} + description: > + Permanently delete a Lead record by ID. This action cannot be undone + unless your org has a recycle bin retention policy. + response_kind: json + parameters: + - name: id + description: "Salesforce Lead record ID to delete." + required: true + location: path + hints: + - "Returns 204 No Content on success." + + - name: contacts + description: "Contact record creation, retrieval, update, and deletion" + tools: + - tool_name: create_contact + endpoint: POST /services/data/v58.0/sobjects/Contact + description: > + Create a new Contact in Salesforce. Requires LastName. Optionally + link to an Account via AccountId. Returns the new record ID on + success. + response_kind: json + parameters: + - name: LastName + description: "Contact last name (required by Salesforce)." + required: true + location: body + - name: FirstName + description: "Contact first name." + required: false + location: body + - name: AccountId + description: > + Salesforce Account ID to associate the contact with (15 or 18 + alphanumeric characters). + required: false + location: body + - name: Title + description: "Job title." + required: false + location: body + - name: Email + description: "Email address." + required: false + location: body + - name: Phone + description: "Primary phone number." + required: false + location: body + - name: MobilePhone + description: "Mobile phone number." + required: false + location: body + - name: MailingStreet + description: "Mailing street address." + required: false + location: body + - name: MailingCity + description: "Mailing city." + required: false + location: body + - name: MailingState + description: "Mailing state or province." + required: false + location: body + - name: MailingPostalCode + description: "Mailing postal or ZIP code." + required: false + location: body + - name: MailingCountry + description: "Mailing country." + required: false + location: body + - name: Description + description: "Free-text description." + required: false + location: body + - name: LeadSource + description: "Source of the contact." + required: false + location: body + - name: Department + description: "Department name." + required: false + location: body + hints: + - "AccountId must be a valid Salesforce Account record ID if provided." + + - tool_name: read_contact + endpoint: GET /services/data/v58.0/sobjects/Contact/{id} + description: > + Retrieve a Contact record by Salesforce ID. Returns all accessible + field values including account linkage when present. + response_kind: json + parameters: + - name: id + description: "Salesforce Contact record ID (15 or 18 alphanumeric characters)." + required: true + location: path + + - tool_name: update_contact + endpoint: PATCH /services/data/v58.0/sobjects/Contact/{id} + description: > + Update fields on an existing Contact. Provide at least one field to + change. AccountId links the contact to a different account when + provided. + response_kind: json + parameters: + - name: id + description: "Salesforce Contact record ID to update." + required: true + location: path + - name: FirstName + description: "Updated first name." + required: false + location: body + - name: LastName + description: "Updated last name." + required: false + location: body + - name: Email + description: "Updated email address." + required: false + location: body + - name: AccountId + description: "Updated Account ID to associate with this contact." + required: false + location: body + hints: + - "At least one body field must be provided for the update." + + - tool_name: delete_contact + endpoint: DELETE /services/data/v58.0/sobjects/Contact/{id} + description: > + Permanently delete a Contact record by ID. This action cannot be + undone unless your org has a recycle bin retention policy. + response_kind: json + parameters: + - name: id + description: "Salesforce Contact record ID to delete." + required: true + location: path + +auth: + type: api_key + notes: > + Salesforce REST API expects a Bearer access token in the Authorization + header. Token refresh (OAuth2 refresh_token grant) must be handled + outside this MCP server — e.g. ToolHive secret injection or an external + token service. Set the org instance URL via server configuration at + deploy time (base_url is org-specific). diff --git a/mcp-builder-files/salesforce_openapi.yaml b/mcp-builder-files/salesforce_openapi.yaml new file mode 100644 index 0000000..101101c --- /dev/null +++ b/mcp-builder-files/salesforce_openapi.yaml @@ -0,0 +1,351 @@ +## +## SPDX-FileCopyrightText: 2026 AOT Technologies +## SPDX-License-Identifier: Apache-2.0 +## + +openapi: "3.0.3" +info: + title: Salesforce sObject REST API (Lead/Contact subset) + description: > + Minimal OpenAPI 3.0 spec for Lead and Contact CRUD via Salesforce REST API v58.0.1 + Handcrafted to mirror the node-wire Salesforce connector actions. + version: v58.0 + +servers: + - url: https://your-instance.my.salesforce.com + description: Salesforce org instance URL (org-specific) + +paths: + /services/data/v58.0/sobjects/Lead: + post: + operationId: createLead + summary: Create a Lead record + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/LeadCreate" + responses: + "201": + description: Lead created + content: + application/json: + schema: + $ref: "#/components/schemas/CreateResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + + /services/data/v58.0/sobjects/Lead/{id}: + get: + operationId: readLead + summary: Retrieve a Lead record by ID + parameters: + - $ref: "#/components/parameters/RecordId" + responses: + "200": + description: Lead record + content: + application/json: + schema: + $ref: "#/components/schemas/SObjectRecord" + "404": + description: Record not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + patch: + operationId: updateLead + summary: Update a Lead record + parameters: + - $ref: "#/components/parameters/RecordId" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/LeadUpdate" + responses: + "204": + description: Lead updated + "200": + description: Lead updated with body + content: + application/json: + schema: + $ref: "#/components/schemas/CreateResponse" + "404": + description: Record not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + delete: + operationId: deleteLead + summary: Delete a Lead record + parameters: + - $ref: "#/components/parameters/RecordId" + responses: + "204": + description: Lead deleted + "404": + description: Record not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + + /services/data/v58.0/sobjects/Contact: + post: + operationId: createContact + summary: Create a Contact record + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/ContactCreate" + responses: + "201": + description: Contact created + content: + application/json: + schema: + $ref: "#/components/schemas/CreateResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + + /services/data/v58.0/sobjects/Contact/{id}: + get: + operationId: readContact + summary: Retrieve a Contact record by ID + parameters: + - $ref: "#/components/parameters/RecordId" + responses: + "200": + description: Contact record + content: + application/json: + schema: + $ref: "#/components/schemas/SObjectRecord" + "404": + description: Record not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + patch: + operationId: updateContact + summary: Update a Contact record + parameters: + - $ref: "#/components/parameters/RecordId" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/ContactUpdate" + responses: + "204": + description: Contact updated + "200": + description: Contact updated with body + content: + application/json: + schema: + $ref: "#/components/schemas/CreateResponse" + "404": + description: Record not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + delete: + operationId: deleteContact + summary: Delete a Contact record + parameters: + - $ref: "#/components/parameters/RecordId" + responses: + "204": + description: Contact deleted + "404": + description: Record not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + +components: + parameters: + RecordId: + name: id + in: path + required: true + description: Salesforce record ID (15 or 18 alphanumeric characters) + schema: + type: string + pattern: "^[a-zA-Z0-9]{15,18}$" + + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: OAuth 2.0 access token for the Salesforce org + + schemas: + LeadCreate: + type: object + required: + - LastName + - Company + properties: + FirstName: + type: string + LastName: + type: string + Company: + type: string + Title: + type: string + Email: + type: string + format: email + Phone: + type: string + MobilePhone: + type: string + Street: + type: string + City: + type: string + State: + type: string + PostalCode: + type: string + Country: + type: string + Description: + type: string + LeadSource: + type: string + Status: + type: string + Rating: + type: string + Website: + type: string + NumberOfEmployees: + type: integer + Industry: + type: string + AnnualRevenue: + type: number + format: double + + LeadUpdate: + type: object + properties: + FirstName: + type: string + LastName: + type: string + Company: + type: string + Email: + type: string + format: email + + ContactCreate: + type: object + required: + - LastName + properties: + FirstName: + type: string + LastName: + type: string + AccountId: + type: string + pattern: "^[a-zA-Z0-9]{15,18}$" + Title: + type: string + Email: + type: string + format: email + Phone: + type: string + MobilePhone: + type: string + MailingStreet: + type: string + MailingCity: + type: string + MailingState: + type: string + MailingPostalCode: + type: string + MailingCountry: + type: string + Description: + type: string + LeadSource: + type: string + Department: + type: string + + ContactUpdate: + type: object + properties: + FirstName: + type: string + LastName: + type: string + Email: + type: string + format: email + AccountId: + type: string + pattern: "^[a-zA-Z0-9]{15,18}$" + + CreateResponse: + type: object + properties: + id: + type: string + success: + type: boolean + errors: + type: array + items: + type: object + + SObjectRecord: + type: object + additionalProperties: true + description: Salesforce sObject record with attributes and field values + + ErrorResponse: + type: array + items: + type: object + properties: + message: + type: string + errorCode: + type: string + fields: + type: array + items: + type: string + +security: + - bearerAuth: [] diff --git a/mcp-builder-files/slack.yaml b/mcp-builder-files/slack.yaml new file mode 100644 index 0000000..f6cb3a9 --- /dev/null +++ b/mcp-builder-files/slack.yaml @@ -0,0 +1,114 @@ +## +## SPDX-FileCopyrightText: 2026 AOT Technologies +## SPDX-License-Identifier: Apache-2.0 +## + +version: "1" + +server: + name: slack + description: "Slack MCP server for posting messages and uploading files (node-wire connector subset)" + +spec: + source: "e2e/fixtures/real/slack_openapi.yaml" + format: openapi3 + base_url: "https://slack.com/api" + total_endpoints: 3 + scoped_endpoints: 3 + +workflows: + - "Team members post status updates and announcements to Slack channels" + - "Support agents send direct messages to users" + - "Bots upload files to channels with the external upload API" + +groups: + - name: messaging + description: "Post messages to channels and direct messages" + tools: + - tool_name: post_message + endpoint: POST /chat.postMessage + description: > + Send a message to a Slack channel. Target can be a channel ID (C…), + channel name (#general), or user ID (U…). Supports plain text and + optional Block Kit blocks. The authenticated bot appears as the + message author. + response_kind: json + parameters: + - name: channel + description: > + Target channel ID (C…), channel name (#general), or user ID (U…). + required: true + location: body + - name: text + description: > + Plain-text message body (mrkdwn supported). Maps to the node-wire + connector "message" field. + required: true + location: body + - name: blocks + description: > + Optional Block Kit blocks as a JSON array. Omit for text-only + messages. + required: false + location: body + hints: + - "Requires chat:write scope on the Slack bot token." + - "Channel names like #general are accepted; uploads require channel IDs." + + - tool_name: send_direct_message + endpoint: POST /chat.postMessage + description: > + Send a direct message to a Slack user. Uses the same chat.postMessage + API as post_message; provide a user ID (U…) or DM channel ID (D…). + Supports plain text and optional Block Kit blocks. + response_kind: json + parameters: + - name: channel + description: > + Target user ID (U…), DM channel ID (D…), or channel name. + required: true + location: body + - name: text + description: "Plain-text DM body (mrkdwn supported)." + required: true + location: body + - name: blocks + description: "Optional Block Kit blocks as a JSON array." + required: false + location: body + hints: + - "Requires im:write or chat:write scope depending on workspace policy." + - "node-wire resolves user IDs to DM channel IDs via conversations.open." + + - name: files + description: "File upload via Slack external upload API" + tools: + - tool_name: upload_file + endpoint: POST /files.getUploadURLExternal + description: > + Request an external upload URL from Slack (step 1 of 3). Provide + filename and file size in bytes. Returns upload_url and file_id; + bytes must be uploaded to upload_url separately, then finalized + with files.completeUploadExternal. For the full automated upload + flow including base64 content, use the node-wire nw-slack connector. + response_kind: json + parameters: + - name: filename + description: "Display name for the file being uploaded." + required: true + location: body + - name: length + description: "File size in bytes." + required: true + location: body + hints: + - "Thin MCP proxy: only performs getUploadURLExternal, not the full 3-step flow." + - "node-wire upload_file accepts content_base64 or filepath under NW_SLACK_ATTACHMENTS_DIR." + - "Channel ID (C/G/D/Z…) is required for sharing after upload completes." + +auth: + type: api_key + notes: > + Slack Web API expects a Bearer bot token (xoxb-…) in the Authorization + header. Set SLACK_BOT_TOKEN via ToolHive secret injection or pass the + token from MCP Inspector. Token is never stored by this MCP server. diff --git a/mcp-builder-files/slack_openapi.yaml b/mcp-builder-files/slack_openapi.yaml new file mode 100644 index 0000000..51903d5 --- /dev/null +++ b/mcp-builder-files/slack_openapi.yaml @@ -0,0 +1,168 @@ +## +## SPDX-FileCopyrightText: 2026 AOT Technologies +## SPDX-License-Identifier: Apache-2.0 +## + +openapi: "3.0.3" +info: + title: Slack Web API (node-wire connector subset) + description: > + Minimal OpenAPI 3.0 spec for post_message, send_direct_message, and + upload_file actions mirrored from the node-wire Slack connector. + version: "1.0.0" + +servers: + - url: https://slack.com/api + description: Slack Web API base URL + +paths: + /chat.postMessage: + post: + operationId: chatPostMessage + summary: Post a message to a channel or DM + description: > + Sends a message to a channel ID, user ID, or channel name. Used by + both post_message and send_direct_message in the node-wire connector. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/ChatPostMessageRequest" + responses: + "200": + description: Slack API response + content: + application/json: + schema: + $ref: "#/components/schemas/SlackApiResponse" + + /files.getUploadURLExternal: + post: + operationId: filesGetUploadURLExternal + summary: Step 1 of external file upload — get upload URL + description: > + Returns a pre-signed upload_url and file_id for the external upload + flow. The node-wire connector chains this with a byte upload and + files.completeUploadExternal. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/GetUploadUrlRequest" + responses: + "200": + description: Slack API response with upload_url and file_id + content: + application/json: + schema: + $ref: "#/components/schemas/GetUploadUrlResponse" + + /files.completeUploadExternal: + post: + operationId: filesCompleteUploadExternal + summary: Step 3 of external file upload — finalize and share + description: > + Finalizes an external upload and optionally shares the file to a + channel. Requires file_id from files.getUploadURLExternal. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CompleteUploadRequest" + responses: + "200": + description: Slack API response + content: + application/json: + schema: + $ref: "#/components/schemas/SlackApiResponse" + +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: Slack Bot Token (xoxb-…) + + schemas: + ChatPostMessageRequest: + type: object + required: + - channel + - text + properties: + channel: + type: string + description: Channel ID (C…), user ID (U…), or channel name (#general). + text: + type: string + description: Plain-text message (mrkdwn supported). + blocks: + type: array + description: Optional Block Kit blocks array. + items: + type: object + additionalProperties: true + + GetUploadUrlRequest: + type: object + required: + - filename + - length + properties: + filename: + type: string + description: Display filename for the upload. + length: + type: integer + description: File size in bytes. + minimum: 1 + + GetUploadUrlResponse: + type: object + properties: + ok: + type: boolean + upload_url: + type: string + file_id: + type: string + error: + type: string + + CompleteUploadRequest: + type: object + required: + - files + - channel_id + properties: + files: + type: string + description: > + JSON-encoded array of file objects, e.g. + [{"id":"F123","title":"report.pdf"}]. + channel_id: + type: string + description: Channel ID (C/G/D/Z…) to share the file with. + initial_comment: + type: string + description: Message posted alongside the file. + + SlackApiResponse: + type: object + additionalProperties: true + properties: + ok: + type: boolean + error: + type: string + ts: + type: string + channel: + type: string + +security: + - bearerAuth: []