diff --git a/docs/my-website/docs/mcp_openapi.md b/docs/my-website/docs/mcp_openapi.md index 0ac90dc12e9..0f18ecc127a 100644 --- a/docs/my-website/docs/mcp_openapi.md +++ b/docs/my-website/docs/mcp_openapi.md @@ -1,30 +1,28 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +import Image from '@theme/IdealImage'; # MCP from OpenAPI Specs -LiteLLM can automatically convert OpenAPI specifications into MCP servers, exposing any REST API as MCP tools without writing custom MCP server code. +LiteLLM can convert any OpenAPI/Swagger spec into an MCP server — no custom MCP server code required. -## Adding an OpenAPI MCP Server +## Step 1 — Add the MCP Server -Add your OpenAPI-based MCP server in `config.yaml`: +Add your OpenAPI-based server in `config.yaml`: ```yaml title="config.yaml" showLineNumbers mcp_servers: - # OpenAPI Spec Example - Petstore API petstore_mcp: url: "https://petstore.swagger.io/v2" spec_path: "/path/to/openapi.json" auth_type: "none" - # OpenAPI Spec with API Key Authentication my_api_mcp: url: "http://0.0.0.0:8090" spec_path: "/path/to/openapi.json" auth_type: "api_key" auth_value: "your-api-key-here" - # OpenAPI Spec with Bearer Token secured_api_mcp: url: "https://api.example.com" spec_path: "/path/to/openapi.json" @@ -32,21 +30,117 @@ mcp_servers: auth_value: "your-bearer-token" ``` +Or from the UI: go to **MCP Servers → Add New MCP Server**, fill in the URL and spec path, and LiteLLM will fetch the spec and load all endpoints as tools. + **Configuration parameters:** | Parameter | Required | Description | |-----------|----------|-------------| -| `url` | Yes | Base URL of your API endpoint | -| `spec_path` | Yes | Path or URL to your OpenAPI spec file (JSON or YAML) | +| `url` | Yes | Base URL of your API | +| `spec_path` | Yes | Path or URL to your OpenAPI spec (JSON or YAML) | | `auth_type` | No | `none`, `api_key`, `bearer_token`, `basic`, `authorization`, `oauth2` | | `auth_value` | No | Auth value (required if `auth_type` is set) | -| `description` | No | Optional description for the MCP server | -| `allowed_tools` | No | List of specific tools to allow | -| `disallowed_tools` | No | List of specific tools to block | +| `description` | No | Optional description | +| `allowed_tools` | No | Allowlist of specific tools | +| `disallowed_tools` | No | Blocklist of specific tools | -**Supported OpenAPI versions:** 3.0.x, 3.1.x, Swagger 2.0 +**Supported spec versions:** OpenAPI 3.0.x, 3.1.x, Swagger 2.0. Each operation's `operationId` becomes the tool name — make sure they're unique. -Each operation's `operationId` becomes the MCP tool name, so make sure your spec has unique `operationId` values. +Once tools are loaded, you'll see them in the Tool Configuration section: + + + +
+ +## Step 2 — Optionally Override Tool Names and Descriptions + +By default, tool names and descriptions come from the `operationId` and description fields in your spec. You can rename or rewrite them so MCP clients see something cleaner — without touching the upstream spec. + +### From the UI + +Each tool card has a pencil icon. Click it to open the inline editor: + + + +
+ +- **Display Name** — overrides the name MCP clients see +- **Description** — overrides the description MCP clients see +- Leave a field blank to keep the original from the spec + +After setting overrides, a purple **Custom name** badge appears on the tool card: + + + +
+ +### From the API + +Pass `tool_name_to_display_name` and `tool_name_to_description` in the create or update request: + +```bash title="Create server with tool name overrides" showLineNumbers +curl -X POST http://localhost:4000/v1/mcp/server \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "petstore_mcp", + "url": "https://petstore.swagger.io/v2", + "spec_path": "/path/to/openapi.json", + "tool_name_to_display_name": { + "getPetById": "Get Pet", + "findPetsByStatus": "List Available Pets" + }, + "tool_name_to_description": { + "getPetById": "Look up a pet by its ID", + "findPetsByStatus": "Returns all pets matching a given status (available, pending, sold)" + } + }' +``` + +```bash title="Update overrides on an existing server" showLineNumbers +curl -X PUT http://localhost:4000/v1/mcp/server/{server_id} \ + -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "tool_name_to_display_name": { + "getPetById": "Get Pet" + }, + "tool_name_to_description": { + "getPetById": "Look up a pet by its ID" + } + }' +``` + +The map key is the **original `operationId`** from the spec — not the prefixed tool name. LiteLLM strips the server prefix before doing the lookup. + +For example, if your server is `petstore_mcp`, the tool is exposed as `petstore_mcp-getPetById`. The map key is still `getPetById`. + +**Before and after:** + +``` +# Without overrides +Tool: "petstore_mcp-getPetById" +Description: "Returns a single pet" + +Tool: "petstore_mcp-findPetsByStatus" +Description: "Finds Pets by status" + +# After overrides +Tool: "Get Pet" +Description: "Look up a pet by its ID" + +Tool: "List Available Pets" +Description: "Returns all pets matching a given status (available, pending, sold)" +``` ## Using the Server @@ -76,7 +170,7 @@ async def main(): print(f"Available tools: {[tool.name for tool in tools]}") response = await client.call_tool( - name="getpetbyid", + name="Get Pet", # overridden name arguments={"petId": "1"} ) print(f"Response: {response}") @@ -123,110 +217,10 @@ curl --location 'https://api.openai.com/v1/responses' \ } } ], - "input": "Find all available pets in the petstore", + "input": "Find all available pets", "tool_choice": "required" }' ``` - -## Overriding Tool Names and Descriptions - -By default, tool names and descriptions come directly from the `operationId` and description fields in your OpenAPI spec. You can override these per-server so MCP clients see friendlier names and clearer descriptions — without touching the upstream spec. - -This is useful when: -- The spec uses machine-generated `operationId` values like `getPetById_v2_deprecated` -- You want to simplify descriptions for your team -- You're exposing the same API to multiple audiences with different naming conventions - -### Via the UI - -When adding or editing an MCP server in the LiteLLM UI, each tool card in the **Tool Configuration** section has a pencil icon. Click it to open an inline edit panel: - -- **Display Name** — overrides the tool name shown to MCP clients -- **Description** — overrides the tool description shown to MCP clients - -A purple **Custom name** badge appears on any tool with an active override. Leave a field blank to keep the original value from the spec. - -### Via the API - -Pass `tool_name_to_display_name` and `tool_name_to_description` when creating or updating an MCP server: - -```bash title="Create server with tool overrides" showLineNumbers -curl -X POST http://localhost:4000/v1/mcp/server \ - -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "petstore_mcp", - "url": "https://petstore.swagger.io/v2", - "spec_path": "/path/to/openapi.json", - "tool_name_to_display_name": { - "getPetById": "Get Pet", - "findPetsByStatus": "List Available Pets" - }, - "tool_name_to_description": { - "getPetById": "Look up a pet by its ID", - "findPetsByStatus": "Returns all pets that match the given status (available, pending, sold)" - } - }' -``` - -```bash title="Update overrides on an existing server" showLineNumbers -curl -X PUT http://localhost:4000/v1/mcp/server/{server_id} \ - -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "tool_name_to_display_name": { - "getPetById": "Get Pet" - }, - "tool_name_to_description": { - "getPetById": "Look up a pet by its ID" - } - }' -``` - -### How It Works - -The key used in both maps is the **original tool name** from the spec (the `operationId`), not the prefixed name. LiteLLM strips the server prefix before looking up overrides. - -For example, if your server is named `petstore_mcp`, the tool is exposed as `petstore_mcp-getPetById`. The map key is still `getPetById`: - -```json -{ - "tool_name_to_display_name": { - "getPetById": "Get Pet" - } -} -``` - -After the override, MCP clients will see `"Get Pet"` instead of `"petstore_mcp-getPetById"`. - -### Example: Before and After - -Admin configures on the `petstore_mcp` server: -```json -{ - "tool_name_to_display_name": { - "getPetById": "Get Pet", - "findPetsByStatus": "List Available Pets" - }, - "tool_name_to_description": { - "getPetById": "Look up a pet by its ID", - "findPetsByStatus": "Returns all pets matching the given status" - } -} -``` - -MCP client calls `tools/list` and sees: - -``` -Tool: "Get Pet" -Description: "Look up a pet by its ID" - -Tool: "List Available Pets" -Description: "Returns all pets matching the given status" - -Tool: "petstore_mcp-addPet" ← no override, original name shown -Description: "Add a new pet to the store" -``` diff --git a/docs/my-website/img/mcp_openapi_custom_name_badge.png b/docs/my-website/img/mcp_openapi_custom_name_badge.png new file mode 100644 index 00000000000..11f94c1e68c Binary files /dev/null and b/docs/my-website/img/mcp_openapi_custom_name_badge.png differ diff --git a/docs/my-website/img/mcp_openapi_tool_edit_panel.png b/docs/my-website/img/mcp_openapi_tool_edit_panel.png new file mode 100644 index 00000000000..f826fb1f176 Binary files /dev/null and b/docs/my-website/img/mcp_openapi_tool_edit_panel.png differ diff --git a/docs/my-website/img/mcp_openapi_tools_loaded.png b/docs/my-website/img/mcp_openapi_tools_loaded.png new file mode 100644 index 00000000000..bb9f6be2719 Binary files /dev/null and b/docs/my-website/img/mcp_openapi_tools_loaded.png differ