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,iconscome from the group'smcp_server_info(falling back field by field to the bundle-wide setting, see Configuration); unset fields are left out of the document.versionis the request's{ver};websiteUrlis the request's scheme, host and port;remotes[0].urlis 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_TOKENenvironment 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 defaultUfo-RPC-Token).
An unknown aiName answers 404 {"error": "Unknown MCP client manifest \"…\"."}. A manifest for another client: see Extensions.