skybridge 0.0.0-dev.fc2cd30 → 0.0.0-dev.fc2ea93

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 (155) hide show
  1. package/dist/commands/dev.js +1 -3
  2. package/dist/commands/dev.js.map +1 -1
  3. package/dist/server/auth/discovery.d.ts +32 -0
  4. package/dist/server/auth/discovery.js +56 -0
  5. package/dist/server/auth/discovery.js.map +1 -0
  6. package/dist/server/auth/discovery.test.d.ts +1 -0
  7. package/dist/server/auth/discovery.test.js +93 -0
  8. package/dist/server/auth/discovery.test.js.map +1 -0
  9. package/dist/server/auth/index.d.ts +18 -0
  10. package/dist/server/auth/index.js +2 -0
  11. package/dist/server/auth/index.js.map +1 -0
  12. package/dist/server/auth/providers/auth0.d.ts +18 -0
  13. package/dist/server/auth/providers/auth0.js +31 -0
  14. package/dist/server/auth/providers/auth0.js.map +1 -0
  15. package/dist/server/auth/providers/auth0.test.d.ts +1 -0
  16. package/dist/server/auth/providers/auth0.test.js +48 -0
  17. package/dist/server/auth/providers/auth0.test.js.map +1 -0
  18. package/dist/server/auth/providers/clerk.d.ts +14 -0
  19. package/dist/server/auth/providers/clerk.js +16 -0
  20. package/dist/server/auth/providers/clerk.js.map +1 -0
  21. package/dist/server/auth/providers/clerk.test.d.ts +1 -0
  22. package/dist/server/auth/providers/clerk.test.js +28 -0
  23. package/dist/server/auth/providers/clerk.test.js.map +1 -0
  24. package/dist/server/auth/providers/custom.d.ts +24 -0
  25. package/dist/server/auth/providers/custom.js +37 -0
  26. package/dist/server/auth/providers/custom.js.map +1 -0
  27. package/dist/server/auth/providers/custom.test.d.ts +1 -0
  28. package/dist/server/auth/providers/custom.test.js +107 -0
  29. package/dist/server/auth/providers/custom.test.js.map +1 -0
  30. package/dist/server/auth/providers/descope.d.ts +15 -0
  31. package/dist/server/auth/providers/descope.js +33 -0
  32. package/dist/server/auth/providers/descope.js.map +1 -0
  33. package/dist/server/auth/providers/descope.test.d.ts +1 -0
  34. package/dist/server/auth/providers/descope.test.js +37 -0
  35. package/dist/server/auth/providers/descope.test.js.map +1 -0
  36. package/dist/server/auth/providers/shared.d.ts +2 -0
  37. package/dist/server/auth/providers/shared.js +6 -0
  38. package/dist/server/auth/providers/shared.js.map +1 -0
  39. package/dist/server/auth/providers/shared.test.d.ts +1 -0
  40. package/dist/server/auth/providers/shared.test.js +10 -0
  41. package/dist/server/auth/providers/shared.test.js.map +1 -0
  42. package/dist/server/auth/providers/stytch.d.ts +12 -0
  43. package/dist/server/auth/providers/stytch.js +13 -0
  44. package/dist/server/auth/providers/stytch.js.map +1 -0
  45. package/dist/server/auth/providers/workos.d.ts +11 -0
  46. package/dist/server/auth/providers/workos.js +12 -0
  47. package/dist/server/auth/providers/workos.js.map +1 -0
  48. package/dist/server/auth/setup.d.ts +4 -0
  49. package/dist/server/auth/setup.js +51 -0
  50. package/dist/server/auth/setup.js.map +1 -0
  51. package/dist/server/auth/setup.test.d.ts +1 -0
  52. package/dist/server/auth/setup.test.js +185 -0
  53. package/dist/server/auth/setup.test.js.map +1 -0
  54. package/dist/server/auth/verify.d.ts +12 -0
  55. package/dist/server/auth/verify.js +38 -0
  56. package/dist/server/auth/verify.js.map +1 -0
  57. package/dist/server/auth/verify.test.d.ts +1 -0
  58. package/dist/server/auth/verify.test.js +100 -0
  59. package/dist/server/auth/verify.test.js.map +1 -0
  60. package/dist/server/express.test.js +31 -0
  61. package/dist/server/express.test.js.map +1 -1
  62. package/dist/server/index.d.ts +8 -1
  63. package/dist/server/index.js +6 -0
  64. package/dist/server/index.js.map +1 -1
  65. package/dist/server/requestOrigin.d.ts +7 -0
  66. package/dist/server/requestOrigin.js +25 -0
  67. package/dist/server/requestOrigin.js.map +1 -0
  68. package/dist/server/server.d.ts +46 -8
  69. package/dist/server/server.js +132 -122
  70. package/dist/server/server.js.map +1 -1
  71. package/dist/server/view-name.test-d.d.ts +1 -0
  72. package/dist/server/view-name.test-d.js +8 -0
  73. package/dist/server/view-name.test-d.js.map +1 -0
  74. package/dist/server/view-resource-resolution.test.d.ts +6 -0
  75. package/dist/server/view-resource-resolution.test.js +103 -0
  76. package/dist/server/view-resource-resolution.test.js.map +1 -0
  77. package/dist/test/view.test.js +69 -101
  78. package/dist/test/view.test.js.map +1 -1
  79. package/dist/web/bridges/adaptor.d.ts +51 -0
  80. package/dist/web/bridges/adaptor.js +310 -0
  81. package/dist/web/bridges/adaptor.js.map +1 -0
  82. package/dist/web/bridges/adaptor.test.d.ts +1 -0
  83. package/dist/web/bridges/adaptor.test.js +197 -0
  84. package/dist/web/bridges/adaptor.test.js.map +1 -0
  85. package/dist/web/bridges/apps-sdk/bridge.d.ts +6 -2
  86. package/dist/web/bridges/apps-sdk/bridge.js +15 -4
  87. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
  88. package/dist/web/bridges/apps-sdk/index.d.ts +0 -1
  89. package/dist/web/bridges/apps-sdk/index.js +0 -1
  90. package/dist/web/bridges/apps-sdk/index.js.map +1 -1
  91. package/dist/web/bridges/get-adaptor.d.ts +4 -4
  92. package/dist/web/bridges/get-adaptor.js +6 -11
  93. package/dist/web/bridges/get-adaptor.js.map +1 -1
  94. package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
  95. package/dist/web/bridges/get-adaptor.test.js +32 -0
  96. package/dist/web/bridges/get-adaptor.test.js.map +1 -0
  97. package/dist/web/bridges/mcp-app/bridge.d.ts +13 -2
  98. package/dist/web/bridges/mcp-app/bridge.js +46 -4
  99. package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
  100. package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
  101. package/dist/web/bridges/mcp-app/bridge.test.js +17 -0
  102. package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
  103. package/dist/web/bridges/mcp-app/index.d.ts +0 -1
  104. package/dist/web/bridges/mcp-app/index.js +0 -1
  105. package/dist/web/bridges/mcp-app/index.js.map +1 -1
  106. package/dist/web/bridges/mcp-app/view-tools.test.js +5 -6
  107. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -1
  108. package/dist/web/bridges/types.d.ts +10 -0
  109. package/dist/web/bridges/types.js +14 -1
  110. package/dist/web/bridges/types.js.map +1 -1
  111. package/dist/web/bridges/types.test.d.ts +1 -0
  112. package/dist/web/bridges/types.test.js +19 -0
  113. package/dist/web/bridges/types.test.js.map +1 -0
  114. package/dist/web/components/modal-provider.js +4 -3
  115. package/dist/web/components/modal-provider.js.map +1 -1
  116. package/dist/web/create-store.test.js +8 -5
  117. package/dist/web/create-store.test.js.map +1 -1
  118. package/dist/web/data-llm.test.js +9 -5
  119. package/dist/web/data-llm.test.js.map +1 -1
  120. package/dist/web/hooks/use-call-tool.test.js +37 -23
  121. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  122. package/dist/web/hooks/use-display-mode.test.js +56 -20
  123. package/dist/web/hooks/use-display-mode.test.js.map +1 -1
  124. package/dist/web/hooks/use-download.test.js +11 -3
  125. package/dist/web/hooks/use-download.test.js.map +1 -1
  126. package/dist/web/hooks/use-files.test.js +10 -2
  127. package/dist/web/hooks/use-files.test.js.map +1 -1
  128. package/dist/web/hooks/use-layout.test.js +59 -26
  129. package/dist/web/hooks/use-layout.test.js.map +1 -1
  130. package/dist/web/hooks/use-open-external.test.js +13 -3
  131. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  132. package/dist/web/hooks/use-request-close.test.js +35 -40
  133. package/dist/web/hooks/use-request-close.test.js.map +1 -1
  134. package/dist/web/hooks/use-request-modal.test.js +10 -0
  135. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  136. package/dist/web/hooks/use-request-size.test.js +35 -53
  137. package/dist/web/hooks/use-request-size.test.js.map +1 -1
  138. package/dist/web/hooks/use-set-open-in-app-url.test.js +28 -8
  139. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
  140. package/dist/web/hooks/use-tool-info.test.js +37 -27
  141. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  142. package/dist/web/hooks/use-user.test.js +81 -35
  143. package/dist/web/hooks/use-user.test.js.map +1 -1
  144. package/dist/web/hooks/use-view-state.test.js +6 -2
  145. package/dist/web/hooks/use-view-state.test.js.map +1 -1
  146. package/package.json +3 -2
  147. package/dist/cli/use-open-tunnel-browser.d.ts +0 -6
  148. package/dist/cli/use-open-tunnel-browser.js +0 -19
  149. package/dist/cli/use-open-tunnel-browser.js.map +0 -1
  150. package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -29
  151. package/dist/web/bridges/apps-sdk/adaptor.js +0 -117
  152. package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
  153. package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -53
  154. package/dist/web/bridges/mcp-app/adaptor.js +0 -283
  155. package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
