Skip to content

Commit b4278c8

Browse files
committed
remove result generic and notification generic, align types with Task types from 2025-11-25 spec
1 parent a297f9d commit b4278c8

File tree

13 files changed

+700
-259
lines changed

13 files changed

+700
-259
lines changed

src/client/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ import {
4646
ListChangedOptions,
4747
ListChangedOptionsBaseSchema,
4848
type ListChangedHandlers,
49-
type RequestGeneric,
50-
type NotificationGeneric,
49+
type Request,
50+
type Notification,
5151
type Result
5252
} from '../types.js';
5353
import { AjvJsonSchemaValidator } from '../validation/ajv-provider.js';
@@ -231,8 +231,8 @@ export type ClientOptions = ProtocolOptions & {
231231
* ```
232232
*/
233233
export class Client<
234-
RequestT extends RequestGeneric = RequestGeneric,
235-
NotificationT extends NotificationGeneric = NotificationGeneric,
234+
RequestT extends Request = Request,
235+
NotificationT extends Notification = Notification,
236236
ResultT extends Result = Result
237237
> extends Protocol<ClientRequest | RequestT, ClientNotification | NotificationT, ClientResult | ResultT> {
238238
private _serverCapabilities?: ServerCapabilities;

src/client/streamableHttp.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Transport, FetchLike, createFetchWithInit, normalizeHeaders } from '../shared/transport.js';
2-
import { isInitializedNotification, isJSONRPCRequest, isJSONRPCResponse, JSONRPCMessage, JSONRPCMessageSchema } from '../types.js';
2+
import { isInitializedNotification, isJSONRPCRequest, isJSONRPCResultResponse, JSONRPCMessage, JSONRPCMessageSchema } from '../types.js';
33
import { auth, AuthResult, extractWWWAuthenticateParams, OAuthClientProvider, UnauthorizedError } from './auth.js';
44
import { EventSourceParserStream } from 'eventsource-parser/stream';
55

@@ -350,7 +350,7 @@ export class StreamableHTTPClientTransport implements Transport {
350350
if (!event.event || event.event === 'message') {
351351
try {
352352
const message = JSONRPCMessageSchema.parse(JSON.parse(event.data));
353-
if (isJSONRPCResponse(message)) {
353+
if (isJSONRPCResultResponse(message)) {
354354
// Mark that we received a response - no need to reconnect for this request
355355
receivedResponse = true;
356356
if (replayMessageId !== undefined) {

src/experimental/tasks/interfaces.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import {
99
Result,
1010
JSONRPCRequest,
1111
JSONRPCNotification,
12-
JSONRPCResponse,
13-
JSONRPCError,
12+
JSONRPCResultResponse,
13+
JSONRPCErrorResponse,
1414
ServerRequest,
1515
ServerNotification,
1616
CallToolResult,
1717
GetTaskResult,
1818
ToolExecution,
19-
RequestGeneric
19+
Request
2020
} from '../../types.js';
2121
import { CreateTaskResult } from './types.js';
2222
import type { RequestHandlerExtra, RequestTaskStore } from '../../shared/protocol.js';
@@ -124,13 +124,13 @@ export interface QueuedNotification extends BaseQueuedMessage {
124124
export interface QueuedResponse extends BaseQueuedMessage {
125125
type: 'response';
126126
/** The actual JSONRPC response */
127-
message: JSONRPCResponse;
127+
message: JSONRPCResultResponse;
128128
}
129129

130130
export interface QueuedError extends BaseQueuedMessage {
131131
type: 'error';
132132
/** The actual JSONRPC error */
133-
message: JSONRPCError;
133+
message: JSONRPCErrorResponse;
134134
}
135135

136136
/**
@@ -226,7 +226,7 @@ export interface TaskStore {
226226
* @param sessionId - Optional session ID for binding the task to a specific session
227227
* @returns The created task object
228228
*/
229-
createTask(taskParams: CreateTaskOptions, requestId: RequestId, request: RequestGeneric, sessionId?: string): Promise<Task>;
229+
createTask(taskParams: CreateTaskOptions, requestId: RequestId, request: Request, sessionId?: string): Promise<Task>;
230230

231231
/**
232232
* Gets the current status of a task.

src/experimental/tasks/stores/in-memory.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
* @experimental
66
*/
77

8-
import { Task, RequestId, Result, RequestGeneric } from '../../../types.js';
8+
import { Task, RequestId, Result, Request } from '../../../types.js';
99
import { TaskStore, isTerminal, TaskMessageQueue, QueuedMessage, CreateTaskOptions } from '../interfaces.js';
1010
import { randomBytes } from 'node:crypto';
1111

1212
interface StoredTask {
1313
task: Task;
14-
request: RequestGeneric;
14+
request: Request;
1515
requestId: RequestId;
1616
result?: Result;
1717
}
@@ -39,7 +39,7 @@ export class InMemoryTaskStore implements TaskStore {
3939
return randomBytes(16).toString('hex');
4040
}
4141

42-
async createTask(taskParams: CreateTaskOptions, requestId: RequestId, request: RequestGeneric, _sessionId?: string): Promise<Task> {
42+
async createTask(taskParams: CreateTaskOptions, requestId: RequestId, request: Request, _sessionId?: string): Promise<Task> {
4343
// Generate a unique task ID
4444
const taskId = this.generateTaskId();
4545

src/server/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ import {
3838
CallToolRequestSchema,
3939
CallToolResultSchema,
4040
CreateTaskResultSchema,
41-
type RequestGeneric,
42-
type NotificationGeneric,
41+
type Request,
42+
type Notification,
4343
type Result
4444
} from '../types.js';
4545
import { AjvJsonSchemaValidator } from '../validation/ajv-provider.js';
@@ -127,8 +127,8 @@ export type ServerOptions = ProtocolOptions & {
127127
* @deprecated Use `McpServer` instead for the high-level API. Only use `Server` for advanced use cases.
128128
*/
129129
export class Server<
130-
RequestT extends RequestGeneric = RequestGeneric,
131-
NotificationT extends NotificationGeneric = NotificationGeneric,
130+
RequestT extends Request = Request,
131+
NotificationT extends Notification = Notification,
132132
ResultT extends Result = Result
133133
> extends Protocol<ServerRequest | RequestT, ServerNotification | NotificationT, ServerResult | ResultT> {
134134
private _clientCapabilities?: ClientCapabilities;

src/server/streamableHttp.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import {
44
MessageExtraInfo,
55
RequestInfo,
66
isInitializeRequest,
7-
isJSONRPCError,
87
isJSONRPCRequest,
9-
isJSONRPCResponse,
8+
isJSONRPCResultResponse,
109
JSONRPCMessage,
1110
JSONRPCMessageSchema,
1211
RequestId,
1312
SUPPORTED_PROTOCOL_VERSIONS,
14-
DEFAULT_NEGOTIATED_PROTOCOL_VERSION
13+
DEFAULT_NEGOTIATED_PROTOCOL_VERSION,
14+
isJSONRPCErrorResponse
1515
} from '../types.js';
1616
import getRawBody from 'raw-body';
1717
import contentType from 'content-type';
@@ -858,7 +858,7 @@ export class StreamableHTTPServerTransport implements Transport {
858858

859859
async send(message: JSONRPCMessage, options?: { relatedRequestId?: RequestId }): Promise<void> {
860860
let requestId = options?.relatedRequestId;
861-
if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
861+
if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
862862
// If the message is a response, use the request ID from the message
863863
requestId = message.id;
864864
}
@@ -868,7 +868,7 @@ export class StreamableHTTPServerTransport implements Transport {
868868
// Those will be sent via dedicated response SSE streams
869869
if (requestId === undefined) {
870870
// For standalone SSE streams, we can only send requests and notifications
871-
if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
871+
if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
872872
throw new Error('Cannot send a response on a standalone SSE stream unless resuming a previous client request');
873873
}
874874

@@ -911,7 +911,7 @@ export class StreamableHTTPServerTransport implements Transport {
911911
}
912912
}
913913

914-
if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
914+
if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
915915
this._requestResponseMap.set(requestId, message);
916916
const relatedIds = Array.from(this._requestToStreamMapping.entries())
917917
.filter(([_, streamId]) => this._streamMapping.get(streamId) === response)

src/shared/protocol.ts

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ import {
1313
ListTasksResultSchema,
1414
CancelTaskRequestSchema,
1515
CancelTaskResultSchema,
16-
isJSONRPCError,
16+
isJSONRPCErrorResponse,
1717
isJSONRPCRequest,
18-
isJSONRPCResponse,
18+
isJSONRPCResultResponse,
1919
isJSONRPCNotification,
20-
JSONRPCError,
20+
JSONRPCErrorResponse,
2121
JSONRPCNotification,
2222
JSONRPCRequest,
2323
JSONRPCResponse,
@@ -40,8 +40,10 @@ import {
4040
Task,
4141
TaskStatusNotification,
4242
TaskStatusNotificationSchema,
43-
RequestGeneric,
44-
NotificationGeneric
43+
Request,
44+
Notification,
45+
JSONRPCResultResponse,
46+
isTaskAugmentedRequestParams
4547
} from '../types.js';
4648
import { Transport, TransportSendOptions } from './transport.js';
4749
import { AuthInfo } from '../server/auth/types.js';
@@ -232,7 +234,7 @@ export interface RequestTaskStore {
232234
/**
233235
* Extra data given to request handlers.
234236
*/
235-
export type RequestHandlerExtra<SendRequestT extends RequestGeneric, SendNotificationT extends NotificationGeneric> = {
237+
export type RequestHandlerExtra<SendRequestT extends Request, SendNotificationT extends Notification> = {
236238
/**
237239
* An abort signal used to communicate if the request was cancelled from the sender's side.
238240
*/
@@ -315,11 +317,7 @@ type TimeoutInfo = {
315317
* Implements MCP protocol framing on top of a pluggable transport, including
316318
* features like request/response linking, notifications, and progress.
317319
*/
318-
export abstract class Protocol<
319-
SendRequestT extends RequestGeneric,
320-
SendNotificationT extends NotificationGeneric,
321-
SendResultT extends Result
322-
> {
320+
export abstract class Protocol<SendRequestT extends Request, SendNotificationT extends Notification, SendResultT extends Result> {
323321
private _transport?: Transport;
324322
private _requestMessageId = 0;
325323
private _requestHandlers: Map<
@@ -328,7 +326,7 @@ export abstract class Protocol<
328326
> = new Map();
329327
private _requestHandlerAbortControllers: Map<RequestId, AbortController> = new Map();
330328
private _notificationHandlers: Map<string, (notification: JSONRPCNotification) => Promise<void>> = new Map();
331-
private _responseHandlers: Map<number, (response: JSONRPCResponse | Error) => void> = new Map();
329+
private _responseHandlers: Map<number, (response: JSONRPCResultResponse | Error) => void> = new Map();
332330
private _progressHandlers: Map<number, ProgressCallback> = new Map();
333331
private _timeoutInfo: Map<number, TimeoutInfo> = new Map();
334332
private _pendingDebouncedNotifications = new Set<string>();
@@ -339,7 +337,7 @@ export abstract class Protocol<
339337
private _taskStore?: TaskStore;
340338
private _taskMessageQueue?: TaskMessageQueue;
341339

342-
private _requestResolvers: Map<RequestId, (response: JSONRPCResponse | Error) => void> = new Map();
340+
private _requestResolvers: Map<RequestId, (response: JSONRPCResultResponse | Error) => void> = new Map();
343341

344342
/**
345343
* Callback for when the connection is closed for any reason.
@@ -363,7 +361,7 @@ export abstract class Protocol<
363361
/**
364362
* A handler to invoke for any notification types that do not have their own handler installed.
365363
*/
366-
fallbackNotificationHandler?: (notification: NotificationGeneric) => Promise<void>;
364+
fallbackNotificationHandler?: (notification: Notification) => Promise<void>;
367365

368366
constructor(private _options?: ProtocolOptions) {
369367
this.setNotificationHandler(CancelledNotificationSchema, notification => {
@@ -412,18 +410,18 @@ export abstract class Protocol<
412410
const requestId = message.id;
413411

414412
// Lookup resolver in _requestResolvers map
415-
const resolver = this._requestResolvers.get(requestId);
413+
const resolver = this._requestResolvers.get(requestId as RequestId);
416414

417415
if (resolver) {
418416
// Remove resolver from map after invocation
419-
this._requestResolvers.delete(requestId);
417+
this._requestResolvers.delete(requestId as RequestId);
420418

421419
// Invoke resolver with response or error
422420
if (queuedMessage.type === 'response') {
423-
resolver(message as JSONRPCResponse);
421+
resolver(message as JSONRPCResultResponse);
424422
} else {
425423
// Convert JSONRPCError to McpError
426-
const errorMessage = message as JSONRPCError;
424+
const errorMessage = message as JSONRPCErrorResponse;
427425
const error = new McpError(
428426
errorMessage.error.code,
429427
errorMessage.error.message,
@@ -550,6 +548,9 @@ export abstract class Protocol<
550548
}
551549

552550
private async _oncancel(notification: CancelledNotification): Promise<void> {
551+
if (!notification.params.requestId) {
552+
return;
553+
}
553554
// Handle request cancellation
554555
const controller = this._requestHandlerAbortControllers.get(notification.params.requestId);
555556
controller?.abort(notification.params.reason);
@@ -620,7 +621,7 @@ export abstract class Protocol<
620621
const _onmessage = this._transport?.onmessage;
621622
this._transport.onmessage = (message, extra) => {
622623
_onmessage?.(message, extra);
623-
if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
624+
if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
624625
this._onresponse(message);
625626
} else if (isJSONRPCRequest(message)) {
626627
this._onrequest(message, extra);
@@ -679,7 +680,7 @@ export abstract class Protocol<
679680
const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
680681

681682
if (handler === undefined) {
682-
const errorResponse: JSONRPCError = {
683+
const errorResponse: JSONRPCErrorResponse = {
683684
jsonrpc: '2.0',
684685
id: request.id,
685686
error: {
@@ -710,7 +711,7 @@ export abstract class Protocol<
710711
const abortController = new AbortController();
711712
this._requestHandlerAbortControllers.set(request.id, abortController);
712713

713-
const taskCreationParams = request.params?.task;
714+
const taskCreationParams = isTaskAugmentedRequestParams(request.params) ? request.params.task : undefined;
714715
const taskStore = this._taskStore ? this.requestTaskStore(request, capturedTransport?.sessionId) : undefined;
715716

716717
const fullExtra: RequestHandlerExtra<SendRequestT, SendNotificationT> = {
@@ -795,7 +796,7 @@ export abstract class Protocol<
795796
return;
796797
}
797798

798-
const errorResponse: JSONRPCError = {
799+
const errorResponse: JSONRPCErrorResponse = {
799800
jsonrpc: '2.0',
800801
id: request.id,
801802
error: {
@@ -856,14 +857,14 @@ export abstract class Protocol<
856857
handler(params);
857858
}
858859

859-
private _onresponse(response: JSONRPCResponse | JSONRPCError): void {
860+
private _onresponse(response: JSONRPCResponse | JSONRPCErrorResponse): void {
860861
const messageId = Number(response.id);
861862

862863
// Check if this is a response to a queued request
863864
const resolver = this._requestResolvers.get(messageId);
864865
if (resolver) {
865866
this._requestResolvers.delete(messageId);
866-
if (isJSONRPCResponse(response)) {
867+
if (isJSONRPCResultResponse(response)) {
867868
resolver(response);
868869
} else {
869870
const error = new McpError(response.error.code, response.error.message, response.error.data);
@@ -883,7 +884,7 @@ export abstract class Protocol<
883884

884885
// Keep progress handler alive for CreateTaskResult responses
885886
let isTaskResponse = false;
886-
if (isJSONRPCResponse(response) && response.result && typeof response.result === 'object') {
887+
if (isJSONRPCResultResponse(response) && response.result && typeof response.result === 'object') {
887888
const result = response.result as Record<string, unknown>;
888889
if (result.task && typeof result.task === 'object') {
889890
const task = result.task as Record<string, unknown>;
@@ -898,7 +899,7 @@ export abstract class Protocol<
898899
this._progressHandlers.delete(messageId);
899900
}
900901

901-
if (isJSONRPCResponse(response)) {
902+
if (isJSONRPCResultResponse(response)) {
902903
handler(response);
903904
} else {
904905
const error = McpError.fromError(response.error.code, response.error.message, response.error.data);
@@ -1195,7 +1196,7 @@ export abstract class Protocol<
11951196
const relatedTaskId = relatedTask?.taskId;
11961197
if (relatedTaskId) {
11971198
// Store the response resolver for this request so responses can be routed back
1198-
const responseResolver = (response: JSONRPCResponse | Error) => {
1199+
const responseResolver = (response: JSONRPCResultResponse | Error) => {
11991200
const handler = this._responseHandlers.get(messageId);
12001201
if (handler) {
12011202
handler(response);

0 commit comments

Comments
 (0)