v2 refactor!: remove Zod schema parameter from public-facing APIs (#1606)

This commit is contained in:
Konstantin Konstantinov 2026-03-04 20:34:47 +02:00 • committed by GitHub
commit f88c376c52
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 1483 additions and 1708 deletions

View file

@ -11,7 +11,6 @@
import type { Prompt, Resource, Tool } from '@modelcontextprotocol/client';
import {
applyMiddlewares,
CallToolResultSchema,
Client,
ClientCredentialsProvider,
createMiddleware,
@ -181,13 +180,16 @@ async function callTool_structuredOutput(client: Client) {
/** Example: Track progress of a long-running tool call. */
async function callTool_progress(client: Client) {
//#region callTool_progress
const result = await client.callTool({ name: 'long-operation', arguments: {} }, undefined, {
onprogress: ({ progress, total }) => {
console.log(`Progress: ${progress}/${total ?? '?'}`);
},
resetTimeoutOnProgress: true,
maxTotalTimeout: 600_000
});
const result = await client.callTool(
{ name: 'long-operation', arguments: {} },
{
onprogress: ({ progress, total }: { progress: number; total?: number }) => {
console.log(`Progress: ${progress}/${total ?? '?'}`);
},
resetTimeoutOnProgress: true,
maxTotalTimeout: 600_000
}
);
console.log(result.content);
//#endregion callTool_progress
}
@ -450,7 +452,6 @@ async function errorHandling_timeout(client: Client) {
try {
const result = await client.callTool(
{ name: 'slow-task', arguments: {} },
undefined,
{ timeout: 120_000 } // 2 minutes instead of the default 60 seconds
);
console.log(result.content);
@ -492,7 +493,6 @@ async function resumptionToken_basic(client: Client) {
method: 'tools/call',
params: { name: 'long-running-task', arguments: {} }
},
CallToolResultSchema,
{
resumptionToken: lastToken,
onresumptiontoken: (token: string) => {

View file

@ -10,6 +10,7 @@ import { createInterface } from 'node:readline';
import type {
CallToolRequest,
CallToolResult,
ElicitRequest,
ElicitRequestURLParams,
ElicitResult,
@ -18,10 +19,8 @@ import type {
ResourceLink
} from '@modelcontextprotocol/client';
import {
CallToolResultSchema,
Client,
getDisplayName,
ListToolsResultSchema,
ProtocolError,
ProtocolErrorCode,
StreamableHTTPClientTransport,
@ -666,7 +665,7 @@ async function listTools(): Promise<void> {
method: 'tools/list',
params: {}
};
const toolsResult = await client.request(toolsRequest, ListToolsResultSchema);
const toolsResult = await client.request(toolsRequest);
console.log('Available tools:');
if (toolsResult.tools.length === 0) {
@ -697,7 +696,7 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<vo
};
console.log(`Calling tool '${name}' with args:`, args);
const result = await client.request(request, CallToolResultSchema);
const result = (await client.request(request)) as CallToolResult;
console.log('Tool result:');
const resourceLinks: ResourceLink[] = [];

View file

@ -1,5 +1,5 @@
import type { CallToolRequest, CallToolResult } from '@modelcontextprotocol/client';
import { CallToolResultSchema, Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
import { Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
/**
* Multiple Clients MCP Example
@ -60,7 +60,7 @@ async function createAndRunClient(config: ClientConfig): Promise<{ id: string; r
}
};
const result = await client.request(toolRequest, CallToolResultSchema);
const result = (await client.request(toolRequest)) as CallToolResult;
console.log(`[${config.id}] Tool call completed`);
// Keep the connection open for a bit to receive notifications

View file

@ -1,5 +1,5 @@
import type { CallToolResult, ListToolsRequest } from '@modelcontextprotocol/client';
import { CallToolResultSchema, Client, ListToolsResultSchema, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
import type { CallToolRequest, CallToolResult, ListToolsRequest } from '@modelcontextprotocol/client';
import { Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
/**
* Parallel Tool Calls MCP Client
@ -86,7 +86,7 @@ async function listTools(client: Client): Promise<void> {
method: 'tools/list',
params: {}
};
const toolsResult = await client.request(toolsRequest, ListToolsResultSchema);
const toolsResult = await client.request(toolsRequest);
console.log('Available tools:');
if (toolsResult.tools.length === 0) {
@ -108,7 +108,7 @@ async function listTools(client: Client): Promise<void> {
async function startParallelNotificationTools(client: Client): Promise<Record<string, CallToolResult>> {
try {
// Define multiple tool calls with different configurations
const toolCalls = [
const toolCalls: Array<{ caller: string; request: CallToolRequest }> = [
{
caller: 'fast-notifier',
request: {
@ -159,7 +159,7 @@ async function startParallelNotificationTools(client: Client): Promise<Record<st
const toolPromises = toolCalls.map(({ caller, request }) => {
console.log(`Starting tool call for ${caller}...`);
return client
.request(request, CallToolResultSchema)
.request(request)
.then(result => ({ caller, result }))
.catch(error => {
console.error(`Error in tool call for ${caller}:`, error);
@ -173,7 +173,7 @@ async function startParallelNotificationTools(client: Client): Promise<Record<st
// Organize results by caller
const resultsByTool: Record<string, CallToolResult> = {};
for (const { caller, result } of results) {
resultsByTool[caller] = result;
resultsByTool[caller] = result as CallToolResult;
}
return resultsByTool;

View file

@ -4,14 +4,8 @@ import { createServer } from 'node:http';
import { createInterface } from 'node:readline';
import { URL } from 'node:url';
import type { CallToolRequest, ListToolsRequest, OAuthClientMetadata } from '@modelcontextprotocol/client';
import {
CallToolResultSchema,
Client,
ListToolsResultSchema,
StreamableHTTPClientTransport,
UnauthorizedError
} from '@modelcontextprotocol/client';
import type { CallToolRequest, CallToolResult, ListToolsRequest, OAuthClientMetadata } from '@modelcontextprotocol/client';
import { Client, StreamableHTTPClientTransport, UnauthorizedError } from '@modelcontextprotocol/client';
import open from 'open';
import { InMemoryOAuthClientProvider } from './simpleOAuthClientProvider.js';
@ -262,7 +256,7 @@ class InteractiveOAuthClient {
params: {}
};
const result = await this.client.request(request, ListToolsResultSchema);
const result = await this.client.request(request);
if (result.tools && result.tools.length > 0) {
console.log('\n📋 Available tools:');
@ -320,7 +314,7 @@ class InteractiveOAuthClient {
}
};
const result = await this.client.request(request, CallToolResultSchema);
const result = (await this.client.request(request)) as CallToolResult;
console.log(`\n🔧 Tool '${toolName}' result:`);
if (result.content) {
@ -404,7 +398,8 @@ class InteractiveOAuthClient {
case 'result': {
console.log('✓ Completed!');
for (const content of message.result.content) {
const toolResult = message.result as CallToolResult;
for (const content of toolResult.content) {
if (content.type === 'text') {
console.log(content.text);
} else {

View file

@ -2,6 +2,7 @@ import { createInterface } from 'node:readline';
import type {
CallToolRequest,
CallToolResult,
GetPromptRequest,
ListPromptsRequest,
ListResourcesRequest,
@ -10,17 +11,11 @@ import type {
ResourceLink
} from '@modelcontextprotocol/client';
import {
CallToolResultSchema,
Client,
getDisplayName,
GetPromptResultSchema,
InMemoryTaskStore,
ListPromptsResultSchema,
ListResourcesResultSchema,
ListToolsResultSchema,
ProtocolError,
ProtocolErrorCode,
ReadResourceResultSchema,
RELATED_TASK_META_KEY,
StreamableHTTPClientTransport
} from '@modelcontextprotocol/client';
@ -541,13 +536,10 @@ async function connect(url?: string): Promise<void> {
console.log('Client disconnected, cannot fetch resources');
return;
}
const resourcesResult = await client.request(
{
method: 'resources/list',
params: {}
},
ListResourcesResultSchema
);
const resourcesResult = await client.request({
method: 'resources/list',
params: {}
});
console.log('Available resources count:', resourcesResult.resources.length);
} catch {
console.log('Failed to list resources after change notification');
@ -632,7 +624,7 @@ async function listTools(): Promise<void> {
method: 'tools/list',
params: {}
};
const toolsResult = await client.request(toolsRequest, ListToolsResultSchema);
const toolsResult = await client.request(toolsRequest);
console.log('Available tools:');
if (toolsResult.tools.length === 0) {
@ -663,7 +655,7 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<vo
};
console.log(`Calling tool '${name}' with args:`, args);
const result = await client.request(request, CallToolResultSchema);
const result = (await client.request(request)) as CallToolResult;
console.log('Tool result:');
const resourceLinks: ResourceLink[] = [];
@ -767,10 +759,10 @@ async function runNotificationsToolWithResumability(interval: number, count: num
console.log(`Updated resumption token: ${event}`);
};
const result = await client.request(request, CallToolResultSchema, {
const result = (await client.request(request, {
resumptionToken: notificationsToolLastEventId,
onresumptiontoken: onLastEventIdUpdate
});
})) as CallToolResult;
console.log('Tool result:');
for (const item of result.content) {
@ -796,7 +788,7 @@ async function listPrompts(): Promise<void> {
method: 'prompts/list',
params: {}
};
const promptsResult = await client.request(promptsRequest, ListPromptsResultSchema);
const promptsResult = await client.request(promptsRequest);
console.log('Available prompts:');
if (promptsResult.prompts.length === 0) {
console.log(' No prompts available');
@ -825,7 +817,7 @@ async function getPrompt(name: string, args: Record<string, unknown>): Promise<v
}
};
const promptResult = await client.request(promptRequest, GetPromptResultSchema);
const promptResult = await client.request(promptRequest);
console.log('Prompt template:');
for (const [index, msg] of promptResult.messages.entries()) {
console.log(` [${index + 1}] ${msg.role}: ${msg.content.type === 'text' ? msg.content.text : JSON.stringify(msg.content)}`);
@ -846,7 +838,7 @@ async function listResources(): Promise<void> {
method: 'resources/list',
params: {}
};
const resourcesResult = await client.request(resourcesRequest, ListResourcesResultSchema);
const resourcesResult = await client.request(resourcesRequest);
console.log('Available resources:');
if (resourcesResult.resources.length === 0) {
@ -874,7 +866,7 @@ async function readResource(uri: string): Promise<void> {
};
console.log(`Reading resource: ${uri}`);
const result = await client.request(request, ReadResourceResultSchema);
const result = await client.request(request);
console.log('Resource contents:');
for (const content of result.contents) {
@ -948,7 +940,8 @@ async function callToolTask(name: string, args: Record<string, unknown>): Promis
case 'result': {
console.log('Task completed!');
console.log('Tool result:');
for (const item of message.result.content) {
const toolResult = message.result as CallToolResult;
for (const item of toolResult.content) {
if (item.type === 'text') {
console.log(` ${item.text}`);
}

View file

@ -9,7 +9,7 @@
import { createInterface } from 'node:readline';
import type { CreateMessageRequest, CreateMessageResult, TextContent } from '@modelcontextprotocol/client';
import type { CallToolResult, CreateMessageRequest, CreateMessageResult, TextContent } from '@modelcontextprotocol/client';
import { Client, ProtocolError, ProtocolErrorCode, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
// Create readline interface for user input
@ -135,7 +135,8 @@ async function run(url: string): Promise<void> {
break;
}
case 'result': {
console.log(`Result: ${getTextContent(message.result)}`);
const toolResult = message.result as CallToolResult;
console.log(`Result: ${getTextContent(toolResult)}`);
break;
}
case 'error': {
@ -165,7 +166,8 @@ async function run(url: string): Promise<void> {
break;
}
case 'result': {
console.log(`Result:\n${getTextContent(message.result)}`);
const toolResult = message.result as CallToolResult;
console.log(`Result:\n${getTextContent(toolResult)}`);
break;
}
case 'error': {

View file

@ -12,7 +12,7 @@
* Run with: pnpm tsx src/ssePollingClient.ts
* Requires: ssePollingExample.ts server running on port 3001
*/
import { CallToolResultSchema, Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
import { Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
const SERVER_URL = 'http://localhost:3001/mcp';
@ -78,7 +78,6 @@ async function main(): Promise<void> {
arguments: {}
}
},
CallToolResultSchema,
{
// Track resumption tokens for debugging
onresumptiontoken: token => {

View file

@ -1,11 +1,5 @@
import type { CallToolRequest, ListToolsRequest } from '@modelcontextprotocol/client';
import {
CallToolResultSchema,
Client,
ListToolsResultSchema,
SSEClientTransport,
StreamableHTTPClientTransport
} from '@modelcontextprotocol/client';
import type { CallToolRequest, CallToolResult, ListToolsRequest } from '@modelcontextprotocol/client';
import { Client, SSEClientTransport, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
/**
* Simplified Backwards Compatible MCP Client
@ -135,7 +129,7 @@ async function listTools(client: Client): Promise<void> {
method: 'tools/list',
params: {}
};
const toolsResult = await client.request(toolsRequest, ListToolsResultSchema);
const toolsResult = await client.request(toolsRequest);
console.log('Available tools:');
if (toolsResult.tools.length === 0) {
@ -168,7 +162,7 @@ async function startNotificationTool(client: Client): Promise<void> {
};
console.log('Calling notification tool...');
const result = await client.request(request, CallToolResultSchema);
const result = (await client.request(request)) as CallToolResult;
console.log('Tool result:');
for (const item of result.content) {

View file

@ -16,13 +16,7 @@ import type {
ReadResourceResult,
ResourceLink
} from '@modelcontextprotocol/server';
import {
ElicitResultSchema,
InMemoryTaskMessageQueue,
InMemoryTaskStore,
isInitializeRequest,
McpServer
} from '@modelcontextprotocol/server';
import { InMemoryTaskMessageQueue, InMemoryTaskStore, isInitializeRequest, McpServer } from '@modelcontextprotocol/server';
import cors from 'cors';
import type { Request, Response } from 'express';
import * as z from 'zod/v4';
@ -222,17 +216,14 @@ const getServer = () => {
try {
// Use sendRequest through the ctx parameter to elicit input
const result = await ctx.mcpReq.send(
{
method: 'elicitation/create',
params: {
mode: 'form',
message,
requestedSchema
}
},
ElicitResultSchema
);
const result = await ctx.mcpReq.send({
method: 'elicitation/create',
params: {
mode: 'form',
message,
requestedSchema
}
});
if (result.action === 'accept') {
return {