@j0hanz/fetch-url-mcp 1.13.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +815 -807
  3. package/dist/assets/logo.svg +53 -53
  4. package/dist/http/auth.d.ts +7 -3
  5. package/dist/http/auth.d.ts.map +1 -1
  6. package/dist/http/auth.js +65 -37
  7. package/dist/http/helpers.d.ts +21 -0
  8. package/dist/http/helpers.d.ts.map +1 -0
  9. package/dist/http/helpers.js +31 -0
  10. package/dist/http/index.d.ts +1 -0
  11. package/dist/http/index.d.ts.map +1 -1
  12. package/dist/http/index.js +1 -0
  13. package/dist/http/native.d.ts +6 -24
  14. package/dist/http/native.d.ts.map +1 -1
  15. package/dist/http/native.js +141 -86
  16. package/dist/http/rate-limit.d.ts +1 -1
  17. package/dist/http/rate-limit.d.ts.map +1 -1
  18. package/dist/http/rate-limit.js +3 -9
  19. package/dist/index.js +0 -0
  20. package/dist/lib/config.d.ts +1 -0
  21. package/dist/lib/config.d.ts.map +1 -1
  22. package/dist/lib/config.js +1 -0
  23. package/dist/lib/core.d.ts +4 -3
  24. package/dist/lib/core.d.ts.map +1 -1
  25. package/dist/lib/core.js +4 -1
  26. package/dist/lib/error/classify.d.ts.map +1 -1
  27. package/dist/lib/error/classify.js +27 -6
  28. package/dist/lib/error/payload.d.ts +2 -2
  29. package/dist/lib/error/payload.d.ts.map +1 -1
  30. package/dist/lib/error/payload.js +2 -2
  31. package/dist/lib/mcp-interop.d.ts +9 -108
  32. package/dist/lib/mcp-interop.d.ts.map +1 -1
  33. package/dist/lib/mcp-interop.js +39 -240
  34. package/dist/lib/net/http.d.ts.map +1 -1
  35. package/dist/lib/net/http.js +4 -17
  36. package/dist/resources/index.d.ts +1 -1
  37. package/dist/resources/index.d.ts.map +1 -1
  38. package/dist/resources/index.js +67 -60
  39. package/dist/server.d.ts +1 -1
  40. package/dist/server.d.ts.map +1 -1
  41. package/dist/server.js +39 -34
  42. package/dist/tasks/adapter.d.ts +15 -0
  43. package/dist/tasks/adapter.d.ts.map +1 -0
  44. package/dist/tasks/adapter.js +138 -0
  45. package/dist/tasks/manager.d.ts +14 -82
  46. package/dist/tasks/manager.d.ts.map +1 -1
  47. package/dist/tasks/manager.js +48 -607
  48. package/dist/tasks/store.d.ts +33 -19
  49. package/dist/tasks/store.d.ts.map +1 -1
  50. package/dist/tasks/store.js +143 -80
  51. package/dist/tools/index.d.ts +7 -13
  52. package/dist/tools/index.d.ts.map +1 -1
  53. package/dist/tools/index.js +153 -58
  54. package/dist/transform/index.js +1 -1
  55. package/package.json +110 -108
@@ -1,4 +1,4 @@
1
- import { completable } from '@modelcontextprotocol/sdk/server/completable.js';
1
+ import { completable, } from '@modelcontextprotocol/server';
2
2
  import { z } from 'zod';
3
3
  import { config } from '../lib/config.js';
4
4
  import { buildOptionalIcons } from '../lib/utils.js';
@@ -46,63 +46,70 @@ export function filterInstructions(instructions, topic) {
46
46
  }
