sunpeak 0.18.1 → 0.18.2

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.
@@ -9006,6 +9006,101 @@ function dZ(Z) {
9006
9006
  return Z.extensions?.[OQ];
9007
9007
  }
9008
9008
  //#endregion
9009
+ //#region src/mcp/resolve-domain.ts
9010
+ /**
9011
+ * Resolve a domain config to a single string for the given host.
9012
+ *
9013
+ * Lookup order: `map[clientName]` → `map['default']` → `undefined`.
9014
+ * If `domain` is a plain string, it's returned as-is regardless of host.
9015
+ */
9016
+ function resolveDomain(domain, clientName) {
9017
+ if (domain === void 0) return void 0;
9018
+ if (typeof domain === "string") return domain;
9019
+ if (clientName && domain[clientName]) return domain[clientName];
9020
+ return domain["default"];
9021
+ }
9022
+ /**
9023
+ * Compute the Claude sandbox domain for a given MCP server URL.
9024
+ *
9025
+ * Claude uses the first 32 hex characters of a SHA-256 hash of the server URL
9026
+ * as a subdomain of `claudemcpcontent.com`.
9027
+ *
9028
+ * @example
9029
+ * ```ts
9030
+ * computeClaudeDomain('https://example.com/mcp')
9031
+ * // → 'a904794854a047f6b936c2d62d57a3c0.claudemcpcontent.com'
9032
+ * ```
9033
+ */
9034
+ function computeClaudeDomain(serverUrl) {
9035
+ return `${(0, node_crypto.createHash)("sha256").update(serverUrl).digest("hex").slice(0, 32)}.claudemcpcontent.com`;
9036
+ }
9037
+ /**
9038
+ * Compute the ChatGPT sandbox domain for a given MCP server URL.
9039
+ *
9040
+ * ChatGPT derives a subdomain from the server URL by replacing non-alphanumeric
9041
+ * characters with hyphens and appending `.oaiusercontent.com`.
9042
+ *
9043
+ * @example
9044
+ * ```ts
9045
+ * computeChatGPTDomain('https://www.example.com/mcp')
9046
+ * // → 'www-example-com.oaiusercontent.com'
9047
+ * ```
9048
+ */
9049
+ function computeChatGPTDomain(serverUrl) {
9050
+ let hostname;
9051
+ try {
9052
+ hostname = new URL(serverUrl).hostname;
9053
+ } catch {
9054
+ hostname = serverUrl;
9055
+ }
9056
+ return `${hostname.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-|-$/g, "")}.oaiusercontent.com`;
9057
+ }
9058
+ /**
9059
+ * Inject a resolved domain into resource metadata.
9060
+ *
9061
+ * If the `_meta.ui.domain` field is a map (Record), it's resolved to a single
9062
+ * string using `clientName`. If it's already a string or absent, the metadata
9063
+ * is returned unchanged.
9064
+ */
9065
+ function injectResolvedDomain(meta, clientName) {
9066
+ if (!meta) return meta;
9067
+ const ui = meta.ui;
9068
+ if (!ui) return meta;
9069
+ const domain = ui.domain;
9070
+ if (domain === void 0 || typeof domain === "string") return meta;
9071
+ const resolved = resolveDomain(domain, clientName);
9072
+ const { domain: _removed, ...restUi } = ui;
9073
+ return {
9074
+ ...meta,
9075
+ ui: {
9076
+ ...restUi,
9077
+ ...resolved !== void 0 ? { domain: resolved } : {}
9078
+ }
9079
+ };
9080
+ }
9081
+ /**
9082
+ * Auto-compute a default domain for the connecting host when the resource
9083
+ * metadata has no domain set.
9084
+ *
9085
+ * Returns the metadata unchanged if `_meta.ui.domain` is already present.
9086
+ * Otherwise, computes a host-appropriate domain from the server URL.
9087
+ */
9088
+ function injectDefaultDomain(meta, clientName, serverUrl) {
9089
+ const ui = meta?.ui ?? {};
9090
+ if (typeof ui.domain === "string") return meta;
9091
+ let domain;
9092
+ if (clientName === "openai-mcp" || clientName?.startsWith("chatgpt")) domain = computeChatGPTDomain(serverUrl);
9093
+ else if (clientName === "claude") domain = computeClaudeDomain(serverUrl);
9094
+ if (!domain) return meta ?? {};
9095
+ return {
9096
+ ...meta,
9097
+ ui: {
9098
+ ...ui,
9099
+ domain
9100
+ }
9101
+ };
9102
+ }
9103
+ //#endregion
9009
9104
  //#region src/mcp/server.ts
