sunpeak 0.19.2 → 0.19.4

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.
Files changed (65) hide show
  1. package/dist/chatgpt/index.cjs +1 -1
  2. package/dist/chatgpt/index.js +1 -1
  3. package/dist/claude/index.cjs +1 -1
  4. package/dist/claude/index.js +1 -1
  5. package/dist/host/chatgpt/index.cjs +1 -1
  6. package/dist/host/chatgpt/index.js +1 -1
  7. package/dist/index.cjs +134 -124
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.ts +3 -1
  10. package/dist/index.js +71 -62
  11. package/dist/index.js.map +1 -1
  12. package/dist/inspector/index.cjs +1 -1
  13. package/dist/inspector/index.js +1 -1
  14. package/dist/{inspector-Cdo5BK2D.js → inspector-Bp9jrHIu.js} +218 -80
  15. package/dist/inspector-Bp9jrHIu.js.map +1 -0
  16. package/dist/{inspector-8nPV2A-z.cjs → inspector-Cvq3yjNL.cjs} +219 -81
  17. package/dist/inspector-Cvq3yjNL.cjs.map +1 -0
  18. package/dist/mcp/index.cjs +235 -138
  19. package/dist/mcp/index.cjs.map +1 -1
  20. package/dist/mcp/index.d.ts +1 -1
  21. package/dist/mcp/index.js +228 -132
  22. package/dist/mcp/index.js.map +1 -1
  23. package/dist/mcp/production-server.d.ts +31 -0
  24. package/dist/{protocol-C7kTcBr_.cjs → protocol-C8pFDmcy.cjs} +8194 -8187
  25. package/dist/protocol-C8pFDmcy.cjs.map +1 -0
  26. package/dist/{protocol-BfAACnv0.js → protocol-CRqiPTLT.js} +8186 -8185
  27. package/dist/protocol-CRqiPTLT.js.map +1 -0
  28. package/dist/{use-app-CfP9VypY.js → use-app-Ck5kR1Sf.js} +193 -93
  29. package/dist/use-app-Ck5kR1Sf.js.map +1 -0
  30. package/dist/{use-app-CzcYw1Kz.cjs → use-app-DHYiev3D.cjs} +253 -147
  31. package/dist/use-app-DHYiev3D.cjs.map +1 -0
  32. package/package.json +2 -2
  33. package/template/dist/albums/albums.html +15 -15
  34. package/template/dist/albums/albums.json +1 -1
  35. package/template/dist/carousel/carousel.html +19 -19
  36. package/template/dist/carousel/carousel.json +1 -1
  37. package/template/dist/map/map.html +14 -14
  38. package/template/dist/map/map.json +1 -1
  39. package/template/dist/review/review.html +11 -11
  40. package/template/dist/review/review.json +1 -1
  41. package/template/node_modules/.vite/deps/_metadata.json +3 -3
  42. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +192 -91
  43. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js.map +1 -1
  44. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js +231 -92
  45. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js.map +1 -1
  46. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js +208 -105
  47. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
  48. package/template/node_modules/.vite-mcp/deps/_metadata.json +24 -24
  49. package/template/node_modules/.vite-mcp/deps/{protocol-B_qKkui_.js → protocol-BqGB4zBx.js} +45 -45
  50. package/template/node_modules/.vite-mcp/deps/protocol-BqGB4zBx.js.map +1 -0
  51. package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-chatgpt-darwin.png +0 -0
  52. package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-claude-darwin.png +0 -0
  53. package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-chatgpt-darwin.png +0 -0
  54. package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-claude-darwin.png +0 -0
  55. package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-chatgpt-darwin.png +0 -0
  56. package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-claude-darwin.png +0 -0
  57. package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-chatgpt-darwin.png +0 -0
  58. package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-claude-darwin.png +0 -0
  59. package/dist/inspector-8nPV2A-z.cjs.map +0 -1
  60. package/dist/inspector-Cdo5BK2D.js.map +0 -1
  61. package/dist/protocol-BfAACnv0.js.map +0 -1
  62. package/dist/protocol-C7kTcBr_.cjs.map +0 -1
  63. package/dist/use-app-CfP9VypY.js.map +0 -1
  64. package/dist/use-app-CzcYw1Kz.cjs.map +0 -1
  65. package/template/node_modules/.vite-mcp/deps/protocol-B_qKkui_.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  export { runMCPServer, type MCPServerConfig, type MCPServerHandle } from './server.js';
2
2
  export type { SimulationWithDist, AppToolConfig, ToolHandlerExtra, CallToolResult, AuthInfo, ServerConfig, } from './types.js';
3
- export { createMcpHandler, createHandler, createProductionMcpServer, startProductionHttpServer, setJsonLogging, } from './production-server.js';
3
+ export { createMcpHandler, createHandler, createProductionMcpServer, startProductionHttpServer, setJsonLogging, detectClientFromHeaders, } from './production-server.js';
4
4
  export type { ProductionTool, ProductionResource, ProductionServerConfig, HttpServerOptions, AuthFunction, WebAuthFunction, WebHandlerConfig, } from './production-server.js';
5
5
  export { resolveDomain, computeClaudeDomain, computeChatGPTDomain, injectResolvedDomain, injectDefaultDomain, } from './resolve-domain.js';
6
6
  export type { DomainConfig } from './resolve-domain.js';