47
47
  export function buildServerInstructions() {
48
48
  const maxHtmlSizeMb = config.constants.maxHtmlBytes / 1024 / 1024;
49
- return `# Fetch public webpages and return clean, readable Markdown.
50
-
51
- # Capabilities
52
- - Tool: \`${FETCH_URL_TOOL_NAME}\` — fetch a URL, return Markdown with metadata.
53
- - Resource: \`internal://instructions\`this document.
54
- - Prompt: \`get-help\` — returns these instructions. Accepts optional \`topic\` filter (${HELP_TOPICS.join(' | ')}).
55
-
56
- # Workflows
57
-
58
- ## Standard
59
- Call \`${FETCH_URL_TOOL_NAME}\` with \`{ url }\` → read \`markdown\` from result. Check \`truncated: true\` for incomplete content.
60
-
61
- ## Progress
62
- Add \`_meta: { progressToken: "<token>" }\` to \`tools/call\` → receive \`notifications/progress\`.
63
-
64
- ## Async (task mode)
65
- Add \`_meta: { "modelcontextprotocol.io/task": { taskId: "<client-id>", keepAlive: <ms> } }\` to \`tools/call\`.
66
-
67
- Lifecycle: \`submitted\` \`working\` → \`completed\` | \`failed\` | \`cancelled\`.
68
-
69
- Endpoints:
70
- - \`tasks/get\` — poll for \`statusMessage\`, \`progress\`, \`total\`.
71
- - \`tasks/result\` retrieve final output for completed tasks.
72
- - \`tasks/list\` — list tasks for the current session.
73
- - \`tasks/cancel\` — cancel an active task.
74
- - \`tasks/delete\` — remove a terminal task.
75
-
76
- Task-linked responses and notifications include
77
- \`_meta["modelcontextprotocol.io/related-task"] = { taskId }\`.
78
-
79
- Notifications (opt-in via \`TASKS_STATUS_NOTIFICATIONS=true\`):
80
- - \`notifications/tasks/created\` — emitted on task creation with related-task metadata.
81
- - \`notifications/tasks/status\` emitted on each status transition with related-task metadata.
82
-
83
- HTTP mode: tasks are bound to the authenticated caller and resumable across sessions.
84
-
85
- # Constraints
86
- - Blocked: localhost, private IPs, link-local, cloud metadata endpoints, \`.local\`/\`.internal\` domains.
87
- - Max HTML: ${maxHtmlSizeMb}MB. Max redirects: ${config.fetcher.maxRedirects}.
88
- - No JS rendering client-rendered pages may return incomplete content.
89
- - Binary content: not supported.
90
- - Batch JSON-RPC (\`[{...}]\`): rejected with HTTP 400.
91
- - \`internal://\` URIs are session-scoped.
92
- - Tasks API is experimental endpoints may change.
93
-
94
- # Errors
95
-
96
- | Code | Cause | Action |
97
- |---|---|---|
98
- | VALIDATION_ERROR | Invalid or blocked URL | Do not retry |
99
- | FETCH_ERROR | Network failure | Retry once with backoff |
100
- | UPSTREAM_HTTP_ERROR | Upstream HTTP error | Retry only for 5xx |
101
- | UPSTREAM_RATE_LIMITED | 429 from upstream | Back off, then retry |
102
- | UPSTREAM_TIMEOUT | Upstream timed out | Retry with backoff |
103
- | UPSTREAM_ABORTED | Request cancelled | Retry if needed |
104
- | MCP_ERROR | Internal protocol error | Do not retry |
105
- | queue_full | Worker pool saturated | Wait, retry, or use task mode |`;
49
+ return `# Fetch public webpages and return clean, readable Markdown
50
+
51
+ # Capabilities
52
+
53
+ - Tool: \`${FETCH_URL_TOOL_NAME}\` — fetch a URL, return Markdown with metadata.
54
+ - Resource: \`internal://instructions\` — this document.
55
+ - Prompt: \`get-help\` — returns these instructions. Accepts optional \`topic\` filter (${HELP_TOPICS.join(' | ')}).
56
+
57
+ # Workflows
58
+
59
+ ## Standard
60
+
61
+ Call \`${FETCH_URL_TOOL_NAME}\` with \`{ url }\` → read \`markdown\` from result. Check \`truncated: true\` for incomplete content.
62
+
63
+ ## Progress
64
+
65
+ Add \`_meta: { progressToken: "<token>" }\` to \`tools/call\` → receive \`notifications/progress\`.
66
+
67
+ ## Async (task mode)
68
+
69
+ Add \`task: { ttl?: <ms> }\` to \`tools/call\`.
70
+
71
+ Lifecycle: \`working\` \`completed\` | \`failed\` | \`cancelled\`.
72
+
73
+ Endpoints:
74
+
75
+ - \`tasks/get\` — poll for task summaries with \`status\`, \`statusMessage\`, \`createdAt\`, \`lastUpdatedAt\`, \`ttl\`, and \`pollInterval\`.
76
+ - \`tasks/result\` wait for terminal status, then retrieve the stored result or terminal error payload.
77
+ - \`tasks/list\` list tasks visible to the current caller.
78
+ - \`tasks/cancel\` — cancel an active task.
79
+ - \`tasks/delete\` — remove a terminal task.
80
+
81
+ Task-linked responses and notifications include
82
+ \`_meta["io.modelcontextprotocol/related-task"] = { taskId }\`.
83
+
84
+ Notifications (opt-in via \`TASKS_STATUS_NOTIFICATIONS=true\`):
85
+
86
+ - \`notifications/tasks/status\` emitted on each status transition with related-task metadata.
87
+
88
+ HTTP mode: tasks are bound to the authenticated caller and resumable across sessions for the same authenticated subject.
89
+
90
+ # Constraints
91
+
92
+ - Blocked: localhost, private IPs, link-local, cloud metadata endpoints, \`.local\`/\`.internal\` domains.
93
+ - Max HTML: ${maxHtmlSizeMb}MB. Max redirects: ${config.fetcher.maxRedirects}.
94
+ - No JS rendering — client-rendered pages may return incomplete content.
95
+ - Binary content: not supported.
96
+ - Batch JSON-RPC (\`[{...}]\`): rejected with HTTP 400.
97
+ - \`internal://\` URIs are session-scoped.
98
+ - Tasks API is experimental endpoints may change.
99
+
100
+ # Errors
101
+
102
+ | Code | Cause | Action |
103
+ | --------------------- | ----------------------- | ----------------------------- |
104
+ | VALIDATION_ERROR | Invalid or blocked URL | Do not retry |
105
+ | FETCH_ERROR | Network failure | Retry once with backoff |
106
+ | UPSTREAM_HTTP_ERROR | Upstream HTTP error | Retry only for 5xx |
107
+ | UPSTREAM_RATE_LIMITED | 429 from upstream | Back off, then retry |
108
+ | UPSTREAM_TIMEOUT | Upstream timed out | Retry with backoff |
109
+ | UPSTREAM_ABORTED | Request cancelled | Retry if needed |
110
+ | MCP_ERROR | Internal protocol error | Do not retry |
111
+ | queue_full | Worker pool saturated | Wait, retry, or use task mode |
112
+ `;
106
113
  }
