Ana içeriğe geç

Update MCP Routing

Endpoint​

PUT /apiops/projects/{projectName}/apiProxies/{apiProxyName}/mcp-routing/
Warning

This endpoint returns HTTP 400 for API proxies whose type is not MCP — mcpRouting can only be set on MCP proxies. To create a new MCP proxy in one call, use Create MCP API Proxy — this endpoint only updates the routing config of a proxy that already exists.

Authentication​

Requires a Personal API Access Token.

Permission: API_MANAGEMENT × MANAGE, or AI_DEVELOPMENT × MANAGE. Both are accepted on AI, MCP and A2A proxies.

Authorization: Bearer YOUR_TOKEN

Request​

Headers​

HeaderValueRequired
AuthorizationBearer {token}Yes
Content-Typeapplication/jsonYes

Path Parameters​

ParameterTypeRequiredDescription
projectNamestringYesProject name
apiProxyNamestringYesMCP API Proxy name

Request Body​

The body is the full McpRouting object — it replaces the proxy's current MCP routing configuration.

The routing has no call quota. A callQuota field sent by an older client is ignored and is not stored. Set call limits in a Limit Plan (per identity) or with the Quota or Throttling policy (per proxy).

Warning

This endpoint replaces the routing as a whole. A field you do not send is dropped, and it returns to its default. If you apply an old body (such as the examples below) to a proxy that uses the Standard MCP OAuth profile, authProfile, serviceClientName, the downstreamIdentity of each tool, riskPolicy, riskPolicyExemptions and toolRiskOverrides are lost. Read the current configuration first, change the fields you need, and send the whole object back.

Full JSON Body Example (TOOL_EXPOSE)​

{
"routingMode": "TOOL_EXPOSE",
"protocolVersion": "2025-06-18",
"authProfile": "STANDARD_MCP_OAUTH",
"serviceClientName": "petstore-service-client",
"serverJsonOverride": "{\"name\":\"com.example/petstore-mcp\",\"description\":\"Petstore MCP server\",\"version\":\"1.0.0\",\"remotes\":[{\"type\":\"streamable-http\",\"url\":\"${GATEWAY_URL}/petstore-mcp/\"}]}",
"exposedTools": [
{
"proxyId": "665f1c2e8b3a4d0012ab34cd",
"toolName": "order_lookup",
"toolDescription": "Looks up an order by id",
"apiMethodHttpMethod": "GET",
"apiMethodPath": "/orders/{id}",
"requiredScopes": ["orders.read"],
"downstreamIdentity": "SERVICE",
"riskTier": "LOW",
"argumentConstraints": []
}
],
"riskPolicy": { "low": "ALLOW", "medium": "REQUIRE_APPROVAL", "high": "DENY" },
"riskPolicyExemptions": [],
"toolRiskOverrides": [],
"identityAcl": [],
"argumentConstraints": [],
"tokenForwardSettings": null
}

Full JSON Body Example (PASSTHROUGH, inline backend server)​

{
"routingMode": "PASSTHROUGH",
"backendServers": [
{
"name": "internal-mcp-server",
"endpoint": "https://mcp.example.com/mcp",
"transport": "HTTP_SSE",
"authScheme": "BEARER",
"bearerToken": "raw-token-in-transit-only",
"driftPolicy": "WARN_ONLY"
}
],
"allowedToolNames": ["search", "fetch_document"],
"tokenForwardSettings": {
"enabled": true,
"source": "CLIENT_AUTHORIZATION_HEADER",
"audienceAllowList": ["https://mcp.example.com"],
"stripGatewayCredential": true
},
"forwardedHeaders": [
{
"name": "app-identifier",
"required": true,
"errorMessage": "{\"jsonrpc\":\"2.0\",\"id\":{{jsonRpcId}},\"error\":{\"code\":-32600,\"message\":\"Send the {{headerName}} header\"}}"
},
{ "name": "x-tenant-id", "required": false, "errorMessage": null }
],
"toolOutputFilter": null,
"identityAcl": []
}

Field Reference​

