@webda/mcp 0.0.0-stage → 4.0.0-beta.4
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 +166 -0
- package/README.md +168 -2
- package/lib/auth.d.ts +27 -0
- package/lib/auth.d.ts.map +1 -0
- package/lib/auth.js +14 -0
- package/lib/auth.js.map +1 -0
- package/lib/bridge.d.ts +26 -0
- package/lib/bridge.d.ts.map +1 -0
- package/lib/bridge.js +72 -0
- package/lib/bridge.js.map +1 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +10 -0
- package/lib/index.js.map +1 -0
- package/lib/invoke.d.ts +108 -0
- package/lib/invoke.d.ts.map +1 -0
- package/lib/invoke.js +180 -0
- package/lib/invoke.js.map +1 -0
- package/lib/mcpservice.service.d.ts +194 -0
- package/lib/mcpservice.service.d.ts.map +1 -0
- package/lib/mcpservice.service.js +463 -0
- package/lib/mcpservice.service.js.map +1 -0
- package/lib/resources.d.ts +86 -0
- package/lib/resources.d.ts.map +1 -0
- package/lib/resources.js +125 -0
- package/lib/resources.js.map +1 -0
- package/lib/schema.d.ts +23 -0
- package/lib/schema.d.ts.map +1 -0
- package/lib/schema.js +69 -0
- package/lib/schema.js.map +1 -0
- package/lib/server.d.ts +54 -0
- package/lib/server.d.ts.map +1 -0
- package/lib/server.js +167 -0
- package/lib/server.js.map +1 -0
- package/lib/sessions.d.ts +78 -0
- package/lib/sessions.d.ts.map +1 -0
- package/lib/sessions.js +99 -0
- package/lib/sessions.js.map +1 -0
- package/lib/tools.d.ts +62 -0
- package/lib/tools.d.ts.map +1 -0
- package/lib/tools.js +126 -0
- package/lib/tools.js.map +1 -0
- package/package.json +47 -3
- package/webda.module.json +211 -0
package/lib/resources.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
const SCHEME = "webda://";
|
|
2
|
+
/**
|
|
3
|
+
* Registry of models exposed as `webda://{Model}/{pk...}` resources
|
|
4
|
+
*/
|
|
5
|
+
export class ResourceRegistry {
|
|
6
|
+
filter;
|
|
7
|
+
entries = [];
|
|
8
|
+
/**
|
|
9
|
+
* @param filter - model short ids to expose, or ["*"]
|
|
10
|
+
*/
|
|
11
|
+
constructor(filter) {
|
|
12
|
+
this.filter = filter;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Rebuild from operations: every visible `{Model}.Get` with `context.pkFields`
|
|
16
|
+
* becomes a model; its `.Query` operation shares the same `context.model`.
|
|
17
|
+
* @param ops - visible operations
|
|
18
|
+
*/
|
|
19
|
+
build(ops) {
|
|
20
|
+
this.entries = [];
|
|
21
|
+
for (const [id, op] of Object.entries(ops)) {
|
|
22
|
+
const match = /^(.+)\.Get$/.exec(id);
|
|
23
|
+
const pkFields = op.context?.pkFields;
|
|
24
|
+
if (!match || op.hidden || op.mcp === false || !Array.isArray(pkFields) || pkFields.length === 0) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const name = match[1];
|
|
28
|
+
if (!this.filter.includes("*") && !this.filter.includes(name)) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const query = Object.entries(ops).find(([qid, q]) => qid.endsWith(".Query") && !q.hidden && q.mcp !== false && q.context?.model !== undefined && q.context.model === op.context.model);
|
|
32
|
+
this.entries.push({ name, getOperationId: id, queryOperationId: query?.[0], pkFields: pkFields.map(String) });
|
|
33
|
+
}
|
|
34
|
+
this.entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* @returns exposed models, sorted by name
|
|
38
|
+
*/
|
|
39
|
+
models() {
|
|
40
|
+
return this.entries;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* @returns MCP resource templates
|
|
44
|
+
*/
|
|
45
|
+
templates() {
|
|
46
|
+
return this.entries.map(m => ({
|
|
47
|
+
uriTemplate: `${SCHEME}${m.name}/${m.pkFields.map(f => `{${f}}`).join("/")}`,
|
|
48
|
+
name: m.name,
|
|
49
|
+
mimeType: "application/json"
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* @param model - the model
|
|
54
|
+
* @param record - an instance (or key object)
|
|
55
|
+
* @returns its resource URI
|
|
56
|
+
*/
|
|
57
|
+
uriFor(model, record) {
|
|
58
|
+
return `${SCHEME}${model.name}/${model.pkFields.map(f => encodeURIComponent(String(record[f]))).join("/")}`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* @param uri - a resource URI
|
|
62
|
+
* @returns the model and decoded key, or undefined when it does not match
|
|
63
|
+
*/
|
|
64
|
+
parse(uri) {
|
|
65
|
+
if (!uri.startsWith(SCHEME)) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const [name, ...segments] = uri.substring(SCHEME.length).split("/");
|
|
69
|
+
const model = this.entries.find(m => m.name === name);
|
|
70
|
+
if (!model || segments.length !== model.pkFields.length || segments.some(s => s === "")) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
const key = {};
|
|
74
|
+
try {
|
|
75
|
+
model.pkFields.forEach((field, i) => (key[field] = decodeURIComponent(segments[i])));
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
return { model, key };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* @param cursor - model and continuation token
|
|
85
|
+
* @param cursor.model - model short id
|
|
86
|
+
* @param cursor.token - continuation token of that model's query
|
|
87
|
+
* @returns opaque cursor
|
|
88
|
+
*/
|
|
89
|
+
export function encodeCursor(cursor) {
|
|
90
|
+
return Buffer.from(JSON.stringify(cursor)).toString("base64url");
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* @param cursor - opaque cursor
|
|
94
|
+
* @returns the decoded cursor, or undefined when absent or invalid
|
|
95
|
+
*/
|
|
96
|
+
export function decodeCursor(cursor) {
|
|
97
|
+
if (!cursor) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const parsed = JSON.parse(Buffer.from(cursor, "base64url").toString());
|
|
102
|
+
if (typeof parsed?.model !== "string") {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
if (parsed.token !== undefined && typeof parsed.token !== "string") {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
return { model: parsed.model, ...(parsed.token !== undefined && { token: parsed.token }) };
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* @param token - continuation token
|
|
116
|
+
* @returns the WebdaQL query for one page
|
|
117
|
+
*/
|
|
118
|
+
export function queryFor(token) {
|
|
119
|
+
if (token === undefined) {
|
|
120
|
+
return "LIMIT 100";
|
|
121
|
+
}
|
|
122
|
+
const escaped = token.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
123
|
+
return `LIMIT 100 OFFSET "${escaped}"`;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
|
package/lib/schema.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loose JSON schema shape used by MCP tool definitions
|
|
3
|
+
*/
|
|
4
|
+
export type JsonSchema = Record<string, any>;
|
|
5
|
+
/**
|
|
6
|
+
* Resolve a schema by name (e.g. an application schema id like "WebdaSample/Post")
|
|
7
|
+
*/
|
|
8
|
+
export type SchemaResolver = (name: string) => JsonSchema | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Return a self-contained copy of a JSON schema with every `$ref` inlined.
|
|
11
|
+
*
|
|
12
|
+
* MCP clients expect self-contained tool schemas. Local refs are looked up in
|
|
13
|
+
* the enclosing schema's `definitions`/`$defs`; anything else is resolved by
|
|
14
|
+
* name through `resolve` (Webda's dangling `#/definitions/<modelId>` refs).
|
|
15
|
+
* Cycles and unresolved refs become `{}` (accept anything).
|
|
16
|
+
*
|
|
17
|
+
* @param schema - the schema to inline
|
|
18
|
+
* @param resolve - resolver for refs not defined locally
|
|
19
|
+
* @param maxDepth - maximum number of nested refs to follow
|
|
20
|
+
* @returns a new schema without `$ref`, `definitions`, `$defs`, `$schema` or `$id`
|
|
21
|
+
*/
|
|
22
|
+
export declare function inlineSchema(schema: JsonSchema, resolve: SchemaResolver, maxDepth?: number): JsonSchema;
|
|
23
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;AAItE;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,GAAE,MAAU,GAAG,UAAU,CAE1G"}
|
package/lib/schema.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const REF_PREFIXES = ["#/definitions/", "#/$defs/"];
|
|
2
|
+
/**
|
|
3
|
+
* Return a self-contained copy of a JSON schema with every `$ref` inlined.
|
|
4
|
+
*
|
|
5
|
+
* MCP clients expect self-contained tool schemas. Local refs are looked up in
|
|
6
|
+
* the enclosing schema's `definitions`/`$defs`; anything else is resolved by
|
|
7
|
+
* name through `resolve` (Webda's dangling `#/definitions/<modelId>` refs).
|
|
8
|
+
* Cycles and unresolved refs become `{}` (accept anything).
|
|
9
|
+
*
|
|
10
|
+
* @param schema - the schema to inline
|
|
11
|
+
* @param resolve - resolver for refs not defined locally
|
|
12
|
+
* @param maxDepth - maximum number of nested refs to follow
|
|
13
|
+
* @returns a new schema without `$ref`, `definitions`, `$defs`, `$schema` or `$id`
|
|
14
|
+
*/
|
|
15
|
+
export function inlineSchema(schema, resolve, maxDepth = 8) {
|
|
16
|
+
return inlineNode(schema, resolve, [schema?.definitions ?? schema?.$defs ?? {}], [], maxDepth);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Inline one schema node
|
|
20
|
+
* @param node - current node
|
|
21
|
+
* @param resolve - external resolver
|
|
22
|
+
* @param defs - stack of definition scopes, innermost last
|
|
23
|
+
* @param seen - ref names currently being expanded (cycle guard)
|
|
24
|
+
* @param maxDepth - remaining ref depth
|
|
25
|
+
* @returns the inlined node
|
|
26
|
+
*/
|
|
27
|
+
function inlineNode(node, resolve, defs, seen, maxDepth) {
|
|
28
|
+
if (Array.isArray(node)) {
|
|
29
|
+
return node.map(item => inlineNode(item, resolve, defs, seen, maxDepth));
|
|
30
|
+
}
|
|
31
|
+
if (node === null || typeof node !== "object") {
|
|
32
|
+
return node;
|
|
33
|
+
}
|
|
34
|
+
if (typeof node.$ref === "string") {
|
|
35
|
+
const prefix = REF_PREFIXES.find(p => node.$ref.startsWith(p));
|
|
36
|
+
let name = prefix ? node.$ref.substring(prefix.length) : node.$ref;
|
|
37
|
+
if (prefix) {
|
|
38
|
+
try {
|
|
39
|
+
name = decodeURIComponent(name);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// malformed escape: fall back to the raw name
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (seen.includes(name) || seen.length >= maxDepth) {
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
let target;
|
|
49
|
+
for (let i = defs.length - 1; i >= 0 && !target; i--) {
|
|
50
|
+
target = defs[i][name];
|
|
51
|
+
}
|
|
52
|
+
target ??= resolve(name);
|
|
53
|
+
if (!target) {
|
|
54
|
+
return {};
|
|
55
|
+
}
|
|
56
|
+
const { $ref, ...siblings } = node;
|
|
57
|
+
const scopes = target.definitions || target.$defs ? [...defs, target.definitions ?? target.$defs] : defs;
|
|
58
|
+
return { ...inlineNode(target, resolve, scopes, [...seen, name], maxDepth), ...inlineNode(siblings, resolve, defs, seen, maxDepth) };
|
|
59
|
+
}
|
|
60
|
+
const out = {};
|
|
61
|
+
for (const [key, value] of Object.entries(node)) {
|
|
62
|
+
if (key === "definitions" || key === "$defs" || key === "$schema" || key === "$id") {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
out[key] = inlineNode(value, resolve, defs, seen, maxDepth);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/lib/server.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Session } from "@webda/core";
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import type { AuthInfo } from "@modelcontextprotocol/sdk/server/auth/types.js";
|
|
4
|
+
import { ResourceRegistry } from "./resources.js";
|
|
5
|
+
import { ToolRegistry } from "./tools.js";
|
|
6
|
+
/**
|
|
7
|
+
* JSON-RPC error code for a missing resource (MCP spec)
|
|
8
|
+
*/
|
|
9
|
+
export declare const RESOURCE_NOT_FOUND = -32002;
|
|
10
|
+
/**
|
|
11
|
+
* Number of tools per tools/list page
|
|
12
|
+
*/
|
|
13
|
+
export declare const TOOLS_PAGE_SIZE = 100;
|
|
14
|
+
/**
|
|
15
|
+
* Dependencies of an MCP server instance
|
|
16
|
+
*/
|
|
17
|
+
export interface McpServerOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Server name and version announced at initialize
|
|
20
|
+
*/
|
|
21
|
+
info: {
|
|
22
|
+
name: string;
|
|
23
|
+
version: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Tools exposed
|
|
27
|
+
*/
|
|
28
|
+
tools: ToolRegistry;
|
|
29
|
+
/**
|
|
30
|
+
* Resources exposed; undefined disables resources
|
|
31
|
+
*/
|
|
32
|
+
resources?: ResourceRegistry;
|
|
33
|
+
/**
|
|
34
|
+
* Truncation threshold for tool and resource text
|
|
35
|
+
*/
|
|
36
|
+
maxOutputBytes: number;
|
|
37
|
+
/**
|
|
38
|
+
* Caller session for a request
|
|
39
|
+
*/
|
|
40
|
+
getSession: (extra: {
|
|
41
|
+
authInfo?: AuthInfo;
|
|
42
|
+
}) => Session;
|
|
43
|
+
/**
|
|
44
|
+
* Hook run before tools/resources requests (tool list change detection)
|
|
45
|
+
*/
|
|
46
|
+
beforeRequest?: () => void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create an SDK server wired to Webda operations
|
|
50
|
+
* @param options - registries, session resolution and limits
|
|
51
|
+
* @returns an unconnected SDK Server
|
|
52
|
+
*/
|
|
53
|
+
export declare function createMcpServer(options: McpServerOptions): Server;
|
|
54
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,OAAO,EAAc,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAa/E,OAAO,EAAwC,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;GAEG;AACH,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAEzC;;GAEG;AACH,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC;;OAEG;IACH,KAAK,EAAE,YAAY,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,UAAU,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,EAAE,QAAQ,CAAA;KAAE,KAAK,OAAO,CAAC;IACxD;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AA6BD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CA4HjE"}
|
package/lib/server.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { canCallOperation, WebdaError } from "@webda/core";
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { CallToolRequestSchema, ErrorCode, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ListToolsRequestSchema, McpError, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import { useLog } from "@webda/workout";
|
|
5
|
+
import { errorToToolResult, runOperation, sessionContext, toToolResult, truncateUtf8 } from "./invoke.js";
|
|
6
|
+
import { decodeCursor, encodeCursor, queryFor } from "./resources.js";
|
|
7
|
+
/**
|
|
8
|
+
* JSON-RPC error code for a missing resource (MCP spec)
|
|
9
|
+
*/
|
|
10
|
+
export const RESOURCE_NOT_FOUND = -32002;
|
|
11
|
+
/**
|
|
12
|
+
* Number of tools per tools/list page
|
|
13
|
+
*/
|
|
14
|
+
export const TOOLS_PAGE_SIZE = 100;
|
|
15
|
+
/**
|
|
16
|
+
* Map an error thrown by a resource operation to an MCP error.
|
|
17
|
+
*
|
|
18
|
+
* With a `uri` (resources/read) a NotFound becomes RESOURCE_NOT_FOUND; without
|
|
19
|
+
* one (resources/list) a NotFound is treated like any other client error.
|
|
20
|
+
* Other 4xx messages are forwarded, anything else is logged and masked.
|
|
21
|
+
* @param err - thrown error
|
|
22
|
+
* @param uri - requested resource uri, when reading one resource
|
|
23
|
+
* @returns the error to throw
|
|
24
|
+
*/
|
|
25
|
+
function toResourceError(err, uri) {
|
|
26
|
+
if (err instanceof McpError) {
|
|
27
|
+
return err;
|
|
28
|
+
}
|
|
29
|
+
if (uri !== undefined && err instanceof WebdaError.NotFound) {
|
|
30
|
+
return new McpError(RESOURCE_NOT_FOUND, "Resource not found", { uri });
|
|
31
|
+
}
|
|
32
|
+
if (err instanceof WebdaError.CodeError) {
|
|
33
|
+
const code = err.getResponseCode();
|
|
34
|
+
if (code >= 400 && code < 500) {
|
|
35
|
+
return new McpError(ErrorCode.InternalError, err.message);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
useLog("ERROR", "MCP resource operation failed", err);
|
|
39
|
+
return new McpError(ErrorCode.InternalError, "Internal error");
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create an SDK server wired to Webda operations
|
|
43
|
+
* @param options - registries, session resolution and limits
|
|
44
|
+
* @returns an unconnected SDK Server
|
|
45
|
+
*/
|
|
46
|
+
export function createMcpServer(options) {
|
|
47
|
+
const { tools, resources } = options;
|
|
48
|
+
const server = new Server(options.info, {
|
|
49
|
+
capabilities: {
|
|
50
|
+
tools: { listChanged: true },
|
|
51
|
+
...(resources ? { resources: { listChanged: false, subscribe: false } } : {})
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const allowed = (session, operationId) => canCallOperation(sessionContext(session), operationId);
|
|
55
|
+
server.setRequestHandler(ListToolsRequestSchema, async (request, extra) => {
|
|
56
|
+
options.beforeRequest?.();
|
|
57
|
+
const session = options.getSession(extra);
|
|
58
|
+
const visible = tools.list().filter(e => allowed(session, e.operationId));
|
|
59
|
+
const offset = Number(request.params?.cursor ?? 0) || 0;
|
|
60
|
+
const page = visible.slice(offset, offset + TOOLS_PAGE_SIZE);
|
|
61
|
+
const next = offset + TOOLS_PAGE_SIZE < visible.length ? String(offset + TOOLS_PAGE_SIZE) : undefined;
|
|
62
|
+
return { tools: page.map(e => e.tool), ...(next ? { nextCursor: next } : {}) };
|
|
63
|
+
});
|
|
64
|
+
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
65
|
+
options.beforeRequest?.();
|
|
66
|
+
const session = options.getSession(extra);
|
|
67
|
+
const entry = tools.get(request.params.name);
|
|
68
|
+
if (!entry || !allowed(session, entry.operationId)) {
|
|
69
|
+
throw new McpError(ErrorCode.InvalidParams, `Unknown tool: ${request.params.name}`);
|
|
70
|
+
}
|
|
71
|
+
const args = request.params.arguments ?? {};
|
|
72
|
+
const progressToken = request.params._meta?.progressToken;
|
|
73
|
+
const pending = [];
|
|
74
|
+
try {
|
|
75
|
+
const { value, streamed } = await runOperation(entry.operationId, {
|
|
76
|
+
session,
|
|
77
|
+
input: entry.wrapped ? args.value : args,
|
|
78
|
+
signal: extra.signal,
|
|
79
|
+
onChunk: progressToken === undefined
|
|
80
|
+
? undefined
|
|
81
|
+
: (chunk, index) => {
|
|
82
|
+
const total = chunk?.total;
|
|
83
|
+
const sent = extra
|
|
84
|
+
.sendNotification({
|
|
85
|
+
method: "notifications/progress",
|
|
86
|
+
params: {
|
|
87
|
+
progressToken,
|
|
88
|
+
progress: index,
|
|
89
|
+
...(typeof total === "number" ? { total } : {}),
|
|
90
|
+
message: JSON.stringify(chunk)
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
.catch(err => useLog("WARN", "MCP progress notification failed", err));
|
|
94
|
+
pending.push(sent);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
await Promise.allSettled(pending);
|
|
98
|
+
return toToolResult(entry, value, streamed, options.maxOutputBytes);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
await Promise.allSettled(pending);
|
|
102
|
+
return errorToToolResult(err);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
if (!resources) {
|
|
106
|
+
return server;
|
|
107
|
+
}
|
|
108
|
+
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
|
|
109
|
+
options.beforeRequest?.();
|
|
110
|
+
return { resourceTemplates: resources.templates() };
|
|
111
|
+
});
|
|
112
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request, extra) => {
|
|
113
|
+
options.beforeRequest?.();
|
|
114
|
+
const match = resources.parse(request.params.uri);
|
|
115
|
+
if (!match) {
|
|
116
|
+
throw new McpError(RESOURCE_NOT_FOUND, "Resource not found", { uri: request.params.uri });
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
const { value } = await runOperation(match.model.getOperationId, { session: options.getSession(extra), input: match.key });
|
|
120
|
+
const cut = truncateUtf8(JSON.stringify(value ?? null), options.maxOutputBytes);
|
|
121
|
+
const text = cut.truncated
|
|
122
|
+
? `${cut.text}\n[output truncated: ${cut.bytes} bytes exceeds maxOutputBytes ${options.maxOutputBytes}]`
|
|
123
|
+
: cut.text;
|
|
124
|
+
return { contents: [{ uri: request.params.uri, mimeType: "application/json", text }] };
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
throw toResourceError(err, request.params.uri);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
server.setRequestHandler(ListResourcesRequestSchema, async (request, extra) => {
|
|
131
|
+
options.beforeRequest?.();
|
|
132
|
+
const session = options.getSession(extra);
|
|
133
|
+
const listable = resources.models().filter(m => m.queryOperationId && allowed(session, m.queryOperationId));
|
|
134
|
+
const cursor = decodeCursor(request.params?.cursor);
|
|
135
|
+
const index = cursor ? listable.findIndex(m => m.name === cursor.model) : 0;
|
|
136
|
+
if (index < 0) {
|
|
137
|
+
throw new McpError(ErrorCode.InvalidParams, "Invalid cursor");
|
|
138
|
+
}
|
|
139
|
+
if (index >= listable.length) {
|
|
140
|
+
return { resources: [] };
|
|
141
|
+
}
|
|
142
|
+
const model = listable[index];
|
|
143
|
+
let value;
|
|
144
|
+
try {
|
|
145
|
+
({ value } = await runOperation(model.queryOperationId, { session, input: { query: queryFor(cursor?.token) } }));
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
throw toResourceError(err);
|
|
149
|
+
}
|
|
150
|
+
const result = (value ?? {});
|
|
151
|
+
const items = (result.results ?? []).map(record => ({
|
|
152
|
+
uri: resources.uriFor(model, record),
|
|
153
|
+
name: `${model.name} ${model.pkFields.map(f => String(record[f])).join("/")}`,
|
|
154
|
+
mimeType: "application/json"
|
|
155
|
+
}));
|
|
156
|
+
let nextCursor;
|
|
157
|
+
if (result.continuationToken) {
|
|
158
|
+
nextCursor = encodeCursor({ model: model.name, token: result.continuationToken });
|
|
159
|
+
}
|
|
160
|
+
else if (index + 1 < listable.length) {
|
|
161
|
+
nextCursor = encodeCursor({ model: listable[index + 1].name });
|
|
162
|
+
}
|
|
163
|
+
return { resources: items, ...(nextCursor ? { nextCursor } : {}) };
|
|
164
|
+
});
|
|
165
|
+
return server;
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAW,UAAU,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,EACL,qBAAqB,EACrB,SAAS,EACT,0BAA0B,EAC1B,kCAAkC,EAClC,sBAAsB,EACtB,QAAQ,EACR,yBAAyB,EAE1B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC1G,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAoB,MAAM,gBAAgB,CAAC;AAGxF;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAK,CAAC;AAEzC;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAgCnC;;;;;;;;;GASG;AACH,SAAS,eAAe,CAAC,GAAY,EAAE,GAAY;IACjD,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,YAAY,UAAU,CAAC,QAAQ,EAAE,CAAC;QAC5D,OAAO,IAAI,QAAQ,CAAC,kBAAkB,EAAE,oBAAoB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,GAAG,YAAY,UAAU,CAAC,SAAS,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;QACnC,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,GAAG,EAAE,CAAC;YAC9B,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IACD,MAAM,CAAC,OAAO,EAAE,+BAA+B,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;AACjE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAAyB;IACvD,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QACtC,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;YAC5B,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9E;KACF,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,CAAC,OAAgB,EAAE,WAAmB,EAAE,EAAE,CAAC,gBAAgB,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC;IAElH,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACxE,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,MAAM,GAAG,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACtG,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvE,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,iBAAiB,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;QAC5C,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,aAAa,CAAC;QAC1D,MAAM,OAAO,GAAuB,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,WAAW,EAAE;gBAChE,OAAO;gBACP,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAE,IAAY,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;gBACjD,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,OAAO,EACL,aAAa,KAAK,SAAS;oBACzB,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;wBACf,MAAM,KAAK,GAAI,KAAa,EAAE,KAAK,CAAC;wBACpC,MAAM,IAAI,GAAG,KAAK;6BACf,gBAAgB,CAAC;4BAChB,MAAM,EAAE,wBAAwB;4BAChC,MAAM,EAAE;gCACN,aAAa;gCACb,QAAQ,EAAE,KAAK;gCACf,GAAG,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gCAC/C,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;6BAC/B;yBACF,CAAC;6BACD,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,kCAAkC,EAAE,GAAG,CAAC,CAAC,CAAC;wBACzE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACrB,CAAC;aACR,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAClC,OAAO,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;QACtE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAClC,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,iBAAiB,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QACtE,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAC1B,OAAO,EAAE,iBAAiB,EAAE,SAAS,CAAC,SAAS,EAAE,EAAE,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,iBAAiB,CAAC,yBAAyB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC3E,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,oBAAoB,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;YAC3H,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;YAChF,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS;gBACxB,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,wBAAwB,GAAG,CAAC,KAAK,iCAAiC,OAAO,CAAC,cAAc,GAAG;gBACxG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;YACb,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACzF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,iBAAiB,CAAC,0BAA0B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC5E,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAC5G,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5E,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC7B,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;QAC3B,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,KAAc,CAAC;QACnB,IAAI,CAAC;YACH,CAAC,EAAE,KAAK,EAAE,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACnH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE,CAAwE,CAAC;QACpG,MAAM,KAAK,GAAe,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC9D,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC;YACpC,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAC7E,QAAQ,EAAE,kBAAkB;SAC7B,CAAC,CAAC,CAAC;QACJ,IAAI,UAA8B,CAAC;QACnC,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;YAC7B,UAAU,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACpF,CAAC;aAAM,IAAI,KAAK,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;YACvC,UAAU,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* An open MCP HTTP session
|
|
4
|
+
*/
|
|
5
|
+
export interface McpSessionEntry {
|
|
6
|
+
/**
|
|
7
|
+
* Mcp-Session-Id
|
|
8
|
+
*/
|
|
9
|
+
id: string;
|
|
10
|
+
/**
|
|
11
|
+
* SDK server bound to this session
|
|
12
|
+
*/
|
|
13
|
+
server: Server;
|
|
14
|
+
/**
|
|
15
|
+
* SDK transport bound to this session
|
|
16
|
+
*/
|
|
17
|
+
transport: {
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* User who initialized the session (undefined = anonymous)
|
|
22
|
+
*/
|
|
23
|
+
userId?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Last activity timestamp (ms)
|
|
26
|
+
*/
|
|
27
|
+
lastSeen: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* In-memory MCP sessions with idle eviction
|
|
31
|
+
*/
|
|
32
|
+
export declare class McpSessionManager {
|
|
33
|
+
protected timeoutMs: number;
|
|
34
|
+
protected now: () => number;
|
|
35
|
+
protected sessions: Map<string, McpSessionEntry>;
|
|
36
|
+
/**
|
|
37
|
+
* @param timeoutMs - idle time before eviction
|
|
38
|
+
* @param now - clock (injectable for tests)
|
|
39
|
+
*/
|
|
40
|
+
constructor(timeoutMs: number, now?: () => number);
|
|
41
|
+
/**
|
|
42
|
+
* @param entry - session to track
|
|
43
|
+
*/
|
|
44
|
+
add(entry: McpSessionEntry): void;
|
|
45
|
+
/**
|
|
46
|
+
* Find a session and refresh its activity
|
|
47
|
+
* @param id - session id
|
|
48
|
+
* @returns the session or undefined
|
|
49
|
+
*/
|
|
50
|
+
get(id: string): McpSessionEntry | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* @param id - session id to forget (does not close it)
|
|
53
|
+
*/
|
|
54
|
+
remove(id: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* @returns all sessions
|
|
57
|
+
*/
|
|
58
|
+
all(): McpSessionEntry[];
|
|
59
|
+
/**
|
|
60
|
+
* Close and remove sessions idle longer than the timeout
|
|
61
|
+
* @returns number of evicted sessions
|
|
62
|
+
*/
|
|
63
|
+
evictIdle(): Promise<number>;
|
|
64
|
+
/**
|
|
65
|
+
* Close and remove the least recently used session
|
|
66
|
+
* @returns the evicted session id, or undefined when there is none
|
|
67
|
+
*/
|
|
68
|
+
evictOldest(): Promise<string | undefined>;
|
|
69
|
+
/**
|
|
70
|
+
* Close every session
|
|
71
|
+
*/
|
|
72
|
+
closeAll(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* @param entry - session to close and remove
|
|
75
|
+
*/
|
|
76
|
+
protected close(entry: McpSessionEntry): Promise<void>;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGxE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,SAAS,EAAE;QAAE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IACtC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAQ1B,SAAS,CAAC,SAAS,EAAE,MAAM;IAC3B,SAAS,CAAC,GAAG,EAAE,MAAM,MAAM;IAR7B,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAa;IAE7D;;;OAGG;IACH,YACY,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAAM,MAAyB,EAC5C;IAEJ;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAGhC;IAED;;;;OAIG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAM3C;IAED;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEvB;IAED;;OAEG;IACH,GAAG,IAAI,eAAe,EAAE,CAEvB;IAED;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAOjC;IAED;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAY/C;IAED;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAI9B;IAED;;OAEG;IACH,UAAgB,KAAK,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ3D;CACF"}
|
package/lib/sessions.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { useLog } from "@webda/workout";
|
|
2
|
+
/**
|
|
3
|
+
* In-memory MCP sessions with idle eviction
|
|
4
|
+
*/
|
|
5
|
+
export class McpSessionManager {
|
|
6
|
+
timeoutMs;
|
|
7
|
+
now;
|
|
8
|
+
sessions = new Map();
|
|
9
|
+
/**
|
|
10
|
+
* @param timeoutMs - idle time before eviction
|
|
11
|
+
* @param now - clock (injectable for tests)
|
|
12
|
+
*/
|
|
13
|
+
constructor(timeoutMs, now = () => Date.now()) {
|
|
14
|
+
this.timeoutMs = timeoutMs;
|
|
15
|
+
this.now = now;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* @param entry - session to track
|
|
19
|
+
*/
|
|
20
|
+
add(entry) {
|
|
21
|
+
entry.lastSeen = this.now();
|
|
22
|
+
this.sessions.set(entry.id, entry);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Find a session and refresh its activity
|
|
26
|
+
* @param id - session id
|
|
27
|
+
* @returns the session or undefined
|
|
28
|
+
*/
|
|
29
|
+
get(id) {
|
|
30
|
+
const entry = this.sessions.get(id);
|
|
31
|
+
if (entry) {
|
|
32
|
+
entry.lastSeen = this.now();
|
|
33
|
+
}
|
|
34
|
+
return entry;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* @param id - session id to forget (does not close it)
|
|
38
|
+
*/
|
|
39
|
+
remove(id) {
|
|
40
|
+
this.sessions.delete(id);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* @returns all sessions
|
|
44
|
+
*/
|
|
45
|
+
all() {
|
|
46
|
+
return [...this.sessions.values()];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Close and remove sessions idle longer than the timeout
|
|
50
|
+
* @returns number of evicted sessions
|
|
51
|
+
*/
|
|
52
|
+
async evictIdle() {
|
|
53
|
+
const limit = this.now() - this.timeoutMs;
|
|
54
|
+
const idle = this.all().filter(e => e.lastSeen < limit);
|
|
55
|
+
for (const entry of idle) {
|
|
56
|
+
await this.close(entry);
|
|
57
|
+
}
|
|
58
|
+
return idle.length;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Close and remove the least recently used session
|
|
62
|
+
* @returns the evicted session id, or undefined when there is none
|
|
63
|
+
*/
|
|
64
|
+
async evictOldest() {
|
|
65
|
+
let oldest;
|
|
66
|
+
for (const entry of this.sessions.values()) {
|
|
67
|
+
if (!oldest || entry.lastSeen < oldest.lastSeen) {
|
|
68
|
+
oldest = entry;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (!oldest) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
await this.close(oldest);
|
|
75
|
+
return oldest.id;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Close every session
|
|
79
|
+
*/
|
|
80
|
+
async closeAll() {
|
|
81
|
+
for (const entry of this.all()) {
|
|
82
|
+
await this.close(entry);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* @param entry - session to close and remove
|
|
87
|
+
*/
|
|
88
|
+
async close(entry) {
|
|
89
|
+
this.sessions.delete(entry.id);
|
|
90
|
+
try {
|
|
91
|
+
await entry.transport.close();
|
|
92
|
+
await entry.server.close();
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
useLog("WARN", "Failed to close MCP session", entry.id, err);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AA4BxC;;GAEG;AACH,MAAM,OAAO,iBAAiB;IAQhB,SAAS;IACT,GAAG;IARL,QAAQ,GAAiC,IAAI,GAAG,EAAE,CAAC;IAE7D;;;OAGG;IACH,YACY,SAAiB,EACjB,GAAG,GAAiB,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;yBADpC,SAAS;mBACT,GAAG;IACZ,CAAC;IAEJ;;OAEG;IACH,GAAG,CAAC,KAAsB;QACxB,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,EAAU;QACZ,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,EAAU;QACf,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,GAAG;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;QAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC;QACxD,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW;QACf,IAAI,MAAmC,CAAC;QACxC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAChD,MAAM,GAAG,KAAK,CAAC;YACjB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACzB,OAAO,MAAM,CAAC,EAAE,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ;QACZ,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC/B,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED;;OAEG;IACO,KAAK,CAAC,KAAK,CAAC,KAAsB;QAC1C,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;YAC9B,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,MAAM,EAAE,6BAA6B,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;CACF"}
|