@@ -6,9 +6,11 @@ import { Server as SdkServer, } from "@modelcontextprotocol/sdk/server/index.js"
6
6
  import { McpServer as McpServerBase } from "@modelcontextprotocol/sdk/server/mcp.js";
7
7
  import { mergeWith, union } from "es-toolkit";
8
8
  import express, {} from "express";
9
+ import { setupOAuth } from "./auth/setup.js";
9
10
  import { createApp } from "./express.js";
10
11
  import { createMiddlewareEntry } from "./metric.js";
11
12
  import { buildMiddlewareChain, getHandlerMaps } from "./middleware.js";
13
+ import { resolveServerOrigin } from "./requestOrigin.js";
12
14
  import { templateHelper } from "./templateHelper.js";
13
15
  const mergeWithUnion = (target, source) => {
14
16
  return mergeWith(target, source, (targetVal, sourceVal) => {
@@ -17,6 +19,15 @@ const mergeWithUnion = (target, source) => {
17
19
  }
18
20
  });
19
21
  };
22
+ /**
23
+ * Drop the query string from a `ui://` view URI, leaving the bare path. The
24
+ * `?v=` cache key is the only query we append, so a plain split is enough and
25
+ * sidesteps `URL` normalization quirks on the non-special `ui:` scheme.
26
+ */
27
+ function stripQuery(uri) {
28
+ const queryIndex = uri.indexOf("?");
29
+ return queryIndex === -1 ? uri : uri.slice(0, queryIndex);
30
+ }
20
31
  /**
21
32
  * Coerce a tool handler's return value into an MCP `content` array. Strings
22
33
  * become a single `TextContent`; a single block is wrapped in an array;
@@ -87,7 +98,9 @@ export class McpServer extends McpServerBaseOmitted {
87
98
  * custom routes, middleware, or settings — e.g.
88
99
  * `server.express.get("/health", ...)`.
89
100
  *
90
- * `express.json()` is pre-applied. Register your handlers before `run()`;
101
+ * `express.json()` is pre-applied tune it via the constructor's third
102
+ * argument, e.g. `new McpServer(info, {}, { json: { limit: "10mb" } })`.
103
+ * Register your handlers before `run()`;
91
104
  * after `run()`, dev-mode middleware, the `/mcp` route, and the default
92
105
  * error handler are appended in that order.
93
106
  *
@@ -100,15 +113,25 @@ export class McpServer extends McpServerBaseOmitted {
100
113
  mcpMiddlewareApplied = false;
101
114
  claimedViews = new Map();
102
115
  viewMetaBuilders = new Map();
116
+ /**
117
+ * Maps a view resource's query-less path to its canonical registered URI
118
+ * (the one carrying the `?v=` cache key). Lets `resources/read` resolve the
119
+ * underlying view no matter which version param the consumer sends, since
120
+ * the param is only a cache key, not part of the resource's identity.
121
+ */
122
+ viewUriByPath = new Map();
103
123
  viteManifest = null;
