@j0hanz/fetch-url-mcp 1.10.2 → 1.10.3
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.
- package/dist/http/native.d.ts.map +1 -1
- package/dist/http/native.js +20 -26
- package/dist/http/session-teardown.d.ts +17 -0
- package/dist/http/session-teardown.d.ts.map +1 -0
- package/dist/http/session-teardown.js +30 -0
- package/dist/lib/core.d.ts.map +1 -1
- package/dist/lib/core.js +2 -0
- package/dist/lib/dom-prep.d.ts.map +1 -1
- package/dist/lib/dom-prep.js +19 -14
- package/dist/lib/progress.d.ts.map +1 -1
- package/dist/lib/progress.js +59 -32
- package/dist/lib/sdk-interop.d.ts +8 -0
- package/dist/lib/sdk-interop.d.ts.map +1 -0
- package/dist/lib/sdk-interop.js +73 -0
- package/dist/lib/task-handlers.d.ts +0 -2
- package/dist/lib/task-handlers.d.ts.map +1 -1
- package/dist/lib/task-handlers.js +9 -94
- package/dist/resources/index.js +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +10 -3
- package/dist/tasks/call-contract.d.ts +25 -0
- package/dist/tasks/call-contract.d.ts.map +1 -0
- package/dist/tasks/call-contract.js +58 -0
- package/dist/tasks/cursor-codec.d.ts +5 -0
- package/dist/tasks/cursor-codec.d.ts.map +1 -0
- package/dist/tasks/cursor-codec.js +41 -0
- package/dist/tasks/execution.d.ts +1 -20
- package/dist/tasks/execution.d.ts.map +1 -1
- package/dist/tasks/execution.js +7 -32
- package/dist/tasks/manager.d.ts +1 -5
- package/dist/tasks/manager.d.ts.map +1 -1
- package/dist/tasks/manager.js +16 -144
- package/dist/tasks/owner.d.ts +12 -2
- package/dist/tasks/owner.d.ts.map +1 -1
- package/dist/tasks/owner.js +52 -3
- package/dist/tasks/tool-registry.d.ts +1 -0
- package/dist/tasks/tool-registry.d.ts.map +1 -1
- package/dist/tasks/waiters.d.ts +27 -0
- package/dist/tasks/waiters.d.ts.map +1 -0
- package/dist/tasks/waiters.js +113 -0
- package/dist/tools/fetch-url-progress.d.ts +17 -0
- package/dist/tools/fetch-url-progress.d.ts.map +1 -0
- package/dist/tools/fetch-url-progress.js +78 -0
- package/dist/tools/fetch-url.d.ts +5 -9
- package/dist/tools/fetch-url.d.ts.map +1 -1
- package/dist/tools/fetch-url.js +43 -96
- package/dist/transform/next-flight.d.ts +2 -0
- package/dist/transform/next-flight.d.ts.map +1 -0
- package/dist/transform/next-flight.js +285 -0
- package/dist/transform/transform.d.ts.map +1 -1
- package/dist/transform/transform.js +21 -336
- package/package.json +4 -4
- package/dist/tools/index.d.ts +0 -3
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js +0 -4
|
@@ -2,56 +2,13 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import {} from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { CallToolRequestSchema, ErrorCode, McpError, } from '@modelcontextprotocol/sdk/types.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import {
|
|
5
|
+
import { parseExtendedCallToolRequest, withRelatedTaskMeta, } from '../tasks/call-contract.js';
|
|
6
|
+
import { abortTaskExecution, emitTaskStatusNotification, handleToolCallRequest, throwTaskNotFound, toTaskSummary, } from '../tasks/execution.js';
|
|
6
7
|
import { taskManager } from '../tasks/manager.js';
|
|
7
8
|
import { isServerResult, parseHandlerExtra, resolveTaskOwnerKey, resolveToolCallContext, } from '../tasks/owner.js';
|
|
8
9
|
import { hasRegisteredTaskCapableTools, hasTaskCapableTool, } from '../tasks/tool-registry.js';
|
|
9
10
|
import { logWarn, runWithRequestContext } from './core.js';
|
|
10
|
-
import {
|
|
11
|
-
const patchedCleanupServers = new WeakSet();
|
|
12
|
-
const serverCleanupCallbacks = new WeakMap();
|
|
13
|
-
function getServerCleanupCallbackSet(server) {
|
|
14
|
-
let callbacks = serverCleanupCallbacks.get(server);
|
|
15
|
-
if (!callbacks) {
|
|
16
|
-
callbacks = new Set();
|
|
17
|
-
serverCleanupCallbacks.set(server, callbacks);
|
|
18
|
-
}
|
|
19
|
-
return callbacks;
|
|
20
|
-
}
|
|
21
|
-
function drainServerCleanupCallbacks(server) {
|
|
22
|
-
const callbacks = serverCleanupCallbacks.get(server);
|
|
23
|
-
if (!callbacks || callbacks.size === 0)
|
|
24
|
-
return;
|
|
25
|
-
const pending = [...callbacks];
|
|
26
|
-
callbacks.clear();
|
|
27
|
-
for (const callback of pending) {
|
|
28
|
-
try {
|
|
29
|
-
callback();
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
logWarn('Server cleanup callback failed', { error });
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function ensureServerCleanupHooks(server) {
|
|
37
|
-
if (patchedCleanupServers.has(server))
|
|
38
|
-
return;
|
|
39
|
-
patchedCleanupServers.add(server);
|
|
40
|
-
const originalOnClose = server.server.onclose;
|
|
41
|
-
server.server.onclose = () => {
|
|
42
|
-
drainServerCleanupCallbacks(server);
|
|
43
|
-
originalOnClose?.();
|
|
44
|
-
};
|
|
45
|
-
const originalClose = server.close.bind(server);
|
|
46
|
-
server.close = async () => {
|
|
47
|
-
drainServerCleanupCallbacks(server);
|
|
48
|
-
await originalClose();
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
export function registerServerLifecycleCleanup(server, callback) {
|
|
52
|
-
ensureServerCleanupHooks(server);
|
|
53
|
-
getServerCleanupCallbackSet(server).add(callback);
|
|
54
|
-
}
|
|
11
|
+
import { getSdkCallToolHandler } from './sdk-interop.js';
|
|
55
12
|
export { cancelTasksForOwner, abortAllTaskExecutions, } from '../tasks/execution.js';
|
|
56
13
|
/* -------------------------------------------------------------------------------------------------
|
|
57
14
|
* Task handler schemas and registration
|
|
@@ -76,41 +33,6 @@ const TaskResultSchema = z.looseObject({
|
|
|
76
33
|
method: z.literal('tasks/result'),
|
|
77
34
|
params: z.looseObject({ taskId: z.string() }),
|
|
78
35
|
});
|
|
79
|
-
const MIN_TASK_TTL_MS = 1_000;
|
|
80
|
-
const MAX_TASK_TTL_MS = 86_400_000;
|
|
81
|
-
const ExtendedCallToolRequestSchema = z.looseObject({
|
|
82
|
-
method: z.literal('tools/call'),
|
|
83
|
-
params: z.strictObject({
|
|
84
|
-
name: z.string().min(1),
|
|
85
|
-
arguments: z.record(z.string(), z.unknown()).optional(),
|
|
86
|
-
task: z
|
|
87
|
-
.strictObject({
|
|
88
|
-
ttl: z
|
|
89
|
-
.number()
|
|
90
|
-
.int()
|
|
91
|
-
.min(MIN_TASK_TTL_MS)
|
|
92
|
-
.max(MAX_TASK_TTL_MS)
|
|
93
|
-
.optional(),
|
|
94
|
-
})
|
|
95
|
-
.optional(),
|
|
96
|
-
_meta: z
|
|
97
|
-
.looseObject({
|
|
98
|
-
progressToken: z.union([z.string(), z.number()]).optional(),
|
|
99
|
-
'io.modelcontextprotocol/related-task': z
|
|
100
|
-
.strictObject({
|
|
101
|
-
taskId: z.string(),
|
|
102
|
-
})
|
|
103
|
-
.optional(),
|
|
104
|
-
})
|
|
105
|
-
.optional(),
|
|
106
|
-
}),
|
|
107
|
-
});
|
|
108
|
-
function parseExtendedCallToolRequest(request) {
|
|
109
|
-
const parsed = ExtendedCallToolRequestSchema.safeParse(request);
|
|
110
|
-
if (parsed.success)
|
|
111
|
-
return parsed.data;
|
|
112
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid tool request params: ${formatZodError(parsed.error)}`);
|
|
113
|
-
}
|
|
114
36
|
function resolveOwnerScopedExtra(extra) {
|
|
115
37
|
const parsedExtra = parseHandlerExtra(extra);
|
|
116
38
|
return {
|
|
@@ -118,14 +40,6 @@ function resolveOwnerScopedExtra(extra) {
|
|
|
118
40
|
ownerKey: resolveTaskOwnerKey(parsedExtra),
|
|
119
41
|
};
|
|
120
42
|
}
|
|
121
|
-
function getSdkCallToolHandler(server) {
|
|
122
|
-
// S-2: see tests/sdk-compat-guard.test.ts
|
|
123
|
-
const maybeHandlers = Reflect.get(server.server, '_requestHandlers');
|
|
124
|
-
if (!(maybeHandlers instanceof Map))
|
|
125
|
-
return null;
|
|
126
|
-
const handler = maybeHandlers.get('tools/call');
|
|
127
|
-
return typeof handler === 'function' ? handler : null;
|
|
128
|
-
}
|
|
129
43
|
export function registerTaskHandlers(server, options) {
|
|
130
44
|
const sdkCallToolHandler = getSdkCallToolHandler(server);
|
|
131
45
|
const taskCapableToolsRegistered = hasRegisteredTaskCapableTools();
|
|
@@ -139,15 +53,15 @@ export function registerTaskHandlers(server, options) {
|
|
|
139
53
|
if (sdkCallToolHandler) {
|
|
140
54
|
server.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
141
55
|
const parsedExtra = parseHandlerExtra(extra);
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
? String(context.requestId)
|
|
56
|
+
const requestId = parsedExtra?.requestId !== undefined
|
|
57
|
+
? String(parsedExtra.requestId)
|
|
145
58
|
: randomUUID();
|
|
146
|
-
const sessionId = parsedExtra?.sessionId;
|
|
147
59
|
return runWithRequestContext({
|
|
148
60
|
requestId,
|
|
149
61
|
operationId: requestId,
|
|
150
|
-
...(sessionId
|
|
62
|
+
...(parsedExtra?.sessionId
|
|
63
|
+
? { sessionId: parsedExtra.sessionId }
|
|
64
|
+
: {}),
|
|
151
65
|
}, () => {
|
|
152
66
|
const toolName = request.params.name;
|
|
153
67
|
// Only intercept task-capable tools managed by the local task registry.
|
|
@@ -156,6 +70,7 @@ export function registerTaskHandlers(server, options) {
|
|
|
156
70
|
return sdkCallToolHandler(request, extra);
|
|
157
71
|
}
|
|
158
72
|
const parsed = parseExtendedCallToolRequest(request);
|
|
73
|
+
const context = resolveToolCallContext(parsedExtra, parsed.params._meta);
|
|
159
74
|
return handleToolCallRequest(server, parsed, context);
|
|
160
75
|
});
|
|
161
76
|
});
|
package/dist/resources/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { ResourceTemplate, } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import { ErrorCode, McpError, SubscribeRequestSchema, UnsubscribeRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
3
3
|
import { get as getCacheEntry, getEntryMeta, keys as listCacheKeys, onCacheUpdate, parseCacheKey, } from '../lib/core.js';
|
|
4
4
|
import { logWarn } from '../lib/core.js';
|
|
5
|
-
import { registerServerLifecycleCleanup } from '../lib/
|
|
5
|
+
import { registerServerLifecycleCleanup } from '../lib/sdk-interop.js';
|
|
6
6
|
import { buildOptionalIcons } from '../lib/types.js';
|
|
7
7
|
import { isObject } from '../lib/utils.js';
|
|
8
8
|
import { parseCachedPayload, resolveCachedPayloadContent } from '../schemas.js';
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA0GpE,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAE1D;AAiDD,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,SAAS,CAAC,CAExE;AAkFD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMtD"}
|
package/dist/server.js
CHANGED
|
@@ -5,12 +5,13 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
5
5
|
import { SetLevelRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
6
6
|
import { config } from './lib/core.js';
|
|
7
7
|
import { getSessionId, logError, logInfo, setLogLevel, setMcpServer, } from './lib/core.js';
|
|
8
|
+
import { setTaskToolCallCapability } from './lib/sdk-interop.js';
|
|
8
9
|
import { abortAllTaskExecutions, registerTaskHandlers, } from './lib/task-handlers.js';
|
|
9
10
|
import { toError } from './lib/utils.js';
|
|
10
11
|
import { registerGetHelpPrompt } from './prompts/index.js';
|
|
11
12
|
import { registerCacheResourceTemplate, registerInstructionResource, } from './resources/index.js';
|
|
12
13
|
import { buildServerInstructions } from './resources/instructions.js';
|
|
13
|
-
import {
|
|
14
|
+
import { registerTools as registerFetchUrlTool } from './tools/fetch-url.js';
|
|
14
15
|
import { shutdownTransformWorkerPool } from './transform/transform.js';
|
|
15
16
|
/* -------------------------------------------------------------------------------------------------
|
|
16
17
|
* Icons + server info
|
|
@@ -50,6 +51,9 @@ function createServerCapabilities() {
|
|
|
50
51
|
},
|
|
51
52
|
};
|
|
52
53
|
}
|
|
54
|
+
function syncTaskCapabilityAdvertisement(server, taskToolCallEnabled) {
|
|
55
|
+
setTaskToolCallCapability(server, taskToolCallEnabled);
|
|
56
|
+
}
|
|
53
57
|
function createServerInfo(icons) {
|
|
54
58
|
return {
|
|
55
59
|
name: config.server.name,
|
|
@@ -83,13 +87,16 @@ async function createMcpServerWithOptions(options) {
|
|
|
83
87
|
if (shouldRegisterObservabilityServer(options)) {
|
|
84
88
|
setMcpServer(server);
|
|
85
89
|
}
|
|
86
|
-
|
|
90
|
+
const toolControls = registerFetchUrlTool(server);
|
|
87
91
|
registerGetHelpPrompt(server, serverInstructions, localIcon);
|
|
88
92
|
registerInstructionResource(server, serverInstructions, localIcon);
|
|
89
93
|
registerCacheResourceTemplate(server, localIcon);
|
|
90
|
-
registerTaskHandlers(server, {
|
|
94
|
+
const taskRegistration = registerTaskHandlers(server, {
|
|
91
95
|
requireInterception: config.tasks.requireInterception,
|
|
92
96
|
});
|
|
97
|
+
const taskToolCallEnabled = taskRegistration.interceptedToolsCall;
|
|
98
|
+
toolControls.setTaskSupport(taskToolCallEnabled ? 'optional' : 'forbidden');
|
|
99
|
+
syncTaskCapabilityAdvertisement(server, taskToolCallEnabled);
|
|
93
100
|
registerLoggingSetLevelHandler(server);
|
|
94
101
|
attachServerErrorHandler(server);
|
|
95
102
|
return server;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ServerResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
export declare const extendedCallToolRequestSchema: z.ZodObject<{
|
|
4
|
+
method: z.ZodLiteral<"tools/call">;
|
|
5
|
+
params: z.ZodObject<{
|
|
6
|
+
name: z.ZodString;
|
|
7
|
+
arguments: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
8
|
+
task: z.ZodOptional<z.ZodObject<{
|
|
9
|
+
ttl: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
}, z.core.$strict>>;
|
|
11
|
+
_meta: z.ZodOptional<z.ZodObject<{
|
|
12
|
+
progressToken: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
13
|
+
'io.modelcontextprotocol/related-task': z.ZodOptional<z.ZodObject<{
|
|
14
|
+
taskId: z.ZodString;
|
|
15
|
+
}, z.core.$strict>>;
|
|
16
|
+
}, z.core.$loose>>;
|
|
17
|
+
}, z.core.$strict>;
|
|
18
|
+
}, z.core.$loose>;
|
|
19
|
+
export type ExtendedCallToolRequest = z.infer<typeof extendedCallToolRequestSchema>;
|
|
20
|
+
export type ToolCallRequestMeta = ExtendedCallToolRequest['params']['_meta'];
|
|
21
|
+
export declare function parseExtendedCallToolRequest(request: unknown): ExtendedCallToolRequest;
|
|
22
|
+
export declare function sanitizeToolCallMeta(meta?: ToolCallRequestMeta): ToolCallRequestMeta | undefined;
|
|
23
|
+
export declare function buildRelatedTaskMeta(taskId: string, meta?: ToolCallRequestMeta): Record<string, unknown>;
|
|
24
|
+
export declare function withRelatedTaskMeta(result: ServerResult, taskId: string): ServerResult;
|
|
25
|
+
//# sourceMappingURL=call-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-contract.d.ts","sourceRoot":"","sources":["../../src/tasks/call-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAEvE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;iBAiBxC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AACF,MAAM,MAAM,mBAAmB,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;AAE7E,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,OAAO,GACf,uBAAuB,CAQzB;AAED,wBAAgB,oBAAoB,CAClC,IAAI,CAAC,EAAE,mBAAmB,GACzB,mBAAmB,GAAG,SAAS,CAMjC;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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { formatZodError } from '../lib/zod.js';
|
|
4
|
+
const MIN_TASK_TTL_MS = 1_000;
|
|
5
|
+
const MAX_TASK_TTL_MS = 86_400_000;
|
|
6
|
+
const relatedTaskMetaSchema = z.strictObject({
|
|
7
|
+
taskId: z.string(),
|
|
8
|
+
});
|
|
9
|
+
const toolCallMetaSchema = z.looseObject({
|
|
10
|
+
progressToken: z.union([z.string(), z.number()]).optional(),
|
|
11
|
+
'io.modelcontextprotocol/related-task': relatedTaskMetaSchema.optional(),
|
|
12
|
+
});
|
|
13
|
+
export const extendedCallToolRequestSchema = z.looseObject({
|
|
14
|
+
method: z.literal('tools/call'),
|
|
15
|
+
params: z.strictObject({
|
|
16
|
+
name: z.string().min(1),
|
|
17
|
+
arguments: z.record(z.string(), z.unknown()).optional(),
|
|
18
|
+
task: z
|
|
19
|
+
.strictObject({
|
|
20
|
+
ttl: z
|
|
21
|
+
.number()
|
|
22
|
+
.int()
|
|
23
|
+
.min(MIN_TASK_TTL_MS)
|
|
24
|
+
.max(MAX_TASK_TTL_MS)
|
|
25
|
+
.optional(),
|
|
26
|
+
})
|
|
27
|
+
.optional(),
|
|
28
|
+
_meta: toolCallMetaSchema.optional(),
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
export function parseExtendedCallToolRequest(request) {
|
|
32
|
+
const parsed = extendedCallToolRequestSchema.safeParse(request);
|
|
33
|
+
if (parsed.success)
|
|
34
|
+
return parsed.data;
|
|
35
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid tool request params: ${formatZodError(parsed.error)}`);
|
|
36
|
+
}
|
|
37
|
+
export function sanitizeToolCallMeta(meta) {
|
|
38
|
+
if (!meta)
|
|
39
|
+
return undefined;
|
|
40
|
+
const sanitized = { ...meta };
|
|
41
|
+
delete sanitized['io.modelcontextprotocol/related-task'];
|
|
42
|
+
return Object.keys(sanitized).length > 0 ? sanitized : undefined;
|
|
43
|
+
}
|
|
44
|
+
export function buildRelatedTaskMeta(taskId, meta) {
|
|
45
|
+
return {
|
|
46
|
+
...(sanitizeToolCallMeta(meta) ?? {}),
|
|
47
|
+
'io.modelcontextprotocol/related-task': { taskId },
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export function withRelatedTaskMeta(result, taskId) {
|
|
51
|
+
return {
|
|
52
|
+
...result,
|
|
53
|
+
_meta: {
|
|
54
|
+
...result._meta,
|
|
55
|
+
'io.modelcontextprotocol/related-task': { taskId },
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-codec.d.ts","sourceRoot":"","sources":["../../src/tasks/cursor-codec.ts"],"names":[],"mappings":"AAkBA,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAO7D;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,GACb;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAuBjC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
const MAX_CURSOR_LENGTH = 256;
|
|
3
|
+
const CURSOR_SECRET = randomBytes(32);
|
|
4
|
+
function signPayload(payload) {
|
|
5
|
+
return createHmac('sha256', CURSOR_SECRET)
|
|
6
|
+
.update(payload)
|
|
7
|
+
.digest('base64url');
|
|
8
|
+
}
|
|
9
|
+
function safeCompare(left, right) {
|
|
10
|
+
const leftBuffer = Buffer.from(left);
|
|
11
|
+
const rightBuffer = Buffer.from(right);
|
|
12
|
+
if (leftBuffer.length !== rightBuffer.length)
|
|
13
|
+
return false;
|
|
14
|
+
return timingSafeEqual(leftBuffer, rightBuffer);
|
|
15
|
+
}
|
|
16
|
+
export function encodeTaskCursor(anchorTaskId) {
|
|
17
|
+
const payload = Buffer.from(JSON.stringify({ anchorTaskId }), 'utf8').toString('base64url');
|
|
18
|
+
const signature = signPayload(payload);
|
|
19
|
+
return `${payload}.${signature}`;
|
|
20
|
+
}
|
|
21
|
+
export function decodeTaskCursor(cursor) {
|
|
22
|
+
if (!cursor || cursor.length > MAX_CURSOR_LENGTH)
|
|
23
|
+
return null;
|
|
24
|
+
const [payload, signature, ...rest] = cursor.split('.');
|
|
25
|
+
if (!payload || !signature || rest.length > 0)
|
|
26
|
+
return null;
|
|
27
|
+
if (!safeCompare(signPayload(payload), signature))
|
|
28
|
+
return null;
|
|
29
|
+
try {
|
|
30
|
+
const decoded = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8'));
|
|
31
|
+
if (typeof decoded.anchorTaskId !== 'string' ||
|
|
32
|
+
decoded.anchorTaskId.length === 0 ||
|
|
33
|
+
decoded.anchorTaskId.length > 128) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return { anchorTaskId: decoded.anchorTaskId };
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,26 +1,8 @@
|
|
|
1
1
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { type ServerResult } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import { type ExtendedCallToolRequest } from './call-contract.js';
|
|
3
4
|
import { type CreateTaskResult, type TaskState } from './manager.js';
|
|
4
5
|
import { type ToolCallContext } from './owner.js';
|
|
5
|
-
export interface ExtendedCallToolRequest {
|
|
6
|
-
method: 'tools/call';
|
|
7
|
-
params: {
|
|
8
|
-
name: string;
|
|
9
|
-
arguments?: Record<string, unknown> | undefined;
|
|
10
|
-
task?: {
|
|
11
|
-
ttl?: number | undefined;
|
|
12
|
-
} | undefined;
|
|
13
|
-
_meta?: {
|
|
14
|
-
progressToken?: string | number | undefined;
|
|
15
|
-
'io.modelcontextprotocol/related-task'?: {
|
|
16
|
-
taskId: string;
|
|
17
|
-
} | undefined;
|
|
18
|
-
[key: string]: unknown;
|
|
19
|
-
} | undefined;
|
|
20
|
-
[key: string]: unknown;
|
|
21
|
-
};
|
|
22
|
-
[key: string]: unknown;
|
|
23
|
-
}
|
|
24
6
|
export declare function abortTaskExecution(taskId: string): void;
|
|
25
7
|
export declare function cancelTasksForOwner(ownerKey: string, statusMessage?: string): number;
|
|
26
8
|
export declare function abortAllTaskExecutions(): void;
|
|
@@ -34,7 +16,6 @@ export declare function toTaskSummary(task: {
|
|
|
34
16
|
ttl: number;
|
|
35
17
|
pollInterval: number;
|
|
36
18
|
}): TaskSummary;
|
|
37
|
-
export declare function withRelatedTaskMeta(result: ServerResult, taskId: string): ServerResult;
|
|
38
19
|
export declare function emitTaskStatusNotification(server: McpServer, task: TaskState): void;
|
|
39
20
|
export declare function throwTaskNotFound(): never;
|
|
40
21
|
export declare function handleToolCallRequest(server: McpServer, request: ExtendedCallToolRequest, context: ToolCallContext): Promise<ServerResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../../src/tasks/execution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../../src/tasks/execution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,oCAAoC,CAAC;AAQ5C,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,KAAK,eAAe,EAErB,MAAM,YAAY,CAAC;AAgCpB,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAKvD;AAMD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,aAAa,SAA4D,GACxE,MAAM,CASR;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAgBD,KAAK,WAAW,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAE5C,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,WAAW,CAUd;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,SAAS,GACd,IAAI,CAmBN;AAoBD,wBAAgB,iBAAiB,IAAI,KAAK,CAEzC;AA+LD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,uBAAuB,EAChC,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,YAAY,CAAC,CAYvB"}
|
package/dist/tasks/execution.js
CHANGED
|
@@ -3,8 +3,9 @@ import { config } from '../lib/core.js';
|
|
|
3
3
|
import { logWarn, runWithRequestContext } from '../lib/core.js';
|
|
4
4
|
import { getErrorMessage } from '../lib/utils.js';
|
|
5
5
|
import { isObject } from '../lib/utils.js';
|
|
6
|
+
import { buildRelatedTaskMeta, } from './call-contract.js';
|
|
6
7
|
import { taskManager, } from './manager.js';
|
|
7
|
-
import { compact, tryReadToolStructuredError, } from './owner.js';
|
|
8
|
+
import { buildToolHandlerExtra, compact, tryReadToolStructuredError, } from './owner.js';
|
|
8
9
|
import { getTaskCapableTool, hasTaskCapableTool, } from './tool-registry.js';
|
|
9
10
|
const TASK_NOT_FOUND_ERROR_CODE = ErrorCode.InvalidParams;
|
|
10
11
|
/* -------------------------------------------------------------------------------------------------
|
|
@@ -61,18 +62,6 @@ export function toTaskSummary(task) {
|
|
|
61
62
|
pollInterval: task.pollInterval,
|
|
62
63
|
};
|
|
63
64
|
}
|
|
64
|
-
export function withRelatedTaskMeta(result, taskId) {
|
|
65
|
-
const relatedTaskMeta = {
|
|
66
|
-
'io.modelcontextprotocol/related-task': { taskId },
|
|
67
|
-
};
|
|
68
|
-
return {
|
|
69
|
-
...result,
|
|
70
|
-
_meta: {
|
|
71
|
-
...result._meta,
|
|
72
|
-
...relatedTaskMeta,
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
65
|
export function emitTaskStatusNotification(server, task) {
|
|
77
66
|
if (!config.tasks.emitStatusNotifications)
|
|
78
67
|
return;
|
|
@@ -124,15 +113,6 @@ function assertKnownTool(name) {
|
|
|
124
113
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: '${name}'`);
|
|
125
114
|
}
|
|
126
115
|
}
|
|
127
|
-
/* -------------------------------------------------------------------------------------------------
|
|
128
|
-
* Task result builders
|
|
129
|
-
* ------------------------------------------------------------------------------------------------- */
|
|
130
|
-
function buildRelatedTaskMeta(taskId, meta) {
|
|
131
|
-
return {
|
|
132
|
-
...(meta ?? {}),
|
|
133
|
-
'io.modelcontextprotocol/related-task': { taskId },
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
116
|
function buildCreateTaskResult(task) {
|
|
137
117
|
return { task };
|
|
138
118
|
}
|
|
@@ -178,13 +158,14 @@ function resolveToolAndArgs(params) {
|
|
|
178
158
|
const args = tool.parseArguments(params.arguments);
|
|
179
159
|
return { tool, args };
|
|
180
160
|
}
|
|
181
|
-
function buildTaskCompletionUpdate(result) {
|
|
161
|
+
function buildTaskCompletionUpdate(result, tool) {
|
|
182
162
|
const isToolError = isObject(result) && 'isError' in result && result.isError === true;
|
|
183
163
|
return {
|
|
184
164
|
status: isToolError ? 'failed' : 'completed',
|
|
185
165
|
statusMessage: isToolError
|
|
186
166
|
? (tryReadToolStructuredError(result) ?? 'Tool execution failed')
|
|
187
|
-
:
|
|
167
|
+
: (tool.getCompletionStatusMessage?.(result) ??
|
|
168
|
+
'Task completed successfully.'),
|
|
188
169
|
result,
|
|
189
170
|
};
|
|
190
171
|
}
|
|
@@ -208,7 +189,7 @@ async function runTaskToolExecution(params) {
|
|
|
208
189
|
updateWorkingTaskStatus(server, taskId, message);
|
|
209
190
|
},
|
|
210
191
|
});
|
|
211
|
-
updateTaskAndEmitStatus(server, taskId, buildTaskCompletionUpdate(result));
|
|
192
|
+
updateTaskAndEmitStatus(server, taskId, buildTaskCompletionUpdate(result, tool));
|
|
212
193
|
}
|
|
213
194
|
catch (error) {
|
|
214
195
|
const failure = buildTaskFailureState(error);
|
|
@@ -241,13 +222,7 @@ function handleTaskToolCall(server, params, context) {
|
|
|
241
222
|
}
|
|
242
223
|
async function handleDirectToolCall(params, context) {
|
|
243
224
|
const { tool, args } = resolveToolAndArgs(params);
|
|
244
|
-
|
|
245
|
-
signal: context.signal,
|
|
246
|
-
requestId: context.requestId,
|
|
247
|
-
sendNotification: context.sendNotification,
|
|
248
|
-
_meta: params._meta,
|
|
249
|
-
});
|
|
250
|
-
return tool.execute(args, extra);
|
|
225
|
+
return tool.execute(args, buildToolHandlerExtra(context, params._meta));
|
|
251
226
|
}
|
|
252
227
|
export async function handleToolCallRequest(server, request, context) {
|
|
253
228
|
const { params } = request;
|
package/dist/tasks/manager.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export interface CreateTaskResult {
|
|
|
34
34
|
declare class TaskManager {
|
|
35
35
|
private tasks;
|
|
36
36
|
private ownerCounts;
|
|
37
|
-
private waiters;
|
|
37
|
+
private readonly waiters;
|
|
38
38
|
private cleanupInterval;
|
|
39
39
|
private ensureCleanupLoop;
|
|
40
40
|
private stopCleanupLoop;
|
|
@@ -63,15 +63,11 @@ declare class TaskManager {
|
|
|
63
63
|
nextCursor?: string;
|
|
64
64
|
};
|
|
65
65
|
private resolveAnchorTaskId;
|
|
66
|
-
private addWaiter;
|
|
67
|
-
private removeWaiter;
|
|
68
66
|
waitForTerminalTask(taskId: string, ownerKey: string, signal?: AbortSignal): Promise<TaskState | undefined>;
|
|
69
67
|
private notifyWaiters;
|
|
70
68
|
private isExpired;
|
|
71
69
|
private maybeUpdateLastUpdatedAt;
|
|
72
70
|
shrinkTtlAfterDelivery(taskId: string): void;
|
|
73
|
-
private encodeCursor;
|
|
74
|
-
private decodeCursor;
|
|
75
71
|
private resolveNextCursor;
|
|
76
72
|
}
|
|
77
73
|
export declare const taskManager: TaskManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/tasks/manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/tasks/manager.ts"],"names":[],"mappings":"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"}
|