Skip to content

Commit 2a33e25

Browse files
olaservoclaude
andcommitted
Integrate progress notification support with PR modelcontextprotocol#373 timeout configuration
Merged with feat-cli-server-request-configs branch and refactored to use the existing RequestOptions from the SDK instead of custom timeout types. Changes: - Use SDK RequestOptions type instead of custom TimeoutOptions interface - Pass mcpRequestOptions from CLI args through to callTool() - Add onprogress callback when resetTimeoutOnProgress is enabled - Remove duplicate CLI option definitions (already in PR modelcontextprotocol#373) - Remove debug logging This completes the implementation of progress notification capture and timeout reset functionality for CLI mode, building on the timeout flag support added in PR modelcontextprotocol#373. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 6b3c0a4 commit 2a33e25

2 files changed

Lines changed: 15 additions & 79 deletions

File tree

cli/src/client/tools.ts

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
22
import type { Progress } from "@modelcontextprotocol/sdk/types.js";
33
import { CallToolResultSchema, Tool } from "@modelcontextprotocol/sdk/types.js";
4+
import { RequestOptions } from "@modelcontextprotocol/sdk/shared/protocol.js";
45
import { McpResponse } from "./types.js";
56

67
// JSON value type matching the client utils
@@ -79,17 +80,11 @@ function convertParameters(
7980
return result;
8081
}
8182

82-
export interface TimeoutOptions {
83-
requestTimeout?: number;
84-
resetTimeoutOnProgress?: boolean;
85-
maxTotalTimeout?: number;
86-
}
87-
8883
export async function callTool(
8984
client: Client,
9085
name: string,
9186
args: Record<string, JsonValue>,
92-
timeoutOptions?: TimeoutOptions,
87+
requestOptions?: RequestOptions,
9388
): Promise<McpResponse> {
9489
try {
9590
const toolsResponse = await listTools(client);
@@ -114,31 +109,15 @@ export async function callTool(
114109
}
115110
}
116111

117-
// Prepare SDK request options with timeout configuration
118-
const requestOptions: {
119-
timeout?: number;
120-
resetTimeoutOnProgress?: boolean;
121-
maxTotalTimeout?: number;
122-
onprogress?: (params: Progress) => void;
123-
} = {};
124-
125-
if (timeoutOptions?.requestTimeout !== undefined) {
126-
requestOptions.timeout = timeoutOptions.requestTimeout;
127-
}
128-
129-
if (timeoutOptions?.resetTimeoutOnProgress !== undefined) {
130-
requestOptions.resetTimeoutOnProgress =
131-
timeoutOptions.resetTimeoutOnProgress;
132-
}
133-
134-
if (timeoutOptions?.maxTotalTimeout !== undefined) {
135-
requestOptions.maxTotalTimeout = timeoutOptions.maxTotalTimeout;
136-
}
112+
// Prepare SDK request options with timeout configuration and progress callback
113+
const options: RequestOptions = {
114+
...requestOptions,
115+
};
137116

138117
// If progress notifications are enabled, add an onprogress hook
139118
// This is required by SDK to reset the timeout on progress notifications
140-
if (requestOptions.resetTimeoutOnProgress) {
141-
requestOptions.onprogress = (params: Progress) => {
119+
if (options.resetTimeoutOnProgress) {
120+
options.onprogress = (params: Progress) => {
142121
// Display progress notification to stderr (so it doesn't interfere with JSON output on stdout)
143122
const progressInfo = {
144123
method: "notifications/progress",
@@ -159,7 +138,7 @@ export async function callTool(
159138
},
160139
},
161140
CallToolResultSchema,
162-
requestOptions,
141+
options,
163142
);
164143
return response;
165144
} catch (error) {

cli/src/index.ts

Lines changed: 6 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,6 @@ type Args = {
4747
maxTotalTimeout?: number;
4848
transport?: "sse" | "stdio" | "http";
4949
headers?: Record<string, string>;
50-
requestTimeout?: number;
51-
resetTimeoutOnProgress?: boolean;
52-
maxTotalTimeout?: number;
5350
};
5451

5552
function createTransportOptions(
@@ -150,11 +147,12 @@ async function callMethod(args: Args): Promise<void> {
150147
);
151148
}
152149

153-
result = await callTool(client, args.toolName, args.toolArg || {}, {
154-
requestTimeout: args.requestTimeout,
155-
resetTimeoutOnProgress: args.resetTimeoutOnProgress,
156-
maxTotalTimeout: args.maxTotalTimeout,
157-
});
150+
result = await callTool(
151+
client,
152+
args.toolName,
153+
args.toolArg || {},
154+
mcpRequestOptions,
155+
);
158156
}
159157
// Resources methods
160158
else if (args.method === "resources/list") {
@@ -378,47 +376,6 @@ function parseArgs(): Args {
378376
'HTTP headers as "HeaderName: Value" pairs (for HTTP/SSE transports)',
379377
parseHeaderPair,
380378
{},
381-
)
382-
//
383-
// Request timeout options
384-
//
385-
.option(
386-
"--request-timeout <milliseconds>",
387-
"Timeout for individual MCP requests in milliseconds",
388-
(value: string) => {
389-
const timeout = parseInt(value, 10);
390-
if (isNaN(timeout) || timeout <= 0) {
391-
throw new Error(
392-
`Invalid request timeout: ${value}. Must be a positive integer.`,
393-
);
394-
}
395-
return timeout;
396-
},
397-
)
398-
.option(
399-
"--reset-timeout-on-progress <boolean>",
400-
"Reset request timeout when progress notifications are received (true/false)",
401-
(value: string) => {
402-
if (value !== "true" && value !== "false") {
403-
throw new Error(
404-
`Invalid reset-timeout-on-progress value: ${value}. Must be 'true' or 'false'.`,
405-
);
406-
}
407-
return value === "true";
408-
},
409-
)
410-
.option(
411-
"--max-total-timeout <milliseconds>",
412-
"Maximum total timeout for requests including progress resets in milliseconds",
413-
(value: string) => {
414-
const timeout = parseInt(value, 10);
415-
if (isNaN(timeout) || timeout <= 0) {
416-
throw new Error(
417-
`Invalid max total timeout: ${value}. Must be a positive integer.`,
418-
);
419-
}
420-
return timeout;
421-
},
422379
);
423380

424381
// Parse only the arguments before --

0 commit comments

Comments
 (0)