Skip to main content

MCP Configuration Reference

This is the canonical decision reference for connecting to LiteLLM's MCP Gateway: which endpoint to use, which transport to configure, and how the two layers of authentication fit together. Use the linked guides for setup steps and provider-specific requirements

Endpoint examples use http://localhost:4000 as the proxy base URL; substitute your own. Set LITELLM_API_KEY to a key with access to the selected MCP servers. Selecting a server by URL or header narrows existing access; it does not grant access. See MCP access grants for key and team setup

Protocol version​

The gateway and upstream MCP servers negotiate a protocol version during initialize. LiteLLM v1.101.0 (18243cd7) pins MCP SDK 1.28.1; a gateway initialization on that release negotiated 2025-11-25. LiteLLM v1.103.0-rc.1 (ccf5e8c9) pins SDK 2.2.0. An SDK pin or negotiated version alone does not establish support for every optional protocol capability; inspect the capabilities returned by the endpoint you use

There is no supported per-server spec_version configuration field. The legacy delegated-auth discovery probe sends 2025-06-18; that probe is separate from client and upstream SDK negotiation

Two layers of authentication​

Gateway and upstream authentication are configured separately. Keep their credentials separate

  1. Gateway authentication (client to LiteLLM). Your LiteLLM virtual key. Send it in the x-litellm-api-key header (x-litellm-api-key: Bearer <key>). Authorization: Bearer sk-... also works, but for MCP traffic prefer x-litellm-api-key so the Authorization header stays free for OAuth tokens and upstream credentials. Use the dedicated header when sending a separate upstream bearer token
  2. Upstream authentication (LiteLLM to the MCP server). Configured per server via auth_type (static keys, OAuth, SigV4, and so on), or supplied per request by the client via x-mcp-{server_alias}-{header_name} headers. See Upstream auth matrix

If you see your LiteLLM key arriving at the upstream MCP server (the debug headers show SAME_AS_LITELLM_KEY), you have put the LiteLLM key in Authorization on a server that forwards Authorization upstream. Move it to x-litellm-api-key. See Debugging OAuth

Endpoint matrix​

EndpointProtocolUse whenRequired headersServer scopeExpected response
/mcpMCP JSON-RPC (streamable HTTP)A direct MCP client (Claude Desktop/Code, Cursor, MCP Inspector, FastMCP) should see every server the key can accessx-litellm-api-key: Bearer sk-...; optionally x-mcp-servers: <name1>,<group1> to narrow the setAll servers the key/team is permitted to use, optionally narrowed by x-mcp-serversMCP initialize / tools/list / tools/call JSON-RPC responses; tool names are prefixed with the server alias (e.g. github_mcp-search_issues)
/{server_name}/mcpMCP JSON-RPC (streamable HTTP)A direct MCP client should see exactly one server (or a comma-separated list /{name1,name2}/mcp)x-litellm-api-key: Bearer sk-...The named server(s), toolset, or access group onlySame JSON-RPC responses, scoped to that server
/toolset/{toolset_name}/mcpMCP JSON-RPC (streamable HTTP)A direct MCP client should see exactly the tools in a toolsetx-litellm-api-key: Bearer sk-...The named toolsetSame JSON-RPC responses, scoped to the toolset
server_url: "litellm_proxy" inside toolsLLM API (/v1/responses or /v1/chat/completions)The LLM should discover and execute MCP tools during a completion. litellm_proxy is a literal sentinel, never a URLAuthorization: Bearer sk-... on the LLM request; per-server upstream creds via x-mcp-... headers or the tool's headers objectAll permitted servers, or use litellm_proxy/mcp/<server_alias> for a server or toolsetResponses / Chat Completions output; require_approval: "never" enables execution of model-selected tools
GET /v1/mcp/serverRESTList configured servers and fetch a real server_id / server_nameAuthorization: Bearer sk-... or x-litellm-api-key: sk-...All servers visible to the keyJSON array of server objects
GET /mcp-rest/tools/listRESTList tools over plain HTTP without an LLM or MCP clientSame as aboveAll accessible servers, or one with ?server_id=JSON object with tools, error, and message; see MCP REST API
POST /mcp-rest/tools/callRESTExecute one known tool over plain HTTPSame as above, plus Content-Type: application/jsonThe server named by the required server_id body fieldJSON tool result; see MCP REST API for error shapes

