fa-mcp-sdk 0.4.142 → 0.11.2
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 +5 -0
- package/cli-template/.dockerignore +16 -0
- package/cli-template/.gitlab-ci.yml +135 -0
- package/cli-template/AGENTS.md +1 -0
- package/cli-template/CHANGELOG.md +64 -0
- package/cli-template/FA-MCP-SDK-DOC/00-FA-MCP-SDK-index.md +27 -4
- package/cli-template/FA-MCP-SDK-DOC/02-1-tools-and-api.md +195 -0
- package/cli-template/FA-MCP-SDK-DOC/02-2-prompts-and-resources.md +172 -9
- package/cli-template/FA-MCP-SDK-DOC/03-configuration.md +170 -12
- package/cli-template/FA-MCP-SDK-DOC/04-authentication.md +158 -8
- package/cli-template/FA-MCP-SDK-DOC/06-utilities.md +67 -6
- package/cli-template/FA-MCP-SDK-DOC/07-testing-and-operations.md +31 -15
- package/cli-template/FA-MCP-SDK-DOC/10-mcp-apps.md +1 -1
- package/cli-template/FA-MCP-SDK-DOC/11-public-contract.md +342 -0
- package/cli-template/README.md +37 -0
- package/cli-template/deploy/docker/.env.example +10 -0
- package/cli-template/deploy/docker/Dockerfile +44 -0
- package/cli-template/deploy/docker/Dockerfile.local +29 -0
- package/cli-template/deploy/docker/README.md +94 -0
- package/cli-template/deploy/docker/config/local.docker.yaml +14 -0
- package/cli-template/deploy/docker/docker-compose.yml +31 -0
- package/cli-template/deploy/gitlab-runner/.env.example +16 -0
- package/cli-template/deploy/gitlab-runner/README.md +65 -0
- package/cli-template/deploy/gitlab-runner/config/config.toml.template +26 -0
- package/cli-template/deploy/gitlab-runner/docker-compose.yml +39 -0
- package/cli-template/deploy/gitlab-runner/entrypoint.sh +27 -0
- package/cli-template/deploy/gitlab-runner/start.sh +47 -0
- package/cli-template/gitignore +96 -95
- package/cli-template/package.json +1 -1
- package/config/_local.yaml +73 -11
- package/config/custom-environment-variables.yaml +102 -0
- package/config/default.yaml +164 -11
- package/config/local.yaml +20 -19
- package/dist/core/_types_/config.d.ts +119 -0
- package/dist/core/_types_/config.d.ts.map +1 -1
- package/dist/core/_types_/types.d.ts +137 -4
- package/dist/core/_types_/types.d.ts.map +1 -1
- package/dist/core/agent-tester/agent-tester-router.d.ts.map +1 -1
- package/dist/core/agent-tester/agent-tester-router.js +25 -11
- package/dist/core/agent-tester/agent-tester-router.js.map +1 -1
- package/dist/core/agent-tester/services/TesterMcpClientService.d.ts.map +1 -1
- package/dist/core/agent-tester/services/TesterMcpClientService.js +6 -4
- package/dist/core/agent-tester/services/TesterMcpClientService.js.map +1 -1
- package/dist/core/auth/admin-auth.js +4 -4
- package/dist/core/auth/admin-auth.js.map +1 -1
- package/dist/core/auth/agent-tester-auth.d.ts +1 -1
- package/dist/core/auth/agent-tester-auth.d.ts.map +1 -1
- package/dist/core/auth/agent-tester-auth.js +8 -4
- package/dist/core/auth/agent-tester-auth.js.map +1 -1
- package/dist/core/auth/auth-profile.d.ts +38 -0
- package/dist/core/auth/auth-profile.d.ts.map +1 -0
- package/dist/core/auth/auth-profile.js +101 -0
- package/dist/core/auth/auth-profile.js.map +1 -0
- package/dist/core/auth/jwt-v2.d.ts +27 -0
- package/dist/core/auth/jwt-v2.d.ts.map +1 -0
- package/dist/core/auth/jwt-v2.js +180 -0
- package/dist/core/auth/jwt-v2.js.map +1 -0
- package/dist/core/auth/jwt.d.ts +27 -13
- package/dist/core/auth/jwt.d.ts.map +1 -1
- package/dist/core/auth/jwt.js +36 -13
- package/dist/core/auth/jwt.js.map +1 -1
- package/dist/core/auth/key-resolver.d.ts +74 -0
- package/dist/core/auth/key-resolver.d.ts.map +1 -0
- package/dist/core/auth/key-resolver.js +330 -0
- package/dist/core/auth/key-resolver.js.map +1 -0
- package/dist/core/auth/middleware.d.ts.map +1 -1
- package/dist/core/auth/middleware.js +66 -0
- package/dist/core/auth/middleware.js.map +1 -1
- package/dist/core/auth/multi-auth.d.ts +1 -1
- package/dist/core/auth/multi-auth.d.ts.map +1 -1
- package/dist/core/auth/multi-auth.js +7 -7
- package/dist/core/auth/multi-auth.js.map +1 -1
- package/dist/core/auth/token-generator/server.js +4 -4
- package/dist/core/auth/token-generator/server.js.map +1 -1
- package/dist/core/auth/types.d.ts +5 -0
- package/dist/core/auth/types.d.ts.map +1 -1
- package/dist/core/db/pg-db.d.ts +7 -0
- package/dist/core/db/pg-db.d.ts.map +1 -1
- package/dist/core/db/pg-db.js +54 -3
- package/dist/core/db/pg-db.js.map +1 -1
- package/dist/core/errors/BaseMcpError.d.ts +21 -1
- package/dist/core/errors/BaseMcpError.d.ts.map +1 -1
- package/dist/core/errors/BaseMcpError.js +20 -1
- package/dist/core/errors/BaseMcpError.js.map +1 -1
- package/dist/core/errors/ValidationError.d.ts +5 -0
- package/dist/core/errors/ValidationError.d.ts.map +1 -1
- package/dist/core/errors/ValidationError.js +6 -1
- package/dist/core/errors/ValidationError.js.map +1 -1
- package/dist/core/errors/errors.d.ts +31 -3
- package/dist/core/errors/errors.d.ts.map +1 -1
- package/dist/core/errors/errors.js +86 -6
- package/dist/core/errors/errors.js.map +1 -1
- package/dist/core/errors/specific-errors.d.ts +54 -0
- package/dist/core/errors/specific-errors.d.ts.map +1 -0
- package/dist/core/errors/specific-errors.js +82 -0
- package/dist/core/errors/specific-errors.js.map +1 -0
- package/dist/core/index.d.ts +10 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +9 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/init-mcp-server.d.ts.map +1 -1
- package/dist/core/init-mcp-server.js +39 -0
- package/dist/core/init-mcp-server.js.map +1 -1
- package/dist/core/mcp/create-mcp-server.d.ts +12 -6
- package/dist/core/mcp/create-mcp-server.d.ts.map +1 -1
- package/dist/core/mcp/create-mcp-server.js +592 -33
- package/dist/core/mcp/create-mcp-server.js.map +1 -1
- package/dist/core/mcp/debug-trace.d.ts +3 -1
- package/dist/core/mcp/debug-trace.d.ts.map +1 -1
- package/dist/core/mcp/debug-trace.js +17 -2
- package/dist/core/mcp/debug-trace.js.map +1 -1
- package/dist/core/mcp/deprecation.d.ts +31 -0
- package/dist/core/mcp/deprecation.d.ts.map +1 -0
- package/dist/core/mcp/deprecation.js +96 -0
- package/dist/core/mcp/deprecation.js.map +1 -0
- package/dist/core/mcp/mcp-logging.d.ts +32 -0
- package/dist/core/mcp/mcp-logging.d.ts.map +1 -0
- package/dist/core/mcp/mcp-logging.js +97 -0
- package/dist/core/mcp/mcp-logging.js.map +1 -0
- package/dist/core/mcp/pagination.d.ts +13 -0
- package/dist/core/mcp/pagination.d.ts.map +1 -0
- package/dist/core/mcp/pagination.js +50 -0
- package/dist/core/mcp/pagination.js.map +1 -0
- package/dist/core/mcp/prompts.d.ts +5 -1
- package/dist/core/mcp/prompts.d.ts.map +1 -1
- package/dist/core/mcp/prompts.js +3 -1
- package/dist/core/mcp/prompts.js.map +1 -1
- package/dist/core/mcp/resources.d.ts +9 -0
- package/dist/core/mcp/resources.d.ts.map +1 -1
- package/dist/core/mcp/resources.js +158 -11
- package/dist/core/mcp/resources.js.map +1 -1
- package/dist/core/mcp/server-stdio.d.ts +7 -1
- package/dist/core/mcp/server-stdio.d.ts.map +1 -1
- package/dist/core/mcp/server-stdio.js +8 -3
- package/dist/core/mcp/server-stdio.js.map +1 -1
- package/dist/core/mcp/task-store.d.ts +97 -0
- package/dist/core/mcp/task-store.d.ts.map +1 -0
- package/dist/core/mcp/task-store.js +175 -0
- package/dist/core/mcp/task-store.js.map +1 -0
- package/dist/core/mcp/tool-limits.d.ts +22 -0
- package/dist/core/mcp/tool-limits.d.ts.map +1 -0
- package/dist/core/mcp/tool-limits.js +115 -0
- package/dist/core/mcp/tool-limits.js.map +1 -0
- package/dist/core/mcp/validate-tool-args.d.ts +16 -0
- package/dist/core/mcp/validate-tool-args.d.ts.map +1 -0
- package/dist/core/mcp/validate-tool-args.js +67 -0
- package/dist/core/mcp/validate-tool-args.js.map +1 -0
- package/dist/core/mcp/validate-tool-names.d.ts +11 -0
- package/dist/core/mcp/validate-tool-names.d.ts.map +1 -0
- package/dist/core/mcp/validate-tool-names.js +23 -0
- package/dist/core/mcp/validate-tool-names.js.map +1 -0
- package/dist/core/metrics/metrics.d.ts +45 -0
- package/dist/core/metrics/metrics.d.ts.map +1 -0
- package/dist/core/metrics/metrics.js +119 -0
- package/dist/core/metrics/metrics.js.map +1 -0
- package/dist/core/utils/mask-sensitive.d.ts +44 -0
- package/dist/core/utils/mask-sensitive.d.ts.map +1 -0
- package/dist/core/utils/mask-sensitive.js +64 -0
- package/dist/core/utils/mask-sensitive.js.map +1 -0
- package/dist/core/utils/testing/McpHttpClient.d.ts +8 -33
- package/dist/core/utils/testing/McpHttpClient.d.ts.map +1 -1
- package/dist/core/utils/testing/McpHttpClient.js +8 -74
- package/dist/core/utils/testing/McpHttpClient.js.map +1 -1
- package/dist/core/utils/testing/McpStreamableHttpClient.d.ts +24 -30
- package/dist/core/utils/testing/McpStreamableHttpClient.d.ts.map +1 -1
- package/dist/core/utils/testing/McpStreamableHttpClient.js +36 -198
- package/dist/core/utils/testing/McpStreamableHttpClient.js.map +1 -1
- package/dist/core/utils/utils.d.ts.map +1 -1
- package/dist/core/utils/utils.js +2 -0
- package/dist/core/utils/utils.js.map +1 -1
- package/dist/core/web/admin-router.js +3 -3
- package/dist/core/web/admin-router.js.map +1 -1
- package/dist/core/web/cors.d.ts +9 -1
- package/dist/core/web/cors.d.ts.map +1 -1
- package/dist/core/web/cors.js +26 -5
- package/dist/core/web/cors.js.map +1 -1
- package/dist/core/web/event-store.d.ts +33 -0
- package/dist/core/web/event-store.d.ts.map +1 -0
- package/dist/core/web/event-store.js +65 -0
- package/dist/core/web/event-store.js.map +1 -0
- package/dist/core/web/oauth-router.d.ts +37 -0
- package/dist/core/web/oauth-router.d.ts.map +1 -0
- package/dist/core/web/oauth-router.js +207 -0
- package/dist/core/web/oauth-router.js.map +1 -0
- package/dist/core/web/request-id.d.ts +44 -0
- package/dist/core/web/request-id.d.ts.map +1 -0
- package/dist/core/web/request-id.js +82 -0
- package/dist/core/web/request-id.js.map +1 -0
- package/dist/core/web/server-http.d.ts.map +1 -1
- package/dist/core/web/server-http.js +322 -182
- package/dist/core/web/server-http.js.map +1 -1
- package/package.json +15 -2
- package/scripts/claude-2-agents-symlink.js +10 -1
- package/scripts/generate-jwt.js +129 -51
- package/src/template/custom-resources.ts +14 -0
- package/src/template/prompts/custom-prompts.ts +4 -0
- package/src/template/tools/handle-tool-call.ts +59 -3
- package/src/template/tools/tools.ts +92 -31
- package/src/tests/mcp/test-http.js +1 -1
- package/src/tests/mcp/test-sse.js +1 -1
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import * as fs from 'node:fs';
|
|
5
5
|
import * as path from 'node:path';
|
|
6
|
+
import { collectAuthProfile } from '../auth/auth-profile.js';
|
|
6
7
|
import { appConfig, getProjectData } from '../bootstrap/init-config.js';
|
|
7
8
|
import { ROOT_PROJECT_DIR } from '../constants.js';
|
|
9
|
+
import { ResourceNotFoundError } from '../errors/specific-errors.js';
|
|
8
10
|
import { debugMcpResource } from '../debug.js';
|
|
9
11
|
import { emitTrace } from './debug-trace.js';
|
|
10
12
|
import { assembleReadmeWithSatellites } from './readme-assembler.js';
|
|
@@ -18,7 +20,7 @@ catch (err) {
|
|
|
18
20
|
console.error(err);
|
|
19
21
|
}
|
|
20
22
|
const createResources = async (args) => {
|
|
21
|
-
const { customResources, usedHttpHeaders: usedHttpHeadersRaw } = getProjectData();
|
|
23
|
+
const { customResources, usedHttpHeaders: usedHttpHeadersRaw, agentBrief, agentPrompt } = getProjectData();
|
|
22
24
|
// Resolve customResources - can be array or async function
|
|
23
25
|
let resolvedCustomResources = [];
|
|
24
26
|
if (customResources) {
|
|
@@ -49,9 +51,20 @@ Used:
|
|
|
49
51
|
content: appConfig.productName,
|
|
50
52
|
requireAuth: false,
|
|
51
53
|
},
|
|
54
|
+
// Standard §4 SHOULD — version surfaced via resources/read in addition to GET /health and serverInfo.
|
|
55
|
+
{
|
|
56
|
+
uri: 'project://version',
|
|
57
|
+
name: 'project-version',
|
|
58
|
+
title: 'Server version',
|
|
59
|
+
description: 'Current server version (semver). Mirrors GET /health.version and serverInfo.version.',
|
|
60
|
+
mimeType: 'text/plain',
|
|
61
|
+
content: appConfig.version,
|
|
62
|
+
requireAuth: false,
|
|
63
|
+
},
|
|
52
64
|
{
|
|
53
65
|
uri: 'doc://readme',
|
|
54
66
|
name: 'README.md',
|
|
67
|
+
title: 'README',
|
|
55
68
|
description: `Documentation of project '${appConfig.productName}':
|
|
56
69
|
Project description, purpose, features, data sources, installation, launch (STDIO/HTTP), MCP API, configuration, testing, deployment.
|
|
57
70
|
This information is used by searching for this MCP server and its information in the RAG system of the "MCP registry"
|
|
@@ -70,8 +83,62 @@ This information is used by searching for this MCP server and its information in
|
|
|
70
83
|
content: usedHttpHeaders,
|
|
71
84
|
requireAuth: false,
|
|
72
85
|
});
|
|
86
|
+
// Standard §11.2 SHOULD — describe enabled auth methods + claims for agent clients.
|
|
87
|
+
resources.push({
|
|
88
|
+
uri: 'use://auth',
|
|
89
|
+
name: 'auth',
|
|
90
|
+
description: 'Authentication profile: enabled schemes, methods, expected claims, header names.',
|
|
91
|
+
mimeType: 'application/json',
|
|
92
|
+
content: collectAuthProfile(),
|
|
93
|
+
requireAuth: false,
|
|
94
|
+
});
|
|
95
|
+
// Standard §11.2 Avatar profile — service-scheme mirrors of agent_brief / agent_prompt.
|
|
96
|
+
const serviceScheme = appConfig.name;
|
|
97
|
+
const briefUri = `${serviceScheme}://agent/brief`;
|
|
98
|
+
const promptUri = `${serviceScheme}://agent/prompt`;
|
|
99
|
+
const customUris = new Set(resolvedCustomResources.map((r) => r.uri));
|
|
100
|
+
if (agentBrief && !customUris.has(briefUri)) {
|
|
101
|
+
resources.push({
|
|
102
|
+
uri: briefUri,
|
|
103
|
+
name: 'agent-brief',
|
|
104
|
+
description: 'Mirror of prompt agent_brief. Routing-level (level 1) agent description.',
|
|
105
|
+
mimeType: 'text/markdown',
|
|
106
|
+
content: agentBrief,
|
|
107
|
+
requireAuth: false,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (agentPrompt && !customUris.has(promptUri)) {
|
|
111
|
+
resources.push({
|
|
112
|
+
uri: promptUri,
|
|
113
|
+
name: 'agent-prompt',
|
|
114
|
+
description: 'Mirror of prompt agent_prompt. Detailed (level 2) agent instructions.',
|
|
115
|
+
mimeType: 'text/markdown',
|
|
116
|
+
content: agentPrompt,
|
|
117
|
+
requireAuth: false,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
73
120
|
return [...resources, ...resolvedCustomResources];
|
|
74
121
|
};
|
|
122
|
+
/**
|
|
123
|
+
* Standard §11.3 (MAY) — compute the byte size of a resource's content for `resources/list`.
|
|
124
|
+
* Strings and objects are measured as they will be serialized; binary blobs by their byte length.
|
|
125
|
+
* Returns `undefined` for lazy (function) content — computing it would require running the
|
|
126
|
+
* function ahead of `resources/read`, so the size is simply not published in that case.
|
|
127
|
+
*/
|
|
128
|
+
function computeResourceSize(content) {
|
|
129
|
+
if (typeof content === 'function') {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
if (typeof content === 'string') {
|
|
133
|
+
return Buffer.byteLength(content, 'utf-8');
|
|
134
|
+
}
|
|
135
|
+
if (content && typeof content === 'object' && 'blob' in content) {
|
|
136
|
+
const { blob } = content;
|
|
137
|
+
return Buffer.isBuffer(blob) ? blob.length : Buffer.byteLength(String(blob), 'utf-8');
|
|
138
|
+
}
|
|
139
|
+
// Plain object — measured as the JSON the transport will emit.
|
|
140
|
+
return Buffer.byteLength(JSON.stringify(content), 'utf-8');
|
|
141
|
+
}
|
|
75
142
|
export const getResourcesList = async (args) => {
|
|
76
143
|
const startedAt = Date.now();
|
|
77
144
|
if (debugMcpResource.enabled) {
|
|
@@ -79,7 +146,14 @@ export const getResourcesList = async (args) => {
|
|
|
79
146
|
}
|
|
80
147
|
emitTrace('mcp:resource', { kind: 'list-req' });
|
|
81
148
|
const resources = await createResources(args);
|
|
82
|
-
const result = {
|
|
149
|
+
const result = {
|
|
150
|
+
resources: resources.map(({ content, ...rest }) => {
|
|
151
|
+
// Publish `size` only when not already set by the author and computable without running
|
|
152
|
+
// lazy content (standard §11.3).
|
|
153
|
+
const size = rest.size ?? computeResourceSize(content);
|
|
154
|
+
return size === undefined ? { ...rest } : { ...rest, size };
|
|
155
|
+
}),
|
|
156
|
+
};
|
|
83
157
|
const ms = Date.now() - startedAt;
|
|
84
158
|
if (debugMcpResource.enabled) {
|
|
85
159
|
debugMcpResource(`← resources/list (${result.resources.length})\n${JSON.stringify(result, null, 2)}`);
|
|
@@ -87,6 +161,73 @@ export const getResourcesList = async (args) => {
|
|
|
87
161
|
emitTrace('mcp:resource', { kind: 'list-res', count: result.resources.length, ms });
|
|
88
162
|
return result;
|
|
89
163
|
};
|
|
164
|
+
/**
|
|
165
|
+
* Standard §11.5 — resources/templates/list handler. Returns project-supplied templates
|
|
166
|
+
* (`customResourceTemplates` in McpServerData) or empty array.
|
|
167
|
+
*/
|
|
168
|
+
export const getResourceTemplatesList = async (args) => {
|
|
169
|
+
const projectData = getProjectData();
|
|
170
|
+
const raw = projectData?.customResourceTemplates;
|
|
171
|
+
if (!raw) {
|
|
172
|
+
return [];
|
|
173
|
+
}
|
|
174
|
+
if (typeof raw === 'function') {
|
|
175
|
+
return (await raw(args)) ?? [];
|
|
176
|
+
}
|
|
177
|
+
return Array.isArray(raw) ? raw : [];
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* Standard §11.5 — resources/subscribe support. Subscriptions are tracked per server instance
|
|
181
|
+
* (each HTTP session owns its own `Server`). Project code calls `notifyResourceUpdated` to
|
|
182
|
+
* broadcast — only the current server's subscribers receive the notification.
|
|
183
|
+
*/
|
|
184
|
+
const subscribersByServer = new WeakMap();
|
|
185
|
+
export function subscribeResource(server, uri) {
|
|
186
|
+
if (!uri) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
let set = subscribersByServer.get(server);
|
|
190
|
+
if (!set) {
|
|
191
|
+
set = new Set();
|
|
192
|
+
subscribersByServer.set(server, set);
|
|
193
|
+
}
|
|
194
|
+
set.add(uri);
|
|
195
|
+
}
|
|
196
|
+
export function unsubscribeResource(server, uri) {
|
|
197
|
+
const set = subscribersByServer.get(server);
|
|
198
|
+
if (set) {
|
|
199
|
+
set.delete(uri);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
export async function notifyResourceUpdated(server, uri) {
|
|
203
|
+
const set = subscribersByServer.get(server);
|
|
204
|
+
if (!set || !set.has(uri)) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
await server.notification({
|
|
209
|
+
method: 'notifications/resources/updated',
|
|
210
|
+
params: { uri },
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
// best-effort — transport may be closed
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Normalize {@link IResourceBinaryContent} to a base64 string for `contents[0].blob`.
|
|
219
|
+
* Buffer → base64; string with `base64:false` → encode raw bytes; string otherwise → assumed
|
|
220
|
+
* already base64 and passed through.
|
|
221
|
+
*/
|
|
222
|
+
function encodeBlob(bin) {
|
|
223
|
+
if (Buffer.isBuffer(bin.blob)) {
|
|
224
|
+
return bin.blob.toString('base64');
|
|
225
|
+
}
|
|
226
|
+
if (bin.base64 === false) {
|
|
227
|
+
return Buffer.from(String(bin.blob), 'utf-8').toString('base64');
|
|
228
|
+
}
|
|
229
|
+
return String(bin.blob);
|
|
230
|
+
}
|
|
90
231
|
export const getResource = async (uri, args) => {
|
|
91
232
|
const startedAt = Date.now();
|
|
92
233
|
if (debugMcpResource.enabled) {
|
|
@@ -97,7 +238,8 @@ export const getResource = async (uri, args) => {
|
|
|
97
238
|
const resource = resources.find((r) => r.uri === uri);
|
|
98
239
|
if (!resource) {
|
|
99
240
|
emitTrace('mcp:resource', { kind: 'read-err', uri, ms: Date.now() - startedAt, error: 'unknown-resource' });
|
|
100
|
-
|
|
241
|
+
// Standard §13 / Appendix B.2 — classify as -32002 (HTTP 404), not a generic -32603.
|
|
242
|
+
throw new ResourceNotFoundError('Unknown resource', { uri, reason: 'unknown_resource' });
|
|
101
243
|
}
|
|
102
244
|
let { content } = resource;
|
|
103
245
|
if (typeof content === 'function') {
|
|
@@ -105,21 +247,26 @@ export const getResource = async (uri, args) => {
|
|
|
105
247
|
}
|
|
106
248
|
if (!content) {
|
|
107
249
|
emitTrace('mcp:resource', { kind: 'read-err', uri, ms: Date.now() - startedAt, error: 'no-content' });
|
|
108
|
-
throw new
|
|
250
|
+
throw new ResourceNotFoundError('Resource has no content', { uri, reason: 'empty_content' });
|
|
109
251
|
}
|
|
252
|
+
// Standard §11.4 / §12.2 — a resource entry carries exactly one of `text` or `blob`. Binary
|
|
253
|
+
// content is declared as { blob: Buffer | base64-string } and emitted as base64 `blob`.
|
|
254
|
+
const isBinary = typeof content === 'object' && content !== null && 'blob' in content;
|
|
255
|
+
const baseEntry = {
|
|
256
|
+
uri: resource.uri,
|
|
257
|
+
mimeType: resource.mimeType,
|
|
258
|
+
...(resource._meta ? { _meta: resource._meta } : {}),
|
|
259
|
+
};
|
|
110
260
|
const result = {
|
|
111
261
|
contents: [
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
text: content,
|
|
116
|
-
...(resource._meta ? { _meta: resource._meta } : {}),
|
|
117
|
-
},
|
|
262
|
+
isBinary
|
|
263
|
+
? { ...baseEntry, blob: encodeBlob(content) }
|
|
264
|
+
: { ...baseEntry, text: content },
|
|
118
265
|
],
|
|
119
266
|
};
|
|
120
267
|
const ms = Date.now() - startedAt;
|
|
121
268
|
if (debugMcpResource.enabled) {
|
|
122
|
-
const body = typeof content === 'string' ? content : JSON.stringify(content, null, 2);
|
|
269
|
+
const body = isBinary ? '[binary blob]' : typeof content === 'string' ? content : JSON.stringify(content, null, 2);
|
|
123
270
|
debugMcpResource(`← resources/read ${uri}\n${body}`);
|
|
124
271
|
}
|
|
125
272
|
emitTrace('mcp:resource', { kind: 'read-res', uri, ms });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../../../src/core/mcp/resources.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../../../src/core/mcp/resources.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Start STDIO server
|
|
2
|
+
* Start STDIO server.
|
|
3
|
+
*
|
|
4
|
+
* The MCP `Server` is built here, NOT at module load time: `createMcpServer` reads
|
|
5
|
+
* `global.__MCP_PROJECT_DATA__` to decide conditional capabilities (`prompts`, `completions`,
|
|
6
|
+
* `tasks` — standard §8.2 / §8.7). `initMcpServer` only populates that global just before calling
|
|
7
|
+
* this function, so an import-time construction would see empty project data and silently drop the
|
|
8
|
+
* prompts capability (and its handlers) on stdio.
|
|
3
9
|
*/
|
|
4
10
|
export declare function startStdioServer(): Promise<void>;
|
|
5
11
|
//# sourceMappingURL=server-stdio.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-stdio.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/server-stdio.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server-stdio.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/server-stdio.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAKtD"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
2
2
|
import { createMcpServer } from './create-mcp-server.js';
|
|
3
|
-
// Create server instance
|
|
4
|
-
const server = createMcpServer();
|
|
5
3
|
/**
|
|
6
|
-
* Start STDIO server
|
|
4
|
+
* Start STDIO server.
|
|
5
|
+
*
|
|
6
|
+
* The MCP `Server` is built here, NOT at module load time: `createMcpServer` reads
|
|
7
|
+
* `global.__MCP_PROJECT_DATA__` to decide conditional capabilities (`prompts`, `completions`,
|
|
8
|
+
* `tasks` — standard §8.2 / §8.7). `initMcpServer` only populates that global just before calling
|
|
9
|
+
* this function, so an import-time construction would see empty project data and silently drop the
|
|
10
|
+
* prompts capability (and its handlers) on stdio.
|
|
7
11
|
*/
|
|
8
12
|
export async function startStdioServer() {
|
|
13
|
+
const server = createMcpServer('stdio');
|
|
9
14
|
const transport = new StdioServerTransport();
|
|
10
15
|
await server.connect(transport);
|
|
11
16
|
console.error('MCP Server running on stdio');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-stdio.js","sourceRoot":"","sources":["../../../src/core/mcp/server-stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,
|
|
1
|
+
{"version":3,"file":"server-stdio.js","sourceRoot":"","sources":["../../../src/core/mcp/server-stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Task } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
export type TTaskStatus = 'working' | 'input_required' | 'completed' | 'failed' | 'cancelled';
|
|
3
|
+
/** True when a task reached a final state and will not transition further on its own. */
|
|
4
|
+
export declare function isTerminalTaskStatus(status: TTaskStatus): boolean;
|
|
5
|
+
export interface ITaskRecord {
|
|
6
|
+
/** Crypto-random task identifier returned to the client. */
|
|
7
|
+
taskId: string;
|
|
8
|
+
/** Originating MCP method — always 'tools/call' in this package. */
|
|
9
|
+
method: string;
|
|
10
|
+
/** Tool name the task executes (for tasks/list display and metrics). */
|
|
11
|
+
toolName: string;
|
|
12
|
+
status: TTaskStatus;
|
|
13
|
+
/** Epoch ms of creation; used for ttl expiry and eviction order. */
|
|
14
|
+
createdAt: number;
|
|
15
|
+
/** Epoch ms of the last status transition. */
|
|
16
|
+
lastUpdatedAt: number;
|
|
17
|
+
/** Clamped retention duration in ms, surfaced to the client as `Task.ttl`. */
|
|
18
|
+
ttlMs: number;
|
|
19
|
+
/** Epoch ms after which a finished task may be evicted (`createdAt + ttlMs`). */
|
|
20
|
+
expiresAt: number;
|
|
21
|
+
/** Optional diagnostic message for `failed` tasks (already sanitized per §13.3). */
|
|
22
|
+
statusMessage?: string;
|
|
23
|
+
/** Correlation id (§15.1), copied from the creating request context. */
|
|
24
|
+
requestId?: string;
|
|
25
|
+
/** Subject key (JWT `sub`, lower-cased) for per-subject scoping and concurrency accounting. */
|
|
26
|
+
subjectKey: string;
|
|
27
|
+
/** Final tool result once status is `completed` (the same shape tools/call returns). */
|
|
28
|
+
result?: unknown;
|
|
29
|
+
/** AbortController whose signal is passed to the tool handler; aborted on tasks/cancel. */
|
|
30
|
+
abort: AbortController;
|
|
31
|
+
}
|
|
32
|
+
export interface ITaskCreateInput {
|
|
33
|
+
method: string;
|
|
34
|
+
toolName: string;
|
|
35
|
+
subjectKey: string;
|
|
36
|
+
requestId?: string;
|
|
37
|
+
/** Client-requested retention in ms; clamped to `[minTtlMs, maxTtlMs]`. Falls back to default. */
|
|
38
|
+
ttlMs?: number;
|
|
39
|
+
}
|
|
40
|
+
export type TTaskPatch = Partial<Pick<ITaskRecord, 'status' | 'statusMessage' | 'result'>>;
|
|
41
|
+
export interface ITaskStore {
|
|
42
|
+
create(input: ITaskCreateInput): ITaskRecord;
|
|
43
|
+
get(taskId: string): ITaskRecord | undefined;
|
|
44
|
+
/** Lists retained tasks, optionally filtered by subject; insertion order (caller may re-sort). */
|
|
45
|
+
list(subjectKey?: string): ITaskRecord[];
|
|
46
|
+
/** Transitions status and stores result / message. Returns the updated record (or undefined). */
|
|
47
|
+
update(taskId: string, patch: TTaskPatch): ITaskRecord | undefined;
|
|
48
|
+
/** Requests cancellation: aborts the controller and sets `cancelled` if not already terminal. */
|
|
49
|
+
cancel(taskId: string): ITaskRecord | undefined;
|
|
50
|
+
/** Removes expired finished tasks; called on a timer and on create(). */
|
|
51
|
+
sweep(now: number): void;
|
|
52
|
+
/** Recommended client poll interval in ms (mirrored into every task object). */
|
|
53
|
+
readonly pollIntervalMs: number;
|
|
54
|
+
}
|
|
55
|
+
export interface ITaskStoreOptions {
|
|
56
|
+
defaultTtlMs: number;
|
|
57
|
+
minTtlMs: number;
|
|
58
|
+
maxTtlMs: number;
|
|
59
|
+
maxTasks: number;
|
|
60
|
+
pollIntervalMs: number;
|
|
61
|
+
/** Injectable clock for tests. Defaults to `Date.now`. */
|
|
62
|
+
now?: () => number;
|
|
63
|
+
/** When > 0, runs a periodic unref'd sweep. Off (0) for direct construction in tests. */
|
|
64
|
+
autoSweepMs?: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Render an internal task record as the wire-format MCP {@link Task} object (ISO timestamps,
|
|
68
|
+
* `ttl` as the retention duration). Used by every task method and the status notification.
|
|
69
|
+
*/
|
|
70
|
+
export declare function toTaskDto(record: ITaskRecord, pollIntervalMs: number): Task;
|
|
71
|
+
export declare class InMemoryTaskStore implements ITaskStore {
|
|
72
|
+
private readonly tasks;
|
|
73
|
+
private readonly opts;
|
|
74
|
+
private readonly now;
|
|
75
|
+
private sweepTimer;
|
|
76
|
+
constructor(opts: ITaskStoreOptions);
|
|
77
|
+
get pollIntervalMs(): number;
|
|
78
|
+
private clampTtl;
|
|
79
|
+
create(input: ITaskCreateInput): ITaskRecord;
|
|
80
|
+
get(taskId: string): ITaskRecord | undefined;
|
|
81
|
+
list(subjectKey?: string): ITaskRecord[];
|
|
82
|
+
update(taskId: string, patch: TTaskPatch): ITaskRecord | undefined;
|
|
83
|
+
cancel(taskId: string): ITaskRecord | undefined;
|
|
84
|
+
sweep(now: number): void;
|
|
85
|
+
/** Evict the oldest finished tasks when the retention cap is reached. Active tasks are kept. */
|
|
86
|
+
private evictIfNeeded;
|
|
87
|
+
/** Stops the periodic sweeper (tests / shutdown). */
|
|
88
|
+
dispose(): void;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Process-wide task store, lazily built from `appConfig.mcp.tasks`. A singleton because tasks
|
|
92
|
+
* outlive individual HTTP sessions and must be pollable from subsequent requests.
|
|
93
|
+
*/
|
|
94
|
+
export declare function getTaskStore(): InMemoryTaskStore;
|
|
95
|
+
/** Reset the singleton (tests only). */
|
|
96
|
+
export declare function resetTaskStore(): void;
|
|
97
|
+
//# sourceMappingURL=task-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-store.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/task-store.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAI/D,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAI9F,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAEjE;AAED,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+FAA+F;IAC/F,UAAU,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2FAA2F;IAC3F,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kGAAkG;IAClG,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,eAAe,GAAG,QAAQ,CAAC,CAAC,CAAC;AAE3F,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAAC;IAC7C,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IAC7C,kGAAkG;IAClG,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAAC;IACzC,iGAAiG;IACjG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,SAAS,CAAC;IACnE,iGAAiG;IACjG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IAChD,yEAAyE;IACzE,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAU3E;AAED,qBAAa,iBAAkB,YAAW,UAAU;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IACxD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoB;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,UAAU,CAA6B;gBAEnC,IAAI,EAAE,iBAAiB;IAWnC,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,OAAO,CAAC,QAAQ;IAKhB,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW;IAsB5C,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAI5C,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE;IAKxC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,SAAS;IAkBlE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAe/C,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQxB,gGAAgG;IAChG,OAAO,CAAC,aAAa;IAiBrB,qDAAqD;IACrD,OAAO,IAAI,IAAI;CAOhB;AAID;;;GAGG;AACH,wBAAgB,YAAY,IAAI,iBAAiB,CAahD;AAED,wCAAwC;AACxC,wBAAgB,cAAc,IAAI,IAAI,CAGrC"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard §8.7 — task-augmented execution storage.
|
|
3
|
+
*
|
|
4
|
+
* The MCP SDK ships the task schemas (`TaskSchema`, `CreateTaskResultSchema`, …) but no storage or
|
|
5
|
+
* lifecycle. This module supplies both: an {@link ITaskStore} abstraction and a process-memory
|
|
6
|
+
* {@link InMemoryTaskStore} default. A task represents one long-running `tools/call` that returned
|
|
7
|
+
* immediately with a `taskId`; the client then polls `tasks/get`, fetches `tasks/result` and may
|
|
8
|
+
* `tasks/cancel`.
|
|
9
|
+
*
|
|
10
|
+
* The in-memory store is sufficient for a single server instance. It does NOT survive a process
|
|
11
|
+
* restart — unfinished tasks are lost on restart, which is an accepted limitation of the default
|
|
12
|
+
* implementation. A consumer needing durability or horizontal scale can implement {@link ITaskStore}
|
|
13
|
+
* over Redis / PostgreSQL and swap it in.
|
|
14
|
+
*/
|
|
15
|
+
import { randomUUID } from 'node:crypto';
|
|
16
|
+
import { appConfig } from '../bootstrap/init-config.js';
|
|
17
|
+
const TERMINAL_STATUSES = new Set(['completed', 'failed', 'cancelled']);
|
|
18
|
+
/** True when a task reached a final state and will not transition further on its own. */
|
|
19
|
+
export function isTerminalTaskStatus(status) {
|
|
20
|
+
return TERMINAL_STATUSES.has(status);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Render an internal task record as the wire-format MCP {@link Task} object (ISO timestamps,
|
|
24
|
+
* `ttl` as the retention duration). Used by every task method and the status notification.
|
|
25
|
+
*/
|
|
26
|
+
export function toTaskDto(record, pollIntervalMs) {
|
|
27
|
+
return {
|
|
28
|
+
taskId: record.taskId,
|
|
29
|
+
status: record.status,
|
|
30
|
+
ttl: record.ttlMs,
|
|
31
|
+
createdAt: new Date(record.createdAt).toISOString(),
|
|
32
|
+
lastUpdatedAt: new Date(record.lastUpdatedAt).toISOString(),
|
|
33
|
+
pollInterval: pollIntervalMs,
|
|
34
|
+
...(record.statusMessage ? { statusMessage: record.statusMessage } : {}),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export class InMemoryTaskStore {
|
|
38
|
+
tasks = new Map();
|
|
39
|
+
opts;
|
|
40
|
+
now;
|
|
41
|
+
sweepTimer;
|
|
42
|
+
constructor(opts) {
|
|
43
|
+
this.opts = opts;
|
|
44
|
+
this.now = opts.now ?? Date.now;
|
|
45
|
+
if (opts.autoSweepMs && opts.autoSweepMs > 0) {
|
|
46
|
+
this.sweepTimer = setInterval(() => this.sweep(this.now()), opts.autoSweepMs);
|
|
47
|
+
if (typeof this.sweepTimer.unref === 'function') {
|
|
48
|
+
this.sweepTimer.unref();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
get pollIntervalMs() {
|
|
53
|
+
return this.opts.pollIntervalMs;
|
|
54
|
+
}
|
|
55
|
+
clampTtl(requested) {
|
|
56
|
+
const base = typeof requested === 'number' && Number.isFinite(requested) ? requested : this.opts.defaultTtlMs;
|
|
57
|
+
return Math.min(this.opts.maxTtlMs, Math.max(this.opts.minTtlMs, base));
|
|
58
|
+
}
|
|
59
|
+
create(input) {
|
|
60
|
+
const now = this.now();
|
|
61
|
+
this.sweep(now);
|
|
62
|
+
this.evictIfNeeded();
|
|
63
|
+
const ttlMs = this.clampTtl(input.ttlMs);
|
|
64
|
+
const record = {
|
|
65
|
+
taskId: randomUUID(),
|
|
66
|
+
method: input.method,
|
|
67
|
+
toolName: input.toolName,
|
|
68
|
+
status: 'working',
|
|
69
|
+
createdAt: now,
|
|
70
|
+
lastUpdatedAt: now,
|
|
71
|
+
ttlMs,
|
|
72
|
+
expiresAt: now + ttlMs,
|
|
73
|
+
...(input.requestId ? { requestId: input.requestId } : {}),
|
|
74
|
+
subjectKey: input.subjectKey,
|
|
75
|
+
abort: new AbortController(),
|
|
76
|
+
};
|
|
77
|
+
this.tasks.set(record.taskId, record);
|
|
78
|
+
return record;
|
|
79
|
+
}
|
|
80
|
+
get(taskId) {
|
|
81
|
+
return this.tasks.get(taskId);
|
|
82
|
+
}
|
|
83
|
+
list(subjectKey) {
|
|
84
|
+
const all = [...this.tasks.values()];
|
|
85
|
+
return subjectKey === undefined ? all : all.filter((r) => r.subjectKey === subjectKey);
|
|
86
|
+
}
|
|
87
|
+
update(taskId, patch) {
|
|
88
|
+
const record = this.tasks.get(taskId);
|
|
89
|
+
if (!record) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
if (patch.status !== undefined) {
|
|
93
|
+
record.status = patch.status;
|
|
94
|
+
}
|
|
95
|
+
if (patch.statusMessage !== undefined) {
|
|
96
|
+
record.statusMessage = patch.statusMessage;
|
|
97
|
+
}
|
|
98
|
+
if ('result' in patch) {
|
|
99
|
+
record.result = patch.result;
|
|
100
|
+
}
|
|
101
|
+
record.lastUpdatedAt = this.now();
|
|
102
|
+
return record;
|
|
103
|
+
}
|
|
104
|
+
cancel(taskId) {
|
|
105
|
+
const record = this.tasks.get(taskId);
|
|
106
|
+
if (!record) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
// Idempotent: cancelling a finished task returns its current state unchanged.
|
|
110
|
+
if (isTerminalTaskStatus(record.status)) {
|
|
111
|
+
return record;
|
|
112
|
+
}
|
|
113
|
+
record.abort.abort();
|
|
114
|
+
record.status = 'cancelled';
|
|
115
|
+
record.lastUpdatedAt = this.now();
|
|
116
|
+
return record;
|
|
117
|
+
}
|
|
118
|
+
sweep(now) {
|
|
119
|
+
for (const [id, record] of this.tasks) {
|
|
120
|
+
if (isTerminalTaskStatus(record.status) && now > record.expiresAt) {
|
|
121
|
+
this.tasks.delete(id);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/** Evict the oldest finished tasks when the retention cap is reached. Active tasks are kept. */
|
|
126
|
+
evictIfNeeded() {
|
|
127
|
+
if (this.tasks.size < this.opts.maxTasks) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const finished = [...this.tasks.values()]
|
|
131
|
+
.filter((r) => isTerminalTaskStatus(r.status))
|
|
132
|
+
.sort((a, b) => a.createdAt - b.createdAt);
|
|
133
|
+
let toEvict = this.tasks.size - this.opts.maxTasks + 1;
|
|
134
|
+
for (const record of finished) {
|
|
135
|
+
if (toEvict <= 0) {
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
this.tasks.delete(record.taskId);
|
|
139
|
+
toEvict -= 1;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** Stops the periodic sweeper (tests / shutdown). */
|
|
143
|
+
dispose() {
|
|
144
|
+
if (this.sweepTimer) {
|
|
145
|
+
clearInterval(this.sweepTimer);
|
|
146
|
+
this.sweepTimer = undefined;
|
|
147
|
+
}
|
|
148
|
+
this.tasks.clear();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
let singleton;
|
|
152
|
+
/**
|
|
153
|
+
* Process-wide task store, lazily built from `appConfig.mcp.tasks`. A singleton because tasks
|
|
154
|
+
* outlive individual HTTP sessions and must be pollable from subsequent requests.
|
|
155
|
+
*/
|
|
156
|
+
export function getTaskStore() {
|
|
157
|
+
if (!singleton) {
|
|
158
|
+
const cfg = appConfig.mcp.tasks ?? {};
|
|
159
|
+
singleton = new InMemoryTaskStore({
|
|
160
|
+
defaultTtlMs: cfg.defaultTtlMs ?? 3_600_000,
|
|
161
|
+
minTtlMs: cfg.minTtlMs ?? 0,
|
|
162
|
+
maxTtlMs: cfg.maxTtlMs ?? 86_400_000,
|
|
163
|
+
maxTasks: cfg.maxTasks ?? 1000,
|
|
164
|
+
pollIntervalMs: cfg.pollIntervalMs ?? 1000,
|
|
165
|
+
autoSweepMs: 60_000,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return singleton;
|
|
169
|
+
}
|
|
170
|
+
/** Reset the singleton (tests only). */
|
|
171
|
+
export function resetTaskStore() {
|
|
172
|
+
singleton?.dispose();
|
|
173
|
+
singleton = undefined;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=task-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-store.js","sourceRoot":"","sources":["../../../src/core/mcp/task-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { TToolHandlerResponse } from '../_types_/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Race a tool invocation against `mcp.limits.toolTimeoutMs`. On expiry the returned promise
|
|
4
|
+
* rejects with an SDK `McpError` carrying code `-32004` (standard §14 / Appendix B). The
|
|
5
|
+
* pending tool promise is left running — Node.js cannot synchronously abort user code —
|
|
6
|
+
* but the server-side timer is cleared so we don't leak handles. The HTTP-level transport
|
|
7
|
+
* layer in `server-http.ts` runs its own race so the response status becomes 504.
|
|
8
|
+
*/
|
|
9
|
+
export declare function withToolTimeout<T>(toolName: string, exec: () => Promise<T>): Promise<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Trim a tool response so its serialized payload stays under `mcp.limits.maxToolResultBytes`
|
|
12
|
+
* (standard §12.2 / §14). Truncation is signalled BOTH in the textual content and in the
|
|
13
|
+
* structured payload so the client cannot silently miss it.
|
|
14
|
+
*
|
|
15
|
+
* - For `content[].text` entries: the offending entry is cut to fit the budget and suffixed
|
|
16
|
+
* with an explicit `…[truncated]` marker.
|
|
17
|
+
* - For `structuredContent`: a sibling `truncated: true` field is set when the JSON exceeds
|
|
18
|
+
* the budget, and the payload is replaced with a minimal sentinel object so the response
|
|
19
|
+
* still fits the wire frame.
|
|
20
|
+
*/
|
|
21
|
+
export declare function truncateToolResponse<T>(response: TToolHandlerResponse<T>): TToolHandlerResponse<T>;
|
|
22
|
+
//# sourceMappingURL=tool-limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-limits.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/tool-limits.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,oBAAoB,EAAkC,MAAM,qBAAqB,CAAC;AAE3F;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAuB7F;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,QAAQ,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAwElG"}
|