104
124
  serverInfo;
105
125
  serverOptions;
106
- constructor(serverInfo, options) {
126
+ constructor(serverInfo, options, skybridgeOptions) {
107
127
  super(serverInfo, options);
108
128
  this.serverInfo = serverInfo;
109
129
  this.serverOptions = options;
110
130
  this.express = express();
111
- this.express.use(express.json());
131
+ this.express.use(express.json(skybridgeOptions?.json));
132
+ if (skybridgeOptions?.oauth) {
133
+ setupOAuth(this.express, skybridgeOptions.oauth);
134
+ }
112
135
  // Pick up the manifest if `dist/__entry.js` primed it before importing
113
136
  // user code. Consume-once: clear after the first construction so a
114
137
  // subsequent test that doesn't prime can't inherit stale state.
@@ -190,10 +213,47 @@ export class McpServer extends McpServerBaseOmitted {
190
213
  return result;
191
214
  },
192
215
  };
216
+ // Resolve a view's `resources/read` by its query-less path so the
217
+ // underlying asset is served no matter the `?v=` value (stale cache key,
218
+ // no param, etc.). The version param is a cache-busting hint for external
219
+ // consumers; it must not gate resolution. We rewrite the lookup URI to the
220
+ // canonical registered one, then restore the requested URI on the response
221
+ // so the consumer-facing URI is never rewritten.
222
+ const viewReadResolveEntry = {
223
+ filter: "resources/read",
224
+ handler: async (req, _extra, next) => {
225
+ const requested = req.params.uri;
226
+ if (typeof requested !== "string") {
227
+ return next();
228
+ }
229
+ const path = stripQuery(requested);
230
+ const canonical = this.viewUriByPath.get(path);
231
+ if (!canonical) {
232
+ return next();
233
+ }
234
+ req.params.uri = canonical;
235
+ try {
236
+ const result = (await next());
237
+ for (const content of result.contents ?? []) {
238
+ if (typeof content.uri === "string" &&
239
+ stripQuery(content.uri) === stripQuery(canonical)) {
240
+ content.uri = requested;
241
+ }
242
+ }
243
+ return result;
244
+ }
245
+ finally {
246
+ // Restore the shared request params so middleware outer to us never
247
+ // observes the rewritten lookup URI after next() unwinds.
248
+ req.params.uri = requested;
249
+ }
250
+ },
251
+ };
193
252
  const monitoringEntry = createMiddlewareEntry();
194
253
  const entries = [
195
254
  ...(monitoringEntry ? [monitoringEntry] : []),
196
255
  viewListMetaEntry,
256
+ viewReadResolveEntry,
197
257
  ...this.mcpMiddlewareEntries,
198
258
  ];
199
259
  if (entries.length === 0) {
@@ -322,27 +382,7 @@ export class McpServer extends McpServerBaseOmitted {
322
382
  return Array.isArray(val) ? val[0] : val;
323
383
  };
324
384
  const isClaude = header("user-agent") === "Claude-User";
325
- let serverUrl;
326
- const forwardedHost = header("x-forwarded-host");
327
- const origin = header("origin");
328
- const host = header("host");
329
- if (forwardedHost) {
330
- const proto = header("x-forwarded-proto") || "https";
331
- serverUrl = `${proto}://${forwardedHost}`;
332
- }
333
- else if (origin) {
334
- serverUrl = origin;
335
- }
336
- else if (host) {
337
- const proto = ["127.0.0.1:", "localhost:"].some((p) => host.startsWith(p))
338
- ? "http"
339
- : "https";
340
- serverUrl = `${proto}://${host}`;
341
- }
342
- else {
343
- const devPort = process.env.__PORT || "3000";
344
- serverUrl = `http://localhost:${devPort}`;
345
- }
385
+ const serverUrl = resolveServerOrigin(header);
346
386
  const connectDomains = [serverUrl];
347
387
  if (!isProduction) {
348
388
  const wsUrl = new URL(serverUrl);
@@ -366,111 +406,74 @@ export class McpServer extends McpServerBaseOmitted {
366
406
  return { serverUrl, connectDomains, contentMetaOverrides };
367
407
  }
368
408
  registerViewResources(toolName, view, toolMeta) {
369
- const hosts = view.hosts ?? ["apps-sdk", "mcp-app"];
370
409
  // Append a content-derived version param so hosts (e.g. ChatGPT) bust
371
410
  // their cache when the bundle changes, but keep the URI stable across
372
411
  // `tools/list` calls when the bundle hasn't changed.
373
412
  const versionParam = this.computeViewVersionParam(view.component);
374
- if (hosts.includes("apps-sdk")) {
375
- const viewResource = {
376
- hostType: "apps-sdk",
377
- uri: `ui://views/apps-sdk/${view.component}.html${versionParam}`,
378
- mimeType: "text/html+skybridge",
379
- buildContentMeta: ({ resourceDomains, connectDomains, domain }, overrides) => {
380
- const defaults = {
381
- "openai/widgetCSP": {
382
- resource_domains: resourceDomains,
383
- connect_domains: connectDomains,
384
- },
385
- "openai/widgetDomain": domain,
386
- "openai/widgetDescription": view.description,
387
- };
388
- const fromView = {
389
- "openai/widgetCSP": {
390
- resource_domains: view.csp?.resourceDomains,
391
- connect_domains: view.csp?.connectDomains,
392
- frame_domains: view.csp?.frameDomains,
393
- redirect_domains: view.csp?.redirectDomains,
394
- },
395
- "openai/widgetDomain": view.domain,
396
- "openai/widgetPrefersBorder": view.prefersBorder,
397
- };
398
- const base = mergeWithUnion(mergeWithUnion(defaults, fromView), {
399
- "openai/widgetDomain": overrides.domain,
400
- });
401
- if (view._meta) {
402
- return { ...base, ...view._meta };
403
- }
404
- return base;
405
- },
406
- };
407
- this.registerViewResource({
408
- name: toolName,
409
- viewResource,
410
- view,
411
- });
412
- toolMeta["openai/outputTemplate"] = viewResource.uri;
413
- }
414
- if (hosts.includes("mcp-app")) {
415
- const viewResource = {
416
- hostType: "mcp-app",
417
- uri: `ui://views/ext-apps/${view.component}.html${versionParam}`,
418
- mimeType: "text/html;profile=mcp-app",
419
- buildContentMeta: ({ resourceDomains, connectDomains, domain, baseUriDomains }, overrides) => {
420
- const defaults = {
421
- ui: {
422
- csp: {
423
- resourceDomains,
424
- connectDomains,
425
- baseUriDomains,
426
- },
427
- domain,
413
+ const viewResource = {
414
+ hostType: "mcp-app",
415
+ uri: `ui://views/ext-apps/${view.component}.html${versionParam}`,
416
+ mimeType: "text/html;profile=mcp-app",
417
+ buildContentMeta: ({ resourceDomains, connectDomains, domain, baseUriDomains }, overrides) => {
418
+ const defaults = {
419
+ ui: {
420
+ csp: {
421
+ resourceDomains,
422
+ connectDomains,
423
+ baseUriDomains,
428
424
  },
429
- };
430
- const fromView = {
431
- ui: {
432
- ...(view.description && { description: view.description }),
433
- ...(view.prefersBorder !== undefined && {
434
- prefersBorder: view.prefersBorder,
425
+ domain,
426
+ },
427
+ };
428
+ const fromView = {
429
+ ui: {
430
+ ...(view.description && { description: view.description }),
431
+ ...(view.prefersBorder !== undefined && {
432
+ prefersBorder: view.prefersBorder,
433
+ }),
434
+ ...(view.domain && { domain: view.domain }),
435
+ csp: {
436
+ ...(view.csp?.resourceDomains && {
437
+ resourceDomains: view.csp.resourceDomains,
438
+ }),
439
+ ...(view.csp?.connectDomains && {
440
+ connectDomains: view.csp.connectDomains,
441
+ }),
442
+ ...(view.csp?.frameDomains && {
443
+ frameDomains: view.csp.frameDomains,
444
+ }),
445
+ ...(view.csp?.baseUriDomains && {
446
+ baseUriDomains: view.csp.baseUriDomains,
435
447
  }),
436
- ...(view.domain && { domain: view.domain }),
437
- csp: {
438
- ...(view.csp?.resourceDomains && {
439
- resourceDomains: view.csp.resourceDomains,
440
- }),
441
- ...(view.csp?.connectDomains && {
442
- connectDomains: view.csp.connectDomains,
443
- }),
444
- ...(view.csp?.frameDomains && {
445
- frameDomains: view.csp.frameDomains,
446
- }),
447
- ...(view.csp?.baseUriDomains && {
448
- baseUriDomains: view.csp.baseUriDomains,
449
- }),
450
- ...(view.csp?.redirectDomains && {
451
- redirectDomains: view.csp.redirectDomains,
452
- }),
453
- },
454
448
  },
455
- };
456
- const base = mergeWithUnion(mergeWithUnion(defaults, fromView), {
457
- ui: overrides,
458
- });
459
- if (view._meta) {
460
- return { ...base, ...view._meta };
461
- }
462
- return base;
463
- },
464
- };
465
- this.registerViewResource({
466
- name: toolName,
467
- viewResource,
468
- view,
469
- });
470
- // @ts-expect-error - For backwards compatibility with Claude current implementation of the specs
471
- toolMeta["ui/resourceUri"] = viewResource.uri;
472
- toolMeta.ui = { ...toolMeta.ui, resourceUri: viewResource.uri };
473
- }
449
+ },
450
+ };
451
+ const ui = mergeWithUnion(mergeWithUnion(defaults, fromView), {
452
+ ui: overrides,
453
+ });
454
+ const base = {
455
+ ...ui,
456
+ ...(view.description && {
457
+ "openai/widgetDescription": view.description,
458
+ }),
459
+ ...(view.csp?.redirectDomains && {
460
+ "openai/widgetCSP": { redirect_domains: view.csp.redirectDomains },
461
+ }),
462
+ };
463
+ if (view._meta) {
464
+ return { ...base, ...view._meta };
465
+ }
466
+ return base;
467
+ },
468
+ };
469
+ this.registerViewResource({ name: toolName, viewResource, view });
470
+ // Advertise via the MCP Apps standard pointer only — ChatGPT renders from
471
+ // ui.resourceUri (verified), and not emitting openai/outputTemplate lets us
472
+ // retire the legacy apps-sdk resource later. The legacy apps-sdk URL is still
473
+ // served (see registerViewResource) so already-published apps keep resolving.
474
+ // @ts-expect-error - For backwards compatibility with Claude current implementation of the specs
475
+ toolMeta["ui/resourceUri"] = viewResource.uri;
476
+ toolMeta.ui = { ...toolMeta.ui, resourceUri: viewResource.uri };
474
477
  }
475
478
  registerViewResource({ name, viewResource, view, }) {
476
479
  const { hostType, uri: viewUri, mimeType, buildContentMeta } = viewResource;
@@ -484,6 +487,8 @@ export class McpServer extends McpServerBaseOmitted {
484
487
  }, contentMetaOverrides);
485
488
  };
486
489
  this.viewMetaBuilders.set(viewUri, buildMeta);
490
+ this.viewUriByPath.set(stripQuery(viewUri), viewUri);
491
+ this.serveLegacyAppsSdkUrl(view.component, viewUri);
487
492
  this.registerResource(name, viewUri, { description: view.description }, async (uri, extra) => {
488
493
  const isProduction = process.env.NODE_ENV === "production";
489
494
  const { serverUrl } = this.resolveViewRequestContext(extra);
@@ -506,6 +511,11 @@ export class McpServer extends McpServerBaseOmitted {
506
511
  };
507
512
  });
508
513
  }
514
+ serveLegacyAppsSdkUrl(component, canonicalUri) {
515
+ this.viewUriByPath.set(`ui://views/apps-sdk/${component}.html`, canonicalUri);
516
+ this.viewUriByPath.set(`ui://widgets/apps-sdk/${component}.html`, canonicalUri);
517
+ this.viewUriByPath.set(`ui://widgets/ext-apps/${component}.html`, canonicalUri);
518
+ }
509
519
  wrapHandler(cb, { attachViewUUID }) {
510
520
  return async (args, extra) => {
511
521
  const result = await cb(args, extra);