skybridge 0.0.0-dev.df0cfdd → 0.0.0-dev.df1e961
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 +7 -7
- package/dist/cli/build-helpers.d.ts +1 -1
- package/dist/cli/build-helpers.js +4 -4
- package/dist/cli/build-helpers.js.map +1 -1
- package/dist/cli/build-helpers.test.js +2 -2
- package/dist/cli/build-helpers.test.js.map +1 -1
- package/dist/cli/build-steps.js +1 -1
- package/dist/cli/build-steps.js.map +1 -1
- package/dist/cli/detect-port.js +0 -1
- package/dist/cli/detect-port.js.map +1 -1
- package/dist/cli/use-execute-steps.d.ts +1 -1
- package/dist/cli/use-nodemon.js +11 -3
- package/dist/cli/use-nodemon.js.map +1 -1
- package/dist/cli/use-typescript-check.js +1 -1
- package/dist/cli/use-typescript-check.js.map +1 -1
- package/dist/commands/dev.js +1 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/start.js +2 -2
- package/dist/commands/start.js.map +1 -1
- package/dist/server/app.d.ts +194 -0
- package/dist/server/app.js +266 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/app.test.js +97 -0
- package/dist/server/app.test.js.map +1 -0
- package/dist/server/auth/discovery.d.ts +2 -1
- package/dist/server/auth/discovery.js +2 -2
- package/dist/server/auth/discovery.js.map +1 -1
- package/dist/server/auth/index.d.ts +21 -17
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/auth/providers/auth0.d.ts +2 -2
- package/dist/server/auth/providers/auth0.js +13 -8
- package/dist/server/auth/providers/auth0.js.map +1 -1
- package/dist/server/auth/providers/auth0.test.js +1 -1
- package/dist/server/auth/providers/auth0.test.js.map +1 -1
- package/dist/server/auth/providers/authplane.d.ts +2 -2
- package/dist/server/auth/providers/authplane.js.map +1 -1
- package/dist/server/auth/providers/authplane.test.js +10 -7
- package/dist/server/auth/providers/authplane.test.js.map +1 -1
- package/dist/server/auth/providers/clerk.d.ts +2 -2
- package/dist/server/auth/providers/clerk.js.map +1 -1
- package/dist/server/auth/providers/clerk.test.js +1 -1
- package/dist/server/auth/providers/clerk.test.js.map +1 -1
- package/dist/server/auth/providers/custom.d.ts +4 -4
- package/dist/server/auth/providers/custom.js +5 -2
- package/dist/server/auth/providers/custom.js.map +1 -1
- package/dist/server/auth/providers/custom.test.js +13 -10
- package/dist/server/auth/providers/custom.test.js.map +1 -1
- package/dist/server/auth/providers/descope.d.ts +2 -2
- package/dist/server/auth/providers/descope.js.map +1 -1
- package/dist/server/auth/providers/descope.test.js +3 -3
- package/dist/server/auth/providers/descope.test.js.map +1 -1
- package/dist/server/auth/providers/stytch.d.ts +2 -2
- package/dist/server/auth/providers/stytch.js.map +1 -1
- package/dist/server/auth/providers/workos.d.ts +2 -2
- package/dist/server/auth/providers/workos.js.map +1 -1
- package/dist/server/auth/setup.d.ts +1 -1
- package/dist/server/auth/setup.js +3 -4
- package/dist/server/auth/setup.js.map +1 -1
- package/dist/server/auth/setup.test.js +83 -77
- package/dist/server/auth/setup.test.js.map +1 -1
- package/dist/server/auth/verify.js +2 -2
- package/dist/server/auth/verify.js.map +1 -1
- package/dist/server/auth-extra.test-d.js +97 -49
- package/dist/server/auth-extra.test-d.js.map +1 -1
- package/dist/server/auth.d.ts +7 -8
- package/dist/server/auth.js +4 -5
- package/dist/server/auth.js.map +1 -1
- package/dist/server/build-manifest.test.js +7 -6
- package/dist/server/build-manifest.test.js.map +1 -1
- package/dist/server/content-helpers.d.ts +1 -1
- package/dist/server/content-helpers.js.map +1 -1
- package/dist/server/express.d.ts +23 -3
- package/dist/server/express.js +38 -32
- package/dist/server/express.js.map +1 -1
- package/dist/server/express.test.js +220 -103
- package/dist/server/express.test.js.map +1 -1
- package/dist/server/file-ref.d.ts +1 -1
- package/dist/server/file-ref.js +1 -1
- package/dist/server/file-ref.js.map +1 -1
- package/dist/server/index.d.ts +6 -3
- package/dist/server/index.js +3 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp-errors.test.js +41 -0
- package/dist/server/mcp-errors.test.js.map +1 -0
- package/dist/server/middleware.d.ts +6 -6
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/middleware.test-d.js +1 -1
- package/dist/server/middleware.test-d.js.map +1 -1
- package/dist/server/middleware.test.js +222 -150
- package/dist/server/middleware.test.js.map +1 -1
- package/dist/server/register-tool.test.d.ts +1 -0
- package/dist/server/register-tool.test.js +27 -0
- package/dist/server/register-tool.test.js.map +1 -0
- package/dist/server/server.d.ts +74 -122
- package/dist/server/server.js +101 -302
- package/dist/server/server.js.map +1 -1
- package/dist/server/skills-integration.test.js +19 -12
- package/dist/server/skills-integration.test.js.map +1 -1
- package/dist/server/skills.d.ts +3 -5
- package/dist/server/skills.js +17 -24
- package/dist/server/skills.js.map +1 -1
- package/dist/server/skills.test.js +8 -12
- package/dist/server/skills.test.js.map +1 -1
- package/dist/server/templateHelper.d.ts +0 -3
- package/dist/server/templateHelper.js.map +1 -1
- package/dist/server/templates.generated.js +4 -8
- package/dist/server/templates.generated.js.map +1 -1
- package/dist/server/tool-extra.test.d.ts +1 -0
- package/dist/server/tool-extra.test.js +88 -0
- package/dist/server/tool-extra.test.js.map +1 -0
- package/dist/server/view-resource-resolution.test.js +18 -13
- package/dist/server/view-resource-resolution.test.js.map +1 -1
- package/dist/test/utils.d.ts +9 -11
- package/dist/test/utils.js +220 -201
- package/dist/test/utils.js.map +1 -1
- package/dist/test/view.test.js +25 -37
- package/dist/test/view.test.js.map +1 -1
- package/dist/views/index.d.ts +10 -0
- package/dist/views/index.js +3 -0
- package/dist/views/index.js.map +1 -0
- package/dist/views/scan-views.d.ts +16 -0
- package/dist/views/scan-views.js +88 -0
- package/dist/views/scan-views.js.map +1 -0
- package/dist/views/scan-views.test.d.ts +1 -0
- package/dist/views/scan-views.test.js +99 -0
- package/dist/views/scan-views.test.js.map +1 -0
- package/dist/views/validate-view.d.ts +1 -0
- package/dist/views/validate-view.js +9 -0
- package/dist/views/validate-view.js.map +1 -0
- package/dist/views/validate-view.test.d.ts +1 -0
- package/dist/views/validate-view.test.js +24 -0
- package/dist/views/validate-view.test.js.map +1 -0
- package/dist/web/bridges/adaptor.test.js +1 -1
- package/dist/web/bridges/adaptor.test.js.map +1 -1
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +1 -1
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +1 -1
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
- package/dist/web/bridges/get-adaptor.test.js +2 -2
- package/dist/web/bridges/get-adaptor.test.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.js +1 -1
- package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.test.js +2 -2
- package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
- package/dist/web/bridges/mcp-app/view-tools.test.js +1 -1
- package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -1
- package/dist/web/bridges/types.d.ts +17 -12
- package/dist/web/bridges/types.js.map +1 -1
- package/dist/web/create-store.test.js +2 -2
- package/dist/web/create-store.test.js.map +1 -1
- package/dist/web/data-llm.test.js +2 -2
- package/dist/web/data-llm.test.js.map +1 -1
- package/dist/web/generate-helpers.d.ts +22 -18
- package/dist/web/generate-helpers.js +19 -15
- package/dist/web/generate-helpers.js.map +1 -1
- package/dist/web/generate-helpers.test-d.js +3 -3
- package/dist/web/generate-helpers.test-d.js.map +1 -1
- package/dist/web/generate-helpers.test.js +2 -2
- package/dist/web/generate-helpers.test.js.map +1 -1
- package/dist/web/hooks/index.d.ts +2 -2
- package/dist/web/hooks/index.js +2 -2
- package/dist/web/hooks/index.js.map +1 -1
- package/dist/web/hooks/use-call-tool.test.js +2 -2
- package/dist/web/hooks/use-call-tool.test.js.map +1 -1
- package/dist/web/hooks/use-display-mode.d.ts +1 -1
- package/dist/web/hooks/use-display-mode.js +1 -1
- package/dist/web/hooks/use-display-mode.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test.js +1 -1
- package/dist/web/hooks/use-display-mode.test.js.map +1 -1
- package/dist/web/hooks/use-download.d.ts +1 -3
- package/dist/web/hooks/use-download.js +1 -2
- package/dist/web/hooks/use-download.js.map +1 -1
- package/dist/web/hooks/use-download.test.js +7 -7
- package/dist/web/hooks/use-download.test.js.map +1 -1
- package/dist/web/hooks/use-files.test.js +1 -1
- package/dist/web/hooks/use-files.test.js.map +1 -1
- package/dist/web/hooks/{use-host-info.d.ts → use-host.d.ts} +2 -2
- package/dist/web/hooks/{use-host-info.js → use-host.js} +3 -3
- package/dist/web/hooks/use-host.js.map +1 -0
- package/dist/web/hooks/use-host.test.d.ts +1 -0
- package/dist/web/hooks/{use-host-info.test.js → use-host.test.js} +7 -7
- package/dist/web/hooks/use-host.test.js.map +1 -0
- package/dist/web/hooks/use-open-external.test.js +2 -2
- package/dist/web/hooks/use-open-external.test.js.map +1 -1
- package/dist/web/hooks/use-register-view-tool.d.ts +2 -3
- package/dist/web/hooks/use-register-view-tool.js.map +1 -1
- package/dist/web/hooks/use-request-close.test.js +1 -1
- package/dist/web/hooks/use-request-close.test.js.map +1 -1
- package/dist/web/hooks/use-request-modal.test.js +1 -1
- package/dist/web/hooks/use-request-modal.test.js.map +1 -1
- package/dist/web/hooks/use-request-size.d.ts +1 -1
- package/dist/web/hooks/use-request-size.js +1 -1
- package/dist/web/hooks/use-request-size.js.map +1 -1
- package/dist/web/hooks/use-request-size.test.js +1 -1
- package/dist/web/hooks/use-request-size.test.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.test.js +2 -8
- package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
- package/dist/web/hooks/use-tool-info.d.ts +1 -20
- package/dist/web/hooks/use-tool-info.js +0 -1
- package/dist/web/hooks/use-tool-info.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test-d.js +0 -5
- package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test.js +2 -7
- package/dist/web/hooks/use-tool-info.test.js.map +1 -1
- package/dist/web/hooks/use-user.d.ts +3 -2
- package/dist/web/hooks/use-user.js +4 -3
- package/dist/web/hooks/use-user.js.map +1 -1
- package/dist/web/hooks/use-user.test.js +5 -3
- package/dist/web/hooks/use-user.test.js.map +1 -1
- package/dist/web/hooks/use-view-state.test.js +2 -2
- package/dist/web/hooks/use-view-state.test.js.map +1 -1
- package/dist/web/hooks/use-viewport.d.ts +20 -0
- package/dist/web/hooks/use-viewport.js +21 -0
- package/dist/web/hooks/use-viewport.js.map +1 -0
- package/dist/web/hooks/use-viewport.test.d.ts +1 -0
- package/dist/web/hooks/{use-layout.test.js → use-viewport.test.js} +12 -32
- package/dist/web/hooks/use-viewport.test.js.map +1 -0
- package/dist/web/mount-view.d.ts +3 -2
- package/dist/web/mount-view.js +5 -8
- package/dist/web/mount-view.js.map +1 -1
- package/package.json +15 -8
- package/dist/web/hooks/use-host-info.js.map +0 -1
- package/dist/web/hooks/use-host-info.test.js.map +0 -1
- package/dist/web/hooks/use-layout.d.ts +0 -24
- package/dist/web/hooks/use-layout.js +0 -25
- package/dist/web/hooks/use-layout.js.map +0 -1
- package/dist/web/hooks/use-layout.test.js.map +0 -1
- /package/dist/{web/hooks/use-host-info.test.d.ts → server/app.test.d.ts} +0 -0
- /package/dist/{web/hooks/use-layout.test.d.ts → server/mcp-errors.test.d.ts} +0 -0
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { Client } from "@modelcontextprotocol/
|
|
2
|
-
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
1
|
+
import { Client, InMemoryTransport } from "@modelcontextprotocol/client";
|
|
3
2
|
import { describe, expect, it, vi } from "vitest";
|
|
4
3
|
import { z } from "zod";
|
|
4
|
+
import { Skybridge } from "./app.js";
|
|
5
5
|
import { buildMiddlewareChain, getHandlerMaps, getToolError, matchesFilter, } from "./middleware.js";
|
|
6
|
-
import { McpServer } from "./server.js";
|
|
7
6
|
// ---------------------------------------------------------------------------
|
|
8
7
|
// matchesFilter
|
|
9
8
|
// ---------------------------------------------------------------------------
|
|
@@ -208,29 +207,42 @@ describe("McpServer.mcpMiddleware()", () => {
|
|
|
208
207
|
return new Client({ name: "test-client", version: "1.0.0" });
|
|
209
208
|
}
|
|
210
209
|
it("returns this for chaining", () => {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
new Skybridge({
|
|
211
|
+
name: "test",
|
|
212
|
+
version: "1.0.0",
|
|
213
|
+
handler: (server) => {
|
|
214
|
+
const result = server.mcpMiddleware(async (_req, _extra, next) => next());
|
|
215
|
+
expect(result).toBe(server);
|
|
216
|
+
return server;
|
|
217
|
+
},
|
|
218
|
+
});
|
|
214
219
|
});
|
|
215
220
|
it("intercepts tools/call and exposes request params", async () => {
|
|
216
221
|
let capturedMethod = "";
|
|
217
222
|
let capturedParams = {};
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
223
|
+
const app = new Skybridge({
|
|
224
|
+
name: "test",
|
|
225
|
+
version: "1.0.0",
|
|
226
|
+
handler: (server) => {
|
|
227
|
+
server.registerTool({
|
|
228
|
+
name: "greet",
|
|
229
|
+
description: "greet",
|
|
230
|
+
inputSchema: { name: z.string() },
|
|
231
|
+
}, (args) => ({
|
|
232
|
+
content: [{ type: "text", text: `hi ${args.name}` }],
|
|
233
|
+
}));
|
|
234
|
+
server.mcpMiddleware("tools/call", async (request, _extra, next) => {
|
|
235
|
+
capturedMethod = request.method;
|
|
236
|
+
capturedParams = request.params;
|
|
237
|
+
return next();
|
|
238
|
+
});
|
|
239
|
+
return server;
|
|
240
|
+
},
|
|
230
241
|
});
|
|
231
242
|
const client = createClient();
|
|
232
243
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
233
|
-
await
|
|
244
|
+
const instance = await app.createServerInstance();
|
|
245
|
+
await instance.connect(serverTransport);
|
|
234
246
|
await client.connect(clientTransport);
|
|
235
247
|
const result = await client.callTool({
|
|
236
248
|
name: "greet",
|
|
@@ -243,59 +255,70 @@ describe("McpServer.mcpMiddleware()", () => {
|
|
|
243
255
|
});
|
|
244
256
|
expect(result.content).toEqual([{ type: "text", text: "hi World" }]);
|
|
245
257
|
await client.close();
|
|
246
|
-
await
|
|
258
|
+
await instance.close();
|
|
247
259
|
});
|
|
248
260
|
it("array filter works", async () => {
|
|
249
261
|
const matchedMethods = [];
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
262
|
+
const app = new Skybridge({
|
|
263
|
+
name: "test",
|
|
264
|
+
version: "1.0.0",
|
|
265
|
+
handler: (server) => {
|
|
266
|
+
server.registerTool({ name: "t1", description: "t1" }, () => ({
|
|
267
|
+
content: [{ type: "text", text: "ok" }],
|
|
268
|
+
}));
|
|
269
|
+
server.mcpMiddleware(["tools/call", "tools/list"], async (request, _extra, next) => {
|
|
270
|
+
matchedMethods.push(request.method);
|
|
271
|
+
return next();
|
|
272
|
+
});
|
|
273
|
+
return server;
|
|
274
|
+
},
|
|
257
275
|
});
|
|
258
276
|
const client = createClient();
|
|
259
277
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
260
|
-
await
|
|
278
|
+
const instance = await app.createServerInstance();
|
|
279
|
+
await instance.connect(serverTransport);
|
|
261
280
|
await client.connect(clientTransport);
|
|
262
281
|
await client.listTools();
|
|
263
282
|
await client.callTool({ name: "t1" });
|
|
264
283
|
expect(matchedMethods).toEqual(["tools/list", "tools/call"]);
|
|
265
284
|
await client.close();
|
|
266
|
-
await
|
|
267
|
-
});
|
|
268
|
-
it("throws
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
expect(() =>
|
|
278
|
-
// @ts-expect-error intentionally passing filter without handler
|
|
279
|
-
server.mcpMiddleware("tools/call")).toThrow("mcpMiddleware requires a handler function");
|
|
285
|
+
await instance.close();
|
|
286
|
+
});
|
|
287
|
+
it("throws when filter provided without handler", async () => {
|
|
288
|
+
const app = new Skybridge({
|
|
289
|
+
name: "test",
|
|
290
|
+
version: "1.0.0",
|
|
291
|
+
handler: (server) =>
|
|
292
|
+
// @ts-expect-error intentionally passing filter without handler
|
|
293
|
+
server.mcpMiddleware("tools/call"),
|
|
294
|
+
});
|
|
295
|
+
await expect(app.createServerInstance()).rejects.toThrow("mcpMiddleware requires a handler function");
|
|
280
296
|
});
|
|
281
297
|
it("catch-all middleware + filtered middleware stack correctly", async () => {
|
|
282
298
|
const calls = [];
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
299
|
+
const app = new Skybridge({
|
|
300
|
+
name: "test",
|
|
301
|
+
version: "1.0.0",
|
|
302
|
+
handler: (server) => {
|
|
303
|
+
server.registerTool({ name: "t1", description: "t1" }, () => ({
|
|
304
|
+
content: [{ type: "text", text: "ok" }],
|
|
305
|
+
}));
|
|
306
|
+
server
|
|
307
|
+
.mcpMiddleware(async (request, _extra, next) => {
|
|
308
|
+
calls.push(`global:${request.method}`);
|
|
309
|
+
return next();
|
|
310
|
+
})
|
|
311
|
+
.mcpMiddleware("tools/call", async (_req, _extra, next) => {
|
|
312
|
+
calls.push("tools-only");
|
|
313
|
+
return next();
|
|
314
|
+
});
|
|
315
|
+
return server;
|
|
316
|
+
},
|
|
295
317
|
});
|
|
296
318
|
const client = createClient();
|
|
297
319
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
298
|
-
await
|
|
320
|
+
const instance = await app.createServerInstance();
|
|
321
|
+
await instance.connect(serverTransport);
|
|
299
322
|
await client.connect(clientTransport);
|
|
300
323
|
await client.listTools();
|
|
301
324
|
await client.callTool({ name: "t1" });
|
|
@@ -309,41 +332,55 @@ describe("McpServer.mcpMiddleware()", () => {
|
|
|
309
332
|
const toolsCallIdx = calls.indexOf("global:tools/call");
|
|
310
333
|
expect(calls[toolsCallIdx + 1]).toBe("tools-only");
|
|
311
334
|
await client.close();
|
|
312
|
-
await
|
|
335
|
+
await instance.close();
|
|
313
336
|
});
|
|
314
337
|
it("notification middleware receives extra as undefined", async () => {
|
|
315
338
|
let capturedExtra = "sentinel";
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
339
|
+
const app = new Skybridge({
|
|
340
|
+
name: "test",
|
|
341
|
+
version: "1.0.0",
|
|
342
|
+
handler: (server) => {
|
|
343
|
+
server.registerTool({ name: "t1", description: "t1" }, () => ({
|
|
344
|
+
content: [{ type: "text", text: "ok" }],
|
|
345
|
+
}));
|
|
346
|
+
server.mcpMiddleware("notification", async (_request, extra, next) => {
|
|
347
|
+
capturedExtra = extra;
|
|
348
|
+
return next();
|
|
349
|
+
});
|
|
350
|
+
return server;
|
|
351
|
+
},
|
|
323
352
|
});
|
|
324
353
|
const client = createClient();
|
|
325
354
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
326
|
-
await
|
|
355
|
+
const instance = await app.createServerInstance();
|
|
356
|
+
await instance.connect(serverTransport);
|
|
327
357
|
await client.connect(clientTransport);
|
|
328
358
|
// The client sends notifications/initialized automatically on connect.
|
|
329
359
|
await client.listTools();
|
|
330
360
|
expect(capturedExtra).toBeUndefined();
|
|
331
361
|
await client.close();
|
|
332
|
-
await
|
|
362
|
+
await instance.close();
|
|
333
363
|
});
|
|
334
364
|
it("wildcard filter intercepts matching methods only", async () => {
|
|
335
365
|
const matchedMethods = [];
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
366
|
+
const app = new Skybridge({
|
|
367
|
+
name: "test",
|
|
368
|
+
version: "1.0.0",
|
|
369
|
+
handler: (server) => {
|
|
370
|
+
server.registerTool({ name: "t1", description: "t1" }, () => ({
|
|
371
|
+
content: [{ type: "text", text: "ok" }],
|
|
372
|
+
}));
|
|
373
|
+
server.mcpMiddleware("tools/*", async (request, _extra, next) => {
|
|
374
|
+
matchedMethods.push(request.method);
|
|
375
|
+
return next();
|
|
376
|
+
});
|
|
377
|
+
return server;
|
|
378
|
+
},
|
|
343
379
|
});
|
|
344
380
|
const client = createClient();
|
|
345
381
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
346
|
-
await
|
|
382
|
+
const instance = await app.createServerInstance();
|
|
383
|
+
await instance.connect(serverTransport);
|
|
347
384
|
await client.connect(clientTransport);
|
|
348
385
|
await client.listTools();
|
|
349
386
|
await client.callTool({ name: "t1" });
|
|
@@ -353,30 +390,37 @@ describe("McpServer.mcpMiddleware()", () => {
|
|
|
353
390
|
expect(matchedMethods).not.toContain("initialize");
|
|
354
391
|
expect(matchedMethods).not.toContain("notifications/initialized");
|
|
355
392
|
await client.close();
|
|
356
|
-
await
|
|
357
|
-
});
|
|
358
|
-
it("middleware can modify tool result via
|
|
359
|
-
const
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
393
|
+
await instance.close();
|
|
394
|
+
});
|
|
395
|
+
it("middleware can modify tool result via Skybridge integration", async () => {
|
|
396
|
+
const app = new Skybridge({
|
|
397
|
+
name: "test",
|
|
398
|
+
version: "1.0.0",
|
|
399
|
+
handler: (server) => {
|
|
400
|
+
server.registerTool({
|
|
401
|
+
name: "greet",
|
|
402
|
+
description: "greet",
|
|
403
|
+
inputSchema: { name: z.string() },
|
|
404
|
+
}, (args) => ({
|
|
405
|
+
content: [{ type: "text", text: `hi ${args.name}` }],
|
|
406
|
+
}));
|
|
407
|
+
server.mcpMiddleware("tools/call", async (_req, _extra, next) => {
|
|
408
|
+
const result = (await next());
|
|
409
|
+
return {
|
|
410
|
+
...result,
|
|
411
|
+
content: [
|
|
412
|
+
...result.content,
|
|
413
|
+
{ type: "text", text: " (modified)" },
|
|
414
|
+
],
|
|
415
|
+
};
|
|
416
|
+
});
|
|
417
|
+
return server;
|
|
418
|
+
},
|
|
376
419
|
});
|
|
377
420
|
const client = createClient();
|
|
378
421
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
379
|
-
await
|
|
422
|
+
const instance = await app.createServerInstance();
|
|
423
|
+
await instance.connect(serverTransport);
|
|
380
424
|
await client.connect(clientTransport);
|
|
381
425
|
const result = await client.callTool({
|
|
382
426
|
name: "greet",
|
|
@@ -387,53 +431,67 @@ describe("McpServer.mcpMiddleware()", () => {
|
|
|
387
431
|
{ type: "text", text: " (modified)" },
|
|
388
432
|
]);
|
|
389
433
|
await client.close();
|
|
390
|
-
await
|
|
434
|
+
await instance.close();
|
|
391
435
|
});
|
|
392
|
-
it("middleware can short-circuit via
|
|
436
|
+
it("middleware can short-circuit via Skybridge integration", async () => {
|
|
393
437
|
const handlerCalled = vi.fn();
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
438
|
+
const app = new Skybridge({
|
|
439
|
+
name: "test",
|
|
440
|
+
version: "1.0.0",
|
|
441
|
+
handler: (server) => {
|
|
442
|
+
server.registerTool({ name: "t1", description: "t1" }, () => {
|
|
443
|
+
handlerCalled();
|
|
444
|
+
return {
|
|
445
|
+
content: [{ type: "text", text: "original" }],
|
|
446
|
+
};
|
|
447
|
+
});
|
|
448
|
+
server.mcpMiddleware("tools/call", async () => ({
|
|
449
|
+
content: [{ type: "text", text: "short-circuited" }],
|
|
450
|
+
}));
|
|
451
|
+
return server;
|
|
452
|
+
},
|
|
400
453
|
});
|
|
401
|
-
server.mcpMiddleware("tools/call", async () => ({
|
|
402
|
-
content: [{ type: "text", text: "short-circuited" }],
|
|
403
|
-
}));
|
|
404
454
|
const client = createClient();
|
|
405
455
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
406
|
-
await
|
|
456
|
+
const instance = await app.createServerInstance();
|
|
457
|
+
await instance.connect(serverTransport);
|
|
407
458
|
await client.connect(clientTransport);
|
|
408
459
|
const result = await client.callTool({ name: "t1" });
|
|
409
460
|
expect(result.content).toEqual([{ type: "text", text: "short-circuited" }]);
|
|
410
461
|
expect(handlerCalled).not.toHaveBeenCalled();
|
|
411
462
|
await client.close();
|
|
412
|
-
await
|
|
463
|
+
await instance.close();
|
|
413
464
|
});
|
|
414
465
|
it("exposes a thrown tool error to middleware via getToolError", async () => {
|
|
415
466
|
const schemaError = new Error("boom with schema");
|
|
416
467
|
const schemalessError = new Error("boom without schema");
|
|
417
468
|
let captured;
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
469
|
+
const app = new Skybridge({
|
|
470
|
+
name: "test",
|
|
471
|
+
version: "1.0.0",
|
|
472
|
+
handler: (server) => {
|
|
473
|
+
server.registerTool({
|
|
474
|
+
name: "withSchema",
|
|
475
|
+
description: "withSchema",
|
|
476
|
+
inputSchema: { name: z.string() },
|
|
477
|
+
}, () => {
|
|
478
|
+
throw schemaError;
|
|
479
|
+
});
|
|
480
|
+
server.registerTool({ name: "withoutSchema", description: "withoutSchema" }, () => {
|
|
481
|
+
throw schemalessError;
|
|
482
|
+
});
|
|
483
|
+
server.mcpMiddleware("tools/call", async (_request, extra, next) => {
|
|
484
|
+
const result = await next();
|
|
485
|
+
captured = getToolError(extra);
|
|
486
|
+
return result;
|
|
487
|
+
});
|
|
488
|
+
return server;
|
|
489
|
+
},
|
|
433
490
|
});
|
|
434
491
|
const client = createClient();
|
|
435
492
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
436
|
-
await
|
|
493
|
+
const instance = await app.createServerInstance();
|
|
494
|
+
await instance.connect(serverTransport);
|
|
437
495
|
await client.connect(clientTransport);
|
|
438
496
|
const withSchema = await client.callTool({
|
|
439
497
|
name: "withSchema",
|
|
@@ -445,28 +503,35 @@ describe("McpServer.mcpMiddleware()", () => {
|
|
|
445
503
|
expect(withoutSchema.isError).toBe(true);
|
|
446
504
|
expect(captured).toBe(schemalessError);
|
|
447
505
|
await client.close();
|
|
448
|
-
await
|
|
506
|
+
await instance.close();
|
|
449
507
|
});
|
|
450
|
-
it("middleware can mutate tool call params via
|
|
508
|
+
it("middleware can mutate tool call params via Skybridge integration", async () => {
|
|
451
509
|
let receivedName = "";
|
|
452
|
-
const
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
510
|
+
const app = new Skybridge({
|
|
511
|
+
name: "test",
|
|
512
|
+
version: "1.0.0",
|
|
513
|
+
handler: (server) => {
|
|
514
|
+
server.registerTool({
|
|
515
|
+
name: "greet",
|
|
516
|
+
description: "greet",
|
|
517
|
+
inputSchema: { name: z.string() },
|
|
518
|
+
}, (args) => {
|
|
519
|
+
receivedName = args.name;
|
|
520
|
+
return {
|
|
521
|
+
content: [{ type: "text", text: `hi ${args.name}` }],
|
|
522
|
+
};
|
|
523
|
+
});
|
|
524
|
+
server.mcpMiddleware("tools/call", async (request, _extra, next) => {
|
|
525
|
+
request.params.arguments = { name: "Overridden" };
|
|
526
|
+
return next();
|
|
527
|
+
});
|
|
528
|
+
return server;
|
|
529
|
+
},
|
|
466
530
|
});
|
|
467
531
|
const client = createClient();
|
|
468
532
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
469
|
-
await
|
|
533
|
+
const instance = await app.createServerInstance();
|
|
534
|
+
await instance.connect(serverTransport);
|
|
470
535
|
await client.connect(clientTransport);
|
|
471
536
|
await client.callTool({
|
|
472
537
|
name: "greet",
|
|
@@ -474,21 +539,28 @@ describe("McpServer.mcpMiddleware()", () => {
|
|
|
474
539
|
});
|
|
475
540
|
expect(receivedName).toBe("Overridden");
|
|
476
541
|
await client.close();
|
|
477
|
-
await
|
|
542
|
+
await instance.close();
|
|
478
543
|
});
|
|
479
544
|
it("category 'request' filter matches requests but not notifications", async () => {
|
|
480
545
|
const matchedMethods = [];
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
546
|
+
const app = new Skybridge({
|
|
547
|
+
name: "test",
|
|
548
|
+
version: "1.0.0",
|
|
549
|
+
handler: (server) => {
|
|
550
|
+
server.registerTool({ name: "t1", description: "t1" }, () => ({
|
|
551
|
+
content: [{ type: "text", text: "ok" }],
|
|
552
|
+
}));
|
|
553
|
+
server.mcpMiddleware("request", async (request, _extra, next) => {
|
|
554
|
+
matchedMethods.push(request.method);
|
|
555
|
+
return next();
|
|
556
|
+
});
|
|
557
|
+
return server;
|
|
558
|
+
},
|
|
488
559
|
});
|
|
489
560
|
const client = createClient();
|
|
490
561
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
491
|
-
await
|
|
562
|
+
const instance = await app.createServerInstance();
|
|
563
|
+
await instance.connect(serverTransport);
|
|
492
564
|
await client.connect(clientTransport);
|
|
493
565
|
await client.listTools();
|
|
494
566
|
await client.callTool({ name: "t1" });
|
|
@@ -496,7 +568,7 @@ describe("McpServer.mcpMiddleware()", () => {
|
|
|
496
568
|
expect(matchedMethods).toContain("tools/call");
|
|
497
569
|
expect(matchedMethods).not.toContain("notifications/initialized");
|
|
498
570
|
await client.close();
|
|
499
|
-
await
|
|
571
|
+
await instance.close();
|
|
500
572
|
});
|
|
501
573
|
});
|
|
502
574
|
// ---------------------------------------------------------------------------
|