@@ -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 */
@@ -282,12 +308,49 @@ export type ServerContext = BaseContext & {
282308 */
283309 closeStandaloneSSE ?: ( ) => void ;
284310 } ;
285- } ;
311+ } & LegacyContextFields ;
286312
287313/**
288314 * Context provided to client-side request handlers.
289315 */
290- export type ClientContext = BaseContext ;
316+ export type ClientContext = BaseContext & LegacyContextFields ;
317+
318+ /**
319+ * @deprecated Use {@linkcode ServerContext} (server side) or {@linkcode ClientContext} (client side).
320+ *
321+ * v1 name for the handler context. v2 also exposes the same data under
322+ * `ctx.mcpReq` / `ctx.http`; the flat fields remain available so existing
323+ * handlers using them compile and run unchanged. HTTP-transport-specific fields
324+ * (`requestInfo`, `closeSSEStream`, `closeStandaloneSSEStream`) are not shimmed
325+ * and require migration to `ctx.http?.req` / `ctx.http?.closeSSE` / `ctx.http?.closeStandaloneSSE`. See {@linkcode BaseContext}.
326+ */
327+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- phantom params kept for v1 source compatibility
328+ export type RequestHandlerExtra < _Req = unknown , _Notif = unknown > = ServerContext ;
329+
330+ /**
331+ * Returns a copy of `ctx` with v1's flat `extra.*` aliases populated as plain properties
332+ * mirroring the nested v2 fields. Intersected onto `ClientContext`/`ServerContext` so
333+ * existing handlers that read `extra.signal` etc. compile and run unchanged.
334+ *
335+ * @internal
336+ */
337+ function withLegacyContextFields < T extends BaseContext > (
338+ ctx : T ,
339+ sendRequest : < S extends AnySchema > ( r : Request , s : S , o ?: RequestOptions ) => Promise < SchemaOutput < S > >
340+ ) : T & LegacyContextFields {
341+ return {
342+ ...ctx ,
343+ signal : ctx . mcpReq . signal ,
344+ requestId : ctx . mcpReq . id ,
345+ _meta : ctx . mcpReq . _meta ,
346+ authInfo : ctx . http ?. authInfo ,
347+ sendNotification : ctx . mcpReq . notify ,
348+ sendRequest,
349+ taskStore : ctx . task ?. store ,
350+ taskId : ctx . task ?. id ,
351+ taskRequestedTtl : ctx . task ?. requestedTtl
352+ } ;
353+ }
291354
292355/**
293356 * Information about a request's timeout state
@@ -406,7 +469,7 @@ export abstract class Protocol<ContextT extends BaseContext> {
406469 * Builds the context object for request handlers. Subclasses must override
407470 * to return the appropriate context type (e.g., ServerContext adds HTTP request info).
408471 */
409- protected abstract buildContext ( ctx : BaseContext , transportInfo ?: MessageExtraInfo ) : ContextT ;
472+ protected abstract buildContext ( ctx : BaseContext & LegacyContextFields , transportInfo ?: MessageExtraInfo ) : ContextT ;
410473
411474 private async _oncancel ( notification : CancelledNotification ) : Promise < void > {
412475 if ( ! notification . params . requestId ) {
@@ -630,7 +693,7 @@ export abstract class Protocol<ContextT extends BaseContext> {
630693 http : extra ?. authInfo ? { authInfo : extra . authInfo } : undefined ,
631694 task : taskContext
632695 } ;
633- const ctx = this . buildContext ( baseCtx , extra ) ;
696+ const ctx = this . buildContext ( withLegacyContextFields ( baseCtx , sendRequest ) , extra ) ;
634697
635698 // Starting with Promise.resolve() puts any synchronous errors into the monad as well.
636699 Promise . resolve ( )
0 commit comments