-
Notifications
You must be signed in to change notification settings - Fork 0
McpAdapter: add callTool() method that returns raw CallToolResult #128
Description
Problem
McpAdapter.request<T>() unwraps the MCP CallToolResult and returns only the parsed data payload (from structuredContent or content[0].text). This makes it impossible for consumers to:
- Access
_meta.ui.resourceUri— needed to discover MCP App HTML resources for interactive rendering - Get the full
CallToolResult— needed by@mcp-ui/client'sAppRenderercomponent (thetoolResultprop) - Access the
content[]array — which may contain multiple content blocks (text, image, resource)
Since mcpClient and transport are private, there's no workaround without modifying the SDK.
Impact
Any app that wants to render MCP App UIs from Scope3 tool responses (like Claude Desktop and ChatGPT do) cannot use McpAdapter today. This affects our own product (Goldie/Bayes) and will affect any third-party consumer building MCP Apps-compatible hosts.
Proposed Solution
Add a callTool() method to McpAdapter that returns the raw CallToolResult:
async callTool(
method: HttpMethod,
path: string,
body?: unknown,
options?: RequestOptions
): Promise<CallToolResult> {
if (!this.connected) await this.connect();
const fullPath = this.buildPath(path, options);
const args = { method, path: fullPath, ...(body ? { body } : {}) };
return this.mcpClient.callTool({ name: 'api_call', arguments: args });
}Also add readResource() for fetching MCP App HTML:
async readResource(uri: string): Promise<ReadResourceResult> {
if (!this.connected) await this.connect();
return this.mcpClient.readResource({ uri });
}Extract the path-building logic from request() into a private buildPath() method so both request() and callTool() share it.
Add these as optional methods on BaseAdapter (non-breaking — RestAdapter doesn't implement them):
export interface BaseAdapter {
// ... existing ...
callTool?(method: HttpMethod, path: string, body?: unknown, options?: RequestOptions): Promise<CallToolResult>;
readResource?(uri: string): Promise<ReadResourceResult>;
}Backwards Compatibility
request<T>()behavior is unchanged- New methods are additive
BaseAdapteradditions are optional (no breaking change forRestAdapter)