107
114
  function buildTopicSchema() {
108
115
  return completable(z
@@ -118,9 +125,9 @@ export function registerGetHelpPrompt(server, instructions, iconInfo) {
118
125
  server.registerPrompt('get-help', {
119
126
  title: 'Get Help',
120
127
  description,
121
- argsSchema: {
128
+ argsSchema: z.object({
122
129
  topic: buildTopicSchema(),
123
- },
130
+ }),
124
131
  ...buildOptionalIcons(iconInfo),
125
132
  }, (args) => ({
126
133
  description,
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import { McpServer } from '@modelcontextprotocol/server';
2
2
  export declare function createMcpServer(): Promise<McpServer>;
3
3
  export declare function createMcpServerForHttpSession(): Promise<McpServer>;
4
4
  export declare function startStdioServer(): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiHpE,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAE1D;AAkDD,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,SAAS,CAAC,CAExE;AAwHD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC;IAChD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C,CAAC,CASD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAwB,MAAM,8BAA8B,CAAC;AAkH/E,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAE1D;AAkED,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,SAAS,CAAC,CAExE;AAwGD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC;IAChD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C,CAAC,CASD"}
package/dist/server.js CHANGED
@@ -1,14 +1,12 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import { SetLevelRequestSchema } from '@modelcontextprotocol/sdk/types.js';
4
- import * as fs from 'node:fs/promises';
1
+ import { McpServer, StdioServerTransport } from '@modelcontextprotocol/server';
2
+ import { readFile } from 'node:fs/promises';
5
3
  import process from 'node:process';
6
4
  import { config } from './lib/config.js';
7
- import { getSessionId, logError, Loggers, logInfo, logNotice, setLogLevel, setMcpServer, } from './lib/core.js';
5
+ import { logError, Loggers, logInfo, resolveMcpSessionIdByServer, resolveMcpSessionOwnerKey, setMcpServer, } from './lib/core.js';
8
6
  import { toError } from './lib/error/index.js';
9
- import { setTaskToolCallCapability } from './lib/mcp-interop.js';
10
7
  import { buildServerInstructions, registerGetHelpPrompt, registerInstructionResource, } from './resources/index.js';
11
- import { abortAllTaskExecutions, registerTaskHandlers } from './tasks/index.js';
8
+ import { TaskStoreAdapter } from './tasks/adapter.js';
9
+ import { abortAllTaskExecutions, emitTaskStatusNotification, registerTaskHandlers, taskManager, } from './tasks/index.js';
12
10
  import { registerTools as registerFetchUrlTool } from './tools/index.js';
13
11
  import { shutdownTransformWorkerPool } from './transform/index.js';
14
12
  /* -------------------------------------------------------------------------------------------------
@@ -21,7 +19,7 @@ async function getLocalIconInfo() {
21
19
  const mime = 'image/svg+xml';
22
20
  try {
23
21
  const iconPath = new URL(`../assets/${name}`, import.meta.url);
24
- const buffer = await fs.readFile(iconPath);
22
+ const buffer = await readFile(iconPath);
25
23
  return {
26
24
  src: `data:${mime};base64,${buffer.toString('base64')}`,
27
25
  mimeType: mime,
@@ -35,28 +33,30 @@ async function getLocalIconInfo() {
35
33
  }
36
34
  const serverInstructions = buildServerInstructions();
37
35
  function createServerCapabilities() {
36
+ const taskCapableToolCalls = config.tools.enabled.includes('fetch-url');
38
37
  return {
39
38
  completions: {},
40
39
  logging: {},
41
- resources: { subscribe: true, listChanged: true },
42
- // SDK auto-adds listChanged to tools capability at runtime.
40
+ resources: {},
43
41
  tools: {},
44
42
  prompts: {},
45
43
  tasks: {
46
44
  list: {},
47
45
  cancel: {},
48
46
  delete: {},
49
- requests: {
50
- tools: {
51
- call: {},
52
- },
53
- },
47
+ ...(taskCapableToolCalls
48
+ ? {
49
+ requests: {
50
+ tools: {
51
+ call: {},
52
+ },
53
+ },
54
+ }
55
+ : {}),
56
+ taskStore: new TaskStoreAdapter(),
54
57
  },
55
58
  };
56
59
  }
57
- function syncTaskCapabilityAdvertisement(server, taskToolCallEnabled) {
58
- setTaskToolCallCapability(server, taskToolCallEnabled);
59
- }
60
60
  function createServerInfo(icons) {
61
61
  return {
62
62
  name: config.server.name,
@@ -90,13 +90,29 @@ async function createMcpServerWithOptions(options) {
90
90
  const toolControls = registerFetchUrlTool(server);
91
91
  registerGetHelpPrompt(server, serverInstructions, localIcon);
92
92
  registerInstructionResource(server, serverInstructions, localIcon);
93
- const taskRegistration = registerTaskHandlers(server, {
94
- requireInterception: config.tasks.requireInterception,
93
+ server.server.registerCapabilities({
94
+ resources: { listChanged: false },
95
+ prompts: { listChanged: false },
96
+ tools: { listChanged: false },
95
97
  });
96
- const taskToolCallEnabled = taskRegistration.interceptedToolsCall;
98
+ const taskRegistration = registerTaskHandlers(server);
99
+ const taskToolCallEnabled = taskRegistration.taskCapableToolsRegistered;
97
100
  toolControls.setTaskSupport(taskToolCallEnabled ? 'optional' : 'forbidden');
98
- syncTaskCapabilityAdvertisement(server, taskToolCallEnabled);
99
- registerLoggingSetLevelHandler(server);
101
+ const disposeTaskStatusListener = taskManager.onStatusChange((task) => {
102
+ const sessionId = resolveMcpSessionIdByServer(server);
103
+ if (sessionId) {
104
+ const ownerKey = resolveMcpSessionOwnerKey(sessionId);
105
+ if (ownerKey && task.ownerKey !== ownerKey) {
106
+ return;
107
+ }
108
+ }
109
+ emitTaskStatusNotification(server, task);
110
+ });
111
+ const close = server.close.bind(server);
112
+ server.close = async () => {
113
+ disposeTaskStatusListener();
114
+ await close();
115
+ };
100
116
  attachServerErrorHandler(server);
101
117
  // Set global ref only after all registrations succeed so callers
102
118
  // never observe a half-initialised server instance.
@@ -108,17 +124,6 @@ async function createMcpServerWithOptions(options) {
108
124
  export async function createMcpServerForHttpSession() {
109
125
  return createMcpServerWithOptions({ registerObservabilityServer: false });
110
126
  }
111
- function registerLoggingSetLevelHandler(server) {
112
- server.server.setRequestHandler(SetLevelRequestSchema, (request) => {
113
- const sessionId = getSessionId();
114
- setLogLevel(request.params.level, sessionId);
115
- logNotice('Logging level updated', {
116
- level: request.params.level,
117
- scope: sessionId ? 'session' : 'stdio',
118
- }, 'logging');
119
- return {};
120
- });
121
- }
122
127
  function attachServerErrorHandler(server) {
123
128
  server.server.onerror = (error) => {
124
129
  logError('MCP server error', toError(error), Loggers.LOG_SERVER);
@@ -0,0 +1,15 @@
1
+ import { type RequestId, type Result, type CreateTaskOptions as SdkCreateTaskOptions, type Task, type TaskStore } from '@modelcontextprotocol/server';
2
+ type SdkRequest = Parameters<TaskStore['createTask']>[2];
3
+ export declare class TaskStoreAdapter implements TaskStore {
4
+ createTask(taskParams: SdkCreateTaskOptions, requestId: RequestId, request: SdkRequest, sessionId?: string): Promise<Task>;
5
+ getTask(taskId: string, sessionId?: string): Promise<Task | null>;
6
+ storeTaskResult(taskId: string, status: 'completed' | 'failed', result: Result, sessionId?: string): Promise<void>;
7
+ getTaskResult(taskId: string, sessionId?: string): Promise<Result>;
8
+ updateTaskStatus(taskId: string, status: Task['status'], statusMessage?: string, sessionId?: string): Promise<void>;
9
+ listTasks(cursor?: string, sessionId?: string): Promise<{
10
+ tasks: Task[];
11
+ nextCursor?: string;
12
+ }>;
13
+ }
14
+ export {};
15
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/tasks/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,iBAAiB,IAAI,oBAAoB,EAC9C,KAAK,IAAI,EACT,KAAK,SAAS,EACf,MAAM,8BAA8B,CAAC;AAiBtC,KAAK,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAqEzD,qBAAa,gBAAiB,YAAW,SAAS;IAChD,UAAU,CACR,UAAU,EAAE,oBAAoB,EAChC,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,UAAU,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAqBhB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAMjE,eAAe,CACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,GAAG,QAAQ,EAC9B,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAOhB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBlE,gBAAgB,CACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,EACtB,aAAa,CAAC,EAAE,MAAM,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAiChB,SAAS,CACP,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;QAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAWnD"}
@@ -0,0 +1,138 @@
1
+ import { ProtocolErrorCode, } from '@modelcontextprotocol/server';
2
+ import { resolveMcpSessionOwnerKey } from '../lib/core.js';
3
+ import { createProtocolError } from '../lib/mcp-interop.js';
4
+ import { abortTaskExecution, isServerResult, withRelatedTaskMeta, } from './manager.js';
5
+ import { createTerminalTaskErrorResult, taskManager, } from './store.js';
6
+ function resolveOwnerKey(sessionId, context) {
7
+ const ownerKey = context?.['ownerKey'];
8
+ if (typeof ownerKey === 'string' && ownerKey.length > 0)
9
+ return ownerKey;
10
+ if (!sessionId)
11
+ return 'default';
12
+ return resolveMcpSessionOwnerKey(sessionId) ?? `session:${sessionId}`;
13
+ }
14
+ function toSdkTask(state) {
15
+ return {
16
+ taskId: state.taskId,
17
+ status: state.status,
18
+ ttl: state.ttl,
19
+ createdAt: state.createdAt,
20
+ lastUpdatedAt: state.lastUpdatedAt,
21
+ pollInterval: state.pollInterval,
22
+ ...(state.statusMessage ? { statusMessage: state.statusMessage } : {}),
23
+ };
24
+ }
25
+ function readRequestMeta(request) {
26
+ const meta = request.params?._meta;
27
+ return meta && typeof meta === 'object' && !Array.isArray(meta)
28
+ ? meta
29
+ : undefined;
30
+ }
31
+ function readStoredTaskResult(state, taskId) {
32
+ if (!state) {
33
+ throw createProtocolError(ProtocolErrorCode.ResourceNotFound, `Task not found: ${taskId}`);
34
+ }
35
+ if (state.result === undefined || state.result === null) {
36
+ const terminalResult = createTerminalTaskErrorResult(state);
37
+ if (terminalResult) {
38
+ const result = {
39
+ ...terminalResult,
40
+ _meta: {
41
+ 'io.modelcontextprotocol/related-task': {
42
+ taskId,
43
+ },
44
+ },
45
+ };
46
+ return result;
47
+ }
48
+ throw createProtocolError(ProtocolErrorCode.InvalidParams, `Task ${taskId} has no result stored`);
49
+ }
50
+ if (isServerResult(state.result)) {
51
+ return withRelatedTaskMeta(state.result, taskId);
52
+ }
53
+ return state.result;
54
+ }
55
+ export class TaskStoreAdapter {
56
+ createTask(taskParams, requestId, request, sessionId) {
57
+ const ownerKey = resolveOwnerKey(sessionId, taskParams.context);
58
+ const requestMeta = readRequestMeta(request);
59
+ const createTaskOptions = {
60
+ requestId: String(requestId),
61
+ requestMethod: request.method,
62
+ ...(taskParams.ttl !== undefined ? { ttl: taskParams.ttl } : {}),
63
+ ...(taskParams.pollInterval !== undefined
64
+ ? { pollInterval: taskParams.pollInterval }
65
+ : {}),
66
+ ...(taskParams.context ? { context: taskParams.context } : {}),
67
+ ...(requestMeta ? { requestMeta } : {}),
68
+ };
69
+ const state = taskManager.createTask(createTaskOptions, 'Task submitted', ownerKey);
70
+ return Promise.resolve(toSdkTask(state));
71
+ }
72
+ getTask(taskId, sessionId) {
73
+ const ownerKey = resolveOwnerKey(sessionId);
74
+ const state = taskManager.getTask(taskId, ownerKey);
75
+ return Promise.resolve(state ? toSdkTask(state) : null);
76
+ }
77
+ storeTaskResult(taskId, status, result, sessionId) {
78
+ const ownerKey = resolveOwnerKey(sessionId);
79
+ if (!taskManager.getTask(taskId, ownerKey))
80
+ return Promise.resolve();
81
+ taskManager.updateTask(taskId, { status, result }, true);
82
+ return Promise.resolve();
83
+ }
84
+ getTaskResult(taskId, sessionId) {
85
+ const ownerKey = resolveOwnerKey(sessionId);
86
+ const state = taskManager.getTask(taskId, ownerKey);
87
+ if (state?.result !== undefined && state.result !== null) {
88
+ const result = readStoredTaskResult(state, taskId);
89
+ taskManager.shrinkTtlAfterDelivery(taskId);
90
+ return Promise.resolve(result);
91
+ }
92
+ return taskManager
93
+ .waitForTerminalTask(taskId, ownerKey)
94
+ .then((terminalState) => {
95
+ const result = readStoredTaskResult(terminalState, taskId);
96
+ taskManager.shrinkTtlAfterDelivery(taskId);
97
+ return result;
98
+ });
99
+ }
100
+ updateTaskStatus(taskId, status, statusMessage, sessionId) {
101
+ const ownerKey = resolveOwnerKey(sessionId);
102
+ if (status === 'cancelled') {
103
+ if (!taskManager.cancelTask(taskId, ownerKey, true))
104
+ return Promise.resolve();
105
+ abortTaskExecution(taskId);
106
+ return Promise.resolve();
107
+ }
108
+ const task = taskManager.getTask(taskId, ownerKey);
109
+ if (!task)
110
+ return Promise.resolve();
111
+ taskManager.updateTask(taskId, {
112
+ status,
113
+ ...(statusMessage ? { statusMessage } : {}),
114
+ ...(status === 'failed'
115
+ ? {
116
+ result: createTerminalTaskErrorResult({
117
+ taskId,
118
+ status: 'failed',
119
+ ...(statusMessage ? { statusMessage } : {}),
120
+ ...(task.error ? { error: task.error } : {}),
121
+ }),
122
+ }
123
+ : {}),
124
+ }, true);
125
+ return Promise.resolve();
126
+ }
127
+ listTasks(cursor, sessionId) {
128
+ const ownerKey = resolveOwnerKey(sessionId);
129
+ const result = taskManager.listTasks({
130
+ ownerKey,
131
+ ...(cursor ? { cursor } : {}),
132
+ });
133
+ return Promise.resolve({
134
+ tasks: result.tasks.map(toSdkTask),
135
+ ...(result.nextCursor ? { nextCursor: result.nextCursor } : {}),
136
+ });
137
+ }
138
+ }
@@ -1,105 +1,37 @@
1
- import { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { type ServerResult } from '@modelcontextprotocol/sdk/types.js';
3
- import { z } from 'zod';
4
- import { type ProgressNotification, type ToolHandlerExtra } from '../lib/mcp-interop.js';
1
+ import { type McpServer, RELATED_TASK_META_KEY, type ServerContext, type ServerResult } from '@modelcontextprotocol/server';
5
2
  import { type CreateTaskResult, decodeTaskCursor, encodeTaskCursor, taskManager, type TaskState, type TaskStatus, TaskWaiterRegistry, waitForTerminalTask } from './store.js';
6
- export declare const extendedCallToolRequestSchema: z.ZodObject<{
7
- method: z.ZodLiteral<"tools/call">;
8
- params: z.ZodObject<{
9
- name: z.ZodString;
10
- arguments: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
11
- _meta: z.ZodOptional<z.ZodObject<{
12
- progressToken: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
13
- 'modelcontextprotocol.io/task': z.ZodOptional<z.ZodObject<{
14
- taskId: z.ZodString;
15
- keepAlive: z.ZodOptional<z.ZodNumber>;
16
- }, z.core.$strict>>;
17
- "modelcontextprotocol.io/related-task": z.ZodOptional<z.ZodObject<{
18
- taskId: z.ZodString;
19
- }, z.core.$strict>>;
20
- }, z.core.$loose>>;
21
- task: z.ZodOptional<z.ZodObject<{
22
- ttl: z.ZodOptional<z.ZodNumber>;
23
- }, z.core.$strip>>;
24
- }, z.core.$strict>;
25
- }, z.core.$loose>;
26
- export type ExtendedCallToolRequest = z.infer<typeof extendedCallToolRequestSchema>;
27
- export type ToolCallRequestMeta = ExtendedCallToolRequest['params']['_meta'];
3
+ interface RelatedTaskMeta {
4
+ taskId: string;
5
+ }
6
+ export interface ToolCallRequestMeta extends Record<string, unknown> {
7
+ progressToken?: string | number;
8
+ [RELATED_TASK_META_KEY]?: RelatedTaskMeta;
9
+ }
28
10
  export { decodeTaskCursor, encodeTaskCursor, taskManager, TaskWaiterRegistry, waitForTerminalTask, };
29
11
  export type { CreateTaskResult, TaskState, TaskStatus };
30
- export declare function parseExtendedCallToolRequest(request: unknown): ExtendedCallToolRequest;
31
12
  export declare function sanitizeToolCallMeta(meta?: ToolCallRequestMeta): ToolCallRequestMeta | undefined;
32
13
  export declare function buildRelatedTaskMeta(taskId: string, meta?: ToolCallRequestMeta): Record<string, unknown>;
33
14
  export declare function withRelatedTaskMeta(result: ServerResult, taskId: string): ServerResult;
15
+ export declare function detachAbortController(taskId: string): AbortController | undefined;
16
+ export declare function attachAbortController(taskId: string): AbortController;
34
17
  export declare function abortTaskExecution(taskId: string): void;
35
18
  export declare function cancelTasksForOwner(ownerKey: string, statusMessage?: string): number;
36
19
  export declare function abortAllTaskExecutions(): void;
37
20
  type TaskSummary = CreateTaskResult['task'];
38
- type TaskLifecycleProjection = Pick<TaskState, 'taskId' | 'status' | 'statusMessage' | 'progress' | 'total' | 'createdAt' | 'lastUpdatedAt' | 'keepAlive' | 'pollFrequency'>;
21
+ type TaskLifecycleProjection = Pick<TaskState, 'taskId' | 'status' | 'statusMessage' | 'createdAt' | 'lastUpdatedAt' | 'ttl' | 'pollInterval'>;
39
22
  export declare function toTaskSummary(task: TaskLifecycleProjection): TaskSummary;
40
23
  export declare function emitTaskStatusNotification(server: McpServer, task: TaskState): void;
41
24
  export declare function throwTaskNotFound(): never;
42
- export declare function handleToolCallRequest(server: McpServer, request: ExtendedCallToolRequest, context: ToolCallContext): Promise<ServerResult>;
43
- interface TaskHandlerRegistrationOptions {
44
- requireInterception?: boolean;
45
- }
46
25
  interface TaskHandlerRegistrationResult {
47
- interceptedToolsCall: boolean;
48
26
  taskCapableToolsRegistered: boolean;
49
27
  }
50
- export declare function registerTaskHandlers(server: McpServer, options?: TaskHandlerRegistrationOptions): TaskHandlerRegistrationResult;
51
- interface HandlerExtra {
52
- sessionId?: string;
53
- authInfo?: {
54
- clientId?: string;
55
- token?: string;
56
- };
57
- signal?: AbortSignal;
58
- requestId?: string | number;
59
- sendNotification?: (notification: ProgressNotification) => Promise<void>;
60
- requestInfo?: unknown;
61
- }
62
- export interface ToolExecutionContext {
63
- ownerKey: string;
64
- sessionId?: string;
65
- signal?: AbortSignal;
66
- requestId?: string | number;
67
- sendNotification?: (notification: ProgressNotification) => Promise<void>;
68
- requestMeta?: ToolCallRequestMeta;
69
- }
70
- export type ToolCallContext = ToolExecutionContext;
28
+ export declare function registerTaskHandlers(server: McpServer): TaskHandlerRegistrationResult;
71
29
  interface AuthIdentity {
72
30
  clientId?: string;
73
31
  token?: string;
32
+ extra?: Record<string, unknown>;
74
33
  }
75
- /** Strip keys whose value is `undefined`, returning an object with only the
76
- * present keys. Return type correctly omits the `undefined` union so the result
77
- * is compatible with `exactOptionalPropertyTypes`. */
78
- type Compacted<T extends object> = {
79
- [K in keyof T as Exclude<T[K], undefined> extends never ? never : K]?: Exclude<T[K], undefined>;
80
- };
81
- export declare function compact<T extends object>(obj: T): Compacted<T>;
82
- export declare function parseHandlerExtra(extra: unknown): HandlerExtra | undefined;
83
34
  export declare function buildAuthenticatedOwnerKey(authInfo?: AuthIdentity): string | undefined;
84
- export declare function resolveTaskOwnerKey(extra?: HandlerExtra): string;
85
- export declare function resolveToolCallContext(extra?: HandlerExtra, requestMeta?: ToolCallRequestMeta): ToolCallContext;
86
- export declare function buildToolHandlerExtra(context: ToolExecutionContext, requestMeta?: ToolCallRequestMeta): ToolHandlerExtra;
87
- export declare function withRequestContextIfMissing<TParams, TResult, TExtra = unknown>(handler: (params: TParams, extra?: TExtra) => Promise<TResult>): (params: TParams, extra?: TExtra) => Promise<TResult>;
35
+ export declare function resolveOwnerKeyFromContext(ctx: ServerContext): string;
88
36
  export declare function isServerResult(value: unknown): value is ServerResult;
89
- export type TaskCapableToolSupport = 'required' | 'optional' | 'forbidden';
90
- export interface TaskCapableToolDescriptor<TArgs = unknown> {
91
- name: string;
92
- parseArguments: (args: unknown) => TArgs;
93
- execute: (args: TArgs, extra?: ToolHandlerExtra) => Promise<ServerResult>;
94
- getCompletionStatusMessage?: (result: ServerResult) => string | undefined;
95
- taskSupport?: TaskCapableToolSupport;
96
- immediateResponse?: string;
97
- }
98
- export declare function registerTaskCapableTool<TArgs>(server: McpServer, descriptor: TaskCapableToolDescriptor<TArgs>): void;
99
- export declare function unregisterTaskCapableTool(server: McpServer, name: string): void;
100
- export declare function getTaskCapableTool(server: McpServer, name: string): TaskCapableToolDescriptor | undefined;
101
- export declare function getTaskCapableToolSupport(server: McpServer, name: string): TaskCapableToolSupport | undefined;
102
- export declare function hasTaskCapableTool(server: McpServer, name: string): boolean;
103
- export declare function hasRegisteredTaskCapableTools(server: McpServer): boolean;
104
- export declare function setTaskCapableToolSupport(server: McpServer, name: string, support: TaskCapableToolSupport): void;
105
37
  //# sourceMappingURL=manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/tasks/manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/tasks/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAEd,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,8BAA8B,CAAC;AAkBtC,OAAO,EACL,KAAK,gBAAgB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,KAAK,SAAS,EACd,KAAK,UAAU,EACf,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAWpB,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAoB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAClE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,CAAC,qBAAqB,CAAC,CAAC,EAAE,eAAe,CAAC;CAC3C;AAED,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,mBAAmB,GACpB,CAAC;AACF,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;AAExD,wBAAgB,oBAAoB,CAClC,IAAI,CAAC,EAAE,mBAAmB,GACzB,mBAAmB,GAAG,SAAS,CAOjC;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,mBAAmB,GACzB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKzB;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,GACb,YAAY,CAQd;AAuBD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,GACb,eAAe,GAAG,SAAS,CAM7B;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,CAiBrE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEvD;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,aAAa,SAA4D,GACxE,MAAM,CAOR;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAMD,KAAK,WAAW,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAC5C,KAAK,uBAAuB,GAAG,IAAI,CACjC,SAAS,EACP,QAAQ,GACR,QAAQ,GACR,eAAe,GACf,WAAW,GACX,eAAe,GACf,KAAK,GACL,cAAc,CACjB,CAAC;AAEF,wBAAgB,aAAa,CAAC,IAAI,EAAE,uBAAuB,GAAG,WAAW,CAUxE;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,SAAS,GACd,IAAI,CAmBN;AAED,wBAAgB,iBAAiB,IAAI,KAAK,CAKzC;AAgBD,UAAU,6BAA6B;IACrC,0BAA0B,EAAE,OAAO,CAAC;CACrC;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,GAChB,6BAA6B,CAyB/B;AAMD,UAAU,YAAY;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAgBD,wBAAgB,0BAA0B,CACxC,QAAQ,CAAC,EAAE,YAAY,GACtB,MAAM,GAAG,SAAS,CAiBpB;AAED,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAkBrE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAEpE"}