skybridge 0.0.0-dev.f391982 → 0.0.0-dev.f3a1db3
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 +132 -124
- package/dist/cli/build-helpers.d.ts +7 -0
- package/dist/cli/build-helpers.js +82 -0
- package/dist/cli/build-helpers.js.map +1 -0
- package/dist/cli/build-helpers.test.js +64 -0
- package/dist/cli/build-helpers.test.js.map +1 -0
- package/dist/cli/detect-port.d.ts +2 -2
- package/dist/cli/detect-port.js +9 -20
- package/dist/cli/detect-port.js.map +1 -1
- package/dist/cli/header.js.map +1 -1
- package/dist/cli/resolve-views-dir.d.ts +1 -0
- package/dist/cli/resolve-views-dir.js +17 -0
- package/dist/cli/resolve-views-dir.js.map +1 -0
- package/dist/cli/run-command.js.map +1 -1
- package/dist/cli/telemetry.js.map +1 -1
- 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.d.ts +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.d.ts +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.d.ts +1 -0
- package/dist/cli/tunnel.test.js +190 -0
- package/dist/cli/tunnel.test.js.map +1 -0
- package/dist/cli/types.js.map +1 -1
- package/dist/cli/use-execute-steps.js.map +1 -1
- package/dist/cli/use-messages.js.map +1 -1
- package/dist/cli/use-nodemon.js +11 -2
- package/dist/cli/use-nodemon.js.map +1 -1
- 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 +1 -1
- package/dist/cli/use-tunnel.js +102 -68
- package/dist/cli/use-tunnel.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/build.d.ts +0 -1
- package/dist/commands/build.js +41 -18
- package/dist/commands/build.js.map +1 -1
- 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 +1 -0
- package/dist/commands/dev.js +49 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/start.js +7 -1
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/telemetry/disable.js.map +1 -1
- package/dist/commands/telemetry/enable.js.map +1 -1
- package/dist/commands/telemetry/status.js.map +1 -1
- package/dist/server/asset-base-url-transform-plugin.d.ts +1 -0
- package/dist/server/asset-base-url-transform-plugin.js +17 -2
- package/dist/server/asset-base-url-transform-plugin.js.map +1 -1
- package/dist/server/asset-base-url-transform-plugin.test.js +80 -1
- package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -1
- package/dist/server/auth/discovery.d.ts +32 -0
- package/dist/server/auth/discovery.js +56 -0
- package/dist/server/auth/discovery.js.map +1 -0
- package/dist/server/auth/discovery.test.d.ts +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 +18 -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 +18 -0
- package/dist/server/auth/providers/auth0.js +31 -0
- package/dist/server/auth/providers/auth0.js.map +1 -0
- package/dist/server/auth/providers/auth0.test.d.ts +1 -0
- package/dist/server/auth/providers/auth0.test.js +48 -0
- package/dist/server/auth/providers/auth0.test.js.map +1 -0
- package/dist/server/auth/providers/clerk.d.ts +14 -0
- package/dist/server/auth/providers/clerk.js +16 -0
- package/dist/server/auth/providers/clerk.js.map +1 -0
- package/dist/server/auth/providers/clerk.test.d.ts +1 -0
- package/dist/server/auth/providers/clerk.test.js +28 -0
- package/dist/server/auth/providers/clerk.test.js.map +1 -0
- package/dist/server/auth/providers/custom.d.ts +24 -0
- package/dist/server/auth/providers/custom.js +37 -0
- package/dist/server/auth/providers/custom.js.map +1 -0
- package/dist/server/auth/providers/custom.test.d.ts +1 -0
- package/dist/server/auth/providers/custom.test.js +107 -0
- package/dist/server/auth/providers/custom.test.js.map +1 -0
- package/dist/server/auth/providers/descope.d.ts +15 -0
- package/dist/server/auth/providers/descope.js +33 -0
- package/dist/server/auth/providers/descope.js.map +1 -0
- package/dist/server/auth/providers/descope.test.d.ts +1 -0
- package/dist/server/auth/providers/descope.test.js +37 -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.d.ts +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 +12 -0
- package/dist/server/auth/providers/stytch.js +13 -0
- package/dist/server/auth/providers/stytch.js.map +1 -0
- package/dist/server/auth/providers/workos.d.ts +11 -0
- package/dist/server/auth/providers/workos.js +12 -0
- package/dist/server/auth/providers/workos.js.map +1 -0
- package/dist/server/auth/setup.d.ts +4 -0
- package/dist/server/auth/setup.js +51 -0
- package/dist/server/auth/setup.js.map +1 -0
- package/dist/server/auth/setup.test.d.ts +1 -0
- package/dist/server/auth/setup.test.js +185 -0
- package/dist/server/auth/setup.test.js.map +1 -0
- package/dist/server/auth/verify.d.ts +12 -0
- package/dist/server/auth/verify.js +38 -0
- package/dist/server/auth/verify.js.map +1 -0
- package/dist/server/auth/verify.test.d.ts +1 -0
- package/dist/server/auth/verify.test.js +100 -0
- package/dist/server/auth/verify.test.js.map +1 -0
- package/dist/server/auth.d.ts +20 -0
- package/dist/server/auth.js +28 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/build-manifest.test.d.ts +1 -0
- package/dist/server/build-manifest.test.js +27 -0
- package/dist/server/build-manifest.test.js.map +1 -0
- package/dist/server/content-helpers.d.ts +40 -0
- package/dist/server/content-helpers.js +33 -0
- package/dist/server/content-helpers.js.map +1 -1
- package/dist/server/content-helpers.test.js.map +1 -1
- package/dist/server/express.d.ts +1 -5
- package/dist/server/express.js +31 -7
- package/dist/server/express.js.map +1 -1
- package/dist/server/express.test.js +271 -69
- package/dist/server/express.test.js.map +1 -1
- 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/index.d.ts +11 -2
- package/dist/server/index.js +9 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/inferUtilityTypes.d.ts +6 -6
- package/dist/server/inferUtilityTypes.js.map +1 -1
- package/dist/server/metric.js.map +1 -1
- package/dist/server/middleware.d.ts +16 -3
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/middleware.test-d.js.map +1 -1
- package/dist/server/middleware.test.js.map +1 -1
- 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 +245 -7
- package/dist/server/server.js +355 -171
- package/dist/server/server.js.map +1 -1
- package/dist/server/templateHelper.d.ts +0 -2
- package/dist/server/templateHelper.js +3 -22
- package/dist/server/templateHelper.js.map +1 -1
- package/dist/server/templates.generated.d.ts +4 -0
- package/dist/server/templates.generated.js +47 -0
- package/dist/server/templates.generated.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-resource-resolution.test.d.ts +6 -0
- package/dist/server/view-resource-resolution.test.js +103 -0
- package/dist/server/view-resource-resolution.test.js.map +1 -0
- package/dist/server/viewsDevServer.js.map +1 -1
- package/dist/test/utils.js.map +1 -1
- package/dist/test/view.test.js +153 -140
- package/dist/test/view.test.js.map +1 -1
- package/dist/version.js +1 -3
- package/dist/version.js.map +1 -1
- package/dist/web/bridges/adaptor.d.ts +51 -0
- package/dist/web/bridges/adaptor.js +310 -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 +197 -0
- package/dist/web/bridges/adaptor.test.js.map +1 -0
- package/dist/web/bridges/apps-sdk/bridge.d.ts +6 -1
- package/dist/web/bridges/apps-sdk/bridge.js +15 -3
- package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
- package/dist/web/bridges/apps-sdk/index.d.ts +0 -1
- package/dist/web/bridges/apps-sdk/index.js +0 -1
- package/dist/web/bridges/apps-sdk/index.js.map +1 -1
- package/dist/web/bridges/apps-sdk/types.d.ts +8 -1
- package/dist/web/bridges/apps-sdk/types.js.map +1 -1
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +11 -0
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +11 -0
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
- package/dist/web/bridges/get-adaptor.d.ts +7 -0
- package/dist/web/bridges/get-adaptor.js +9 -7
- package/dist/web/bridges/get-adaptor.js.map +1 -1
- 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.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.d.ts +15 -2
- package/dist/web/bridges/mcp-app/bridge.js +68 -4
- package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
- 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 +0 -1
- package/dist/web/bridges/mcp-app/index.js +0 -1
- package/dist/web/bridges/mcp-app/index.js.map +1 -1
- package/dist/web/bridges/mcp-app/types.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +12 -0
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js +12 -0
- 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.map +1 -1
- 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 +113 -8
- package/dist/web/bridges/types.js +14 -1
- package/dist/web/bridges/types.js.map +1 -1
- 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 +5 -0
- package/dist/web/bridges/use-host-context.js +5 -0
- package/dist/web/bridges/use-host-context.js.map +1 -1
- package/dist/web/components/modal-provider.js +4 -3
- package/dist/web/components/modal-provider.js.map +1 -1
- package/dist/web/create-store.d.ts +26 -0
- package/dist/web/create-store.js +35 -9
- package/dist/web/create-store.js.map +1 -1
- package/dist/web/create-store.test.js +22 -21
- package/dist/web/create-store.test.js.map +1 -1
- package/dist/web/data-llm.d.ts +34 -1
- package/dist/web/data-llm.js +31 -3
- package/dist/web/data-llm.js.map +1 -1
- package/dist/web/data-llm.test.js +31 -27
- package/dist/web/data-llm.test.js.map +1 -1
- package/dist/web/generate-helpers.d.ts +2 -0
- package/dist/web/generate-helpers.js +2 -0
- package/dist/web/generate-helpers.js.map +1 -1
- package/dist/web/generate-helpers.test-d.js +11 -9
- package/dist/web/generate-helpers.test-d.js.map +1 -1
- package/dist/web/generate-helpers.test.js.map +1 -1
- package/dist/web/helpers/state.d.ts +2 -2
- package/dist/web/helpers/state.js +11 -11
- package/dist/web/helpers/state.js.map +1 -1
- package/dist/web/helpers/state.test.js +9 -9
- package/dist/web/helpers/state.test.js.map +1 -1
- package/dist/web/hooks/index.d.ts +5 -1
- package/dist/web/hooks/index.js +5 -1
- package/dist/web/hooks/index.js.map +1 -1
- package/dist/web/hooks/test/utils.d.ts +6 -2
- package/dist/web/hooks/test/utils.js +13 -2
- package/dist/web/hooks/test/utils.js.map +1 -1
- package/dist/web/hooks/use-call-tool.d.ts +45 -0
- package/dist/web/hooks/use-call-tool.js +28 -0
- package/dist/web/hooks/use-call-tool.js.map +1 -1
- package/dist/web/hooks/use-call-tool.test-d.js.map +1 -1
- package/dist/web/hooks/use-call-tool.test.js +62 -27
- package/dist/web/hooks/use-call-tool.test.js.map +1 -1
- package/dist/web/hooks/use-display-mode.d.ts +20 -0
- package/dist/web/hooks/use-display-mode.js +20 -0
- package/dist/web/hooks/use-display-mode.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test-d.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test.js +56 -20
- package/dist/web/hooks/use-display-mode.test.js.map +1 -1
- package/dist/web/hooks/use-download.d.ts +5 -0
- package/dist/web/hooks/use-download.js +8 -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-files.d.ts +32 -0
- package/dist/web/hooks/use-files.js +32 -0
- package/dist/web/hooks/use-files.js.map +1 -1
- package/dist/web/hooks/use-files.test.js +10 -2
- package/dist/web/hooks/use-files.test.js.map +1 -1
- package/dist/web/hooks/use-layout.d.ts +2 -0
- package/dist/web/hooks/use-layout.js +2 -0
- package/dist/web/hooks/use-layout.js.map +1 -1
- package/dist/web/hooks/use-layout.test.js +59 -26
- package/dist/web/hooks/use-layout.test.js.map +1 -1
- package/dist/web/hooks/use-open-external.d.ts +17 -0
- package/dist/web/hooks/use-open-external.js +16 -0
- package/dist/web/hooks/use-open-external.js.map +1 -1
- package/dist/web/hooks/use-open-external.test.js +13 -3
- package/dist/web/hooks/use-open-external.test.js.map +1 -1
- package/dist/web/hooks/use-register-view-tool.d.ts +38 -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 +16 -1
- package/dist/web/hooks/use-request-modal.js +19 -4
- package/dist/web/hooks/use-request-modal.js.map +1 -1
- package/dist/web/hooks/use-request-modal.test.js +11 -1
- package/dist/web/hooks/use-request-modal.test.js.map +1 -1
- 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 +19 -1
- package/dist/web/hooks/use-send-follow-up-message.js +19 -2
- package/dist/web/hooks/use-send-follow-up-message.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.d.ts +17 -0
- package/dist/web/hooks/use-set-open-in-app-url.js +17 -0
- package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.test.js +28 -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 +53 -2
- package/dist/web/hooks/use-tool-info.js +30 -7
- package/dist/web/hooks/use-tool-info.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test-d.js +11 -29
- package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test.js +42 -32
- package/dist/web/hooks/use-tool-info.test.js.map +1 -1
- package/dist/web/hooks/use-user.d.ts +2 -0
- package/dist/web/hooks/use-user.js +2 -0
- package/dist/web/hooks/use-user.js.map +1 -1
- package/dist/web/hooks/use-user.test.js +81 -35
- package/dist/web/hooks/use-user.test.js.map +1 -1
- package/dist/web/hooks/use-view-state.d.ts +25 -0
- package/dist/web/hooks/use-view-state.js +32 -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-widget-state.test.js → use-view-state.test.js} +23 -19
- package/dist/web/hooks/use-view-state.test.js.map +1 -0
- package/dist/web/index.d.ts +1 -3
- package/dist/web/index.js +1 -2
- package/dist/web/index.js.map +1 -1
- package/dist/web/mount-view.d.ts +20 -0
- package/dist/web/{mount-widget.js → mount-view.js} +21 -2
- package/dist/web/mount-view.js.map +1 -0
- package/dist/web/plugin/data-llm.test.js.map +1 -1
- package/dist/web/plugin/plugin.d.ts +28 -0
- package/dist/web/plugin/plugin.js +65 -17
- package/dist/web/plugin/plugin.js.map +1 -1
- package/dist/web/plugin/scan-views.d.ts +8 -0
- package/dist/web/plugin/scan-views.js +26 -8
- package/dist/web/plugin/scan-views.js.map +1 -1
- package/dist/web/plugin/scan-views.test.js +33 -1
- package/dist/web/plugin/scan-views.test.js.map +1 -1
- package/dist/web/plugin/transform-data-llm.js.map +1 -1
- package/dist/web/plugin/transform-data-llm.test.js.map +1 -1
- package/dist/web/plugin/validate-view.js.map +1 -1
- package/dist/web/plugin/validate-view.test.js.map +1 -1
- package/dist/web/proxy.js.map +1 -1
- package/dist/web/types.d.ts +4 -0
- package/dist/web/types.js.map +1 -1
- package/package.json +21 -8
- package/dist/server/templates/development.hbs +0 -12
- package/dist/server/templates/production.hbs +0 -6
- package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -24
- package/dist/web/bridges/apps-sdk/adaptor.js +0 -87
- package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
- package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -48
- package/dist/web/bridges/mcp-app/adaptor.js +0 -268
- package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
- package/dist/web/hooks/use-widget-state.d.ts +0 -4
- package/dist/web/hooks/use-widget-state.js +0 -32
- package/dist/web/hooks/use-widget-state.js.map +0 -1
- package/dist/web/hooks/use-widget-state.test.js.map +0 -1
- package/dist/web/mount-widget.d.ts +0 -1
- package/dist/web/mount-widget.js.map +0 -1
- /package/dist/{web/hooks/use-widget-state.test.d.ts → cli/build-helpers.test.d.ts} +0 -0
package/dist/test/view.test.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
|
+
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
2
4
|
import { afterEach, beforeEach, describe, expect, it, vi, } from "vitest";
|
|
5
|
+
import { McpServer as McpServerClass } from "../server/server.js";
|
|
3
6
|
import { createMockExtra, createMockMcpServer, resetTestEnv, setTestEnv, } from "./utils.js";
|
|
4
7
|
const mockManifest = {
|
|
5
|
-
"skybridge:view:my-
|
|
6
|
-
file: "assets/my-
|
|
7
|
-
name: "my-
|
|
8
|
+
"skybridge:view:my-view": {
|
|
9
|
+
file: "assets/my-view-abc123.js",
|
|
10
|
+
name: "my-view",
|
|
8
11
|
isEntry: true,
|
|
9
12
|
},
|
|
10
|
-
"skybridge:view:folder-
|
|
11
|
-
file: "assets/folder-
|
|
12
|
-
name: "folder-
|
|
13
|
+
"skybridge:view:folder-view": {
|
|
14
|
+
file: "assets/folder-view-def456.js",
|
|
15
|
+
name: "folder-view",
|
|
13
16
|
isEntry: true,
|
|
14
17
|
},
|
|
15
18
|
"style.css": { file: "style.css" },
|
|
@@ -57,10 +60,10 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
57
60
|
it("should generate correct HTML for development mode", async () => {
|
|
58
61
|
setTestEnv({ NODE_ENV: "development" });
|
|
59
62
|
server.registerTool({
|
|
60
|
-
name: "my-
|
|
63
|
+
name: "my-view",
|
|
61
64
|
description: "Test tool",
|
|
62
65
|
view: {
|
|
63
|
-
component: "my-
|
|
66
|
+
component: "my-view",
|
|
64
67
|
description: "Test view",
|
|
65
68
|
},
|
|
66
69
|
}, vi.fn());
|
|
@@ -71,20 +74,24 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
71
74
|
const serverUrl = `http://${host}`;
|
|
72
75
|
const hmrUrl = `ws://${host}`;
|
|
73
76
|
const mockExtra = createMockExtra(host);
|
|
74
|
-
const result = await appsSdkResourceCallback(new URL("ui://
|
|
77
|
+
const result = await appsSdkResourceCallback(new URL("ui://views/ext-apps/my-view.html"), mockExtra);
|
|
75
78
|
expect(mockRegisterTool).toHaveBeenCalled();
|
|
76
79
|
expect(result).toEqual({
|
|
77
80
|
contents: [
|
|
78
81
|
{
|
|
79
|
-
uri: "ui://
|
|
80
|
-
mimeType: "text/html
|
|
82
|
+
uri: "ui://views/ext-apps/my-view.html",
|
|
83
|
+
mimeType: "text/html;profile=mcp-app",
|
|
81
84
|
text: expect.stringContaining('<div id="root"></div>'),
|
|
82
85
|
_meta: {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
ui: {
|
|
87
|
+
csp: {
|
|
88
|
+
resourceDomains: [serverUrl],
|
|
89
|
+
connectDomains: [serverUrl, hmrUrl],
|
|
90
|
+
baseUriDomains: [serverUrl],
|
|
91
|
+
},
|
|
92
|
+
domain: serverUrl,
|
|
93
|
+
description: "Test view",
|
|
86
94
|
},
|
|
87
|
-
"openai/widgetDomain": serverUrl,
|
|
88
95
|
"openai/widgetDescription": "Test view",
|
|
89
96
|
},
|
|
90
97
|
},
|
|
@@ -92,15 +99,15 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
92
99
|
});
|
|
93
100
|
expect(result.contents[0]?.text).toContain(`${serverUrl}/assets/@react-refresh`);
|
|
94
101
|
expect(result.contents[0]?.text).toContain(`${serverUrl}/@vite/client`);
|
|
95
|
-
expect(result.contents[0]?.text).toContain(`${serverUrl}/_skybridge/view/my-
|
|
102
|
+
expect(result.contents[0]?.text).toContain(`${serverUrl}/_skybridge/view/my-view`);
|
|
96
103
|
});
|
|
97
104
|
it("should generate correct HTML for production mode", async () => {
|
|
98
105
|
setTestEnv({ NODE_ENV: "production" });
|
|
99
106
|
server.registerTool({
|
|
100
|
-
name: "my-
|
|
107
|
+
name: "my-view",
|
|
101
108
|
description: "Test tool",
|
|
102
109
|
view: {
|
|
103
|
-
component: "my-
|
|
110
|
+
component: "my-view",
|
|
104
111
|
description: "Test view",
|
|
105
112
|
},
|
|
106
113
|
}, vi.fn());
|
|
@@ -110,20 +117,24 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
110
117
|
const host = "myapp.com";
|
|
111
118
|
const serverUrl = `https://${host}`;
|
|
112
119
|
const mockExtra = createMockExtra(host);
|
|
113
|
-
const versionedUri = `ui://
|
|
120
|
+
const versionedUri = `ui://views/ext-apps/my-view.html${expectedVersionParam("assets/my-view-abc123.js", "style.css")}`;
|
|
114
121
|
const result = await appsSdkResourceCallback(new URL(versionedUri), mockExtra);
|
|
115
122
|
expect(result).toEqual({
|
|
116
123
|
contents: [
|
|
117
124
|
{
|
|
118
125
|
uri: versionedUri,
|
|
119
|
-
mimeType: "text/html
|
|
126
|
+
mimeType: "text/html;profile=mcp-app",
|
|
120
127
|
text: expect.stringContaining('<div id="root"></div>'),
|
|
121
128
|
_meta: {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
129
|
+
ui: {
|
|
130
|
+
csp: {
|
|
131
|
+
resourceDomains: [serverUrl],
|
|
132
|
+
connectDomains: [serverUrl],
|
|
133
|
+
baseUriDomains: [serverUrl],
|
|
134
|
+
},
|
|
135
|
+
domain: serverUrl,
|
|
136
|
+
description: "Test view",
|
|
125
137
|
},
|
|
126
|
-
"openai/widgetDomain": serverUrl,
|
|
127
138
|
"openai/widgetDescription": "Test view",
|
|
128
139
|
},
|
|
129
140
|
},
|
|
@@ -131,18 +142,18 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
131
142
|
});
|
|
132
143
|
expect(result.contents[0]?.text).not.toContain(`${serverUrl}/assets/@react-refresh`);
|
|
133
144
|
expect(result.contents[0]?.text).not.toContain(`${serverUrl}@vite/client`);
|
|
134
|
-
expect(result.contents[0]?.text).toContain(`${serverUrl}/assets/assets/my-
|
|
145
|
+
expect(result.contents[0]?.text).toContain(`${serverUrl}/assets/assets/my-view-abc123.js`);
|
|
135
146
|
expect(result.contents[0]?.text).toContain(`${serverUrl}/assets/style.css`);
|
|
136
147
|
});
|
|
137
148
|
it("should prefer x-alpic-forwarded-url when hashing Claude view domains", async () => {
|
|
138
149
|
setTestEnv({ NODE_ENV: "production" });
|
|
139
150
|
server.registerTool({
|
|
140
|
-
name: "my-
|
|
151
|
+
name: "my-view",
|
|
141
152
|
description: "Test tool",
|
|
142
|
-
view: { component: "my-
|
|
153
|
+
view: { component: "my-view", description: "Test view" },
|
|
143
154
|
}, vi.fn());
|
|
144
155
|
const extAppsResourceCallback = mockRegisterResource.mock
|
|
145
|
-
.calls[
|
|
156
|
+
.calls[0]?.[3];
|
|
146
157
|
expect(extAppsResourceCallback).toBeDefined();
|
|
147
158
|
const forwardedUrl = "https://everything-3a2c1264.staging.alpic.live/mcp?foo=bar";
|
|
148
159
|
const expectedDomain = `${crypto
|
|
@@ -150,7 +161,7 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
150
161
|
.update(forwardedUrl)
|
|
151
162
|
.digest("hex")
|
|
152
163
|
.slice(0, 32)}.claudemcpcontent.com`;
|
|
153
|
-
const result = await extAppsResourceCallback(new URL(`ui://
|
|
164
|
+
const result = await extAppsResourceCallback(new URL(`ui://views/ext-apps/my-view.html${expectedVersionParam("assets/my-view-abc123.js", "style.css")}`), createMockExtra("localhost:3000", {
|
|
154
165
|
headers: {
|
|
155
166
|
"user-agent": "Claude-User",
|
|
156
167
|
"x-alpic-forwarded-url": forwardedUrl,
|
|
@@ -167,52 +178,30 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
167
178
|
description: "Test view",
|
|
168
179
|
domain: expectedDomain,
|
|
169
180
|
},
|
|
181
|
+
"openai/widgetDescription": "Test view",
|
|
170
182
|
});
|
|
171
183
|
});
|
|
172
|
-
it("should register
|
|
184
|
+
it("should register a single ext-apps resource", async () => {
|
|
173
185
|
server.registerTool({
|
|
174
|
-
name: "my-
|
|
186
|
+
name: "my-view",
|
|
175
187
|
description: "Test tool",
|
|
176
188
|
view: {
|
|
177
|
-
component: "my-
|
|
189
|
+
component: "my-view",
|
|
178
190
|
description: "Test view",
|
|
179
191
|
prefersBorder: true,
|
|
180
192
|
},
|
|
181
193
|
}, vi.fn());
|
|
182
|
-
expect(mockRegisterResource).toHaveBeenCalledTimes(
|
|
183
|
-
const
|
|
194
|
+
expect(mockRegisterResource).toHaveBeenCalledTimes(1);
|
|
195
|
+
const resourceCallback = mockRegisterResource.mock
|
|
184
196
|
.calls[0]?.[3];
|
|
185
197
|
const host = "localhost:3000";
|
|
186
198
|
const serverUrl = `http://${host}`;
|
|
187
199
|
const hmrUrl = `ws://${host}`;
|
|
188
|
-
const
|
|
189
|
-
expect(
|
|
190
|
-
contents: [
|
|
191
|
-
{
|
|
192
|
-
uri: "ui://widgets/apps-sdk/my-widget.html",
|
|
193
|
-
mimeType: "text/html+skybridge",
|
|
194
|
-
text: expect.stringContaining('<div id="root"></div>'),
|
|
195
|
-
_meta: {
|
|
196
|
-
"openai/widgetCSP": {
|
|
197
|
-
resource_domains: [serverUrl],
|
|
198
|
-
connect_domains: [serverUrl, hmrUrl],
|
|
199
|
-
},
|
|
200
|
-
"openai/widgetDomain": serverUrl,
|
|
201
|
-
"openai/widgetDescription": "Test view",
|
|
202
|
-
"openai/widgetPrefersBorder": true,
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
],
|
|
206
|
-
});
|
|
207
|
-
expect(appsSdkResult.contents[0]?.text).toContain('window.skybridge = { hostType: "apps-sdk", serverUrl: "http://localhost:3000" };');
|
|
208
|
-
const extAppsResourceCallback = mockRegisterResource.mock
|
|
209
|
-
.calls[1]?.[3];
|
|
210
|
-
expect(extAppsResourceCallback).toBeDefined();
|
|
211
|
-
const extAppsResult = await extAppsResourceCallback(new URL("ui://widgets/ext-apps/my-widget.html"), createMockExtra(host));
|
|
212
|
-
expect(extAppsResult).toEqual({
|
|
200
|
+
const result = await resourceCallback(new URL("ui://views/ext-apps/my-view.html"), createMockExtra(host));
|
|
201
|
+
expect(result).toEqual({
|
|
213
202
|
contents: [
|
|
214
203
|
{
|
|
215
|
-
uri: "ui://
|
|
204
|
+
uri: "ui://views/ext-apps/my-view.html",
|
|
216
205
|
mimeType: "text/html;profile=mcp-app",
|
|
217
206
|
text: expect.stringContaining('<div id="root"></div>'),
|
|
218
207
|
_meta: {
|
|
@@ -226,116 +215,93 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
226
215
|
description: "Test view",
|
|
227
216
|
prefersBorder: true,
|
|
228
217
|
},
|
|
218
|
+
"openai/widgetDescription": "Test view",
|
|
229
219
|
},
|
|
230
220
|
},
|
|
231
221
|
],
|
|
232
222
|
});
|
|
233
|
-
expect(
|
|
223
|
+
expect(result.contents[0]?.text).toContain('window.skybridge = { hostType: "mcp-app", serverUrl: "http://localhost:3000" };');
|
|
234
224
|
});
|
|
235
|
-
it("should
|
|
225
|
+
it("should advertise the single resource via ui.resourceUri only (no openai/outputTemplate)", async () => {
|
|
236
226
|
server.registerTool({
|
|
237
|
-
name: "my-
|
|
227
|
+
name: "my-view",
|
|
238
228
|
description: "Test tool",
|
|
239
|
-
view: { component: "my-
|
|
229
|
+
view: { component: "my-view", description: "Test view" },
|
|
240
230
|
}, vi.fn());
|
|
241
|
-
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
expect(toolConfig._meta
|
|
245
|
-
expect(toolConfig._meta?.
|
|
246
|
-
resourceUri: "ui://widgets/ext-apps/my-widget.html",
|
|
247
|
-
});
|
|
231
|
+
const toolConfig = mockRegisterTool.mock.calls[0]?.[1];
|
|
232
|
+
const uri = "ui://views/ext-apps/my-view.html";
|
|
233
|
+
expect(toolConfig._meta?.ui?.resourceUri).toBe(uri);
|
|
234
|
+
expect(toolConfig._meta?.["ui/resourceUri"]).toBe(uri);
|
|
235
|
+
expect(toolConfig._meta?.["openai/outputTemplate"]).toBeUndefined();
|
|
248
236
|
});
|
|
249
|
-
it("
|
|
237
|
+
it("treats the deprecated hosts option as a no-op (always the single resource)", async () => {
|
|
250
238
|
server.registerTool({
|
|
251
|
-
name: "my-
|
|
239
|
+
name: "my-view",
|
|
252
240
|
description: "Test tool",
|
|
253
241
|
view: {
|
|
254
|
-
component: "my-
|
|
242
|
+
component: "my-view",
|
|
255
243
|
description: "Test view",
|
|
256
244
|
hosts: ["apps-sdk"],
|
|
257
245
|
},
|
|
258
246
|
}, vi.fn());
|
|
259
|
-
expect(
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
expect(toolConfig._meta).
|
|
263
|
-
expect(toolConfig._meta?.["openai/outputTemplate"]).toBe("ui://widgets/apps-sdk/my-widget.html");
|
|
247
|
+
expect(mockRegisterResource).toHaveBeenCalledTimes(1);
|
|
248
|
+
const toolConfig = mockRegisterTool.mock.calls[0]?.[1];
|
|
249
|
+
expect(toolConfig._meta?.ui?.resourceUri).toBe("ui://views/ext-apps/my-view.html");
|
|
250
|
+
expect(toolConfig._meta?.["openai/outputTemplate"]).toBeUndefined();
|
|
264
251
|
});
|
|
265
252
|
it("should not version view URIs in development", () => {
|
|
266
253
|
server.registerTool({
|
|
267
|
-
name: "my-
|
|
254
|
+
name: "my-view",
|
|
268
255
|
description: "Test tool",
|
|
269
|
-
view: { component: "my-
|
|
256
|
+
view: { component: "my-view", description: "Test view" },
|
|
270
257
|
}, vi.fn());
|
|
271
258
|
const toolConfig = mockRegisterTool.mock.calls[0]?.[1];
|
|
272
|
-
expect(toolConfig._meta?.["openai/outputTemplate"]).
|
|
273
|
-
expect(toolConfig._meta?.ui?.resourceUri).toBe("ui://
|
|
274
|
-
// The URI registered with the resource handler must match
|
|
275
|
-
//
|
|
276
|
-
expect(mockRegisterResource.mock.calls[0]?.[1]).toBe("ui://
|
|
277
|
-
expect(mockRegisterResource.mock.calls[1]?.[1]).toBe("ui://widgets/ext-apps/my-widget.html");
|
|
259
|
+
expect(toolConfig._meta?.["openai/outputTemplate"]).toBeUndefined();
|
|
260
|
+
expect(toolConfig._meta?.ui?.resourceUri).toBe("ui://views/ext-apps/my-view.html");
|
|
261
|
+
// The URI registered with the resource handler must match ui.resourceUri
|
|
262
|
+
// exactly so the SDK can resolve `resources/read` requests.
|
|
263
|
+
expect(mockRegisterResource.mock.calls[0]?.[1]).toBe("ui://views/ext-apps/my-view.html");
|
|
278
264
|
});
|
|
279
265
|
it("should append a stable content hash to view URIs in production", () => {
|
|
280
266
|
setTestEnv({ NODE_ENV: "production" });
|
|
281
267
|
server.registerTool({
|
|
282
|
-
name: "my-
|
|
268
|
+
name: "my-view",
|
|
283
269
|
description: "Test tool",
|
|
284
|
-
view: { component: "my-
|
|
270
|
+
view: { component: "my-view", description: "Test view" },
|
|
285
271
|
}, vi.fn());
|
|
286
|
-
const expected = expectedVersionParam("assets/my-
|
|
272
|
+
const expected = expectedVersionParam("assets/my-view-abc123.js", "style.css");
|
|
287
273
|
const toolConfig = mockRegisterTool.mock.calls[0]?.[1];
|
|
288
|
-
expect(toolConfig._meta?.["openai/outputTemplate"]).
|
|
289
|
-
expect(toolConfig._meta?.ui?.resourceUri).toBe(`ui://
|
|
290
|
-
expect(mockRegisterResource.mock.calls[0]?.[1]).toBe(`ui://
|
|
291
|
-
expect(mockRegisterResource.mock.calls[1]?.[1]).toBe(`ui://widgets/ext-apps/my-widget.html${expected}`);
|
|
274
|
+
expect(toolConfig._meta?.["openai/outputTemplate"]).toBeUndefined();
|
|
275
|
+
expect(toolConfig._meta?.ui?.resourceUri).toBe(`ui://views/ext-apps/my-view.html${expected}`);
|
|
276
|
+
expect(mockRegisterResource.mock.calls[0]?.[1]).toBe(`ui://views/ext-apps/my-view.html${expected}`);
|
|
292
277
|
});
|
|
293
278
|
it("should produce different version params for views with different bundles", () => {
|
|
294
279
|
setTestEnv({ NODE_ENV: "production" });
|
|
295
280
|
server.registerTool({
|
|
296
|
-
name: "my-
|
|
281
|
+
name: "my-view",
|
|
297
282
|
description: "First tool",
|
|
298
|
-
view: { component: "my-
|
|
283
|
+
view: { component: "my-view" },
|
|
299
284
|
}, vi.fn());
|
|
300
285
|
server.registerTool({
|
|
301
|
-
name: "folder-
|
|
286
|
+
name: "folder-view",
|
|
302
287
|
description: "Second tool",
|
|
303
|
-
view: { component: "folder-
|
|
288
|
+
view: { component: "folder-view" },
|
|
304
289
|
}, vi.fn());
|
|
305
|
-
const
|
|
306
|
-
const
|
|
307
|
-
expect(
|
|
308
|
-
expect(
|
|
309
|
-
expect(
|
|
290
|
+
const myviewTemplate = (mockRegisterTool.mock.calls[0]?.[1])._meta?.ui?.resourceUri;
|
|
291
|
+
const folderviewTemplate = (mockRegisterTool.mock.calls[1]?.[1])._meta?.ui?.resourceUri;
|
|
292
|
+
expect(myviewTemplate).not.toEqual(folderviewTemplate);
|
|
293
|
+
expect(myviewTemplate).toMatch(/\?v=[0-9a-f]{8}$/);
|
|
294
|
+
expect(folderviewTemplate).toMatch(/\?v=[0-9a-f]{8}$/);
|
|
310
295
|
});
|
|
311
296
|
it("should fall back to bare URI in production when manifest is missing", () => {
|
|
312
297
|
setTestEnv({ NODE_ENV: "production" });
|
|
313
298
|
server.registerTool({
|
|
314
|
-
name: "unknown-
|
|
299
|
+
name: "unknown-view",
|
|
315
300
|
description: "Test tool",
|
|
316
|
-
view: { component: "unknown-
|
|
301
|
+
view: { component: "unknown-view" },
|
|
317
302
|
}, vi.fn());
|
|
318
303
|
const toolConfig = mockRegisterTool.mock.calls[0]?.[1];
|
|
319
|
-
expect(toolConfig._meta?.
|
|
320
|
-
});
|
|
321
|
-
it("should register tool with ui.resourceUri only when mcp-app only", async () => {
|
|
322
|
-
server.registerTool({
|
|
323
|
-
name: "my-widget",
|
|
324
|
-
description: "Test tool",
|
|
325
|
-
view: {
|
|
326
|
-
component: "my-widget",
|
|
327
|
-
description: "Test view",
|
|
328
|
-
hosts: ["mcp-app"],
|
|
329
|
-
},
|
|
330
|
-
}, vi.fn());
|
|
331
|
-
expect(mockRegisterTool).toHaveBeenCalledTimes(1);
|
|
332
|
-
const toolCallArgs = mockRegisterTool.mock.calls[0];
|
|
333
|
-
const toolConfig = toolCallArgs?.[1];
|
|
334
|
-
expect(toolConfig._meta).toHaveProperty("ui");
|
|
335
|
-
expect(toolConfig._meta?.ui).toEqual({
|
|
336
|
-
resourceUri: "ui://widgets/ext-apps/my-widget.html",
|
|
337
|
-
});
|
|
338
|
-
expect(toolConfig._meta?.["openai/outputTemplate"]).toBeUndefined();
|
|
304
|
+
expect(toolConfig._meta?.ui?.resourceUri).toBe("ui://views/ext-apps/unknown-view.html");
|
|
339
305
|
});
|
|
340
306
|
it("should inject viewUUID into _meta of tool callback results", async () => {
|
|
341
307
|
const mockToolCallback = vi.fn().mockResolvedValue({
|
|
@@ -343,9 +309,9 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
343
309
|
structuredContent: { data: "test" },
|
|
344
310
|
});
|
|
345
311
|
server.registerTool({
|
|
346
|
-
name: "my-
|
|
312
|
+
name: "my-view",
|
|
347
313
|
description: "Test tool",
|
|
348
|
-
view: { component: "my-
|
|
314
|
+
view: { component: "my-view", description: "Test view" },
|
|
349
315
|
}, mockToolCallback);
|
|
350
316
|
const wrappedCallback = mockRegisterTool.mock.calls[0]?.[2];
|
|
351
317
|
expect(wrappedCallback).toBeDefined();
|
|
@@ -362,9 +328,9 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
362
328
|
_meta: { requestId: "req-123", cached: true },
|
|
363
329
|
});
|
|
364
330
|
server.registerTool({
|
|
365
|
-
name: "my-
|
|
331
|
+
name: "my-view",
|
|
366
332
|
description: "Test tool",
|
|
367
|
-
view: { component: "my-
|
|
333
|
+
view: { component: "my-view", description: "Test view" },
|
|
368
334
|
}, mockToolCallback);
|
|
369
335
|
const wrappedCallback = mockRegisterTool.mock.calls[0]?.[2];
|
|
370
336
|
const result = await wrappedCallback({}, {});
|
|
@@ -378,9 +344,9 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
378
344
|
structuredContent: {},
|
|
379
345
|
});
|
|
380
346
|
server.registerTool({
|
|
381
|
-
name: "my-
|
|
347
|
+
name: "my-view",
|
|
382
348
|
description: "Test tool",
|
|
383
|
-
view: { component: "my-
|
|
349
|
+
view: { component: "my-view", description: "Test view" },
|
|
384
350
|
}, mockToolCallback);
|
|
385
351
|
const wrappedCallback = mockRegisterTool.mock.calls[0]?.[2];
|
|
386
352
|
const result1 = await wrappedCallback({}, {});
|
|
@@ -473,11 +439,12 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
473
439
|
const host = "localhost:3000";
|
|
474
440
|
const serverUrl = `http://${host}`;
|
|
475
441
|
const hmrUrl = `ws://${host}`;
|
|
476
|
-
const result = await appsSdkCallback(new URL("ui://
|
|
442
|
+
const result = await appsSdkCallback(new URL("ui://views/ext-apps/csp-tool.html"), createMockExtra(host));
|
|
477
443
|
const meta = result.contents[0]?._meta;
|
|
478
|
-
expect(meta
|
|
479
|
-
|
|
480
|
-
|
|
444
|
+
expect(meta.ui?.csp).toEqual({
|
|
445
|
+
resourceDomains: [serverUrl, "https://cdn.example.com"],
|
|
446
|
+
connectDomains: [serverUrl, hmrUrl, "https://api.example.com"],
|
|
447
|
+
baseUriDomains: [serverUrl],
|
|
481
448
|
});
|
|
482
449
|
});
|
|
483
450
|
it("should let view._meta override framework-computed keys", async () => {
|
|
@@ -489,18 +456,20 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
489
456
|
description: "Test view",
|
|
490
457
|
csp: { connectDomains: ["https://api.x.com"] },
|
|
491
458
|
_meta: {
|
|
492
|
-
|
|
493
|
-
|
|
459
|
+
ui: {
|
|
460
|
+
csp: {
|
|
461
|
+
connectDomains: ["https://api.y.com"],
|
|
462
|
+
},
|
|
494
463
|
},
|
|
495
464
|
},
|
|
496
465
|
},
|
|
497
466
|
}, vi.fn());
|
|
498
467
|
const appsSdkCallback = mockRegisterResource.mock
|
|
499
468
|
.calls[0]?.[3];
|
|
500
|
-
const result = await appsSdkCallback(new URL("ui://
|
|
469
|
+
const result = await appsSdkCallback(new URL("ui://views/ext-apps/override-tool.html"), createMockExtra("localhost:3000"));
|
|
501
470
|
const meta = result.contents[0]?._meta;
|
|
502
|
-
expect(meta
|
|
503
|
-
|
|
471
|
+
expect(meta.ui?.csp).toEqual({
|
|
472
|
+
connectDomains: ["https://api.y.com"],
|
|
504
473
|
});
|
|
505
474
|
});
|
|
506
475
|
it("should pass user _meta keys through to tool config", () => {
|
|
@@ -520,4 +489,48 @@ describe("McpServer.registerTool (unified API)", () => {
|
|
|
520
489
|
expect(toolConfig._meta?.["acme.com/category"]).toBe("utility");
|
|
521
490
|
});
|
|
522
491
|
});
|
|
492
|
+
describe("resources/list view _meta injection", () => {
|
|
493
|
+
afterEach(() => resetTestEnv());
|
|
494
|
+
it("attaches CSP, domain, and connectDomains _meta to view resources at list time", async () => {
|
|
495
|
+
setTestEnv({ NODE_ENV: "production" });
|
|
496
|
+
const server = new McpServerClass({ name: "test", version: "1.0.0" }, { capabilities: {} });
|
|
497
|
+
server.registerTool({
|
|
498
|
+
name: "start",
|
|
499
|
+
description: "Start",
|
|
500
|
+
view: {
|
|
501
|
+
component: "my-view",
|
|
502
|
+
description: "Onboarding deck",
|
|
503
|
+
domain: "skybridge.tech",
|
|
504
|
+
csp: {
|
|
505
|
+
resourceDomains: ["https://fonts.googleapis.com"],
|
|
506
|
+
redirectDomains: ["https://docs.skybridge.tech"],
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
}, vi.fn().mockResolvedValue({
|
|
510
|
+
content: [{ type: "text", text: "ok" }],
|
|
511
|
+
structuredContent: {},
|
|
512
|
+
}));
|
|
513
|
+
const client = new Client({ name: "test-client", version: "1.0.0" });
|
|
514
|
+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
515
|
+
await server.connect(serverTransport);
|
|
516
|
+
await client.connect(clientTransport);
|
|
517
|
+
const { resources } = await client.listResources();
|
|
518
|
+
await client.close();
|
|
519
|
+
await server.close();
|
|
520
|
+
const appsSdk = resources.find((r) => r.uri.includes("apps-sdk"));
|
|
521
|
+
const extApps = resources.find((r) => r.uri.includes("ext-apps"));
|
|
522
|
+
expect(appsSdk).toBeUndefined();
|
|
523
|
+
expect(extApps?._meta).toBeDefined();
|
|
524
|
+
const extUi = (extApps?._meta).ui;
|
|
525
|
+
expect(extUi?.csp?.connectDomains?.length).toBeGreaterThan(0);
|
|
526
|
+
expect(extUi?.csp?.resourceDomains).toContain("https://fonts.googleapis.com");
|
|
527
|
+
expect(extUi?.domain).toBe("skybridge.tech");
|
|
528
|
+
const meta = extApps?._meta;
|
|
529
|
+
expect(meta["openai/widgetDescription"]).toBe("Onboarding deck");
|
|
530
|
+
expect(meta["openai/widgetCSP"]?.redirect_domains).toEqual([
|
|
531
|
+
"https://docs.skybridge.tech",
|
|
532
|
+
]);
|
|
533
|
+
expect(meta.ui?.csp).not.toHaveProperty("redirectDomains");
|
|
534
|
+
});
|
|
535
|
+
});
|
|
523
536
|
//# sourceMappingURL=view.test.js.map
|