@ggui-ai/mcp-server 0.2.0-alpha.4 → 0.4.0-rc.0

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 (152) hide show
  1. package/dist/admin-blueprints-transport.d.ts.map +1 -1
  2. package/dist/admin-blueprints-transport.js +2 -1
  3. package/dist/admin-oauth-providers-transport.d.ts.map +1 -1
  4. package/dist/admin-oauth-providers-transport.js +7 -5
  5. package/dist/api-renders-routes.d.ts +85 -0
  6. package/dist/api-renders-routes.d.ts.map +1 -0
  7. package/dist/api-renders-routes.js +372 -0
  8. package/dist/build-mcp.d.ts +2 -2
  9. package/dist/build-mcp.d.ts.map +1 -1
  10. package/dist/build-mcp.js +64 -5
  11. package/dist/code-routes.d.ts +47 -0
  12. package/dist/code-routes.d.ts.map +1 -0
  13. package/dist/code-routes.js +81 -0
  14. package/dist/code-store-fs.js +2 -2
  15. package/dist/console-auth.d.ts +10 -10
  16. package/dist/console-auth.d.ts.map +1 -1
  17. package/dist/console-auth.js +5 -5
  18. package/dist/console-blueprint-routes.d.ts +71 -0
  19. package/dist/console-blueprint-routes.d.ts.map +1 -0
  20. package/dist/console-blueprint-routes.js +348 -0
  21. package/dist/console-chat-routes.d.ts +80 -0
  22. package/dist/console-chat-routes.d.ts.map +1 -0
  23. package/dist/console-chat-routes.js +204 -0
  24. package/dist/console-config-routes.d.ts +37 -0
  25. package/dist/console-config-routes.d.ts.map +1 -0
  26. package/dist/console-config-routes.js +91 -0
  27. package/dist/console-headers.d.ts +1 -1
  28. package/dist/console-info-routes.d.ts +84 -0
  29. package/dist/console-info-routes.d.ts.map +1 -0
  30. package/dist/console-info-routes.js +135 -0
  31. package/dist/console-keys-routes.d.ts +50 -0
  32. package/dist/console-keys-routes.d.ts.map +1 -0
  33. package/dist/console-keys-routes.js +222 -0
  34. package/dist/console-llm-keys-routes.d.ts +47 -0
  35. package/dist/console-llm-keys-routes.d.ts.map +1 -0
  36. package/dist/console-llm-keys-routes.js +443 -0
  37. package/dist/console-mcp-tools-routes.d.ts +41 -0
  38. package/dist/console-mcp-tools-routes.d.ts.map +1 -0
  39. package/dist/console-mcp-tools-routes.js +60 -0
  40. package/dist/console-registry-routes.d.ts +66 -0
  41. package/dist/console-registry-routes.d.ts.map +1 -0
  42. package/dist/console-registry-routes.js +276 -0
  43. package/dist/console-session-routes.d.ts +89 -0
  44. package/dist/console-session-routes.d.ts.map +1 -0
  45. package/dist/console-session-routes.js +385 -0
  46. package/dist/console-sessions-routes.d.ts +52 -0
  47. package/dist/console-sessions-routes.d.ts.map +1 -0
  48. package/dist/console-sessions-routes.js +106 -0
  49. package/dist/console-static-routes.d.ts +54 -0
  50. package/dist/console-static-routes.d.ts.map +1 -0
  51. package/dist/console-static-routes.js +190 -0
  52. package/dist/console-theme-routes.d.ts +3 -3
  53. package/dist/console-theme-routes.js +1 -1
  54. package/dist/console-timeline.d.ts +5 -5
  55. package/dist/console-timeline.d.ts.map +1 -1
  56. package/dist/console-timeline.js +27 -26
  57. package/dist/console-welcome.js +2 -2
  58. package/dist/email-login.d.ts.map +1 -1
  59. package/dist/email-login.js +2 -3
  60. package/dist/ggui-session-channel/action-ingress.d.ts +54 -0
  61. package/dist/ggui-session-channel/action-ingress.d.ts.map +1 -0
  62. package/dist/ggui-session-channel/action-ingress.js +228 -0
  63. package/dist/ggui-session-channel/channel-subscriptions.d.ts +97 -0
  64. package/dist/ggui-session-channel/channel-subscriptions.d.ts.map +1 -0
  65. package/dist/ggui-session-channel/channel-subscriptions.js +224 -0
  66. package/dist/ggui-session-channel/internal-types.d.ts +102 -0
  67. package/dist/ggui-session-channel/internal-types.d.ts.map +1 -0
  68. package/dist/ggui-session-channel/internal-types.js +6 -0
  69. package/dist/ggui-session-channel/outbound.d.ts +81 -0
  70. package/dist/ggui-session-channel/outbound.d.ts.map +1 -0
  71. package/dist/ggui-session-channel/outbound.js +174 -0
  72. package/dist/ggui-session-channel/socket-router.d.ts +38 -0
  73. package/dist/ggui-session-channel/socket-router.d.ts.map +1 -0
  74. package/dist/ggui-session-channel/socket-router.js +213 -0
  75. package/dist/ggui-session-channel/subscribe.d.ts +165 -0
  76. package/dist/ggui-session-channel/subscribe.d.ts.map +1 -0
  77. package/dist/ggui-session-channel/subscribe.js +370 -0
  78. package/dist/ggui-session-channel/subscriber-lifecycle.d.ts +40 -0
  79. package/dist/ggui-session-channel/subscriber-lifecycle.d.ts.map +1 -0
  80. package/dist/ggui-session-channel/subscriber-lifecycle.js +123 -0
  81. package/dist/ggui-session-channel.d.ts +425 -0
  82. package/dist/ggui-session-channel.d.ts.map +1 -0
  83. package/dist/ggui-session-channel.js +262 -0
  84. package/dist/health-routes.d.ts +76 -0
  85. package/dist/health-routes.d.ts.map +1 -0
  86. package/dist/health-routes.js +145 -0
  87. package/dist/index.d.ts +10 -11
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +8 -9
  90. package/dist/instructions-presets.d.ts +3 -3
  91. package/dist/instructions-presets.js +24 -24
  92. package/dist/llm-backed-negotiator.d.ts +68 -67
  93. package/dist/llm-backed-negotiator.d.ts.map +1 -1
  94. package/dist/llm-backed-negotiator.js +82 -221
  95. package/dist/mcp-apps-outbound.d.ts +47 -48
  96. package/dist/mcp-apps-outbound.d.ts.map +1 -1
  97. package/dist/mcp-apps-outbound.js +154 -177
  98. package/dist/mcp-endpoint-routes.d.ts +88 -0
  99. package/dist/mcp-endpoint-routes.d.ts.map +1 -0
  100. package/dist/mcp-endpoint-routes.js +359 -0
  101. package/dist/mcp-mounts.d.ts +2 -76
  102. package/dist/mcp-mounts.d.ts.map +1 -1
  103. package/dist/mcp-mounts.js +0 -76
  104. package/dist/oauth-as-routes.d.ts +60 -0
  105. package/dist/oauth-as-routes.d.ts.map +1 -0
  106. package/dist/oauth-as-routes.js +82 -0
  107. package/dist/oauth-clients-routes.d.ts +39 -0
  108. package/dist/oauth-clients-routes.d.ts.map +1 -0
  109. package/dist/oauth-clients-routes.js +87 -0
  110. package/dist/oauth-login-types.d.ts +1 -20
  111. package/dist/oauth-login-types.d.ts.map +1 -1
  112. package/dist/oauth-login-types.js +30 -7
  113. package/dist/oauth-login.d.ts.map +1 -1
  114. package/dist/oauth-login.js +3 -2
  115. package/dist/oauth-providers-store.d.ts.map +1 -1
  116. package/dist/oauth-providers-store.js +5 -5
  117. package/dist/oauth.d.ts +9 -8
  118. package/dist/oauth.d.ts.map +1 -1
  119. package/dist/oauth.js +41 -19
  120. package/dist/pairing-transport.d.ts.map +1 -1
  121. package/dist/pairing-transport.js +2 -1
  122. package/dist/request-context.d.ts +2 -2
  123. package/dist/request-context.js +2 -2
  124. package/dist/reserved-validators.d.ts.map +1 -1
  125. package/dist/reserved-validators.js +9 -1
  126. package/dist/route-param.d.ts +9 -0
  127. package/dist/route-param.d.ts.map +1 -0
  128. package/dist/route-param.js +10 -0
  129. package/dist/runtime-bundle-route.d.ts +43 -0
  130. package/dist/runtime-bundle-route.d.ts.map +1 -0
  131. package/dist/runtime-bundle-route.js +80 -0
  132. package/dist/schema-compat.d.ts +64 -62
  133. package/dist/schema-compat.d.ts.map +1 -1
  134. package/dist/schema-compat.js +23 -51
  135. package/dist/server.d.ts +179 -193
  136. package/dist/server.d.ts.map +1 -1
  137. package/dist/server.js +644 -3759
  138. package/dist/storage.d.ts +5 -5
  139. package/dist/storage.d.ts.map +1 -1
  140. package/dist/storage.js +5 -5
  141. package/dist/thread-transport.d.ts.map +1 -1
  142. package/dist/thread-transport.js +4 -3
  143. package/dist/user-session-auth.d.ts +7 -21
  144. package/dist/user-session-auth.d.ts.map +1 -1
  145. package/dist/user-session-auth.js +7 -28
  146. package/package.json +16 -15
  147. package/dist/mcp-apps-inbound.d.ts +0 -86
  148. package/dist/mcp-apps-inbound.d.ts.map +0 -1
  149. package/dist/mcp-apps-inbound.js +0 -283
  150. package/dist/render-channel.d.ts +0 -694
  151. package/dist/render-channel.d.ts.map +0 -1
  152. package/dist/render-channel.js +0 -1775
