@@ -162,6 +162,32 @@ export type NotificationOptions = {
162162 relatedTask ?: RelatedTaskMetadata ;
163163} ;
164164
165+ /**
166+ * v1-compat flat aliases — added by `withLegacyContextFields`.
167+ * The v2 nested forms (`ctx.mcpReq.*`, `ctx.http?.*`, `ctx.task?.*`) are preferred.
168+ * Do not add new fields here.
169+ */
170+ export interface LegacyContextFields {
171+ /** @deprecated Use `ctx.mcpReq.signal` */
172+ signal : AbortSignal ;
173+ /** @deprecated Use `ctx.mcpReq.id` */
174+ requestId : RequestId ;
175+ /** @deprecated Use `ctx.mcpReq._meta` */
176+ _meta ?: RequestMeta ;
177+ /** @deprecated Use `ctx.http?.authInfo` */
178+ authInfo ?: AuthInfo ;
179+ /** @deprecated Use `ctx.mcpReq.notify` */
180+ sendNotification : ( notification : Notification ) => Promise < void > ;
181+ /** @deprecated Use `ctx.mcpReq.send` */
182+ sendRequest : < T extends AnySchema > ( request : Request , resultSchema : T , options ?: RequestOptions ) => Promise < SchemaOutput < T > > ;
183+ /** @deprecated Use `ctx.task?.store` */
184+ taskStore ?: TaskContext [ 'store' ] ;
185+ /** @deprecated Use `ctx.task?.id` */
186+ taskId ?: TaskContext [ 'id' ] ;
187+ /** @deprecated Use `ctx.task?.requestedTtl` */
188+ taskRequestedTtl ?: TaskContext [ 'requestedTtl' ] ;
189+ }
190+
165191/**
166192 * Base context provided to all request handlers.
167193 */
@@ -272,12 +298,45 @@ export type ServerContext = BaseContext & {
272298 */
273299 closeStandaloneSSE ?: ( ) => void ;
274300 } ;
275- } ;
301+ } & LegacyContextFields ;
276302
277303/**
278304 * Context provided to client-side request handlers.
279305 */
280- export type ClientContext = BaseContext ;
306+ export type ClientContext = BaseContext & LegacyContextFields ;
307+
308+ /**
309+ * v1 name for the handler context. v2 also exposes the same data under
310+ * `ctx.mcpReq` / `ctx.http`; the flat fields remain available so existing
311+ * handlers compile and run unchanged. See {@linkcode BaseContext}.
312+ */
313+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- phantom params kept for v1 source compatibility
314+ export type RequestHandlerExtra < _Req = unknown , _Notif = unknown > = ServerContext ;
315+
316+ /**
317+ * Returns a copy of `ctx` with v1's flat `extra.*` aliases populated as plain properties
318+ * mirroring the nested v2 fields. Intersected onto `ClientContext`/`ServerContext` so
319+ * existing handlers that read `extra.signal` etc. compile and run unchanged.
320+ *
321+ * @internal
322+ */
323+ function withLegacyContextFields < T extends BaseContext > (
324+ ctx : T ,
325+ sendRequest : < S extends AnySchema > ( r : Request , s : S , o ?: RequestOptions ) => Promise < SchemaOutput < S > >
326+ ) : T & LegacyContextFields {
327+ return {
328+ ...ctx ,
329+ signal : ctx . mcpReq . signal ,
330+ requestId : ctx . mcpReq . id ,
331+ _meta : ctx . mcpReq . _meta ,
332+ authInfo : ctx . http ?. authInfo ,
333+ sendNotification : ctx . mcpReq . notify ,
334+ sendRequest,
335+ taskStore : ctx . task ?. store ,
336+ taskId : ctx . task ?. id ,
337+ taskRequestedTtl : ctx . task ?. requestedTtl
338+ } ;
339+ }
281340
282341/**
283342 * Information about a request's timeout state
@@ -393,7 +452,7 @@ export abstract class Protocol<ContextT extends BaseContext> {
393452 * Builds the context object for request handlers. Subclasses must override
394453 * to return the appropriate context type (e.g., ServerContext adds HTTP request info).
395454 */
396- protected abstract buildContext ( ctx : BaseContext , transportInfo ?: MessageExtraInfo ) : ContextT ;
455+ protected abstract buildContext ( ctx : BaseContext & LegacyContextFields , transportInfo ?: MessageExtraInfo ) : ContextT ;
397456
398457 private async _oncancel ( notification : CancelledNotification ) : Promise < void > {
399458 if ( ! notification . params . requestId ) {
@@ -605,7 +664,7 @@ export abstract class Protocol<ContextT extends BaseContext> {
605664 http : extra ?. authInfo ? { authInfo : extra . authInfo } : undefined ,
606665 task : taskContext
607666 } ;
608- const ctx = this . buildContext ( baseCtx , extra ) ;
667+ const ctx = this . buildContext ( withLegacyContextFields ( baseCtx , sendRequest ) , extra ) ;
609668
610669 // Starting with Promise.resolve() puts any synchronous errors into the monad as well.
611670 Promise . resolve ( )
0 commit comments