9010
9105
  var localDevServerUrl = "http://localhost:8000";
9011
9106
  var localHmrWsUrl = "ws://localhost:24678";
@@ -9132,6 +9227,19 @@ function createAppServer(config, simulations, viteMode) {
9132
9227
  resources: {},
9133
9228
  tools: {}
9134
9229
  } });
9230
+ let clientName;
9231
+ mcpServer.server.oninitialized = () => {
9232
+ clientName = mcpServer.server.getClientVersion()?.name;
9233
+ for (const [, handle] of resourceHandles) {
9234
+ const currentMeta = handle.metadata?._meta;
9235
+ const resolved = injectResolvedDomain(currentMeta, clientName) ?? currentMeta;
9236
+ const withDefault = injectDefaultDomain(resolved, clientName, localDevServerUrl);
9237
+ if (withDefault !== resolved) handle.update({ metadata: {
9238
+ ...handle.metadata,
9239
+ _meta: withDefault
9240
+ } });
9241
+ }
9242
+ };
9135
9243
  const registeredUriSet = /* @__PURE__ */ new Set();
9136
9244
  const registeredToolNames = /* @__PURE__ */ new Set();
9137
9245
  const resourceHandles = /* @__PURE__ */ new Map();
@@ -9154,7 +9262,8 @@ function createAppServer(config, simulations, viteMode) {
9154
9262
  _meta: listMeta
9155
9263
  }, async (readUri, extra) => {
9156
9264
  const prodBuild = needsProdBuild(extra?.requestInfo?.headers ?? {});
9157
- const readMeta = viteMode && !prodBuild ? injectViteCSP(resourceMeta) : resourceMeta;
9265
+ const baseMeta = viteMode && !prodBuild ? injectViteCSP(resourceMeta) : resourceMeta;
9266
+ const readMeta = injectDefaultDomain(injectResolvedDomain(baseMeta, clientName) ?? baseMeta, clientName, localDevServerUrl);
9158
9267
  let content;
9159
9268
  try {
9160
9269
  content = getResourceHtml(simulation, viteMode, prodBuild);
@@ -9549,7 +9658,7 @@ function log(level, msg, extra) {
9549
9658
  * Resources serve pre-built HTML with their _meta preserved.
9550
9659
  */
9551
9660
  function createProductionMcpServer(config) {
9552
- const { name = "sunpeak-app", version = "0.1.0", serverInfo, tools, resources } = config;
9661
+ const { name = "sunpeak-app", version = "0.1.0", serverInfo, tools, resources, serverUrl } = config;
9553
9662
  const mcpServer = new McpServer({
9554
9663
  name: serverInfo?.name ?? name,
9555
9664
  version: serverInfo?.version ?? version,
@@ -9565,9 +9674,23 @@ function createProductionMcpServer(config) {
9565
9674
  resources: {},
9566
9675
  tools: {}
9567
9676
  } });
9677
+ let clientName;
9678
+ mcpServer.server.oninitialized = () => {
9679
+ clientName = mcpServer.server.getClientVersion()?.name;
9680
+ for (const handle of resourceHandles) {
9681
+ const currentMeta = handle.metadata?._meta;
9682
+ const resolved = injectResolvedDomain(currentMeta, clientName) ?? currentMeta;
9683
+ const withDefault = serverUrl ? injectDefaultDomain(resolved, clientName, serverUrl) : resolved;
9684
+ if (withDefault !== resolved) handle.update({ metadata: {
9685
+ ...handle.metadata,
9686
+ _meta: withDefault
9687
+ } });
9688
+ }
9689
+ };
9568
9690
  const resourceByName = /* @__PURE__ */ new Map();
9569
9691
  for (const res of resources) resourceByName.set(res.name, res);
9570
9692
  const registeredResources = /* @__PURE__ */ new Set();
9693
+ const resourceHandles = [];
9571
9694
  let toolCount = 0;
9572
9695
  for (const tool of tools) {
9573
9696
  const makeCallback = () => {
@@ -9595,15 +9718,20 @@ function createProductionMcpServer(config) {
9595
9718
  if (res) {
9596
9719
  if (!registeredResources.has(res.uri)) {
9597
9720
  registeredResources.add(res.uri);
9598
- fZ(mcpServer, res.name, res.uri, {
9721
+ const handle = fZ(mcpServer, res.name, res.uri, {
9599
9722
  description: res.description,
9600
9723
  _meta: res._meta
9601
- }, async () => ({ contents: [{
9602
- uri: res.uri,
9603
- mimeType: d,
9604
- text: res.html,
9605
- _meta: res._meta
9606
- }] }));
9724
+ }, async () => {
9725
+ const resolved = injectResolvedDomain(res._meta, clientName) ?? res._meta;
9726
+ const readMeta = serverUrl ? injectDefaultDomain(resolved, clientName, serverUrl) : resolved;
9727
+ return { contents: [{
9728
+ uri: res.uri,
9729
+ mimeType: d,
9730
+ text: res.html,
9731
+ _meta: readMeta
9732
+ }] };
9733
+ });
9734
+ resourceHandles.push(handle);
9607
9735
  }
9608
9736
  const toolConfig = {
9609
9737
  title: tool.tool.title,
@@ -9872,13 +10000,14 @@ function createHandler(config) {
9872
10000
  }));
9873
10001
  }
9874
10002
  if (req.method === "POST") {
9875
- const { name, version, serverInfo, tools, resources } = config;
10003
+ const { name, version, serverInfo, tools, resources, serverUrl } = config;
9876
10004
  const server = createProductionMcpServer({
9877
10005
  name,
9878
10006
  version,
9879
10007
  serverInfo,
9880
10008
  tools,
9881
- resources
10009
+ resources,
10010
+ serverUrl
9882
10011
  });
9883
10012
  const transport = new WebStandardStreamableHTTPServerTransport({
9884
10013
  sessionIdGenerator: () => (0, node_crypto.randomUUID)(),
@@ -10039,12 +10168,17 @@ exports.FAVICON_BUFFER = FAVICON_BUFFER;
10039
10168
  exports.FAVICON_DATA_URI = FAVICON_DATA_URI;
10040
10169
  exports.RESOURCE_MIME_TYPE = d;
10041
10170
  exports.RESOURCE_URI_META_KEY = v;
10171
+ exports.computeChatGPTDomain = computeChatGPTDomain;
10172
+ exports.computeClaudeDomain = computeClaudeDomain;
10042
10173
  exports.createHandler = createHandler;
10043
10174
  exports.createMcpHandler = createMcpHandler;
10044
10175
  exports.createProductionMcpServer = createProductionMcpServer;
10045
10176
  exports.getUiCapability = dZ;
10177
+ exports.injectDefaultDomain = injectDefaultDomain;
10178
+ exports.injectResolvedDomain = injectResolvedDomain;
10046
10179
  exports.registerAppResource = fZ;
10047
10180
  exports.registerAppTool = uZ;
10181
+ exports.resolveDomain = resolveDomain;
10048
10182
  exports.runMCPServer = runMCPServer;
10049
10183
  exports.setJsonLogging = setJsonLogging;
10050
10184
  exports.startProductionHttpServer = startProductionHttpServer;