sunpeak 0.19.2 → 0.19.10
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 +6 -4
- package/bin/commands/dev.mjs +1 -1
- package/bin/commands/inspect.mjs +1 -1
- package/bin/commands/new.mjs +9 -5
- package/bin/commands/start.mjs +3 -1
- package/bin/commands/test-init.mjs +478 -76
- package/bin/commands/test.mjs +357 -4
- package/bin/lib/eval/eval-reporter.mjs +105 -0
- package/bin/lib/eval/eval-runner.mjs +310 -0
- package/bin/lib/eval/eval-types.d.mts +168 -0
- package/bin/lib/eval/eval-vitest-plugin.mjs +158 -0
- package/bin/lib/eval/model-registry.mjs +73 -0
- package/bin/lib/sandbox-server.mjs +5 -2
- package/bin/sunpeak.js +1 -0
- package/dist/chatgpt/index.cjs +1 -1
- package/dist/chatgpt/index.js +1 -1
- package/dist/claude/index.cjs +1 -1
- package/dist/claude/index.js +1 -1
- package/dist/host/chatgpt/index.cjs +1 -1
- package/dist/host/chatgpt/index.js +1 -1
- package/dist/index.cjs +134 -124
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +71 -62
- package/dist/index.js.map +1 -1
- package/dist/inspector/index.cjs +1 -1
- package/dist/inspector/index.js +1 -1
- package/dist/{inspector-Cdo5BK2D.js → inspector-D5DckQuU.js} +236 -98
- package/dist/inspector-D5DckQuU.js.map +1 -0
- package/dist/{inspector-8nPV2A-z.cjs → inspector-jY9O18z9.cjs} +237 -99
- package/dist/inspector-jY9O18z9.cjs.map +1 -0
- package/dist/mcp/index.cjs +237 -140
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +230 -134
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/production-server.d.ts +31 -0
- package/dist/{protocol-C7kTcBr_.cjs → protocol-C8pFDmcy.cjs} +8194 -8187
- package/dist/protocol-C8pFDmcy.cjs.map +1 -0
- package/dist/{protocol-BfAACnv0.js → protocol-CRqiPTLT.js} +8186 -8185
- package/dist/protocol-CRqiPTLT.js.map +1 -0
- package/dist/{use-app-CfP9VypY.js → use-app-Bfargfa3.js} +194 -94
- package/dist/use-app-Bfargfa3.js.map +1 -0
- package/dist/{use-app-CzcYw1Kz.cjs → use-app-CbsBEmwv.cjs} +254 -148
- package/dist/use-app-CbsBEmwv.cjs.map +1 -0
- package/package.json +27 -3
- package/template/README.md +17 -7
- package/template/_gitignore +2 -0
- package/template/dist/albums/albums.html +15 -15
- package/template/dist/albums/albums.json +1 -1
- package/template/dist/carousel/carousel.html +19 -19
- package/template/dist/carousel/carousel.json +1 -1
- package/template/dist/map/map.html +14 -14
- package/template/dist/map/map.json +1 -1
- package/template/dist/review/review.html +11 -11
- package/template/dist/review/review.json +1 -1
- package/template/node_modules/.bin/vitest +2 -2
- package/template/node_modules/.vite/deps/_metadata.json +3 -3
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +192 -91
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js +231 -92
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js +208 -105
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/_metadata.json +25 -25
- package/template/node_modules/.vite-mcp/deps/{protocol-B_qKkui_.js → protocol-BqGB4zBx.js} +45 -45
- package/template/node_modules/.vite-mcp/deps/protocol-BqGB4zBx.js.map +1 -0
- package/template/node_modules/.vite-mcp/deps/vitest.js +7 -7
- package/template/node_modules/.vite-mcp/deps/vitest.js.map +1 -1
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-chatgpt-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-claude-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-chatgpt-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-claude-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-chatgpt-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-claude-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-chatgpt-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-claude-darwin.png +0 -0
- package/template/tests/evals/.env.example +5 -0
- package/template/tests/evals/albums.eval.ts +28 -0
- package/template/tests/evals/carousel.eval.ts +26 -0
- package/template/tests/evals/eval.config.ts +26 -0
- package/template/tests/evals/map.eval.ts +23 -0
- package/template/tests/evals/review.eval.ts +48 -0
- package/dist/inspector-8nPV2A-z.cjs.map +0 -1
- package/dist/inspector-Cdo5BK2D.js.map +0 -1
- package/dist/protocol-BfAACnv0.js.map +0 -1
- package/dist/protocol-C7kTcBr_.cjs.map +0 -1
- package/dist/use-app-CfP9VypY.js.map +0 -1
- package/dist/use-app-CzcYw1Kz.cjs.map +0 -1
- package/template/node_modules/.vite-mcp/deps/protocol-B_qKkui_.js.map +0 -1
package/dist/mcp/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../chunk-9hOWP6kD.cjs");
|
|
3
|
-
const require_protocol = require("../protocol-
|
|
3
|
+
const require_protocol = require("../protocol-C8pFDmcy.cjs");
|
|
4
4
|
let node_http = require("node:http");
|
|
5
5
|
let node_url = require("node:url");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
@@ -8684,12 +8684,12 @@ var StreamableHTTPServerTransport = class {
|
|
|
8684
8684
|
}
|
|
8685
8685
|
};
|
|
8686
8686
|
//#endregion
|
|
8687
|
-
//#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.
|
|
8688
|
-
var
|
|
8687
|
+
//#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.5.0_@modelcontextprotocol+sdk@1.29.0_zod@4.3.6__react-_f4871531d9cf52c692eb6edc1ee416ef/node_modules/@modelcontextprotocol/ext-apps/dist/src/server/index.js
|
|
8688
|
+
var S = require_protocol.union([require_protocol.literal("light"), require_protocol.literal("dark")]).describe("Color theme preference for the host environment."), W = require_protocol.union([
|
|
8689
8689
|
require_protocol.literal("inline"),
|
|
8690
8690
|
require_protocol.literal("fullscreen"),
|
|
8691
8691
|
require_protocol.literal("pip")
|
|
8692
|
-
]).describe("Display mode for UI presentation."),
|
|
8692
|
+
]).describe("Display mode for UI presentation."), i = require_protocol.union([
|
|
8693
8693
|
require_protocol.literal("--color-background-primary"),
|
|
8694
8694
|
require_protocol.literal("--color-background-secondary"),
|
|
8695
8695
|
require_protocol.literal("--color-background-tertiary"),
|
|
@@ -8766,7 +8766,7 @@ var M = require_protocol.union([require_protocol.literal("light"), require_proto
|
|
|
8766
8766
|
require_protocol.literal("--shadow-sm"),
|
|
8767
8767
|
require_protocol.literal("--shadow-md"),
|
|
8768
8768
|
require_protocol.literal("--shadow-lg")
|
|
8769
|
-
]).describe("CSS variable keys available to MCP apps for theming."),
|
|
8769
|
+
]).describe("CSS variable keys available to MCP apps for theming."), n = require_protocol.record(i.describe(`Style variables for theming MCP apps.
|
|
8770
8770
|
|
|
8771
8771
|
Individual style keys are optional - hosts may provide any subset of these values.
|
|
8772
8772
|
Values are strings containing CSS values (colors, sizes, font stacks, etc.).
|
|
@@ -8796,7 +8796,7 @@ require_protocol.object({
|
|
|
8796
8796
|
method: require_protocol.literal("ui/notifications/sandbox-proxy-ready"),
|
|
8797
8797
|
params: require_protocol.object({})
|
|
8798
8798
|
});
|
|
8799
|
-
var
|
|
8799
|
+
var K = require_protocol.object({
|
|
8800
8800
|
connectDomains: require_protocol.array(require_protocol.string()).optional().describe(`Origins for network requests (fetch/XHR/WebSocket).
|
|
8801
8801
|
|
|
8802
8802
|
- Maps to CSP \`connect-src\` directive
|
|
@@ -8804,7 +8804,7 @@ var B = require_protocol.object({
|
|
|
8804
8804
|
resourceDomains: require_protocol.array(require_protocol.string()).optional().describe("Origins for static resources (images, scripts, stylesheets, fonts, media).\n\n- Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives\n- Wildcard subdomains supported: `https://*.example.com`\n- Empty or omitted → no network resources (secure default)"),
|
|
8805
8805
|
frameDomains: require_protocol.array(require_protocol.string()).optional().describe("Origins for nested iframes.\n\n- Maps to CSP `frame-src` directive\n- Empty or omitted → no nested iframes allowed (`frame-src 'none'`)"),
|
|
8806
8806
|
baseUriDomains: require_protocol.array(require_protocol.string()).optional().describe("Allowed base URIs for the document.\n\n- Maps to CSP `base-uri` directive\n- Empty or omitted → only same origin allowed (`base-uri 'self'`)")
|
|
8807
|
-
}),
|
|
8807
|
+
}), N = require_protocol.object({
|
|
8808
8808
|
camera: require_protocol.object({}).optional().describe("Request camera access.\n\nMaps to Permission Policy `camera` feature."),
|
|
8809
8809
|
microphone: require_protocol.object({}).optional().describe("Request microphone access.\n\nMaps to Permission Policy `microphone` feature."),
|
|
8810
8810
|
geolocation: require_protocol.object({}).optional().describe("Request geolocation access.\n\nMaps to Permission Policy `geolocation` feature."),
|
|
@@ -8829,8 +8829,8 @@ require_protocol.object({
|
|
|
8829
8829
|
method: require_protocol.literal("ui/notifications/tool-cancelled"),
|
|
8830
8830
|
params: require_protocol.object({ reason: require_protocol.string().optional().describe("Optional reason for the cancellation (e.g., \"user action\", \"timeout\").") })
|
|
8831
8831
|
});
|
|
8832
|
-
var b = require_protocol.object({ fonts: require_protocol.string().optional() }),
|
|
8833
|
-
variables:
|
|
8832
|
+
var b = require_protocol.object({ fonts: require_protocol.string().optional() }), C = require_protocol.object({
|
|
8833
|
+
variables: n.optional().describe("CSS variables for theming the app."),
|
|
8834
8834
|
css: b.optional().describe("CSS blocks that apps can inject.")
|
|
8835
8835
|
});
|
|
8836
8836
|
require_protocol.object({
|
|
@@ -8838,7 +8838,7 @@ require_protocol.object({
|
|
|
8838
8838
|
params: require_protocol.object({})
|
|
8839
8839
|
});
|
|
8840
8840
|
require_protocol.record(require_protocol.string(), require_protocol.unknown());
|
|
8841
|
-
var
|
|
8841
|
+
var q = require_protocol.object({
|
|
8842
8842
|
text: require_protocol.object({}).optional().describe("Host supports text content blocks."),
|
|
8843
8843
|
image: require_protocol.object({}).optional().describe("Host supports image content blocks."),
|
|
8844
8844
|
audio: require_protocol.object({}).optional().describe("Host supports audio content blocks."),
|
|
@@ -8850,7 +8850,7 @@ require_protocol.object({
|
|
|
8850
8850
|
method: require_protocol.literal("ui/notifications/request-teardown"),
|
|
8851
8851
|
params: require_protocol.object({}).optional()
|
|
8852
8852
|
});
|
|
8853
|
-
var
|
|
8853
|
+
var y = require_protocol.object({
|
|
8854
8854
|
experimental: require_protocol.object({}).optional().describe("Experimental features (structure TBD)."),
|
|
8855
8855
|
openLinks: require_protocol.object({}).optional().describe("Host supports opening external URLs."),
|
|
8856
8856
|
downloadFile: require_protocol.object({}).optional().describe("Host supports file downloads via ui/download-file."),
|
|
@@ -8858,23 +8858,23 @@ var S = require_protocol.object({
|
|
|
8858
8858
|
serverResources: require_protocol.object({ listChanged: require_protocol.boolean().optional().describe("Host supports resources/list_changed notifications.") }).optional().describe("Host can proxy resource reads to the MCP server."),
|
|
8859
8859
|
logging: require_protocol.object({}).optional().describe("Host accepts log messages."),
|
|
8860
8860
|
sandbox: require_protocol.object({
|
|
8861
|
-
permissions:
|
|
8862
|
-
csp:
|
|
8861
|
+
permissions: N.optional().describe("Permissions granted by the host (camera, microphone, geolocation)."),
|
|
8862
|
+
csp: K.optional().describe("CSP domains approved by the host.")
|
|
8863
8863
|
}).optional().describe("Sandbox configuration applied by the host."),
|
|
8864
|
-
updateModelContext:
|
|
8865
|
-
message:
|
|
8866
|
-
}),
|
|
8864
|
+
updateModelContext: q.optional().describe("Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns."),
|
|
8865
|
+
message: q.optional().describe("Host supports receiving content messages (ui/message) from the view.")
|
|
8866
|
+
}), v = require_protocol.object({
|
|
8867
8867
|
experimental: require_protocol.object({}).optional().describe("Experimental features (structure TBD)."),
|
|
8868
8868
|
tools: require_protocol.object({ listChanged: require_protocol.boolean().optional().describe("App supports tools/list_changed notifications.") }).optional().describe("App exposes MCP-style tools that the host can call."),
|
|
8869
|
-
availableDisplayModes: require_protocol.array(
|
|
8869
|
+
availableDisplayModes: require_protocol.array(W).optional().describe("Display modes the app supports.")
|
|
8870
8870
|
});
|
|
8871
8871
|
require_protocol.object({
|
|
8872
8872
|
method: require_protocol.literal("ui/notifications/initialized"),
|
|
8873
8873
|
params: require_protocol.object({}).optional()
|
|
8874
8874
|
});
|
|
8875
8875
|
require_protocol.object({
|
|
8876
|
-
csp:
|
|
8877
|
-
permissions:
|
|
8876
|
+
csp: K.optional().describe("Content Security Policy configuration for UI resources."),
|
|
8877
|
+
permissions: N.optional().describe("Sandbox permissions requested by the UI resource."),
|
|
8878
8878
|
domain: require_protocol.string().optional().describe(`Dedicated origin for view sandbox.
|
|
8879
8879
|
|
|
8880
8880
|
Useful when views need stable, dedicated origins for OAuth callbacks, CORS policies, or API key allowlists.
|
|
@@ -8894,13 +8894,13 @@ Boolean requesting whether a visible border and background is provided by the ho
|
|
|
8894
8894
|
});
|
|
8895
8895
|
require_protocol.object({
|
|
8896
8896
|
method: require_protocol.literal("ui/request-display-mode"),
|
|
8897
|
-
params: require_protocol.object({ mode:
|
|
8897
|
+
params: require_protocol.object({ mode: W.describe("The display mode being requested.") })
|
|
8898
8898
|
});
|
|
8899
|
-
require_protocol.object({ mode:
|
|
8900
|
-
var
|
|
8899
|
+
require_protocol.object({ mode: W.describe("The display mode that was actually set. May differ from requested if not supported.") }).passthrough();
|
|
8900
|
+
var f = require_protocol.union([require_protocol.literal("model"), require_protocol.literal("app")]).describe("Tool visibility scope - who can access the tool.");
|
|
8901
8901
|
require_protocol.object({
|
|
8902
8902
|
resourceUri: require_protocol.string().optional(),
|
|
8903
|
-
visibility: require_protocol.array(
|
|
8903
|
+
visibility: require_protocol.array(f).optional().describe(`Who can access this tool. Default: ["model", "app"]
|
|
8904
8904
|
- "model": Tool visible to and callable by the agent
|
|
8905
8905
|
- "app": Tool callable by the app from this server only`)
|
|
8906
8906
|
});
|
|
@@ -8921,8 +8921,8 @@ require_protocol.object({
|
|
|
8921
8921
|
params: require_protocol.object({
|
|
8922
8922
|
html: require_protocol.string().describe("HTML content to load into the inner iframe."),
|
|
8923
8923
|
sandbox: require_protocol.string().optional().describe("Optional override for the inner iframe's sandbox attribute."),
|
|
8924
|
-
csp:
|
|
8925
|
-
permissions:
|
|
8924
|
+
csp: K.optional().describe("CSP configuration from resource metadata."),
|
|
8925
|
+
permissions: N.optional().describe("Sandbox permissions from resource metadata.")
|
|
8926
8926
|
})
|
|
8927
8927
|
});
|
|
8928
8928
|
require_protocol.object({
|
|
@@ -8934,10 +8934,10 @@ var E = require_protocol.object({
|
|
|
8934
8934
|
id: require_protocol.RequestIdSchema.optional().describe("JSON-RPC id of the tools/call request."),
|
|
8935
8935
|
tool: require_protocol.ToolSchema.describe("Tool definition including name, inputSchema, etc.")
|
|
8936
8936
|
}).optional().describe("Metadata of the tool call that instantiated this App."),
|
|
8937
|
-
theme:
|
|
8938
|
-
styles:
|
|
8939
|
-
displayMode:
|
|
8940
|
-
availableDisplayModes: require_protocol.array(
|
|
8937
|
+
theme: S.optional().describe("Current color theme preference."),
|
|
8938
|
+
styles: C.optional().describe("Style configuration for theming the app."),
|
|
8939
|
+
displayMode: W.optional().describe("How the UI is currently displayed."),
|
|
8940
|
+
availableDisplayModes: require_protocol.array(W).optional().describe("Display modes the host supports."),
|
|
8941
8941
|
containerDimensions: require_protocol.union([require_protocol.object({ height: require_protocol.number().describe("Fixed container height in pixels.") }), require_protocol.object({ maxHeight: require_protocol.union([require_protocol.number(), require_protocol._undefined()]).optional().describe("Maximum container height in pixels.") })]).and(require_protocol.union([require_protocol.object({ width: require_protocol.number().describe("Fixed container width in pixels.") }), require_protocol.object({ maxWidth: require_protocol.union([require_protocol.number(), require_protocol._undefined()]).optional().describe("Maximum container width in pixels.") })])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
|
|
8942
8942
|
container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),
|
|
8943
8943
|
locale: require_protocol.string().optional().describe("User's language and region preference in BCP 47 format."),
|
|
@@ -8974,45 +8974,45 @@ require_protocol.object({
|
|
|
8974
8974
|
method: require_protocol.literal("ui/initialize"),
|
|
8975
8975
|
params: require_protocol.object({
|
|
8976
8976
|
appInfo: require_protocol.ImplementationSchema.describe("App identification (name and version)."),
|
|
8977
|
-
appCapabilities:
|
|
8977
|
+
appCapabilities: v.describe("Features and capabilities this app provides."),
|
|
8978
8978
|
protocolVersion: require_protocol.string().describe("Protocol version this app supports.")
|
|
8979
8979
|
})
|
|
8980
8980
|
});
|
|
8981
8981
|
require_protocol.object({
|
|
8982
8982
|
protocolVersion: require_protocol.string().describe("Negotiated protocol version string (e.g., \"2025-11-21\")."),
|
|
8983
8983
|
hostInfo: require_protocol.ImplementationSchema.describe("Host application identification and version."),
|
|
8984
|
-
hostCapabilities:
|
|
8984
|
+
hostCapabilities: y.describe("Features and capabilities provided by the host."),
|
|
8985
8985
|
hostContext: E.describe("Rich context about the host environment.")
|
|
8986
8986
|
}).passthrough();
|
|
8987
|
-
var
|
|
8988
|
-
function
|
|
8989
|
-
let V = J._meta,
|
|
8990
|
-
if (
|
|
8987
|
+
var M = "ui/resourceUri", u = "text/html;profile=mcp-app";
|
|
8988
|
+
function hZ(Z, $, J, X) {
|
|
8989
|
+
let V = J._meta, D = V.ui, G = V[M], L = V;
|
|
8990
|
+
if (D?.resourceUri && !G) L = {
|
|
8991
8991
|
...V,
|
|
8992
|
-
[
|
|
8992
|
+
[M]: D.resourceUri
|
|
8993
8993
|
};
|
|
8994
|
-
else if (
|
|
8994
|
+
else if (G && !D?.resourceUri) L = {
|
|
8995
8995
|
...V,
|
|
8996
8996
|
ui: {
|
|
8997
|
-
...
|
|
8998
|
-
resourceUri:
|
|
8997
|
+
...D,
|
|
8998
|
+
resourceUri: G
|
|
8999
8999
|
}
|
|
9000
9000
|
};
|
|
9001
9001
|
return Z.registerTool($, {
|
|
9002
9002
|
...J,
|
|
9003
|
-
_meta:
|
|
9003
|
+
_meta: L
|
|
9004
9004
|
}, X);
|
|
9005
9005
|
}
|
|
9006
|
-
function
|
|
9006
|
+
function mZ(Z, $, J, X, V) {
|
|
9007
9007
|
return Z.registerResource($, J, {
|
|
9008
|
-
mimeType:
|
|
9008
|
+
mimeType: u,
|
|
9009
9009
|
...X
|
|
9010
9010
|
}, V);
|
|
9011
9011
|
}
|
|
9012
|
-
var
|
|
9013
|
-
function
|
|
9012
|
+
var qQ = "io.modelcontextprotocol/ui";
|
|
9013
|
+
function pZ(Z) {
|
|
9014
9014
|
if (!Z) return;
|
|
9015
|
-
return Z.extensions?.[
|
|
9015
|
+
return Z.extensions?.[qQ];
|
|
9016
9016
|
}
|
|
9017
9017
|
//#endregion
|
|
9018
9018
|
//#region src/mcp/resolve-domain.ts
|
|
@@ -9327,7 +9327,7 @@ function createAppServer(config, simulations, viteMode) {
|
|
|
9327
9327
|
registeredUriSet.add(uri);
|
|
9328
9328
|
const listMeta = viteMode ? injectViteCSP(resourceMeta) : resourceMeta;
|
|
9329
9329
|
const handle = mcpServer.registerResource(resourceName, uri, {
|
|
9330
|
-
mimeType:
|
|
9330
|
+
mimeType: u,
|
|
9331
9331
|
description: resource.description,
|
|
9332
9332
|
_meta: listMeta
|
|
9333
9333
|
}, async (readUri, extra) => {
|
|
@@ -9346,7 +9346,7 @@ function createAppServer(config, simulations, viteMode) {
|
|
|
9346
9346
|
console.log(`[MCP] ReadResource: ${readUri.href} → ${sizeKB}KB${servedVite ? " (vite)" : " (built)"}`);
|
|
9347
9347
|
return { contents: [{
|
|
9348
9348
|
uri: readUri.href,
|
|
9349
|
-
mimeType:
|
|
9349
|
+
mimeType: u,
|
|
9350
9350
|
text: content,
|
|
9351
9351
|
_meta: readMeta
|
|
9352
9352
|
}] };
|
|
@@ -9360,7 +9360,7 @@ function createAppServer(config, simulations, viteMode) {
|
|
|
9360
9360
|
...toolMeta.ui?.visibility ? { visibility: toolMeta.ui.visibility } : {}
|
|
9361
9361
|
}
|
|
9362
9362
|
};
|
|
9363
|
-
const toolHandle =
|
|
9363
|
+
const toolHandle = hZ(mcpServer, tool.name, {
|
|
9364
9364
|
description: tool.description,
|
|
9365
9365
|
inputSchema: zod.z.object({}).passthrough(),
|
|
9366
9366
|
...simulation.outputSchema ? { outputSchema: simulation.outputSchema } : {},
|
|
@@ -9519,6 +9519,11 @@ async function handleMcpRequest(req, res, config, simulations, viteMode) {
|
|
|
9519
9519
|
const extra = parsed.method === "resources/read" ? ` uri=${JSON.stringify(parsed.params?.uri)}` : "";
|
|
9520
9520
|
console.log(`[MCP] ← ${parsed.method}${extra}${sidStr}`);
|
|
9521
9521
|
}
|
|
9522
|
+
if (process.env.SUNPEAK_LOG_HEADERS) {
|
|
9523
|
+
const headerEntries = {};
|
|
9524
|
+
for (const [key, value] of Object.entries(req.headers)) if (value != null) headerEntries[key] = Array.isArray(value) ? value.join(", ") : value;
|
|
9525
|
+
console.log(`[MCP] Headers: ${JSON.stringify(headerEntries, null, 2)}`);
|
|
9526
|
+
}
|
|
9522
9527
|
} catch {
|
|
9523
9528
|
res.writeHead(400).end("Invalid JSON");
|
|
9524
9529
|
return;
|
|
@@ -9563,6 +9568,7 @@ async function handleMcpRequest(req, res, config, simulations, viteMode) {
|
|
|
9563
9568
|
return;
|
|
9564
9569
|
}
|
|
9565
9570
|
if (error.message?.includes("Server not initialized")) return;
|
|
9571
|
+
if (error.message?.includes("Only one SSE stream")) return;
|
|
9566
9572
|
const id = transport.sessionId;
|
|
9567
9573
|
console.error(`[MCP] Transport error${id ? ` (${id.substring(0, 8)}...)` : ""}:`, error);
|
|
9568
9574
|
};
|
|
@@ -9647,7 +9653,7 @@ function runMCPServer(config) {
|
|
|
9647
9653
|
viteServer.ws.handleUpgrade(request, socket, head);
|
|
9648
9654
|
});
|
|
9649
9655
|
httpServer.on("clientError", (err, socket) => {
|
|
9650
|
-
if (err.code === "ECONNRESET") {} else if (err.code === "HPE_INVALID_METHOD" && "rawPacket" in err && Buffer.isBuffer(err.rawPacket) && err.rawPacket[0]
|
|
9656
|
+
if (err.code === "ECONNRESET") {} else if (err.code === "HPE_INVALID_METHOD" && "rawPacket" in err && Buffer.isBuffer(err.rawPacket) && err.rawPacket[0] >= 20 && err.rawPacket[0] <= 24) console.error("Received HTTPS request on HTTP server. If you're using ngrok, make sure the upstream is http:// (not https://). Example: ngrok http 8000\nIf this only happens in Safari, use Chrome for `sunpeak dev` instead. Safari is not compatible with the dev server. Production deploys (`sunpeak start`) work in all browsers.");
|
|
9651
9657
|
else console.error("HTTP client error", err);
|
|
9652
9658
|
socket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
|
|
9653
9659
|
});
|
|
@@ -9741,6 +9747,20 @@ function log(level, msg, extra) {
|
|
|
9741
9747
|
else console.log(extra ? `${prefix} ${msg} ${JSON.stringify(extra)}` : `${prefix} ${msg}`);
|
|
9742
9748
|
}
|
|
9743
9749
|
}
|
|
9750
|
+
/** Build an InternalServerConfig from any handler config + detected client name. */
|
|
9751
|
+
function toInternalConfig(config, clientName) {
|
|
9752
|
+
return {
|
|
9753
|
+
name: config.name,
|
|
9754
|
+
version: config.version,
|
|
9755
|
+
serverInfo: config.serverInfo,
|
|
9756
|
+
tools: config.tools,
|
|
9757
|
+
resources: config.resources,
|
|
9758
|
+
serverUrl: config.serverUrl,
|
|
9759
|
+
enableJsonResponse: config.enableJsonResponse,
|
|
9760
|
+
stateless: config.stateless,
|
|
9761
|
+
_clientName: clientName
|
|
9762
|
+
};
|
|
9763
|
+
}
|
|
9744
9764
|
/**
|
|
9745
9765
|
* Create an MCP server with production tool handlers and pre-built resources.
|
|
9746
9766
|
*
|
|
@@ -9749,6 +9769,7 @@ function log(level, msg, extra) {
|
|
|
9749
9769
|
*/
|
|
9750
9770
|
function createProductionMcpServer(config) {
|
|
9751
9771
|
const { name = "sunpeak-app", version = "0.1.0", serverInfo, tools, resources, serverUrl } = config;
|
|
9772
|
+
const clientName = config._clientName;
|
|
9752
9773
|
const mcpServer = new McpServer({
|
|
9753
9774
|
name: serverInfo?.name ?? name,
|
|
9754
9775
|
version: serverInfo?.version ?? version,
|
|
@@ -9764,23 +9785,9 @@ function createProductionMcpServer(config) {
|
|
|
9764
9785
|
resources: {},
|
|
9765
9786
|
tools: {}
|
|
9766
9787
|
} });
|
|
9767
|
-
let clientName;
|
|
9768
|
-
mcpServer.server.oninitialized = () => {
|
|
9769
|
-
clientName = mcpServer.server.getClientVersion()?.name;
|
|
9770
|
-
for (const handle of resourceHandles) {
|
|
9771
|
-
const currentMeta = handle.metadata?._meta;
|
|
9772
|
-
const resolved = injectResolvedDomain(currentMeta, clientName) ?? currentMeta;
|
|
9773
|
-
const withDefault = serverUrl ? injectDefaultDomain(resolved, clientName, serverUrl) : resolved;
|
|
9774
|
-
if (withDefault !== resolved) handle.update({ metadata: {
|
|
9775
|
-
...handle.metadata,
|
|
9776
|
-
_meta: withDefault
|
|
9777
|
-
} });
|
|
9778
|
-
}
|
|
9779
|
-
};
|
|
9780
9788
|
const resourceByName = /* @__PURE__ */ new Map();
|
|
9781
9789
|
for (const res of resources) resourceByName.set(res.name, res);
|
|
9782
9790
|
const registeredResources = /* @__PURE__ */ new Set();
|
|
9783
|
-
const resourceHandles = [];
|
|
9784
9791
|
let toolCount = 0;
|
|
9785
9792
|
for (const tool of tools) {
|
|
9786
9793
|
const makeCallback = () => {
|
|
@@ -9808,20 +9815,17 @@ function createProductionMcpServer(config) {
|
|
|
9808
9815
|
if (res) {
|
|
9809
9816
|
if (!registeredResources.has(res.uri)) {
|
|
9810
9817
|
registeredResources.add(res.uri);
|
|
9811
|
-
const
|
|
9818
|
+
const resolvedMeta = injectResolvedDomain(res._meta, clientName) ?? res._meta;
|
|
9819
|
+
const finalMeta = serverUrl ? injectDefaultDomain(resolvedMeta, clientName, serverUrl) : resolvedMeta;
|
|
9820
|
+
mZ(mcpServer, res.name, res.uri, {
|
|
9812
9821
|
description: res.description,
|
|
9813
|
-
_meta:
|
|
9814
|
-
}, async () => {
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
text: res.html,
|
|
9821
|
-
_meta: readMeta
|
|
9822
|
-
}] };
|
|
9823
|
-
});
|
|
9824
|
-
resourceHandles.push(handle);
|
|
9822
|
+
_meta: finalMeta
|
|
9823
|
+
}, async () => ({ contents: [{
|
|
9824
|
+
uri: res.uri,
|
|
9825
|
+
mimeType: u,
|
|
9826
|
+
text: res.html,
|
|
9827
|
+
_meta: finalMeta
|
|
9828
|
+
}] }));
|
|
9825
9829
|
}
|
|
9826
9830
|
const toolConfig = {
|
|
9827
9831
|
title: tool.tool.title,
|
|
@@ -9837,7 +9841,7 @@ function createProductionMcpServer(config) {
|
|
|
9837
9841
|
}
|
|
9838
9842
|
}
|
|
9839
9843
|
};
|
|
9840
|
-
|
|
9844
|
+
hZ(mcpServer, tool.name, toolConfig, makeCallback());
|
|
9841
9845
|
} else {
|
|
9842
9846
|
const cb = makeCallback();
|
|
9843
9847
|
const toolConfig = {
|
|
@@ -9864,6 +9868,20 @@ var SESSION_IDLE_TIMEOUT_MS = 300 * 1e3;
|
|
|
9864
9868
|
function isJsonRpcMessage(value) {
|
|
9865
9869
|
return typeof value === "object" && value !== null && typeof value.method === "string";
|
|
9866
9870
|
}
|
|
9871
|
+
function detectClientFromHeaders(headers) {
|
|
9872
|
+
const get = (name) => {
|
|
9873
|
+
if (headers instanceof Headers) return headers.get(name) ?? void 0;
|
|
9874
|
+
const raw = headers[name];
|
|
9875
|
+
return typeof raw === "string" ? raw : Array.isArray(raw) ? raw[0] : void 0;
|
|
9876
|
+
};
|
|
9877
|
+
const ua = get("user-agent");
|
|
9878
|
+
if (ua) {
|
|
9879
|
+
if (/claude/i.test(ua)) return "claude";
|
|
9880
|
+
if (/openai/i.test(ua)) return "openai-mcp";
|
|
9881
|
+
}
|
|
9882
|
+
if (get("x-anthropic-client")) return "claude";
|
|
9883
|
+
if (get("x-openai-session")) return "openai-mcp";
|
|
9884
|
+
}
|
|
9867
9885
|
var CORS_HEADERS = {
|
|
9868
9886
|
"Access-Control-Allow-Origin": "*",
|
|
9869
9887
|
"Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
|
|
@@ -9934,25 +9952,14 @@ async function pipeWebResponseToNode(webResponse, res) {
|
|
|
9934
9952
|
* ```
|
|
9935
9953
|
*/
|
|
9936
9954
|
function createMcpHandler(config) {
|
|
9937
|
-
const sessions = /* @__PURE__ */ new Map();
|
|
9938
9955
|
const authFn = config.auth;
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9942
|
-
log("info", `Session expired: ${id.substring(0, 8)}...`, {
|
|
9943
|
-
sessionId: id,
|
|
9944
|
-
active: sessions.size - 1
|
|
9945
|
-
});
|
|
9946
|
-
session.server.close();
|
|
9947
|
-
}
|
|
9948
|
-
}, 6e4).unref();
|
|
9949
|
-
return async (req, res) => {
|
|
9950
|
-
if (!req.url) return;
|
|
9951
|
-
if (new node_url.URL(req.url, `http://${req.headers.host ?? "localhost"}`).pathname !== MCP_PATH) return;
|
|
9956
|
+
async function preamble(req, res) {
|
|
9957
|
+
if (!req.url) return null;
|
|
9958
|
+
if (new node_url.URL(req.url, `http://${req.headers.host ?? "localhost"}`).pathname !== MCP_PATH) return null;
|
|
9952
9959
|
if (req.method === "OPTIONS") {
|
|
9953
9960
|
res.writeHead(204, CORS_HEADERS);
|
|
9954
9961
|
res.end();
|
|
9955
|
-
return;
|
|
9962
|
+
return null;
|
|
9956
9963
|
}
|
|
9957
9964
|
let authInfo;
|
|
9958
9965
|
if (authFn) {
|
|
@@ -9963,7 +9970,7 @@ function createMcpHandler(config) {
|
|
|
9963
9970
|
"WWW-Authenticate": "Bearer"
|
|
9964
9971
|
});
|
|
9965
9972
|
res.end("Unauthorized");
|
|
9966
|
-
return;
|
|
9973
|
+
return null;
|
|
9967
9974
|
}
|
|
9968
9975
|
authInfo = result;
|
|
9969
9976
|
}
|
|
@@ -9986,12 +9993,58 @@ function createMcpHandler(config) {
|
|
|
9986
9993
|
const extra = parsedBody.method === "resources/read" ? ` uri=${JSON.stringify(parsedBody.params?.uri)}` : "";
|
|
9987
9994
|
log("info", `← ${parsedBody.method}${extra}${sidStr}`);
|
|
9988
9995
|
}
|
|
9996
|
+
if (process.env.SUNPEAK_LOG_HEADERS) {
|
|
9997
|
+
const headerEntries = {};
|
|
9998
|
+
for (const [key, value] of Object.entries(req.headers)) if (value != null) headerEntries[key] = Array.isArray(value) ? value.join(", ") : value;
|
|
9999
|
+
log("info", `Headers: ${JSON.stringify(headerEntries, null, 2)}`);
|
|
10000
|
+
}
|
|
9989
10001
|
} catch {
|
|
9990
10002
|
res.writeHead(400).end("Invalid JSON");
|
|
9991
|
-
return;
|
|
10003
|
+
return null;
|
|
9992
10004
|
}
|
|
9993
10005
|
}
|
|
9994
|
-
|
|
10006
|
+
return {
|
|
10007
|
+
authInfo,
|
|
10008
|
+
parsedBody,
|
|
10009
|
+
webRequest: nodeReqToWebRequest(req)
|
|
10010
|
+
};
|
|
10011
|
+
}
|
|
10012
|
+
if (config.stateless) return async (req, res) => {
|
|
10013
|
+
const ctx = await preamble(req, res);
|
|
10014
|
+
if (!ctx) return;
|
|
10015
|
+
if (req.method !== "POST") {
|
|
10016
|
+
res.writeHead(405, CORS_HEADERS);
|
|
10017
|
+
res.end("Method Not Allowed: stateless mode only supports POST");
|
|
10018
|
+
return;
|
|
10019
|
+
}
|
|
10020
|
+
const server = createProductionMcpServer(toInternalConfig(config, detectClientFromHeaders(req.headers)));
|
|
10021
|
+
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
10022
|
+
sessionIdGenerator: void 0,
|
|
10023
|
+
enableJsonResponse: config.enableJsonResponse ?? true
|
|
10024
|
+
});
|
|
10025
|
+
transport.onerror = (error) => {
|
|
10026
|
+
log("error", "Transport error (stateless)", { error: String(error) });
|
|
10027
|
+
};
|
|
10028
|
+
await server.connect(transport);
|
|
10029
|
+
await pipeWebResponseToNode(addCorsHeaders(await transport.handleRequest(ctx.webRequest, {
|
|
10030
|
+
parsedBody: ctx.parsedBody,
|
|
10031
|
+
authInfo: ctx.authInfo
|
|
10032
|
+
})), res);
|
|
10033
|
+
};
|
|
10034
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
10035
|
+
setInterval(() => {
|
|
10036
|
+
const now = Date.now();
|
|
10037
|
+
for (const [id, session] of sessions) if (now - session.lastActivity > SESSION_IDLE_TIMEOUT_MS) {
|
|
10038
|
+
log("info", `Session expired: ${id.substring(0, 8)}...`, {
|
|
10039
|
+
sessionId: id,
|
|
10040
|
+
active: sessions.size - 1
|
|
10041
|
+
});
|
|
10042
|
+
session.server.close();
|
|
10043
|
+
}
|
|
10044
|
+
}, 6e4).unref();
|
|
10045
|
+
return async (req, res) => {
|
|
10046
|
+
const ctx = await preamble(req, res);
|
|
10047
|
+
if (!ctx) return;
|
|
9995
10048
|
const sessionId = req.headers["mcp-session-id"];
|
|
9996
10049
|
if (sessionId) {
|
|
9997
10050
|
const session = sessions.get(sessionId);
|
|
@@ -10000,14 +10053,14 @@ function createMcpHandler(config) {
|
|
|
10000
10053
|
return;
|
|
10001
10054
|
}
|
|
10002
10055
|
session.lastActivity = Date.now();
|
|
10003
|
-
await pipeWebResponseToNode(addCorsHeaders(await session.transport.handleRequest(webRequest, {
|
|
10004
|
-
parsedBody,
|
|
10005
|
-
authInfo
|
|
10056
|
+
await pipeWebResponseToNode(addCorsHeaders(await session.transport.handleRequest(ctx.webRequest, {
|
|
10057
|
+
parsedBody: ctx.parsedBody,
|
|
10058
|
+
authInfo: ctx.authInfo
|
|
10006
10059
|
})), res);
|
|
10007
10060
|
return;
|
|
10008
10061
|
}
|
|
10009
10062
|
if (req.method === "POST") {
|
|
10010
|
-
const server = createProductionMcpServer(config);
|
|
10063
|
+
const server = createProductionMcpServer(toInternalConfig(config, detectClientFromHeaders(req.headers)));
|
|
10011
10064
|
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
10012
10065
|
sessionIdGenerator: () => (0, node_crypto.randomUUID)(),
|
|
10013
10066
|
enableJsonResponse: config.enableJsonResponse ?? true,
|
|
@@ -10048,9 +10101,9 @@ function createMcpHandler(config) {
|
|
|
10048
10101
|
}
|
|
10049
10102
|
};
|
|
10050
10103
|
await server.connect(transport);
|
|
10051
|
-
await pipeWebResponseToNode(addCorsHeaders(await transport.handleRequest(webRequest, {
|
|
10052
|
-
parsedBody,
|
|
10053
|
-
authInfo
|
|
10104
|
+
await pipeWebResponseToNode(addCorsHeaders(await transport.handleRequest(ctx.webRequest, {
|
|
10105
|
+
parsedBody: ctx.parsedBody,
|
|
10106
|
+
authInfo: ctx.authInfo
|
|
10054
10107
|
})), res);
|
|
10055
10108
|
return;
|
|
10056
10109
|
}
|
|
@@ -10088,19 +10141,8 @@ function createMcpHandler(config) {
|
|
|
10088
10141
|
* ```
|
|
10089
10142
|
*/
|
|
10090
10143
|
function createHandler(config) {
|
|
10091
|
-
const sessions = /* @__PURE__ */ new Map();
|
|
10092
10144
|
const authFn = config.auth;
|
|
10093
|
-
|
|
10094
|
-
const now = Date.now();
|
|
10095
|
-
for (const [id, session] of sessions) if (now - session.lastActivity > SESSION_IDLE_TIMEOUT_MS) {
|
|
10096
|
-
log("info", `Session expired: ${id.substring(0, 8)}...`, {
|
|
10097
|
-
sessionId: id,
|
|
10098
|
-
active: sessions.size - 1
|
|
10099
|
-
});
|
|
10100
|
-
session.server.close();
|
|
10101
|
-
}
|
|
10102
|
-
}, 6e4).unref();
|
|
10103
|
-
return async (req) => {
|
|
10145
|
+
async function webPreamble(req) {
|
|
10104
10146
|
if (req.method === "OPTIONS") return new Response(null, {
|
|
10105
10147
|
status: 204,
|
|
10106
10148
|
headers: CORS_HEADERS
|
|
@@ -10118,31 +10160,75 @@ function createHandler(config) {
|
|
|
10118
10160
|
authInfo = result;
|
|
10119
10161
|
}
|
|
10120
10162
|
let parsedBody;
|
|
10121
|
-
if (req.method === "POST")
|
|
10122
|
-
|
|
10123
|
-
|
|
10124
|
-
|
|
10163
|
+
if (req.method === "POST") {
|
|
10164
|
+
try {
|
|
10165
|
+
parsedBody = await req.json();
|
|
10166
|
+
} catch {
|
|
10167
|
+
return new Response("Invalid JSON", { status: 400 });
|
|
10168
|
+
}
|
|
10169
|
+
if (isJsonRpcMessage(parsedBody)) {
|
|
10170
|
+
const sid = req.headers.get("mcp-session-id");
|
|
10171
|
+
const sidStr = sid ? ` (${sid.substring(0, 8)}...)` : "";
|
|
10172
|
+
const extra = parsedBody.method === "resources/read" ? ` uri=${JSON.stringify(parsedBody.params?.uri)}` : "";
|
|
10173
|
+
log("info", `← ${parsedBody.method}${extra}${sidStr}`);
|
|
10174
|
+
}
|
|
10175
|
+
if (typeof globalThis.process !== "undefined" && globalThis.process.env?.SUNPEAK_LOG_HEADERS) {
|
|
10176
|
+
const headerEntries = {};
|
|
10177
|
+
req.headers.forEach((value, key) => {
|
|
10178
|
+
headerEntries[key] = value;
|
|
10179
|
+
});
|
|
10180
|
+
log("info", `Headers: ${JSON.stringify(headerEntries, null, 2)}`);
|
|
10181
|
+
}
|
|
10182
|
+
}
|
|
10183
|
+
return {
|
|
10184
|
+
authInfo,
|
|
10185
|
+
parsedBody
|
|
10186
|
+
};
|
|
10187
|
+
}
|
|
10188
|
+
if (config.stateless) return async (req) => {
|
|
10189
|
+
const ctx = await webPreamble(req);
|
|
10190
|
+
if (ctx instanceof Response) return ctx;
|
|
10191
|
+
if (req.method !== "POST") return addCorsHeaders(new Response("Method Not Allowed: stateless mode only supports POST", { status: 405 }));
|
|
10192
|
+
const server = createProductionMcpServer(toInternalConfig(config, detectClientFromHeaders(req.headers)));
|
|
10193
|
+
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
10194
|
+
sessionIdGenerator: void 0,
|
|
10195
|
+
enableJsonResponse: config.enableJsonResponse ?? true
|
|
10196
|
+
});
|
|
10197
|
+
transport.onerror = (error) => {
|
|
10198
|
+
log("error", "Transport error (stateless)", { error: String(error) });
|
|
10199
|
+
};
|
|
10200
|
+
await server.connect(transport);
|
|
10201
|
+
return addCorsHeaders(await transport.handleRequest(req, {
|
|
10202
|
+
parsedBody: ctx.parsedBody,
|
|
10203
|
+
authInfo: ctx.authInfo
|
|
10204
|
+
}));
|
|
10205
|
+
};
|
|
10206
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
10207
|
+
setInterval(() => {
|
|
10208
|
+
const now = Date.now();
|
|
10209
|
+
for (const [id, session] of sessions) if (now - session.lastActivity > SESSION_IDLE_TIMEOUT_MS) {
|
|
10210
|
+
log("info", `Session expired: ${id.substring(0, 8)}...`, {
|
|
10211
|
+
sessionId: id,
|
|
10212
|
+
active: sessions.size - 1
|
|
10213
|
+
});
|
|
10214
|
+
session.server.close();
|
|
10125
10215
|
}
|
|
10216
|
+
}, 6e4).unref();
|
|
10217
|
+
return async (req) => {
|
|
10218
|
+
const ctx = await webPreamble(req);
|
|
10219
|
+
if (ctx instanceof Response) return ctx;
|
|
10126
10220
|
const sessionId = req.headers.get("mcp-session-id");
|
|
10127
10221
|
if (sessionId) {
|
|
10128
10222
|
const session = sessions.get(sessionId);
|
|
10129
10223
|
if (!session) return new Response("Unknown session", { status: 404 });
|
|
10130
10224
|
session.lastActivity = Date.now();
|
|
10131
10225
|
return addCorsHeaders(await session.transport.handleRequest(req, {
|
|
10132
|
-
parsedBody,
|
|
10133
|
-
authInfo
|
|
10226
|
+
parsedBody: ctx.parsedBody,
|
|
10227
|
+
authInfo: ctx.authInfo
|
|
10134
10228
|
}));
|
|
10135
10229
|
}
|
|
10136
10230
|
if (req.method === "POST") {
|
|
10137
|
-
const
|
|
10138
|
-
const server = createProductionMcpServer({
|
|
10139
|
-
name,
|
|
10140
|
-
version,
|
|
10141
|
-
serverInfo,
|
|
10142
|
-
tools,
|
|
10143
|
-
resources,
|
|
10144
|
-
serverUrl
|
|
10145
|
-
});
|
|
10231
|
+
const server = createProductionMcpServer(toInternalConfig(config, detectClientFromHeaders(req.headers)));
|
|
10146
10232
|
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
10147
10233
|
sessionIdGenerator: () => (0, node_crypto.randomUUID)(),
|
|
10148
10234
|
enableJsonResponse: config.enableJsonResponse ?? true,
|
|
@@ -10166,16 +10252,26 @@ function createHandler(config) {
|
|
|
10166
10252
|
}
|
|
10167
10253
|
});
|
|
10168
10254
|
transport.onerror = (error) => {
|
|
10169
|
-
|
|
10255
|
+
const id = transport.sessionId;
|
|
10256
|
+
log("error", `Transport error${id ? ` (${id.substring(0, 8)}...)` : ""}`, {
|
|
10257
|
+
sessionId: id,
|
|
10258
|
+
error: String(error)
|
|
10259
|
+
});
|
|
10170
10260
|
};
|
|
10171
10261
|
transport.onclose = () => {
|
|
10172
10262
|
const id = transport.sessionId;
|
|
10173
|
-
if (id && sessions.has(id))
|
|
10263
|
+
if (id && sessions.has(id)) {
|
|
10264
|
+
sessions.delete(id);
|
|
10265
|
+
log("info", `Session closed: ${id.substring(0, 8)}...`, {
|
|
10266
|
+
sessionId: id,
|
|
10267
|
+
active: sessions.size
|
|
10268
|
+
});
|
|
10269
|
+
}
|
|
10174
10270
|
};
|
|
10175
10271
|
await server.connect(transport);
|
|
10176
10272
|
return addCorsHeaders(await transport.handleRequest(req, {
|
|
10177
|
-
parsedBody,
|
|
10178
|
-
authInfo
|
|
10273
|
+
parsedBody: ctx.parsedBody,
|
|
10274
|
+
authInfo: ctx.authInfo
|
|
10179
10275
|
}));
|
|
10180
10276
|
}
|
|
10181
10277
|
return new Response("Bad Request: session ID required", { status: 400 });
|
|
@@ -10264,7 +10360,7 @@ function startProductionHttpServer(config, portOrOptions) {
|
|
|
10264
10360
|
}
|
|
10265
10361
|
});
|
|
10266
10362
|
httpServer.on("clientError", (err, socket) => {
|
|
10267
|
-
if (err.code === "HPE_INVALID_METHOD" && "rawPacket" in err && Buffer.isBuffer(err.rawPacket) && err.rawPacket[0]
|
|
10363
|
+
if (err.code === "ECONNRESET") {} else if (err.code === "HPE_INVALID_METHOD" && "rawPacket" in err && Buffer.isBuffer(err.rawPacket) && err.rawPacket[0] >= 20 && err.rawPacket[0] <= 24) log("error", "Received HTTPS request on HTTP server. If you're using ngrok, make sure the upstream is http:// (not https://). Example: ngrok http 8000");
|
|
10268
10364
|
else log("error", "HTTP client error", { error: err.message });
|
|
10269
10365
|
socket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
|
|
10270
10366
|
});
|
|
@@ -10299,22 +10395,23 @@ function startProductionHttpServer(config, portOrOptions) {
|
|
|
10299
10395
|
process.on("SIGINT", () => void shutdown());
|
|
10300
10396
|
}
|
|
10301
10397
|
//#endregion
|
|
10302
|
-
exports.EXTENSION_ID =
|
|
10398
|
+
exports.EXTENSION_ID = qQ;
|
|
10303
10399
|
exports.FAVICON_BASE64 = FAVICON_BASE64;
|
|
10304
10400
|
exports.FAVICON_BUFFER = FAVICON_BUFFER;
|
|
10305
10401
|
exports.FAVICON_DATA_URI = FAVICON_DATA_URI;
|
|
10306
|
-
exports.RESOURCE_MIME_TYPE =
|
|
10307
|
-
exports.RESOURCE_URI_META_KEY =
|
|
10402
|
+
exports.RESOURCE_MIME_TYPE = u;
|
|
10403
|
+
exports.RESOURCE_URI_META_KEY = M;
|
|
10308
10404
|
exports.computeChatGPTDomain = computeChatGPTDomain;
|
|
10309
10405
|
exports.computeClaudeDomain = computeClaudeDomain;
|
|
10310
10406
|
exports.createHandler = createHandler;
|
|
10311
10407
|
exports.createMcpHandler = createMcpHandler;
|
|
10312
10408
|
exports.createProductionMcpServer = createProductionMcpServer;
|
|
10313
|
-
exports.
|
|
10409
|
+
exports.detectClientFromHeaders = detectClientFromHeaders;
|
|
10410
|
+
exports.getUiCapability = pZ;
|
|
10314
10411
|
exports.injectDefaultDomain = injectDefaultDomain;
|
|
10315
10412
|
exports.injectResolvedDomain = injectResolvedDomain;
|
|
10316
|
-
exports.registerAppResource =
|
|
10317
|
-
exports.registerAppTool =
|
|
10413
|
+
exports.registerAppResource = mZ;
|
|
10414
|
+
exports.registerAppTool = hZ;
|
|
10318
10415
|
exports.resolveDomain = resolveDomain;
|
|
10319
10416
|
exports.runMCPServer = runMCPServer;
|
|
10320
10417
|
exports.setJsonLogging = setJsonLogging;
|