package/dist/mcp/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as __toESM, i as __toCommonJS, n as __esmMin, r as __exportAll, t as __commonJSMin } from "../chunk-D6g4UhsZ.js";
2
- import { $ as literal, A as LoggingLevelSchema, B as SUPPORTED_PROTOCOL_VERSIONS, E as ListResourcesRequestSchema, F as ReadResourceRequestSchema, G as assertCompleteRequestResourceTemplate, J as isJSONRPCRequest, K as isInitializeRequest, L as RequestIdSchema, M as McpError, O as ListRootsResultSchema, Q as boolean, R as ResourceLinkSchema, S as ListPromptsRequestSchema, U as ToolSchema, V as SetLevelRequestSchema, W as assertCompleteRequestPrompt, X as _undefined, Y as isJSONRPCResultResponse, Z as array, _ as ImplementationSchema, a as CallToolResultSchema, at as unknown, b as JSONRPCMessageSchema, c as CreateMessageResultSchema, ct as getParseErrorMessage, dt as isZ4Schema, et as number, f as ElicitResultSchema, ft as normalizeObjectSchema, g as GetPromptRequestSchema, h as ErrorCode, ht as safeParseAsync, i as CallToolRequestSchema, it as union, k as ListToolsRequestSchema, l as CreateMessageResultWithToolsSchema, lt as getSchemaDescription, m as EmptyResultSchema, mt as safeParse, n as mergeCapabilities, nt as record, o as CompleteRequestSchema, ot as getLiteralValue, p as EmbeddedResourceSchema, pt as objectFromShape, q as isJSONRPCErrorResponse, r as toJsonSchemaCompat, rt as string, s as ContentBlockSchema, st as getObjectShape, t as Protocol, tt as object, u as CreateTaskResultSchema, ut as isSchemaOptional, v as InitializeRequestSchema, w as ListResourceTemplatesRequestSchema, x as LATEST_PROTOCOL_VERSION, y as InitializedNotificationSchema } from "../protocol-BfAACnv0.js";
2
+ import { A as JSONRPCMessageSchema, C as EmbeddedResourceSchema, D as ImplementationSchema, E as GetPromptRequestSchema, I as ListResourcesRequestSchema, J as RequestIdSchema, K as ReadResourceRequestSchema, M as ListPromptsRequestSchema, O as InitializeRequestSchema, P as ListResourceTemplatesRequestSchema, Q as SetLevelRequestSchema, R as ListRootsResultSchema, S as ElicitResultSchema, T as ErrorCode, U as McpError, V as LoggingLevelSchema, Y as ResourceLinkSchema, Z as SUPPORTED_PROTOCOL_VERSIONS, _ as ContentBlockSchema, a as getObjectShape, at as isJSONRPCRequest, b as CreateTaskResultSchema, c as isSchemaOptional, ct as array, d as objectFromShape, dt as number, et as ToolSchema, f as safeParse, ft as object, g as CompleteRequestSchema, gt as unknown, h as CallToolResultSchema, ht as union, i as getLiteralValue, it as isJSONRPCErrorResponse, j as LATEST_PROTOCOL_VERSION, k as InitializedNotificationSchema, l as isZ4Schema, lt as boolean, m as CallToolRequestSchema, mt as string, n as mergeCapabilities, nt as assertCompleteRequestResourceTemplate, o as getParseErrorMessage, ot as isJSONRPCResultResponse, p as safeParseAsync, pt as record, r as toJsonSchemaCompat, rt as isInitializeRequest, s as getSchemaDescription, st as _undefined, t as Protocol, tt as assertCompleteRequestPrompt, u as normalizeObjectSchema, ut as literal, v as CreateMessageResultSchema, w as EmptyResultSchema, y as CreateMessageResultWithToolsSchema, z as ListToolsRequestSchema } from "../protocol-CRqiPTLT.js";
3
3
  import { createServer } from "node:http";
4
4
  import { URL as URL$1 } from "node:url";
5
5
  import fs from "node:fs";
@@ -8680,12 +8680,12 @@ var StreamableHTTPServerTransport = class {
8680
8680
  }
8681
8681
  };
8682
8682
  //#endregion