FieldTypeDescription
routingModestringTOOL_EXPOSE (expose selected Apinizer proxies as MCP tools) or PASSTHROUGH (proxy one or more external backend MCP servers)
authProfilestringClient authentication profile: LEGACY (default; also the value when the field is not sent) or STANDARD_MCP_OAUTH. See Standard MCP Client Profile
serviceClientNamestringName of the existing API client that the proxy acts as in the Standard profile. Required there when the proxy exposes any tool. It is a reference only
protocolVersionstringMCP protocol version: 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25 or 2026-07-28 (default). A blank value uses 2026-07-28. See Protocol Versions
serverJsonOverridestringOptional. A hand-written replacement for the generated .well-known/mcp/server.json discovery document — see Discovery Document. Empty/omitted (the default) keeps the auto-generated document. The value is a JSON document encoded as a string; it must be valid JSON, but its schema completeness is not checked here — a document missing name/description/version/remotes saves successfully and only surfaces as a warning on the MCP Gateway console. ${VAR} placeholders inside the string are resolved to environment variables when the document is served, so the same document can be promoted across environments while advertising each one's own host. Once set, the document is served exactly as written — unauthenticated — at {relativePath}/.well-known/mcp/server.json; never put a credential in it
exposedToolsarrayTOOL_EXPOSE only. Tool definitions — proxyId (target ApiProxy id), toolName, toolDescription, optional overrideSchema, apiMethodHttpMethod/apiMethodPath (pin to a specific method), requiredScopes, downstreamIdentity (SERVICE | DELEGATED; required on the Standard profile, ignored on Legacy), per-tool argumentConstraints, optional riskTier (LOW | MEDIUM | HIGH; empty = the HTTP method default, read only while riskPolicy is set). toolName is normalized before it is published in tools/list (lowercased, any character other than a letter or digit becomes _, repeated underscores collapsed, truncated to 64 chars; colliding names get a _2/_3 suffix). A blank toolName falls back to the normalized proxyId. The published catalog changes only after the proxy is deployed again
backendServersarrayPASSTHROUGH only. The only way to configure a backend target — there is no reference-based alternative. Inline MCP server definitions — up to 10. Each entry is a full connection object: name, endpoint, transport (HTTP_SSE), authScheme (BEARER | OAUTH2_CLIENT_CREDENTIALS | OAUTH2_TOKEN_EXCHANGE | MTLS | API_KEY | BASIC | NONE) plus the matching credential fields (bearerToken; credentialRef/tokenEndpoint/clientId/clientSecret/scope for the two OAuth2 schemes; tokenExchangeAudience (optional) for OAUTH2_TOKEN_EXCHANGE; apiKeyHeaderName and apiKey for API_KEY; basicUsername and basicPassword for BASIC; mTLSSettings), trustToolAnnotations (default false; true = the tool annotations of this server lower the risk tier), relayElicitation (default false; true = relay elicitation requests of this server to a legacy client), driftPolicy (WARN_ONLY | FAIL_CLOSED), allowPrivateNetworkEgress. Server-managed fields (id, discoveredTools, toolsParsedAt, healthStatus, lastHealthCheckAt, pinnedCatalogHash, driftDetected) are always read from the server's own persisted state — a client-supplied value for any of them is ignored, never trusted. Multiple entries aggregate behind one endpoint (see Multi-Target Aggregation). PASSTHROUGH mode requires at least one entry
riskPolicyobjectTool risk policy: an action for each tier — low, medium, high — each one ALLOW | REQUIRE_APPROVAL | DENY. An unset tier means ALLOW. null (default) = the policy is off and every call is allowed. See Tool Risk Policy and Approval
riskPolicyExemptionsarrayIdentity rules (same shape as identityAcl entries). For a matching caller, REQUIRE_APPROVAL becomes ALLOW. DENY does not change
toolRiskOverridesarrayPASSTHROUGH. Risk tier of a tool by the tool name as tools/list shows it. Each entry: toolName, riskTier (LOW | MEDIUM | HIGH). A tool name can appear once
allowedToolNamesarrayPASSTHROUGH tool filter — only listed backend tools are exposed
toolOutputFilterobjectPASSTHROUGH tool output filtering rules
identityAclarrayPer-principal allow rules (principalType: CREDENTIAL | ROLE | ORGANIZATION). Enforced on the PASSTHROUGH dispatch path
argumentConstraintsarrayTool argument constraint rules. In PASSTHROUGH mode each entry names a toolName (as tools/list shows it, case-sensitive) and its rules; in TOOL_EXPOSE mode the rules sit on each exposed tool. A rule has argumentPath (property names separated by dots; no array index or wildcard), ruleType (REGEX | MAX_LENGTH | ENUM | REQUIRED) and value. The gateway skips a saved rule that is not valid
tokenForwardSettingsobjectPASSTHROUGH. Caller-token forwarding; null = off. enabled (boolean), source (CLIENT_AUTHORIZATION_HEADER), audienceAllowList (optional JWT aud allow-list, ${VAR} supported; empty = any Bearer token), stripGatewayCredential (default true). When enabled, the caller's Bearer token is sent to the backend on every hop — initialize, tools/list and tools/call. When no token can be forwarded, the server row's own credential is used
forwardedHeadersarrayPASSTHROUGH. Caller request headers relayed to the backend MCP server on every hop (at most 20). Each entry: name (string, case-insensitive, unique), required (boolean, default false), errorMessage (string, optional). A header the caller does not send is skipped, unless required is true. Independent of tokenForwardSettings. Authorization, Proxy-Authorization, Host, Connection, Keep-Alive, Proxy-Connection, Transfer-Encoding, TE, Trailer, Upgrade, Content-Length, Content-Type, Content-Encoding, Accept, Accept-Encoding, Mcp-Session-Id and MCP-Protocol-Version are rejected with HTTP 400 (error.mcpRouting.forwardedHeaderNotAllowed). More than 20 entries return error.mcpRouting.tooManyForwardedHeaders. A duplicate name returns error.mcpRouting.duplicateForwardedHeader. A non-blank errorMessage that is not valid JSON (placeholders filled with sample values) returns error.mcpRouting.forwardedHeaderErrorMessageInvalidJson

