@absolutejs/mcp 0.4.2 → 0.5.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/README.md +43 -0
- package/dist/index.js +261 -9
- package/dist/manifest.js +8606 -0
- package/dist/manifest.json +124 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/jsonrpc.d.ts +2 -1
- package/dist/src/manifest.d.ts +2 -0
- package/dist/src/tasks.d.ts +14 -0
- package/dist/src/types.d.ts +53 -0
- package/package.json +23 -2
package/README.md
CHANGED
|
@@ -7,6 +7,49 @@ package owns the JSON-RPC protocol, protocol-version negotiation, RFC 9728
|
|
|
7
7
|
discovery metadata, and the `401` challenge that lets a client find your
|
|
8
8
|
authorization server.
|
|
9
9
|
|
|
10
|
+
## Agent action enforcement
|
|
11
|
+
|
|
12
|
+
Tools carrying manifest contract 2 `authorization` metadata fail closed unless
|
|
13
|
+
an `agency` enforcement point is configured. Every call becomes an exact-input
|
|
14
|
+
action request; allowed calls execute through a short-lived single-use lease and
|
|
15
|
+
produce a receipt. Requestable denials return an `absolute.action_decision`
|
|
16
|
+
payload containing the action id for an approval workflow.
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { createAgency, createMemoryAgencyStore } from "@absolutejs/agency";
|
|
20
|
+
|
|
21
|
+
const agency = createAgency({ policy, store: createMemoryAgencyStore() });
|
|
22
|
+
|
|
23
|
+
mcpServer<Caller>({
|
|
24
|
+
agency: {
|
|
25
|
+
enforcement: agency,
|
|
26
|
+
resolveActor: ({ caller, scopes }) => ({
|
|
27
|
+
agentId: caller.agentId,
|
|
28
|
+
delegationId: caller.delegationId,
|
|
29
|
+
scopes,
|
|
30
|
+
userId: caller.userId,
|
|
31
|
+
}),
|
|
32
|
+
},
|
|
33
|
+
// normal MCP config…
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Durable Tasks
|
|
38
|
+
|
|
39
|
+
The package implements the final `io.modelcontextprotocol/tasks` extension from
|
|
40
|
+
SEP-2663: server-directed task creation, `tasks/get`, `tasks/update`, and
|
|
41
|
+
`tasks/cancel`. There is intentionally no `tasks/list`; task handles are bound
|
|
42
|
+
to an authorization key and checked on every request.
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
tasks: {
|
|
46
|
+
authorizationKey: (caller) => caller.userId,
|
|
47
|
+
shouldCreate: ({ name }) => name === "long_running_report",
|
|
48
|
+
store: createMemoryMcpTaskStore(), // use a durable shared store in production
|
|
49
|
+
ttlMs: 60 * 60 * 1000,
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
10
53
|
Nothing here depends on a model. The tool shape is structurally compatible with
|
|
11
54
|
[`@absolutejs/ai`](https://github.com/absolutejs/ai)'s `AIToolMap`, so an AI tool
|
|
12
55
|
registry serves over MCP without conversion — but any typed tool registry works.
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
|
|
2
17
|
// src/guards.ts
|
|
3
18
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
19
|
|
|
@@ -270,12 +285,32 @@ var createMcpClient = (options) => {
|
|
|
270
285
|
};
|
|
271
286
|
return { callTool, initialize, listResources, listTools, ping, readResource };
|
|
272
287
|
};
|
|
288
|
+
// node_modules/@absolutejs/agency/dist/authzen.js
|
|
289
|
+
var createCoazActionInput = ({
|
|
290
|
+
actor,
|
|
291
|
+
call,
|
|
292
|
+
effects = ["read"],
|
|
293
|
+
requiredScopes = []
|
|
294
|
+
}) => ({
|
|
295
|
+
action: "call_tool",
|
|
296
|
+
actor,
|
|
297
|
+
context: { required_scopes: requiredScopes, source: "mcp" },
|
|
298
|
+
effects,
|
|
299
|
+
input: call.arguments,
|
|
300
|
+
resource: {
|
|
301
|
+
id: call.name,
|
|
302
|
+
properties: { server_id: call.serverId },
|
|
303
|
+
type: "mcp_tool"
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
273
307
|
// src/jsonrpc.ts
|
|
274
308
|
var JSONRPC_PARSE_ERROR = -32700;
|
|
275
309
|
var JSONRPC_INVALID_REQUEST = -32600;
|
|
276
310
|
var JSONRPC_METHOD_NOT_FOUND = -32601;
|
|
277
311
|
var JSONRPC_INVALID_PARAMS = -32602;
|
|
278
312
|
var JSONRPC_INTERNAL_ERROR = -32603;
|
|
313
|
+
var JSONRPC_MISSING_REQUIRED_CLIENT_CAPABILITY = -32003;
|
|
279
314
|
var HTTP_ACCEPTED = 202;
|
|
280
315
|
var HTTP_NO_CONTENT = 204;
|
|
281
316
|
var HTTP_UNAUTHORIZED = 401;
|
|
@@ -286,7 +321,11 @@ var jsonHeaders = {
|
|
|
286
321
|
var rpcResult = (id, result) => new Response(JSON.stringify({ id, jsonrpc: "2.0", result }), {
|
|
287
322
|
headers: jsonHeaders
|
|
288
323
|
});
|
|
289
|
-
var rpcError = (id, code, message) => new Response(JSON.stringify({
|
|
324
|
+
var rpcError = (id, code, message, data) => new Response(JSON.stringify({
|
|
325
|
+
error: { code, message, ...data === undefined ? {} : { data } },
|
|
326
|
+
id,
|
|
327
|
+
jsonrpc: "2.0"
|
|
328
|
+
}), {
|
|
290
329
|
headers: jsonHeaders
|
|
291
330
|
});
|
|
292
331
|
var notificationAck = () => new Response(null, { status: HTTP_ACCEPTED });
|
|
@@ -302,6 +341,49 @@ var unauthorized = (metadataUrl, detail) => new Response(JSON.stringify({
|
|
|
302
341
|
status: HTTP_UNAUTHORIZED
|
|
303
342
|
});
|
|
304
343
|
|
|
344
|
+
// src/tasks.ts
|
|
345
|
+
var clone = (value) => structuredClone(value);
|
|
346
|
+
var createMemoryMcpTaskStore = () => {
|
|
347
|
+
const tasks = new Map;
|
|
348
|
+
return {
|
|
349
|
+
cancel: (taskId) => {
|
|
350
|
+
const task = tasks.get(taskId);
|
|
351
|
+
if (task === undefined)
|
|
352
|
+
return;
|
|
353
|
+
tasks.set(taskId, {
|
|
354
|
+
...task,
|
|
355
|
+
lastUpdatedAt: new Date().toISOString(),
|
|
356
|
+
status: "cancelled"
|
|
357
|
+
});
|
|
358
|
+
},
|
|
359
|
+
get: (taskId) => {
|
|
360
|
+
const task = tasks.get(taskId);
|
|
361
|
+
return task === undefined ? null : clone(task);
|
|
362
|
+
},
|
|
363
|
+
save: (task) => {
|
|
364
|
+
tasks.set(task.taskId, clone(task));
|
|
365
|
+
},
|
|
366
|
+
update: (taskId, update) => {
|
|
367
|
+
const task = tasks.get(taskId);
|
|
368
|
+
if (task === undefined)
|
|
369
|
+
return null;
|
|
370
|
+
if (["cancelled", "completed", "failed"].includes(task.status)) {
|
|
371
|
+
return clone(task);
|
|
372
|
+
}
|
|
373
|
+
const next = {
|
|
374
|
+
...task,
|
|
375
|
+
...update,
|
|
376
|
+
lastUpdatedAt: new Date().toISOString()
|
|
377
|
+
};
|
|
378
|
+
tasks.set(taskId, next);
|
|
379
|
+
return clone(next);
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
};
|
|
383
|
+
var publicMcpTask = ({ authorizationKey, ...task }) => {
|
|
384
|
+
return task;
|
|
385
|
+
};
|
|
386
|
+
|
|
305
387
|
// src/dispatch.ts
|
|
306
388
|
var DEFAULT_PROTOCOLS = ["2025-06-18", "2025-03-26", "2024-11-05"];
|
|
307
389
|
var DEFAULT_RESOURCE_MIME = "text/markdown";
|
|
@@ -332,6 +414,16 @@ var negotiateProtocol = (supported, params) => {
|
|
|
332
414
|
return supported.includes(requested) ? requested : preferred;
|
|
333
415
|
};
|
|
334
416
|
var scopeAllows = (tool, scopes) => tool.scope === undefined || scopes.includes(tool.scope);
|
|
417
|
+
var valueAtPath = (value, path) => {
|
|
418
|
+
let current = value;
|
|
419
|
+
for (const segment of path.split(".")) {
|
|
420
|
+
if (!isRecord(current))
|
|
421
|
+
return;
|
|
422
|
+
current = current[segment];
|
|
423
|
+
}
|
|
424
|
+
return current;
|
|
425
|
+
};
|
|
426
|
+
var agencyAllows = (config, tool, scopes) => tool.authorization === undefined || config.agency !== undefined && (tool.authorization.requiredScopes ?? []).every((scope) => scopes.includes(scope));
|
|
335
427
|
var normalizeResult = (value) => {
|
|
336
428
|
if (typeof value === "string") {
|
|
337
429
|
return { content: [{ text: value, type: "text" }], isError: false };
|
|
@@ -350,6 +442,9 @@ var initialize = async (config, id, params, context) => {
|
|
|
350
442
|
const capabilities = {
|
|
351
443
|
tools: { listChanged: false }
|
|
352
444
|
};
|
|
445
|
+
if (config.tasks !== undefined) {
|
|
446
|
+
capabilities.extensions = { "io.modelcontextprotocol/tasks": {} };
|
|
447
|
+
}
|
|
353
448
|
if (config.prompts)
|
|
354
449
|
capabilities.prompts = { listChanged: false };
|
|
355
450
|
if (config.resources) {
|
|
@@ -369,7 +464,7 @@ var initialize = async (config, id, params, context) => {
|
|
|
369
464
|
};
|
|
370
465
|
var toolsList = async (config, caller, scopes, id, params) => {
|
|
371
466
|
const tools = await config.tools({ caller, meta: {} });
|
|
372
|
-
const visible = Object.entries(tools).filter(([, tool]) => scopeAllows(tool, scopes)).map(([name, tool]) => ({
|
|
467
|
+
const visible = Object.entries(tools).filter(([, tool]) => scopeAllows(tool, scopes) && agencyAllows(config, tool, scopes)).map(([name, tool]) => ({
|
|
373
468
|
annotations: tool.annotations,
|
|
374
469
|
description: tool.description,
|
|
375
470
|
inputSchema: tool.inputSchema,
|
|
@@ -396,11 +491,70 @@ var SSE_HEADERS = {
|
|
|
396
491
|
var sseFrame = (message) => `data: ${JSON.stringify(message)}
|
|
397
492
|
|
|
398
493
|
`;
|
|
399
|
-
var runTool = async (config, caller, id, name, args, meta, tool, context) => {
|
|
494
|
+
var runTool = async (config, caller, scopes, id, name, args, meta, tool, context) => {
|
|
400
495
|
let ok = false;
|
|
401
496
|
let payload;
|
|
402
497
|
try {
|
|
403
|
-
const
|
|
498
|
+
const invoke = async () => normalizeResult(await tool.handler(args, context));
|
|
499
|
+
let result;
|
|
500
|
+
if (tool.authorization === undefined) {
|
|
501
|
+
result = await invoke();
|
|
502
|
+
} else {
|
|
503
|
+
const agency = config.agency;
|
|
504
|
+
if (agency === undefined)
|
|
505
|
+
throw new Error("Agent action policy is not configured");
|
|
506
|
+
const actor = await agency.resolveActor({ caller, scopes });
|
|
507
|
+
const actionInput = createCoazActionInput({
|
|
508
|
+
actor,
|
|
509
|
+
call: {
|
|
510
|
+
arguments: args,
|
|
511
|
+
name,
|
|
512
|
+
serverId: agency.serverId ?? config.serverInfo.name
|
|
513
|
+
},
|
|
514
|
+
effects: tool.authorization.effects,
|
|
515
|
+
requiredScopes: tool.authorization.requiredScopes
|
|
516
|
+
});
|
|
517
|
+
const amount = tool.authorization.spend ? valueAtPath(args, tool.authorization.spend.amountMinorField) : undefined;
|
|
518
|
+
const currency = tool.authorization.spend ? valueAtPath(args, tool.authorization.spend.currencyField) : undefined;
|
|
519
|
+
const idempotencyKey = tool.authorization.idempotencyKeyField ? valueAtPath(args, tool.authorization.idempotencyKeyField) : undefined;
|
|
520
|
+
const requested = await agency.enforcement.request({
|
|
521
|
+
...actionInput,
|
|
522
|
+
context: {
|
|
523
|
+
...actionInput.context,
|
|
524
|
+
manifest_authorization: tool.authorization
|
|
525
|
+
},
|
|
526
|
+
idempotencyKey: typeof idempotencyKey === "string" ? idempotencyKey : undefined,
|
|
527
|
+
spend: typeof amount === "number" && typeof currency === "string" ? { amountMinor: amount, currency } : undefined
|
|
528
|
+
});
|
|
529
|
+
meta.agencyActionId = requested.action.actionId;
|
|
530
|
+
meta.agencyDecisionId = requested.decision.decisionId;
|
|
531
|
+
if (requested.decision.kind === "deny") {
|
|
532
|
+
result = {
|
|
533
|
+
content: [
|
|
534
|
+
{
|
|
535
|
+
text: requested.decision.requestable ? `Action requires approval (${requested.action.actionId})` : `Action denied: ${requested.decision.reason}`,
|
|
536
|
+
type: "text"
|
|
537
|
+
}
|
|
538
|
+
],
|
|
539
|
+
isError: true,
|
|
540
|
+
structuredContent: {
|
|
541
|
+
actionId: requested.action.actionId,
|
|
542
|
+
decision: requested.decision,
|
|
543
|
+
type: "absolute.action_decision"
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
} else {
|
|
547
|
+
const lease = await agency.enforcement.issueLease(requested.action.actionId);
|
|
548
|
+
const executed = await agency.enforcement.execute({
|
|
549
|
+
executor: `mcp:${config.serverInfo.name}/${name}`,
|
|
550
|
+
leaseId: lease.leaseId,
|
|
551
|
+
run: invoke
|
|
552
|
+
});
|
|
553
|
+
meta.agencyLeaseId = lease.leaseId;
|
|
554
|
+
meta.agencyReceiptId = executed.receipt.receiptId;
|
|
555
|
+
result = executed.result;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
404
558
|
ok = result.isError !== true;
|
|
405
559
|
payload = { id, jsonrpc: "2.0", result };
|
|
406
560
|
} catch (error) {
|
|
@@ -418,7 +572,7 @@ var runTool = async (config, caller, id, name, args, meta, tool, context) => {
|
|
|
418
572
|
await config.onCall({ args, caller, meta, name, ok });
|
|
419
573
|
return payload;
|
|
420
574
|
};
|
|
421
|
-
var toolsCallStreaming = (config, caller, id, name, args, meta, tool, sessions, canElicit) => {
|
|
575
|
+
var toolsCallStreaming = (config, caller, scopes, id, name, args, meta, tool, sessions, canElicit) => {
|
|
422
576
|
const encoder = new TextEncoder;
|
|
423
577
|
const body = new ReadableStream({
|
|
424
578
|
async start(controller) {
|
|
@@ -447,7 +601,7 @@ var toolsCallStreaming = (config, caller, id, name, args, meta, tool, sessions,
|
|
|
447
601
|
return await pending.answer;
|
|
448
602
|
}
|
|
449
603
|
};
|
|
450
|
-
const payload = await runTool(config, caller, id, name, args, meta, tool, context);
|
|
604
|
+
const payload = await runTool(config, caller, scopes, id, name, args, meta, tool, context);
|
|
451
605
|
send(payload);
|
|
452
606
|
if (open) {
|
|
453
607
|
try {
|
|
@@ -474,19 +628,101 @@ var toolsCall = async (config, caller, scopes, id, params, context) => {
|
|
|
474
628
|
}
|
|
475
629
|
const tools = await config.tools({ caller, meta });
|
|
476
630
|
const tool = tools[name];
|
|
477
|
-
if (!tool || !scopeAllows(tool, scopes)) {
|
|
631
|
+
if (!tool || !scopeAllows(tool, scopes) || !agencyAllows(config, tool, scopes)) {
|
|
478
632
|
return rpcError(id, JSONRPC_INVALID_PARAMS, `Unknown tool: ${name}`);
|
|
479
633
|
}
|
|
634
|
+
const tasks = config.tasks;
|
|
635
|
+
if (tasks !== undefined && await tasks.shouldCreate({ args, caller, name })) {
|
|
636
|
+
if (!supportsTasks(params)) {
|
|
637
|
+
return rpcError(id, JSONRPC_MISSING_REQUIRED_CLIENT_CAPABILITY, "Missing required client capability", {
|
|
638
|
+
requiredCapabilities: {
|
|
639
|
+
extensions: { "io.modelcontextprotocol/tasks": {} }
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
const createdAt = new Date().toISOString();
|
|
644
|
+
const task = {
|
|
645
|
+
authorizationKey: await tasks.authorizationKey(caller),
|
|
646
|
+
createdAt,
|
|
647
|
+
lastUpdatedAt: createdAt,
|
|
648
|
+
pollIntervalMs: tasks.pollIntervalMs,
|
|
649
|
+
status: "working",
|
|
650
|
+
taskId: crypto.randomUUID(),
|
|
651
|
+
ttlMs: tasks.ttlMs ?? null
|
|
652
|
+
};
|
|
653
|
+
await tasks.store.save(task);
|
|
654
|
+
setTimeout(() => {
|
|
655
|
+
runTool(config, caller, scopes, id, name, args, meta, tool, noElicit).then(async (payload2) => {
|
|
656
|
+
const result = isRecord(payload2) && isRecord(payload2.result) ? payload2.result : { content: [], isError: true };
|
|
657
|
+
await tasks.store.update(task.taskId, {
|
|
658
|
+
result,
|
|
659
|
+
status: "completed"
|
|
660
|
+
});
|
|
661
|
+
}).catch(async (error) => {
|
|
662
|
+
await tasks.store.update(task.taskId, {
|
|
663
|
+
error: {
|
|
664
|
+
code: JSONRPC_INTERNAL_ERROR,
|
|
665
|
+
message: error instanceof Error ? error.message : "Task failed"
|
|
666
|
+
},
|
|
667
|
+
status: "failed"
|
|
668
|
+
});
|
|
669
|
+
});
|
|
670
|
+
}, 0);
|
|
671
|
+
return rpcResult(id, { ...publicMcpTask(task), resultType: "task" });
|
|
672
|
+
}
|
|
480
673
|
const sessions = context.sessions;
|
|
481
674
|
const session = sessions ? await sessions.get(context.sessionId ?? null) : null;
|
|
482
675
|
if (tool.mayElicit === true && config.elicitation?.enabled === true && sessions && session) {
|
|
483
|
-
return toolsCallStreaming(config, caller, id, name, args, meta, tool, sessions, session.canElicit);
|
|
676
|
+
return toolsCallStreaming(config, caller, scopes, id, name, args, meta, tool, sessions, session.canElicit);
|
|
484
677
|
}
|
|
485
|
-
const payload = await runTool(config, caller, id, name, args, meta, tool, noElicit);
|
|
678
|
+
const payload = await runTool(config, caller, scopes, id, name, args, meta, tool, noElicit);
|
|
486
679
|
return new Response(JSON.stringify(payload), {
|
|
487
680
|
headers: { "content-type": "application/json" }
|
|
488
681
|
});
|
|
489
682
|
};
|
|
683
|
+
var supportsTasks = (params) => {
|
|
684
|
+
if (!isRecord(params) || !isRecord(params._meta))
|
|
685
|
+
return false;
|
|
686
|
+
const capabilities = params._meta["io.modelcontextprotocol/clientCapabilities"];
|
|
687
|
+
if (!isRecord(capabilities) || !isRecord(capabilities.extensions))
|
|
688
|
+
return false;
|
|
689
|
+
return isRecord(capabilities.extensions["io.modelcontextprotocol/tasks"]);
|
|
690
|
+
};
|
|
691
|
+
var authorizedTask = async (config, caller, params) => {
|
|
692
|
+
if (config.tasks === undefined || !isRecord(params) || typeof params.taskId !== "string") {
|
|
693
|
+
return null;
|
|
694
|
+
}
|
|
695
|
+
const task = await config.tasks.store.get(params.taskId);
|
|
696
|
+
if (task === null)
|
|
697
|
+
return null;
|
|
698
|
+
const authorizationKey = await config.tasks.authorizationKey(caller);
|
|
699
|
+
return task.authorizationKey === authorizationKey ? task : null;
|
|
700
|
+
};
|
|
701
|
+
var tasksGet = async (config, caller, id, params) => {
|
|
702
|
+
const task = await authorizedTask(config, caller, params);
|
|
703
|
+
if (task === null)
|
|
704
|
+
return rpcError(id, JSONRPC_INVALID_PARAMS, "Unknown task");
|
|
705
|
+
return rpcResult(id, { ...publicMcpTask(task), resultType: "complete" });
|
|
706
|
+
};
|
|
707
|
+
var tasksUpdate = async (config, caller, id, params) => {
|
|
708
|
+
const task = await authorizedTask(config, caller, params);
|
|
709
|
+
if (task === null || !isRecord(params) || !isRecord(params.inputResponses)) {
|
|
710
|
+
return rpcError(id, JSONRPC_INVALID_PARAMS, "Unknown task or invalid inputResponses");
|
|
711
|
+
}
|
|
712
|
+
await config.tasks?.onUpdate?.({
|
|
713
|
+
caller,
|
|
714
|
+
inputResponses: params.inputResponses,
|
|
715
|
+
task
|
|
716
|
+
});
|
|
717
|
+
return rpcResult(id, { resultType: "complete" });
|
|
718
|
+
};
|
|
719
|
+
var tasksCancel = async (config, caller, id, params) => {
|
|
720
|
+
const task = await authorizedTask(config, caller, params);
|
|
721
|
+
if (task === null)
|
|
722
|
+
return rpcError(id, JSONRPC_INVALID_PARAMS, "Unknown task");
|
|
723
|
+
await config.tasks?.store.cancel(task.taskId);
|
|
724
|
+
return rpcResult(id, { resultType: "complete" });
|
|
725
|
+
};
|
|
490
726
|
var promptsList = (config, id, params) => {
|
|
491
727
|
const definitions = config.prompts?.definitions ?? {};
|
|
492
728
|
const all = Object.entries(definitions).map(([name, def]) => ({
|
|
@@ -578,6 +814,14 @@ var dispatchMcp = async (config, caller, scopes, message, context = {}) => {
|
|
|
578
814
|
if (method === "initialize") {
|
|
579
815
|
return await initialize(config, id, params, context);
|
|
580
816
|
}
|
|
817
|
+
if (method === "server/discover") {
|
|
818
|
+
return rpcResult(id, {
|
|
819
|
+
capabilities: {
|
|
820
|
+
extensions: config.tasks === undefined ? {} : { "io.modelcontextprotocol/tasks": {} }
|
|
821
|
+
},
|
|
822
|
+
serverInfo: config.serverInfo
|
|
823
|
+
});
|
|
824
|
+
}
|
|
581
825
|
if (method === "ping")
|
|
582
826
|
return rpcResult(id, {});
|
|
583
827
|
if (method === "tools/list") {
|
|
@@ -586,6 +830,12 @@ var dispatchMcp = async (config, caller, scopes, message, context = {}) => {
|
|
|
586
830
|
if (method === "tools/call") {
|
|
587
831
|
return toolsCall(config, caller, scopes, id, params, context);
|
|
588
832
|
}
|
|
833
|
+
if (method === "tasks/get")
|
|
834
|
+
return tasksGet(config, caller, id, params);
|
|
835
|
+
if (method === "tasks/update")
|
|
836
|
+
return tasksUpdate(config, caller, id, params);
|
|
837
|
+
if (method === "tasks/cancel")
|
|
838
|
+
return tasksCancel(config, caller, id, params);
|
|
589
839
|
if (method === "prompts/list")
|
|
590
840
|
return promptsList(config, id, params);
|
|
591
841
|
if (method === "prompts/get")
|
|
@@ -881,12 +1131,14 @@ var mcpServer = (config) => {
|
|
|
881
1131
|
};
|
|
882
1132
|
export {
|
|
883
1133
|
verifyBearer,
|
|
1134
|
+
publicMcpTask,
|
|
884
1135
|
protectedResourceMetadata,
|
|
885
1136
|
metadataPathFor,
|
|
886
1137
|
mcpServer,
|
|
887
1138
|
feedbackTools,
|
|
888
1139
|
dispatchMcp,
|
|
889
1140
|
createSessionRegistry,
|
|
1141
|
+
createMemoryMcpTaskStore,
|
|
890
1142
|
createMcpHandler,
|
|
891
1143
|
createMcpClient,
|
|
892
1144
|
McpClientError,
|