Skip to content

Commit 0107d6c

Browse files
docs(examples,migration): TODO(F3) markers on client task demos; drop server tasks capability wiring; condense self-contradictory ttl section
1 parent 39e10ab commit 0107d6c

5 files changed

Lines changed: 26 additions & 205 deletions

File tree

docs/migration.md

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -869,44 +869,7 @@ There is no migration path for the removed surface; it was always `@experimental
869869

870870
#### `TaskCreationParams.ttl` no longer accepts `null`
871871

872-
The `ttl` field in `TaskCreationParams` (used when requesting the server to create a task) no longer accepts `null`. Per the MCP spec, `null` TTL (meaning unlimited lifetime) is only valid in server responses (`Task.ttl`), not in client requests. Clients should omit `ttl` to let
873-
the server decide the lifetime.
874-
875-
This also narrows the type of `requestedTtl` in `TaskContext`, `CreateTaskServerContext`, and `TaskServerContext` from `number | null | undefined` to `number | undefined`.
876-
877-
**Before (v1):**
878-
879-
```typescript
880-
// Requesting unlimited lifetime by passing null
881-
const result = await client.callTool({
882-
name: 'long-task',
883-
arguments: {},
884-
task: { ttl: null }
885-
});
886-
887-
// Handler context had number | null | undefined
888-
server.setRequestHandler('tools/call', async (request, ctx) => {
889-
const ttl: number | null | undefined = ctx.task?.requestedTtl;
890-
});
891-
```
892-
893-
**After (v2):**
894-
895-
```typescript
896-
// Omit ttl to let the server decide (server may return null for unlimited)
897-
const result = await client.callTool({
898-
name: 'long-task',
899-
arguments: {},
900-
task: {}
901-
});
902-
903-
// Handler context is now number | undefined
904-
server.setRequestHandler('tools/call', async (request, ctx) => {
905-
const ttl: number | undefined = ctx.task?.requestedTtl;
906-
});
907-
```
908-
909-
> **Note:** These task APIs are marked `@experimental` and may change without notice.
872+
`TaskCreationParams.ttl` (the storage-layer creation parameter) is now `number | undefined`; `null` is no longer accepted. Per the MCP spec, `null` TTL (unlimited lifetime) is only valid in server responses (`Task.ttl`), not in creation requests. Omit `ttl` to let the store decide. This is a storage-interface change and is independent of the Protocol-level removals above.
910873

911874
## Enhancements
912875

examples/client/src/simpleOAuthClient.ts

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { createServer } from 'node:http';
44
import { createInterface } from 'node:readline';
55
import { URL } from 'node:url';
66

7-
import type { CallToolResult, ListToolsRequest, OAuthClientMetadata } from '@modelcontextprotocol/client';
7+
import type { ListToolsRequest, OAuthClientMetadata } from '@modelcontextprotocol/client';
88
import { Client, StreamableHTTPClientTransport, UnauthorizedError } from '@modelcontextprotocol/client';
99
import open from 'open';
1010

@@ -358,54 +358,12 @@ class InteractiveOAuthClient {
358358
return;
359359
}
360360

361-
try {
362-
// Using the experimental tasks API - WARNING: may change without notice
363-
console.log(`\n🔧 Streaming tool '${toolName}'...`);
364-
365-
const stream = this.client.experimental.tasks.callToolStream({
366-
name: toolName,
367-
arguments: toolArgs
368-
});
369-
370-
// Iterate through all messages yielded by the generator
371-
for await (const message of stream) {
372-
switch (message.type) {
373-
case 'taskCreated': {
374-
console.log(`✓ Task created: ${message.task.taskId}`);
375-
break;
376-
}
377-
378-
case 'taskStatus': {
379-
console.log(`⟳ Status: ${message.task.status}`);
380-
if (message.task.statusMessage) {
381-
console.log(` ${message.task.statusMessage}`);
382-
}
383-
break;
384-
}
385-
386-
case 'result': {
387-
console.log('✓ Completed!');
388-
const toolResult = message.result as CallToolResult;
389-
for (const content of toolResult.content) {
390-
if (content.type === 'text') {
391-
console.log(content.text);
392-
} else {
393-
console.log(content);
394-
}
395-
}
396-
break;
397-
}
398-
399-
case 'error': {
400-
console.log('✗ Error:');
401-
console.log(` ${message.error.message}`);
402-
break;
403-
}
404-
}
405-
}
406-
} catch (error) {
407-
console.error(`❌ Failed to stream tool '${toolName}':`, error);
408-
}
361+
// TODO(F3): re-enable streaming-tool demo via tasksPlugin (SEP-2663).
362+
// The 2025-11 callToolStream API is removed by R0; this command is disabled
363+
// until the F3 rewrite.
364+
void toolName;
365+
void toolArgs;
366+
console.log('Streaming tool demo disabled pending tasksPlugin (SEP-2663). See TODO(F3).');
409367
}
410368

411369
close(): void {

examples/client/src/simpleStreamableHttp.ts

Lines changed: 6 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { createInterface } from 'node:readline';
22

33
import type {
4-
CallToolResult,
54
GetPromptRequest,
65
ListPromptsRequest,
76
ListResourcesRequest,
@@ -881,55 +880,12 @@ async function callToolTask(name: string, args: Record<string, unknown>): Promis
881880
return;
882881
}
883882

884-
console.log(`Calling tool '${name}' with task-based execution...`);
885-
console.log('Arguments:', args);
886-
887-
// Use task-based execution - call now, fetch later
888-
// Using the experimental tasks API - WARNING: may change without notice
889-
console.log('This will return immediately while processing continues in the background...');
890-
891-
try {
892-
// Call the tool with task metadata using streaming API
893-
const stream = client.experimental.tasks.callToolStream({
894-
name,
895-
arguments: args
896-
});
897-
898-
console.log('Waiting for task completion...');
899-
900-
let lastStatus = '';
901-
for await (const message of stream) {
902-
switch (message.type) {
903-
case 'taskCreated': {
904-
console.log('Task created successfully with ID:', message.task.taskId);
905-
break;
906-
}
907-
case 'taskStatus': {
908-
if (lastStatus !== message.task.status) {
909-
console.log(` ${message.task.status}${message.task.statusMessage ? ` - ${message.task.statusMessage}` : ''}`);
910-
}
911-
lastStatus = message.task.status;
912-
break;
913-
}
914-
case 'result': {
915-
console.log('Task completed!');
916-
console.log('Tool result:');
917-
const toolResult = message.result as CallToolResult;
918-
for (const item of toolResult.content) {
919-
if (item.type === 'text') {
920-
console.log(` ${item.text}`);
921-
}
922-
}
923-
break;
924-
}
925-
case 'error': {
926-
throw message.error;
927-
}
928-
}
929-
}
930-
} catch (error) {
931-
console.log(`Error with task-based execution: ${error}`);
932-
}
883+
// TODO(F3): re-enable task-based demo via tasksPlugin (SEP-2663).
884+
// The 2025-11 callToolStream API is removed by R0; this command is disabled
885+
// until the F3 rewrite (callTool returns {resultType:'task'}, then pollTask).
886+
void name;
887+
void args;
888+
console.log('Task-based execution demo disabled pending tasksPlugin (SEP-2663). See TODO(F3).');
933889
}
934890

935891
async function cleanup(): Promise<void> {

examples/client/src/simpleTaskInteractiveClient.ts

Lines changed: 7 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import { createInterface } from 'node:readline';
1111

12-
import type { CallToolResult, CreateMessageRequest, CreateMessageResult, TextContent } from '@modelcontextprotocol/client';
12+
import type { CreateMessageRequest, CreateMessageResult, TextContent } from '@modelcontextprotocol/client';
1313
import { Client, ProtocolError, ProtocolErrorCode, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
1414

1515
// Create readline interface for user input
@@ -115,64 +115,12 @@ async function run(url: string): Promise<void> {
115115
const toolsResult = await client.listTools();
116116
console.log(`Available tools: ${toolsResult.tools.map(t => t.name).join(', ')}`);
117117

118-
// Demo 1: Elicitation (confirm_delete)
119-
console.log('\n--- Demo 1: Elicitation ---');
120-
console.log('Calling confirm_delete tool...');
121-
122-
const confirmStream = client.experimental.tasks.callToolStream(
123-
{ name: 'confirm_delete', arguments: { filename: 'important.txt' } },
124-
{}
125-
);
126-
127-
for await (const message of confirmStream) {
128-
switch (message.type) {
129-
case 'taskCreated': {
130-
console.log(`Task created: ${message.task.taskId}`);
131-
break;
132-
}
133-
case 'taskStatus': {
134-
console.log(`Task status: ${message.task.status}`);
135-
break;
136-
}
137-
case 'result': {
138-
const toolResult = message.result as CallToolResult;
139-
console.log(`Result: ${getTextContent(toolResult)}`);
140-
break;
141-
}
142-
case 'error': {
143-
console.error(`Error: ${message.error}`);
144-
break;
145-
}
146-
}
147-
}
148-
149-
// Demo 2: Sampling (write_haiku)
150-
console.log('\n--- Demo 2: Sampling ---');
151-
console.log('Calling write_haiku tool...');
152-
153-
const haikuStream = client.experimental.tasks.callToolStream({ name: 'write_haiku', arguments: { topic: 'autumn leaves' } }, {});
154-
155-
for await (const message of haikuStream) {
156-
switch (message.type) {
157-
case 'taskCreated': {
158-
console.log(`Task created: ${message.task.taskId}`);
159-
break;
160-
}
161-
case 'taskStatus': {
162-
console.log(`Task status: ${message.task.status}`);
163-
break;
164-
}
165-
case 'result': {
166-
const toolResult = message.result as CallToolResult;
167-
console.log(`Result:\n${getTextContent(toolResult)}`);
168-
break;
169-
}
170-
case 'error': {
171-
console.error(`Error: ${message.error}`);
172-
break;
173-
}
174-
}
175-
}
118+
// TODO(F3): re-enable interactive task demos via tasksPlugin (SEP-2663).
119+
// The 2025-11 callToolStream API is removed by R0; the demos below were the
120+
// streaming consumer of that API and are disabled until the F3 rewrite.
121+
void client;
122+
void getTextContent;
123+
console.log('\nInteractive task demo disabled pending tasksPlugin (SEP-2663). See TODO(F3).');
176124

177125
// Cleanup
178126
console.log('\nDemo complete. Closing connection...');

examples/server/src/simpleStreamableHttp.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type {
1010
ReadResourceResult,
1111
ResourceLink
1212
} from '@modelcontextprotocol/server';
13-
import { InMemoryTaskMessageQueue, InMemoryTaskStore, isInitializeRequest, McpServer } from '@modelcontextprotocol/server';
13+
import { isInitializeRequest, McpServer } from '@modelcontextprotocol/server';
1414
import cors from 'cors';
1515
import type { Request, Response } from 'express';
1616
import * as z from 'zod/v4';
@@ -21,8 +21,8 @@ import { InMemoryEventStore } from './inMemoryEventStore.js';
2121
const useOAuth = process.argv.includes('--oauth');
2222
const dangerousLoggingEnabled = process.argv.includes('--dangerous-logging-enabled');
2323

24-
// Create shared task store for demonstration
25-
const taskStore = new InMemoryTaskStore();
24+
// TODO(F3): re-add task store wiring via tasksPlugin (SEP-2663).
25+
// const taskStore = new InMemoryTaskStore();
2626

2727
// Create an MCP server with implementation details
2828
const getServer = () => {
@@ -35,12 +35,8 @@ const getServer = () => {
3535
},
3636
{
3737
capabilities: {
38-
logging: {},
39-
tasks: {
40-
requests: { tools: { call: {} } },
41-
taskStore,
42-
taskMessageQueue: new InMemoryTaskMessageQueue()
43-
}
38+
logging: {}
39+
// TODO(F3): tasks capability re-added via tasksPlugin (SEP-2663)
4440
}
4541
}
4642
);

0 commit comments

Comments
 (0)