8683
- //#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.3.2_@modelcontextprotocol+sdk@1.29.0_zod@4.3.6__react-_38e5f6c50a4ca9cf3f1dffc73a60c951/node_modules/@modelcontextprotocol/ext-apps/dist/src/server/index.js
8684
- var M = union([literal("light"), literal("dark")]).describe("Color theme preference for the host environment."), G = union([
8683
+ //#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
8684
+ var S = union([literal("light"), literal("dark")]).describe("Color theme preference for the host environment."), W = union([
8685
8685
  literal("inline"),
8686
8686
  literal("fullscreen"),
8687
8687
  literal("pip")
8688
- ]).describe("Display mode for UI presentation."), r = record(union([
8688
+ ]).describe("Display mode for UI presentation."), n = record(union([
8689
8689
  literal("--color-background-primary"),
8690
8690
  literal("--color-background-secondary"),
8691
8691
  literal("--color-background-tertiary"),
@@ -8792,7 +8792,7 @@ object({
8792
8792
  method: literal("ui/notifications/sandbox-proxy-ready"),
8793
8793
  params: object({})
8794
8794
  });
8795
- var B = object({
8795
+ var K = object({
8796
8796
  connectDomains: array(string()).optional().describe(`Origins for network requests (fetch/XHR/WebSocket).
8797
8797
 
8798
8798
  - Maps to CSP \`connect-src\` directive
@@ -8800,7 +8800,7 @@ var B = object({
8800
8800
  resourceDomains: array(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)"),
8801
8801
  frameDomains: array(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'`)"),
8802
8802
  baseUriDomains: array(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'`)")
8803
- }), K = object({
8803
+ }), N = object({
8804
8804
  camera: object({}).optional().describe("Request camera access.\n\nMaps to Permission Policy `camera` feature."),
8805
8805
  microphone: object({}).optional().describe("Request microphone access.\n\nMaps to Permission Policy `microphone` feature."),
8806
8806
  geolocation: object({}).optional().describe("Request geolocation access.\n\nMaps to Permission Policy `geolocation` feature."),
@@ -8825,8 +8825,8 @@ object({
8825
8825
  method: literal("ui/notifications/tool-cancelled"),
8826
8826
  params: object({ reason: string().optional().describe("Optional reason for the cancellation (e.g., \"user action\", \"timeout\").") })
8827
8827
  });
8828
- var b = object({ fonts: string().optional() }), g = object({
8829
- variables: r.optional().describe("CSS variables for theming the app."),
8828
+ var b = object({ fonts: string().optional() }), C = object({
8829
+ variables: n.optional().describe("CSS variables for theming the app."),
8830
8830
  css: b.optional().describe("CSS blocks that apps can inject.")
8831
8831
  });
8832
8832
  object({
@@ -8834,7 +8834,7 @@ object({
8834
8834
  params: object({})
8835
8835
  });
8836
8836
  record(string(), unknown());
8837
- var z$1 = object({
8837
+ var q = object({
8838
8838
  text: object({}).optional().describe("Host supports text content blocks."),
8839
8839
  image: object({}).optional().describe("Host supports image content blocks."),
8840
8840
  audio: object({}).optional().describe("Host supports audio content blocks."),
@@ -8846,7 +8846,7 @@ object({
8846
8846
  method: literal("ui/notifications/request-teardown"),
8847
8847
  params: object({}).optional()
8848
8848
  });
8849
- var S = object({
8849
+ var y = object({
8850
8850
  experimental: object({}).optional().describe("Experimental features (structure TBD)."),
8851
8851
  openLinks: object({}).optional().describe("Host supports opening external URLs."),
8852
8852
  downloadFile: object({}).optional().describe("Host supports file downloads via ui/download-file."),
@@ -8854,23 +8854,23 @@ var S = object({
8854
8854
  serverResources: object({ listChanged: boolean().optional().describe("Host supports resources/list_changed notifications.") }).optional().describe("Host can proxy resource reads to the MCP server."),
8855
8855
  logging: object({}).optional().describe("Host accepts log messages."),
8856
8856
  sandbox: object({
8857
- permissions: K.optional().describe("Permissions granted by the host (camera, microphone, geolocation)."),
8858
- csp: B.optional().describe("CSP domains approved by the host.")
8857
+ permissions: N.optional().describe("Permissions granted by the host (camera, microphone, geolocation)."),
8858
+ csp: K.optional().describe("CSP domains approved by the host.")
8859
8859
  }).optional().describe("Sandbox configuration applied by the host."),
8860
- updateModelContext: z$1.optional().describe("Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns."),
8861
- message: z$1.optional().describe("Host supports receiving content messages (ui/message) from the view.")
8862
- }), y = object({
8860
+ updateModelContext: q.optional().describe("Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns."),
8861
+ message: q.optional().describe("Host supports receiving content messages (ui/message) from the view.")
8862
+ }), v = object({
8863
8863
  experimental: object({}).optional().describe("Experimental features (structure TBD)."),
8864
8864
  tools: object({ listChanged: boolean().optional().describe("App supports tools/list_changed notifications.") }).optional().describe("App exposes MCP-style tools that the host can call."),
8865
- availableDisplayModes: array(G).optional().describe("Display modes the app supports.")
8865
+ availableDisplayModes: array(W).optional().describe("Display modes the app supports.")
8866
8866
  });
8867
8867
  object({
8868
8868
  method: literal("ui/notifications/initialized"),
8869
8869
  params: object({}).optional()
8870
8870
  });
8871
8871
  object({
8872
- csp: B.optional().describe("Content Security Policy configuration for UI resources."),
8873
- permissions: K.optional().describe("Sandbox permissions requested by the UI resource."),
8872
+ csp: K.optional().describe("Content Security Policy configuration for UI resources."),
8873
+ permissions: N.optional().describe("Sandbox permissions requested by the UI resource."),
8874
8874
  domain: string().optional().describe(`Dedicated origin for view sandbox.
8875
8875
 
8876
8876
  Useful when views need stable, dedicated origins for OAuth callbacks, CORS policies, or API key allowlists.
@@ -8890,13 +8890,13 @@ Boolean requesting whether a visible border and background is provided by the ho
8890
8890
  });
8891
8891
  object({
8892
8892
  method: literal("ui/request-display-mode"),
8893
- params: object({ mode: G.describe("The display mode being requested.") })
8893
+ params: object({ mode: W.describe("The display mode being requested.") })
8894
8894
  });
8895
- object({ mode: G.describe("The display mode that was actually set. May differ from requested if not supported.") }).passthrough();
8896
- var C = union([literal("model"), literal("app")]).describe("Tool visibility scope - who can access the tool.");
8895
+ object({ mode: W.describe("The display mode that was actually set. May differ from requested if not supported.") }).passthrough();
8896
+ var f = union([literal("model"), literal("app")]).describe("Tool visibility scope - who can access the tool.");
8897
8897
  object({
8898
8898
  resourceUri: string().optional(),
8899
- visibility: array(C).optional().describe(`Who can access this tool. Default: ["model", "app"]
8899
+ visibility: array(f).optional().describe(`Who can access this tool. Default: ["model", "app"]
8900
8900
  - "model": Tool visible to and callable by the agent
8901
8901
  - "app": Tool callable by the app from this server only`)
8902
8902
  });
@@ -8917,8 +8917,8 @@ object({
8917
8917
  params: object({
8918
8918
  html: string().describe("HTML content to load into the inner iframe."),
8919
8919
  sandbox: string().optional().describe("Optional override for the inner iframe's sandbox attribute."),
8920
- csp: B.optional().describe("CSP configuration from resource metadata."),
8921
- permissions: K.optional().describe("Sandbox permissions from resource metadata.")
8920
+ csp: K.optional().describe("CSP configuration from resource metadata."),
8921
+ permissions: N.optional().describe("Sandbox permissions from resource metadata.")
8922
8922
  })
8923
8923
  });
8924
8924
  object({
@@ -8930,10 +8930,10 @@ var E = object({
8930
8930
  id: RequestIdSchema.optional().describe("JSON-RPC id of the tools/call request."),
8931
8931
  tool: ToolSchema.describe("Tool definition including name, inputSchema, etc.")
8932
8932
  }).optional().describe("Metadata of the tool call that instantiated this App."),
8933
- theme: M.optional().describe("Current color theme preference."),
8934
- styles: g.optional().describe("Style configuration for theming the app."),
8935
- displayMode: G.optional().describe("How the UI is currently displayed."),
8936
- availableDisplayModes: array(G).optional().describe("Display modes the host supports."),
8933
+ theme: S.optional().describe("Current color theme preference."),
8934
+ styles: C.optional().describe("Style configuration for theming the app."),
8935
+ displayMode: W.optional().describe("How the UI is currently displayed."),
8936
+ availableDisplayModes: array(W).optional().describe("Display modes the host supports."),
8937
8937
  containerDimensions: union([object({ height: number().describe("Fixed container height in pixels.") }), object({ maxHeight: union([number(), _undefined()]).optional().describe("Maximum container height in pixels.") })]).and(union([object({ width: number().describe("Fixed container width in pixels.") }), object({ maxWidth: union([number(), _undefined()]).optional().describe("Maximum container width in pixels.") })])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
8938
8938
  container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),
8939
8939
  locale: string().optional().describe("User's language and region preference in BCP 47 format."),
@@ -8970,45 +8970,45 @@ object({
8970
8970
  method: literal("ui/initialize"),
8971
8971
  params: object({
8972
8972
  appInfo: ImplementationSchema.describe("App identification (name and version)."),
8973
- appCapabilities: y.describe("Features and capabilities this app provides."),
8973
+ appCapabilities: v.describe("Features and capabilities this app provides."),
8974
8974
  protocolVersion: string().describe("Protocol version this app supports.")
8975
8975
  })
8976
8976
  });
8977
8977
  object({
8978
8978
  protocolVersion: string().describe("Negotiated protocol version string (e.g., \"2025-11-21\")."),
8979
8979
  hostInfo: ImplementationSchema.describe("Host application identification and version."),
8980
- hostCapabilities: S.describe("Features and capabilities provided by the host."),
8980
+ hostCapabilities: y.describe("Features and capabilities provided by the host."),
8981
8981
  hostContext: E.describe("Rich context about the host environment.")
8982
8982
  }).passthrough();
8983
- var U = "ui/resourceUri", f = "text/html;profile=mcp-app";
8984
- function fZ(Z, $, J, X) {
8985
- let V = J._meta, W = V.ui, L = V[U], D = V;
8986
- if (W?.resourceUri && !L) D = {
8983
+ var M = "ui/resourceUri", u = "text/html;profile=mcp-app";
8984
+ function hZ(Z, $, J, X) {
8985
+ let V = J._meta, D = V.ui, G = V[M], L = V;
8986
+ if (D?.resourceUri && !G) L = {
8987
8987
  ...V,
8988
- [U]: W.resourceUri
8988
+ [M]: D.resourceUri
8989
8989
  };
8990
- else if (L && !W?.resourceUri) D = {
8990
+ else if (G && !D?.resourceUri) L = {
8991
8991
  ...V,
8992
8992
  ui: {
8993
- ...W,
8994
- resourceUri: L
8993
+ ...D,
8994
+ resourceUri: G
8995
8995
  }
8996
8996
  };
8997
8997
  return Z.registerTool($, {
8998
8998
  ...J,
8999
- _meta: D
8999
+ _meta: L
9000
9000
  }, X);
9001
9001
  }
9002
- function uZ(Z, $, J, X, V) {
9002
+ function mZ(Z, $, J, X, V) {
9003
9003
  return Z.registerResource($, J, {
9004
- mimeType: f,
9004
+ mimeType: u,
9005
9005
  ...X
9006
9006
  }, V);
9007
9007
  }
9008
- var zQ = "io.modelcontextprotocol/ui";
9009
- function dZ(Z) {
9008
+ var qQ = "io.modelcontextprotocol/ui";
9009
+ function pZ(Z) {
9010
9010
  if (!Z) return;
9011
- return Z.extensions?.[zQ];
9011
+ return Z.extensions?.[qQ];
9012
9012
  }
9013
9013
  //#endregion
9014
9014
  //#region src/mcp/resolve-domain.ts
@@ -9323,7 +9323,7 @@ function createAppServer(config, simulations, viteMode) {
9323
9323
  registeredUriSet.add(uri);
9324
9324
  const listMeta = viteMode ? injectViteCSP(resourceMeta) : resourceMeta;
9325
9325
  const handle = mcpServer.registerResource(resourceName, uri, {
9326
- mimeType: f,
9326
+ mimeType: u,
9327
9327
  description: resource.description,
9328
9328
  _meta: listMeta
9329
9329
  }, async (readUri, extra) => {
@@ -9342,7 +9342,7 @@ function createAppServer(config, simulations, viteMode) {
9342
9342
  console.log(`[MCP] ReadResource: ${readUri.href} → ${sizeKB}KB${servedVite ? " (vite)" : " (built)"}`);
9343
9343
  return { contents: [{
9344
9344
  uri: readUri.href,
9345
- mimeType: f,
9345
+ mimeType: u,
9346
9346
  text: content,
9347
9347
  _meta: readMeta
9348
9348
  }] };
@@ -9356,7 +9356,7 @@ function createAppServer(config, simulations, viteMode) {
9356
9356
  ...toolMeta.ui?.visibility ? { visibility: toolMeta.ui.visibility } : {}
9357
9357
  }
9358
9358
  };
9359
- const toolHandle = fZ(mcpServer, tool.name, {
9359
+ const toolHandle = hZ(mcpServer, tool.name, {
9360
9360
  description: tool.description,
9361
9361
  inputSchema: z.object({}).passthrough(),
9362
9362
  ...simulation.outputSchema ? { outputSchema: simulation.outputSchema } : {},
@@ -9515,6 +9515,11 @@ async function handleMcpRequest(req, res, config, simulations, viteMode) {
9515
9515
  const extra = parsed.method === "resources/read" ? ` uri=${JSON.stringify(parsed.params?.uri)}` : "";
9516
9516
  console.log(`[MCP] ← ${parsed.method}${extra}${sidStr}`);
9517
9517
  }
9518
+ if (process.env.SUNPEAK_LOG_HEADERS) {
9519
+ const headerEntries = {};
9520
+ for (const [key, value] of Object.entries(req.headers)) if (value != null) headerEntries[key] = Array.isArray(value) ? value.join(", ") : value;
9521
+ console.log(`[MCP] Headers: ${JSON.stringify(headerEntries, null, 2)}`);
9522
+ }
9518
9523
  } catch {
9519
9524
  res.writeHead(400).end("Invalid JSON");
9520
9525
  return;
@@ -9559,6 +9564,7 @@ async function handleMcpRequest(req, res, config, simulations, viteMode) {
9559
9564
  return;
9560
9565
  }
9561
9566
  if (error.message?.includes("Server not initialized")) return;
9567
+ if (error.message?.includes("Only one SSE stream")) return;
9562
9568
  const id = transport.sessionId;
9563
9569
  console.error(`[MCP] Transport error${id ? ` (${id.substring(0, 8)}...)` : ""}:`, error);
9564
9570
  };
@@ -9737,6 +9743,20 @@ function log(level, msg, extra) {
9737
9743
  else console.log(extra ? `${prefix} ${msg} ${JSON.stringify(extra)}` : `${prefix} ${msg}`);
9738
9744
  }
9739
9745
  }
9746
+ /** Build an InternalServerConfig from any handler config + detected client name. */
9747
+ function toInternalConfig(config, clientName) {
9748
+ return {
9749
+ name: config.name,
9750
+ version: config.version,
9751
+ serverInfo: config.serverInfo,
9752
+ tools: config.tools,
9753
+ resources: config.resources,
9754
+ serverUrl: config.serverUrl,
9755
+ enableJsonResponse: config.enableJsonResponse,
9756
+ stateless: config.stateless,
9757
+ _clientName: clientName
9758
+ };
9759
+ }
9740
9760
  /**
9741
9761
  * Create an MCP server with production tool handlers and pre-built resources.
9742
9762
  *
@@ -9745,6 +9765,7 @@ function log(level, msg, extra) {
9745
9765
  */
9746
9766
  function createProductionMcpServer(config) {
9747
9767
  const { name = "sunpeak-app", version = "0.1.0", serverInfo, tools, resources, serverUrl } = config;
9768
+ const clientName = config._clientName;
9748
9769
  const mcpServer = new McpServer({
9749
9770
  name: serverInfo?.name ?? name,
9750
9771
  version: serverInfo?.version ?? version,
@@ -9760,23 +9781,9 @@ function createProductionMcpServer(config) {
9760
9781
  resources: {},
9761
9782
  tools: {}
9762
9783
  } });
9763
- let clientName;
9764
- mcpServer.server.oninitialized = () => {
9765
- clientName = mcpServer.server.getClientVersion()?.name;
9766
- for (const handle of resourceHandles) {
9767
- const currentMeta = handle.metadata?._meta;
9768
- const resolved = injectResolvedDomain(currentMeta, clientName) ?? currentMeta;
9769
- const withDefault = serverUrl ? injectDefaultDomain(resolved, clientName, serverUrl) : resolved;
9770
- if (withDefault !== resolved) handle.update({ metadata: {
9771
- ...handle.metadata,
9772
- _meta: withDefault
9773
- } });
9774
- }
9775
- };
9776
9784
  const resourceByName = /* @__PURE__ */ new Map();
9777
9785
  for (const res of resources) resourceByName.set(res.name, res);
9778
9786
  const registeredResources = /* @__PURE__ */ new Set();
9779
- const resourceHandles = [];
9780
9787
  let toolCount = 0;
9781
9788
  for (const tool of tools) {
9782
9789
  const makeCallback = () => {
@@ -9804,20 +9811,17 @@ function createProductionMcpServer(config) {
9804
9811
  if (res) {
9805
9812
  if (!registeredResources.has(res.uri)) {
9806
9813
  registeredResources.add(res.uri);
9807
- const handle = uZ(mcpServer, res.name, res.uri, {
9814
+ const resolvedMeta = injectResolvedDomain(res._meta, clientName) ?? res._meta;
9815
+ const finalMeta = serverUrl ? injectDefaultDomain(resolvedMeta, clientName, serverUrl) : resolvedMeta;
9816
+ mZ(mcpServer, res.name, res.uri, {
9808
9817
  description: res.description,
9809
- _meta: res._meta
9810
- }, async () => {
9811
- const resolved = injectResolvedDomain(res._meta, clientName) ?? res._meta;
9812
- const readMeta = serverUrl ? injectDefaultDomain(resolved, clientName, serverUrl) : resolved;
9813
- return { contents: [{
9814
- uri: res.uri,
9815
- mimeType: f,
9816
- text: res.html,
9817
- _meta: readMeta
9818
- }] };
9819
- });
9820
- resourceHandles.push(handle);
9818
+ _meta: finalMeta
9819
+ }, async () => ({ contents: [{
9820
+ uri: res.uri,
9821
+ mimeType: u,
9822
+ text: res.html,
9823
+ _meta: finalMeta
9824
+ }] }));
9821
9825
  }
9822
9826
  const toolConfig = {
9823
9827
  title: tool.tool.title,
@@ -9833,7 +9837,7 @@ function createProductionMcpServer(config) {
9833
9837
  }
9834
9838
  }
9835
9839
  };
9836
- fZ(mcpServer, tool.name, toolConfig, makeCallback());
9840
+ hZ(mcpServer, tool.name, toolConfig, makeCallback());
9837
9841
  } else {
9838
9842
  const cb = makeCallback();
9839
9843
  const toolConfig = {
@@ -9860,6 +9864,20 @@ var SESSION_IDLE_TIMEOUT_MS = 300 * 1e3;
9860
9864
  function isJsonRpcMessage(value) {
9861
9865
  return typeof value === "object" && value !== null && typeof value.method === "string";
9862
9866
  }
9867
+ function detectClientFromHeaders(headers) {
9868
+ const get = (name) => {
9869
+ if (headers instanceof Headers) return headers.get(name) ?? void 0;
9870
+ const raw = headers[name];
9871
+ return typeof raw === "string" ? raw : Array.isArray(raw) ? raw[0] : void 0;
9872
+ };
9873
+ const ua = get("user-agent");
9874
+ if (ua) {
9875
+ if (/claude/i.test(ua)) return "claude";
9876
+ if (/openai/i.test(ua)) return "openai-mcp";
9877
+ }
9878
+ if (get("x-anthropic-client")) return "claude";
9879
+ if (get("x-openai-session")) return "openai-mcp";
9880
+ }
9863
9881
  var CORS_HEADERS = {
9864
9882
  "Access-Control-Allow-Origin": "*",
9865
9883
  "Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
@@ -9930,25 +9948,14 @@ async function pipeWebResponseToNode(webResponse, res) {
9930
9948
  * ```
9931
9949
  */
9932
9950
  function createMcpHandler(config) {
9933
- const sessions = /* @__PURE__ */ new Map();
9934
9951
  const authFn = config.auth;
9935
- setInterval(() => {
9936
- const now = Date.now();
9937
- for (const [id, session] of sessions) if (now - session.lastActivity > SESSION_IDLE_TIMEOUT_MS) {
9938
- log("info", `Session expired: ${id.substring(0, 8)}...`, {
9939
- sessionId: id,
9940
- active: sessions.size - 1
9941
- });
9942
- session.server.close();
9943
- }
9944
- }, 6e4).unref();
9945
- return async (req, res) => {
9946
- if (!req.url) return;
9947
- if (new URL$1(req.url, `http://${req.headers.host ?? "localhost"}`).pathname !== MCP_PATH) return;
9952
+ async function preamble(req, res) {
9953
+ if (!req.url) return null;
9954
+ if (new URL$1(req.url, `http://${req.headers.host ?? "localhost"}`).pathname !== MCP_PATH) return null;
9948
9955
  if (req.method === "OPTIONS") {
9949
9956
  res.writeHead(204, CORS_HEADERS);
9950
9957
  res.end();
9951
- return;
9958
+ return null;
9952
9959
  }
9953
9960
  let authInfo;
9954
9961
  if (authFn) {
@@ -9959,7 +9966,7 @@ function createMcpHandler(config) {
9959
9966
  "WWW-Authenticate": "Bearer"
9960
9967
  });
9961
9968
  res.end("Unauthorized");
9962
- return;
9969
+ return null;
9963
9970
  }
9964
9971
  authInfo = result;
9965
9972
  }
@@ -9982,12 +9989,58 @@ function createMcpHandler(config) {
9982
9989
  const extra = parsedBody.method === "resources/read" ? ` uri=${JSON.stringify(parsedBody.params?.uri)}` : "";
9983
9990
  log("info", `← ${parsedBody.method}${extra}${sidStr}`);
9984
9991
  }
9992
+ if (process.env.SUNPEAK_LOG_HEADERS) {
9993
+ const headerEntries = {};
9994
+ for (const [key, value] of Object.entries(req.headers)) if (value != null) headerEntries[key] = Array.isArray(value) ? value.join(", ") : value;
9995
+ log("info", `Headers: ${JSON.stringify(headerEntries, null, 2)}`);
9996
+ }
9985
9997
  } catch {
9986
9998
  res.writeHead(400).end("Invalid JSON");
9987
- return;
9999
+ return null;
9988
10000
  }
9989
10001
  }
9990
- const webRequest = nodeReqToWebRequest(req);
10002
+ return {
10003
+ authInfo,
10004
+ parsedBody,
10005
+ webRequest: nodeReqToWebRequest(req)
10006
+ };
10007
+ }
10008
+ if (config.stateless) return async (req, res) => {
10009
+ const ctx = await preamble(req, res);
10010
+ if (!ctx) return;
10011
+ if (req.method !== "POST") {
10012
+ res.writeHead(405, CORS_HEADERS);
10013
+ res.end("Method Not Allowed: stateless mode only supports POST");
10014
+ return;
10015
+ }
10016
+ const server = createProductionMcpServer(toInternalConfig(config, detectClientFromHeaders(req.headers)));
10017
+ const transport = new WebStandardStreamableHTTPServerTransport({
10018
+ sessionIdGenerator: void 0,
10019
+ enableJsonResponse: config.enableJsonResponse ?? true
10020
+ });
10021
+ transport.onerror = (error) => {
10022
+ log("error", "Transport error (stateless)", { error: String(error) });
10023
+ };
10024
+ await server.connect(transport);
10025
+ await pipeWebResponseToNode(addCorsHeaders(await transport.handleRequest(ctx.webRequest, {
10026
+ parsedBody: ctx.parsedBody,
10027
+ authInfo: ctx.authInfo
10028
+ })), res);
10029
+ };
10030
+ const sessions = /* @__PURE__ */ new Map();
10031
+ setInterval(() => {
10032
+ const now = Date.now();
10033
+ for (const [id, session] of sessions) if (now - session.lastActivity > SESSION_IDLE_TIMEOUT_MS) {
10034
+ log("info", `Session expired: ${id.substring(0, 8)}...`, {
10035
+ sessionId: id,
10036
+ active: sessions.size - 1
10037
+ });
10038
+ session.server.close();
10039
+ }
10040
+ }, 6e4).unref();
10041
+ return async (req, res) => {
10042
+ const ctx = await preamble(req, res);
10043
+ if (!ctx) return;
9991
10044
  const sessionId = req.headers["mcp-session-id"];
9992
10045
  if (sessionId) {
9993
10046
  const session = sessions.get(sessionId);
@@ -9996,14 +10049,14 @@ function createMcpHandler(config) {
9996
10049
  return;
9997
10050
  }
9998
10051
  session.lastActivity = Date.now();
9999
- await pipeWebResponseToNode(addCorsHeaders(await session.transport.handleRequest(webRequest, {
10000
- parsedBody,
10001
- authInfo
10052
+ await pipeWebResponseToNode(addCorsHeaders(await session.transport.handleRequest(ctx.webRequest, {
10053
+ parsedBody: ctx.parsedBody,
10054
+ authInfo: ctx.authInfo
10002
10055
  })), res);
10003
10056
  return;
10004
10057
  }
10005
10058
  if (req.method === "POST") {
10006
- const server = createProductionMcpServer(config);
10059
+ const server = createProductionMcpServer(toInternalConfig(config, detectClientFromHeaders(req.headers)));
10007
10060
  const transport = new WebStandardStreamableHTTPServerTransport({
10008
10061
  sessionIdGenerator: () => randomUUID(),
10009
10062
  enableJsonResponse: config.enableJsonResponse ?? true,
@@ -10044,9 +10097,9 @@ function createMcpHandler(config) {
10044
10097
  }
10045
10098
  };
10046
10099
  await server.connect(transport);
10047
- await pipeWebResponseToNode(addCorsHeaders(await transport.handleRequest(webRequest, {
10048
- parsedBody,
10049
- authInfo
10100
+ await pipeWebResponseToNode(addCorsHeaders(await transport.handleRequest(ctx.webRequest, {
10101
+ parsedBody: ctx.parsedBody,
10102
+ authInfo: ctx.authInfo
10050
10103
  })), res);
10051
10104
  return;
10052
10105
  }
@@ -10084,19 +10137,8 @@ function createMcpHandler(config) {
10084
10137
  * ```
10085
10138
  */
10086
10139
  function createHandler(config) {
10087
- const sessions = /* @__PURE__ */ new Map();
10088
10140
  const authFn = config.auth;
10089
- setInterval(() => {
10090
- const now = Date.now();
10091
- for (const [id, session] of sessions) if (now - session.lastActivity > SESSION_IDLE_TIMEOUT_MS) {
10092
- log("info", `Session expired: ${id.substring(0, 8)}...`, {
10093
- sessionId: id,
10094
- active: sessions.size - 1
10095
- });
10096
- session.server.close();
10097
- }
10098
- }, 6e4).unref();
10099
- return async (req) => {
10141
+ async function webPreamble(req) {
10100
10142
  if (req.method === "OPTIONS") return new Response(null, {
10101
10143
  status: 204,
10102
10144
  headers: CORS_HEADERS
@@ -10114,31 +10156,75 @@ function createHandler(config) {
10114
10156
  authInfo = result;
10115
10157
  }
10116
10158
  let parsedBody;
10117
- if (req.method === "POST") try {
10118
- parsedBody = await req.json();
10119
- } catch {
10120
- return new Response("Invalid JSON", { status: 400 });
10159
+ if (req.method === "POST") {
10160
+ try {
10161
+ parsedBody = await req.json();
10162
+ } catch {
10163
+ return new Response("Invalid JSON", { status: 400 });
10164
+ }
10165
+ if (isJsonRpcMessage(parsedBody)) {
10166
+ const sid = req.headers.get("mcp-session-id");
10167
+ const sidStr = sid ? ` (${sid.substring(0, 8)}...)` : "";
10168
+ const extra = parsedBody.method === "resources/read" ? ` uri=${JSON.stringify(parsedBody.params?.uri)}` : "";
10169
+ log("info", `← ${parsedBody.method}${extra}${sidStr}`);
10170
+ }
10171
+ if (typeof globalThis.process !== "undefined" && globalThis.process.env?.SUNPEAK_LOG_HEADERS) {
10172
+ const headerEntries = {};
10173
+ req.headers.forEach((value, key) => {
10174
+ headerEntries[key] = value;
10175
+ });
10176
+ log("info", `Headers: ${JSON.stringify(headerEntries, null, 2)}`);
10177
+ }
10178
+ }
10179
+ return {
10180
+ authInfo,
10181
+ parsedBody
10182
+ };
10183
+ }
10184
+ if (config.stateless) return async (req) => {
10185
+ const ctx = await webPreamble(req);
10186
+ if (ctx instanceof Response) return ctx;
10187
+ if (req.method !== "POST") return addCorsHeaders(new Response("Method Not Allowed: stateless mode only supports POST", { status: 405 }));
10188
+ const server = createProductionMcpServer(toInternalConfig(config, detectClientFromHeaders(req.headers)));
10189
+ const transport = new WebStandardStreamableHTTPServerTransport({
10190
+ sessionIdGenerator: void 0,
10191
+ enableJsonResponse: config.enableJsonResponse ?? true
10192
+ });
10193
+ transport.onerror = (error) => {
10194
+ log("error", "Transport error (stateless)", { error: String(error) });
10195
+ };
10196
+ await server.connect(transport);
10197
+ return addCorsHeaders(await transport.handleRequest(req, {
10198
+ parsedBody: ctx.parsedBody,
10199
+ authInfo: ctx.authInfo
10200
+ }));
10201
+ };
10202
+ const sessions = /* @__PURE__ */ new Map();
10203
+ setInterval(() => {
10204
+ const now = Date.now();
10205
+ for (const [id, session] of sessions) if (now - session.lastActivity > SESSION_IDLE_TIMEOUT_MS) {
10206
+ log("info", `Session expired: ${id.substring(0, 8)}...`, {
10207
+ sessionId: id,
10208
+ active: sessions.size - 1
10209
+ });
10210
+ session.server.close();
10121
10211
  }
10212
+ }, 6e4).unref();
10213
+ return async (req) => {
10214
+ const ctx = await webPreamble(req);
10215
+ if (ctx instanceof Response) return ctx;
10122
10216
  const sessionId = req.headers.get("mcp-session-id");
10123
10217
  if (sessionId) {
10124
10218
  const session = sessions.get(sessionId);
10125
10219
  if (!session) return new Response("Unknown session", { status: 404 });
10126
10220
  session.lastActivity = Date.now();
10127
10221
  return addCorsHeaders(await session.transport.handleRequest(req, {
10128
- parsedBody,
10129
- authInfo
10222
+ parsedBody: ctx.parsedBody,
10223
+ authInfo: ctx.authInfo
10130
10224
  }));
10131
10225
  }
10132
10226
  if (req.method === "POST") {
10133
- const { name, version, serverInfo, tools, resources, serverUrl } = config;
10134
- const server = createProductionMcpServer({
10135
- name,
10136
- version,
10137
- serverInfo,
10138
- tools,
10139
- resources,
10140
- serverUrl
10141
- });
10227
+ const server = createProductionMcpServer(toInternalConfig(config, detectClientFromHeaders(req.headers)));
10142
10228
  const transport = new WebStandardStreamableHTTPServerTransport({
10143
10229
  sessionIdGenerator: () => randomUUID(),
10144
10230
  enableJsonResponse: config.enableJsonResponse ?? true,
@@ -10162,16 +10248,26 @@ function createHandler(config) {
10162
10248
  }
10163
10249
  });
10164
10250
  transport.onerror = (error) => {
10165
- log("error", "Transport error", { error: String(error) });
10251
+ const id = transport.sessionId;
10252
+ log("error", `Transport error${id ? ` (${id.substring(0, 8)}...)` : ""}`, {
10253
+ sessionId: id,
10254
+ error: String(error)
10255
+ });
10166
10256
  };
10167
10257
  transport.onclose = () => {
10168
10258
  const id = transport.sessionId;
10169
- if (id && sessions.has(id)) sessions.delete(id);
10259
+ if (id && sessions.has(id)) {
10260
+ sessions.delete(id);
10261
+ log("info", `Session closed: ${id.substring(0, 8)}...`, {
10262
+ sessionId: id,
10263
+ active: sessions.size
10264
+ });
10265
+ }
10170
10266
  };
10171
10267
  await server.connect(transport);
10172
10268
  return addCorsHeaders(await transport.handleRequest(req, {
10173
- parsedBody,
10174
- authInfo
10269
+ parsedBody: ctx.parsedBody,
10270
+ authInfo: ctx.authInfo
10175
10271
  }));
10176
10272
  }
10177
10273
  return new Response("Bad Request: session ID required", { status: 400 });
@@ -10295,6 +10391,6 @@ function startProductionHttpServer(config, portOrOptions) {
10295
10391
  process.on("SIGINT", () => void shutdown());
10296
10392
  }
10297
10393
  //#endregion
10298
- export { zQ as EXTENSION_ID, FAVICON_BASE64, FAVICON_BUFFER, FAVICON_DATA_URI, f as RESOURCE_MIME_TYPE, U as RESOURCE_URI_META_KEY, computeChatGPTDomain, computeClaudeDomain, createHandler, createMcpHandler, createProductionMcpServer, dZ as getUiCapability, injectDefaultDomain, injectResolvedDomain, uZ as registerAppResource, fZ as registerAppTool, resolveDomain, runMCPServer, setJsonLogging, startProductionHttpServer };
10394
+ export { qQ as EXTENSION_ID, FAVICON_BASE64, FAVICON_BUFFER, FAVICON_DATA_URI, u as RESOURCE_MIME_TYPE, M as RESOURCE_URI_META_KEY, computeChatGPTDomain, computeClaudeDomain, createHandler, createMcpHandler, createProductionMcpServer, detectClientFromHeaders, pZ as getUiCapability, injectDefaultDomain, injectResolvedDomain, mZ as registerAppResource, hZ as registerAppTool, resolveDomain, runMCPServer, setJsonLogging, startProductionHttpServer };
10299
10395
 
10300
10396
  //# sourceMappingURL=index.js.map