Zudoku
Guides

Documenting MCP Servers

Zudoku can render a dedicated MCP endpoint UI for any OpenAPI operation that has the x-mcp-server extension. When detected, the operation page replaces the standard request/response view with an MCP card showing the endpoint URL, a copy button, and tabbed installation instructions for Claude, ChatGPT, Cursor, VS Code, and a generic config.

Adding the extension

Add the x-mcp-server extension to an operation in your OpenAPI spec. While MCP servers typically use POST, the extension works on any HTTP method:

JSONCode
{ "paths": { "/mcp": { "post": { "summary": "My MCP Server", "description": "MCP endpoint for querying documentation.", "operationId": "mcpEndpoint", "x-mcp-server": { "name": "my-mcp-server", "version": "1.0.0", "tools": [ { "name": "search_docs", "description": "Search the documentation" }, { "name": "get_page", "description": "Retrieve a specific documentation page" } ] }, "responses": { "200": { "description": "MCP response" } } } } } }

The UI will display beneath the operation heading, showing the full MCP URL derived from the server URL and the operation path.

You can also use the shorthand "x-mcp-server": true to enable the MCP UI without specifying any metadata. In this case, the operation's summary is used as the server name.

Extension properties

PropertyTypeRequiredDescription
namestringNoDisplay name used in the generated client configuration snippets. Falls back to the operation summary, then "mcp-server"
versionstringNoVersion metadata (included for completeness; not currently rendered in UI)
urlstringNoOverrides the endpoint URL shown in the card and install snippets
toolsarrayNoTools metadata (used by Zuplo enrichment; not currently rendered in UI)

Each tool in the tools array has:

PropertyTypeRequiredDescription
namestringYesTool name
descriptionstringNoHuman-readable tool description

MCP URL resolution

The displayed MCP URL is constructed from the server URL of the API and the path of the operation. The server URL comes from the OpenAPI servers array (or the operation-level servers override if present).

For example, with this configuration:

JSONCode
{ "servers": [{ "url": "https://api.example.com" }], "paths": { "/mcp/docs": { "post": { "x-mcp-server": { "name": "docs-mcp" }, "responses": { "200": { "description": "OK" } } } } } }

The displayed MCP URL will be https://api.example.com/mcp/docs.

If your MCP server lives on its own hostname, set url on the extension to override the derived endpoint:

JSONCode
{ "x-mcp-server": { "name": "docs-mcp", "url": "https://mcp.example.com/mcp" } }

An absolute URL is used verbatim everywhere the endpoint appears, and takes precedence over the server dropdown. A value without a scheme (such as /v2/mcp) is treated as a path on the server URL instead. See the x-mcp-server reference for details.

Authentication instructions

When the x-mcp-server extension carries security and securitySchemes (Zuplo adds these automatically for authenticated routes), the card derives the credential header from the first scheme and threads it through every install snippet — for example an Authorization: Bearer YOUR_API_KEY header in the mcp.json samples, plus a step telling users to replace the placeholder with their key. API key auth also hides the clients that cannot send custom headers (Claude Desktop and ChatGPT), and the one-click install buttons for Cursor and VS Code, since those links cannot carry a secret.

If your users get their credentials some other way — the key is injected by a proxy, handled by your own login flow, or simply documented elsewhere — turn the authentication instructions off in your Zudoku config:

ReactCode
const config: ZudokuConfig = { apis: [ { type: "file", input: "./mcp-api.json", path: "mcp", options: { disableMcpAuthInstructions: true, }, }, ], };

The card then renders the server as if it were unauthenticated, whatever its security says: no header in the snippets, no placeholder step, and every client available again. Set it under defaults.apis instead to apply it to all APIs.

Complete example

This is a minimal but complete OpenAPI spec that produces an MCP endpoint page:

JSONCode
{ "openapi": "3.0.3", "info": { "title": "Documentation MCP Server", "version": "1.0.0" }, "servers": [ { "url": "https://api.example.com", "description": "Production" } ], "paths": { "/mcp": { "post": { "tags": ["MCP"], "summary": "Documentation MCP Server", "description": "MCP endpoint powered by Inkeep for searching and querying documentation.", "operationId": "mcpEndpoint", "x-mcp-server": { "name": "example-docs", "version": "1.0.0", "tools": [ { "name": "search_docs", "description": "Search the documentation" } ] }, "responses": { "200": { "description": "MCP response" } } } } } }

Then reference this spec in your Zudoku config (see API Reference for full apis configuration):

ReactCode
import type { ZudokuConfig } from "zudoku"; const config: ZudokuConfig = { apis: [ { type: "file", input: "./mcp-api.json", path: "mcp", }, ], navigation: [ { type: "link", label: "MCP Server", to: "/mcp", icon: "bot", }, ], }; export default config;

You can see a live example of this in the Cosmo Cargo demo.

Generated UI

When Zudoku detects the x-mcp-server extension on an operation, the page shows:

  • MCP Endpoint card with the full URL and a copy button
  • AI Tool Configuration tabs with setup instructions for:
    • Claude — add via Connectors UI or claude mcp add CLI command
    • ChatGPT — app setup via Settings → Apps → Advanced Settings
    • Cursormcp.json configuration (global or project-level)
    • VS Code.vscode/mcp.json with native HTTP transport for GitHub Copilot
    • Generic — standard mcp.json format compatible with most MCP clients

The standard method badge, request body, parameters, and sidecar panels are hidden for MCP endpoints since they use a different interaction model.

Using with Zuplo

If you are using Zuplo to host your API, the x-mcp-server extension is automatically added to POST operations that use the mcpServerHandler. No manual schema changes are needed. See the Zuplo MCP documentation for details.

The server name shown in the install snippets (for example claude mcp add … 'MCP Server' …) is taken from the handler's name option — the same name your MCP server advertises to clients. Set it to override the default "MCP Server" title:

JSONCode
{ "/mcp": { "post": { "operationId": "mcpServerHandler", "x-zuplo-route": { "handler": { "export": "mcpServerHandler", "module": "$import(@zuplo/runtime)", "options": { "name": "Acme API", "operations": [{ "file": "./config/routes.oas.json", "id": "get-users" }] } } } } } }

With this configuration the snippets read claude mcp add --transport http 'Acme API' ….

Last modified on