Skip to content

Commit 3bd0f08

Browse files
refactor(core): restore deprecated Task* schemas to neutral layer
Drops the Q1-SD2 wire/rev type-only carve-out; layering rule now zero-exception. The 14 deprecated Task message-surface schemas (TaskSchema, TaskStatusSchema, CreateTaskResultSchema, TaskStatusNotification*, Get/List/CancelTask*) return to types/schemas.ts in a clearly-bannered @deprecated block. types/types.ts now infers them from ./schemas.js like every other public type — no import from wire/rev2025-11-25 remains outside src/wire/. - layeringInvariants test (a) tightened to expect(offenders).toEqual([]) - eslint.config.mjs outbound rule comment + message drop the carve-out (allowTypeImports kept: erased-at-runtime crossings stay a lint non-event; the test enforces zero crossings regardless) - wire/rev2025-11-25/schemas.ts header rewritten to point at the neutral copy - specTypeSchema SPEC_SCHEMA_KEYS gains the 14 entries (each has a public type in types.ts; drift-guard contract requires it — matches the existing TaskMetadata/RelatedTaskMetadata/TaskAugmentedRequestParams entries) - client.ts callTool() comment drops the stale Q1-SD2 reference The wire-parse contract for these shapes is unchanged — the FROZEN copies in wire/rev2025-11-25/schemas.ts remain the era registry's parse source; the neutral-layer copies are nameable-only and appear in no role union.
1 parent 3db5805 commit 3bd0f08

7 files changed

Lines changed: 215 additions & 49 deletions

File tree