@@ -1 +1 @@
1
- {"version":3,"file":"admin-blueprints-transport.d.ts","sourceRoot":"","sources":["../src/admin-blueprints-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE/E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,sBAAsB,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,QAAQ,EAAE;QACpB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACzB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI,CAAC;CACV;AAED,0EAA0E;AAC1E,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,iBAAiB,GAC1B,QAAQ,IAAI,iBAAiB,GAAG,mBAAmB,CAIrD;AAED,MAAM,WAAW,+BAA+B;IAC9C,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,+BAA+B,GACpC,IAAI,CA8GN"}
1
+ {"version":3,"file":"admin-blueprints-transport.d.ts","sourceRoot":"","sources":["../src/admin-blueprints-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE/E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,sBAAsB,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,QAAQ,EAAE;QACpB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACzB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI,CAAC;CACV;AAED,0EAA0E;AAC1E,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,iBAAiB,GAC1B,QAAQ,IAAI,iBAAiB,GAAG,mBAAmB,CAIrD;AAED,MAAM,WAAW,+BAA+B;IAC9C,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,+BAA+B,GACpC,IAAI,CA8GN"}
@@ -1,3 +1,4 @@
1
+ import { isRecord } from '@ggui-ai/protocol';
1
2
  import { resolveIdentity, UnauthenticatedError } from './auth.js';
2
3
  /**
3
4
  * Default URL path the admin-blueprints route is mounted at. Sits
@@ -56,7 +57,7 @@ export function mountAdminBlueprintsTransport(app, opts) {
56
57
  // 2. Body validation. Minimum shape: {id: string, name: string}.
57
58
  // Optional fields: description, category, tags (string[]),
58
59
  // updatedAt (ISO string). Anything else is ignored.
59
- const body = (req.body ?? {});
60
+ const body = isRecord(req.body) ? req.body : {};
60
61
  const id = typeof body['id'] === 'string' ? body['id'] : undefined;
61
62
  const name = typeof body['name'] === 'string' ? body['name'] : undefined;
62
63
  if (!id || !name) {
@@ -1 +1 @@
1
- {"version":3,"file":"admin-oauth-providers-transport.d.ts","sourceRoot":"","sources":["../src/admin-oauth-providers-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC;AAC1D,OAAO,KAAK,EAEV,SAAS,EACT,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,eAAO,MAAM,kCAAkC,gCAAgC,CAAC;AAEhF,MAAM,WAAW,mCAAmC;IAClD,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAqCD,wBAAgB,iCAAiC,CAC/C,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,mCAAmC,GACxC,IAAI,CAiQN"}
1
+ {"version":3,"file":"admin-oauth-providers-transport.d.ts","sourceRoot":"","sources":["../src/admin-oauth-providers-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC;AAE1D,OAAO,KAAK,EAEV,SAAS,EACT,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGtE,eAAO,MAAM,kCAAkC,gCAAgC,CAAC;AAEhF,MAAM,WAAW,mCAAmC;IAClD,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAqCD,wBAAgB,iCAAiC,CAC/C,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,mCAAmC,GACxC,IAAI,CAiQN"}
@@ -1,4 +1,6 @@
1
+ import { isRecord } from '@ggui-ai/protocol';
1
2
  import { resolveIdentity, UnauthenticatedError } from './auth.js';
3
+ import { singleParam } from './route-param.js';
2
4
  export const DEFAULT_ADMIN_OAUTH_PROVIDERS_PATH = '/ggui/admin/oauth-providers';
3
5
  function redact(record) {
4
6
  return {
@@ -100,8 +102,8 @@ export function mountAdminOAuthProvidersTransport(app, opts) {
100
102
  const reqLogger = opts.logger.child({ route: 'PUT ' + basePath + '/:providerId' });
101
103
  if (!(await requireBuilder(req, res, reqLogger)))
102
104
  return;
103
- const providerId = req.params['providerId'] ?? '';
104
- const body = (req.body ?? {});
105
+ const providerId = singleParam(req.params['providerId']) ?? '';
106
+ const body = isRecord(req.body) ? req.body : {};
105
107
  const clientId = typeof body['clientId'] === 'string' ? body['clientId'] : undefined;
106
108
  const clientSecret = typeof body['clientSecret'] === 'string' ? body['clientSecret'] : undefined;
107
109
  const enabled = typeof body['enabled'] === 'boolean' ? body['enabled'] : undefined;
@@ -171,8 +173,8 @@ export function mountAdminOAuthProvidersTransport(app, opts) {
171
173
  });
172
174
  if (!(await requireBuilder(req, res, reqLogger)))
173
175
  return;
174
- const providerId = req.params['providerId'] ?? '';
175
- const body = (req.body ?? {});
176
+ const providerId = singleParam(req.params['providerId']) ?? '';
177
+ const body = isRecord(req.body) ? req.body : {};
176
178
  const enabled = typeof body['enabled'] === 'boolean' ? body['enabled'] : undefined;
177
179
  if (enabled === undefined) {
178
180
  res.status(400).json({
@@ -233,7 +235,7 @@ export function mountAdminOAuthProvidersTransport(app, opts) {
233
235
  });
234
236
  if (!(await requireBuilder(req, res, reqLogger)))
235
237
  return;
236
- const providerId = req.params['providerId'] ?? '';
238
+ const providerId = singleParam(req.params['providerId']) ?? '';
237
239
  try {
238
240
  await opts.store.remove(providerId);
239
241
  reqLogger.info('admin_oauth_providers_remove', { providerId });
@@ -0,0 +1,85 @@
1
+ /**
2
+ * wsToken-gated render read routes (R6 + R7).
3
+ *
4
+ * R6 — GET /api/sessions/:sessionId/state?wsToken=<token>
5
+ *
6
+ * Auth'd snapshot read of the current render state, returning the
7
+ * same slice envelope as the wire `_meta` (a single
8
+ * `{"ai.ggui/render": {...}}` slice — Phase B collapsed the prior
9
+ * session + stack-item pair). Polling clients call this on a fixed
10
+ * interval (registry-level polling — see R6 library refactor) to
11
+ * pick up changes when WS is blocked at the host's CSP layer.
12
+ *
13
+ * wsToken-gated: same credential as the live-channel WS upgrade
14
+ * (`?wsToken=<token>` on `/ws`). Drift-free with the WS surface —
15
+ * the iframe-runtime already has the token from the bootstrap
16
+ * envelope; no separate refresh path needed.
17
+ *
18
+ * Distinct from `/r/:shortCode` (JSON branch):
19
+ * - `/r/...` was shortCode-gated (bearer-by-obscurity; anyone with
20
+ * the URL could read). R5 deleted that surface entirely.
21
+ * - `/api/sessions/.../state` is wsToken-gated (HMAC-signed,
22
+ * short-TTL, scoped to sessionId+appId). Survives R5.
23
+ *
24
+ * R7 — GET /api/sessions/:sessionId/events?wsToken=&sinceSequence=N&limit=M
25
+ *
26
+ * Cursor-replay read from the GguiSessionEvent ledger. Returns events
27
+ * with `seq > sinceSequence`, up to `limit` (default 100, max 500).
28
+ *
29
+ * Unification: WS subscribe's `sinceSequence` cursor and this HTTP
30
+ * endpoint read from the SAME ledger via the same `listEventsSince`
31
+ * GguiSessionStore method. Different transports, same cursor model —
32
+ * that's R7's payoff.
33
+ *
34
+ * Auth: wsToken-gated, identical posture to /state.
35
+ *
36
+ * Responses (/events):
37
+ * - 200 — `{events, lastSequence, hasMore}` (matches
38
+ * `EventsResponse` from @ggui-ai/protocol/integrations/mcp-apps).
39
+ * - 401 — wsToken missing / invalid / wrong-scope.
40
+ * - 404 — sessionId does not resolve.
41
+ * - 410 — `{reason: 'REPLAY_HORIZON_PASSED', currentSequence}` when
42
+ * `sinceSequence` is below the server's replay horizon OR strictly
43
+ * greater than `lastSequence` (cursor is from a stale deployment
44
+ * or the render was reset). Clients re-mount from /state.
45
+ */
46
+ import type { AppMetadataStore, CodeStore, GguiSessionStore } from "@ggui-ai/mcp-server-core";
47
+ import { type McpAppAiGguiRenderMeta } from "@ggui-ai/protocol/integrations/mcp-apps";
48
+ import type { Express } from "express";
49
+ import type { Logger } from "./logger.js";
50
+ interface MountOptions {
51
+ /** Express app to mount onto. */
52
+ readonly app: Express;
53
+ /** GguiSession store both routes read from. */
54
+ readonly renderStore: GguiSessionStore;
55
+ /** Shared HMAC secret the wsToken query credential verifies against. */
56
+ readonly secret: string;
57
+ /** Per-app metadata store for the publicEnv projection (optional). */
58
+ readonly appMetadataStore?: AppMetadataStore;
59
+ /** Operator-picked theme preset id stamped on /state reads. */
60
+ readonly themeId?: string;
61
+ /** Operator-picked theme mode stamped on /state reads. */
62
+ readonly themeMode?: McpAppAiGguiRenderMeta["themeMode"];
63
+ /** Content-addressable store for codeUrl / validatorsUrl emission. */
64
+ readonly codeStore?: CodeStore;
65
+ /** Operator-configured public origin for absolute URL composition. */
66
+ readonly publicBaseUrl?: string;
67
+ /** Live-mode credential minter — fresh trio on every /state read. */
68
+ readonly mintBootstrap?: (sessionId: string, appId: string) => {
69
+ wsUrl: string;
70
+ token: string;
71
+ expiresAt: string;
72
+ };
73
+ /** Per-request runtime-bundle URL resolver (tunnel/proxy aware). */
74
+ readonly resolveRuntimeUrl: () => string;
75
+ /** Structured logger for store-read failures. */
76
+ readonly logger: Logger;
77
+ }
78
+ /**
79
+ * Mount `GET /api/sessions/:sessionId/state` +
80
+ * `GET /api/sessions/:sessionId/events` onto the express app.
81
+ * Returns nothing — the routes self-register.
82
+ */
83
+ export declare function mountApiRendersRoutes(opts: MountOptions): void;
84
+ export {};
85
+ //# sourceMappingURL=api-renders-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-renders-routes.d.ts","sourceRoot":"","sources":["../src/api-renders-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAO9F,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,UAAU,YAAY;IACpB,iCAAiC;IACjC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,+CAA+C;IAC/C,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;IACvC,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAC7C,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,sBAAsB,CAAC,WAAW,CAAC,CAAC;IACzD,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,qEAAqE;IACrE,QAAQ,CAAC,aAAa,CAAC,EAAE,CACvB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,KACV;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,oEAAoE;IACpE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,MAAM,CAAC;IACzC,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAwU9D"}
@@ -0,0 +1,372 @@
1
+ /**
2
+ * wsToken-gated render read routes (R6 + R7).
3
+ *
4
+ * R6 — GET /api/sessions/:sessionId/state?wsToken=<token>
5
+ *
6
+ * Auth'd snapshot read of the current render state, returning the
7
+ * same slice envelope as the wire `_meta` (a single
8
+ * `{"ai.ggui/render": {...}}` slice — Phase B collapsed the prior
9
+ * session + stack-item pair). Polling clients call this on a fixed
10
+ * interval (registry-level polling — see R6 library refactor) to
11
+ * pick up changes when WS is blocked at the host's CSP layer.
12
+ *
13
+ * wsToken-gated: same credential as the live-channel WS upgrade
14
+ * (`?wsToken=<token>` on `/ws`). Drift-free with the WS surface —
15
+ * the iframe-runtime already has the token from the bootstrap
16
+ * envelope; no separate refresh path needed.
17
+ *
18
+ * Distinct from `/r/:shortCode` (JSON branch):
19
+ * - `/r/...` was shortCode-gated (bearer-by-obscurity; anyone with
20
+ * the URL could read). R5 deleted that surface entirely.
21
+ * - `/api/sessions/.../state` is wsToken-gated (HMAC-signed,
22
+ * short-TTL, scoped to sessionId+appId). Survives R5.
23
+ *
24
+ * R7 — GET /api/sessions/:sessionId/events?wsToken=&sinceSequence=N&limit=M
25
+ *
26
+ * Cursor-replay read from the GguiSessionEvent ledger. Returns events
27
+ * with `seq > sinceSequence`, up to `limit` (default 100, max 500).
28
+ *
29
+ * Unification: WS subscribe's `sinceSequence` cursor and this HTTP
30
+ * endpoint read from the SAME ledger via the same `listEventsSince`
31
+ * GguiSessionStore method. Different transports, same cursor model —
32
+ * that's R7's payoff.
33
+ *
34
+ * Auth: wsToken-gated, identical posture to /state.
35
+ *
36
+ * Responses (/events):
37
+ * - 200 — `{events, lastSequence, hasMore}` (matches
38
+ * `EventsResponse` from @ggui-ai/protocol/integrations/mcp-apps).
39
+ * - 401 — wsToken missing / invalid / wrong-scope.
40
+ * - 404 — sessionId does not resolve.
41
+ * - 410 — `{reason: 'REPLAY_HORIZON_PASSED', currentSequence}` when
42
+ * `sinceSequence` is below the server's replay horizon OR strictly
43
+ * greater than `lastSequence` (cursor is from a stale deployment
44
+ * or the render was reset). Clients re-mount from /state.
45
+ */
46
+ import { verifyToken } from "@ggui-ai/mcp-server-core";
47
+ import { deriveContractBundle, derivePublicEnvProjection, deriveRenderMeta, } from "@ggui-ai/mcp-server-handlers/renders";
48
+ import { MCP_APP_AI_GGUI_RENDER_META_KEY, } from "@ggui-ai/protocol/integrations/mcp-apps";
49
+ /**
50
+ * Mount `GET /api/sessions/:sessionId/state` +
51
+ * `GET /api/sessions/:sessionId/events` onto the express app.
52
+ * Returns nothing — the routes self-register.
53
+ */
54
+ export function mountApiRendersRoutes(opts) {
55
+ const { app, renderStore, secret, appMetadataStore, themeId, themeMode, codeStore, publicBaseUrl, mintBootstrap, resolveRuntimeUrl, logger, } = opts;
56
+ app.get("/api/sessions/:sessionId/state", async (req, res) => {
57
+ const sessionId = req.params["sessionId"];
58
+ if (typeof sessionId !== "string" || sessionId.length === 0) {
59
+ res.status(400).type("text/plain").send("sessionId required");
60
+ return;
61
+ }
62
+ const wsTokenRaw = req.query["wsToken"];
63
+ const wsToken = typeof wsTokenRaw === "string" ? wsTokenRaw : "";
64
+ if (wsToken.length === 0) {
65
+ res.status(401).type("text/plain").send("wsToken query required");
66
+ return;
67
+ }
68
+ const verify = verifyToken(wsToken, secret, "ws");
69
+ if (!verify.ok) {
70
+ // 410 Gone for expired (matches the `BOOTSTRAP_EXPIRED`
71
+ // semantics on the WS upgrade): the envelope was once valid
72
+ // but has aged out; the iframe-runtime branches on this to
73
+ // surface a refresh-vs-rehandshake prompt instead of treating
74
+ // it as a hostile request.
75
+ if (verify.reason === "expired") {
76
+ res.status(410).type("text/plain").send("wsToken expired");
77
+ return;
78
+ }
79
+ // 401 for tamper / wrong-kind / malformed / invalid-format —
80
+ // the caller is broken or hostile; no info leak.
81
+ res.status(401).type("text/plain").send("wsToken invalid");
82
+ return;
83
+ }
84
+ // Tenancy gate: the wsToken's claimed sessionId MUST match the
85
+ // URL's sessionId. A wsToken minted for render A MUST NOT read
86
+ // render B's state.
87
+ if (verify.claims.sessionId !== sessionId) {
88
+ res.status(401).type("text/plain").send("wsToken scope mismatch");
89
+ return;
90
+ }
91
+ let stored;
92
+ try {
93
+ stored = await renderStore.get(sessionId);
94
+ }
95
+ catch (err) {
96
+ logger.warn("state_read_failed", {
97
+ sessionId,
98
+ error: String(err),
99
+ });
100
+ res.status(500).type("text/plain").send("internal error");
101
+ return;
102
+ }
103
+ if (!stored) {
104
+ // 404: render evicted / never existed. Polling clients fold
105
+ // this into "stop polling" — distinct from 410 which signals
106
+ // "credential aged out, refresh".
107
+ res.status(404).type("text/plain").send("render not found");
108
+ return;
109
+ }
110
+ // Tenancy gate (round 2): the wsToken's appId MUST match the
111
+ // render's appId. Closes the case where a render is created
112
+ // under a different appId than the token was minted for.
113
+ if (verify.claims.appId !== stored.appId) {
114
+ res.status(401).type("text/plain").send("wsToken scope mismatch");
115
+ return;
116
+ }
117
+ // Phase B: a render IS the addressable unit. Pick directly from
118
+ // the resolved GguiSession (no stack walk).
119
+ const render = stored.render;
120
+ const isMcpApps = render.type === "mcpApps";
121
+ const isSystem = !isMcpApps && render.type === "system";
122
+ const renderKind = isSystem && typeof render.kind === "string"
123
+ ? render.kind
124
+ : undefined;
125
+ // Build render-slice meta. Mirror render.resultMeta's shape so
126
+ // the iframe-runtime parser admits identical envelopes regardless
127
+ // of which surface served them. `lastSequence` is the load-bearing
128
+ // R6 addition: polling clients use it to initialize the R7 /events
129
+ // cursor (`?sinceSequence=N`) aligned with the WS stream.
130
+ const view = !isMcpApps ? deriveRenderMeta(render) : undefined;
131
+ let statePublicEnv;
132
+ if (appMetadataStore && !isMcpApps) {
133
+ try {
134
+ const appRecord = await appMetadataStore.get(stored.appId);
135
+ statePublicEnv = derivePublicEnvProjection(render, appRecord?.publicEnv);
136
+ }
137
+ catch {
138
+ // Silent — wrappers calling getPublicEnv throw clearly.
139
+ }
140
+ }
141
+ // Live-mode credential trio. Always minted fresh on /state reads
142
+ // so the iframe-runtime gets a long-TTL token + the host learns
143
+ // `wsUrl` (the CSP-permitted WebSocket origin). Without this,
144
+ // any caller of /state — including the restore-bootstrap path in
145
+ // every host (claude.ai, ChatGPT, our sample-agent) — receives a
146
+ // render slice missing `wsUrl`. CSP `connect-src` then omits the
147
+ // `ws://` scheme, the browser blocks the upgrade, and props_update
148
+ // never reaches the iframe. The render-commit handler already
149
+ // stamps this trio on its resultMeta; mirroring here closes the
150
+ // drift.
151
+ const liveTrio = mintBootstrap ? mintBootstrap(stored.id, stored.appId) : undefined;
152
+ // Polling URL — the iframe-runtime's R6 polling-fallback path
153
+ // composes its fetch URL from `render.pollingUrl`. The /state
154
+ // endpoint IS that URL, so we stamp it here; without it the
155
+ // iframe-runtime can't fall back when the WS upgrade fails.
156
+ const requestHostForPolling = req.get("host") ?? "";
157
+ const pollingBase = publicBaseUrl
158
+ ? publicBaseUrl.replace(/\/$/, "")
159
+ : `${req.protocol}://${requestHostForPolling}`;
160
+ const pollingUrl = `${pollingBase}/api/sessions/${encodeURIComponent(stored.id)}/state`;
161
+ // Static-component delivery via codeUrl (the same content-addressable
162
+ // channel the code routes serve). Polling clients are render-capable
163
+ // and need the URL to mount/refresh the static-component variant.
164
+ let renderCodeUrl;
165
+ let renderCodeHash;
166
+ let renderContractHash;
167
+ let renderValidatorsUrl;
168
+ if (!isSystem && !isMcpApps && codeStore) {
169
+ const code = render.componentCode;
170
+ if (typeof code === "string" && code.length > 0) {
171
+ try {
172
+ const hash = codeStore.hashOf(code);
173
+ await codeStore.put(hash, code);
174
+ renderCodeHash = hash;
175
+ const requestHost = req.get("host") ?? "";
176
+ const base = publicBaseUrl
177
+ ? publicBaseUrl.replace(/\/$/, "")
178
+ : `${req.protocol}://${requestHost}`;
179
+ renderCodeUrl = `${base}/code/${hash}.js`;
180
+ }
181
+ catch {
182
+ // Silent — caller falls back to live-mode delivery.
183
+ }
184
+ try {
185
+ const bundle = await deriveContractBundle(render);
186
+ if (bundle) {
187
+ await codeStore.put(bundle.contractHash, bundle.bundleSource);
188
+ renderContractHash = bundle.contractHash;
189
+ const requestHost = req.get("host") ?? "";
190
+ const base = publicBaseUrl
191
+ ? publicBaseUrl.replace(/\/$/, "")
192
+ : `${req.protocol}://${requestHost}`;
193
+ renderValidatorsUrl = `${base}/contract/${bundle.contractHash}.js`;
194
+ }
195
+ }
196
+ catch {
197
+ // Silent — server-side gate remains authoritative.
198
+ }
199
+ }
200
+ }
201
+ // Phase B: single flat ai.ggui/render slice — render + visible-
202
+ // bits surface fields merged into one shape.
203
+ const renderMeta = {
204
+ sessionId: stored.id,
205
+ appId: stored.appId,
206
+ runtimeUrl: resolveRuntimeUrl(),
207
+ ...(liveTrio !== undefined
208
+ ? {
209
+ wsUrl: liveTrio.wsUrl,
210
+ wsToken: liveTrio.token,
211
+ expiresAt: liveTrio.expiresAt,
212
+ }
213
+ : {}),
214
+ pollingUrl,
215
+ ...(themeId !== undefined ? { themeId } : {}),
216
+ ...(themeMode !== undefined ? { themeMode } : {}),
217
+ // Per-app theme overlay projected by `deriveRenderMeta` from the
218
+ // render's `theme` sidecar — same field the render result-meta
219
+ // carries, so a /state read returns the identical overlay.
220
+ ...(view?.theme !== undefined ? { theme: view.theme } : {}),
221
+ ...(view?.gadgets !== undefined && view.gadgets.length > 0 ? { gadgets: view.gadgets } : {}),
222
+ ...(statePublicEnv !== undefined && Object.keys(statePublicEnv).length > 0
223
+ ? { publicEnv: statePublicEnv }
224
+ : {}),
225
+ ...(view?.permissionsPolicy !== undefined && view.permissionsPolicy.length > 0
226
+ ? { permissionsPolicy: view.permissionsPolicy }
227
+ : {}),
228
+ // R6 — load-bearing ledger cursor. Always stamped on /state
229
+ // reads so polling clients can position the R7 /events cursor.
230
+ lastSequence: stored.eventSequence,
231
+ // Visible-bits surface merged onto the single render slice.
232
+ ...(renderKind !== undefined ? { kind: renderKind } : {}),
233
+ ...(renderCodeUrl !== undefined
234
+ ? {
235
+ codeUrl: renderCodeUrl,
236
+ ...(renderCodeHash !== undefined ? { codeHash: renderCodeHash } : {}),
237
+ }
238
+ : {}),
239
+ ...(view?.propsJson !== undefined ? { propsJson: view.propsJson } : {}),
240
+ ...(view?.contextSlots !== undefined ? { contextSlots: view.contextSlots } : {}),
241
+ ...(renderContractHash !== undefined && renderValidatorsUrl !== undefined
242
+ ? {
243
+ contractHash: renderContractHash,
244
+ validatorsUrl: renderValidatorsUrl,
245
+ }
246
+ : {}),
247
+ };
248
+ res.setHeader("Access-Control-Allow-Origin", "*");
249
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
250
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
251
+ res.status(200).json({
252
+ [MCP_APP_AI_GGUI_RENDER_META_KEY]: renderMeta,
253
+ });
254
+ });
255
+ app.get("/api/sessions/:sessionId/events", async (req, res) => {
256
+ const sessionId = req.params["sessionId"];
257
+ if (typeof sessionId !== "string" || sessionId.length === 0) {
258
+ res.status(400).type("text/plain").send("sessionId required");
259
+ return;
260
+ }
261
+ const wsTokenRaw = req.query["wsToken"];
262
+ const wsToken = typeof wsTokenRaw === "string" ? wsTokenRaw : "";
263
+ if (wsToken.length === 0) {
264
+ res.status(401).type("text/plain").send("wsToken query required");
265
+ return;
266
+ }
267
+ const verify = verifyToken(wsToken, secret, "ws");
268
+ if (!verify.ok) {
269
+ if (verify.reason === "expired") {
270
+ res.status(410).type("text/plain").send("wsToken expired");
271
+ return;
272
+ }
273
+ res.status(401).type("text/plain").send("wsToken invalid");
274
+ return;
275
+ }
276
+ if (verify.claims.sessionId !== sessionId) {
277
+ res.status(401).type("text/plain").send("wsToken scope mismatch");
278
+ return;
279
+ }
280
+ // Parse + validate sinceSequence (required, non-negative integer)
281
+ // and limit (optional, 1..500, default 100).
282
+ //
283
+ // sinceSequence is REQUIRED — explicit cursor reads only. A missing
284
+ // query is a caller bug (no sensible default; `0` means "replay
285
+ // everything" which we don't want to fire unintentionally).
286
+ const sinceSequenceRaw = req.query["sinceSequence"];
287
+ if (typeof sinceSequenceRaw !== "string" || sinceSequenceRaw.length === 0) {
288
+ res
289
+ .status(400)
290
+ .type("text/plain")
291
+ .send("sinceSequence query required (non-negative integer)");
292
+ return;
293
+ }
294
+ const sinceSequence = Number(sinceSequenceRaw);
295
+ if (!Number.isInteger(sinceSequence) || sinceSequence < 0) {
296
+ res.status(400).type("text/plain").send("sinceSequence must be a non-negative integer");
297
+ return;
298
+ }
299
+ const limitRaw = req.query["limit"];
300
+ let limit = 100;
301
+ if (typeof limitRaw === "string" && limitRaw.length > 0) {
302
+ const parsed = Number(limitRaw);
303
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > 500) {
304
+ res.status(400).type("text/plain").send("limit must be an integer in [1, 500]");
305
+ return;
306
+ }
307
+ limit = parsed;
308
+ }
309
+ let result;
310
+ try {
311
+ result = await renderStore.listEventsSince(sessionId, sinceSequence, limit);
312
+ }
313
+ catch (err) {
314
+ logger.warn("events_read_failed", {
315
+ sessionId,
316
+ error: String(err),
317
+ });
318
+ res.status(500).type("text/plain").send("internal error");
319
+ return;
320
+ }
321
+ if (result === null) {
322
+ // 404 — render not found. Distinct from 410 (cursor stale on
323
+ // a live render) so polling clients can branch.
324
+ res.status(404).type("text/plain").send("render not found");
325
+ return;
326
+ }
327
+ // Tenancy gate (round 2): the wsToken's appId MUST match the
328
+ // render's appId. We need the render record to check — fetch
329
+ // it. listEventsSince validated the render exists.
330
+ const stored = await renderStore.get(sessionId);
331
+ if (!stored) {
332
+ res.status(404).type("text/plain").send("render not found");
333
+ return;
334
+ }
335
+ if (verify.claims.appId !== stored.appId) {
336
+ res.status(401).type("text/plain").send("wsToken scope mismatch");
337
+ return;
338
+ }
339
+ // Replay-horizon gate. Two cases collapse to REPLAY_HORIZON_PASSED:
340
+ // (a) sinceSequence < horizonSeq — events evicted (cloud TTL,
341
+ // in-mem never).
342
+ // (b) sinceSequence > lastSequence — cursor from a different
343
+ // deployment / reset render; the server has no events
344
+ // beyond what it knows, and we can't safely advance.
345
+ if (sinceSequence > result.lastSequence) {
346
+ res.status(410).type("application/json").json({
347
+ reason: "REPLAY_HORIZON_PASSED",
348
+ currentSequence: result.lastSequence,
349
+ });
350
+ return;
351
+ }
352
+ if (sinceSequence < result.horizonSeq) {
353
+ res.status(410).type("application/json").json({
354
+ reason: "REPLAY_HORIZON_PASSED",
355
+ currentSequence: result.lastSequence,
356
+ });
357
+ return;
358
+ }
359
+ // GguiSessionEvent is now the unified wire-shape ledger primitive
360
+ // (Wave 7 of flatten-render-identity, 2026-05-28). The store
361
+ // returns events in protocol-canonical shape (seq + type +
362
+ // timestamp[ISO] + data); no projection needed.
363
+ res.setHeader("Access-Control-Allow-Origin", "*");
364
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
365
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
366
+ res.status(200).json({
367
+ events: result.events,
368
+ lastSequence: result.lastSequence,
369
+ hasMore: result.hasMore,
370
+ });
371
+ });
372
+ }
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
12
12
  import { type ZodRawShape } from 'zod';
13
- import type { HandlerContext, SharedHandler } from '@ggui-ai/mcp-server-handlers';
13
+ import { type HandlerContext, type SharedHandler } from '@ggui-ai/mcp-server-handlers';
14
14
  import type { Logger } from './logger.js';
15
15
  import { type GguiRenderResourceTemplateOptions } from './mcp-apps-outbound.js';
16
16
  export interface ServerInfo {
@@ -40,7 +40,7 @@ export interface BuildMcpServerOptions {
40
40
  /**
41
41
  * Per-render self-contained shell options. When supplied,
42
42
  * `installMcpAppsOutbound` ALSO registers
43
- * `ui://ggui/render/{renderId}` as a resource template — the URI
43
+ * `ui://ggui/render/{sessionId}` as a resource template — the URI
44
44
  * `ggui_render.resultMeta` stamps on per-call `_meta.ui.resourceUri`
45
45
  * for third-party MCP Apps hosts (Claude Desktop, claude.ai web)
46
46
  * that don't speak ggui's custom postMessage protocol.
@@ -1 +1 @@
1
- {"version":3,"file":"build-mcp.d.ts","sourceRoot":"","sources":["../src/build-mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAK,KAAK,WAAW,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACd,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAEL,KAAK,iCAAiC,EACvC,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,iCAAiC,CAAC;IAC3D;;;;;;;;;OASG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;IAElE;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,aAAa,CAAC,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC,CAAC;CACtE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,EAChE,UAAU,EAAE,MAAM,cAAc,EAChC,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,qBAA0B,GAC/B,SAAS,CA8IX"}
1
+ {"version":3,"file":"build-mcp.d.ts","sourceRoot":"","sources":["../src/build-mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,EAAK,KAAK,WAAW,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAEL,KAAK,iCAAiC,EACvC,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,iCAAiC,CAAC;IAC3D;;;;;;;;;OASG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;IAElE;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,aAAa,CAAC,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC,CAAC;CACtE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,EAChE,UAAU,EAAE,MAAM,cAAc,EAChC,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,qBAA0B,GAC/B,SAAS,CAiLX"}