Behavior​

  • The configuration is validated (McpA2aRoutingValidator) before save; invalid mode/field combinations return HTTP 400.
  • Required forwarded headers: in PASSTHROUGH mode, the gateway checks every JSON-RPC request for each forwardedHeaders entry with required: true. A missing or blank header stops the request before the backend call. The gateway returns HTTP 400 with Content-Type: application/json. The body is the header's errorMessage, or this default when it is blank: {"jsonrpc":"2.0","id":{{jsonRpcId}},"error":{"code":-32600,"message":"Missing required header: {{headerName}}"}}. {{headerName}} is replaced with the header name. {{jsonRpcId}} is replaced with the request id as JSON (a number stays a number, a string is quoted, a missing id is null). The traffic log records the request as blocked.
  • Tool risk policy: riskPolicy, riskPolicyExemptions, toolRiskOverrides and the riskTier of an exposed tool are set with this endpoint. Create MCP API Proxy does not carry them. A toolRiskOverrides entry with a blank or repeated toolName, or without riskTier, returns HTTP 400 (error.mcpRouting.toolRiskOverrideInvalid). Approving or rejecting a held call is done in the Manager, not through this API.
  • Updating an existing backendServers entry: to update rather than replace a server, send back the id from a prior read (GET/getApiProxy) unchanged — a matching id is treated as an update and its server-managed fields (discovered catalog, health, drift) are preserved. An entry whose id is blank, or doesn't match anything currently persisted, is always treated as brand-new: a fresh id is minted server-side and any client-supplied id is discarded.
  • Secret fields on backendServers entries (bearerToken, clientSecret, apiKey, basicPassword) follow the platform's standard blank-preserves-existing convention: omit the field (or send it unset) to keep the currently stored secret, send a non-blank value to replace it. There is no separate boolean presence flag on this write path — unlike a read, which never returns the secret's plaintext.
  • Every environment the proxy is currently deployed to is marked redeploy required — redeploy to activate the new configuration.

Response​

Success Response (200 OK)​

{
"status": "SUCCESS",
"deploymentResult": {
"success": false,
"detailList": []
}
}

The call does not deploy the proxy. Redeploy it to activate the change.

Error Responses​

StatusCondition
400Blank apiProxyName, empty body, proxy not found, proxy is not an MCP proxy, backendServers exceeds 10 entries, serverJsonOverride is not valid JSON, or another validation failure
401Invalid or missing token
500Unexpected server error