Selection rule in one sentence: MCP-speaking clients connect to /mcp (all permitted servers) or /{server_name}/mcp (one server); LLM-driven tool use inside /v1/responses or /v1/chat/completions uses the literal server_url: "litellm_proxy"; and scripted HTTP calls without an MCP client use /mcp-rest/*

Use litellm_proxy inside requests sent to LiteLLM's LLM API. The accepted aggregate form litellm_proxy/mcp has the same purpose; standardize new examples on litellm_proxy. For a server or toolset, use litellm_proxy/mcp/<name>. These selectors are not network URLs. When calling a hosted LLM API directly, supply a reachable https://<proxy-host>/mcp URL instead

A minimal direct-client request, useful as a smoke test:

curl -s -X POST http://localhost:4000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "x-litellm-api-key: Bearer $LITELLM_API_KEY" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

Expected: a JSON-RPC result whose tools array contains prefixed tool names from reachable servers the key can access. Inspect per-server outcomes in result._meta when an upstream returns no tools. A 401 means the gateway credential is wrong; a 404 on /{server_name}/mcp means the server name, toolset, or access group does not exist

Transport matrix​

transport describes how LiteLLM connects to the upstream MCP server. Clients always reach LiteLLM over streamable HTTP regardless of the upstream transport

When transport is omitted in config.yaml, the loader defaults to http (streamable HTTP). The management API create/update request models default to sse. Set transport explicitly in both entry points to avoid relying on different defaults

config.yaml: the three transports side by side
mcp_servers:
# Streamable HTTP (default): url required
deepwiki_mcp:
url: "https://mcp.deepwiki.com/mcp"
transport: "http"

# SSE: url required, transport must be set explicitly
legacy_mcp:
url: "https://your-sse-server.example.com/sse"
transport: "sse"

# stdio: command required, url unused; LiteLLM launches the process
everything_mcp:
transport: "stdio"
command: "npx"
args: ["-y", "@modelcontextprotocol/server-everything@2026.8.31"]
TransportRequired fieldsWhen to useExpected behavior
http (YAML default)urlAny modern remote MCP server; this is the MCP streamable HTTP transportLiteLLM POSTs JSON-RPC to url and streams responses
sseurl, transport: "sse"Legacy servers that only expose an SSE endpointLiteLLM opens an SSE stream to url
stdiotransport: "stdio", command; optional args, envLocal MCP servers launched as a subprocess on the proxy hostLiteLLM spawns command and speaks MCP over stdin/stdout. Per-request headers can be mapped into env with ${X-HEADER-NAME} syntax; see header-to-env forwarding

Replace the SSE URL with a running legacy SSE server. The stdio example requires Node.js and npx on the proxy host and launches the pinned demonstration server; it is a connectivity control. Use your own server command for production

In the UI (MCP Servers, Add New MCP Server) the same three transports appear as Streamable HTTP, SSE, and Standard Input/Output (stdio), and stdio config is pasted as JSON

Upstream auth matrix​

auth_type selects how LiteLLM authenticates to the upstream MCP server. The YAML below configures upstream credentials. Clients still authenticate to the gateway separately. Replace example endpoints, register the required OAuth client, and set each referenced secret in the proxy environment before starting it

config.yaml: upstream auth side by side
mcp_servers:
# 1. none: server needs no credentials
open_server:
url: "https://mcp.example.com/mcp"
transport: "http"
auth_type: "none"

# 2. Static API key: sent as X-API-Key
api_key_server:
url: "https://mcp.example.com/mcp"
transport: "http"
auth_type: "api_key"
auth_value: os.environ/MCP_API_KEY # -> X-API-Key: <value>

# 3. Static bearer token: sent as Authorization: Bearer
bearer_server:
url: "https://mcp.example.com/mcp"
transport: "http"
auth_type: "bearer_token"
auth_value: os.environ/MCP_BEARER_TOKEN # -> Authorization: Bearer <value>

# 4. Interactive OAuth (PKCE): each user signs in via browser
oauth_interactive_server:
url: "https://mcp.example.com/mcp"
transport: "http"
auth_type: "oauth2"
oauth2_flow: "authorization_code"
client_id: os.environ/OAUTH_CLIENT_ID
client_secret: os.environ/OAUTH_CLIENT_SECRET

# 5. M2M OAuth (client_credentials): LiteLLM fetches and refreshes the token
oauth_m2m_server:
url: "https://mcp.example.com/mcp"
transport: "http"
auth_type: "oauth2"
oauth2_flow: "client_credentials"
client_id: os.environ/M2M_CLIENT_ID
client_secret: os.environ/M2M_CLIENT_SECRET
token_url: "https://auth.example.com/oauth/token"
scopes: ["tool.read", "tool.write"]

# 6. OBO / delegated (RFC 8693 token exchange): user's token exchanged per request
obo_server:
url: "https://mcp.example.com/mcp"
transport: "http"
auth_type: "oauth2_token_exchange"
token_exchange_endpoint: "https://auth.example.com/oauth/token"
client_id: os.environ/OBO_CLIENT_ID
client_secret: os.environ/OBO_CLIENT_SECRET
audience: "https://mcp.example.com"
auth_typeHeader LiteLLM sends upstreamCredential sourceUse whenSetup guide
none (or omitted)No auth header generated from auth_typen/aOpen or network-protected servers
api_keyX-API-Key: <auth_value>auth_valueServer expects a key header
bearer_tokenAuthorization: Bearer <auth_value>auth_valueServer expects a static bearer token
basicAuthorization: Basic <base64(auth_value)>auth_value as raw username:passwordServer uses HTTP Basic
authorizationAuthorization: <auth_value> verbatimauth_valueServer needs a nonstandard scheme
tokenAuthorization: token <auth_value>auth_valueGitHub-style token scheme
oauth2 + oauth2_flow: authorization_codeAuthorization: Bearer <per-user token>Interactive PKCE sign-in per userHuman users must consent individuallyMCP OAuth
oauth2 + oauth2_flow: client_credentialsAuthorization: Bearer <M2M token>LiteLLM fetches, caches, refreshesBackend services, no human in the loopMCP OAuth M2M
oauth2_token_exchangeAuthorization: Bearer <exchanged token>Caller token exchanged using RFC 8693 or the Entra OBO profileOn-behalf-of / delegated accessMCP OBO Auth
oauth2_id_jagAuthorization: Bearer <ID-JAG assertion-derived token>Okta ID-JAG two-leg exchangeOkta AI agent token exchangeMCP ID-JAG
true_passthrough / oauth_delegateThe caller's own token, forwardedClient requestUpstream must see the end user's token untouchedMCP OAuth Passthrough
aws_sigv4Per-request SigV4 signatureAWS credentials or boto3 chainAWS Bedrock AgentCore serversMCP AWS SigV4

auth_type: oauth2 requires an explicit oauth2_flow; missing or invalid values prevent YAML startup. Use authorization_code for per-user consent or client_credentials for a service identity. Omit the interactive client ID/secret only when the upstream supports dynamic client registration; see interactive setup and redirects

For a token on a different header, reuse upstream_token_header alongside static_headers. For Microsoft Entra ID, follow the existing token_exchange_profile: entra_obo guide. Gateway admission, upstream token exchange, and server access grants are separate requirements

For complete static credential inputs, see non-OAuth authentication. The header column describes the managed SSE/HTTP transport path. The OpenAPI-tool path emits Authorization: ApiKey <value> instead of X-API-Key for auth_type: api_key

Two more ways to send upstream credentials that do not involve auth_type:

  • Static headers: static_headers: {X-API-Key: "...", X-Custom: "..."} on the server config attaches fixed headers to every upstream request
  • Client-supplied per-server headers: clients send x-mcp-{server_alias}-{header_name} (e.g. x-mcp-github_mcp-authorization: Bearer gho_...) and LiteLLM forwards {header_name} to that server only. This is the supported client-side credential mechanism

Deprecated: x-mcp-auth​

The global x-mcp-auth header (one credential broadcast to every MCP server on the request) is deprecated. Replace it with the per-server form x-mcp-{server_alias}-{header_name}, which scopes each credential to one server. x-mcp-auth still works today (its header name can be renamed via mcp_client_side_auth_header_name in general_settings or the LITELLM_MCP_CLIENT_SIDE_AUTH_HEADER_NAME env var), but new setups should not use it

Common client configs​

For Cursor, use a network URL and match the credential header to the configured github_mcp alias. Replace the key and token placeholders. For Claude Code, use the CLI setup guide

Cursor mcpServers entry
{
"mcpServers": {
"github": {
"url": "http://localhost:4000/github_mcp/mcp",
"headers": {
"x-litellm-api-key": "Bearer sk-1234",
"x-mcp-github_mcp-authorization": "Bearer gho_your_token"
}
}
}
}

LLM-driven tool use on the proxy's Responses API (note server_url is the literal string litellm_proxy):

Responses API with MCP tools
curl -s http://localhost:4000/v1/responses \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $LITELLM_API_KEY" \
-d '{
"model": "gpt-5.6-terra",
"input": "Run available tools",
"tools": [{
"type": "mcp",
"server_label": "litellm",
"server_url": "litellm_proxy",
"require_approval": "never",
"headers": {"x-mcp-github_mcp-authorization": "Bearer gho_your_token"}
}],
"tool_choice": "required"
}'

Scripted REST calls can reuse deepwiki_mcp from the HTTP example above. First discover the server and tool, then call it. Use the returned server_id if your server has a different name or alias

MCP REST API
curl -sS http://localhost:4000/v1/mcp/server \
-H "Authorization: Bearer $LITELLM_API_KEY"

curl -sS 'http://localhost:4000/mcp-rest/tools/list?server_id=deepwiki_mcp' \
-H "Authorization: Bearer $LITELLM_API_KEY"

curl -sS -X POST http://localhost:4000/mcp-rest/tools/call \
-H "Authorization: Bearer $LITELLM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"server_id":"deepwiki_mcp","name":"read_wiki_structure","arguments":{"repoName":"BerriAI/litellm"}}'

Expect a tool result containing the repository's wiki structure. Omitting server_id returns 400 missing_parameter, even if the tool name is prefixed. Use {} for tools without arguments; do not pass null

🚅
LiteLLM Enterprise
SSO/SAML, audit logs, spend tracking, multi-team management, and guardrails — built for production.
Learn more →