packages/client/src/client/client.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2219,8 +2219,7 @@ export class Client extends Protocol<ClientContext> {
22192219

22202220
// The method-keyed request() path validates the era registry's plain
22212221
// CallToolResult schema — with the result map aligned to the typed
2222-
// map there is no wider union to narrow away (Q1-SD2 holds by
2223-
// construction).
2222+
// map there is no wider union to narrow away.
22242223
let result: CallToolResult;
22252224
try {
22262225
result = await this.request({ method: 'tools/call', params }, await buildSendOptions());

packages/core/eslint.config.mjs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ export default [
88
// Wire-layer isolation, outbound direction: nothing outside src/wire/ may
99
// reach into a wire revision module. The wire layer's only public surface
1010
// is src/wire/codec.ts (the WireCodec interface) and src/wire/bootstrap.ts.
11-
// Type-only imports are exempted — the sole intended user of that exemption
12-
// is types/types.ts re-exporting the deprecated Task* vocabulary as types
13-
// (Q1-SD2); test/wire/layeringInvariants.test.ts pins it to that one site.
11+
// test/wire/layeringInvariants.test.ts re-derives the same invariant with
12+
// zero exceptions. Type-only imports are exempted at the lint layer (a
13+
// type-only crossing is erased at runtime), but the test allows none.
1414
files: ['src/**/*.ts'],
1515
ignores: ['src/wire/**'],
1616
rules: {
@@ -21,9 +21,7 @@ export default [
2121
{
2222
group: ['**/wire/rev*', '**/wire/rev*/**', '@modelcontextprotocol/core/wire/rev*'],
2323
allowTypeImports: true,
24-
message:
25-
'Wire revision modules are codec-private. Route through src/wire/codec.ts (WireCodec) instead. ' +
26-
'The only permitted crossing is the type-only Task* re-export in types/types.ts (Q1-SD2).'
24+
message: 'Wire revision modules are codec-private. Route through src/wire/codec.ts (WireCodec) instead.'
2725
}
2826
]
2927
}

packages/core/src/types/schemas.ts

Lines changed: 173 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2154,13 +2154,182 @@ export const RootsListChangedNotificationSchema = NotificationSchema.extend({
21542154
params: NotificationsParamsSchema.optional()
21552155
});
21562156

2157+
/* ───────────────────────────────────────────────────────────────────────────
2158+
* Tasks (2025-11-25 wire vocabulary, DEPRECATED)
2159+
*
2160+
* The task message surface defined by the 2025-11-25 protocol revision. These
2161+
* schemas are kept in the neutral layer so the public Task* types stay
2162+
* nameable without a cross-layer import into wire/rev*; the wire-parse
2163+
* contract for them is the FROZEN copy in wire/rev2025-11-25/schemas.ts.
2164+
*
2165+
* They appear in NO role aggregate below and no API signature — nameable-only
2166+
* vocabulary for interop with task-capable 2025 peers (#2248). Removable at
2167+
* the major version that drops 2025-era support.
2168+
* ─────────────────────────────────────────────────────────────────────────── */
2169+
2170+
/**
2171+
* Task creation parameters, used to ask that the server create a task to represent a request.
2172+
*
2173+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2174+
*/
2175+
export const TaskCreationParamsSchema = z.looseObject({
2176+
/**
2177+
* Requested duration in milliseconds to retain task from creation.
2178+
*/
2179+
ttl: z.number().optional(),
2180+
2181+
/**
2182+
* Time in milliseconds to wait between task status requests.
2183+
*/
2184+
pollInterval: z.number().optional()
2185+
});
2186+
2187+
/**
2188+
* The status of a task.
2189+
*
2190+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2191+
*/
2192+
export const TaskStatusSchema = z.enum(['working', 'input_required', 'completed', 'failed', 'cancelled']);
2193+
2194+
/**
2195+
* A pollable state object associated with a request.
2196+
*
2197+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2198+
*/
2199+
export const TaskSchema = z.object({
2200+
taskId: z.string(),
2201+
status: TaskStatusSchema,
2202+
/**
2203+
* Time in milliseconds to keep task results available after completion.
2204+
* If `null`, the task has unlimited lifetime until manually cleaned up.
2205+
*/
2206+
ttl: z.union([z.number(), z.null()]),
2207+
/**
2208+
* ISO 8601 timestamp when the task was created.
2209+
*/
2210+
createdAt: z.string(),
2211+
/**
2212+
* ISO 8601 timestamp when the task was last updated.
2213+
*/
2214+
lastUpdatedAt: z.string(),
2215+
pollInterval: z.optional(z.number()),
2216+
/**
2217+
* Optional diagnostic message for failed tasks or other status information.
2218+
*/
2219+
statusMessage: z.optional(z.string())
2220+
});
2221+
2222+
/**
2223+
* Result returned when a task is created, containing the task data wrapped in a `task` field.
2224+
*
2225+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2226+
*/
2227+
export const CreateTaskResultSchema = ResultSchema.extend({
2228+
task: TaskSchema
2229+
});
2230+
2231+
/**
2232+
* Parameters for task status notification.
2233+
*
2234+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2235+
*/
2236+
export const TaskStatusNotificationParamsSchema = NotificationsParamsSchema.merge(TaskSchema);
2237+
2238+
/**
2239+
* A notification sent when a task's status changes.
2240+
*
2241+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2242+
*/
2243+
export const TaskStatusNotificationSchema = NotificationSchema.extend({
2244+
method: z.literal('notifications/tasks/status'),
2245+
params: TaskStatusNotificationParamsSchema
2246+
});
2247+
2248+
/**
2249+
* A request to get the state of a specific task.
2250+
*
2251+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2252+
*/
2253+
export const GetTaskRequestSchema = RequestSchema.extend({
2254+
method: z.literal('tasks/get'),
2255+
params: BaseRequestParamsSchema.extend({
2256+
taskId: z.string()
2257+
})
2258+
});
2259+
2260+
/**
2261+
* The response to a {@linkcode GetTaskRequest | tasks/get} request.
2262+
*
2263+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2264+
*/
2265+
export const GetTaskResultSchema = ResultSchema.merge(TaskSchema);
2266+
2267+
/**
2268+
* A request to get the result of a specific task.
2269+
*
2270+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2271+
*/
2272+
export const GetTaskPayloadRequestSchema = RequestSchema.extend({
2273+
method: z.literal('tasks/result'),
2274+
params: BaseRequestParamsSchema.extend({
2275+
taskId: z.string()
2276+
})
2277+
});
2278+
2279+
/**
2280+
* The response to a `tasks/result` request.
2281+
* The structure matches the result type of the original request.
2282+
* For example, a {@linkcode CallToolRequest | tools/call} task would return the `CallToolResult` structure.
2283+
*
2284+
*
2285+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2286+
*/
2287+
export const GetTaskPayloadResultSchema = ResultSchema.loose();
2288+
2289+
/**
2290+
* A request to list tasks.
2291+
*
2292+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2293+
*/
2294+
export const ListTasksRequestSchema = PaginatedRequestSchema.extend({
2295+
method: z.literal('tasks/list')
2296+
});
2297+
2298+
/**
2299+
* The response to a {@linkcode ListTasksRequest | tasks/list} request.
2300+
*
2301+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2302+
*/
2303+
export const ListTasksResultSchema = PaginatedResultSchema.extend({
2304+
tasks: z.array(TaskSchema)
2305+
});
2306+
2307+
/**
2308+
* A request to cancel a specific task.
2309+
*
2310+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2311+
*/
2312+
export const CancelTaskRequestSchema = RequestSchema.extend({
2313+
method: z.literal('tasks/cancel'),
2314+
params: BaseRequestParamsSchema.extend({
2315+
taskId: z.string()
2316+
})
2317+
});
2318+
2319+
/**
2320+
* The response to a {@linkcode CancelTaskRequest | tasks/cancel} request.
2321+
*
2322+
* @deprecated 2025-11-25 wire vocabulary with no SDK runtime; kept importable for interoperability only.
2323+
*/
2324+
export const CancelTaskResultSchema = ResultSchema.merge(TaskSchema);
2325+
21572326
/* Client messages */
21582327
// NOTE (Q1 increment 2): the role unions below are the NEUTRAL message sets.
21592328
// The 2025-era task vocabulary (tasks/* methods, task results, the task
2160-
// status notification) is 2025-only WIRE vocabulary and now lives in
2161-
// `wire/rev2025-11-25/schemas.ts`, which also exports the era's full wire
2162-
// role unions. The deprecated Task* types remain importable from the types
2163-
// barrel (Q1-SD2); they appear in no role aggregate and no API signature.
2329+
// status notification) is 2025-only WIRE vocabulary; the deprecated Task*
2330+
// schemas above are nameable-only and appear in NO role aggregate and no API
2331+
// signature. The era's full wire role unions live in
2332+
// `wire/rev2025-11-25/schemas.ts`.
21642333
export const ClientRequestSchema = z.union([
21652334
PingRequestSchema,
21662335
InitializeRequestSchema,

packages/core/src/types/specTypeSchema.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ const SPEC_SCHEMA_KEYS = [
4141
'CallToolResultSchema',
4242
'CancelledNotificationSchema',
4343
'CancelledNotificationParamsSchema',
44+
'CancelTaskRequestSchema',
45+
'CancelTaskResultSchema',
4446
'ClientCapabilitiesSchema',
4547
'ClientNotificationSchema',
4648
'ClientRequestSchema',
@@ -54,6 +56,7 @@ const SPEC_SCHEMA_KEYS = [
5456
'CreateMessageRequestParamsSchema',
5557
'CreateMessageResultSchema',
5658
'CreateMessageResultWithToolsSchema',
59+
'CreateTaskResultSchema',
5760
'CursorSchema',
5861
'DiscoverRequestSchema',
5962
'DiscoverResultSchema',
@@ -70,6 +73,10 @@ const SPEC_SCHEMA_KEYS = [
7073
'GetPromptRequestSchema',
7174
'GetPromptRequestParamsSchema',
7275
'GetPromptResultSchema',
76+
'GetTaskPayloadRequestSchema',
77+
'GetTaskPayloadResultSchema',
78+
'GetTaskRequestSchema',
79+
'GetTaskResultSchema',
7380
'IconSchema',
7481
'IconsSchema',
7582
'ImageContentSchema',
@@ -96,6 +103,8 @@ const SPEC_SCHEMA_KEYS = [
96103
'ListResourceTemplatesResultSchema',
97104
'ListRootsRequestSchema',
98105
'ListRootsResultSchema',
106+
'ListTasksRequestSchema',
107+
'ListTasksResultSchema',
99108
'ListToolsRequestSchema',
100109
'ListToolsResultSchema',
101110
'LoggingLevelSchema',
@@ -159,7 +168,12 @@ const SPEC_SCHEMA_KEYS = [
159168
'SubscriptionsListenRequestSchema',
160169
'SubscriptionsListenRequestParamsSchema',
161170
'TaskAugmentedRequestParamsSchema',
171+
'TaskCreationParamsSchema',
162172
'TaskMetadataSchema',
173+
'TaskSchema',
174+
'TaskStatusSchema',
175+
'TaskStatusNotificationSchema',
176+
'TaskStatusNotificationParamsSchema',
163177
'TextContentSchema',
164178
'TextResourceContentsSchema',
165179
'TitledMultiSelectEnumSchemaSchema',

packages/core/src/types/types.ts

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,6 @@
44

55
import type * as z from 'zod/v4';
66

7-
// Wire-module schema imports, TYPE-ONLY (erased at runtime): the deprecated
8-
// task vocabulary and the per-request envelope are wire-era artifacts whose
9-
// schemas live in the codec modules; their inferred TYPES stay importable
10-
// from this neutral layer (Q1-SD2).
11-
import type {
12-
CancelTaskRequestSchema,
13-
CancelTaskResultSchema,
14-
CreateTaskResultSchema,
15-
GetTaskPayloadRequestSchema,
16-
GetTaskPayloadResultSchema,
17-
GetTaskRequestSchema,
18-
GetTaskResultSchema,
19-
ListTasksRequestSchema,
20-
ListTasksResultSchema,
21-
TaskCreationParamsSchema,
22-
TaskSchema,
23-
TaskStatusNotificationParamsSchema,
24-
TaskStatusNotificationSchema,
25-
TaskStatusSchema
26-
} from '../wire/rev2025-11-25/schemas.js';
277
import type {
288
CLIENT_CAPABILITIES_META_KEY,
299
CLIENT_INFO_META_KEY,
@@ -47,6 +27,8 @@ import type {
4727
CallToolResultSchema,
4828
CancelledNotificationParamsSchema,
4929
CancelledNotificationSchema,
30+
CancelTaskRequestSchema,
31+
CancelTaskResultSchema,
5032
ClientCapabilitiesSchema,
5133
ClientNotificationSchema,
5234
ClientRequestSchema,
@@ -60,6 +42,7 @@ import type {
6042
CreateMessageRequestSchema,
6143
CreateMessageResultSchema,
6244
CreateMessageResultWithToolsSchema,
45+
CreateTaskResultSchema,
6346
CursorSchema,
6447
DiscoverRequestSchema,
6548
DiscoverResultSchema,
@@ -76,6 +59,10 @@ import type {
7659
GetPromptRequestParamsSchema,
7760
GetPromptRequestSchema,
7861
GetPromptResultSchema,
62+
GetTaskPayloadRequestSchema,
63+
GetTaskPayloadResultSchema,
64+
GetTaskRequestSchema,
65+
GetTaskResultSchema,
7966
IconSchema,
8067
IconsSchema,
8168
ImageContentSchema,
@@ -97,6 +84,8 @@ import type {
9784
ListResourceTemplatesResultSchema,
9885
ListRootsRequestSchema,
9986
ListRootsResultSchema,
87+
ListTasksRequestSchema,
88+
ListTasksResultSchema,
10089
ListToolsRequestSchema,
10190
ListToolsResultSchema,
10291
LoggingLevelSchema,
@@ -161,7 +150,12 @@ import type {
161150
SubscriptionsListenRequestParamsSchema,
162151
SubscriptionsListenRequestSchema,
163152
TaskAugmentedRequestParamsSchema,
153+
TaskCreationParamsSchema,
164154
TaskMetadataSchema,
155+
TaskSchema,
156+
TaskStatusNotificationParamsSchema,
157+
TaskStatusNotificationSchema,
158+
TaskStatusSchema,
165159
TextContentSchema,
166160
TextResourceContentsSchema,
167161
TitledMultiSelectEnumSchemaSchema,
@@ -247,9 +241,8 @@ export type NotificationParams = Infer<typeof NotificationsParamsSchema>;
247241
*
248242
* Neutral hand-written shape keyed by the public meta-key constants — never
249243
* inferred from a wire-module schema (this neutral layer does not import from
250-
* `wire/rev*` for runtime types; the deprecated 2025-11-25 task vocabulary
251-
* above is the sole, type-only carve-out). A `type` alias rather than an
252-
* interface so it stays assignable to `_meta`'s string-indexed object slot.
244+
* `wire/rev*`). A `type` alias rather than an interface so it stays assignable
245+
* to `_meta`'s string-indexed object slot.
253246
*/
254247
export type RequestMetaEnvelope = {
255248
[PROTOCOL_VERSION_META_KEY]: string;

packages/core/src/wire/rev2025-11-25/schemas.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
*
1313
* The 2025-only delta (the task message surface, restored types-only by #2248
1414
* for interop with task-capable 2025 peers) is parsed ONLY through this era's
15-
* registry; the deprecated Task* TYPES remain importable from the types barrel
16-
* (Q1-SD2: nameability is constant, runtime availability is version-keyed) but
17-
* appear in no API signature. Q1 increment 2 — deletions are physical: the
15+
* registry; the deprecated Task* schemas also live (marked `@deprecated`) in
16+
* the neutral schema layer so the public types stay nameable without a
17+
* cross-layer import — nameability is constant, runtime availability is
18+
* version-keyed — but appear in no API signature. Q1 increment 2 — deletions
19+
* are physical: the
1820
* 2026-era REGISTRY has no Task* methods (its frozen building-block copies do
1921
* carry the deprecated Task* sub-schemas by composition — soft contamination,
2022
* tracked for anchor-exactness adjudication).

0 commit comments

Comments
 (0)