skybridge 0.0.0-dev.f5759ba → 0.0.0-dev.f58ff90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +155 -0
- package/bin/run.js +5 -0
- package/dist/cli/build-helpers.d.ts +11 -0
- package/dist/cli/build-helpers.js +115 -0
- package/dist/cli/build-helpers.js.map +1 -0
- package/dist/cli/build-helpers.test.js +156 -0
- package/dist/cli/build-helpers.test.js.map +1 -0
- package/dist/cli/build-steps.d.ts +2 -0
- package/dist/cli/build-steps.js +84 -0
- package/dist/cli/build-steps.js.map +1 -0
- package/dist/cli/build-steps.test.js +72 -0
- package/dist/cli/build-steps.test.js.map +1 -0
- package/dist/cli/detect-port.d.ts +18 -0
- package/dist/cli/detect-port.js +49 -0
- package/dist/cli/detect-port.js.map +1 -0
- package/dist/cli/header.d.ts +4 -0
- package/dist/cli/header.js +6 -0
- package/dist/cli/header.js.map +1 -0
- package/dist/cli/resolve-skybridge-config.d.ts +6 -0
- package/dist/cli/resolve-skybridge-config.js +28 -0
- package/dist/cli/resolve-skybridge-config.js.map +1 -0
- package/dist/cli/run-command.d.ts +2 -0
- package/dist/cli/run-command.js +43 -0
- package/dist/cli/run-command.js.map +1 -0
- package/dist/cli/run-plain.d.ts +18 -0
- package/dist/cli/run-plain.js +90 -0
- package/dist/cli/run-plain.js.map +1 -0
- package/dist/cli/telemetry.d.ts +7 -0
- package/dist/cli/telemetry.js +125 -0
- package/dist/cli/telemetry.js.map +1 -0
- package/dist/cli/tunnel-control-server.d.ts +9 -0
- package/dist/cli/tunnel-control-server.js +31 -0
- package/dist/cli/tunnel-control-server.js.map +1 -0
- package/dist/cli/tunnel-control-server.test.js +39 -0
- package/dist/cli/tunnel-control-server.test.js.map +1 -0
- package/dist/cli/tunnel-handler.d.ts +3 -0
- package/dist/cli/tunnel-handler.js +48 -0
- package/dist/cli/tunnel-handler.js.map +1 -0
- package/dist/cli/tunnel-handler.test.js +105 -0
- package/dist/cli/tunnel-handler.test.js.map +1 -0
- package/dist/cli/tunnel.d.ts +57 -0
- package/dist/cli/tunnel.js +154 -0
- package/dist/cli/tunnel.js.map +1 -0
- package/dist/cli/tunnel.test.js +190 -0
- package/dist/cli/tunnel.test.js.map +1 -0
- package/dist/cli/types.d.ts +5 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/use-execute-steps.d.ts +11 -0
- package/dist/cli/use-execute-steps.js +36 -0
- package/dist/cli/use-execute-steps.js.map +1 -0
- package/dist/cli/use-messages.d.ts +3 -0
- package/dist/cli/use-messages.js +11 -0
- package/dist/cli/use-messages.js.map +1 -0
- package/dist/cli/use-nodemon.d.ts +26 -0
- package/dist/cli/use-nodemon.js +106 -0
- package/dist/cli/use-nodemon.js.map +1 -0
- package/dist/cli/use-open-browser.d.ts +1 -0
- package/dist/cli/use-open-browser.js +44 -0
- package/dist/cli/use-open-browser.js.map +1 -0
- package/dist/cli/use-tunnel.d.ts +14 -0
- package/dist/cli/use-tunnel.js +131 -0
- package/dist/cli/use-tunnel.js.map +1 -0
- package/dist/cli/use-typescript-check.d.ts +15 -0
- package/dist/cli/use-typescript-check.js +99 -0
- package/dist/cli/use-typescript-check.js.map +1 -0
- package/dist/commands/build.d.ts +6 -0
- package/dist/commands/build.js +31 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/create.d.ts +9 -0
- package/dist/commands/create.js +30 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/dev.d.ts +13 -0
- package/dist/commands/dev.js +128 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/start.d.ts +9 -0
- package/dist/commands/start.js +55 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/telemetry/disable.d.ts +5 -0
- package/dist/commands/telemetry/disable.js +14 -0
- package/dist/commands/telemetry/disable.js.map +1 -0
- package/dist/commands/telemetry/enable.d.ts +5 -0
- package/dist/commands/telemetry/enable.js +14 -0
- package/dist/commands/telemetry/enable.js.map +1 -0
- package/dist/commands/telemetry/status.d.ts +5 -0
- package/dist/commands/telemetry/status.js +14 -0
- package/dist/commands/telemetry/status.js.map +1 -0
- package/dist/context-warnings.d.ts +5 -0
- package/dist/context-warnings.js +31 -0
- package/dist/context-warnings.js.map +1 -0
- package/dist/context-warnings.test.js +28 -0
- package/dist/context-warnings.test.js.map +1 -0
- package/dist/server/app.d.ts +211 -0
- package/dist/server/app.js +277 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/app.test.js +178 -0
- package/dist/server/app.test.js.map +1 -0
- package/dist/server/asset-base-url-transform-plugin.d.ts +11 -0
- package/dist/server/asset-base-url-transform-plugin.js +48 -0
- package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
- package/dist/server/asset-base-url-transform-plugin.test.js +134 -0
- package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
- package/dist/server/auth/discovery.d.ts +33 -0
- package/dist/server/auth/discovery.js +56 -0
- package/dist/server/auth/discovery.js.map +1 -0
- package/dist/server/auth/discovery.test.js +93 -0
- package/dist/server/auth/discovery.test.js.map +1 -0
- package/dist/server/auth/index.d.ts +48 -0
- package/dist/server/auth/index.js +2 -0
- package/dist/server/auth/index.js.map +1 -0
- package/dist/server/auth/providers/auth0.d.ts +40 -0
- package/dist/server/auth/providers/auth0.js +36 -0
- package/dist/server/auth/providers/auth0.js.map +1 -0
- package/dist/server/auth/providers/auth0.test.js +50 -0
- package/dist/server/auth/providers/auth0.test.js.map +1 -0
- package/dist/server/auth/providers/authplane.d.ts +49 -0
- package/dist/server/auth/providers/authplane.js +57 -0
- package/dist/server/auth/providers/authplane.js.map +1 -0
- package/dist/server/auth/providers/authplane.test.js +143 -0
- package/dist/server/auth/providers/authplane.test.js.map +1 -0
- package/dist/server/auth/providers/clerk.d.ts +51 -0
- package/dist/server/auth/providers/clerk.js +19 -0
- package/dist/server/auth/providers/clerk.js.map +1 -0
- package/dist/server/auth/providers/clerk.test.js +30 -0
- package/dist/server/auth/providers/clerk.test.js.map +1 -0
- package/dist/server/auth/providers/custom.d.ts +42 -0
- package/dist/server/auth/providers/custom.js +59 -0
- package/dist/server/auth/providers/custom.js.map +1 -0
- package/dist/server/auth/providers/custom.test.js +161 -0
- package/dist/server/auth/providers/custom.test.js.map +1 -0
- package/dist/server/auth/providers/descope.d.ts +44 -0
- package/dist/server/auth/providers/descope.js +44 -0
- package/dist/server/auth/providers/descope.js.map +1 -0
- package/dist/server/auth/providers/descope.test.js +62 -0
- package/dist/server/auth/providers/descope.test.js.map +1 -0
- package/dist/server/auth/providers/shared.d.ts +2 -0
- package/dist/server/auth/providers/shared.js +6 -0
- package/dist/server/auth/providers/shared.js.map +1 -0
- package/dist/server/auth/providers/shared.test.js +10 -0
- package/dist/server/auth/providers/shared.test.js.map +1 -0
- package/dist/server/auth/providers/stytch.d.ts +25 -0
- package/dist/server/auth/providers/stytch.js +16 -0
- package/dist/server/auth/providers/stytch.js.map +1 -0
- package/dist/server/auth/providers/verify-spy.d.ts +12 -0
- package/dist/server/auth/providers/verify-spy.js +21 -0
- package/dist/server/auth/providers/verify-spy.js.map +1 -0
- package/dist/server/auth/providers/workos.d.ts +34 -0
- package/dist/server/auth/providers/workos.js +16 -0
- package/dist/server/auth/providers/workos.js.map +1 -0
- package/dist/server/auth/security-schemes.d.ts +23 -0
- package/dist/server/auth/security-schemes.js +64 -0
- package/dist/server/auth/security-schemes.js.map +1 -0
- package/dist/server/auth/security-schemes.test.js +99 -0
- package/dist/server/auth/security-schemes.test.js.map +1 -0
- package/dist/server/auth/setup.d.ts +6 -0
- package/dist/server/auth/setup.js +91 -0
- package/dist/server/auth/setup.js.map +1 -0
- package/dist/server/auth/setup.test.js +514 -0
- package/dist/server/auth/setup.test.js.map +1 -0
- package/dist/server/auth/verify.d.ts +48 -0
- package/dist/server/auth/verify.js +62 -0
- package/dist/server/auth/verify.js.map +1 -0
- package/dist/server/auth/verify.test.js +165 -0
- package/dist/server/auth/verify.test.js.map +1 -0
- package/dist/server/auth-extra.test-d.js +130 -0
- package/dist/server/auth-extra.test-d.js.map +1 -0
- package/dist/server/auth.d.ts +57 -0
- package/dist/server/auth.js +27 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/build-manifest.test.js +28 -0
- package/dist/server/build-manifest.test.js.map +1 -0
- package/dist/server/content-helpers.d.ts +67 -0
- package/dist/server/content-helpers.js +79 -0
- package/dist/server/content-helpers.js.map +1 -0
- package/dist/server/content-helpers.test.d.ts +1 -0
- package/dist/server/content-helpers.test.js +70 -0
- package/dist/server/content-helpers.test.js.map +1 -0
- package/dist/server/events.d.ts +113 -0
- package/dist/server/events.js +318 -0
- package/dist/server/events.js.map +1 -0
- package/dist/server/events.test.d.ts +1 -0
- package/dist/server/events.test.js +172 -0
- package/dist/server/events.test.js.map +1 -0
- package/dist/server/express.d.ts +32 -0
- package/dist/server/express.js +113 -0
- package/dist/server/express.js.map +1 -0
- package/dist/server/express.test.d.ts +1 -0
- package/dist/server/express.test.js +653 -0
- package/dist/server/express.test.js.map +1 -0
- package/dist/server/file-ref.d.ts +28 -0
- package/dist/server/file-ref.js +27 -0
- package/dist/server/file-ref.js.map +1 -0
- package/dist/server/form-input.d.ts +120 -0
- package/dist/server/form-input.js +89 -0
- package/dist/server/form-input.js.map +1 -0
- package/dist/server/host.d.ts +2 -0
- package/dist/server/host.js +11 -0
- package/dist/server/host.js.map +1 -0
- package/dist/server/host.test.d.ts +1 -0
- package/dist/server/host.test.js +13 -0
- package/dist/server/host.test.js.map +1 -0
- package/dist/server/index.d.ts +24 -0
- package/dist/server/index.js +20 -0
- package/dist/server/index.js.map +1 -0
- package/dist/{src/server → server}/inferUtilityTypes.d.ts +6 -6
- package/dist/server/inferUtilityTypes.js.map +1 -0
- package/dist/server/mcp-errors.test.d.ts +1 -0
- package/dist/server/mcp-errors.test.js +229 -0
- package/dist/server/mcp-errors.test.js.map +1 -0
- package/dist/server/metric.d.ts +16 -0
- package/dist/server/metric.js +62 -0
- package/dist/server/metric.js.map +1 -0
- package/dist/server/middleware.d.ts +162 -0
- package/dist/server/middleware.js +126 -0
- package/dist/server/middleware.js.map +1 -0
- package/dist/server/middleware.test-d.d.ts +1 -0
- package/dist/server/middleware.test-d.js +75 -0
- package/dist/server/middleware.test-d.js.map +1 -0
- package/dist/server/middleware.test.d.ts +1 -0
- package/dist/server/middleware.test.js +601 -0
- package/dist/server/middleware.test.js.map +1 -0
- package/dist/server/register-tool.test.d.ts +1 -0
- package/dist/server/register-tool.test.js +230 -0
- package/dist/server/register-tool.test.js.map +1 -0
- package/dist/server/requestOrigin.d.ts +7 -0
- package/dist/server/requestOrigin.js +25 -0
- package/dist/server/requestOrigin.js.map +1 -0
- package/dist/server/server.d.ts +665 -0
- package/dist/server/server.js +815 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/skills-integration.test.d.ts +1 -0
- package/dist/server/skills-integration.test.js +86 -0
- package/dist/server/skills-integration.test.js.map +1 -0
- package/dist/server/skills.d.ts +27 -0
- package/dist/server/skills.js +188 -0
- package/dist/server/skills.js.map +1 -0
- package/dist/server/skills.test.d.ts +1 -0
- package/dist/server/skills.test.js +243 -0
- package/dist/server/skills.test.js.map +1 -0
- package/dist/{src/server → server}/templateHelper.d.ts +3 -7
- package/dist/server/templateHelper.js +11 -0
- package/dist/server/templateHelper.js.map +1 -0
- package/dist/server/templates.generated.d.ts +4 -0
- package/dist/server/templates.generated.js +57 -0
- package/dist/server/templates.generated.js.map +1 -0
- package/dist/server/tool-extra.test.d.ts +1 -0
- package/dist/server/tool-extra.test.js +167 -0
- package/dist/server/tool-extra.test.js.map +1 -0
- package/dist/server/tunnel-proxy-router.d.ts +7 -0
- package/dist/server/tunnel-proxy-router.js +110 -0
- package/dist/server/tunnel-proxy-router.js.map +1 -0
- package/dist/server/tunnel-proxy-router.test.d.ts +1 -0
- package/dist/server/tunnel-proxy-router.test.js +229 -0
- package/dist/server/tunnel-proxy-router.test.js.map +1 -0
- package/dist/server/view-name.test-d.d.ts +1 -0
- package/dist/server/view-name.test-d.js +8 -0
- package/dist/server/view-name.test-d.js.map +1 -0
- package/dist/server/view-resource-resolution.test.d.ts +6 -0
- package/dist/server/view-resource-resolution.test.js +211 -0
- package/dist/server/view-resource-resolution.test.js.map +1 -0
- package/dist/server/viewsDevServer.d.ts +14 -0
- package/dist/server/viewsDevServer.js +48 -0
- package/dist/server/viewsDevServer.js.map +1 -0
- package/dist/{src/test → test}/utils.d.ts +21 -31
- package/dist/test/utils.js +266 -0
- package/dist/test/utils.js.map +1 -0
- package/dist/test/view.test.d.ts +1 -0
- package/dist/test/view.test.js +540 -0
- package/dist/test/view.test.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- 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.d.ts +62 -0
- package/dist/web/bridges/adaptor.js +480 -0
- package/dist/web/bridges/adaptor.js.map +1 -0
- package/dist/web/bridges/adaptor.test.d.ts +1 -0
- package/dist/web/bridges/adaptor.test.js +292 -0
- package/dist/web/bridges/adaptor.test.js.map +1 -0
- package/dist/web/bridges/apps-sdk/bridge.d.ts +15 -0
- package/dist/web/bridges/apps-sdk/bridge.js +58 -0
- package/dist/web/bridges/apps-sdk/bridge.js.map +1 -0
- package/dist/web/bridges/apps-sdk/index.d.ts +4 -0
- package/dist/web/bridges/apps-sdk/index.js +4 -0
- package/dist/web/bridges/apps-sdk/index.js.map +1 -0
- package/dist/web/bridges/apps-sdk/types.d.ts +132 -0
- package/dist/{src/web → web/bridges/apps-sdk}/types.js +0 -1
- package/dist/web/bridges/apps-sdk/types.js.map +1 -0
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +13 -0
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +18 -0
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -0
- package/dist/web/bridges/get-adaptor.d.ts +9 -0
- package/dist/web/bridges/get-adaptor.js +10 -0
- package/dist/web/bridges/get-adaptor.js.map +1 -0
- package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
- package/dist/web/bridges/get-adaptor.test.js +32 -0
- package/dist/web/bridges/get-adaptor.test.js.map +1 -0
- package/dist/web/bridges/index.d.ts +5 -0
- package/dist/web/bridges/index.js +6 -0
- package/dist/web/bridges/index.js.map +1 -0
- package/dist/web/bridges/mcp-app/bridge.d.ts +39 -0
- package/dist/web/bridges/mcp-app/bridge.js +175 -0
- package/dist/web/bridges/mcp-app/bridge.js.map +1 -0
- package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
- package/dist/web/bridges/mcp-app/bridge.test.js +17 -0
- package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
- package/dist/web/bridges/mcp-app/index.d.ts +3 -0
- package/dist/web/bridges/mcp-app/index.js +3 -0
- package/dist/web/bridges/mcp-app/index.js.map +1 -0
- package/dist/web/bridges/mcp-app/types.d.ts +25 -0
- package/dist/web/bridges/mcp-app/types.js +2 -0
- package/dist/web/bridges/mcp-app/types.js.map +1 -0
- package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +19 -0
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js +19 -0
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -0
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.d.ts +1 -0
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +26 -0
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -0
- package/dist/web/bridges/mcp-app/view-tools.test.d.ts +1 -0
- package/dist/web/bridges/mcp-app/view-tools.test.js +143 -0
- package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -0
- package/dist/web/bridges/types.d.ts +272 -0
- package/dist/web/bridges/types.js +15 -0
- package/dist/web/bridges/types.js.map +1 -0
- package/dist/web/bridges/types.test.d.ts +1 -0
- package/dist/web/bridges/types.test.js +19 -0
- package/dist/web/bridges/types.test.js.map +1 -0
- package/dist/web/bridges/use-host-context.d.ts +7 -0
- package/dist/web/bridges/use-host-context.js +13 -0
- package/dist/web/bridges/use-host-context.js.map +1 -0
- package/dist/web/components/modal-provider.d.ts +4 -0
- package/dist/web/components/modal-provider.js +46 -0
- package/dist/web/components/modal-provider.js.map +1 -0
- package/dist/web/create-store.d.ts +29 -0
- package/dist/web/create-store.js +64 -0
- package/dist/web/create-store.js.map +1 -0
- package/dist/web/create-store.test.d.ts +1 -0
- package/dist/web/create-store.test.js +132 -0
- package/dist/web/create-store.test.js.map +1 -0
- package/dist/web/data-llm.d.ts +47 -0
- package/dist/{src/web → web}/data-llm.js +42 -9
- package/dist/web/data-llm.js.map +1 -0
- package/dist/web/data-llm.test.d.ts +1 -0
- package/dist/web/data-llm.test.js +161 -0
- package/dist/web/data-llm.test.js.map +1 -0
- package/dist/{src/web → web}/generate-helpers.d.ts +41 -32
- package/dist/{src/web → web}/generate-helpers.js +38 -30
- package/dist/web/generate-helpers.js.map +1 -0
- package/dist/web/generate-helpers.test-d.d.ts +1 -0
- package/dist/{src/web → web}/generate-helpers.test-d.js +35 -30
- package/dist/web/generate-helpers.test-d.js.map +1 -0
- package/dist/web/generate-helpers.test.d.ts +1 -0
- package/dist/{src/web → web}/generate-helpers.test.js +2 -2
- package/dist/web/generate-helpers.test.js.map +1 -0
- package/dist/{src/web → web}/helpers/state.d.ts +2 -2
- package/dist/web/helpers/state.js +45 -0
- package/dist/web/helpers/state.js.map +1 -0
- package/dist/web/helpers/state.test.d.ts +1 -0
- package/dist/{src/web → web}/helpers/state.test.js +9 -9
- package/dist/web/helpers/state.test.js.map +1 -0
- package/dist/web/hooks/index.d.ts +20 -0
- package/dist/web/hooks/index.js +21 -0
- package/dist/web/hooks/index.js.map +1 -0
- package/dist/web/hooks/openai-extensions.test.d.ts +1 -0
- package/dist/web/hooks/openai-extensions.test.js +107 -0
- package/dist/web/hooks/openai-extensions.test.js.map +1 -0
- package/dist/web/hooks/test/utils.d.ts +21 -0
- package/dist/web/hooks/test/utils.js +75 -0
- package/dist/web/hooks/test/utils.js.map +1 -0
- package/dist/{src/web → web}/hooks/use-call-tool.d.ts +48 -2
- package/dist/web/hooks/use-call-tool.js +101 -0
- package/dist/web/hooks/use-call-tool.js.map +1 -0
- package/dist/web/hooks/use-call-tool.test-d.d.ts +1 -0
- package/dist/web/hooks/use-call-tool.test-d.js.map +1 -0
- package/dist/web/hooks/use-call-tool.test.d.ts +1 -0
- package/dist/{src/web → web}/hooks/use-call-tool.test.js +95 -24
- package/dist/web/hooks/use-call-tool.test.js.map +1 -0
- package/dist/web/hooks/use-deep-link.d.ts +22 -0
- package/dist/web/hooks/use-deep-link.js +34 -0
- package/dist/web/hooks/use-deep-link.js.map +1 -0
- package/dist/web/hooks/use-display-mode.d.ts +24 -0
- package/dist/web/hooks/use-display-mode.js +29 -0
- package/dist/web/hooks/use-display-mode.js.map +1 -0
- package/dist/web/hooks/use-display-mode.test-d.d.ts +1 -0
- package/dist/web/hooks/use-display-mode.test-d.js +8 -0
- package/dist/web/hooks/use-display-mode.test-d.js.map +1 -0
- package/dist/web/hooks/use-display-mode.test.d.ts +1 -0
- package/dist/web/hooks/use-display-mode.test.js +77 -0
- package/dist/web/hooks/use-display-mode.test.js.map +1 -0
- package/dist/web/hooks/use-download.d.ts +3 -0
- package/dist/web/hooks/use-download.js +7 -0
- package/dist/web/hooks/use-download.js.map +1 -0
- package/dist/web/hooks/use-download.test.d.ts +1 -0
- package/dist/web/hooks/use-download.test.js +103 -0
- package/dist/web/hooks/use-download.test.js.map +1 -0
- package/dist/web/hooks/use-file-resource.d.ts +37 -0
- package/dist/web/hooks/use-file-resource.js +98 -0
- package/dist/web/hooks/use-file-resource.js.map +1 -0
- package/dist/web/hooks/use-file-resource.test.d.ts +1 -0
- package/dist/web/hooks/use-file-resource.test.js +65 -0
- package/dist/web/hooks/use-file-resource.test.js.map +1 -0
- package/dist/web/hooks/use-files.d.ts +39 -0
- package/dist/web/hooks/use-files.js +42 -0
- package/dist/web/hooks/use-files.js.map +1 -0
- package/dist/web/hooks/use-files.test.d.ts +1 -0
- package/dist/web/hooks/use-files.test.js +62 -0
- package/dist/web/hooks/use-files.test.js.map +1 -0
- package/dist/web/hooks/use-host.d.ts +44 -0
- package/dist/web/hooks/use-host.js +45 -0
- 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.test.js +59 -0
- package/dist/web/hooks/use-host.test.js.map +1 -0
- package/dist/web/hooks/use-model-context.d.ts +44 -0
- package/dist/web/hooks/use-model-context.js +63 -0
- package/dist/web/hooks/use-model-context.js.map +1 -0
- package/dist/web/hooks/use-open-external.d.ts +20 -0
- package/dist/web/hooks/use-open-external.js +24 -0
- package/dist/web/hooks/use-open-external.js.map +1 -0
- package/dist/web/hooks/use-open-external.test.d.ts +1 -0
- package/dist/web/hooks/use-open-external.test.js +75 -0
- package/dist/web/hooks/use-open-external.test.js.map +1 -0
- package/dist/web/hooks/use-open-file.d.ts +20 -0
- package/dist/web/hooks/use-open-file.js +25 -0
- package/dist/web/hooks/use-open-file.js.map +1 -0
- package/dist/web/hooks/use-register-view-tool.d.ts +37 -0
- package/dist/web/hooks/use-register-view-tool.js +50 -0
- package/dist/web/hooks/use-register-view-tool.js.map +1 -0
- package/dist/web/hooks/use-request-close.d.ts +16 -0
- package/dist/web/hooks/use-request-close.js +21 -0
- package/dist/web/hooks/use-request-close.js.map +1 -0
- package/dist/web/hooks/use-request-close.test.d.ts +1 -0
- package/dist/web/hooks/use-request-close.test.js +47 -0
- package/dist/web/hooks/use-request-close.test.js.map +1 -0
- package/dist/web/hooks/use-request-modal.d.ts +24 -0
- package/dist/web/hooks/use-request-modal.js +31 -0
- package/dist/web/hooks/use-request-modal.js.map +1 -0
- package/dist/web/hooks/use-request-modal.test.d.ts +1 -0
- package/dist/web/hooks/use-request-modal.test.js +71 -0
- package/dist/web/hooks/use-request-modal.test.js.map +1 -0
- package/dist/web/hooks/use-request-size.d.ts +20 -0
- package/dist/web/hooks/use-request-size.js +24 -0
- package/dist/web/hooks/use-request-size.js.map +1 -0
- package/dist/web/hooks/use-request-size.test.d.ts +1 -0
- package/dist/web/hooks/use-request-size.test.js +47 -0
- package/dist/web/hooks/use-request-size.test.js.map +1 -0
- package/dist/web/hooks/use-send-follow-up-message.d.ts +25 -0
- package/dist/web/hooks/use-send-follow-up-message.js +31 -0
- package/dist/web/hooks/use-send-follow-up-message.js.map +1 -0
- package/dist/web/hooks/use-set-open-in-app-url.d.ts +18 -0
- package/dist/web/hooks/use-set-open-in-app-url.js +25 -0
- package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -0
- package/dist/web/hooks/use-set-open-in-app-url.test.d.ts +1 -0
- package/dist/web/hooks/use-set-open-in-app-url.test.js +57 -0
- package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -0
- package/dist/web/hooks/use-tool-info.d.ts +68 -0
- package/dist/web/hooks/use-tool-info.js +48 -0
- package/dist/web/hooks/use-tool-info.js.map +1 -0
- package/dist/web/hooks/use-tool-info.test-d.d.ts +1 -0
- package/dist/{src/web → web}/hooks/use-tool-info.test-d.js +19 -6
- package/dist/web/hooks/use-tool-info.test-d.js.map +1 -0
- package/dist/web/hooks/use-tool-info.test.d.ts +1 -0
- package/dist/web/hooks/use-tool-info.test.js +135 -0
- package/dist/web/hooks/use-tool-info.test.js.map +1 -0
- package/dist/{src/web → web}/hooks/use-user.d.ts +5 -2
- package/dist/web/hooks/use-user.js +38 -0
- package/dist/web/hooks/use-user.js.map +1 -0
- package/dist/web/hooks/use-user.test.d.ts +1 -0
- package/dist/web/hooks/use-user.test.js +170 -0
- package/dist/web/hooks/use-user.test.js.map +1 -0
- package/dist/web/hooks/use-view-state.d.ts +25 -0
- package/dist/web/hooks/use-view-state.js +42 -0
- package/dist/web/hooks/use-view-state.js.map +1 -0
- package/dist/web/hooks/use-view-state.test.d.ts +1 -0
- package/dist/web/hooks/use-view-state.test.js +212 -0
- package/dist/web/hooks/use-view-state.test.js.map +1 -0
- 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-viewport.test.js +109 -0
- package/dist/web/hooks/use-viewport.test.js.map +1 -0
- package/dist/{src/web → web}/index.d.ts +1 -2
- package/dist/{src/web → web}/index.js +1 -2
- package/dist/web/index.js.map +1 -0
- package/dist/web/mount-view.d.ts +21 -0
- package/dist/web/mount-view.js +41 -0
- package/dist/web/mount-view.js.map +1 -0
- package/dist/{src/web → web}/proxy.js +0 -1
- package/dist/web/proxy.js.map +1 -0
- package/dist/web/types.d.ts +20 -0
- package/dist/web/types.js +2 -0
- package/dist/web/types.js.map +1 -0
- package/package.json +92 -41
- package/tsconfig.base.json +33 -0
- package/dist/src/server/devtoolsStaticServer.d.ts +0 -15
- package/dist/src/server/devtoolsStaticServer.js +0 -38
- package/dist/src/server/devtoolsStaticServer.js.map +0 -1
- package/dist/src/server/index.d.ts +0 -5
- package/dist/src/server/index.js +0 -4
- package/dist/src/server/index.js.map +0 -1
- package/dist/src/server/inferUtilityTypes.js.map +0 -1
- package/dist/src/server/server.d.ts +0 -74
- package/dist/src/server/server.js +0 -82
- package/dist/src/server/server.js.map +0 -1
- package/dist/src/server/templateHelper.js +0 -30
- package/dist/src/server/templateHelper.js.map +0 -1
- package/dist/src/server/templates/development.hbs +0 -13
- package/dist/src/server/templates/production.hbs +0 -7
- package/dist/src/server/widgetsDevServer.d.ts +0 -12
- package/dist/src/server/widgetsDevServer.js +0 -39
- package/dist/src/server/widgetsDevServer.js.map +0 -1
- package/dist/src/test/utils.js +0 -242
- package/dist/src/test/utils.js.map +0 -1
- package/dist/src/test/widget.test.js +0 -146
- package/dist/src/test/widget.test.js.map +0 -1
- package/dist/src/web/bridges/apps-sdk-bridge.d.ts +0 -8
- package/dist/src/web/bridges/apps-sdk-bridge.js +0 -41
- package/dist/src/web/bridges/apps-sdk-bridge.js.map +0 -1
- package/dist/src/web/bridges/hooks/use-apps-sdk-bridge.d.ts +0 -2
- package/dist/src/web/bridges/hooks/use-apps-sdk-bridge.js +0 -7
- package/dist/src/web/bridges/hooks/use-apps-sdk-bridge.js.map +0 -1
- package/dist/src/web/bridges/hooks/use-bridge.d.ts +0 -3
- package/dist/src/web/bridges/hooks/use-bridge.js +0 -27
- package/dist/src/web/bridges/hooks/use-bridge.js.map +0 -1
- package/dist/src/web/bridges/hooks/use-mcp-app-bridge.d.ts +0 -4
- package/dist/src/web/bridges/hooks/use-mcp-app-bridge.js +0 -7
- package/dist/src/web/bridges/hooks/use-mcp-app-bridge.js.map +0 -1
- package/dist/src/web/bridges/hooks/use-mcp-app-bridge.test.js +0 -58
- package/dist/src/web/bridges/hooks/use-mcp-app-bridge.test.js.map +0 -1
- package/dist/src/web/bridges/index.d.ts +0 -3
- package/dist/src/web/bridges/index.js +0 -4
- package/dist/src/web/bridges/index.js.map +0 -1
- package/dist/src/web/bridges/mcp-app-bridge.d.ts +0 -26
- package/dist/src/web/bridges/mcp-app-bridge.js +0 -130
- package/dist/src/web/bridges/mcp-app-bridge.js.map +0 -1
- package/dist/src/web/create-store.d.ts +0 -3
- package/dist/src/web/create-store.js +0 -25
- package/dist/src/web/create-store.js.map +0 -1
- package/dist/src/web/create-store.test.js +0 -70
- package/dist/src/web/create-store.test.js.map +0 -1
- package/dist/src/web/data-llm.d.ts +0 -14
- package/dist/src/web/data-llm.js.map +0 -1
- package/dist/src/web/data-llm.test.js +0 -76
- package/dist/src/web/data-llm.test.js.map +0 -1
- package/dist/src/web/generate-helpers.js.map +0 -1
- package/dist/src/web/generate-helpers.test-d.js.map +0 -1
- package/dist/src/web/generate-helpers.test.js.map +0 -1
- package/dist/src/web/helpers/state.js +0 -40
- package/dist/src/web/helpers/state.js.map +0 -1
- package/dist/src/web/helpers/state.test.js.map +0 -1
- package/dist/src/web/hooks/index.d.ts +0 -11
- package/dist/src/web/hooks/index.js +0 -12
- package/dist/src/web/hooks/index.js.map +0 -1
- package/dist/src/web/hooks/use-call-tool.js +0 -60
- package/dist/src/web/hooks/use-call-tool.js.map +0 -1
- package/dist/src/web/hooks/use-call-tool.test-d.js.map +0 -1
- package/dist/src/web/hooks/use-call-tool.test.js.map +0 -1
- package/dist/src/web/hooks/use-display-mode.d.ts +0 -4
- package/dist/src/web/hooks/use-display-mode.js +0 -7
- package/dist/src/web/hooks/use-display-mode.js.map +0 -1
- package/dist/src/web/hooks/use-display-mode.test.js +0 -41
- package/dist/src/web/hooks/use-display-mode.test.js.map +0 -1
- package/dist/src/web/hooks/use-files.d.ts +0 -10
- package/dist/src/web/hooks/use-files.js +0 -7
- package/dist/src/web/hooks/use-files.js.map +0 -1
- package/dist/src/web/hooks/use-files.test.js +0 -29
- package/dist/src/web/hooks/use-files.test.js.map +0 -1
- package/dist/src/web/hooks/use-layout.d.ts +0 -22
- package/dist/src/web/hooks/use-layout.js +0 -23
- package/dist/src/web/hooks/use-layout.js.map +0 -1
- package/dist/src/web/hooks/use-layout.test.js +0 -46
- package/dist/src/web/hooks/use-layout.test.js.map +0 -1
- package/dist/src/web/hooks/use-open-external.d.ts +0 -1
- package/dist/src/web/hooks/use-open-external.js +0 -6
- package/dist/src/web/hooks/use-open-external.js.map +0 -1
- package/dist/src/web/hooks/use-open-external.test.js +0 -24
- package/dist/src/web/hooks/use-open-external.test.js.map +0 -1
- package/dist/src/web/hooks/use-openai-global.d.ts +0 -3
- package/dist/src/web/hooks/use-openai-global.js +0 -6
- package/dist/src/web/hooks/use-openai-global.js.map +0 -1
- package/dist/src/web/hooks/use-request-modal.d.ts +0 -6
- package/dist/src/web/hooks/use-request-modal.js +0 -9
- package/dist/src/web/hooks/use-request-modal.js.map +0 -1
- package/dist/src/web/hooks/use-request-modal.test.js +0 -24
- package/dist/src/web/hooks/use-request-modal.test.js.map +0 -1
- package/dist/src/web/hooks/use-send-follow-up-message.d.ts +0 -1
- package/dist/src/web/hooks/use-send-follow-up-message.js +0 -11
- package/dist/src/web/hooks/use-send-follow-up-message.js.map +0 -1
- package/dist/src/web/hooks/use-tool-info.d.ts +0 -25
- package/dist/src/web/hooks/use-tool-info.js +0 -20
- package/dist/src/web/hooks/use-tool-info.js.map +0 -1
- package/dist/src/web/hooks/use-tool-info.test-d.js.map +0 -1
- package/dist/src/web/hooks/use-tool-info.test.js +0 -60
- package/dist/src/web/hooks/use-tool-info.test.js.map +0 -1
- package/dist/src/web/hooks/use-user.js +0 -19
- package/dist/src/web/hooks/use-user.js.map +0 -1
- package/dist/src/web/hooks/use-user.test.js +0 -44
- package/dist/src/web/hooks/use-user.test.js.map +0 -1
- package/dist/src/web/hooks/use-widget-state.d.ts +0 -4
- package/dist/src/web/hooks/use-widget-state.js +0 -32
- package/dist/src/web/hooks/use-widget-state.js.map +0 -1
- package/dist/src/web/hooks/use-widget-state.test.js +0 -61
- package/dist/src/web/hooks/use-widget-state.test.js.map +0 -1
- package/dist/src/web/index.js.map +0 -1
- package/dist/src/web/mount-widget.d.ts +0 -1
- package/dist/src/web/mount-widget.js +0 -19
- package/dist/src/web/mount-widget.js.map +0 -1
- package/dist/src/web/plugin/data-llm.test.js +0 -81
- package/dist/src/web/plugin/data-llm.test.js.map +0 -1
- package/dist/src/web/plugin/plugin.d.ts +0 -2
- package/dist/src/web/plugin/plugin.js +0 -39
- package/dist/src/web/plugin/plugin.js.map +0 -1
- package/dist/src/web/plugin/transform-data-llm.d.ts +0 -12
- package/dist/src/web/plugin/transform-data-llm.js +0 -93
- package/dist/src/web/plugin/transform-data-llm.js.map +0 -1
- package/dist/src/web/plugin/transform-data-llm.test.js +0 -81
- package/dist/src/web/plugin/transform-data-llm.test.js.map +0 -1
- package/dist/src/web/proxy.js.map +0 -1
- package/dist/src/web/types.d.ts +0 -138
- package/dist/src/web/types.js.map +0 -1
- package/dist/vitest.config.d.ts +0 -2
- package/dist/vitest.config.js +0 -8
- package/dist/vitest.config.js.map +0 -1
- /package/dist/{src/test/widget.test.d.ts → cli/build-helpers.test.d.ts} +0 -0
- /package/dist/{src/web/bridges/hooks/use-mcp-app-bridge.test.d.ts → cli/build-steps.test.d.ts} +0 -0
- /package/dist/{src/web/create-store.test.d.ts → cli/tunnel-control-server.test.d.ts} +0 -0
- /package/dist/{src/web/data-llm.test.d.ts → cli/tunnel-handler.test.d.ts} +0 -0
- /package/dist/{src/web/generate-helpers.test-d.d.ts → cli/tunnel.test.d.ts} +0 -0
- /package/dist/{src/web/generate-helpers.test.d.ts → context-warnings.test.d.ts} +0 -0
- /package/dist/{src/web/helpers/state.test.d.ts → server/app.test.d.ts} +0 -0
- /package/dist/{src/web/hooks/use-call-tool.test-d.d.ts → server/asset-base-url-transform-plugin.test.d.ts} +0 -0
- /package/dist/{src/web/hooks/use-display-mode.test.d.ts → server/auth/discovery.test.d.ts} +0 -0
- /package/dist/{src/web/hooks/use-files.test.d.ts → server/auth/providers/auth0.test.d.ts} +0 -0
- /package/dist/{src/web/hooks/use-layout.test.d.ts → server/auth/providers/authplane.test.d.ts} +0 -0
- /package/dist/{src/web/hooks/use-open-external.test.d.ts → server/auth/providers/clerk.test.d.ts} +0 -0
- /package/dist/{src/web/hooks/use-request-modal.test.d.ts → server/auth/providers/custom.test.d.ts} +0 -0
- /package/dist/{src/web/hooks/use-tool-info.test-d.d.ts → server/auth/providers/descope.test.d.ts} +0 -0
- /package/dist/{src/web/hooks/use-tool-info.test.d.ts → server/auth/providers/shared.test.d.ts} +0 -0
- /package/dist/{src/web/hooks/use-user.test.d.ts → server/auth/security-schemes.test.d.ts} +0 -0
- /package/dist/{src/web/hooks/use-widget-state.test.d.ts → server/auth/setup.test.d.ts} +0 -0
- /package/dist/{src/web/plugin/data-llm.test.d.ts → server/auth/verify.test.d.ts} +0 -0
- /package/dist/{src/web/hooks/use-call-tool.test.d.ts → server/auth-extra.test-d.d.ts} +0 -0
- /package/dist/{src/web/plugin/transform-data-llm.test.d.ts → server/build-manifest.test.d.ts} +0 -0
- /package/dist/{src/server → server}/inferUtilityTypes.js +0 -0
- /package/dist/{src/web → web}/hooks/use-call-tool.test-d.js +0 -0
- /package/dist/{src/web → web}/proxy.d.ts +0 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// @vitest-environment node
|
|
2
|
+
import http from "node:http";
|
|
3
|
+
import { CLIENT_CAPABILITIES_META_KEY, PROTOCOL_VERSION_META_KEY, UnsupportedProtocolVersionError, } from "@modelcontextprotocol/server";
|
|
4
|
+
import { afterEach, expect, it, vi } from "vitest";
|
|
5
|
+
import { Skybridge } from "./app.js";
|
|
6
|
+
import { buildMcpHandler, createApp } from "./express.js";
|
|
7
|
+
vi.mock("@skybridge/devtools", () => ({
|
|
8
|
+
devtoolsStaticServer: () => ((_r, _s, n) => n()),
|
|
9
|
+
}));
|
|
10
|
+
vi.mock("./viewsDevServer.js", () => ({
|
|
11
|
+
viewsDevServer: () => ((_r, _s, n) => n()),
|
|
12
|
+
}));
|
|
13
|
+
const REJECTED = {
|
|
14
|
+
headers: {
|
|
15
|
+
"content-type": "application/json",
|
|
16
|
+
accept: "application/json, text/event-stream",
|
|
17
|
+
"mcp-protocol-version": "client-supplied-text",
|
|
18
|
+
},
|
|
19
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/list" }),
|
|
20
|
+
};
|
|
21
|
+
const UNSUPPORTED = {
|
|
22
|
+
headers: {
|
|
23
|
+
"content-type": "application/json",
|
|
24
|
+
accept: "application/json, text/event-stream",
|
|
25
|
+
},
|
|
26
|
+
body: JSON.stringify({
|
|
27
|
+
jsonrpc: "2.0",
|
|
28
|
+
id: 1,
|
|
29
|
+
method: "tools/list",
|
|
30
|
+
params: {
|
|
31
|
+
_meta: {
|
|
32
|
+
[PROTOCOL_VERSION_META_KEY]: "2099-01-01",
|
|
33
|
+
[CLIENT_CAPABILITIES_META_KEY]: {},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
let openServer;
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
openServer?.close();
|
|
41
|
+
vi.restoreAllMocks();
|
|
42
|
+
});
|
|
43
|
+
function createTestApp() {
|
|
44
|
+
return new Skybridge({
|
|
45
|
+
name: "t",
|
|
46
|
+
version: "0.0.0",
|
|
47
|
+
handler: (server) => server,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async function serve(options) {
|
|
51
|
+
const expressApp = await createApp({
|
|
52
|
+
app: options.app ?? createTestApp(),
|
|
53
|
+
httpServer: http.createServer(),
|
|
54
|
+
mcpHandler: options.mcpHandler,
|
|
55
|
+
onMcpError: options.onMcpError,
|
|
56
|
+
});
|
|
57
|
+
const listening = http.createServer(expressApp);
|
|
58
|
+
await new Promise((r) => listening.listen(0, r));
|
|
59
|
+
openServer = listening;
|
|
60
|
+
return listening.address().port;
|
|
61
|
+
}
|
|
62
|
+
function post(port, request) {
|
|
63
|
+
return fetch(`http://localhost:${port}/mcp`, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: request.headers,
|
|
66
|
+
body: request.body,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
it("reports a failure inside the MCP leg instead of swallowing it", async () => {
|
|
70
|
+
const { createApp } = await import("./express.js");
|
|
71
|
+
const app = new Skybridge({
|
|
72
|
+
name: "t",
|
|
73
|
+
version: "0.0.0",
|
|
74
|
+
handler: (server) => server,
|
|
75
|
+
});
|
|
76
|
+
vi.spyOn(app, "createServerInstance").mockImplementation(() => {
|
|
77
|
+
throw new Error("boom");
|
|
78
|
+
});
|
|
79
|
+
const errors = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
80
|
+
const httpServer = http.createServer();
|
|
81
|
+
const expressApp = await createApp({ app, httpServer });
|
|
82
|
+
const listening = http.createServer(expressApp);
|
|
83
|
+
await new Promise((r) => listening.listen(0, r));
|
|
84
|
+
openServer = listening;
|
|
85
|
+
const port = listening.address().port;
|
|
86
|
+
const res = await fetch(`http://localhost:${port}/mcp`, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: { "content-type": "application/json" },
|
|
89
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "initialize" }),
|
|
90
|
+
});
|
|
91
|
+
expect(res.status).toBeGreaterThanOrEqual(500);
|
|
92
|
+
expect(errors.mock.calls.some(([msg]) => String(msg).includes("Error handling MCP request"))).toBe(true);
|
|
93
|
+
});
|
|
94
|
+
it("logs a rejected request by default", async () => {
|
|
95
|
+
const errors = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
96
|
+
const port = await serve({});
|
|
97
|
+
const res = await post(port, REJECTED);
|
|
98
|
+
expect(res.status).toBe(400);
|
|
99
|
+
expect(errors).toHaveBeenCalledTimes(1);
|
|
100
|
+
const [prefix, error] = errors.mock.calls[0] ?? [];
|
|
101
|
+
expect(prefix).toBe("Error handling MCP request:");
|
|
102
|
+
expect(error).toBeInstanceOf(Error);
|
|
103
|
+
expect(error.message).toMatch(/^Rejected inbound request \(modern-header-without-claim\)/);
|
|
104
|
+
});
|
|
105
|
+
it("skips the unsupported protocol version by default", async () => {
|
|
106
|
+
const errors = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
107
|
+
const port = await serve({});
|
|
108
|
+
const res = await post(port, UNSUPPORTED);
|
|
109
|
+
expect(res.status).toBe(400);
|
|
110
|
+
expect((await res.json()).error.code).toBe(-32022);
|
|
111
|
+
expect(errors).not.toHaveBeenCalled();
|
|
112
|
+
});
|
|
113
|
+
it("passes a rejected request to onMcpError instead of logging it", async () => {
|
|
114
|
+
const errors = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
115
|
+
const onMcpError = vi.fn();
|
|
116
|
+
const port = await serve({ onMcpError });
|
|
117
|
+
const res = await post(port, REJECTED);
|
|
118
|
+
expect(res.status).toBe(400);
|
|
119
|
+
expect(onMcpError).toHaveBeenCalledTimes(1);
|
|
120
|
+
const [error] = onMcpError.mock.calls[0] ?? [];
|
|
121
|
+
expect(error).toBeInstanceOf(Error);
|
|
122
|
+
expect(error.message).toMatch(/^Rejected inbound request/);
|
|
123
|
+
expect(errors).not.toHaveBeenCalled();
|
|
124
|
+
});
|
|
125
|
+
it("passes the unsupported protocol version to onMcpError", async () => {
|
|
126
|
+
const errors = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
127
|
+
const onMcpError = vi.fn();
|
|
128
|
+
const port = await serve({ onMcpError });
|
|
129
|
+
const res = await post(port, UNSUPPORTED);
|
|
130
|
+
expect(res.status).toBe(400);
|
|
131
|
+
expect((await res.json()).error.code).toBe(-32022);
|
|
132
|
+
expect(onMcpError).toHaveBeenCalledTimes(1);
|
|
133
|
+
expect(onMcpError.mock.calls[0]?.[0]).toBeInstanceOf(UnsupportedProtocolVersionError);
|
|
134
|
+
expect(errors).not.toHaveBeenCalled();
|
|
135
|
+
});
|
|
136
|
+
it("passes a server factory failure to onMcpError as the same error", async () => {
|
|
137
|
+
const errors = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
138
|
+
const onMcpError = vi.fn();
|
|
139
|
+
const app = createTestApp();
|
|
140
|
+
const boom = new Error("boom");
|
|
141
|
+
vi.spyOn(app, "createServerInstance").mockImplementation(() => {
|
|
142
|
+
throw boom;
|
|
143
|
+
});
|
|
144
|
+
const port = await serve({ app, onMcpError });
|
|
145
|
+
const res = await post(port, {
|
|
146
|
+
headers: { "content-type": "application/json" },
|
|
147
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "initialize" }),
|
|
148
|
+
});
|
|
149
|
+
expect(res.status).toBe(500);
|
|
150
|
+
expect(onMcpError).toHaveBeenCalledTimes(1);
|
|
151
|
+
expect(onMcpError.mock.calls[0]?.[0]).toBe(boom);
|
|
152
|
+
expect(errors).not.toHaveBeenCalled();
|
|
153
|
+
});
|
|
154
|
+
it("passes a Node adapter failure to onMcpError", async () => {
|
|
155
|
+
const errors = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
156
|
+
const onMcpError = vi.fn();
|
|
157
|
+
const app = createTestApp();
|
|
158
|
+
const mcpHandler = buildMcpHandler(app);
|
|
159
|
+
await mcpHandler.close();
|
|
160
|
+
const port = await serve({ app, mcpHandler, onMcpError });
|
|
161
|
+
const res = await post(port, REJECTED);
|
|
162
|
+
expect(res.status).toBe(500);
|
|
163
|
+
expect(onMcpError).toHaveBeenCalledTimes(1);
|
|
164
|
+
expect(onMcpError.mock.calls[0]?.[0].message).toBe("This MCP handler has been closed");
|
|
165
|
+
expect(errors).not.toHaveBeenCalled();
|
|
166
|
+
});
|
|
167
|
+
it("does not log a Node adapter failure by default", async () => {
|
|
168
|
+
const errors = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
169
|
+
const app = createTestApp();
|
|
170
|
+
const mcpHandler = buildMcpHandler(app);
|
|
171
|
+
await mcpHandler.close();
|
|
172
|
+
const port = await serve({ app, mcpHandler });
|
|
173
|
+
const res = await post(port, REJECTED);
|
|
174
|
+
expect(res.status).toBe(500);
|
|
175
|
+
expect(errors).not.toHaveBeenCalled();
|
|
176
|
+
});
|
|
177
|
+
it("wires onMcpError through run() on Node", async () => {
|
|
178
|
+
const errors = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
179
|
+
const onMcpError = vi.fn();
|
|
180
|
+
const prevPort = process.env.__PORT;
|
|
181
|
+
const prevSend = process.send;
|
|
182
|
+
const sigterm = process.listeners("SIGTERM");
|
|
183
|
+
const sigint = process.listeners("SIGINT");
|
|
184
|
+
let runServer;
|
|
185
|
+
const realCreateServer = http.createServer.bind(http);
|
|
186
|
+
vi.spyOn(http, "createServer").mockImplementation(((...args) => {
|
|
187
|
+
runServer = realCreateServer(...args);
|
|
188
|
+
return runServer;
|
|
189
|
+
}));
|
|
190
|
+
process.env.__PORT = "0";
|
|
191
|
+
if (process.send) {
|
|
192
|
+
process.send = vi.fn();
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
const app = new Skybridge({
|
|
196
|
+
name: "t",
|
|
197
|
+
version: "0.0.0",
|
|
198
|
+
onMcpError,
|
|
199
|
+
handler: (server) => server,
|
|
200
|
+
});
|
|
201
|
+
await app.run();
|
|
202
|
+
const { port } = runServer.address();
|
|
203
|
+
const res = await post(port, REJECTED);
|
|
204
|
+
expect(res.status).toBe(400);
|
|
205
|
+
expect(onMcpError).toHaveBeenCalledTimes(1);
|
|
206
|
+
expect(errors).not.toHaveBeenCalled();
|
|
207
|
+
}
|
|
208
|
+
finally {
|
|
209
|
+
runServer?.close();
|
|
210
|
+
for (const [signal, saved] of [
|
|
211
|
+
["SIGTERM", sigterm],
|
|
212
|
+
["SIGINT", sigint],
|
|
213
|
+
]) {
|
|
214
|
+
for (const listener of process.listeners(signal)) {
|
|
215
|
+
if (!saved.includes(listener)) {
|
|
216
|
+
process.off(signal, listener);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (prevPort === undefined) {
|
|
221
|
+
delete process.env.__PORT;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
process.env.__PORT = prevPort;
|
|
225
|
+
}
|
|
226
|
+
process.send = prevSend;
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
//# sourceMappingURL=mcp-errors.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-errors.test.js","sourceRoot":"","sources":["../../src/server/mcp-errors.test.ts"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment node\nimport http from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport {\n CLIENT_CAPABILITIES_META_KEY,\n PROTOCOL_VERSION_META_KEY,\n UnsupportedProtocolVersionError,\n} from \"@modelcontextprotocol/server\";\nimport type { RequestHandler } from \"express\";\nimport { afterEach, expect, it, vi } from \"vitest\";\nimport { Skybridge } from \"./app.js\";\nimport { buildMcpHandler, createApp } from \"./express.js\";\n\nvi.mock(\"@skybridge/devtools\", () => ({\n devtoolsStaticServer: () =>\n ((_r: unknown, _s: unknown, n: () => void) => n()) as RequestHandler,\n}));\nvi.mock(\"./viewsDevServer.js\", () => ({\n viewsDevServer: () =>\n ((_r: unknown, _s: unknown, n: () => void) => n()) as RequestHandler,\n}));\n\nconst REJECTED = {\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json, text/event-stream\",\n \"mcp-protocol-version\": \"client-supplied-text\",\n },\n body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method: \"tools/list\" }),\n};\n\nconst UNSUPPORTED = {\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json, text/event-stream\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/list\",\n params: {\n _meta: {\n [PROTOCOL_VERSION_META_KEY]: \"2099-01-01\",\n [CLIENT_CAPABILITIES_META_KEY]: {},\n },\n },\n }),\n};\n\nlet openServer: http.Server | undefined;\nafterEach(() => {\n openServer?.close();\n vi.restoreAllMocks();\n});\n\nfunction createTestApp() {\n return new Skybridge({\n name: \"t\",\n version: \"0.0.0\",\n handler: (server) => server,\n });\n}\n\nasync function serve(options: {\n app?: Skybridge;\n mcpHandler?: ReturnType<typeof buildMcpHandler>;\n onMcpError?: (error: Error) => void;\n}) {\n const expressApp = await createApp({\n app: options.app ?? createTestApp(),\n httpServer: http.createServer(),\n mcpHandler: options.mcpHandler,\n onMcpError: options.onMcpError,\n });\n const listening = http.createServer(expressApp);\n await new Promise<void>((r) => listening.listen(0, r));\n openServer = listening;\n return (listening.address() as AddressInfo).port;\n}\n\nfunction post(\n port: number,\n request: { headers: Record<string, string>; body: string },\n) {\n return fetch(`http://localhost:${port}/mcp`, {\n method: \"POST\",\n headers: request.headers,\n body: request.body,\n });\n}\n\nit(\"reports a failure inside the MCP leg instead of swallowing it\", async () => {\n const { createApp } = await import(\"./express.js\");\n const app = new Skybridge({\n name: \"t\",\n version: \"0.0.0\",\n handler: (server) => server,\n });\n vi.spyOn(app, \"createServerInstance\").mockImplementation(() => {\n throw new Error(\"boom\");\n });\n const errors = vi.spyOn(console, \"error\").mockImplementation(() => {});\n\n const httpServer = http.createServer();\n const expressApp = await createApp({ app, httpServer });\n const listening = http.createServer(expressApp);\n await new Promise<void>((r) => listening.listen(0, r));\n openServer = listening;\n const port = (listening.address() as { port: number }).port;\n\n const res = await fetch(`http://localhost:${port}/mcp`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method: \"initialize\" }),\n });\n\n expect(res.status).toBeGreaterThanOrEqual(500);\n expect(\n errors.mock.calls.some(([msg]) =>\n String(msg).includes(\"Error handling MCP request\"),\n ),\n ).toBe(true);\n});\n\nit(\"logs a rejected request by default\", async () => {\n const errors = vi.spyOn(console, \"error\").mockImplementation(() => {});\n const port = await serve({});\n\n const res = await post(port, REJECTED);\n\n expect(res.status).toBe(400);\n expect(errors).toHaveBeenCalledTimes(1);\n const [prefix, error] = errors.mock.calls[0] ?? [];\n expect(prefix).toBe(\"Error handling MCP request:\");\n expect(error).toBeInstanceOf(Error);\n expect((error as Error).message).toMatch(\n /^Rejected inbound request \\(modern-header-without-claim\\)/,\n );\n});\n\nit(\"skips the unsupported protocol version by default\", async () => {\n const errors = vi.spyOn(console, \"error\").mockImplementation(() => {});\n const port = await serve({});\n\n const res = await post(port, UNSUPPORTED);\n\n expect(res.status).toBe(400);\n expect((await res.json()).error.code).toBe(-32022);\n expect(errors).not.toHaveBeenCalled();\n});\n\nit(\"passes a rejected request to onMcpError instead of logging it\", async () => {\n const errors = vi.spyOn(console, \"error\").mockImplementation(() => {});\n const onMcpError = vi.fn();\n const port = await serve({ onMcpError });\n\n const res = await post(port, REJECTED);\n\n expect(res.status).toBe(400);\n expect(onMcpError).toHaveBeenCalledTimes(1);\n const [error] = onMcpError.mock.calls[0] ?? [];\n expect(error).toBeInstanceOf(Error);\n expect(error.message).toMatch(/^Rejected inbound request/);\n expect(errors).not.toHaveBeenCalled();\n});\n\nit(\"passes the unsupported protocol version to onMcpError\", async () => {\n const errors = vi.spyOn(console, \"error\").mockImplementation(() => {});\n const onMcpError = vi.fn();\n const port = await serve({ onMcpError });\n\n const res = await post(port, UNSUPPORTED);\n\n expect(res.status).toBe(400);\n expect((await res.json()).error.code).toBe(-32022);\n expect(onMcpError).toHaveBeenCalledTimes(1);\n expect(onMcpError.mock.calls[0]?.[0]).toBeInstanceOf(\n UnsupportedProtocolVersionError,\n );\n expect(errors).not.toHaveBeenCalled();\n});\n\nit(\"passes a server factory failure to onMcpError as the same error\", async () => {\n const errors = vi.spyOn(console, \"error\").mockImplementation(() => {});\n const onMcpError = vi.fn();\n const app = createTestApp();\n const boom = new Error(\"boom\");\n vi.spyOn(app, \"createServerInstance\").mockImplementation(() => {\n throw boom;\n });\n const port = await serve({ app, onMcpError });\n\n const res = await post(port, {\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method: \"initialize\" }),\n });\n\n expect(res.status).toBe(500);\n expect(onMcpError).toHaveBeenCalledTimes(1);\n expect(onMcpError.mock.calls[0]?.[0]).toBe(boom);\n expect(errors).not.toHaveBeenCalled();\n});\n\nit(\"passes a Node adapter failure to onMcpError\", async () => {\n const errors = vi.spyOn(console, \"error\").mockImplementation(() => {});\n const onMcpError = vi.fn();\n const app = createTestApp();\n const mcpHandler = buildMcpHandler(app);\n await mcpHandler.close();\n const port = await serve({ app, mcpHandler, onMcpError });\n\n const res = await post(port, REJECTED);\n\n expect(res.status).toBe(500);\n expect(onMcpError).toHaveBeenCalledTimes(1);\n expect(onMcpError.mock.calls[0]?.[0].message).toBe(\n \"This MCP handler has been closed\",\n );\n expect(errors).not.toHaveBeenCalled();\n});\n\nit(\"does not log a Node adapter failure by default\", async () => {\n const errors = vi.spyOn(console, \"error\").mockImplementation(() => {});\n const app = createTestApp();\n const mcpHandler = buildMcpHandler(app);\n await mcpHandler.close();\n const port = await serve({ app, mcpHandler });\n\n const res = await post(port, REJECTED);\n\n expect(res.status).toBe(500);\n expect(errors).not.toHaveBeenCalled();\n});\n\nit(\"wires onMcpError through run() on Node\", async () => {\n const errors = vi.spyOn(console, \"error\").mockImplementation(() => {});\n const onMcpError = vi.fn();\n const prevPort = process.env.__PORT;\n const prevSend = process.send;\n const sigterm = process.listeners(\"SIGTERM\");\n const sigint = process.listeners(\"SIGINT\");\n let runServer: http.Server | undefined;\n const realCreateServer = http.createServer.bind(http);\n vi.spyOn(http, \"createServer\").mockImplementation(((\n ...args: Parameters<typeof http.createServer>\n ) => {\n runServer = realCreateServer(...args);\n return runServer;\n }) as typeof http.createServer);\n process.env.__PORT = \"0\";\n if (process.send) {\n process.send = vi.fn() as unknown as typeof process.send;\n }\n try {\n const app = new Skybridge({\n name: \"t\",\n version: \"0.0.0\",\n onMcpError,\n handler: (server) => server,\n });\n await app.run();\n const { port } = (runServer as http.Server).address() as AddressInfo;\n\n const res = await post(port, REJECTED);\n\n expect(res.status).toBe(400);\n expect(onMcpError).toHaveBeenCalledTimes(1);\n expect(errors).not.toHaveBeenCalled();\n } finally {\n runServer?.close();\n for (const [signal, saved] of [\n [\"SIGTERM\", sigterm],\n [\"SIGINT\", sigint],\n ] as const) {\n for (const listener of process.listeners(signal)) {\n if (!saved.includes(listener)) {\n process.off(signal, listener);\n }\n }\n }\n if (prevPort === undefined) {\n delete process.env.__PORT;\n } else {\n process.env.__PORT = prevPort;\n }\n process.send = prevSend;\n }\n});\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { McpMiddlewareEntry } from "./middleware.js";
|
|
2
|
+
/**
|
|
3
|
+
* Registers internal MCP middleware that emits a DogStatsD counter over UDP
|
|
4
|
+
* for every tool call. Enabled by default; respects the existing telemetry
|
|
5
|
+
* opt-out (SKYBRIDGE_TELEMETRY_DISABLED, DO_NOT_TRACK, or `skybridge telemetry disable`).
|
|
6
|
+
*
|
|
7
|
+
* Skips registration when the version string contains "-dev" (e.g. development
|
|
8
|
+
* builds) or when the version cannot be parsed into major.minor, so that
|
|
9
|
+
* malformed data does not pollute production metrics.
|
|
10
|
+
*
|
|
11
|
+
* Metric (DogStatsD counter format with tags):
|
|
12
|
+
* Requests:1|c|#version:<major>.<minor> — every tools/call
|
|
13
|
+
*/
|
|
14
|
+
export declare function registerMonitoring(app: {
|
|
15
|
+
withMcpMiddleware(entry: McpMiddlewareEntry): unknown;
|
|
16
|
+
}): void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createSocket } from "node:dgram";
|
|
2
|
+
import { isEnabled } from "../cli/telemetry.js";
|
|
3
|
+
import { VERSION } from "../version.js";
|
|
4
|
+
function parseMajorMinor(version) {
|
|
5
|
+
const parts = version.split(".");
|
|
6
|
+
if (parts.length < 2) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
return `${parts[0]}.${parts[1]}`;
|
|
10
|
+
}
|
|
11
|
+
const isDev = VERSION.includes("-dev");
|
|
12
|
+
const versionTag = parseMajorMinor(VERSION);
|
|
13
|
+
const STATSD_HOST = "18.208.242.161";
|
|
14
|
+
const STATSD_PORT = 8125;
|
|
15
|
+
let socket = null;
|
|
16
|
+
function getSocket() {
|
|
17
|
+
if (!socket) {
|
|
18
|
+
socket = createSocket("udp4");
|
|
19
|
+
socket.unref();
|
|
20
|
+
}
|
|
21
|
+
return socket;
|
|
22
|
+
}
|
|
23
|
+
function sendMetric(metric) {
|
|
24
|
+
if (!STATSD_HOST) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const payload = Buffer.from(metric);
|
|
28
|
+
getSocket().send(payload, STATSD_PORT, STATSD_HOST, () => {
|
|
29
|
+
// fire-and-forget: errors are intentionally silenced
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Registers internal MCP middleware that emits a DogStatsD counter over UDP
|
|
34
|
+
* for every tool call. Enabled by default; respects the existing telemetry
|
|
35
|
+
* opt-out (SKYBRIDGE_TELEMETRY_DISABLED, DO_NOT_TRACK, or `skybridge telemetry disable`).
|
|
36
|
+
*
|
|
37
|
+
* Skips registration when the version string contains "-dev" (e.g. development
|
|
38
|
+
* builds) or when the version cannot be parsed into major.minor, so that
|
|
39
|
+
* malformed data does not pollute production metrics.
|
|
40
|
+
*
|
|
41
|
+
* Metric (DogStatsD counter format with tags):
|
|
42
|
+
* Requests:1|c|#version:<major>.<minor> — every tools/call
|
|
43
|
+
*/
|
|
44
|
+
export function registerMonitoring(app) {
|
|
45
|
+
if (isDev || !versionTag) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const handler = async (_req, _extra, next) => {
|
|
49
|
+
// Check on every call so opt-out takes effect immediately without restart.
|
|
50
|
+
if (!isEnabled()) {
|
|
51
|
+
return next();
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
return await next();
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
sendMetric(`Requests:1|c|#version:${versionTag}`);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
app.withMcpMiddleware({ filter: "tools/call", handler });
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=metric.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric.js","sourceRoot":"","sources":["../../src/server/metric.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGxC,SAAS,eAAe,CAAC,OAAe;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACvC,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;AAE5C,MAAM,WAAW,GAAG,gBAAgB,CAAC;AACrC,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB,IAAI,MAAM,GAA2C,IAAI,CAAC;AAE1D,SAAS,SAAS;IAChB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAAC,MAAc;IAChC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,SAAS,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE;QACvD,qDAAqD;IACvD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAElC;IACC,IAAI,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;QACzB,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAoB,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QAC5D,2EAA2E;QAC3E,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACjB,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,EAAE,CAAC;QACtB,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,yBAAyB,UAAU,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC,CAAC;IAEF,GAAG,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC;AAC3D,CAAC","sourcesContent":["import { createSocket } from \"node:dgram\";\nimport { isEnabled } from \"../cli/telemetry.js\";\nimport { VERSION } from \"../version.js\";\nimport type { McpMiddlewareEntry, McpMiddlewareFn } from \"./middleware.js\";\n\nfunction parseMajorMinor(version: string): string | null {\n const parts = version.split(\".\");\n if (parts.length < 2) {\n return null;\n }\n return `${parts[0]}.${parts[1]}`;\n}\n\nconst isDev = VERSION.includes(\"-dev\");\nconst versionTag = parseMajorMinor(VERSION);\n\nconst STATSD_HOST = \"18.208.242.161\";\nconst STATSD_PORT = 8125;\n\nlet socket: ReturnType<typeof createSocket> | null = null;\n\nfunction getSocket() {\n if (!socket) {\n socket = createSocket(\"udp4\");\n socket.unref();\n }\n return socket;\n}\n\nfunction sendMetric(metric: string): void {\n if (!STATSD_HOST) {\n return;\n }\n const payload = Buffer.from(metric);\n getSocket().send(payload, STATSD_PORT, STATSD_HOST, () => {\n // fire-and-forget: errors are intentionally silenced\n });\n}\n\n/**\n * Registers internal MCP middleware that emits a DogStatsD counter over UDP\n * for every tool call. Enabled by default; respects the existing telemetry\n * opt-out (SKYBRIDGE_TELEMETRY_DISABLED, DO_NOT_TRACK, or `skybridge telemetry disable`).\n *\n * Skips registration when the version string contains \"-dev\" (e.g. development\n * builds) or when the version cannot be parsed into major.minor, so that\n * malformed data does not pollute production metrics.\n *\n * Metric (DogStatsD counter format with tags):\n * Requests:1|c|#version:<major>.<minor> — every tools/call\n */\nexport function registerMonitoring(app: {\n withMcpMiddleware(entry: McpMiddlewareEntry): unknown;\n}): void {\n if (isDev || !versionTag) {\n return;\n }\n\n const handler: McpMiddlewareFn = async (_req, _extra, next) => {\n // Check on every call so opt-out takes effect immediately without restart.\n if (!isEnabled()) {\n return next();\n }\n\n try {\n return await next();\n } finally {\n sendMetric(`Requests:1|c|#version:${versionTag}`);\n }\n };\n\n app.withMcpMiddleware({ filter: \"tools/call\", handler });\n}\n"]}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import type { CallToolResult, CancelTaskResult, ClientNotification, ClientRequest, CompleteResult, EmptyResult, GetPromptResult, GetTaskPayloadResult, GetTaskResult, InitializeResult, ListPromptsResult, ListResourcesResult, ListResourceTemplatesResult, ListTasksResult, ListToolsResult, ReadResourceResult, Server, ServerContext, ServerResult } from "@modelcontextprotocol/server";
|
|
2
|
+
import type { AuthInfo, ExtraClaims } from "./auth.js";
|
|
3
|
+
/**
|
|
4
|
+
* The per-request handler context provided by the MCP SDK to request handlers.
|
|
5
|
+
*/
|
|
6
|
+
export type McpExtra<TAuthExtra extends ExtraClaims = ExtraClaims> = Omit<ServerContext, "http"> & {
|
|
7
|
+
http?: Omit<NonNullable<ServerContext["http"]>, "authInfo"> & {
|
|
8
|
+
authInfo?: AuthInfo<TAuthExtra>;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A single MCP middleware function following the onion model.
|
|
13
|
+
* Call `next()` to invoke the next middleware or the final handler.
|
|
14
|
+
* For notifications, `extra` is `undefined` (SDK does not provide extra context)
|
|
15
|
+
* and `next()` resolves to `undefined`.
|
|
16
|
+
*/
|
|
17
|
+
export type McpMiddlewareFn<TAuthExtra extends ExtraClaims = ExtraClaims> = (request: {
|
|
18
|
+
method: string;
|
|
19
|
+
params: Record<string, unknown>;
|
|
20
|
+
}, extra: McpExtra<TAuthExtra> | undefined, next: () => Promise<unknown>) => Promise<unknown> | unknown;
|
|
21
|
+
export declare function captureToolError(extra: McpExtra | undefined, error: unknown): void;
|
|
22
|
+
/**
|
|
23
|
+
* Retrieve the error a tool handler threw during this request, if any.
|
|
24
|
+
*
|
|
25
|
+
* The MCP SDK catches anything a tool handler throws and turns it into an
|
|
26
|
+
* `isError` tool result, so `await next()` in middleware resolves normally and
|
|
27
|
+
* the original `Error` — stack, `cause` — is lost. Skybridge stores it on
|
|
28
|
+
* `extra` (never serialized to the client) so observability middleware can
|
|
29
|
+
* report it:
|
|
30
|
+
*
|
|
31
|
+
* ```ts
|
|
32
|
+
* server.mcpMiddleware("tools/call", async (request, extra, next) => {
|
|
33
|
+
* const result = await next();
|
|
34
|
+
* const error = getToolError(extra);
|
|
35
|
+
* if (error) {
|
|
36
|
+
* Sentry.captureException(error);
|
|
37
|
+
* }
|
|
38
|
+
* return result;
|
|
39
|
+
* });
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function getToolError(extra: McpExtra | undefined): unknown;
|
|
43
|
+
/**
|
|
44
|
+
* MCP methods the server handles (incoming from client).
|
|
45
|
+
*/
|
|
46
|
+
export type McpMethodString = ClientRequest["method"] | ClientNotification["method"];
|
|
47
|
+
/**
|
|
48
|
+
* Resolve the `params` type for a specific MCP method (request or notification)
|
|
49
|
+
* from the SDK's typed unions. Falls back to `Record<string, unknown>` for
|
|
50
|
+
* unknown methods. Used by {@link McpTypedMiddlewareFn} to narrow the request
|
|
51
|
+
* shape in typed middleware.
|
|
52
|
+
*/
|
|
53
|
+
export type McpRequestParams<M extends string> = Extract<ClientRequest, {
|
|
54
|
+
method: M;
|
|
55
|
+
}> extends {
|
|
56
|
+
params: infer P;
|
|
57
|
+
} ? P : Extract<ClientNotification, {
|
|
58
|
+
method: M;
|
|
59
|
+
}> extends {
|
|
60
|
+
params: infer P;
|
|
61
|
+
} ? P : Record<string, unknown>;
|
|
62
|
+
/**
|
|
63
|
+
* Resolve the `extra` arg type for a specific MCP method: {@link McpExtra} for
|
|
64
|
+
* request methods, `undefined` for notification methods (the SDK does not
|
|
65
|
+
* pass extra context for notifications).
|
|
66
|
+
*/
|
|
67
|
+
export type McpExtraFor<M extends string, TAuthExtra extends ExtraClaims = ExtraClaims> = M extends ClientRequest["method"] ? McpExtra<TAuthExtra> : M extends ClientNotification["method"] ? undefined : McpExtra<TAuthExtra> | undefined;
|
|
68
|
+
/** Maps each MCP request method to its SDK result type. */
|
|
69
|
+
interface McpResultMap {
|
|
70
|
+
ping: EmptyResult;
|
|
71
|
+
initialize: InitializeResult;
|
|
72
|
+
"tools/list": ListToolsResult;
|
|
73
|
+
"tools/call": CallToolResult;
|
|
74
|
+
"resources/list": ListResourcesResult;
|
|
75
|
+
"resources/templates/list": ListResourceTemplatesResult;
|
|
76
|
+
"resources/read": ReadResourceResult;
|
|
77
|
+
"resources/subscribe": EmptyResult;
|
|
78
|
+
"resources/unsubscribe": EmptyResult;
|
|
79
|
+
"prompts/list": ListPromptsResult;
|
|
80
|
+
"prompts/get": GetPromptResult;
|
|
81
|
+
"completion/complete": CompleteResult;
|
|
82
|
+
"logging/setLevel": EmptyResult;
|
|
83
|
+
"tasks/get": GetTaskResult;
|
|
84
|
+
"tasks/result": GetTaskPayloadResult;
|
|
85
|
+
"tasks/list": ListTasksResult;
|
|
86
|
+
"tasks/cancel": CancelTaskResult;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Map an MCP method string to its corresponding result type.
|
|
90
|
+
* For request methods, resolves to the specific SDK result type.
|
|
91
|
+
* For wildcard patterns (e.g. `"tools/*"`), resolves to the union of matching result types.
|
|
92
|
+
* For notification methods, resolves to `undefined`.
|
|
93
|
+
* For unknown/unmatched methods, falls back to `ServerResult`.
|
|
94
|
+
*/
|
|
95
|
+
export type McpResultFor<M extends string> = M extends keyof McpResultMap ? McpResultMap[M] : M extends `${infer Prefix}/*` ? [McpResultMap[keyof McpResultMap & `${Prefix}/${string}`]] extends [never] ? M extends ToWildcard<ClientNotification["method"]> ? undefined : ServerResult : McpResultMap[keyof McpResultMap & `${Prefix}/${string}`] : M extends ClientNotification["method"] ? undefined : ServerResult;
|
|
96
|
+
/**
|
|
97
|
+
* Typed middleware function for a specific method. Narrows `request.params`
|
|
98
|
+
* via {@link McpRequestParams}, `extra` via {@link McpExtraFor}, and the
|
|
99
|
+
* resolved value of `next()` via {@link McpResultFor}.
|
|
100
|
+
*/
|
|
101
|
+
export type McpTypedMiddlewareFn<M extends string, TAuthExtra extends ExtraClaims = ExtraClaims> = (request: {
|
|
102
|
+
method: M;
|
|
103
|
+
params: McpRequestParams<M>;
|
|
104
|
+
}, extra: McpExtraFor<M, TAuthExtra>, next: () => Promise<McpResultFor<M>>) => Promise<unknown> | unknown;
|
|
105
|
+
/** Extracts `"prefix/*"` from `"prefix/anything"` — distributive over unions. */
|
|
106
|
+
type ToWildcard<T extends string> = T extends `${infer Prefix}/${string}` ? `${Prefix}/*` : never;
|
|
107
|
+
/** Wildcard prefixes derived from method strings (e.g. `"tools/*"` from `"tools/call"`). */
|
|
108
|
+
export type McpWildcard = ToWildcard<McpMethodString>;
|
|
109
|
+
/** Category keywords matching all requests or all notifications. */
|
|
110
|
+
type McpCategory = "request" | "notification";
|
|
111
|
+
/**
|
|
112
|
+
* A single filter pattern for MCP middleware:
|
|
113
|
+
* - Exact method: `"tools/call"`
|
|
114
|
+
* - Wildcard: `"tools/*"`
|
|
115
|
+
* - Category: `"request"` | `"notification"`
|
|
116
|
+
* - Escape hatch: arbitrary string via `string & {}`
|
|
117
|
+
*/
|
|
118
|
+
type McpMiddlewareFilterPattern = McpMethodString | McpWildcard | McpCategory | (string & {});
|
|
119
|
+
/**
|
|
120
|
+
* Filter determining which MCP methods a middleware applies to.
|
|
121
|
+
* A single pattern or an array of patterns (OR logic).
|
|
122
|
+
*/
|
|
123
|
+
export type McpMiddlewareFilter = McpMiddlewareFilterPattern | McpMiddlewareFilterPattern[];
|
|
124
|
+
/**
|
|
125
|
+
* Internal entry stored for each registered middleware.
|
|
126
|
+
* `filter: null` means catch-all (matches everything).
|
|
127
|
+
*/
|
|
128
|
+
export type McpMiddlewareEntry = {
|
|
129
|
+
filter: McpMiddlewareFilter | null;
|
|
130
|
+
handler: McpMiddlewareFn;
|
|
131
|
+
};
|
|
132
|
+
type HandlerMap = Map<string, (...args: unknown[]) => Promise<unknown>>;
|
|
133
|
+
/**
|
|
134
|
+
* Extract the TS-private `_requestHandlers` and `_notificationHandlers` maps
|
|
135
|
+
* from the SDK's `Server` (extends `Protocol`). These are runtime-accessible
|
|
136
|
+
* but declared `private` in TypeScript.
|
|
137
|
+
*
|
|
138
|
+
* Validates with `instanceof Map` so an incompatible SDK version fails fast
|
|
139
|
+
* instead of silently breaking.
|
|
140
|
+
*/
|
|
141
|
+
export declare function getHandlerMaps(server: Server): {
|
|
142
|
+
requestHandlers: HandlerMap;
|
|
143
|
+
notificationHandlers: HandlerMap;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Check if a single filter pattern matches a given method.
|
|
147
|
+
*
|
|
148
|
+
* - Exact: `"tools/call"` matches only `"tools/call"`
|
|
149
|
+
* - Wildcard: `"tools/*"` matches any method starting with `"tools/"`
|
|
150
|
+
* - Category `"request"`: matches when `isNotification` is false
|
|
151
|
+
* - Category `"notification"`: matches when `isNotification` is true
|
|
152
|
+
*/
|
|
153
|
+
export declare function matchesFilter(method: string, filter: string, isNotification: boolean): boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Build an onion-model middleware chain for a specific method.
|
|
156
|
+
*
|
|
157
|
+
* Filters `entries` to those matching `method`, then composes them
|
|
158
|
+
* so the first registered middleware is the outermost layer.
|
|
159
|
+
* `next()` is guarded against multiple calls within a single middleware.
|
|
160
|
+
*/
|
|
161
|
+
export declare function buildMiddlewareChain(method: string, isNotification: boolean, originalHandler: (...args: unknown[]) => Promise<unknown>, entries: McpMiddlewareEntry[]): (...args: unknown[]) => Promise<unknown>;
|
|
162
|
+
export {};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const TOOL_ERROR = Symbol.for("skybridge.toolError");
|
|
2
|
+
function toolErrorSlot(extra) {
|
|
3
|
+
return extra;
|
|
4
|
+
}
|
|
5
|
+
export function captureToolError(extra, error) {
|
|
6
|
+
const slot = toolErrorSlot(extra);
|
|
7
|
+
if (slot) {
|
|
8
|
+
slot[TOOL_ERROR] = error;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Retrieve the error a tool handler threw during this request, if any.
|
|
13
|
+
*
|
|
14
|
+
* The MCP SDK catches anything a tool handler throws and turns it into an
|
|
15
|
+
* `isError` tool result, so `await next()` in middleware resolves normally and
|
|
16
|
+
* the original `Error` — stack, `cause` — is lost. Skybridge stores it on
|
|
17
|
+
* `extra` (never serialized to the client) so observability middleware can
|
|
18
|
+
* report it:
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* server.mcpMiddleware("tools/call", async (request, extra, next) => {
|
|
22
|
+
* const result = await next();
|
|
23
|
+
* const error = getToolError(extra);
|
|
24
|
+
* if (error) {
|
|
25
|
+
* Sentry.captureException(error);
|
|
26
|
+
* }
|
|
27
|
+
* return result;
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function getToolError(extra) {
|
|
32
|
+
return toolErrorSlot(extra)?.[TOOL_ERROR];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Extract the TS-private `_requestHandlers` and `_notificationHandlers` maps
|
|
36
|
+
* from the SDK's `Server` (extends `Protocol`). These are runtime-accessible
|
|
37
|
+
* but declared `private` in TypeScript.
|
|
38
|
+
*
|
|
39
|
+
* Validates with `instanceof Map` so an incompatible SDK version fails fast
|
|
40
|
+
* instead of silently breaking.
|
|
41
|
+
*/
|
|
42
|
+
export function getHandlerMaps(server) {
|
|
43
|
+
const obj = server;
|
|
44
|
+
if (!("_requestHandlers" in obj && obj._requestHandlers instanceof Map) ||
|
|
45
|
+
!("_notificationHandlers" in obj && obj._notificationHandlers instanceof Map)) {
|
|
46
|
+
throw new Error("Incompatible MCP SDK version: expected _requestHandlers and _notificationHandlers on Server");
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
requestHandlers: obj._requestHandlers,
|
|
50
|
+
notificationHandlers: obj._notificationHandlers,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if a single filter pattern matches a given method.
|
|
55
|
+
*
|
|
56
|
+
* - Exact: `"tools/call"` matches only `"tools/call"`
|
|
57
|
+
* - Wildcard: `"tools/*"` matches any method starting with `"tools/"`
|
|
58
|
+
* - Category `"request"`: matches when `isNotification` is false
|
|
59
|
+
* - Category `"notification"`: matches when `isNotification` is true
|
|
60
|
+
*/
|
|
61
|
+
export function matchesFilter(method, filter, isNotification) {
|
|
62
|
+
if (filter === "request") {
|
|
63
|
+
return !isNotification;
|
|
64
|
+
}
|
|
65
|
+
if (filter === "notification") {
|
|
66
|
+
return isNotification;
|
|
67
|
+
}
|
|
68
|
+
if (filter.endsWith("/*")) {
|
|
69
|
+
const prefix = filter.slice(0, -1); // "tools/*" → "tools/"
|
|
70
|
+
return method.startsWith(prefix);
|
|
71
|
+
}
|
|
72
|
+
return method === filter;
|
|
73
|
+
}
|
|
74
|
+
function matchesAnyFilter(method, filter, isNotification) {
|
|
75
|
+
if (filter === null) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
if (typeof filter === "string") {
|
|
79
|
+
return matchesFilter(method, filter, isNotification);
|
|
80
|
+
}
|
|
81
|
+
return filter.some((pattern) => matchesFilter(method, pattern, isNotification));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build an onion-model middleware chain for a specific method.
|
|
85
|
+
*
|
|
86
|
+
* Filters `entries` to those matching `method`, then composes them
|
|
87
|
+
* so the first registered middleware is the outermost layer.
|
|
88
|
+
* `next()` is guarded against multiple calls within a single middleware.
|
|
89
|
+
*/
|
|
90
|
+
export function buildMiddlewareChain(method, isNotification, originalHandler, entries) {
|
|
91
|
+
const applicable = entries.filter((entry) => matchesAnyFilter(method, entry.filter, isNotification));
|
|
92
|
+
if (applicable.length === 0) {
|
|
93
|
+
return originalHandler;
|
|
94
|
+
}
|
|
95
|
+
return (...args) => {
|
|
96
|
+
const rawRequest = args[0];
|
|
97
|
+
// SDK calls request handlers as handler(request, extra) but
|
|
98
|
+
// notification handlers as handler(notification) — no extra arg.
|
|
99
|
+
const extra = isNotification ? undefined : args[1];
|
|
100
|
+
const mcpRequest = {
|
|
101
|
+
method,
|
|
102
|
+
params: rawRequest?.params ?? {},
|
|
103
|
+
};
|
|
104
|
+
let index = 0;
|
|
105
|
+
const executeLayer = () => {
|
|
106
|
+
const entry = applicable[index++];
|
|
107
|
+
if (!entry) {
|
|
108
|
+
if (rawRequest) {
|
|
109
|
+
rawRequest.params = mcpRequest.params;
|
|
110
|
+
}
|
|
111
|
+
return originalHandler(...args);
|
|
112
|
+
}
|
|
113
|
+
let nextCalled = false;
|
|
114
|
+
const next = () => {
|
|
115
|
+
if (nextCalled) {
|
|
116
|
+
throw new Error(`next() called multiple times in middleware for "${method}"`);
|
|
117
|
+
}
|
|
118
|
+
nextCalled = true;
|
|
119
|
+
return executeLayer();
|
|
120
|
+
};
|
|
121
|
+
return Promise.resolve(entry.handler(mcpRequest, extra, next));
|
|
122
|
+
};
|
|
123
|
+
return executeLayer();
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=middleware.js.map
|