[RFC] refactor: remove vestigial generic type parameters from Protocol, Server, and Client (#1451)

This commit is contained in:
Felix Weinberger 2026-02-03 20:55:32 +00:00 • committed by GitHub
commit faeb03ec17
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 210 additions and 306 deletions

View file

@ -23,8 +23,8 @@ import type { BaseToolCallback } from '../../server/mcp.js';
* Handler for creating a task.
* @experimental
*/
export type CreateTaskRequestHandler<SendResultT extends Result, Args extends AnySchema | undefined = undefined> = BaseToolCallback<
SendResultT,
export type CreateTaskRequestHandler<ResultT extends Result, Args extends AnySchema | undefined = undefined> = BaseToolCallback<
ResultT,
CreateTaskServerContext,
Args
>;
@ -33,8 +33,8 @@ export type CreateTaskRequestHandler<SendResultT extends Result, Args extends An
* Handler for task operations (get, getResult).
* @experimental
*/
export type TaskRequestHandler<SendResultT extends Result, Args extends AnySchema | undefined = undefined> = BaseToolCallback<
SendResultT,
export type TaskRequestHandler<ResultT extends Result, Args extends AnySchema | undefined = undefined> = BaseToolCallback<
ResultT,
TaskServerContext,
Args
>;

View file

@ -10,13 +10,11 @@ import type {
CancelTaskResult,
GetTaskResult,
ListTasksResult,
Notification,
Request,
RequestOptions,
ResponseMessage,
Result,
SchemaOutput,
ServerRequest
SchemaOutput
} from '@modelcontextprotocol/core';
import type { Server } from '../../server/server.js';
@ -33,12 +31,8 @@ import type { Server } from '../../server/server.js';
*
* @experimental
*/
export class ExperimentalServerTasks<
RequestT extends Request = Request,
NotificationT extends Notification = Notification,
ResultT extends Result = Result
> {
constructor(private readonly _server: Server<RequestT, NotificationT, ResultT>) {}
export class ExperimentalServerTasks {
constructor(private readonly _server: Server) {}
/**
* Sends a request and returns an AsyncGenerator that yields response messages.
@ -55,14 +49,14 @@ export class ExperimentalServerTasks<
* @experimental
*/
requestStream<T extends AnySchema>(
request: ServerRequest | RequestT,
request: Request,
resultSchema: T,
options?: RequestOptions
): AsyncGenerator<ResponseMessage<SchemaOutput<T> & Result>, void, void> {
// Delegate to the server's underlying Protocol method
type ServerWithRequestStream = {
requestStream<U extends AnySchema>(
request: ServerRequest | RequestT,
request: Request,
resultSchema: U,
options?: RequestOptions
): AsyncGenerator<ResponseMessage<SchemaOutput<U> & Result>, void, void>;

View file

@ -980,13 +980,9 @@ export class ResourceTemplate {
}
}
export type BaseToolCallback<
SendResultT extends Result,
Ctx extends ServerContext,
Args extends AnySchema | undefined
> = Args extends AnySchema
? (args: SchemaOutput<Args>, ctx: Ctx) => SendResultT | Promise<SendResultT>
: (ctx: Ctx) => SendResultT | Promise<SendResultT>;
export type BaseToolCallback<ResultT extends Result, Ctx extends ServerContext, Args extends AnySchema | undefined> = Args extends AnySchema
? (args: SchemaOutput<Args>, ctx: Ctx) => ResultT | Promise<ResultT>
: (ctx: Ctx) => ResultT | Promise<ResultT>;
/**
* Callback for a tool handler registered with Server.tool().

View file

@ -18,19 +18,16 @@ import type {
LoggingLevel,
LoggingMessageNotification,
MessageExtraInfo,
Notification,
NotificationMethod,
NotificationOptions,
ProtocolOptions,
Request,
RequestMethod,
RequestOptions,
RequestTypeMap,
ResourceUpdatedNotification,
Result,
ResultTypeMap,
ServerCapabilities,
ServerContext,
ServerNotification,
ServerRequest,
ServerResult,
ToolResultContent,
ToolUseContent
@ -87,43 +84,15 @@ export type ServerOptions = ProtocolOptions & {
*
* This server will automatically respond to the initialization flow as initiated from the client.
*
* To use with custom types, extend the base Request/Notification/Result types and pass them as type parameters:
*
* ```typescript
* // Custom schemas
* const CustomRequestSchema = RequestSchema.extend({...})
* const CustomNotificationSchema = NotificationSchema.extend({...})
* const CustomResultSchema = ResultSchema.extend({...})
*
* // Type aliases
* type CustomRequest = z.infer<typeof CustomRequestSchema>
* type CustomNotification = z.infer<typeof CustomNotificationSchema>
* type CustomResult = z.infer<typeof CustomResultSchema>
*
* // Create typed server
* const server = new Server<CustomRequest, CustomNotification, CustomResult>({
* name: "CustomServer",
* version: "1.0.0"
* })
* ```
* @deprecated Use `McpServer` instead for the high-level API. Only use `Server` for advanced use cases.
*/
export class Server<
RequestT extends Request = Request,
NotificationT extends Notification = Notification,
ResultT extends Result = Result
> extends Protocol<
ServerRequest | RequestT,
ServerNotification | NotificationT,
ServerResult | ResultT,
ServerContext<ServerRequest | RequestT, ServerNotification | NotificationT>
> {
export class Server extends Protocol<ServerContext> {
private _clientCapabilities?: ClientCapabilities;
private _clientVersion?: Implementation;
private _capabilities: ServerCapabilities;
private _instructions?: string;
private _jsonSchemaValidator: jsonSchemaValidator;
private _experimental?: { tasks: ExperimentalServerTasks<RequestT, NotificationT, ResultT> };
private _experimental?: { tasks: ExperimentalServerTasks };
/**
* Callback for when initialization has fully completed (i.e., the client has sent an `initialized` notification).
@ -159,10 +128,7 @@ export class Server<
}
}
protected override buildContext(
ctx: BaseContext<ServerRequest | RequestT, ServerNotification | NotificationT>,
transportInfo?: MessageExtraInfo
): ServerContext<ServerRequest | RequestT, ServerNotification | NotificationT> {
protected override buildContext(ctx: BaseContext, transportInfo?: MessageExtraInfo): ServerContext {
// Only create http when there's actual HTTP transport info or auth info
const hasHttpInfo =
ctx.http || transportInfo?.requestInfo || transportInfo?.closeSSEStream || transportInfo?.closeStandaloneSSEStream;
@ -192,7 +158,7 @@ export class Server<
*
* @experimental
*/
get experimental(): { tasks: ExperimentalServerTasks<RequestT, NotificationT, ResultT> } {
get experimental(): { tasks: ExperimentalServerTasks } {
if (!this._experimental) {
this._experimental = {
tasks: new ExperimentalServerTasks(this)
@ -230,16 +196,10 @@ export class Server<
*/
public override setRequestHandler<M extends RequestMethod>(
method: M,
handler: (
request: RequestTypeMap[M],
ctx: ServerContext<ServerRequest | RequestT, ServerNotification | NotificationT>
) => ServerResult | ResultT | Promise<ServerResult | ResultT>
handler: (request: RequestTypeMap[M], ctx: ServerContext) => ResultTypeMap[M] | Promise<ResultTypeMap[M]>
): void {
if (method === 'tools/call') {
const wrappedHandler = async (
request: RequestTypeMap[M],
ctx: ServerContext<ServerRequest | RequestT, ServerNotification | NotificationT>
): Promise<ServerResult | ResultT> => {
const wrappedHandler = async (request: RequestTypeMap[M], ctx: ServerContext): Promise<ServerResult> => {
const validatedRequest = parseSchema(CallToolRequestSchema, request);
if (!validatedRequest.success) {
const errorMessage =
@ -283,8 +243,8 @@ export class Server<
return super.setRequestHandler(method, handler);
}
protected assertCapabilityForMethod(method: RequestT['method']): void {
switch (method as ServerRequest['method']) {
protected assertCapabilityForMethod(method: RequestMethod): void {
switch (method) {
case 'sampling/createMessage': {
if (!this._clientCapabilities?.sampling) {
throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Client does not support sampling (required for ${method})`);
@ -316,8 +276,8 @@ export class Server<
}
}
protected assertNotificationCapability(method: (ServerNotification | NotificationT)['method']): void {
switch (method as ServerNotification['method']) {
protected assertNotificationCapability(method: NotificationMethod): void {
switch (method) {
case 'notifications/message': {
if (!this._capabilities.logging) {
throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Server does not support logging (required for ${method})`);