@silkweave/mcp 3.2.1 → 4.0.1

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.
@@ -0,0 +1,163 @@
1
+ import { i as rpcInfo, n as FilterRequest, r as filterErrorResponse, t as FilterActions } from "./filter-BuYC4eO9.mjs";
2
+ import { Action, AdapterFactory, OnToolCall, SilkweaveContext, SilkweaveOptions } from "@silkweave/core";
3
+ import { CreateMcpExpressAppOptions } from "@modelcontextprotocol/sdk/server/express.js";
4
+ import { Express, Request, RequestHandler } from "express";
5
+ import { AuthConfig, AuthInfo } from "@silkweave/auth";
6
+ import { CorsOptions, CorsOptions as CorsOptions$1 } from "cors";
7
+ import { Server } from "http";
8
+
9
+ //#region src/adapter/http.d.ts
10
+ interface StartMcpHttpOptions extends CreateMcpExpressAppOptions {
11
+ host: string;
12
+ port: number;
13
+ auth?: AuthConfig;
14
+ /** CORS configuration. `false` to disable, omitted/`true` for permissive defaults, or a `CorsOptions` object. */
15
+ cors?: CorsOptions$1 | boolean;
16
+ /** Mount the `/resource/:id` sideload route. Default `true`. */
17
+ sideloadResources?: boolean;
18
+ /** Directory the sideload route reads from. Default `'resources'`. */
19
+ resourceDir?: string;
20
+ /**
21
+ * Per-request tool filter, applied before `registerTools()` on every
22
+ * `POST /mcp` (the stateless transport recomputes the tool list per request,
23
+ * so permission changes apply on the next `tools/list`). See `FilterActions`
24
+ * for the request stand-in (`headers`/`url`/`method`/`toolName`) and error
25
+ * semantics (a throw surfaces as its `SilkweaveError.statusCode` or 500 -
26
+ * never an empty tool list).
27
+ */
28
+ filterActions?: FilterActions;
29
+ /** Telemetry hook invoked once per tool call (fire-and-forget). */
30
+ onToolCall?: OnToolCall;
31
+ }
32
+ /**
33
+ * Build a fully-wired Express app that exposes the MCP Streamable HTTP
34
+ * transport (plus OAuth / sideload / well-known routes when configured).
35
+ *
36
+ * Pass the resulting `app` to `app.listen(port, host)` yourself, or use the
37
+ * top-level `startMcpServer()` / `http()` adapter conveniences.
38
+ */
39
+ declare function buildMcpExpressApp(silkweaveOptions: SilkweaveOptions, context: SilkweaveContext, actions: Action[], options: StartMcpHttpOptions): Express;
40
+ /**
41
+ * Spin up a standalone MCP Streamable HTTP server on `host:port` for the
42
+ * given `actions`. Returns the underlying `Server` so callers can close it.
43
+ *
44
+ * Convenience for use cases that don't go through the `silkweave()` builder.
45
+ */
46
+ declare function startMcpServer(silkweaveOptions: SilkweaveOptions, actions: Action[], options: StartMcpHttpOptions, context?: SilkweaveContext): Promise<Server>;
47
+ /**
48
+ * Silkweave adapter that owns its own HTTP server. Composes the MCP handler
49
+ * primitives into a fully-wired Express app and listens on `host:port`.
50
+ */
51
+ declare const http: AdapterFactory<StartMcpHttpOptions>;
52
+ //#endregion
53
+ //#region src/handlers/auth.d.ts
54
+ /**
55
+ * Key under which `authMiddleware` stashes the resolved `AuthInfo` on the
56
+ * Express request. `mcpTransport` reads it back and forks it into the per-request
57
+ * silkweave context (whose `fork` the tool-call context inherits), so auth
58
+ * reaches tool handlers without `AsyncLocalStorage` - keeping this handler set
59
+ * free of `node:async_hooks` for edge/serverless portability.
60
+ */
61
+ declare const AUTH_REQUEST_KEY = "__silkweaveAuth";
62
+ /** Read the `AuthInfo` a prior `authMiddleware` attached to the request, if any. */
63
+ declare function authFromRequest(req: Request): AuthInfo | undefined;
64
+ /**
65
+ * Express middleware that validates the `Authorization: Bearer …` header via
66
+ * the supplied `AuthConfig`. On success the resolved `AuthInfo` is attached to
67
+ * the request (see `authFromRequest` / `AUTH_REQUEST_KEY`); `mcpTransport` forks
68
+ * it into the silkweave context for the tool call.
69
+ *
70
+ * The middleware should NOT be applied to OAuth-discovery / token routes -
71
+ * compose it only on the routes that require an authenticated caller (the MCP
72
+ * transport itself, sideload, etc.).
73
+ */
74
+ declare function authMiddleware(auth: AuthConfig, context: SilkweaveContext): RequestHandler;
75
+ //#endregion
76
+ //#region src/handlers/cors.d.ts
77
+ /** Headers required by the MCP protocol that must always be exposed when CORS is in use. */
78
+ declare const MCP_REQUIRED_HEADERS: string[];
79
+ /**
80
+ * CORS middleware preconfigured to expose the headers MCP clients need
81
+ * (`Last-Event-Id`, `Mcp-Protocol-Version`, `WWW-Authenticate`) on top of any
82
+ * user-supplied options. (Stateless transport - no `Mcp-Session-Id`.)
83
+ *
84
+ * Pass `false` to disable, omit / pass `true` for permissive defaults, or pass
85
+ * a `CorsOptions` object to override.
86
+ */
87
+ declare function mcpCors(corsConfig?: CorsOptions$1 | boolean): RequestHandler | null;
88
+ //#endregion
89
+ //#region src/handlers/metadata.d.ts
90
+ /**
91
+ * Handler for `GET /.well-known/oauth-protected-resource` (RFC 9728). Returns
92
+ * the resource server's metadata pointing at the configured authorization
93
+ * servers. Requires `auth.resourceUrl` and a non-empty `auth.authorizationServers`.
94
+ */
95
+ declare function protectedResourceMetadata(auth: AuthConfig): RequestHandler;
96
+ //#endregion
97
+ //#region src/handlers/oauth.d.ts
98
+ interface OAuthRouteHandlers {
99
+ /** `GET /.well-known/oauth-authorization-server` - RFC 8414 discovery. */
100
+ wellKnownAuthServer: RequestHandler;
101
+ /** `GET /authorize` - start the OAuth flow. */
102
+ authorize: RequestHandler;
103
+ /** `GET {callbackPath}` - provider callback. */
104
+ callback: RequestHandler;
105
+ /** Path the provider should redirect to (defaults to `/auth/callback`). */
106
+ callbackPath: string;
107
+ /** `POST /token` - exchange code / refresh token. Includes urlencoded body parser. */
108
+ token: RequestHandler[];
109
+ /** `POST /register` - dynamic client registration. Includes JSON body parser. */
110
+ register: RequestHandler[];
111
+ }
112
+ /**
113
+ * Build the OAuth 2.1 proxy route handlers (authorize, callback, token,
114
+ * register, well-known) backed by the configured `auth.provider`. Returns the
115
+ * handlers as individual `RequestHandler`s so callers can register them
116
+ * wherever they like - under `/mcp`, at the server root, etc.
117
+ *
118
+ * `token` and `register` are returned as middleware arrays because the
119
+ * appropriate body parser must run before the handler. Apply with
120
+ * `app.post(path, ...token)`.
121
+ */
122
+ declare function oauthRoutes(auth: AuthConfig): OAuthRouteHandlers;
123
+ //#endregion
124
+ //#region src/handlers/sideload.d.ts
125
+ interface SideloadResourceOptions {
126
+ /** Directory to read sideload resources from. Defaults to `resources/` (cwd-relative). */
127
+ resourceDir?: string;
128
+ }
129
+ /**
130
+ * Handler for `GET /resource/:id` - serves a large MCP response that was
131
+ * sideloaded to disk as a `{id}` payload with a `{id}.json` metadata sidecar.
132
+ *
133
+ * The route param `id` is provided by the host framework (Express, Nest, etc.).
134
+ */
135
+ declare function sideloadResource(options?: SideloadResourceOptions): RequestHandler;
136
+ //#endregion
137
+ //#region src/handlers/transport.d.ts
138
+ interface McpTransportHandlers {
139
+ /** `POST /mcp` - handle a single stateless MCP request/response (SSE per call). */
140
+ post: RequestHandler;
141
+ }
142
+ interface McpTransportOptions {
143
+ /**
144
+ * Per-request tool filter, applied before `registerTools()` on every POST.
145
+ * See `FilterActions` for the request stand-in and error semantics.
146
+ */
147
+ filterActions?: FilterActions;
148
+ /** Telemetry hook invoked once per tool call (fire-and-forget). */
149
+ onToolCall?: OnToolCall;
150
+ }
151
+ /**
152
+ * Build the MCP Streamable HTTP transport route handler.
153
+ *
154
+ * Stateless (per the 2026 spec direction): each `POST /mcp` mints a fresh
155
+ * transport + server with `sessionIdGenerator: undefined`, handles exactly that
156
+ * request (streaming progress over SSE when the call carries a `progressToken`),
157
+ * and tears down on response close. No `Mcp-Session-Id`, no session map, no
158
+ * `GET`/`DELETE` reconnect - any request can hit any instance.
159
+ */
160
+ declare function mcpTransport(silkweaveOptions: SilkweaveOptions, context: SilkweaveContext, actions: Action[], options?: McpTransportOptions): McpTransportHandlers;
161
+ //#endregion
162
+ export { AUTH_REQUEST_KEY, type CorsOptions, FilterActions, FilterRequest, MCP_REQUIRED_HEADERS, McpTransportHandlers, McpTransportOptions, OAuthRouteHandlers, SideloadResourceOptions, StartMcpHttpOptions, authFromRequest, authMiddleware, buildMcpExpressApp, filterErrorResponse, http, mcpCors, mcpTransport, oauthRoutes, protectedResourceMetadata, rpcInfo, sideloadResource, startMcpServer };
163
+ //# sourceMappingURL=server.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.mts","names":[],"sources":["../src/adapter/http.ts","../src/handlers/auth.ts","../src/handlers/cors.ts","../src/handlers/metadata.ts","../src/handlers/oauth.ts","../src/handlers/sideload.ts","../src/handlers/transport.ts"],"mappings":";;;;;;;;;UAciB,mBAAA,SAA4B,0BAAA;EAC3C,IAAA;EACA,IAAA;EACA,IAAA,GAAO,UAAA;;EAEP,IAAA,GAAO,aAAA;EAAA;EAEP,iBAAA;EAaa;EAXb,WAAA;EATqE;;;;;;;;EAkBrE,aAAA,GAAgB,aAAA;EAXhB;EAaA,UAAA,GAAa,UAAA;AAAA;;;;;;AAUf;;iBAAgB,kBAAA,CACd,gBAAA,EAAkB,gBAAA,EAClB,OAAA,EAAS,gBAAA,EACT,OAAA,EAAS,MAAA,IACT,OAAA,EAAS,mBAAA,GACR,OAAA;;;;;;;iBA8CmB,cAAA,CACpB,gBAAA,EAAkB,gBAAA,EAClB,OAAA,EAAS,MAAA,IACT,OAAA,EAAS,mBAAA,EACT,OAAA,GAAU,gBAAA,GACT,OAAA,CAAQ,MAAA;;;;;cAgBE,IAAA,EAAM,cAAA,CAAe,mBAAA;;;;;;;;;AAtGlC;cCHa,gBAAA;;iBAGG,eAAA,CAAgB,GAAA,EAAK,OAAA,GAAU,QAAA;;;;;;;;;;;iBAc/B,cAAA,CAAe,IAAA,EAAM,UAAA,EAAY,OAAA,EAAS,gBAAA,GAAmB,cAAA;;;;cCxBhE,oBAAA;;;;;;AFUb;;;iBEAgB,OAAA,CAAQ,UAAA,GAAY,aAAA,aAA+B,cAAA;;;;;;;;iBCNnD,yBAAA,CAA0B,IAAA,EAAM,UAAA,GAAa,cAAA;;;UCa5C,kBAAA;;EAEf,mBAAA,EAAqB,cAAA;;EAErB,SAAA,EAAW,cAAA;;EAEX,QAAA,EAAU,cAAA;EJbK;EIef,YAAA;;EAEA,KAAA,EAAO,cAAA;EJZA;EIcP,QAAA,EAAU,cAAA;AAAA;;;;;;;;;;;iBAaI,WAAA,CAAY,IAAA,EAAM,UAAA,GAAa,kBAAA;;;UCzC9B,uBAAA;;EAEf,WAAA;AAAA;;;;;ALOF;;iBKEgB,gBAAA,CAAiB,OAAA,GAAS,uBAAA,GAA+B,cAAA;;;UCIxD,oBAAA;;EAEf,IAAA,EAAM,cAAA;AAAA;AAAA,UAGS,mBAAA;;ANXjB;;;EMgBE,aAAA,GAAgB,aAAA;ENXT;EMaP,UAAA,GAAa,UAAA;AAAA;;;;;;;;;;iBAYC,YAAA,CACd,gBAAA,EAAkB,gBAAA,EAClB,OAAA,EAAS,gBAAA,EACT,OAAA,EAAS,MAAA,IACT,OAAA,GAAS,mBAAA,GACR,oBAAA"}
@@ -0,0 +1,339 @@
1
+ import { n as rpcInfo, r as registerTools, t as filterErrorResponse } from "./filter-Baxr12pu.mjs";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { createContext, validateActionDisposition } from "@silkweave/core";
4
+ import { readFile } from "fs/promises";
5
+ import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
6
+ import express from "express";
7
+ import { generateProtectedResourceMetadata, validateToken } from "@silkweave/auth";
8
+ import cors from "cors";
9
+ import { basename, resolve, sep } from "path";
10
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
11
+ //#region src/handlers/auth.ts
12
+ /**
13
+ * Key under which `authMiddleware` stashes the resolved `AuthInfo` on the
14
+ * Express request. `mcpTransport` reads it back and forks it into the per-request
15
+ * silkweave context (whose `fork` the tool-call context inherits), so auth
16
+ * reaches tool handlers without `AsyncLocalStorage` - keeping this handler set
17
+ * free of `node:async_hooks` for edge/serverless portability.
18
+ */
19
+ const AUTH_REQUEST_KEY = "__silkweaveAuth";
20
+ /** Read the `AuthInfo` a prior `authMiddleware` attached to the request, if any. */
21
+ function authFromRequest(req) {
22
+ return req[AUTH_REQUEST_KEY];
23
+ }
24
+ /**
25
+ * Express middleware that validates the `Authorization: Bearer …` header via
26
+ * the supplied `AuthConfig`. On success the resolved `AuthInfo` is attached to
27
+ * the request (see `authFromRequest` / `AUTH_REQUEST_KEY`); `mcpTransport` forks
28
+ * it into the silkweave context for the tool call.
29
+ *
30
+ * The middleware should NOT be applied to OAuth-discovery / token routes -
31
+ * compose it only on the routes that require an authenticated caller (the MCP
32
+ * transport itself, sideload, etc.).
33
+ */
34
+ function authMiddleware(auth, context) {
35
+ return async (req, res, next) => {
36
+ const result = await validateToken(req.headers.authorization, auth, context.fork({ request: req }));
37
+ if (result.error) {
38
+ for (const [key, value] of Object.entries(result.error.headers)) res.header(key, value);
39
+ res.status(result.error.statusCode).json(result.error.body);
40
+ return;
41
+ }
42
+ if (result.auth) req[AUTH_REQUEST_KEY] = result.auth;
43
+ next();
44
+ };
45
+ }
46
+ //#endregion
47
+ //#region src/handlers/cors.ts
48
+ /** Headers required by the MCP protocol that must always be exposed when CORS is in use. */
49
+ const MCP_REQUIRED_HEADERS = [
50
+ "WWW-Authenticate",
51
+ "Last-Event-Id",
52
+ "Mcp-Protocol-Version"
53
+ ];
54
+ /**
55
+ * CORS middleware preconfigured to expose the headers MCP clients need
56
+ * (`Last-Event-Id`, `Mcp-Protocol-Version`, `WWW-Authenticate`) on top of any
57
+ * user-supplied options. (Stateless transport - no `Mcp-Session-Id`.)
58
+ *
59
+ * Pass `false` to disable, omit / pass `true` for permissive defaults, or pass
60
+ * a `CorsOptions` object to override.
61
+ */
62
+ function mcpCors(corsConfig = true) {
63
+ if (corsConfig === false) return null;
64
+ const userConfig = corsConfig === true ? {} : corsConfig;
65
+ const userExposed = userConfig.exposedHeaders;
66
+ const exposedHeaders = [...MCP_REQUIRED_HEADERS, ...Array.isArray(userExposed) ? userExposed : userExposed ? [userExposed] : []];
67
+ return cors({
68
+ origin: "*",
69
+ ...userConfig,
70
+ exposedHeaders
71
+ });
72
+ }
73
+ //#endregion
74
+ //#region src/handlers/metadata.ts
75
+ /**
76
+ * Handler for `GET /.well-known/oauth-protected-resource` (RFC 9728). Returns
77
+ * the resource server's metadata pointing at the configured authorization
78
+ * servers. Requires `auth.resourceUrl` and a non-empty `auth.authorizationServers`.
79
+ */
80
+ function protectedResourceMetadata(auth) {
81
+ if (!auth.resourceUrl || !auth.authorizationServers?.length) throw new Error("@silkweave/mcp protectedResourceMetadata(): auth.resourceUrl and auth.authorizationServers are required");
82
+ const metadata = generateProtectedResourceMetadata(auth.resourceUrl, auth.authorizationServers, auth.requiredScopes);
83
+ return (_req, res) => {
84
+ res.json(metadata);
85
+ };
86
+ }
87
+ //#endregion
88
+ //#region src/handlers/oauth.ts
89
+ function toOAuthReq(req) {
90
+ return {
91
+ method: req.method,
92
+ url: new URL(req.url, `${req.protocol}://${req.get("host")}`),
93
+ headers: Object.fromEntries(Object.entries(req.headers).map(([k, v]) => [k, Array.isArray(v) ? v[0] : v])),
94
+ body: req.body
95
+ };
96
+ }
97
+ function sendOAuth(res, oauthRes) {
98
+ for (const [key, value] of Object.entries(oauthRes.headers)) res.header(key, value);
99
+ if (oauthRes.body) res.status(oauthRes.status).send(typeof oauthRes.body === "string" ? oauthRes.body : JSON.stringify(oauthRes.body));
100
+ else res.status(oauthRes.status).end();
101
+ }
102
+ /**
103
+ * Build the OAuth 2.1 proxy route handlers (authorize, callback, token,
104
+ * register, well-known) backed by the configured `auth.provider`. Returns the
105
+ * handlers as individual `RequestHandler`s so callers can register them
106
+ * wherever they like - under `/mcp`, at the server root, etc.
107
+ *
108
+ * `token` and `register` are returned as middleware arrays because the
109
+ * appropriate body parser must run before the handler. Apply with
110
+ * `app.post(path, ...token)`.
111
+ */
112
+ function oauthRoutes(auth) {
113
+ if (!auth.provider) throw new Error("@silkweave/mcp oauthRoutes(): auth.provider is required");
114
+ const provider = auth.provider;
115
+ return {
116
+ callbackPath: auth.callbackPath ?? "/auth/callback",
117
+ wellKnownAuthServer: (_req, res) => {
118
+ sendOAuth(res, provider.metadata());
119
+ },
120
+ authorize: async (req, res) => {
121
+ sendOAuth(res, await provider.authorize(toOAuthReq(req)));
122
+ },
123
+ callback: async (req, res) => {
124
+ sendOAuth(res, await provider.callback(toOAuthReq(req)));
125
+ },
126
+ token: [express.urlencoded({ extended: false }), async (req, res) => {
127
+ sendOAuth(res, await provider.token(toOAuthReq(req)));
128
+ }],
129
+ register: [express.json(), async (req, res) => {
130
+ sendOAuth(res, await provider.register(toOAuthReq(req)));
131
+ }]
132
+ };
133
+ }
134
+ //#endregion
135
+ //#region src/handlers/sideload.ts
136
+ /**
137
+ * Handler for `GET /resource/:id` - serves a large MCP response that was
138
+ * sideloaded to disk as a `{id}` payload with a `{id}.json` metadata sidecar.
139
+ *
140
+ * The route param `id` is provided by the host framework (Express, Nest, etc.).
141
+ */
142
+ function sideloadResource(options = {}) {
143
+ const { resourceDir = "resources" } = options;
144
+ const baseDir = resolve(resourceDir);
145
+ return async (req, res) => {
146
+ const id = req.params["id"];
147
+ if (!id || typeof id !== "string") throw new Error("Invalid ID");
148
+ const safeId = basename(id);
149
+ const target = resolve(baseDir, safeId);
150
+ if (safeId !== id || target !== baseDir && !target.startsWith(baseDir + sep)) {
151
+ res.status(400).json({ error: "invalid_resource_id" });
152
+ return;
153
+ }
154
+ const resourceMeta = JSON.parse(await readFile(`${target}.json`, "utf-8"));
155
+ const buffer = await readFile(target);
156
+ res.status(200);
157
+ res.header("Content-Type", resourceMeta.contentType);
158
+ res.send(buffer);
159
+ };
160
+ }
161
+ //#endregion
162
+ //#region src/handlers/transport.ts
163
+ function createMcpServer(options, actions, context, onToolCall) {
164
+ const server = new McpServer({
165
+ name: options.name,
166
+ description: options.description,
167
+ version: options.version
168
+ }, { capabilities: {
169
+ tools: {},
170
+ logging: {}
171
+ } });
172
+ registerTools(server, actions, context, { onToolCall });
173
+ return server;
174
+ }
175
+ /**
176
+ * Build the MCP Streamable HTTP transport route handler.
177
+ *
178
+ * Stateless (per the 2026 spec direction): each `POST /mcp` mints a fresh
179
+ * transport + server with `sessionIdGenerator: undefined`, handles exactly that
180
+ * request (streaming progress over SSE when the call carries a `progressToken`),
181
+ * and tears down on response close. No `Mcp-Session-Id`, no session map, no
182
+ * `GET`/`DELETE` reconnect - any request can hit any instance.
183
+ */
184
+ function mcpTransport(silkweaveOptions, context, actions, options = {}) {
185
+ actions.forEach(validateActionDisposition);
186
+ const post = async (req, res) => {
187
+ if (Array.isArray(req.body)) {
188
+ res.status(400).json({
189
+ jsonrpc: "2.0",
190
+ error: {
191
+ code: -32600,
192
+ message: "JSON-RPC batch requests are not supported"
193
+ },
194
+ id: null
195
+ });
196
+ return;
197
+ }
198
+ let active = actions;
199
+ if (options.filterActions) try {
200
+ active = await options.filterActions(actions, {
201
+ headers: req.headers,
202
+ url: req.originalUrl ?? req.url,
203
+ ...rpcInfo(req.body)
204
+ });
205
+ } catch (error) {
206
+ const { status, body } = filterErrorResponse(error, req.body);
207
+ res.status(status).json(body);
208
+ return;
209
+ }
210
+ try {
211
+ const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
212
+ const auth = authFromRequest(req);
213
+ const reqContext = auth ? context.fork({ auth }) : context;
214
+ const server = createMcpServer(silkweaveOptions, active, reqContext, options.onToolCall);
215
+ res.on("close", () => {
216
+ transport.close();
217
+ server.close();
218
+ });
219
+ await server.connect(transport);
220
+ await transport.handleRequest(req, res, req.body);
221
+ } catch (error) {
222
+ console.error("Error handling MCP request:", error);
223
+ if (!res.headersSent) res.status(500).json({
224
+ jsonrpc: "2.0",
225
+ error: {
226
+ code: -32603,
227
+ message: "Internal server error"
228
+ },
229
+ id: null
230
+ });
231
+ }
232
+ };
233
+ return { post };
234
+ }
235
+ //#endregion
236
+ //#region src/adapter/http.ts
237
+ /**
238
+ * Build a fully-wired Express app that exposes the MCP Streamable HTTP
239
+ * transport (plus OAuth / sideload / well-known routes when configured).
240
+ *
241
+ * Pass the resulting `app` to `app.listen(port, host)` yourself, or use the
242
+ * top-level `startMcpServer()` / `http()` adapter conveniences.
243
+ */
244
+ function buildMcpExpressApp(silkweaveOptions, context, actions, options) {
245
+ const { host, auth, cors: corsConfig, sideloadResources = true, resourceDir, filterActions, onToolCall, ...mcpAppOptions } = options;
246
+ const app = createMcpExpressApp({
247
+ ...mcpAppOptions,
248
+ host
249
+ });
250
+ const corsHandler = mcpCors(corsConfig ?? true);
251
+ if (corsHandler) app.use(corsHandler);
252
+ if (auth?.authorizationServers?.length && auth.resourceUrl) app.get("/.well-known/oauth-protected-resource", protectedResourceMetadata(auth));
253
+ let oauthPaths = /* @__PURE__ */ new Set();
254
+ if (auth?.provider) {
255
+ const oauth = oauthRoutes(auth);
256
+ app.get("/.well-known/oauth-authorization-server", oauth.wellKnownAuthServer);
257
+ app.get("/authorize", oauth.authorize);
258
+ app.get(oauth.callbackPath, oauth.callback);
259
+ app.post("/token", ...oauth.token);
260
+ app.post("/register", ...oauth.register);
261
+ oauthPaths = new Set([
262
+ "/.well-known/oauth-authorization-server",
263
+ "/authorize",
264
+ oauth.callbackPath,
265
+ "/token",
266
+ "/register"
267
+ ]);
268
+ }
269
+ if (auth) {
270
+ const guard = authMiddleware(auth, context);
271
+ app.use((req, res, next) => {
272
+ if (req.path.startsWith("/.well-known/") || oauthPaths.has(req.path)) return next();
273
+ return guard(req, res, next);
274
+ });
275
+ }
276
+ if (sideloadResources) app.get("/resource/:id", sideloadResource({ resourceDir }));
277
+ const transport = mcpTransport(silkweaveOptions, context, actions, {
278
+ filterActions,
279
+ onToolCall
280
+ });
281
+ app.post("/mcp", express.json(), transport.post);
282
+ return app;
283
+ }
284
+ /**
285
+ * Spin up a standalone MCP Streamable HTTP server on `host:port` for the
286
+ * given `actions`. Returns the underlying `Server` so callers can close it.
287
+ *
288
+ * Convenience for use cases that don't go through the `silkweave()` builder.
289
+ */
290
+ async function startMcpServer(silkweaveOptions, actions, options, context) {
291
+ const app = buildMcpExpressApp(silkweaveOptions, context ?? createContext({ adapter: "http" }), actions, options);
292
+ return new Promise((resolve, reject) => {
293
+ const server = app.listen(options.port, options.host, (error) => {
294
+ if (error) {
295
+ reject(error);
296
+ return;
297
+ }
298
+ console.log(`MCP Streamable HTTP Server listening on http://${options.host}:${options.port}/mcp`);
299
+ resolve(server);
300
+ });
301
+ });
302
+ }
303
+ /**
304
+ * Silkweave adapter that owns its own HTTP server. Composes the MCP handler
305
+ * primitives into a fully-wired Express app and listens on `host:port`.
306
+ */
307
+ const http = (options) => {
308
+ return (silkweaveOptions, baseContext) => {
309
+ const context = baseContext.fork({ adapter: "http" });
310
+ let httpServer;
311
+ return {
312
+ context,
313
+ start: async (actions) => {
314
+ const app = buildMcpExpressApp(silkweaveOptions, context, actions, options);
315
+ httpServer = await new Promise((resolve, reject) => {
316
+ const s = app.listen(options.port, options.host, (error) => {
317
+ if (error) {
318
+ reject(error);
319
+ return;
320
+ }
321
+ console.log(`MCP Streamable HTTP Server listening on http://${options.host}:${options.port}/mcp`);
322
+ resolve(s);
323
+ });
324
+ });
325
+ },
326
+ stop: async () => {
327
+ if (!httpServer) return;
328
+ await new Promise((resolve, reject) => {
329
+ httpServer.close((err) => err ? reject(err) : resolve());
330
+ });
331
+ httpServer = void 0;
332
+ }
333
+ };
334
+ };
335
+ };
336
+ //#endregion
337
+ export { AUTH_REQUEST_KEY, MCP_REQUIRED_HEADERS, authFromRequest, authMiddleware, buildMcpExpressApp, filterErrorResponse, http, mcpCors, mcpTransport, oauthRoutes, protectedResourceMetadata, rpcInfo, sideloadResource, startMcpServer };
338
+
339
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.mjs","names":[],"sources":["../src/handlers/auth.ts","../src/handlers/cors.ts","../src/handlers/metadata.ts","../src/handlers/oauth.ts","../src/handlers/sideload.ts","../src/handlers/transport.ts","../src/adapter/http.ts"],"sourcesContent":["import { AuthConfig, AuthInfo, validateToken } from '@silkweave/auth'\nimport { SilkweaveContext } from '@silkweave/core'\nimport { type Request, type RequestHandler } from 'express'\n\n/**\n * Key under which `authMiddleware` stashes the resolved `AuthInfo` on the\n * Express request. `mcpTransport` reads it back and forks it into the per-request\n * silkweave context (whose `fork` the tool-call context inherits), so auth\n * reaches tool handlers without `AsyncLocalStorage` - keeping this handler set\n * free of `node:async_hooks` for edge/serverless portability.\n */\nexport const AUTH_REQUEST_KEY = '__silkweaveAuth'\n\n/** Read the `AuthInfo` a prior `authMiddleware` attached to the request, if any. */\nexport function authFromRequest(req: Request): AuthInfo | undefined {\n return (req as Request & { [AUTH_REQUEST_KEY]?: AuthInfo })[AUTH_REQUEST_KEY]\n}\n\n/**\n * Express middleware that validates the `Authorization: Bearer …` header via\n * the supplied `AuthConfig`. On success the resolved `AuthInfo` is attached to\n * the request (see `authFromRequest` / `AUTH_REQUEST_KEY`); `mcpTransport` forks\n * it into the silkweave context for the tool call.\n *\n * The middleware should NOT be applied to OAuth-discovery / token routes -\n * compose it only on the routes that require an authenticated caller (the MCP\n * transport itself, sideload, etc.).\n */\nexport function authMiddleware(auth: AuthConfig, context: SilkweaveContext): RequestHandler {\n return async (req, res, next) => {\n const result = await validateToken(req.headers.authorization, auth, context.fork({ request: req }))\n if (result.error) {\n for (const [key, value] of Object.entries(result.error.headers)) { res.header(key, value) }\n res.status(result.error.statusCode).json(result.error.body)\n return\n }\n if (result.auth) {\n (req as Request & { [AUTH_REQUEST_KEY]?: AuthInfo })[AUTH_REQUEST_KEY] = result.auth\n }\n next()\n }\n}\n","import cors, { CorsOptions } from 'cors'\nimport { type RequestHandler } from 'express'\n\n/** Headers required by the MCP protocol that must always be exposed when CORS is in use. */\nexport const MCP_REQUIRED_HEADERS = ['WWW-Authenticate', 'Last-Event-Id', 'Mcp-Protocol-Version']\n\n/**\n * CORS middleware preconfigured to expose the headers MCP clients need\n * (`Last-Event-Id`, `Mcp-Protocol-Version`, `WWW-Authenticate`) on top of any\n * user-supplied options. (Stateless transport - no `Mcp-Session-Id`.)\n *\n * Pass `false` to disable, omit / pass `true` for permissive defaults, or pass\n * a `CorsOptions` object to override.\n */\nexport function mcpCors(corsConfig: CorsOptions | boolean = true): RequestHandler | null {\n if (corsConfig === false) { return null }\n const userConfig = corsConfig === true ? {} : corsConfig\n const userExposed = userConfig.exposedHeaders\n const exposedHeaders = [\n ...MCP_REQUIRED_HEADERS,\n ...(Array.isArray(userExposed) ? userExposed : userExposed ? [userExposed] : [])\n ]\n return cors({ origin: '*', ...userConfig, exposedHeaders })\n}\n","import { AuthConfig, generateProtectedResourceMetadata } from '@silkweave/auth'\nimport { type RequestHandler } from 'express'\n\n/**\n * Handler for `GET /.well-known/oauth-protected-resource` (RFC 9728). Returns\n * the resource server's metadata pointing at the configured authorization\n * servers. Requires `auth.resourceUrl` and a non-empty `auth.authorizationServers`.\n */\nexport function protectedResourceMetadata(auth: AuthConfig): RequestHandler {\n if (!auth.resourceUrl || !auth.authorizationServers?.length) {\n throw new Error('@silkweave/mcp protectedResourceMetadata(): auth.resourceUrl and auth.authorizationServers are required')\n }\n const metadata = generateProtectedResourceMetadata(auth.resourceUrl, auth.authorizationServers, auth.requiredScopes)\n return (_req, res) => { res.json(metadata) }\n}\n","import { AuthConfig, OAuthRequest, OAuthResponse } from '@silkweave/auth'\nimport express, { type Request, type RequestHandler, type Response } from 'express'\n\nfunction toOAuthReq(req: Request): OAuthRequest {\n return {\n method: req.method,\n url: new URL(req.url, `${req.protocol}://${req.get('host')}`),\n headers: Object.fromEntries(Object.entries(req.headers).map(([k, v]) => [k, Array.isArray(v) ? v[0] : v])),\n body: req.body as Record<string, string> | undefined\n }\n}\n\nfunction sendOAuth(res: Response, oauthRes: OAuthResponse) {\n for (const [key, value] of Object.entries(oauthRes.headers)) { res.header(key, value) }\n if (oauthRes.body) {\n res.status(oauthRes.status).send(typeof oauthRes.body === 'string' ? oauthRes.body : JSON.stringify(oauthRes.body))\n } else {\n res.status(oauthRes.status).end()\n }\n}\n\nexport interface OAuthRouteHandlers {\n /** `GET /.well-known/oauth-authorization-server` - RFC 8414 discovery. */\n wellKnownAuthServer: RequestHandler\n /** `GET /authorize` - start the OAuth flow. */\n authorize: RequestHandler\n /** `GET {callbackPath}` - provider callback. */\n callback: RequestHandler\n /** Path the provider should redirect to (defaults to `/auth/callback`). */\n callbackPath: string\n /** `POST /token` - exchange code / refresh token. Includes urlencoded body parser. */\n token: RequestHandler[]\n /** `POST /register` - dynamic client registration. Includes JSON body parser. */\n register: RequestHandler[]\n}\n\n/**\n * Build the OAuth 2.1 proxy route handlers (authorize, callback, token,\n * register, well-known) backed by the configured `auth.provider`. Returns the\n * handlers as individual `RequestHandler`s so callers can register them\n * wherever they like - under `/mcp`, at the server root, etc.\n *\n * `token` and `register` are returned as middleware arrays because the\n * appropriate body parser must run before the handler. Apply with\n * `app.post(path, ...token)`.\n */\nexport function oauthRoutes(auth: AuthConfig): OAuthRouteHandlers {\n if (!auth.provider) { throw new Error('@silkweave/mcp oauthRoutes(): auth.provider is required') }\n const provider = auth.provider\n const callbackPath = auth.callbackPath ?? '/auth/callback'\n\n return {\n callbackPath,\n wellKnownAuthServer: (_req, res) => { sendOAuth(res, provider.metadata()) },\n authorize: async (req, res) => { sendOAuth(res, await provider.authorize(toOAuthReq(req))) },\n callback: async (req, res) => { sendOAuth(res, await provider.callback(toOAuthReq(req))) },\n token: [\n express.urlencoded({ extended: false }),\n async (req, res) => { sendOAuth(res, await provider.token(toOAuthReq(req))) }\n ],\n register: [\n express.json(),\n async (req, res) => { sendOAuth(res, await provider.register(toOAuthReq(req))) }\n ]\n }\n}\n","import { type RequestHandler } from 'express'\nimport { readFile } from 'fs/promises'\nimport { basename, resolve, sep } from 'path'\nimport { type SideloadResource } from '../util/sideload.js'\n\nexport interface SideloadResourceOptions {\n /** Directory to read sideload resources from. Defaults to `resources/` (cwd-relative). */\n resourceDir?: string\n}\n\n/**\n * Handler for `GET /resource/:id` - serves a large MCP response that was\n * sideloaded to disk as a `{id}` payload with a `{id}.json` metadata sidecar.\n *\n * The route param `id` is provided by the host framework (Express, Nest, etc.).\n */\nexport function sideloadResource(options: SideloadResourceOptions = {}): RequestHandler {\n const { resourceDir = 'resources' } = options\n const baseDir = resolve(resourceDir)\n return async (req, res) => {\n const id = req.params['id']\n if (!id || typeof id !== 'string') { throw new Error('Invalid ID') }\n // Contain the read to resourceDir. Express 5 decodes %2F in the route param,\n // so an untrusted `id` like `../../etc/passwd` would otherwise escape the\n // directory. basename() strips any path separators; the resolve+prefix check\n // is defense in depth against platform-specific separator handling.\n const safeId = basename(id)\n const target = resolve(baseDir, safeId)\n if (safeId !== id || (target !== baseDir && !target.startsWith(baseDir + sep))) {\n res.status(400).json({ error: 'invalid_resource_id' })\n return\n }\n const resourceMeta: SideloadResource = JSON.parse(await readFile(`${target}.json`, 'utf-8'))\n const buffer = await readFile(target)\n res.status(200)\n res.header('Content-Type', resourceMeta.contentType)\n res.send(buffer)\n }\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'\nimport { Action, OnToolCall, SilkweaveContext, SilkweaveOptions, validateActionDisposition } from '@silkweave/core'\nimport { type RequestHandler } from 'express'\nimport { authFromRequest } from './auth.js'\nimport { filterErrorResponse, rpcInfo, type FilterActions } from './filter.js'\nimport { registerTools } from './registerTools.js'\n\nfunction createMcpServer(options: SilkweaveOptions, actions: Action[], context: SilkweaveContext, onToolCall?: OnToolCall): McpServer {\n const server = new McpServer({\n name: options.name,\n description: options.description,\n version: options.version\n }, {\n capabilities: { tools: {}, logging: {} }\n })\n registerTools(server, actions, context, { onToolCall })\n return server\n}\n\nexport interface McpTransportHandlers {\n /** `POST /mcp` - handle a single stateless MCP request/response (SSE per call). */\n post: RequestHandler\n}\n\nexport interface McpTransportOptions {\n /**\n * Per-request tool filter, applied before `registerTools()` on every POST.\n * See `FilterActions` for the request stand-in and error semantics.\n */\n filterActions?: FilterActions\n /** Telemetry hook invoked once per tool call (fire-and-forget). */\n onToolCall?: OnToolCall\n}\n\n/**\n * Build the MCP Streamable HTTP transport route handler.\n *\n * Stateless (per the 2026 spec direction): each `POST /mcp` mints a fresh\n * transport + server with `sessionIdGenerator: undefined`, handles exactly that\n * request (streaming progress over SSE when the call carries a `progressToken`),\n * and tears down on response close. No `Mcp-Session-Id`, no session map, no\n * `GET`/`DELETE` reconnect - any request can hit any instance.\n */\nexport function mcpTransport(\n silkweaveOptions: SilkweaveOptions,\n context: SilkweaveContext,\n actions: Action[],\n options: McpTransportOptions = {}\n): McpTransportHandlers {\n // Fail at boot, not per request - the factory runs once when the app is built.\n actions.forEach(validateActionDisposition)\n\n const post: RequestHandler = async (req, res) => {\n // JSON-RPC batching was removed from the MCP spec (2025-06-18). A batch also\n // defeats per-request filterActions: rpcInfo reflects only the first message\n // but the SDK transport would execute every entry, so a later batch entry\n // could invoke a tool the filter gated on the first. Reject batches outright.\n if (Array.isArray(req.body)) {\n res.status(400).json({ jsonrpc: '2.0', error: { code: -32_600, message: 'JSON-RPC batch requests are not supported' }, id: null })\n return\n }\n let active = actions\n if (options.filterActions) {\n try {\n active = await options.filterActions(actions, { headers: req.headers, url: req.originalUrl ?? req.url, ...rpcInfo(req.body) })\n } catch (error) {\n // A throw never degrades to an empty tool list - it surfaces as its\n // statusCode (SilkweaveError) or a 500, so a bad key reads as an auth\n // failure rather than \"server has no tools\".\n const { status, body } = filterErrorResponse(error, req.body)\n res.status(status).json(body)\n return\n }\n }\n try {\n const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined })\n // Fork the caller's resolved auth (attached by authMiddleware) into the\n // per-request context; registerTools' tool-call fork inherits it.\n const auth = authFromRequest(req)\n const reqContext = auth ? context.fork({ auth }) : context\n const server = createMcpServer(silkweaveOptions, active, reqContext, options.onToolCall)\n res.on('close', () => { void transport.close(); void server.close() })\n await server.connect(transport)\n await transport.handleRequest(req, res, req.body)\n } catch (error) {\n console.error('Error handling MCP request:', error)\n if (!res.headersSent) {\n res.status(500).json({ jsonrpc: '2.0', error: { code: -32_603, message: 'Internal server error' }, id: null })\n }\n }\n }\n\n return { post }\n}\n","import { createMcpExpressApp, type CreateMcpExpressAppOptions } from '@modelcontextprotocol/sdk/server/express.js'\nimport { AuthConfig } from '@silkweave/auth'\nimport { Action, AdapterFactory, createContext, OnToolCall, SilkweaveContext, SilkweaveOptions } from '@silkweave/core'\nimport { CorsOptions } from 'cors'\nimport express, { type Express } from 'express'\nimport { Server } from 'http'\nimport { authMiddleware } from '../handlers/auth.js'\nimport { mcpCors } from '../handlers/cors.js'\nimport { protectedResourceMetadata } from '../handlers/metadata.js'\nimport { oauthRoutes } from '../handlers/oauth.js'\nimport { type FilterActions } from '../handlers/filter.js'\nimport { sideloadResource } from '../handlers/sideload.js'\nimport { mcpTransport } from '../handlers/transport.js'\n\nexport interface StartMcpHttpOptions extends CreateMcpExpressAppOptions {\n host: string\n port: number\n auth?: AuthConfig\n /** CORS configuration. `false` to disable, omitted/`true` for permissive defaults, or a `CorsOptions` object. */\n cors?: CorsOptions | boolean\n /** Mount the `/resource/:id` sideload route. Default `true`. */\n sideloadResources?: boolean\n /** Directory the sideload route reads from. Default `'resources'`. */\n resourceDir?: string\n /**\n * Per-request tool filter, applied before `registerTools()` on every\n * `POST /mcp` (the stateless transport recomputes the tool list per request,\n * so permission changes apply on the next `tools/list`). See `FilterActions`\n * for the request stand-in (`headers`/`url`/`method`/`toolName`) and error\n * semantics (a throw surfaces as its `SilkweaveError.statusCode` or 500 -\n * never an empty tool list).\n */\n filterActions?: FilterActions\n /** Telemetry hook invoked once per tool call (fire-and-forget). */\n onToolCall?: OnToolCall\n}\n\n/**\n * Build a fully-wired Express app that exposes the MCP Streamable HTTP\n * transport (plus OAuth / sideload / well-known routes when configured).\n *\n * Pass the resulting `app` to `app.listen(port, host)` yourself, or use the\n * top-level `startMcpServer()` / `http()` adapter conveniences.\n */\nexport function buildMcpExpressApp(\n silkweaveOptions: SilkweaveOptions,\n context: SilkweaveContext,\n actions: Action[],\n options: StartMcpHttpOptions\n): Express {\n const { host, auth, cors: corsConfig, sideloadResources = true, resourceDir, filterActions, onToolCall, ...mcpAppOptions } = options\n const app = createMcpExpressApp({ ...mcpAppOptions, host })\n\n const corsHandler = mcpCors(corsConfig ?? true)\n if (corsHandler) { app.use(corsHandler) }\n\n if (auth?.authorizationServers?.length && auth.resourceUrl) {\n app.get('/.well-known/oauth-protected-resource', protectedResourceMetadata(auth))\n }\n\n let oauthPaths = new Set<string>()\n if (auth?.provider) {\n const oauth = oauthRoutes(auth)\n app.get('/.well-known/oauth-authorization-server', oauth.wellKnownAuthServer)\n app.get('/authorize', oauth.authorize)\n app.get(oauth.callbackPath, oauth.callback)\n app.post('/token', ...oauth.token)\n app.post('/register', ...oauth.register)\n oauthPaths = new Set(['/.well-known/oauth-authorization-server', '/authorize', oauth.callbackPath, '/token', '/register'])\n }\n\n if (auth) {\n const guard = authMiddleware(auth, context)\n app.use((req, res, next) => {\n if (req.path.startsWith('/.well-known/') || oauthPaths.has(req.path)) { return next() }\n return guard(req, res, next)\n })\n }\n\n if (sideloadResources) {\n app.get('/resource/:id', sideloadResource({ resourceDir }))\n }\n\n const transport = mcpTransport(silkweaveOptions, context, actions, { filterActions, onToolCall })\n app.post('/mcp', express.json(), transport.post)\n\n return app\n}\n\n/**\n * Spin up a standalone MCP Streamable HTTP server on `host:port` for the\n * given `actions`. Returns the underlying `Server` so callers can close it.\n *\n * Convenience for use cases that don't go through the `silkweave()` builder.\n */\nexport async function startMcpServer(\n silkweaveOptions: SilkweaveOptions,\n actions: Action[],\n options: StartMcpHttpOptions,\n context?: SilkweaveContext\n): Promise<Server> {\n const ctx = context ?? createContext({ adapter: 'http' })\n const app = buildMcpExpressApp(silkweaveOptions, ctx, actions, options)\n return new Promise<Server>((resolve, reject) => {\n const server = app.listen(options.port, options.host, (error) => {\n if (error) { reject(error); return }\n console.log(`MCP Streamable HTTP Server listening on http://${options.host}:${options.port}/mcp`)\n resolve(server)\n })\n })\n}\n\n/**\n * Silkweave adapter that owns its own HTTP server. Composes the MCP handler\n * primitives into a fully-wired Express app and listens on `host:port`.\n */\nexport const http: AdapterFactory<StartMcpHttpOptions> = (options) => {\n return (silkweaveOptions, baseContext) => {\n const context = baseContext.fork({ adapter: 'http' })\n let httpServer: Server | undefined\n return {\n context,\n start: async (actions) => {\n const app = buildMcpExpressApp(silkweaveOptions, context, actions, options)\n httpServer = await new Promise<Server>((resolve, reject) => {\n const s = app.listen(options.port, options.host, (error) => {\n if (error) { reject(error); return }\n console.log(`MCP Streamable HTTP Server listening on http://${options.host}:${options.port}/mcp`)\n resolve(s)\n })\n })\n },\n stop: async () => {\n if (!httpServer) { return }\n await new Promise<void>((resolve, reject) => {\n httpServer!.close((err) => err ? reject(err) : resolve())\n })\n httpServer = undefined\n }\n }\n }\n}\n"],"mappings":"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"}
package/build/tools.d.mts CHANGED
@@ -1,2 +1,3 @@
1
- import { a as smartToolResult, c as registerTools, d as FilterRequest, f as filterErrorResponse, i as parseResourceMessage, l as requestFromExtra, n as handleToolError, o as structuredToolResult, p as rpcInfo, r as jsonToolResult, s as RegisterToolsOptions, t as errorToolResult, u as FilterActions } from "./result-I04HIJR5.mjs";
1
+ import { i as rpcInfo, n as FilterRequest, r as filterErrorResponse, t as FilterActions } from "./filter-BuYC4eO9.mjs";
2
+ import { a as smartToolResult, c as registerTools, i as parseResourceMessage, l as requestFromExtra, n as handleToolError, o as structuredToolResult, r as jsonToolResult, s as RegisterToolsOptions, t as errorToolResult } from "./result-CQT2v6P1.mjs";
2
3
  export { FilterActions, FilterRequest, RegisterToolsOptions, errorToolResult, filterErrorResponse, handleToolError, jsonToolResult, parseResourceMessage, registerTools, requestFromExtra, rpcInfo, smartToolResult, structuredToolResult };
package/build/tools.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { i as rpcInfo, n as requestFromExtra, r as filterErrorResponse, t as registerTools } from "./registerTools-B_vjxOrs.mjs";
2
- import { a as smartToolResult, i as parseResourceMessage, n as handleToolError, o as structuredToolResult, r as jsonToolResult, t as errorToolResult } from "./result-CXgeE8ca.mjs";
1
+ import { a as smartToolResult, i as parseResourceMessage, n as handleToolError, o as structuredToolResult, r as jsonToolResult, t as errorToolResult } from "./result-uIqPNNxF.mjs";
2
+ import { i as requestFromExtra, n as rpcInfo, r as registerTools, t as filterErrorResponse } from "./filter-Baxr12pu.mjs";
3
3
  export { errorToolResult, filterErrorResponse, handleToolError, jsonToolResult, parseResourceMessage, registerTools, requestFromExtra, rpcInfo, smartToolResult, structuredToolResult };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silkweave/mcp",
3
- "version": "3.2.1",
3
+ "version": "4.0.1",
4
4
  "description": "Silkweave MCP Package",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.silkweave.dev",
@@ -24,6 +24,11 @@
24
24
  "types": "./build/index.d.mts",
25
25
  "default": "./build/index.mjs"
26
26
  },
27
+ "./server": {
28
+ "@silkweave/source": "./src/server.ts",
29
+ "types": "./build/server.d.mts",
30
+ "default": "./build/server.mjs"
31
+ },
27
32
  "./tools": {
28
33
  "@silkweave/source": "./src/tools.ts",
29
34
  "types": "./build/tools.d.mts",
@@ -39,8 +44,8 @@
39
44
  "@modelcontextprotocol/sdk": "^1.29.0",
40
45
  "change-case": "^5.4.4",
41
46
  "zod": "^3.25.0",
42
- "@silkweave/auth": "3.2.1",
43
- "@silkweave/core": "3.2.1"
47
+ "@silkweave/auth": "4.0.1",
48
+ "@silkweave/core": "4.0.1"
44
49
  },
45
50
  "peerDependencies": {
46
51
  "commander": "^13.1.0",