Skip to content

Latest commit

 

History

History

openapi-mcp-server

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Twilio AlphaTwilio Alpha

OpenAPI MCP Server

This is a Proof of Concept (PoC) project by the ETI team, exploring the use of Model Context Protocol (MCP) for the exchange of model context information between different tools.

Prerequisites

  • Node.js 18 or higher
  • npm 9 or higher
  • A Twilio account with API credentials

Getting Started

The easiest way to get started is to edit the configuration of your client to point to the MCP server using npx.

{
  "mcpServers": {
    "twilio": {
      "command": "npx",
      "args": [
        "-y",
        "@twilio-alpha/openapi-mcp-server",
        "--apiPath",
        "<PATH_TO_OPEN_API_YAML_DIR>",
        "--username",
        "YOUR_USERNAME",
        "--password",
        "YOUR_PASSWORD"
      ]
    }
  }
}

Security Recommendations

To guard against injection attacks that may allow untrusted systems access to your Twilio data, the ETI team advises users of Twilio MCP servers to avoid installing or running any community MCP servers alongside our official ones. Doing so helps ensure that only trusted MCP servers have access to tools interacting with your Twilio account, reducing the risk of unauthorized data access.

Configuration Parameters

You can pass the following optional parameters to the mcp server:

--username / --password (optional)

If provided, the username/password will be used as basic-auth authentication with the API calls.

--services (optional)

The name of the services you want to use - this corresponds to the individual filename inside the directory of your OpenAPI yaml files.

--tags (optional)

The tag name as defined in each of the individual endpoints. If you want to filter by tags only, make sure you pass --services '' as an empty object.

Custom Server

First, install the package in your repo:

# Clone the repository
npm install @twilio-alpha/openapi-mcp-server --save

Then you can extend OpenAPIMCPServer:

import {
  OpenAPIMCPServer,
  OpenAPIMCPServerConfiguration,
} from '@twilio-alpha/openapi-mcp-server';

class CustomOpenAPIServer extends OpenAPIMCPServer {
  constructor(config: OpenAPIMCPServerConfiguration) {
    super({
      // these are required
      server: config.server,
      openAPIDir: '/path/to/openapi/yaml',

      // These are optional
      filters: config.filters,
      authorization: {
        type: 'BasicAuth',
        username: config.credentials.apiKey,
        password: config.credentials.apiSecret,
      },
    });

    // perform any other option
  }
}

const server = new CustomOpenAPIServer({ ... });
const transport = new StdioServerTransport();
await server.start(transport);
logger.info('MCP Server running on stdio');

loadCapabilities() => Promise

Use this method to load/modify any additional capabilities, such as making change to the default tools or adding resources.

Note: To enable resources, include

const configuration = {
  server: {
    name: config.server.name,
    version: config.server.version,
    capabilities: {
      resources: {},
      tools: {},
    },
  }
}

Example

/**
 * Loads resources for the server
 * @returns
 */
protected async loadCapabilities(): Promise<void> {
  this.resources.push({
    uri: 'text://accountSid',
    name: 'Twilio AccountSid',
    description: 'The account SID for the Twilio account',
  });

  this.prompts.set('userSid', {
    name: 'Twilio UserSid',
    description: 'The UserSid for the Twilio account',
    arguments: [
      {
        name: 'userSid'
        description: 'The UserSid for the Twilio account',
        required: true,
      },
    ],
  });

  // Modify anything else here
}

callToolBody(tool: Tool, api: API, body: Record<string, unknown>) => Record<string, unknown>

This method can be used to modify the body of the request before an API call is made.

callToolResponse(httpResponse: HttpResponse, response: CallToolResponse,) => CallToolResponse

This method can be used to modify the response of the API call before it is sent back to the client.

handleReadResource(request: ReadResourceRequest) => Promise

Use this method to handle Resource loading.

Example

/**
 * Handles read resource requests
 * @param request
 * @returns
 */
protected async handleReadResource(
  request: ReadResourceRequest,
): Promise<ReadResourceResult> {
  const { uri, name } = request.params;
  if (uri === 'text://accountSid') {
    return {
      contents: [
        {
          uri,
          name,
          mimeType: 'text/plain',
          text: `The Twilio accountSid is ${this.config.accountSid}`,
        },
      ],
    };
  }

  throw new Error(`Resource ${name} not found`);
}

For more information see resources#example-implementation

protected async handleGetPrompt(request: GetPromptRequest) => Promise

/**
 * Handles the get prompt request
 * @param request the request to handle
 */
protected async handleGetPrompt(
  request: GetPromptRequest,
): Promise<GetPromptResult> {
  const { name, arguments } = request.params;
  if (name === 'twilio-userSid') {
    return {
      messages: [
        {
          role: 'user',
          content: {
            type: 'text',
            text: `The Twilio UserSid is ${arguments.userSid}`,
          },
        },
      ],
    };
  }

  throw new Error(`Prompt ${name} not found`);
}

For more information see prompts#example-implementation