skybridge 0.0.0-dev.81dc563 → 0.0.0-dev.81fd90a
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 +3 -0
- package/dist/cli/build-helpers.d.ts +6 -2
- package/dist/cli/build-helpers.js +37 -12
- package/dist/cli/build-helpers.js.map +1 -1
- package/dist/cli/build-helpers.test.js +71 -3
- package/dist/cli/build-helpers.test.js.map +1 -1
- package/dist/cli/build-steps.d.ts +2 -0
- package/dist/cli/build-steps.js +73 -0
- package/dist/cli/build-steps.js.map +1 -0
- package/dist/cli/build-steps.test.js +52 -0
- package/dist/cli/build-steps.test.js.map +1 -0
- package/dist/cli/header.d.ts +1 -1
- package/dist/cli/resolve-skybridge-config.d.ts +5 -0
- package/dist/cli/{resolve-views-dir.js → resolve-skybridge-config.js} +4 -3
- package/dist/cli/resolve-skybridge-config.js.map +1 -0
- package/dist/cli/run-plain.d.ts +18 -0
- package/dist/cli/run-plain.js +89 -0
- package/dist/cli/run-plain.js.map +1 -0
- package/dist/cli/use-execute-steps.d.ts +1 -1
- package/dist/cli/use-nodemon.d.ts +14 -0
- package/dist/cli/use-nodemon.js +71 -60
- package/dist/cli/use-nodemon.js.map +1 -1
- package/dist/cli/use-typescript-check.d.ts +8 -2
- package/dist/cli/use-typescript-check.js +70 -67
- package/dist/cli/use-typescript-check.js.map +1 -1
- package/dist/commands/build.d.ts +0 -2
- package/dist/commands/build.js +2 -61
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/dev.d.ts +1 -0
- package/dist/commands/dev.js +34 -2
- package/dist/commands/dev.js.map +1 -1
- 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.d.ts +1 -0
- package/dist/context-warnings.test.js +28 -0
- package/dist/context-warnings.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.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 +17 -7
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/auth/providers/auth0.d.ts +40 -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 +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.d.ts +1 -0
- package/dist/server/auth/providers/authplane.test.js +140 -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.d.ts +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 +40 -0
- package/dist/server/auth/providers/custom.js +56 -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 +158 -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.d.ts +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.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 +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 +33 -0
- package/dist/server/auth/providers/workos.js +15 -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.d.ts +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 +3 -1
- package/dist/server/auth/setup.js +64 -25
- package/dist/server/auth/setup.js.map +1 -1
- package/dist/server/auth/setup.test.js +330 -19
- package/dist/server/auth/setup.test.js.map +1 -1
- package/dist/server/auth/verify.d.ts +40 -5
- package/dist/server/auth/verify.js +29 -4
- package/dist/server/auth/verify.js.map +1 -1
- package/dist/server/auth/verify.test.js +62 -0
- package/dist/server/auth/verify.test.js.map +1 -1
- package/dist/server/auth-extra.test-d.d.ts +1 -0
- package/dist/server/auth-extra.test-d.js +71 -0
- package/dist/server/auth-extra.test-d.js.map +1 -0
- package/dist/server/auth.d.ts +42 -5
- package/dist/server/auth.js +3 -4
- package/dist/server/auth.js.map +1 -1
- package/dist/server/content-helpers.d.ts +1 -1
- package/dist/server/content-helpers.js.map +1 -1
- package/dist/server/express.js +9 -28
- package/dist/server/express.js.map +1 -1
- package/dist/server/express.test.js +42 -7
- package/dist/server/express.test.js.map +1 -1
- 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 +14 -3
- package/dist/server/index.js +12 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp-errors.test.d.ts +1 -0
- package/dist/server/mcp-errors.test.js +37 -0
- package/dist/server/mcp-errors.test.js.map +1 -0
- package/dist/server/middleware.d.ts +35 -10
- package/dist/server/middleware.js +33 -0
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/middleware.test-d.js +1 -1
- package/dist/server/middleware.test-d.js.map +1 -1
- package/dist/server/middleware.test.js +38 -3
- package/dist/server/middleware.test.js.map +1 -1
- package/dist/server/register-tool.test.d.ts +1 -0
- package/dist/server/register-tool.test.js +25 -0
- package/dist/server/register-tool.test.js.map +1 -0
- package/dist/server/requestOrigin.d.ts +3 -2
- package/dist/server/requestOrigin.js +8 -8
- package/dist/server/requestOrigin.js.map +1 -1
- package/dist/server/server.d.ts +138 -50
- package/dist/server/server.js +280 -147
- package/dist/server/server.js.map +1 -1
- package/dist/server/skills-integration.test.d.ts +1 -0
- package/dist/server/skills-integration.test.js +79 -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/server/tool-extra.test.d.ts +1 -0
- package/dist/server/tool-extra.test.js +72 -0
- package/dist/server/tool-extra.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.js +93 -12
- package/dist/server/view-resource-resolution.test.js.map +1 -1
- package/dist/server/viewsDevServer.js +4 -1
- package/dist/server/viewsDevServer.js.map +1 -1
- package/dist/standard-schema.d.ts +3 -0
- package/dist/standard-schema.js +2 -0
- package/dist/standard-schema.js.map +1 -0
- package/dist/test/utils.d.ts +5 -8
- package/dist/test/utils.js +8 -4
- package/dist/test/utils.js.map +1 -1
- package/dist/test/view.test.js +82 -114
- package/dist/test/view.test.js.map +1 -1
- package/dist/web/bridges/adaptor.d.ts +51 -0
- package/dist/web/bridges/adaptor.js +327 -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 +225 -0
- package/dist/web/bridges/adaptor.test.js.map +1 -0
- package/dist/web/bridges/apps-sdk/bridge.d.ts +6 -2
- package/dist/web/bridges/apps-sdk/bridge.js +15 -4
- 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/use-apps-sdk-context.d.ts +1 -1
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +1 -1
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
- package/dist/web/bridges/get-adaptor.d.ts +4 -4
- package/dist/web/bridges/get-adaptor.js +6 -11
- 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/mcp-app/bridge.d.ts +13 -2
- package/dist/web/bridges/mcp-app/bridge.js +51 -7
- 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.d.ts +2 -0
- package/dist/web/bridges/mcp-app/types.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
- package/dist/web/bridges/mcp-app/view-tools.test.js +5 -6
- package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -1
- package/dist/web/bridges/types.d.ts +27 -9
- 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/components/modal-provider.d.ts +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.test.js +9 -6
- package/dist/web/create-store.test.js.map +1 -1
- package/dist/web/data-llm.d.ts +1 -1
- package/dist/web/data-llm.test.js +19 -6
- package/dist/web/data-llm.test.js.map +1 -1
- package/dist/web/hooks/index.d.ts +2 -1
- package/dist/web/hooks/index.js +2 -1
- package/dist/web/hooks/index.js.map +1 -1
- package/dist/web/hooks/test/utils.d.ts +2 -1
- package/dist/web/hooks/test/utils.js +1 -1
- package/dist/web/hooks/test/utils.js.map +1 -1
- package/dist/web/hooks/use-call-tool.test.js +39 -25
- package/dist/web/hooks/use-call-tool.test.js.map +1 -1
- package/dist/web/hooks/use-display-mode.d.ts +1 -1
- package/dist/web/hooks/use-display-mode.js +1 -1
- package/dist/web/hooks/use-display-mode.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test.js +57 -21
- package/dist/web/hooks/use-display-mode.test.js.map +1 -1
- package/dist/web/hooks/use-download.d.ts +1 -3
- package/dist/web/hooks/use-download.js +1 -2
- package/dist/web/hooks/use-download.js.map +1 -1
- package/dist/web/hooks/use-download.test.js +16 -8
- package/dist/web/hooks/use-download.test.js.map +1 -1
- package/dist/web/hooks/use-files.test.js +11 -3
- package/dist/web/hooks/use-files.test.js.map +1 -1
- package/dist/web/hooks/use-host.d.ts +22 -0
- package/dist/web/hooks/use-host.js +30 -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-open-external.test.js +14 -4
- package/dist/web/hooks/use-open-external.test.js.map +1 -1
- package/dist/web/hooks/use-register-view-tool.d.ts +2 -3
- package/dist/web/hooks/use-register-view-tool.js.map +1 -1
- package/dist/web/hooks/use-request-close.test.js +35 -40
- package/dist/web/hooks/use-request-close.test.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 +1 -1
- package/dist/web/hooks/use-request-size.js +1 -1
- package/dist/web/hooks/use-request-size.js.map +1 -1
- package/dist/web/hooks/use-request-size.test.js +35 -53
- package/dist/web/hooks/use-request-size.test.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.test.js +29 -9
- package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
- package/dist/web/hooks/use-tool-info.d.ts +1 -20
- package/dist/web/hooks/use-tool-info.js +0 -1
- package/dist/web/hooks/use-tool-info.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test-d.js +0 -5
- package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test.js +37 -32
- package/dist/web/hooks/use-tool-info.test.js.map +1 -1
- package/dist/web/hooks/use-user.d.ts +3 -2
- package/dist/web/hooks/use-user.js +4 -3
- package/dist/web/hooks/use-user.js.map +1 -1
- package/dist/web/hooks/use-user.test.js +84 -36
- package/dist/web/hooks/use-user.test.js.map +1 -1
- package/dist/web/hooks/use-view-state.js +19 -9
- package/dist/web/hooks/use-view-state.js.map +1 -1
- package/dist/web/hooks/use-view-state.test.js +38 -3
- package/dist/web/hooks/use-view-state.test.js.map +1 -1
- package/dist/web/hooks/use-viewport.d.ts +20 -0
- package/dist/web/hooks/use-viewport.js +21 -0
- package/dist/web/hooks/use-viewport.js.map +1 -0
- package/dist/web/hooks/use-viewport.test.d.ts +1 -0
- package/dist/web/hooks/use-viewport.test.js +109 -0
- package/dist/web/hooks/use-viewport.test.js.map +1 -0
- package/dist/web/index.d.ts +1 -0
- package/dist/web/index.js.map +1 -1
- package/dist/web/mount-view.d.ts +3 -2
- package/dist/web/mount-view.js +3 -2
- package/dist/web/mount-view.js.map +1 -1
- package/dist/web/plugin/plugin-build.test.d.ts +1 -0
- package/dist/web/plugin/plugin-build.test.js +54 -0
- package/dist/web/plugin/plugin-build.test.js.map +1 -0
- package/dist/web/plugin/plugin.d.ts +6 -0
- package/dist/web/plugin/plugin.js +18 -7
- package/dist/web/plugin/plugin.js.map +1 -1
- package/dist/web/plugin/plugin.test.d.ts +1 -0
- package/dist/web/plugin/plugin.test.js +61 -0
- package/dist/web/plugin/plugin.test.js.map +1 -0
- package/package.json +28 -23
- package/dist/cli/resolve-views-dir.d.ts +0 -1
- package/dist/cli/resolve-views-dir.js.map +0 -1
- package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -29
- package/dist/web/bridges/apps-sdk/adaptor.js +0 -117
- package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
- package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -53
- package/dist/web/bridges/mcp-app/adaptor.js +0 -283
- package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
- package/dist/web/hooks/use-layout.d.ts +0 -24
- package/dist/web/hooks/use-layout.js +0 -25
- package/dist/web/hooks/use-layout.js.map +0 -1
- package/dist/web/hooks/use-layout.test.js +0 -96
- package/dist/web/hooks/use-layout.test.js.map +0 -1
- /package/dist/{web/hooks/use-layout.test.d.ts → cli/build-steps.test.d.ts} +0 -0
package/dist/server/server.js
CHANGED
|
@@ -2,15 +2,18 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import http from "node:http";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import {
|
|
6
|
-
import { McpServer as McpServerBase } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { McpServer as McpServerBase, } from "@modelcontextprotocol/server";
|
|
7
6
|
import { mergeWith, union } from "es-toolkit";
|
|
8
7
|
import express, {} from "express";
|
|
8
|
+
import { warnOnLargeToolOutput } from "../context-warnings.js";
|
|
9
|
+
import { authToSecuritySchemes, evaluateSecuritySchemes, inBandChallengeResult, } from "./auth/security-schemes.js";
|
|
9
10
|
import { setupOAuth } from "./auth/setup.js";
|
|
10
11
|
import { createApp } from "./express.js";
|
|
12
|
+
import { hostFromUserAgent } from "./host.js";
|
|
11
13
|
import { createMiddlewareEntry } from "./metric.js";
|
|
12
|
-
import { buildMiddlewareChain, getHandlerMaps } from "./middleware.js";
|
|
14
|
+
import { buildMiddlewareChain, captureToolError, getHandlerMaps, } from "./middleware.js";
|
|
13
15
|
import { resolveServerOrigin } from "./requestOrigin.js";
|
|
16
|
+
import { discoverSkills, registerSkills, SKILLS_EXTENSION_KEY, } from "./skills.js";
|
|
14
17
|
import { templateHelper } from "./templateHelper.js";
|
|
15
18
|
const mergeWithUnion = (target, source) => {
|
|
16
19
|
return mergeWith(target, source, (targetVal, sourceVal) => {
|
|
@@ -19,6 +22,20 @@ const mergeWithUnion = (target, source) => {
|
|
|
19
22
|
}
|
|
20
23
|
});
|
|
21
24
|
};
|
|
25
|
+
const SKILLS_DIR = "src/skills";
|
|
26
|
+
/**
|
|
27
|
+
* Normalize an `x-forwarded-prefix` value into a leading-slash, no-trailing-slash
|
|
28
|
+
* path. Takes the first hop of a comma-separated proxy chain.
|
|
29
|
+
* "/v1/", "v1", "/v1, /internal" → "/v1"; "", "/", undefined → "".
|
|
30
|
+
*/
|
|
31
|
+
function normalizeForwardedPrefix(raw) {
|
|
32
|
+
const firstHop = raw?.split(",")[0]?.trim() ?? "";
|
|
33
|
+
const trimmed = firstHop.replace(/\/+$/, "");
|
|
34
|
+
if (trimmed === "") {
|
|
35
|
+
return "";
|
|
36
|
+
}
|
|
37
|
+
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
38
|
+
}
|
|
22
39
|
/**
|
|
23
40
|
* Drop the query string from a `ui://` view URI, leaving the bare path. The
|
|
24
41
|
* `?v=` cache key is the only query we append, so a plain split is enough and
|
|
@@ -92,6 +109,27 @@ let pendingBuildManifest = null;
|
|
|
92
109
|
export function __setBuildManifest(manifest) {
|
|
93
110
|
pendingBuildManifest = manifest;
|
|
94
111
|
}
|
|
112
|
+
let pendingSkillsManifest = null;
|
|
113
|
+
export function __setSkillsManifest(manifest) {
|
|
114
|
+
pendingSkillsManifest = manifest;
|
|
115
|
+
}
|
|
116
|
+
// Pure and `this`-free so it can run inside the `super(...)` call, before `this`
|
|
117
|
+
// exists — the capability must be present for the `initialize` response.
|
|
118
|
+
function withSkillsCapability(options, skybridgeOptions) {
|
|
119
|
+
if (!skybridgeOptions?.skills) {
|
|
120
|
+
return options;
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
...options,
|
|
124
|
+
capabilities: {
|
|
125
|
+
...options?.capabilities,
|
|
126
|
+
extensions: {
|
|
127
|
+
...options?.capabilities?.extensions,
|
|
128
|
+
[SKILLS_EXTENSION_KEY]: { directoryRead: true },
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
95
133
|
export class McpServer extends McpServerBaseOmitted {
|
|
96
134
|
/**
|
|
97
135
|
* The underlying Express app. Use this to extend the HTTP server with
|
|
@@ -111,6 +149,8 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
111
149
|
customErrorMiddleware = [];
|
|
112
150
|
mcpMiddlewareEntries = [];
|
|
113
151
|
mcpMiddlewareApplied = false;
|
|
152
|
+
middlewareEntriesCache = null;
|
|
153
|
+
registrations = [];
|
|
114
154
|
claimedViews = new Map();
|
|
115
155
|
viewMetaBuilders = new Map();
|
|
116
156
|
/**
|
|
@@ -123,14 +163,19 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
123
163
|
viteManifest = null;
|
|
124
164
|
serverInfo;
|
|
125
165
|
serverOptions;
|
|
166
|
+
oauthEnabled = false;
|
|
167
|
+
resolveResourceMetadataUrl;
|
|
168
|
+
securitySchemesByTool = new Map();
|
|
126
169
|
constructor(serverInfo, options, skybridgeOptions) {
|
|
127
|
-
|
|
170
|
+
const mergedOptions = withSkillsCapability(options, skybridgeOptions);
|
|
171
|
+
super(serverInfo, mergedOptions);
|
|
128
172
|
this.serverInfo = serverInfo;
|
|
129
|
-
this.serverOptions =
|
|
173
|
+
this.serverOptions = mergedOptions;
|
|
130
174
|
this.express = express();
|
|
131
175
|
this.express.use(express.json(skybridgeOptions?.json));
|
|
132
176
|
if (skybridgeOptions?.oauth) {
|
|
133
|
-
|
|
177
|
+
this.oauthEnabled = true;
|
|
178
|
+
this.resolveResourceMetadataUrl = setupOAuth(this.express, skybridgeOptions.oauth, this.securitySchemesByTool);
|
|
134
179
|
}
|
|
135
180
|
// Pick up the manifest if `dist/__entry.js` primed it before importing
|
|
136
181
|
// user code. Consume-once: clear after the first construction so a
|
|
@@ -141,6 +186,56 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
141
186
|
this.setViteManifest(pendingBuildManifest);
|
|
142
187
|
pendingBuildManifest = null;
|
|
143
188
|
}
|
|
189
|
+
this.setupSkills(Boolean(skybridgeOptions?.skills));
|
|
190
|
+
}
|
|
191
|
+
registerResource(...args) {
|
|
192
|
+
return this.recordInherited("registerResource", args);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Register a prompt, recorded so every per-request instance carries it.
|
|
196
|
+
* Signature owned by Skybridge (not inherited) so a typed wrapper can land
|
|
197
|
+
* in a minor without a type-level break.
|
|
198
|
+
*/
|
|
199
|
+
registerPrompt(name, config, cb) {
|
|
200
|
+
return this.recordInherited("registerPrompt", [
|
|
201
|
+
name,
|
|
202
|
+
config,
|
|
203
|
+
cb,
|
|
204
|
+
]);
|
|
205
|
+
}
|
|
206
|
+
recordInherited(method, args) {
|
|
207
|
+
const base = McpServerBase.prototype[method];
|
|
208
|
+
let registered;
|
|
209
|
+
this.record((target) => {
|
|
210
|
+
const result = base.apply(target, args);
|
|
211
|
+
if (target === this) {
|
|
212
|
+
registered = result;
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
return registered;
|
|
216
|
+
}
|
|
217
|
+
skillRegistrar() {
|
|
218
|
+
const registerResource = this.registerResource.bind(this);
|
|
219
|
+
return {
|
|
220
|
+
registerResource,
|
|
221
|
+
server: {
|
|
222
|
+
setRequestHandler: ((...args) => {
|
|
223
|
+
this.recordRequestHandler(...args);
|
|
224
|
+
}),
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
setupSkills(enabled) {
|
|
229
|
+
const manifest = pendingSkillsManifest;
|
|
230
|
+
pendingSkillsManifest = null;
|
|
231
|
+
if (!enabled) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const skills = manifest ?? discoverSkills(SKILLS_DIR);
|
|
235
|
+
if (skills.length === 0) {
|
|
236
|
+
console.warn(`skybridge: the "skills" option is enabled but no skills were found in "${SKILLS_DIR}". Add a <name>/SKILL.md there, or remove the option.`);
|
|
237
|
+
}
|
|
238
|
+
registerSkills(this.skillRegistrar(), skills);
|
|
144
239
|
}
|
|
145
240
|
use(pathOrHandler, ...handlers) {
|
|
146
241
|
// Branching is load-bearing: Express's `app.use` overloads can't be
|
|
@@ -236,7 +331,7 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
236
331
|
const result = (await next());
|
|
237
332
|
for (const content of result.contents ?? []) {
|
|
238
333
|
if (typeof content.uri === "string" &&
|
|
239
|
-
stripQuery(content.uri) ===
|
|
334
|
+
stripQuery(content.uri) === stripQuery(canonical)) {
|
|
240
335
|
content.uri = requested;
|
|
241
336
|
}
|
|
242
337
|
}
|
|
@@ -249,17 +344,39 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
249
344
|
}
|
|
250
345
|
},
|
|
251
346
|
};
|
|
347
|
+
// ChatGPT reads `securitySchemes` at the tool descriptor top level (SEP-1488,
|
|
348
|
+
// still Draft), but the SDK's registerTool strips unknown top-level fields, so
|
|
349
|
+
// it's stashed in `_meta` at registration. This restores it to the top level
|
|
350
|
+
// on tools/list output. Remove once SEP-1488 lands and the SDK preserves it.
|
|
351
|
+
// { name: "checkout", _meta: { securitySchemes: [{ type: "oauth2" }] } }
|
|
352
|
+
// -> { name: "checkout", _meta: {…}, securitySchemes: [{ type: "oauth2" }] }
|
|
353
|
+
const toolsListSecuritySchemesEntry = {
|
|
354
|
+
filter: "tools/list",
|
|
355
|
+
handler: async (_req, _extra, next) => {
|
|
356
|
+
const result = (await next());
|
|
357
|
+
for (const tool of result.tools) {
|
|
358
|
+
const schemes = tool._meta?.securitySchemes;
|
|
359
|
+
if (schemes && !("securitySchemes" in tool)) {
|
|
360
|
+
tool.securitySchemes = schemes;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return result;
|
|
364
|
+
},
|
|
365
|
+
};
|
|
252
366
|
const monitoringEntry = createMiddlewareEntry();
|
|
253
367
|
const entries = [
|
|
254
368
|
...(monitoringEntry ? [monitoringEntry] : []),
|
|
255
369
|
viewListMetaEntry,
|
|
256
370
|
viewReadResolveEntry,
|
|
371
|
+
toolsListSecuritySchemesEntry,
|
|
257
372
|
...this.mcpMiddlewareEntries,
|
|
258
373
|
];
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
374
|
+
this.middlewareEntriesCache = entries;
|
|
375
|
+
this.instrumentHandlers(this.server);
|
|
376
|
+
}
|
|
377
|
+
instrumentHandlers(server) {
|
|
378
|
+
const entries = this.middlewareEntriesCache ?? [];
|
|
379
|
+
const { requestHandlers, notificationHandlers } = getHandlerMaps(server);
|
|
263
380
|
const instrumentMap = (map, isNotification) => {
|
|
264
381
|
for (const [method, handler] of map) {
|
|
265
382
|
map.set(method, buildMiddlewareChain(method, isNotification, handler, entries));
|
|
@@ -283,23 +400,36 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
283
400
|
return McpServerBase.prototype.connect.call(this, transport);
|
|
284
401
|
}
|
|
285
402
|
/**
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
* read side and fails fast on SDK field renames.
|
|
403
|
+
* Build a fresh server for one stateless HTTP request, as
|
|
404
|
+
* `createMcpHandler`'s factory contract requires: every registration is
|
|
405
|
+
* replayed onto the new instance so the SDK's handler closures belong to
|
|
406
|
+
* the instance whose protocol era it stamps. Sharing the singleton's
|
|
407
|
+
* handler maps instead would bind them to an instance that is never
|
|
408
|
+
* marked, pinning every request to the 2025 codec and letting concurrent
|
|
409
|
+
* callers overwrite each other's negotiated version.
|
|
294
410
|
*/
|
|
295
|
-
|
|
411
|
+
createStatelessServerInstance() {
|
|
296
412
|
this.applyMcpMiddleware();
|
|
297
|
-
const
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
413
|
+
const fresh = new McpServerBase(this.serverInfo, this.serverOptions);
|
|
414
|
+
for (const apply of this.registrations) {
|
|
415
|
+
apply(fresh);
|
|
416
|
+
}
|
|
417
|
+
this.instrumentHandlers(fresh.server);
|
|
418
|
+
return fresh.server;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Apply an SDK registration to the singleton and remember it, so each
|
|
422
|
+
* per-request instance can be built with the same surface.
|
|
423
|
+
*/
|
|
424
|
+
record(apply) {
|
|
425
|
+
this.registrations.push(apply);
|
|
426
|
+
apply(this);
|
|
427
|
+
}
|
|
428
|
+
/** Records a raw request handler (used for methods the SDK has no sugar for). */
|
|
429
|
+
recordRequestHandler(...args) {
|
|
430
|
+
this.record((target) => {
|
|
431
|
+
target.server.setRequestHandler(...args);
|
|
432
|
+
});
|
|
303
433
|
}
|
|
304
434
|
/**
|
|
305
435
|
* Start the HTTP server. Listens on `process.env.__PORT` (default `3000`),
|
|
@@ -374,15 +504,16 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
374
504
|
}
|
|
375
505
|
this.claimedViews.set(component, toolName);
|
|
376
506
|
}
|
|
377
|
-
resolveViewRequestContext(
|
|
507
|
+
resolveViewRequestContext(ctx) {
|
|
378
508
|
const isProduction = process.env.NODE_ENV === "production";
|
|
379
|
-
const
|
|
380
|
-
const
|
|
381
|
-
const val = headers[key];
|
|
382
|
-
return Array.isArray(val) ? val[0] : val;
|
|
383
|
-
};
|
|
384
|
-
const isClaude = header("user-agent") === "Claude-User";
|
|
509
|
+
const header = (key) => ctx?.http?.req?.headers.get(key) ?? undefined;
|
|
510
|
+
const isClaude = hostFromUserAgent(header("user-agent")) === "claude";
|
|
385
511
|
const serverUrl = resolveServerOrigin(header);
|
|
512
|
+
// Path prefix the proxy routed this request under (e.g. `foo.com/v1`). Read
|
|
513
|
+
// per-request so one process can serve many hosts/prefixes at once: the
|
|
514
|
+
// origin is recovered from x-forwarded-host, the prefix from
|
|
515
|
+
// x-forwarded-prefix. Empty when served at the origin root.
|
|
516
|
+
const assetsBasePath = normalizeForwardedPrefix(header("x-forwarded-prefix"));
|
|
386
517
|
const connectDomains = [serverUrl];
|
|
387
518
|
if (!isProduction) {
|
|
388
519
|
const wsUrl = new URL(serverUrl);
|
|
@@ -391,7 +522,7 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
391
522
|
}
|
|
392
523
|
let contentMetaOverrides = {};
|
|
393
524
|
if (isClaude) {
|
|
394
|
-
const pathname =
|
|
525
|
+
const pathname = ctx?.http?.req ? new URL(ctx.http.req.url).pathname : "";
|
|
395
526
|
const rawUrl = header("x-alpic-forwarded-url") ?? `${serverUrl}${pathname}`;
|
|
396
527
|
// Strip a lone trailing slash so the hash matches the connector URL
|
|
397
528
|
// as registered with Claude (which has no trailing slash on bare origins).
|
|
@@ -403,114 +534,77 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
403
534
|
.slice(0, 32);
|
|
404
535
|
contentMetaOverrides = { domain: `${hash}.claudemcpcontent.com` };
|
|
405
536
|
}
|
|
406
|
-
return { serverUrl, connectDomains, contentMetaOverrides };
|
|
537
|
+
return { serverUrl, assetsBasePath, connectDomains, contentMetaOverrides };
|
|
407
538
|
}
|
|
408
539
|
registerViewResources(toolName, view, toolMeta) {
|
|
409
|
-
const hosts = view.hosts ?? ["apps-sdk", "mcp-app"];
|
|
410
540
|
// Append a content-derived version param so hosts (e.g. ChatGPT) bust
|
|
411
541
|
// their cache when the bundle changes, but keep the URI stable across
|
|
412
542
|
// `tools/list` calls when the bundle hasn't changed.
|
|
413
543
|
const versionParam = this.computeViewVersionParam(view.component);
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
"openai/widgetDomain": domain,
|
|
426
|
-
"openai/widgetDescription": view.description,
|
|
427
|
-
};
|
|
428
|
-
const fromView = {
|
|
429
|
-
"openai/widgetCSP": {
|
|
430
|
-
resource_domains: view.csp?.resourceDomains,
|
|
431
|
-
connect_domains: view.csp?.connectDomains,
|
|
432
|
-
frame_domains: view.csp?.frameDomains,
|
|
433
|
-
redirect_domains: view.csp?.redirectDomains,
|
|
434
|
-
},
|
|
435
|
-
"openai/widgetDomain": view.domain,
|
|
436
|
-
"openai/widgetPrefersBorder": view.prefersBorder,
|
|
437
|
-
};
|
|
438
|
-
const base = mergeWithUnion(mergeWithUnion(defaults, fromView), {
|
|
439
|
-
"openai/widgetDomain": overrides.domain,
|
|
440
|
-
});
|
|
441
|
-
if (view._meta) {
|
|
442
|
-
return { ...base, ...view._meta };
|
|
443
|
-
}
|
|
444
|
-
return base;
|
|
445
|
-
},
|
|
446
|
-
};
|
|
447
|
-
this.registerViewResource({
|
|
448
|
-
name: toolName,
|
|
449
|
-
viewResource,
|
|
450
|
-
view,
|
|
451
|
-
});
|
|
452
|
-
toolMeta["openai/outputTemplate"] = viewResource.uri;
|
|
453
|
-
}
|
|
454
|
-
if (hosts.includes("mcp-app")) {
|
|
455
|
-
const viewResource = {
|
|
456
|
-
hostType: "mcp-app",
|
|
457
|
-
uri: `ui://views/ext-apps/${view.component}.html${versionParam}`,
|
|
458
|
-
mimeType: "text/html;profile=mcp-app",
|
|
459
|
-
buildContentMeta: ({ resourceDomains, connectDomains, domain, baseUriDomains }, overrides) => {
|
|
460
|
-
const defaults = {
|
|
461
|
-
ui: {
|
|
462
|
-
csp: {
|
|
463
|
-
resourceDomains,
|
|
464
|
-
connectDomains,
|
|
465
|
-
baseUriDomains,
|
|
466
|
-
},
|
|
467
|
-
domain,
|
|
544
|
+
const viewResource = {
|
|
545
|
+
hostType: "mcp-app",
|
|
546
|
+
uri: `ui://views/ext-apps/${view.component}.html${versionParam}`,
|
|
547
|
+
mimeType: "text/html;profile=mcp-app",
|
|
548
|
+
buildContentMeta: ({ resourceDomains, connectDomains, domain, baseUriDomains }, overrides) => {
|
|
549
|
+
const defaults = {
|
|
550
|
+
ui: {
|
|
551
|
+
csp: {
|
|
552
|
+
resourceDomains,
|
|
553
|
+
connectDomains,
|
|
554
|
+
baseUriDomains,
|
|
468
555
|
},
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
556
|
+
domain,
|
|
557
|
+
},
|
|
558
|
+
};
|
|
559
|
+
const fromView = {
|
|
560
|
+
ui: {
|
|
561
|
+
...(view.description && { description: view.description }),
|
|
562
|
+
...(view.prefersBorder !== undefined && {
|
|
563
|
+
prefersBorder: view.prefersBorder,
|
|
564
|
+
}),
|
|
565
|
+
...(view.domain && { domain: view.domain }),
|
|
566
|
+
csp: {
|
|
567
|
+
...(view.csp?.resourceDomains && {
|
|
568
|
+
resourceDomains: view.csp.resourceDomains,
|
|
569
|
+
}),
|
|
570
|
+
...(view.csp?.connectDomains && {
|
|
571
|
+
connectDomains: view.csp.connectDomains,
|
|
572
|
+
}),
|
|
573
|
+
...(view.csp?.frameDomains && {
|
|
574
|
+
frameDomains: view.csp.frameDomains,
|
|
575
|
+
}),
|
|
576
|
+
...(view.csp?.baseUriDomains && {
|
|
577
|
+
baseUriDomains: view.csp.baseUriDomains,
|
|
475
578
|
}),
|
|
476
|
-
...(view.domain && { domain: view.domain }),
|
|
477
|
-
csp: {
|
|
478
|
-
...(view.csp?.resourceDomains && {
|
|
479
|
-
resourceDomains: view.csp.resourceDomains,
|
|
480
|
-
}),
|
|
481
|
-
...(view.csp?.connectDomains && {
|
|
482
|
-
connectDomains: view.csp.connectDomains,
|
|
483
|
-
}),
|
|
484
|
-
...(view.csp?.frameDomains && {
|
|
485
|
-
frameDomains: view.csp.frameDomains,
|
|
486
|
-
}),
|
|
487
|
-
...(view.csp?.baseUriDomains && {
|
|
488
|
-
baseUriDomains: view.csp.baseUriDomains,
|
|
489
|
-
}),
|
|
490
|
-
...(view.csp?.redirectDomains && {
|
|
491
|
-
redirectDomains: view.csp.redirectDomains,
|
|
492
|
-
}),
|
|
493
|
-
},
|
|
494
579
|
},
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
580
|
+
},
|
|
581
|
+
};
|
|
582
|
+
const ui = mergeWithUnion(mergeWithUnion(defaults, fromView), {
|
|
583
|
+
ui: overrides,
|
|
584
|
+
});
|
|
585
|
+
const base = {
|
|
586
|
+
...ui,
|
|
587
|
+
...(view.description && {
|
|
588
|
+
"openai/widgetDescription": view.description,
|
|
589
|
+
}),
|
|
590
|
+
...(view.csp?.redirectDomains && {
|
|
591
|
+
"openai/widgetCSP": { redirect_domains: view.csp.redirectDomains },
|
|
592
|
+
}),
|
|
593
|
+
};
|
|
594
|
+
if (view._meta) {
|
|
595
|
+
return { ...base, ...view._meta };
|
|
596
|
+
}
|
|
597
|
+
return base;
|
|
598
|
+
},
|
|
599
|
+
};
|
|
600
|
+
this.registerViewResource({ name: toolName, viewResource, view });
|
|
601
|
+
// Advertise via the MCP Apps standard pointer only — ChatGPT renders from
|
|
602
|
+
// ui.resourceUri (verified), and not emitting openai/outputTemplate lets us
|
|
603
|
+
// retire the legacy apps-sdk resource later. The legacy apps-sdk URL is still
|
|
604
|
+
// served (see registerViewResource) so already-published apps keep resolving.
|
|
605
|
+
// @ts-expect-error - For backwards compatibility with Claude current implementation of the specs
|
|
606
|
+
toolMeta["ui/resourceUri"] = viewResource.uri;
|
|
607
|
+
toolMeta.ui = { ...toolMeta.ui, resourceUri: viewResource.uri };
|
|
514
608
|
}
|
|
515
609
|
registerViewResource({ name, viewResource, view, }) {
|
|
516
610
|
const { hostType, uri: viewUri, mimeType, buildContentMeta } = viewResource;
|
|
@@ -525,19 +619,24 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
525
619
|
};
|
|
526
620
|
this.viewMetaBuilders.set(viewUri, buildMeta);
|
|
527
621
|
this.viewUriByPath.set(stripQuery(viewUri), viewUri);
|
|
622
|
+
this.serveLegacyAppsSdkUrl(view.component, viewUri);
|
|
528
623
|
this.registerResource(name, viewUri, { description: view.description }, async (uri, extra) => {
|
|
529
624
|
const isProduction = process.env.NODE_ENV === "production";
|
|
530
|
-
const { serverUrl } = this.resolveViewRequestContext(extra);
|
|
625
|
+
const { serverUrl, assetsBasePath } = this.resolveViewRequestContext(extra);
|
|
626
|
+
// The view resolves all assets (template imports + runtime lazy chunks
|
|
627
|
+
// via `window.skybridge.serverUrl`) against this base, so it carries the
|
|
628
|
+
// proxy path prefix. CSP domains in `buildMeta` stay the bare origin.
|
|
629
|
+
const viewBase = `${serverUrl}${assetsBasePath}`;
|
|
531
630
|
const html = isProduction
|
|
532
631
|
? templateHelper.renderProduction({
|
|
533
632
|
hostType,
|
|
534
|
-
serverUrl,
|
|
633
|
+
serverUrl: viewBase,
|
|
535
634
|
viewFile: this.lookupViewFile(view.component),
|
|
536
635
|
styleFile: this.lookupDistFile("style.css") ?? "",
|
|
537
636
|
})
|
|
538
637
|
: templateHelper.renderDevelopment({
|
|
539
638
|
hostType,
|
|
540
|
-
serverUrl,
|
|
639
|
+
serverUrl: viewBase,
|
|
541
640
|
viewName: view.component,
|
|
542
641
|
});
|
|
543
642
|
return {
|
|
@@ -547,9 +646,29 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
547
646
|
};
|
|
548
647
|
});
|
|
549
648
|
}
|
|
550
|
-
|
|
649
|
+
serveLegacyAppsSdkUrl(component, canonicalUri) {
|
|
650
|
+
this.viewUriByPath.set(`ui://views/apps-sdk/${component}.html`, canonicalUri);
|
|
651
|
+
this.viewUriByPath.set(`ui://widgets/apps-sdk/${component}.html`, canonicalUri);
|
|
652
|
+
this.viewUriByPath.set(`ui://widgets/ext-apps/${component}.html`, canonicalUri);
|
|
653
|
+
}
|
|
654
|
+
decorateToolHandler(cb, { attachViewUUID, securitySchemes, toolName, }) {
|
|
551
655
|
return async (args, extra) => {
|
|
552
|
-
|
|
656
|
+
if (this.oauthEnabled) {
|
|
657
|
+
const failure = evaluateSecuritySchemes(securitySchemes, extra.http?.authInfo);
|
|
658
|
+
if (failure) {
|
|
659
|
+
const header = (key) => extra.http?.req?.headers.get(key) ?? undefined;
|
|
660
|
+
return inBandChallengeResult(failure, this.resolveResourceMetadataUrl?.(header));
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
let result;
|
|
664
|
+
try {
|
|
665
|
+
result = await cb(args, extra);
|
|
666
|
+
}
|
|
667
|
+
catch (error) {
|
|
668
|
+
captureToolError(extra, error);
|
|
669
|
+
throw error;
|
|
670
|
+
}
|
|
671
|
+
warnOnLargeToolOutput(result, toolName);
|
|
553
672
|
return {
|
|
554
673
|
...result,
|
|
555
674
|
content: normalizeContent(result.content),
|
|
@@ -611,16 +730,22 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
611
730
|
}
|
|
612
731
|
return JSON.parse(readFileSync(path.join(process.cwd(), "dist", "assets", ".vite", "manifest.json"), "utf-8"));
|
|
613
732
|
}
|
|
614
|
-
registerTool(
|
|
733
|
+
registerTool(rawConfig, rawCb) {
|
|
615
734
|
const baseFn = McpServerBase.prototype.registerTool;
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
735
|
+
const config = rawConfig;
|
|
736
|
+
const cb = rawCb;
|
|
737
|
+
const { name, view, auth, securitySchemes: rawSecuritySchemes, _meta: userToolMeta, ...toolFields } = config;
|
|
738
|
+
const authNeedsProvider = auth !== undefined &&
|
|
739
|
+
(!auth.allowsAnonymous || Boolean(auth.scopes?.length));
|
|
740
|
+
if (rawSecuritySchemes === undefined &&
|
|
741
|
+
authNeedsProvider &&
|
|
742
|
+
!this.oauthEnabled) {
|
|
743
|
+
throw new Error(`Tool "${name}" sets \`auth: ${JSON.stringify(auth)}\` but the server has no \`oauth\` provider configured.`);
|
|
619
744
|
}
|
|
620
|
-
const
|
|
621
|
-
|
|
622
|
-
const { name, view, securitySchemes, _meta: userToolMeta, ...toolFields } = config;
|
|
745
|
+
const securitySchemes = rawSecuritySchemes ??
|
|
746
|
+
(auth && this.oauthEnabled ? authToSecuritySchemes(auth) : undefined);
|
|
623
747
|
const toolMeta = { ...userToolMeta };
|
|
748
|
+
this.securitySchemesByTool.set(name, securitySchemes);
|
|
624
749
|
if (securitySchemes) {
|
|
625
750
|
// SEP-1488 puts `securitySchemes` at the top level of the tool
|
|
626
751
|
// descriptor, but the SDK's `registerTool` drops unknown top-level
|
|
@@ -633,8 +758,16 @@ export class McpServer extends McpServerBaseOmitted {
|
|
|
633
758
|
this.enforceOneToolPerView(view.component, name);
|
|
634
759
|
this.registerViewResources(name, view, toolMeta);
|
|
635
760
|
}
|
|
636
|
-
const wrappedCb = this.
|
|
637
|
-
|
|
761
|
+
const wrappedCb = this.decorateToolHandler(cb, {
|
|
762
|
+
attachViewUUID: Boolean(view),
|
|
763
|
+
securitySchemes,
|
|
764
|
+
toolName: name,
|
|
765
|
+
});
|
|
766
|
+
this.record((target) => {
|
|
767
|
+
baseFn.call(target, name, { ...toolFields, _meta: toolMeta }, toolFields.inputSchema === undefined
|
|
768
|
+
? (extra) => wrappedCb({}, extra)
|
|
769
|
+
: wrappedCb);
|
|
770
|
+
});
|
|
638
771
|
return this;
|
|
639
772
|
}
|
|
640
773
|
}
|