server.json and client manifests

← server.json and client manifests

Ashterix

docs: rewrite JsonRpcBundle docs, add SDK docs, move them under docs/api

en/docs/api/mcp-bundle/discovery.md new file +41 −0

server.json and client manifests

Every endpoint also serves two kinds of documents. Both are protected by the documentation token rule (JsonRpcBundle protected_doc), answer 404 the same way as the endpoint itself, and take the endpoint URL from the request: <prefix>[/{ver}].

server.json for the MCP Registry

GET <prefix>/server.json (or <prefix>/v2/server.json) is the document the MCP Registry expects when the server is published there (schema 2025-12-11). Clients do not read it to connect.

{
    "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
    "name": "io.github.your-org/your-app",
    "title": "Your App MCP Server",
    "description": "Exposes Your App RPC services as MCP tools.",
    "version": "v1",
    "websiteUrl": "https://api.example.com",
    "icons": [{"src": "https://example.com/icon.png", "mimeType": "image/png", "sizes": ["128x128"]}],
    "remotes": [{"type": "streamable-http", "url": "https://api.example.com/mcp"}]
}
  • name, title, description, icons come from the group's mcp_server_info (falling back field by field to the bundle-wide setting, see Configuration); unset fields are left out of the document.
  • version is the request's {ver}; websiteUrl is the request's scheme, host and port; remotes[0].url is the endpoint URL.

Client manifests

GET <prefix>/manifest/{aiName}.json is a ready connection config. The token stays a placeholder: a manifest never contains a real token. The server key in the config is the group name.

aiName For Format
claude Claude Code (.mcp.json) {"mcpServers": {"<group>": {"type": "http", "url": "…", "headers": {"Ufo-RPC-Token": "${UFO_MCP_TOKEN}"}}}}
cursor Cursor (mcp.json) {"mcpServers": {"<group>": {"url": "…", "headers": {"Ufo-RPC-Token": "${env:UFO_MCP_TOKEN}"}}}}
gemini Gemini CLI (settings.json) {"mcpServers": {"<group>": {"httpUrl": "…", "headers": {"Ufo-RPC-Token": "<UFO_MCP_TOKEN>"}}}}
openai OpenAI Responses API a tools[] item: {"type": "mcp", "server_label": "<group>", "server_url": "…", "headers": {…}, "require_approval": "always"}
  • Claude Code and Cursor substitute the UFO_MCP_TOKEN environment variable themselves.
  • Gemini CLI does not substitute variables in headers, and the OpenAI API sends headers as is: replace <UFO_MCP_TOKEN> with the token by hand or in your code.
  • require_approval: "always" for OpenAI is a conservative value so that the bundle never authorizes calls without confirmation; change it if needed.
  • The header name is ufo_json_rpc.security.token_name (by default Ufo-RPC-Token).

An unknown aiName answers 404 {"error": "Unknown MCP client manifest \"…\"."}. A manifest for another client: see Extensions.