apcore-mcp 0.12.0 → 0.14.0
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/LICENSE +190 -0
- package/README.md +165 -19
- package/dist/acl-builder.d.ts +43 -0
- package/dist/acl-builder.d.ts.map +1 -0
- package/dist/acl-builder.js +115 -0
- package/dist/acl-builder.js.map +1 -0
- package/dist/adapters/annotations.d.ts.map +1 -1
- package/dist/adapters/annotations.js +37 -2
- package/dist/adapters/annotations.js.map +1 -1
- package/dist/adapters/errors.d.ts +17 -0
- package/dist/adapters/errors.d.ts.map +1 -1
- package/dist/adapters/errors.js +192 -2
- package/dist/adapters/errors.js.map +1 -1
- package/dist/adapters/id-normalizer.d.ts +40 -0
- package/dist/adapters/id-normalizer.d.ts.map +1 -0
- package/dist/adapters/id-normalizer.js +59 -0
- package/dist/adapters/id-normalizer.js.map +1 -0
- package/dist/adapters/index.d.ts +2 -2
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +2 -2
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/{mcpErrorFormatter.d.ts → mcp-error-formatter.d.ts} +5 -7
- package/dist/adapters/mcp-error-formatter.d.ts.map +1 -0
- package/dist/adapters/mcp-error-formatter.js +30 -0
- package/dist/adapters/mcp-error-formatter.js.map +1 -0
- package/dist/adapters/schema.d.ts +21 -4
- package/dist/adapters/schema.d.ts.map +1 -1
- package/dist/adapters/schema.js +147 -13
- package/dist/adapters/schema.js.map +1 -1
- package/dist/apcore-mcp.d.ts +24 -2
- package/dist/apcore-mcp.d.ts.map +1 -1
- package/dist/apcore-mcp.js +8 -0
- package/dist/apcore-mcp.js.map +1 -1
- package/dist/auth/hooks.d.ts +1 -1
- package/dist/auth/hooks.d.ts.map +1 -1
- package/dist/auth/hooks.js +10 -3
- package/dist/auth/hooks.js.map +1 -1
- package/dist/auth/jwt.d.ts +1 -2
- package/dist/auth/jwt.d.ts.map +1 -1
- package/dist/auth/jwt.js +18 -10
- package/dist/auth/jwt.js.map +1 -1
- package/dist/auth/types.d.ts +6 -3
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +23 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +15 -6
- package/dist/config.js.map +1 -1
- package/dist/converters/openai.d.ts +10 -0
- package/dist/converters/openai.d.ts.map +1 -1
- package/dist/converters/openai.js +100 -5
- package/dist/converters/openai.js.map +1 -1
- package/dist/explorer/index.d.ts +2 -0
- package/dist/explorer/index.d.ts.map +1 -0
- package/dist/explorer/index.js +2 -0
- package/dist/explorer/index.js.map +1 -0
- package/dist/index.d.ts +68 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +346 -60
- package/dist/index.js.map +1 -1
- package/dist/inspector/index.d.ts +2 -0
- package/dist/inspector/index.d.ts.map +1 -0
- package/dist/inspector/index.js +2 -0
- package/dist/inspector/index.js.map +1 -0
- package/dist/middleware-builder.d.ts +41 -0
- package/dist/middleware-builder.d.ts.map +1 -0
- package/dist/middleware-builder.js +129 -0
- package/dist/middleware-builder.js.map +1 -0
- package/dist/server/async-task-bridge.d.ts +190 -0
- package/dist/server/async-task-bridge.d.ts.map +1 -0
- package/dist/server/async-task-bridge.js +393 -0
- package/dist/server/async-task-bridge.js.map +1 -0
- package/dist/server/context.d.ts +9 -2
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/context.js +14 -6
- package/dist/server/context.js.map +1 -1
- package/dist/server/factory.d.ts +25 -2
- package/dist/server/factory.d.ts.map +1 -1
- package/dist/server/factory.js +127 -7
- package/dist/server/factory.js.map +1 -1
- package/dist/server/listener.d.ts +3 -0
- package/dist/server/listener.d.ts.map +1 -1
- package/dist/server/listener.js +13 -2
- package/dist/server/listener.js.map +1 -1
- package/dist/server/observability.d.ts +51 -0
- package/dist/server/observability.d.ts.map +1 -0
- package/dist/server/observability.js +96 -0
- package/dist/server/observability.js.map +1 -0
- package/dist/server/router.d.ts +114 -0
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/router.js +360 -18
- package/dist/server/router.js.map +1 -1
- package/dist/server/trace-context.d.ts +40 -0
- package/dist/server/trace-context.d.ts.map +1 -0
- package/dist/server/trace-context.js +67 -0
- package/dist/server/trace-context.js.map +1 -0
- package/dist/server/transport.d.ts +39 -0
- package/dist/server/transport.d.ts.map +1 -1
- package/dist/server/transport.js +134 -4
- package/dist/server/transport.js.map +1 -1
- package/dist/types.d.ts +18 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -1
- package/package.json +12 -6
- package/dist/adapters/idNormalizer.d.ts +0 -22
- package/dist/adapters/idNormalizer.d.ts.map +0 -1
- package/dist/adapters/idNormalizer.js +0 -30
- package/dist/adapters/idNormalizer.js.map +0 -1
- package/dist/adapters/mcpErrorFormatter.d.ts.map +0 -1
- package/dist/adapters/mcpErrorFormatter.js +0 -24
- package/dist/adapters/mcpErrorFormatter.js.map +0 -1
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AsyncTaskBridge — MCP ↔ apcore `AsyncTaskManager` adapter.
|
|
3
|
+
*
|
|
4
|
+
* Surfaces apcore's {@link AsyncTaskManager} through the MCP protocol so
|
|
5
|
+
* that long-running modules can be submitted, polled, cancelled, and listed
|
|
6
|
+
* via reserved meta-tools. Async-hinted modules (either
|
|
7
|
+
* `metadata.async === true` OR `annotations.extra["mcp_async"] === "true"`)
|
|
8
|
+
* are routed through `AsyncTaskManager.submit()` instead of the synchronous
|
|
9
|
+
* executor call path; the agent receives a `{task_id, status: "pending"}`
|
|
10
|
+
* envelope it can resolve via the four reserved `__apcore_task_*` meta-tools.
|
|
11
|
+
*
|
|
12
|
+
* Full spec: apcore-mcp/docs/features/async-task-bridge.md (F-043).
|
|
13
|
+
*/
|
|
14
|
+
/** Reserved meta-tool prefix. Module ids starting with this are forbidden. */
|
|
15
|
+
export const APCORE_META_TOOL_PREFIX = "__apcore_";
|
|
16
|
+
/** The four reserved meta-tool names. */
|
|
17
|
+
export const META_TOOL_NAMES = Object.freeze({
|
|
18
|
+
SUBMIT: "__apcore_task_submit",
|
|
19
|
+
STATUS: "__apcore_task_status",
|
|
20
|
+
CANCEL: "__apcore_task_cancel",
|
|
21
|
+
LIST: "__apcore_task_list",
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* Routes MCP tool calls either to the synchronous Execution Router (default)
|
|
25
|
+
* or to `AsyncTaskManager.submit()` for async-hinted modules.
|
|
26
|
+
*/
|
|
27
|
+
export class AsyncTaskBridge {
|
|
28
|
+
_manager;
|
|
29
|
+
_enabled;
|
|
30
|
+
_redactSensitive;
|
|
31
|
+
_outputSchemaMap;
|
|
32
|
+
_descriptorLookup;
|
|
33
|
+
/**
|
|
34
|
+
* Maps task_id → progressToken recorded at submit time so terminal-
|
|
35
|
+
* state notifications can be fanned out via the original token.
|
|
36
|
+
* [A-D-018]
|
|
37
|
+
*/
|
|
38
|
+
_progressTokens = new Map();
|
|
39
|
+
/**
|
|
40
|
+
* Maps session/connection key → list of task ids launched from that
|
|
41
|
+
* session so {@link cancelSessionTasks} can cancel them on transport
|
|
42
|
+
* disconnect. Mirrors Rust's `session_tasks` map. [A-D-018]
|
|
43
|
+
*/
|
|
44
|
+
_sessionTasks = new Map();
|
|
45
|
+
constructor(manager, options) {
|
|
46
|
+
this._manager = manager;
|
|
47
|
+
this._enabled = options?.enabled ?? true;
|
|
48
|
+
this._redactSensitive = options?.redactSensitive;
|
|
49
|
+
this._outputSchemaMap = options?.outputSchemaMap ?? {};
|
|
50
|
+
this._descriptorLookup = options?.descriptorLookup;
|
|
51
|
+
}
|
|
52
|
+
/** Whether async routing and meta-tools are enabled. */
|
|
53
|
+
get enabled() {
|
|
54
|
+
return this._enabled;
|
|
55
|
+
}
|
|
56
|
+
/** Expose the underlying manager (used by server lifecycle for shutdown). */
|
|
57
|
+
get manager() {
|
|
58
|
+
return this._manager;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Return true if the descriptor carries an async hint — either
|
|
62
|
+
* `metadata.async === true` OR `annotations.extra["mcp_async"] === "true"`.
|
|
63
|
+
*/
|
|
64
|
+
isAsyncModule(descriptor) {
|
|
65
|
+
if (!this._enabled || !descriptor)
|
|
66
|
+
return false;
|
|
67
|
+
const meta = descriptor.metadata ?? {};
|
|
68
|
+
// Accept both boolean true AND the string "true" — Python and Rust
|
|
69
|
+
// both accept the string form (registries that store annotations as
|
|
70
|
+
// YAML produce string booleans). [A-D-021]
|
|
71
|
+
const asyncFlag = meta["async"];
|
|
72
|
+
if (asyncFlag === true || asyncFlag === "true")
|
|
73
|
+
return true;
|
|
74
|
+
const annotations = descriptor.annotations;
|
|
75
|
+
if (annotations?.extra) {
|
|
76
|
+
const flag = annotations.extra["mcp_async"];
|
|
77
|
+
if (flag === true || flag === "true")
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Submit a module invocation to the AsyncTaskManager. Returns the standard
|
|
84
|
+
* MCP envelope `{task_id, status: "pending"}`.
|
|
85
|
+
*/
|
|
86
|
+
async submit(moduleId, inputs, context, options) {
|
|
87
|
+
// [D11-015] Install progress sink on the context BEFORE submitting, so the
|
|
88
|
+
// module can emit mid-execution progress via context.data[MCP_PROGRESS_KEY].
|
|
89
|
+
// Mirrors Python's async_task_bridge.py _install_progress_sink() pattern.
|
|
90
|
+
if (options?.progressToken !== undefined &&
|
|
91
|
+
options?.sendNotification !== undefined &&
|
|
92
|
+
context !== null &&
|
|
93
|
+
context !== undefined &&
|
|
94
|
+
typeof context === "object") {
|
|
95
|
+
const progressToken = options.progressToken;
|
|
96
|
+
const sendNotification = options.sendNotification;
|
|
97
|
+
const contextData = context.data;
|
|
98
|
+
if (contextData && typeof contextData === "object") {
|
|
99
|
+
contextData["_mcp_progress"] = async (progress, total) => {
|
|
100
|
+
await sendNotification({
|
|
101
|
+
method: "notifications/progress",
|
|
102
|
+
params: { progressToken, progress, total },
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const taskId = await this._manager.submit(moduleId, inputs, context ?? null);
|
|
108
|
+
if (options?.progressToken !== undefined) {
|
|
109
|
+
this._progressTokens.set(taskId, options.progressToken);
|
|
110
|
+
}
|
|
111
|
+
if (options?.sessionKey !== undefined) {
|
|
112
|
+
const list = this._sessionTasks.get(options.sessionKey) ?? [];
|
|
113
|
+
list.push(taskId);
|
|
114
|
+
this._sessionTasks.set(options.sessionKey, list);
|
|
115
|
+
}
|
|
116
|
+
return { task_id: taskId, status: "pending" };
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Look up the progress token recorded for a task at submit time.
|
|
120
|
+
*
|
|
121
|
+
* Used by transport / terminal-notification dispatch to route
|
|
122
|
+
* `notifications/progress` to the original caller. Returns undefined
|
|
123
|
+
* when no token was registered. [A-D-018]
|
|
124
|
+
*/
|
|
125
|
+
getProgressToken(taskId) {
|
|
126
|
+
return this._progressTokens.get(taskId);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Cancel every async task currently tracked under `sessionKey`.
|
|
130
|
+
*
|
|
131
|
+
* Used by the transport layer on client disconnect to ensure
|
|
132
|
+
* long-running tasks bound to that session don't keep running after
|
|
133
|
+
* the client has gone. Returns the number of tasks cancelled.
|
|
134
|
+
* Mirrors Rust's `AsyncTaskBridge::cancel_session_tasks`. [A-D-018]
|
|
135
|
+
*/
|
|
136
|
+
async cancelSessionTasks(sessionKey) {
|
|
137
|
+
// [A-D-005] Detach the task list from the map BEFORE iterating cancels.
|
|
138
|
+
// A concurrent submit() between get() and the post-loop delete() would
|
|
139
|
+
// otherwise append to the same Array reference and the trailing delete
|
|
140
|
+
// would drop the newly-tracked task. Mirrors Python's `pop()` and Rust's
|
|
141
|
+
// `remove()` — both detach before yielding to manager.cancel.
|
|
142
|
+
const taskIds = this._sessionTasks.get(sessionKey);
|
|
143
|
+
if (!taskIds || taskIds.length === 0)
|
|
144
|
+
return 0;
|
|
145
|
+
this._sessionTasks.delete(sessionKey);
|
|
146
|
+
let cancelled = 0;
|
|
147
|
+
for (const taskId of taskIds) {
|
|
148
|
+
try {
|
|
149
|
+
const ok = await this._manager.cancel(taskId);
|
|
150
|
+
if (ok)
|
|
151
|
+
cancelled++;
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// Cancel may fail if the task has already completed; swallow.
|
|
155
|
+
}
|
|
156
|
+
this._progressTokens.delete(taskId);
|
|
157
|
+
}
|
|
158
|
+
return cancelled;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Build the four MCP meta-tool definitions. Caller merges these with
|
|
162
|
+
* the regular tool list returned by `tools/list`.
|
|
163
|
+
*/
|
|
164
|
+
buildMetaTools() {
|
|
165
|
+
if (!this._enabled)
|
|
166
|
+
return [];
|
|
167
|
+
return [
|
|
168
|
+
{
|
|
169
|
+
name: META_TOOL_NAMES.SUBMIT,
|
|
170
|
+
description: "Submit an async-hinted apcore module for background execution. " +
|
|
171
|
+
"Returns `{task_id, status: \"pending\"}`. Use `__apcore_task_status` " +
|
|
172
|
+
"to poll until terminal state.",
|
|
173
|
+
inputSchema: {
|
|
174
|
+
type: "object",
|
|
175
|
+
additionalProperties: false,
|
|
176
|
+
properties: {
|
|
177
|
+
module_id: { type: "string" },
|
|
178
|
+
arguments: { type: "object", additionalProperties: true, default: {} },
|
|
179
|
+
version_hint: { type: "string" },
|
|
180
|
+
},
|
|
181
|
+
required: ["module_id"],
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: META_TOOL_NAMES.STATUS,
|
|
186
|
+
description: "Return the TaskInfo projection for a previously submitted async " +
|
|
187
|
+
"task. When the task is `completed`, the redacted result is inlined.",
|
|
188
|
+
inputSchema: {
|
|
189
|
+
type: "object",
|
|
190
|
+
additionalProperties: false,
|
|
191
|
+
properties: { task_id: { type: "string" } },
|
|
192
|
+
required: ["task_id"],
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: META_TOOL_NAMES.CANCEL,
|
|
197
|
+
description: "Cooperatively cancel a pending or running async task. Returns " +
|
|
198
|
+
"`{task_id, cancelled: bool}`.",
|
|
199
|
+
inputSchema: {
|
|
200
|
+
type: "object",
|
|
201
|
+
additionalProperties: false,
|
|
202
|
+
properties: { task_id: { type: "string" } },
|
|
203
|
+
required: ["task_id"],
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: META_TOOL_NAMES.LIST,
|
|
208
|
+
description: "List tracked async tasks. Optional `status` filter narrows to a " +
|
|
209
|
+
"single lifecycle state.",
|
|
210
|
+
inputSchema: {
|
|
211
|
+
type: "object",
|
|
212
|
+
additionalProperties: false,
|
|
213
|
+
properties: {
|
|
214
|
+
status: {
|
|
215
|
+
type: "string",
|
|
216
|
+
enum: ["pending", "running", "completed", "failed", "cancelled"],
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
];
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Whether `toolName` is one of the reserved meta-tools. Used by the
|
|
225
|
+
* execution router to short-circuit dispatch before touching the executor.
|
|
226
|
+
*/
|
|
227
|
+
isMetaTool(toolName) {
|
|
228
|
+
return (this._enabled &&
|
|
229
|
+
(toolName === META_TOOL_NAMES.SUBMIT ||
|
|
230
|
+
toolName === META_TOOL_NAMES.STATUS ||
|
|
231
|
+
toolName === META_TOOL_NAMES.CANCEL ||
|
|
232
|
+
toolName === META_TOOL_NAMES.LIST));
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Dispatch a meta-tool invocation. The caller must have already confirmed
|
|
236
|
+
* `isMetaTool(toolName)` is true.
|
|
237
|
+
*/
|
|
238
|
+
async handleMetaTool(toolName, args, context) {
|
|
239
|
+
switch (toolName) {
|
|
240
|
+
case META_TOOL_NAMES.SUBMIT: {
|
|
241
|
+
const moduleId = args["module_id"];
|
|
242
|
+
if (typeof moduleId !== "string" || moduleId.length === 0) {
|
|
243
|
+
throw new Error("__apcore_task_submit requires module_id (string)");
|
|
244
|
+
}
|
|
245
|
+
if (moduleId.startsWith(APCORE_META_TOOL_PREFIX)) {
|
|
246
|
+
throw new Error(`Reserved module id: "${moduleId}". Ids prefixed with ` +
|
|
247
|
+
`"${APCORE_META_TOOL_PREFIX}" are reserved for apcore-mcp meta-tools.`);
|
|
248
|
+
}
|
|
249
|
+
// Spec: __apcore_task_submit on a non-async module returns
|
|
250
|
+
// ASYNC_MODULE_NOT_ASYNC. Python enforces; TS+Rust were silently
|
|
251
|
+
// wrapping sync modules as async tasks. The check is only applied
|
|
252
|
+
// when a descriptor-lookup callback is wired (the normal
|
|
253
|
+
// production path); direct test construction without a registry
|
|
254
|
+
// skips this guard to preserve unit-test ergonomics. [A-D-008]
|
|
255
|
+
if (this._descriptorLookup) {
|
|
256
|
+
const descriptor = this._descriptorLookup(moduleId);
|
|
257
|
+
if (!descriptor || !this.isAsyncModule(descriptor)) {
|
|
258
|
+
const err = new Error(`ASYNC_MODULE_NOT_ASYNC: module "${moduleId}" is not async-hinted; ` +
|
|
259
|
+
`use regular tools/call instead of __apcore_task_submit`);
|
|
260
|
+
err.code = "ASYNC_MODULE_NOT_ASYNC";
|
|
261
|
+
throw err;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// [A-D-020] Validate `arguments` is a JSON object (not an array,
|
|
265
|
+
// string, number, etc.). Python rejects non-objects; pre-fix TS
|
|
266
|
+
// coerced via `?? {}` and silently passed through arrays/strings.
|
|
267
|
+
const rawArgs = args["arguments"];
|
|
268
|
+
if (rawArgs !== undefined &&
|
|
269
|
+
rawArgs !== null &&
|
|
270
|
+
(typeof rawArgs !== "object" || Array.isArray(rawArgs))) {
|
|
271
|
+
throw new Error("__apcore_task_submit requires `arguments` to be a JSON object");
|
|
272
|
+
}
|
|
273
|
+
const inputs = rawArgs ?? {};
|
|
274
|
+
return this.submit(moduleId, inputs, context);
|
|
275
|
+
}
|
|
276
|
+
case META_TOOL_NAMES.STATUS: {
|
|
277
|
+
const taskId = args["task_id"];
|
|
278
|
+
if (typeof taskId !== "string" || taskId.length === 0) {
|
|
279
|
+
throw new Error("__apcore_task_status requires task_id (string)");
|
|
280
|
+
}
|
|
281
|
+
const info = this._manager.getStatus(taskId);
|
|
282
|
+
if (!info) {
|
|
283
|
+
const err = new Error(`Task not found: ${taskId}`);
|
|
284
|
+
err.code = "ASYNC_TASK_NOT_FOUND";
|
|
285
|
+
throw err;
|
|
286
|
+
}
|
|
287
|
+
const projection = this._projectTaskInfo(info);
|
|
288
|
+
// [A-D-025] Inline result on terminal completed status — even
|
|
289
|
+
// when info.result is null/undefined (Python always inlines;
|
|
290
|
+
// pre-fix TS only inlined when truthy, silently dropping `null`).
|
|
291
|
+
// [A-D-026] Wrap redactor in try/catch — a buggy redactor must
|
|
292
|
+
// not bring down handle_status; fall back to original result.
|
|
293
|
+
if (info.status === "completed") {
|
|
294
|
+
const schema = this._outputSchemaMap[info.moduleId];
|
|
295
|
+
let redacted = info.result;
|
|
296
|
+
if (this._redactSensitive && schema && info.result) {
|
|
297
|
+
try {
|
|
298
|
+
redacted = this._redactSensitive(info.result, schema);
|
|
299
|
+
}
|
|
300
|
+
catch (err) {
|
|
301
|
+
console.warn(`task-result redactor raised for ${info.moduleId}; returning unredacted result`, err);
|
|
302
|
+
redacted = info.result;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
projection.result = redacted;
|
|
306
|
+
}
|
|
307
|
+
else if (info.status === "failed" && info.error) {
|
|
308
|
+
projection.error = info.error;
|
|
309
|
+
}
|
|
310
|
+
return projection;
|
|
311
|
+
}
|
|
312
|
+
case META_TOOL_NAMES.CANCEL: {
|
|
313
|
+
const taskId = args["task_id"];
|
|
314
|
+
if (typeof taskId !== "string" || taskId.length === 0) {
|
|
315
|
+
throw new Error("__apcore_task_cancel requires task_id (string)");
|
|
316
|
+
}
|
|
317
|
+
const cancelled = await this._manager.cancel(taskId);
|
|
318
|
+
// [A-D-009] Drop the progress-token binding after a single-task cancel
|
|
319
|
+
// so notifications/progress for cancelled tasks don't fan out to a
|
|
320
|
+
// token whose caller has already been told the task is gone. Mirrors
|
|
321
|
+
// Python's `_progress_bindings.pop(task_id, None)` and Rust's
|
|
322
|
+
// `progress_tokens.remove(task_id)`.
|
|
323
|
+
this._progressTokens.delete(taskId);
|
|
324
|
+
return { task_id: taskId, cancelled };
|
|
325
|
+
}
|
|
326
|
+
case META_TOOL_NAMES.LIST: {
|
|
327
|
+
// [A-D-024] Validate status filter against the spec enum;
|
|
328
|
+
// Python+Rust both reject unknown values. Pre-fix TS forwarded
|
|
329
|
+
// any string verbatim to listTasks(filter).
|
|
330
|
+
const status = args["status"];
|
|
331
|
+
let filter;
|
|
332
|
+
if (status !== undefined && status !== null) {
|
|
333
|
+
if (typeof status !== "string") {
|
|
334
|
+
throw new Error("__apcore_task_list `status` filter must be a string");
|
|
335
|
+
}
|
|
336
|
+
const validStatuses = [
|
|
337
|
+
"pending",
|
|
338
|
+
"running",
|
|
339
|
+
"completed",
|
|
340
|
+
"failed",
|
|
341
|
+
"cancelled",
|
|
342
|
+
];
|
|
343
|
+
if (!validStatuses.includes(status)) {
|
|
344
|
+
throw new Error(`__apcore_task_list invalid status filter: ${JSON.stringify(status)}; ` +
|
|
345
|
+
`must be one of ${validStatuses.join(", ")}`);
|
|
346
|
+
}
|
|
347
|
+
filter = status;
|
|
348
|
+
}
|
|
349
|
+
const tasks = this._manager.listTasks(filter);
|
|
350
|
+
return { tasks: tasks.map((t) => this._projectTaskInfo(t)) };
|
|
351
|
+
}
|
|
352
|
+
default:
|
|
353
|
+
throw new Error(`Unknown meta-tool: ${toolName}`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
_projectTaskInfo(info) {
|
|
357
|
+
return {
|
|
358
|
+
task_id: info.taskId,
|
|
359
|
+
module_id: info.moduleId,
|
|
360
|
+
status: info.status,
|
|
361
|
+
submitted_at: info.submittedAt,
|
|
362
|
+
started_at: info.startedAt,
|
|
363
|
+
completed_at: info.completedAt,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Factory that dynamically imports apcore-js's `AsyncTaskManager` and wraps
|
|
369
|
+
* it in an `AsyncTaskBridge`. Returns null when apcore-js is unavailable.
|
|
370
|
+
*/
|
|
371
|
+
export async function createAsyncTaskBridge(executor, options) {
|
|
372
|
+
if (options?.enabled === false)
|
|
373
|
+
return null;
|
|
374
|
+
try {
|
|
375
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
376
|
+
const apcore = (await import("apcore-js"));
|
|
377
|
+
const AsyncTaskManager = apcore.AsyncTaskManager ?? apcore.default?.AsyncTaskManager;
|
|
378
|
+
if (!AsyncTaskManager)
|
|
379
|
+
return null;
|
|
380
|
+
const manager = new AsyncTaskManager(executor, options?.maxConcurrent ?? 10, options?.maxTasks ?? 1000);
|
|
381
|
+
const redactSensitive = apcore.redactSensitive ?? apcore.default?.redactSensitive;
|
|
382
|
+
return new AsyncTaskBridge(manager, {
|
|
383
|
+
enabled: true,
|
|
384
|
+
redactSensitive: typeof redactSensitive === "function" ? redactSensitive : undefined,
|
|
385
|
+
outputSchemaMap: options?.outputSchemaMap,
|
|
386
|
+
descriptorLookup: options?.descriptorLookup,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=async-task-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-task-bridge.js","sourceRoot":"","sources":["../../src/server/async-task-bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/server/context.d.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* `data` reference so MCP callbacks remain accessible throughout the call chain.
|
|
12
12
|
*/
|
|
13
13
|
import type { Identity } from "../auth/types.js";
|
|
14
|
+
import type { CancelToken } from "./router.js";
|
|
14
15
|
/** Shape of the bridge context object. */
|
|
15
16
|
export interface BridgeContext {
|
|
16
17
|
readonly traceId: string;
|
|
@@ -18,7 +19,7 @@ export interface BridgeContext {
|
|
|
18
19
|
readonly callChain: readonly string[];
|
|
19
20
|
readonly executor: unknown;
|
|
20
21
|
readonly identity: Identity | null;
|
|
21
|
-
readonly cancelToken: null;
|
|
22
|
+
readonly cancelToken: CancelToken | null;
|
|
22
23
|
redactedInputs: Record<string, unknown> | null;
|
|
23
24
|
readonly data: Record<string, unknown>;
|
|
24
25
|
child(moduleId: string): BridgeContext;
|
|
@@ -28,7 +29,13 @@ export interface BridgeContext {
|
|
|
28
29
|
*
|
|
29
30
|
* @param data - Shared data dict (MCP callbacks are injected here)
|
|
30
31
|
* @param identity - Authenticated identity, if any
|
|
32
|
+
* @param traceId - Optional pre-existing traceId (32-hex, W3C format). When
|
|
33
|
+
* omitted, a fresh UUID is generated. Used to propagate incoming W3C
|
|
34
|
+
* `traceparent` trace_id so the downstream trace chain stays linked.
|
|
35
|
+
* @param cancelToken - Cooperative cancel token. Threaded into the context so
|
|
36
|
+
* modules can read `context.cancelToken?.isCancelled` to react to inbound
|
|
37
|
+
* MCP `notifications/cancelled`. [A-D-001]
|
|
31
38
|
* @returns A BridgeContext with a working child() method
|
|
32
39
|
*/
|
|
33
|
-
export declare function createBridgeContext(data: Record<string, unknown>, identity?: Identity | null): BridgeContext;
|
|
40
|
+
export declare function createBridgeContext(data: Record<string, unknown>, identity?: Identity | null, traceId?: string, cancelToken?: CancelToken | null): BridgeContext;
|
|
34
41
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,0CAA0C;AAC1C,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IACzC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAAC;CACxC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,EAC1B,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,GAC/B,aAAa,CASf"}
|
package/dist/server/context.js
CHANGED
|
@@ -16,25 +16,33 @@ import { randomUUID } from "node:crypto";
|
|
|
16
16
|
*
|
|
17
17
|
* @param data - Shared data dict (MCP callbacks are injected here)
|
|
18
18
|
* @param identity - Authenticated identity, if any
|
|
19
|
+
* @param traceId - Optional pre-existing traceId (32-hex, W3C format). When
|
|
20
|
+
* omitted, a fresh UUID is generated. Used to propagate incoming W3C
|
|
21
|
+
* `traceparent` trace_id so the downstream trace chain stays linked.
|
|
22
|
+
* @param cancelToken - Cooperative cancel token. Threaded into the context so
|
|
23
|
+
* modules can read `context.cancelToken?.isCancelled` to react to inbound
|
|
24
|
+
* MCP `notifications/cancelled`. [A-D-001]
|
|
19
25
|
* @returns A BridgeContext with a working child() method
|
|
20
26
|
*/
|
|
21
|
-
export function createBridgeContext(data, identity) {
|
|
22
|
-
return _buildContext(data, randomUUID(), null, [], identity ?? null);
|
|
27
|
+
export function createBridgeContext(data, identity, traceId, cancelToken) {
|
|
28
|
+
return _buildContext(data, traceId ?? randomUUID(), null, [], identity ?? null, cancelToken ?? null);
|
|
23
29
|
}
|
|
24
|
-
function _buildContext(data, traceId, callerId, callChain, identity) {
|
|
30
|
+
function _buildContext(data, traceId, callerId, callChain, identity, cancelToken) {
|
|
25
31
|
return {
|
|
26
32
|
traceId,
|
|
27
33
|
callerId,
|
|
28
34
|
callChain,
|
|
29
35
|
executor: null,
|
|
30
36
|
identity,
|
|
31
|
-
cancelToken
|
|
37
|
+
cancelToken,
|
|
32
38
|
redactedInputs: null,
|
|
33
39
|
data,
|
|
34
40
|
child(moduleId) {
|
|
35
|
-
// Match real Context.child(): callerId = last element of current callChain
|
|
41
|
+
// Match real Context.child(): callerId = last element of current callChain.
|
|
42
|
+
// child() preserves the cancelToken so cooperative cancel propagates
|
|
43
|
+
// through the entire executor call chain.
|
|
36
44
|
const newCallerId = callChain.length > 0 ? callChain[callChain.length - 1] : null;
|
|
37
|
-
return _buildContext(data, traceId, newCallerId, [...callChain, moduleId], identity);
|
|
45
|
+
return _buildContext(data, traceId, newCallerId, [...callChain, moduleId], identity, cancelToken);
|
|
38
46
|
},
|
|
39
47
|
};
|
|
40
48
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAiBzC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAA6B,EAC7B,QAA0B,EAC1B,OAAgB,EAChB,WAAgC;IAEhC,OAAO,aAAa,CAClB,IAAI,EACJ,OAAO,IAAI,UAAU,EAAE,EACvB,IAAI,EACJ,EAAE,EACF,QAAQ,IAAI,IAAI,EAChB,WAAW,IAAI,IAAI,CACpB,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CACpB,IAA6B,EAC7B,OAAe,EACf,QAAuB,EACvB,SAAmB,EACnB,QAAyB,EACzB,WAA+B;IAE/B,OAAO;QACL,OAAO;QACP,QAAQ;QACR,SAAS;QACT,QAAQ,EAAE,IAAI;QACd,QAAQ;QACR,WAAW;QACX,cAAc,EAAE,IAAI;QACpB,IAAI;QACJ,KAAK,CAAC,QAAgB;YACpB,4EAA4E;YAC5E,qEAAqE;YACrE,0CAA0C;YAC1C,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAClF,OAAO,aAAa,CAClB,IAAI,EACJ,OAAO,EACP,WAAW,EACX,CAAC,GAAG,SAAS,EAAE,QAAQ,CAAC,EACxB,QAAQ,EACR,WAAW,CACZ,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/server/factory.d.ts
CHANGED
|
@@ -10,10 +10,18 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
10
10
|
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
11
11
|
import type { Registry, ModuleDescriptor } from "../types.js";
|
|
12
12
|
import type { ExecutionRouter } from "./router.js";
|
|
13
|
+
import { type AsyncTaskBridge } from "./async-task-bridge.js";
|
|
13
14
|
/** Options for filtering when building tools from a registry. */
|
|
14
15
|
export interface BuildToolsOptions {
|
|
15
16
|
tags?: string[] | null;
|
|
16
17
|
prefix?: string | null;
|
|
18
|
+
strict?: boolean;
|
|
19
|
+
registry?: Registry;
|
|
20
|
+
}
|
|
21
|
+
/** Options for building a single MCP tool. */
|
|
22
|
+
export interface BuildToolOptions {
|
|
23
|
+
strict?: boolean;
|
|
24
|
+
registry?: Registry;
|
|
17
25
|
}
|
|
18
26
|
export declare class MCPServerFactory {
|
|
19
27
|
private readonly _schemaConverter;
|
|
@@ -36,14 +44,23 @@ export declare class MCPServerFactory {
|
|
|
36
44
|
* - inputSchema = converted via SchemaConverter
|
|
37
45
|
* - annotations = mapped from AnnotationMapper with camelCase keys
|
|
38
46
|
*/
|
|
39
|
-
buildTool(descriptor: ModuleDescriptor): Tool;
|
|
47
|
+
buildTool(descriptor: ModuleDescriptor, options?: BuildToolOptions): Tool;
|
|
40
48
|
/**
|
|
41
49
|
* Build an array of MCP Tool objects from all modules in a registry.
|
|
42
50
|
*
|
|
43
51
|
* Iterates over registry.list(), gets each definition, and builds tools.
|
|
44
52
|
* Skips modules that return null definitions or throw errors (with console.warn).
|
|
53
|
+
*
|
|
54
|
+
* Reserved: module ids starting with `__apcore_` collide with the async
|
|
55
|
+
* task bridge meta-tool namespace and are rejected with a console.error.
|
|
45
56
|
*/
|
|
46
57
|
buildTools(registry: Registry, options?: BuildToolsOptions): Tool[];
|
|
58
|
+
/**
|
|
59
|
+
* Merge the four async-task meta-tools onto an existing tool list. Called
|
|
60
|
+
* after `buildTools()` when an `AsyncTaskBridge` is active so meta-tools
|
|
61
|
+
* are advertised via `tools/list`.
|
|
62
|
+
*/
|
|
63
|
+
attachAsyncMetaTools(tools: Tool[], bridge: AsyncTaskBridge | undefined): Tool[];
|
|
47
64
|
/**
|
|
48
65
|
* Register resources/list and resources/read handlers for modules with documentation.
|
|
49
66
|
*
|
|
@@ -62,7 +79,13 @@ export declare class MCPServerFactory {
|
|
|
62
79
|
* @param server - The MCP Server to register handlers on
|
|
63
80
|
* @param tools - Array of MCP Tool objects to serve
|
|
64
81
|
* @param router - ExecutionRouter to handle tool call execution
|
|
82
|
+
* @param options - Optional extra options; `asyncTaskBridge` adds meta-tools
|
|
83
|
+
* and routes meta-tool calls to the bridge (mirrors Python's
|
|
84
|
+
* `register_handlers(server, tools, router, async_bridge)`).
|
|
85
|
+
* [D11-014]
|
|
65
86
|
*/
|
|
66
|
-
registerHandlers(server: Server, tools: Tool[], router: ExecutionRouter
|
|
87
|
+
registerHandlers(server: Server, tools: Tool[], router: ExecutionRouter, options?: {
|
|
88
|
+
asyncTaskBridge?: AsyncTaskBridge;
|
|
89
|
+
}): void;
|
|
67
90
|
}
|
|
68
91
|
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/server/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAOnE,OAAO,KAAK,EACV,IAAI,EAIL,MAAM,oCAAoC,CAAC;AAI5C,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/server/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAOnE,OAAO,KAAK,EACV,IAAI,EAIL,MAAM,oCAAoC,CAAC;AAI5C,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAc,MAAM,aAAa,CAAC;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,OAAO,EAA2B,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAKvF,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkB;IACnD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;;IAOrD;;;;;;OAMG;IACH,YAAY,CACV,IAAI,GAAE,MAAqB,EAC3B,OAAO,GAAE,MAAgB,GACxB,MAAM;IAkBT;;;;;;;;OAQG;IACH,SAAS,CAAC,UAAU,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAqGzE;;;;;;;;OAQG;IACH,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI,EAAE;IAiCnE;;;;OAIG;IACH,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI,EAAE;IAgBhF;;;;;;;;;;OAUG;IACH,wBAAwB,CACtB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,GACjB,IAAI;IAsDP;;;;;;;;;;OAUG;IACH,gBAAgB,CACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,IAAI,EAAE,EACb,MAAM,EAAE,eAAe,EACvB,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,eAAe,CAAA;KAAE,GAC9C,IAAI;CAuGR"}
|