@silkweave/mcp 2.6.0 → 3.0.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 +5 -5
- package/build/cliProxy.d.mts +13 -0
- package/build/cliProxy.d.mts.map +1 -0
- package/build/cliProxy.mjs +113 -0
- package/build/cliProxy.mjs.map +1 -0
- package/build/index.d.mts +12 -33
- package/build/index.d.mts.map +1 -1
- package/build/index.mjs +25 -415
- package/build/index.mjs.map +1 -1
- package/build/registerTools-DlguElKV.mjs +145 -0
- package/build/registerTools-DlguElKV.mjs.map +1 -0
- package/build/result-BVpEX7jU.d.mts +64 -0
- package/build/result-BVpEX7jU.d.mts.map +1 -0
- package/build/result-B_9Eo1ey.mjs +79 -0
- package/build/result-B_9Eo1ey.mjs.map +1 -0
- package/build/tools.d.mts +2 -0
- package/build/tools.mjs +3 -0
- package/package.json +42 -10
package/build/index.mjs
CHANGED
|
@@ -1,241 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
4
|
-
import { LoggingMessageNotificationSchema, ProgressNotificationSchema, isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
-
import { createCLILogger, createLogger } from "@silkweave/logger";
|
|
6
|
-
import { capitalCase, kebabCase, pascalCase } from "change-case";
|
|
7
|
-
import { Command } from "commander";
|
|
8
|
-
import { randomUUID } from "crypto";
|
|
9
|
-
import { SilkweaveError, createContext, isStreamingAction, runStreamingAction } from "@silkweave/core";
|
|
10
|
-
import { randomUUID as randomUUID$1 } from "node:crypto";
|
|
1
|
+
import { i as authStorage, n as requestFromExtra, r as authMiddleware, t as registerTools } from "./registerTools-DlguElKV.mjs";
|
|
2
|
+
import { a as smartToolResult, i as parseResourceMessage, n as handleToolError, r as jsonToolResult, t as errorToolResult } from "./result-B_9Eo1ey.mjs";
|
|
11
3
|
import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
|
|
4
|
+
import { createContext } from "@silkweave/core";
|
|
12
5
|
import express from "express";
|
|
13
|
-
import { generateProtectedResourceMetadata
|
|
14
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
|
+
import { generateProtectedResourceMetadata } from "@silkweave/auth";
|
|
15
7
|
import cors from "cors";
|
|
16
8
|
import { readFile, writeFile } from "fs/promises";
|
|
17
|
-
import { InMemoryEventStore } from "@modelcontextprotocol/sdk/examples/shared/inMemoryEventStore.js";
|
|
18
9
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
19
10
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
20
11
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
21
|
-
|
|
22
|
-
function smartToolResult(data) {
|
|
23
|
-
const text = typeof data === "string" ? data : JSON.stringify(data);
|
|
24
|
-
const mimeType = typeof data === "string" ? "text/plain" : "application/json";
|
|
25
|
-
const ext = typeof data === "string" ? "txt" : "json";
|
|
26
|
-
if (text.length > 4096) {
|
|
27
|
-
const uri = `mcp://toolResult/${randomUUID$1()}.${ext}`;
|
|
28
|
-
const buffer = Buffer.from(text);
|
|
29
|
-
const blob = buffer.toString("base64");
|
|
30
|
-
return { content: [{
|
|
31
|
-
type: "text",
|
|
32
|
-
text: `Received resource ${uri} with ${buffer.byteLength} bytes`
|
|
33
|
-
}, {
|
|
34
|
-
type: "resource",
|
|
35
|
-
resource: {
|
|
36
|
-
uri,
|
|
37
|
-
mimeType,
|
|
38
|
-
blob
|
|
39
|
-
}
|
|
40
|
-
}] };
|
|
41
|
-
} else return { content: [{
|
|
42
|
-
type: "text",
|
|
43
|
-
text
|
|
44
|
-
}] };
|
|
45
|
-
}
|
|
46
|
-
function jsonToolResult(data, isError = false) {
|
|
47
|
-
const result = { content: [{
|
|
48
|
-
type: "text",
|
|
49
|
-
text: JSON.stringify(data)
|
|
50
|
-
}] };
|
|
51
|
-
if (isError) result.isError = true;
|
|
52
|
-
return result;
|
|
53
|
-
}
|
|
54
|
-
function errorToolResult({ code, name, message }) {
|
|
55
|
-
return {
|
|
56
|
-
isError: true,
|
|
57
|
-
content: [{
|
|
58
|
-
type: "text",
|
|
59
|
-
text: JSON.stringify({
|
|
60
|
-
success: false,
|
|
61
|
-
code,
|
|
62
|
-
name,
|
|
63
|
-
message
|
|
64
|
-
})
|
|
65
|
-
}]
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
function handleToolError(error) {
|
|
69
|
-
if (error instanceof SilkweaveError) return jsonToolResult({
|
|
70
|
-
success: false,
|
|
71
|
-
name: error.name,
|
|
72
|
-
message: error.message,
|
|
73
|
-
code: error.code
|
|
74
|
-
}, true);
|
|
75
|
-
else if (error instanceof Error) {
|
|
76
|
-
console.error(error);
|
|
77
|
-
return jsonToolResult({
|
|
78
|
-
success: false,
|
|
79
|
-
name: error.name,
|
|
80
|
-
message: error.message
|
|
81
|
-
}, true);
|
|
82
|
-
} else {
|
|
83
|
-
console.error("Unknown tool error:", error);
|
|
84
|
-
return jsonToolResult({
|
|
85
|
-
success: false,
|
|
86
|
-
name: "Unknown error",
|
|
87
|
-
message: "An unknown error occurred"
|
|
88
|
-
}, true);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
function parseResourceMessage({ resource }) {
|
|
92
|
-
return "blob" in resource ? Buffer.from(resource.blob, "base64").toString("utf-8") : resource.text;
|
|
93
|
-
}
|
|
94
|
-
//#endregion
|
|
95
|
-
//#region src/adapter/cliProxy.ts
|
|
96
|
-
function coerce(value, type) {
|
|
97
|
-
if (value === void 0) return;
|
|
98
|
-
if (type === "number" || type === "integer") {
|
|
99
|
-
const n = Number(value);
|
|
100
|
-
return Number.isNaN(n) ? value : n;
|
|
101
|
-
}
|
|
102
|
-
return value;
|
|
103
|
-
}
|
|
104
|
-
function addCliOption(command, key, prop) {
|
|
105
|
-
const flag = kebabCase(key);
|
|
106
|
-
const description = prop.description;
|
|
107
|
-
const defaultValue = prop.default;
|
|
108
|
-
const type = prop.type;
|
|
109
|
-
if (type === "boolean") {
|
|
110
|
-
command.option(`--${flag}`, description, defaultValue);
|
|
111
|
-
command.option(`--no-${flag}`);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
if (type === "number" || type === "integer") {
|
|
115
|
-
command.option(`--${flag} <number>`, description, defaultValue);
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
if (type === "string" || prop.enum) {
|
|
119
|
-
command.option(`--${flag} <string>`, description, defaultValue);
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
if (type === "object" || type === "array") {
|
|
123
|
-
command.option(`--${flag} <json>`, description ?? "", JSON.parse, defaultValue);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
throw new Error(`Unsupported JSON Schema type for CLI option "${key}": ${type ?? "undefined"}`);
|
|
127
|
-
}
|
|
128
|
-
const defaultFormatter = (message) => {
|
|
129
|
-
if (message.type === "text" && !message.text.includes("mcp://toolResult/")) return `${message.text}`;
|
|
130
|
-
else if (message.type === "resource") return parseResourceMessage(message);
|
|
131
|
-
else return JSON.stringify(message);
|
|
132
|
-
};
|
|
133
|
-
const cliProxy = ({ url, formatter = defaultFormatter }) => {
|
|
134
|
-
return (options, baseContext) => {
|
|
135
|
-
const context = baseContext.fork({ adapter: "cliProxy" });
|
|
136
|
-
const program = new Command().name(options.name).description(options.description).version(options.version).option("-s, --silent", "Silent mode, prevent log messages", false);
|
|
137
|
-
return {
|
|
138
|
-
context,
|
|
139
|
-
start: async () => {
|
|
140
|
-
const client = new Client({
|
|
141
|
-
name: options.name,
|
|
142
|
-
description: options.description,
|
|
143
|
-
version: options.version
|
|
144
|
-
});
|
|
145
|
-
const transport = new StreamableHTTPClientTransport(url);
|
|
146
|
-
await client.connect(transport);
|
|
147
|
-
const { tools } = await client.listTools();
|
|
148
|
-
for (const tool of tools) {
|
|
149
|
-
const name = kebabCase(tool.name);
|
|
150
|
-
const command = program.command(name);
|
|
151
|
-
if (tool.description) command.description(tool.description);
|
|
152
|
-
const properties = tool.inputSchema.properties ?? {};
|
|
153
|
-
for (const key of Object.keys(properties)) addCliOption(command, key, properties[key]);
|
|
154
|
-
command.action(async (args) => {
|
|
155
|
-
const { silent } = program.opts();
|
|
156
|
-
const logger = createCLILogger();
|
|
157
|
-
if (!silent) {
|
|
158
|
-
intro(`${options.name} - ${tool.name}`);
|
|
159
|
-
client.setNotificationHandler(LoggingMessageNotificationSchema, ({ params: { level, data } }) => {
|
|
160
|
-
logger[level](data);
|
|
161
|
-
});
|
|
162
|
-
client.setNotificationHandler(ProgressNotificationSchema, ({ params: { progress, total, message } }) => {
|
|
163
|
-
logger.info({
|
|
164
|
-
progress,
|
|
165
|
-
total,
|
|
166
|
-
message
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
const input = {};
|
|
171
|
-
for (const key of Object.keys(properties)) {
|
|
172
|
-
const value = args[key];
|
|
173
|
-
if (value !== void 0) input[key] = coerce(value, properties[key]?.type);
|
|
174
|
-
}
|
|
175
|
-
(await client.callTool({
|
|
176
|
-
name: tool.name,
|
|
177
|
-
arguments: input,
|
|
178
|
-
_meta: {
|
|
179
|
-
progressToken: randomUUID(),
|
|
180
|
-
disposition: "json"
|
|
181
|
-
}
|
|
182
|
-
})).content.forEach((message, index, messages) => {
|
|
183
|
-
const text = formatter(message, index, messages);
|
|
184
|
-
process.stdout.write(`${text}\n`);
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
await program.parseAsync();
|
|
189
|
-
await transport.close();
|
|
190
|
-
},
|
|
191
|
-
stop: async () => {}
|
|
192
|
-
};
|
|
193
|
-
};
|
|
194
|
-
};
|
|
195
|
-
//#endregion
|
|
196
|
-
//#region src/handlers/auth.ts
|
|
197
|
-
/**
|
|
198
|
-
* Per-request bearer-token storage used by tool handlers to read the resolved
|
|
199
|
-
* `AuthInfo` for the currently-handled MCP call.
|
|
200
|
-
*/
|
|
201
|
-
const authStorage = new AsyncLocalStorage();
|
|
202
|
-
/**
|
|
203
|
-
* Express middleware that validates the `Authorization: Bearer …` header via
|
|
204
|
-
* the supplied `AuthConfig`. On success the resolved `AuthInfo` is placed in
|
|
205
|
-
* `authStorage` for the duration of the downstream handler - `mcpTransport`'s
|
|
206
|
-
* tool callbacks pick it up to populate the silkweave context's `auth` key.
|
|
207
|
-
*
|
|
208
|
-
* The middleware should NOT be applied to OAuth-discovery / token routes -
|
|
209
|
-
* compose it only on the routes that require an authenticated caller (the MCP
|
|
210
|
-
* transport itself, sideload, etc.).
|
|
211
|
-
*/
|
|
212
|
-
function authMiddleware(auth, context) {
|
|
213
|
-
return async (req, res, next) => {
|
|
214
|
-
const result = await validateToken(req.headers.authorization, auth, context.fork({ request: req }));
|
|
215
|
-
if (result.error) {
|
|
216
|
-
for (const [key, value] of Object.entries(result.error.headers)) res.header(key, value);
|
|
217
|
-
res.status(result.error.statusCode).json(result.error.body);
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
if (result.auth) authStorage.run(result.auth, () => {
|
|
221
|
-
next();
|
|
222
|
-
});
|
|
223
|
-
else next();
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
//#endregion
|
|
12
|
+
import { randomUUID } from "crypto";
|
|
227
13
|
//#region src/handlers/cors.ts
|
|
228
14
|
/** Headers required by the MCP protocol that must always be exposed when CORS is in use. */
|
|
229
15
|
const MCP_REQUIRED_HEADERS = [
|
|
230
16
|
"WWW-Authenticate",
|
|
231
|
-
"Mcp-Session-Id",
|
|
232
17
|
"Last-Event-Id",
|
|
233
18
|
"Mcp-Protocol-Version"
|
|
234
19
|
];
|
|
235
20
|
/**
|
|
236
21
|
* CORS middleware preconfigured to expose the headers MCP clients need
|
|
237
|
-
* (`
|
|
238
|
-
*
|
|
22
|
+
* (`Last-Event-Id`, `Mcp-Protocol-Version`, `WWW-Authenticate`) on top of any
|
|
23
|
+
* user-supplied options. (Stateless transport - no `Mcp-Session-Id`.)
|
|
239
24
|
*
|
|
240
25
|
* Pass `false` to disable, omit / pass `true` for permissive defaults, or pass
|
|
241
26
|
* a `CorsOptions` object to override.
|
|
@@ -260,7 +45,7 @@ function mcpCors(corsConfig = true) {
|
|
|
260
45
|
*/
|
|
261
46
|
function protectedResourceMetadata(auth) {
|
|
262
47
|
if (!auth.resourceUrl || !auth.authorizationServers?.length) throw new Error("@silkweave/mcp protectedResourceMetadata(): auth.resourceUrl and auth.authorizationServers are required");
|
|
263
|
-
const metadata = generateProtectedResourceMetadata(auth.resourceUrl, auth.authorizationServers);
|
|
48
|
+
const metadata = generateProtectedResourceMetadata(auth.resourceUrl, auth.authorizationServers, auth.requiredScopes);
|
|
264
49
|
return (_req, res) => {
|
|
265
50
|
res.json(metadata);
|
|
266
51
|
};
|
|
@@ -334,85 +119,6 @@ function sideloadResource(options = {}) {
|
|
|
334
119
|
}
|
|
335
120
|
//#endregion
|
|
336
121
|
//#region src/handlers/transport.ts
|
|
337
|
-
/**
|
|
338
|
-
* Build the generic `request` context value (the same key REST/tRPC populate)
|
|
339
|
-
* from the MCP SDK's `extra.requestInfo`, so transport-agnostic consumers - e.g.
|
|
340
|
-
* `@silkweave/nestjs` `@UseGuards` guards reading
|
|
341
|
-
* `switchToHttp().getRequest().headers` - work over MCP. There is no path
|
|
342
|
-
* `params`/`query` on an MCP call, so those are empty stand-ins for graceful
|
|
343
|
-
* degradation. Returns `undefined` when no HTTP request info is available.
|
|
344
|
-
*/
|
|
345
|
-
function requestFromExtra(requestInfo) {
|
|
346
|
-
if (!requestInfo) return;
|
|
347
|
-
return {
|
|
348
|
-
headers: requestInfo.headers ?? {},
|
|
349
|
-
url: requestInfo.url?.toString(),
|
|
350
|
-
params: {},
|
|
351
|
-
query: {}
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
function registerTools$1(server, actions, context) {
|
|
355
|
-
for (const action of actions) server.registerTool(pascalCase(action.name), {
|
|
356
|
-
title: capitalCase(action.name),
|
|
357
|
-
description: action.description,
|
|
358
|
-
inputSchema: action.input
|
|
359
|
-
}, async (input, extra) => {
|
|
360
|
-
const logger = createLogger({
|
|
361
|
-
stream: process.stderr,
|
|
362
|
-
onLog: (level, data) => {
|
|
363
|
-
extra.sendNotification({
|
|
364
|
-
method: "notifications/message",
|
|
365
|
-
params: {
|
|
366
|
-
level,
|
|
367
|
-
data
|
|
368
|
-
}
|
|
369
|
-
});
|
|
370
|
-
},
|
|
371
|
-
onProgress: ({ progress, total, message }) => {
|
|
372
|
-
if (!extra._meta?.progressToken) return;
|
|
373
|
-
extra.sendNotification({
|
|
374
|
-
method: "notifications/progress",
|
|
375
|
-
params: {
|
|
376
|
-
progress,
|
|
377
|
-
total,
|
|
378
|
-
message,
|
|
379
|
-
progressToken: extra._meta.progressToken
|
|
380
|
-
}
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
const currentAuth = authStorage.getStore();
|
|
385
|
-
const actionContext = context.fork({
|
|
386
|
-
logger,
|
|
387
|
-
extra,
|
|
388
|
-
request: requestFromExtra(extra.requestInfo),
|
|
389
|
-
...currentAuth ? { auth: currentAuth } : {}
|
|
390
|
-
});
|
|
391
|
-
const disposition = extra._meta?.disposition ?? action.disposition;
|
|
392
|
-
const progressToken = extra._meta?.progressToken;
|
|
393
|
-
try {
|
|
394
|
-
let result;
|
|
395
|
-
if (isStreamingAction(action)) result = await runStreamingAction(action, input, actionContext, progressToken ? async (chunk, index) => {
|
|
396
|
-
await extra.sendNotification({
|
|
397
|
-
method: "notifications/progress",
|
|
398
|
-
params: {
|
|
399
|
-
progressToken,
|
|
400
|
-
progress: index + 1,
|
|
401
|
-
message: JSON.stringify(chunk)
|
|
402
|
-
}
|
|
403
|
-
});
|
|
404
|
-
} : void 0);
|
|
405
|
-
else result = await action.run(input, actionContext);
|
|
406
|
-
if (action.toolResult) {
|
|
407
|
-
const response = action.toolResult(result, actionContext);
|
|
408
|
-
if (response) return response;
|
|
409
|
-
}
|
|
410
|
-
return disposition === "json" ? jsonToolResult(result) : smartToolResult(result);
|
|
411
|
-
} catch (error) {
|
|
412
|
-
return handleToolError(error);
|
|
413
|
-
}
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
122
|
function createMcpServer(options, actions, context) {
|
|
417
123
|
const server = new McpServer({
|
|
418
124
|
name: options.name,
|
|
@@ -422,56 +128,28 @@ function createMcpServer(options, actions, context) {
|
|
|
422
128
|
tools: {},
|
|
423
129
|
logging: {}
|
|
424
130
|
} });
|
|
425
|
-
registerTools
|
|
131
|
+
registerTools(server, actions, context);
|
|
426
132
|
return server;
|
|
427
133
|
}
|
|
428
|
-
function createSessionTransport(transports) {
|
|
429
|
-
const transport = new StreamableHTTPServerTransport({
|
|
430
|
-
sessionIdGenerator: () => randomUUID(),
|
|
431
|
-
enableJsonResponse: false,
|
|
432
|
-
eventStore: new InMemoryEventStore(),
|
|
433
|
-
onsessioninitialized: (sId) => {
|
|
434
|
-
transports[sId] = transport;
|
|
435
|
-
}
|
|
436
|
-
});
|
|
437
|
-
transport.onerror = (error) => {
|
|
438
|
-
console.error(error);
|
|
439
|
-
};
|
|
440
|
-
transport.onclose = () => {
|
|
441
|
-
const sid = transport.sessionId;
|
|
442
|
-
if (sid && transports[sid]) delete transports[sid];
|
|
443
|
-
};
|
|
444
|
-
return transport;
|
|
445
|
-
}
|
|
446
134
|
/**
|
|
447
|
-
* Build the MCP Streamable HTTP transport route
|
|
135
|
+
* Build the MCP Streamable HTTP transport route handler.
|
|
448
136
|
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
*
|
|
137
|
+
* Stateless (per the 2026 spec direction): each `POST /mcp` mints a fresh
|
|
138
|
+
* transport + server with `sessionIdGenerator: undefined`, handles exactly that
|
|
139
|
+
* request (streaming progress over SSE when the call carries a `progressToken`),
|
|
140
|
+
* and tears down on response close. No `Mcp-Session-Id`, no session map, no
|
|
141
|
+
* `GET`/`DELETE` reconnect - any request can hit any instance.
|
|
452
142
|
*/
|
|
453
143
|
function mcpTransport(silkweaveOptions, context, actions) {
|
|
454
|
-
const transports = {};
|
|
455
144
|
const post = async (req, res) => {
|
|
456
|
-
const sessionId = req.headers["mcp-session-id"];
|
|
457
145
|
try {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
error: {
|
|
466
|
-
code: -32e3,
|
|
467
|
-
message: "Session not found"
|
|
468
|
-
},
|
|
469
|
-
id: null
|
|
470
|
-
});
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
const transport = createSessionTransport(transports);
|
|
474
|
-
await createMcpServer(silkweaveOptions, actions, context).connect(transport);
|
|
146
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
|
|
147
|
+
const server = createMcpServer(silkweaveOptions, actions, context);
|
|
148
|
+
res.on("close", () => {
|
|
149
|
+
transport.close();
|
|
150
|
+
server.close();
|
|
151
|
+
});
|
|
152
|
+
await server.connect(transport);
|
|
475
153
|
await transport.handleRequest(req, res, req.body);
|
|
476
154
|
} catch (error) {
|
|
477
155
|
console.error("Error handling MCP request:", error);
|
|
@@ -485,18 +163,7 @@ function mcpTransport(silkweaveOptions, context, actions) {
|
|
|
485
163
|
});
|
|
486
164
|
}
|
|
487
165
|
};
|
|
488
|
-
|
|
489
|
-
const sessionId = req.headers["mcp-session-id"];
|
|
490
|
-
if (!sessionId || !transports[sessionId]) {
|
|
491
|
-
res.status(400).send("Invalid or missing session ID");
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
await transports[sessionId].handleRequest(req, res);
|
|
495
|
-
};
|
|
496
|
-
return {
|
|
497
|
-
post,
|
|
498
|
-
stream
|
|
499
|
-
};
|
|
166
|
+
return { post };
|
|
500
167
|
}
|
|
501
168
|
//#endregion
|
|
502
169
|
//#region src/adapter/http.ts
|
|
@@ -542,9 +209,6 @@ function buildMcpExpressApp(silkweaveOptions, context, actions, options) {
|
|
|
542
209
|
if (sideloadResources) app.get("/resource/:id", sideloadResource({ resourceDir }));
|
|
543
210
|
const transport = mcpTransport(silkweaveOptions, context, actions);
|
|
544
211
|
app.post("/mcp", express.json(), transport.post);
|
|
545
|
-
app.get("/mcp", transport.stream);
|
|
546
|
-
app.delete("/mcp", transport.stream);
|
|
547
|
-
app.get("/mcp/resource/:id", transport.stream);
|
|
548
212
|
return app;
|
|
549
213
|
}
|
|
550
214
|
/**
|
|
@@ -601,60 +265,6 @@ const http = (options) => {
|
|
|
601
265
|
};
|
|
602
266
|
//#endregion
|
|
603
267
|
//#region src/adapter/stdio.ts
|
|
604
|
-
function registerTools(server, actions, context) {
|
|
605
|
-
for (const action of actions) server.registerTool(pascalCase(action.name), {
|
|
606
|
-
title: capitalCase(action.name),
|
|
607
|
-
description: action.description,
|
|
608
|
-
inputSchema: action.input
|
|
609
|
-
}, async (input, extra) => {
|
|
610
|
-
const logger = createLogger({
|
|
611
|
-
stream: false,
|
|
612
|
-
onLog: (level, data) => {
|
|
613
|
-
extra.sendNotification({
|
|
614
|
-
method: "notifications/message",
|
|
615
|
-
params: {
|
|
616
|
-
level,
|
|
617
|
-
data
|
|
618
|
-
}
|
|
619
|
-
});
|
|
620
|
-
},
|
|
621
|
-
onProgress: ({ progress, total, message }) => {
|
|
622
|
-
if (!extra._meta?.progressToken) return;
|
|
623
|
-
extra.sendNotification({
|
|
624
|
-
method: "notifications/progress",
|
|
625
|
-
params: {
|
|
626
|
-
progress,
|
|
627
|
-
total,
|
|
628
|
-
message,
|
|
629
|
-
progressToken: extra._meta.progressToken
|
|
630
|
-
}
|
|
631
|
-
});
|
|
632
|
-
}
|
|
633
|
-
});
|
|
634
|
-
const actionContext = context.fork({
|
|
635
|
-
logger,
|
|
636
|
-
extra
|
|
637
|
-
});
|
|
638
|
-
const progressToken = extra._meta?.progressToken;
|
|
639
|
-
try {
|
|
640
|
-
let result;
|
|
641
|
-
if (isStreamingAction(action)) result = await runStreamingAction(action, input, actionContext, progressToken ? async (chunk, index) => {
|
|
642
|
-
await extra.sendNotification({
|
|
643
|
-
method: "notifications/progress",
|
|
644
|
-
params: {
|
|
645
|
-
progressToken,
|
|
646
|
-
progress: index + 1,
|
|
647
|
-
message: JSON.stringify(chunk)
|
|
648
|
-
}
|
|
649
|
-
});
|
|
650
|
-
} : void 0);
|
|
651
|
-
else result = await action.run(input, actionContext);
|
|
652
|
-
return action.toolResult?.(result, actionContext) ?? smartToolResult(result);
|
|
653
|
-
} catch (error) {
|
|
654
|
-
return handleToolError(error);
|
|
655
|
-
}
|
|
656
|
-
});
|
|
657
|
-
}
|
|
658
268
|
const stdio = () => {
|
|
659
269
|
return (options, baseContext) => {
|
|
660
270
|
const context = baseContext.fork({ adapter: "stdio" });
|
|
@@ -669,7 +279,7 @@ const stdio = () => {
|
|
|
669
279
|
return {
|
|
670
280
|
context,
|
|
671
281
|
start: async (actions) => {
|
|
672
|
-
registerTools(server, actions, context);
|
|
282
|
+
registerTools(server, actions, context, { logStream: false });
|
|
673
283
|
const transport = new StdioServerTransport();
|
|
674
284
|
await server.connect(transport);
|
|
675
285
|
},
|
|
@@ -693,6 +303,6 @@ async function createSideloadResource(buffer, { name, contentType }) {
|
|
|
693
303
|
return resource;
|
|
694
304
|
}
|
|
695
305
|
//#endregion
|
|
696
|
-
export { MCP_REQUIRED_HEADERS, authMiddleware, authStorage, buildMcpExpressApp,
|
|
306
|
+
export { MCP_REQUIRED_HEADERS, authMiddleware, authStorage, buildMcpExpressApp, createSideloadResource, errorToolResult, handleToolError, http, jsonToolResult, mcpCors, mcpTransport, oauthRoutes, parseResourceMessage, protectedResourceMetadata, registerTools, requestFromExtra, sideloadResource, smartToolResult, startMcpServer, stdio };
|
|
697
307
|
|
|
698
308
|
//# sourceMappingURL=index.mjs.map
|