ZuploMcpSdk
The ZuploMcpSdk class provides a helper API for custom MCP tool handlers to
interact with the MCP runtime. Use it to read metadata from the incoming
tools/call request and to override fields of the tool result the gateway sends
back to the AI client.
Code
ZuploMcpSdk is available in custom tool handlers for both the
MCP Server handler and the
MCP Gateway. It is exported from
@zuplo/runtime.
Methods
setRawCallToolResult(result)
Overrides fields of the MCP tool result the gateway is about to send to the AI client. Every field is independently optional — an absent field keeps the value the gateway derives from the downstream response.
Code
Parameters
The result argument is a ZuploMcpToolResultOverride object with the
following optional fields:
| Field | Type | Description |
|---|---|---|
content | CallToolResult["content"] | Content blocks the model reads. Replaces the gateway's default (the serialized downstream body in a text block). |
structuredContent | Record<string, unknown> | The structured form of the tool's output. Must be a JSON object — the MCP 2025-11-25 wire format rejects arrays and scalars. |
_meta | Record<string, unknown> | Per-call metadata. Replaces the gateway's default of {}. |
Compact summary example
The most useful combination is content alone: a human-readable summary
replaces the raw serialized body in the model's context, while
structuredContent is still auto-derived from the downstream response. This
reduces token consumption without losing data.
Code
The model sees "Fetched the todo list" instead of the full JSON body, but the
structuredContent field still carries the complete payload for spec-compliant
clients that read it.
Full override example
Override all available fields at once:
Code
isError is not overridable. It follows the HTTP status of the response
your handler returns, so upstream failures cannot be masked. If the downstream
route returns a non-2xx status, the tool result carries isError: true
regardless of any override.
Single-use — consumed once
The override is consumed when the gateway assembles the tool result. It is
read and deleted from the context at that point, so calling
setRawCallToolResult twice in the same request replaces the first value before
the gateway reads it.
How context lookup works
setRawCallToolResult writes the override to the context that carried the
matching tools/call request. The lookup travels exactly one
context.invokeRoute generation up from the context passed to the constructor.
This means:
- In a typical custom tool handler that calls
context.invokeRoute, the override is written to the parent context (the one carrying thetools/callrequest), which is correct. - If your handler calls
invokeRouteto a route that also callsinvokeRoute, and you constructZuploMcpSdkin that grandchild invocation, the override is stored on the immediate parent — not the grandparent that carries the tool call. The gateway never reads it. ConstructZuploMcpSdkin the handler that is one level below the MCP route.
getRawCallToolRequest()
Retrieves the original MCP tools/call request object from the context. Use
this to access metadata like the _meta field from the incoming tool call.
Code
Returns the CallToolRequest object, or null if no MCP tool call is in flight
on the current or parent context.
Code
Unlike setRawCallToolResult, this method can be called any number of times —
the request object is not consumed.
Output schema enforcement
When a tool advertises an outputSchema (via includeOutputSchema on the
handler or route config), the gateway validates the tool result's
structuredContent against that schema before sending it to the client. A
result whose structuredContent does not conform to the advertised schema fails
the call with a diagnostic isError result instead of a raw protocol error.
This enforcement is skipped on the error path (isError: true), matching the
MCP SDK's own behavior.
includeOutputSchema implies includeStructuredContent
Advertising an outputSchema while returning no structuredContent makes the
advertised schema inaccurate — spec-compliant clients reject the call. When
includeOutputSchema resolves to true, the gateway automatically forces
includeStructuredContent to true as well, and logs a warning naming the
route where the override kicked in.
You can set both explicitly to avoid the warning:
Code
Type reference
ZuploMcpToolResultOverride
Code
The subset of a tools/call result that a module author may override via
setRawCallToolResult. Every field is independently optional.
See also
- MCP Server custom tools — how to build custom MCP tool handlers with TypeScript
- MCP Server handler — handler configuration
reference including
includeOutputSchemaandincludeStructuredContent - MCP Gateway introduction — overview of the MCP Gateway product
- MCP specification — the canonical protocol reference