Skip to content

MCP function facade

The mcp facade serves one function of a function-mode AgentRuntime as one MCP tool over Streamable HTTP. Facade fields are in the AgentRuntime reference.

EndpointPortListener
POST /mcpfacades[].mcp.port, default 9998External
POST /mcp19998 (mcp-mgmt)Management-plane twin
/.well-known/oauth-protected-resource, /.well-known/oauth-protected-resource/mcp9998External, no credential
/metrics8081 (health port)Facade

The twin runs unless the mcp facade sets managementPlane: false. When it runs, status.managementEndpoints.mcp is 19998. The Service also exposes port 8080 for POST /functions/{name}.

AspectBehaviour
TransportStreamable HTTP, stateless: tools/list and tools/call need no prior initialize
Protocol versions2025-03-26 and 2025-06-18. initialize agrees to either version when asked and answers 2025-06-18 otherwise
JSON-RPC batchesNot supported. A JSON array body returns a parse error
GET /mcp405
Methodsprompts/* and resources/* are not supported. Legacy SSE clients cannot connect
ToolsOne tool per pod, named after the AgentRuntime in lower case, with the inputSchema and outputSchema from the spec after the adaptation below

MCP requires a tool schema to have a "type": "object" root. The facade adapts the function’s spec.inputSchema and spec.outputSchema.

Root of the spec schemaAdvertised schema
Object rootUnchanged
Describes an object but omits type"type": "object" added
Has oneOf, anyOf, allOf, not, $ref, if, enum or const, or a non-object typeWrapped in an object with one required property: input for the input schema, output for the output schema

For a wrapped input schema, callers send the function input under arguments.input. The facade unwraps it before it validates the input.

A successful tools/call returns the function output as structuredContent and as a text part. A tools/call with no arguments calls the function with {}.

ConditionResult
tools/call for an unknown toolJSON-RPC error -32602
A call that runs and failsMCP result with isError: true

The text of an isError result starts with one of the outcomes below.

OutcomeMeaning
input_invalidThe input failed validation
output_invalidThe output failed validation. A second text part, prefixed raw_output:, carries the runtime output
runtime_errorThe runtime call failed. The facade logs the detail
rate_limitedThe agent’s spec.rateLimit refused the call before the runtime saw it
function_not_foundThe function does not exist
payload_too_largeThe input exceeds the facade’s maximum body size
sync_timeoutThe call exceeded the time limit
internal_errorAn internal failure. The facade logs the detail
Listenertools/call limit
External30 seconds, the same limit as a synchronous POST /functions/{name}. The call returns a sync_timeout error result
Management-plane twinNone

POST /functions/{name}?mode=async runs longer work and requires facades[].async.

ListenerAccepts
ExternalThe validators built from spec.externalAuth, the same chain as POST /functions/{name}
Management-plane twinManagement-plane JWTs. It refuses every request it cannot authenticate

An unauthenticated POST /mcp returns 401. An AgentRuntime with no spec.externalAuth has an empty external chain, so its external listener rejects every request with 401. Management-plane JWTs are never accepted on the external listener.

The 401 response carries a WWW-Authenticate header:

spec.externalAuth.oidcWWW-Authenticateauthorization_servers
SetCarries resource_metadataLists its issuer
UnsetBearer realm="omnia" aloneNot applicable

The RFC 9728 metadata resource is the agent’s external MCP URL when the operator observes one, else the in-cluster Service URL.

A POST /mcp that carries a browser Origin header gets 403 with the body origin not allowed unless the origin is the agent’s own external or in-cluster URL. Requests with no Origin header are unaffected. Authentication runs first, so an unauthenticated request with a bad Origin gets 401.

VariableValue
OMNIA_MCP_ALLOWED_ORIGINSComma-separated list of additional allowed origins. * turns the check off

Set the variable in the extraEnv of the rest entry. The operator copies extraEnv from the primary facade only (the rest facade of a function), and the API server rejects extraEnv on the mcp entry.

facades[].expose is read from the primary facade only, and the operator’s HTTPRoute targets only that facade’s port (8080). The API server rejects expose on the mcp facade, and the operator creates no route for the MCP port. status.facade.endpoints gets an entry with protocol: mcp when an observed HTTPRoute in the namespace has a backendRef to the agent’s Service on the MCP port.

A tools/call writes a sessions row when session-api is reachable, as the HTTP route does. The session carries the agent, namespace and workspace identity, so ToolPolicy rules on identity.agent and identity.workspace apply.

MetricLabels
omnia_mcp_requests_totalmethod, status
omnia_mcp_request_duration_secondsmethod
omnia_mcp_tool_invocations_totalfunction, outcome

Every metric also carries agent and namespace. A failed tool call counts as status="ok" on the request series and appears on the invocation series.

Spans named mcp-facade join the trace through the runtime gRPC call.