@mono-agent/web 0.19.0 → 0.20.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 (54) hide show
  1. package/README.md +123 -21
  2. package/dist/contracts.d.ts +115 -4
  3. package/dist/contracts.d.ts.map +1 -1
  4. package/dist/contracts.js +1 -1
  5. package/dist/contracts.js.map +1 -1
  6. package/dist/discovery.d.ts +1 -0
  7. package/dist/discovery.d.ts.map +1 -1
  8. package/dist/discovery.js +43 -1
  9. package/dist/discovery.js.map +1 -1
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/mcp-app-document.d.ts +15 -0
  14. package/dist/mcp-app-document.d.ts.map +1 -0
  15. package/dist/mcp-app-document.js +42 -0
  16. package/dist/mcp-app-document.js.map +1 -0
  17. package/dist/mcp-app-proxy.d.ts +20 -0
  18. package/dist/mcp-app-proxy.d.ts.map +1 -0
  19. package/dist/mcp-app-proxy.js +321 -0
  20. package/dist/mcp-app-proxy.js.map +1 -0
  21. package/dist/notification-client.d.ts +18 -4
  22. package/dist/notification-client.d.ts.map +1 -1
  23. package/dist/notification-client.js +13 -4
  24. package/dist/notification-client.js.map +1 -1
  25. package/dist/notification-ingress.d.ts +19 -0
  26. package/dist/notification-ingress.d.ts.map +1 -1
  27. package/dist/notification-ingress.js +68 -6
  28. package/dist/notification-ingress.js.map +1 -1
  29. package/dist/operator-client.d.ts +51 -2
  30. package/dist/operator-client.d.ts.map +1 -1
  31. package/dist/operator-client.js +349 -2
  32. package/dist/operator-client.js.map +1 -1
  33. package/dist/push.d.ts +3 -0
  34. package/dist/push.d.ts.map +1 -1
  35. package/dist/push.js +11 -3
  36. package/dist/push.js.map +1 -1
  37. package/dist/server.d.ts.map +1 -1
  38. package/dist/server.js +244 -0
  39. package/dist/server.js.map +1 -1
  40. package/dist/service.d.ts +81 -5
  41. package/dist/service.d.ts.map +1 -1
  42. package/dist/service.js +401 -30
  43. package/dist/service.js.map +1 -1
  44. package/dist/store.d.ts +79 -7
  45. package/dist/store.d.ts.map +1 -1
  46. package/dist/store.js +2046 -162
  47. package/dist/store.js.map +1 -1
  48. package/package.json +4 -4
  49. package/webapp/dist/assets/index-CNY5_en5.css +1 -0
  50. package/webapp/dist/assets/index-Dl-iLQzF.js +152 -0
  51. package/webapp/dist/index.html +2 -2
  52. package/webapp/dist/sw.js +1 -1
  53. package/webapp/dist/assets/index-DBk-VjNE.css +0 -1
  54. package/webapp/dist/assets/index-DntvgDjy.js +0 -51
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE1E,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,YAAY,EACV,2BAA2B,EAC3B,6BAA6B,EAC7B,4BAA4B,GAC7B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,8BAA8B,EAC9B,6BAA6B,EAC7B,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EACV,qBAAqB,EACrB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,oCAAoC,EACpC,sBAAsB,EACtB,8BAA8B,EAC9B,2BAA2B,EAC3B,sBAAsB,EACtB,+BAA+B,EAC/B,6BAA6B,EAC7B,wBAAwB,EACxB,UAAU,GACX,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,kBAAkB,EAClB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,0BAA0B,EAC1B,gBAAgB,EAChB,wBAAwB,EACxB,yBAAyB,EACzB,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,yBAAyB,EACzB,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,QAAQ,GACT,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE1E,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,YAAY,EACV,2BAA2B,EAC3B,6BAA6B,EAC7B,4BAA4B,EAC5B,qCAAqC,EACrC,iCAAiC,GAClC,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,8BAA8B,EAC9B,6BAA6B,EAC7B,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EACV,qBAAqB,EACrB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,oCAAoC,EACpC,sBAAsB,EACtB,8BAA8B,EAC9B,2BAA2B,EAC3B,sBAAsB,EACtB,+BAA+B,EAC/B,6BAA6B,EAC7B,wBAAwB,EACxB,UAAU,GACX,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,kBAAkB,EAClB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,0BAA0B,EAC1B,gCAAgC,EAChC,gBAAgB,EAChB,wBAAwB,EACxB,yBAAyB,EACzB,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,yBAAyB,EACzB,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,QAAQ,GACT,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,GACf,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAOlE,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAC;AAOxB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAStD,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,oCAAoC,EACpC,sBAAsB,EACtB,8BAA8B,EAC9B,2BAA2B,EAC3B,sBAAsB,EACtB,+BAA+B,EAC/B,6BAA6B,EAC7B,wBAAwB,EACxB,UAAU,GACX,MAAM,gBAAgB,CAAC;AAwCxB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,GACf,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AASlE,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAC;AAOxB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAStD,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,oCAAoC,EACpC,sBAAsB,EACtB,8BAA8B,EAC9B,2BAA2B,EAC3B,sBAAsB,EACtB,+BAA+B,EAC/B,6BAA6B,EAC7B,wBAAwB,EACxB,UAAU,GACX,MAAM,gBAAgB,CAAC;AAyCxB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,15 @@
1
+ export declare const MCP_APP_SECURED_HTML_MAX_BYTES: number;
2
+ export interface McpAppDocumentCsp {
3
+ readonly connectDomains?: readonly string[];
4
+ readonly resourceDomains?: readonly string[];
5
+ readonly frameDomains?: readonly string[];
6
+ readonly baseUriDomains?: readonly string[];
7
+ }
8
+ export interface McpAppDocumentMetadata {
9
+ readonly csp?: McpAppDocumentCsp;
10
+ }
11
+ /** Build the inner document policy from already intersected host grants. */
12
+ export declare const mcpAppContentSecurityPolicy: (metadata: McpAppDocumentMetadata) => string;
13
+ /** Place the restrictive policy before any server-controlled markup executes. */
14
+ export declare const secureMcpAppHtml: (html: string, metadata: McpAppDocumentMetadata) => string;
15
+ //# sourceMappingURL=mcp-app-document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-app-document.d.ts","sourceRoot":"","sources":["../src/mcp-app-document.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,8BAA8B,QAAkB,CAAC;AAE9D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,iBAAiB,CAAC;CAClC;AAID,4EAA4E;AAC5E,eAAO,MAAM,2BAA2B,GAAI,UAAU,sBAAsB,KAAG,MAyB9E,CAAC;AAOF,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,EAAE,UAAU,sBAAsB,KAAG,MAOjF,CAAC"}
@@ -0,0 +1,42 @@
1
+ export const MCP_APP_SECURED_HTML_MAX_BYTES = 2 * 1024 * 1024;
2
+ const byteSize = (value) => new TextEncoder().encode(value).byteLength;
3
+ /** Build the inner document policy from already intersected host grants. */
4
+ export const mcpAppContentSecurityPolicy = (metadata) => {
5
+ const resources = metadata.csp?.resourceDomains ?? [];
6
+ const connects = metadata.csp?.connectDomains ?? [];
7
+ const frames = metadata.csp?.frameDomains ?? [];
8
+ const bases = metadata.csp?.baseUriDomains ?? [];
9
+ const sources = (items, extras = []) => [...extras, ...items].join(" ") || "'none'";
10
+ return [
11
+ "default-src 'none'",
12
+ // Server-declared resource origins never become executable-script origins.
13
+ "script-src 'unsafe-inline'",
14
+ `style-src 'unsafe-inline'${resources.length > 0 ? ` ${resources.join(" ")}` : ""}`,
15
+ `img-src ${sources(resources, ["data:", "blob:"])}`,
16
+ `font-src ${sources(resources, ["data:"])}`,
17
+ `media-src ${sources(resources, ["blob:"])}`,
18
+ `connect-src ${sources(connects)}`,
19
+ `frame-src ${sources(frames)}`,
20
+ `base-uri ${sources(bases)}`,
21
+ "form-action 'none'",
22
+ "object-src 'none'",
23
+ "child-src 'none'",
24
+ "worker-src 'none'",
25
+ "manifest-src 'none'",
26
+ "navigate-to 'none'",
27
+ ].join("; ");
28
+ };
29
+ const htmlAttribute = (value) => value
30
+ .replaceAll("&", "&")
31
+ .replaceAll('"', """)
32
+ .replaceAll("<", "&lt;");
33
+ /** Place the restrictive policy before any server-controlled markup executes. */
34
+ export const secureMcpAppHtml = (html, metadata) => {
35
+ const csp = htmlAttribute(mcpAppContentSecurityPolicy(metadata));
36
+ const secured = `<!doctype html><head><meta http-equiv="Content-Security-Policy" content="${csp}"><meta name="referrer" content="no-referrer"></head>${html}`;
37
+ if (byteSize(secured) > MCP_APP_SECURED_HTML_MAX_BYTES) {
38
+ throw new Error("The MCP App resource is too large.");
39
+ }
40
+ return secured;
41
+ };
42
+ //# sourceMappingURL=mcp-app-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-app-document.js","sourceRoot":"","sources":["../src/mcp-app-document.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAa9D,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC;AAEvF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,QAAgC,EAAU,EAAE;IACtF,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,EAAE,eAAe,IAAI,EAAE,CAAC;IACtD,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,EAAE,cAAc,IAAI,EAAE,CAAC;IACpD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,YAAY,IAAI,EAAE,CAAC;IAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,cAAc,IAAI,EAAE,CAAC;IACjD,MAAM,OAAO,GAAG,CAAC,KAAwB,EAAE,SAA4B,EAAE,EAAE,EAAE,CAC3E,CAAC,GAAG,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC;IAC9C,OAAO;QACL,oBAAoB;QACpB,2EAA2E;QAC3E,4BAA4B;QAC5B,4BAA4B,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;QACnF,WAAW,OAAO,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE;QACnD,YAAY,OAAO,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE;QAC3C,aAAa,OAAO,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE;QAC5C,eAAe,OAAO,CAAC,QAAQ,CAAC,EAAE;QAClC,aAAa,OAAO,CAAC,MAAM,CAAC,EAAE;QAC9B,YAAY,OAAO,CAAC,KAAK,CAAC,EAAE;QAC5B,oBAAoB;QACpB,mBAAmB;QACnB,kBAAkB;QAClB,mBAAmB;QACnB,qBAAqB;QACrB,oBAAoB;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK;KACnD,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;KACxB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;KACzB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAE3B,iFAAiF;AACjF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAE,QAAgC,EAAU,EAAE;IACzF,MAAM,GAAG,GAAG,aAAa,CAAC,2BAA2B,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,4EAA4E,GAAG,wDAAwD,IAAI,EAAE,CAAC;IAC9J,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,8BAA8B,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC"}
@@ -0,0 +1,20 @@
1
+ export declare const MCP_APP_PROXY_PATH = "/api/v1/mcp-app-proxy";
2
+ /**
3
+ * This policy applies only to the fixed, opaque-origin proxy document. The
4
+ * nested app srcdoc inherits it, so capability directives belong exclusively
5
+ * to the canonical inner meta policy. With no default-src, the fixed proxy's
6
+ * inline bootstrap and layout style still work while this envelope retains
7
+ * non-clipping containment.
8
+ */
9
+ export declare const MCP_APP_PROXY_CONTENT_SECURITY_POLICY: string;
10
+ /**
11
+ * Fixed trusted outer proxy for the MCP Apps double-iframe model.
12
+ *
13
+ * Invocation-specific values never enter this response or its URL. The direct
14
+ * parent supplies bounded configuration after load; the proxy derives the
15
+ * parent origin from the browser-authenticated MessageEvent, permanently binds
16
+ * the first valid identity tuple, and accepts only an exact repeated
17
+ * configuration to re-arm it. Host-ready remains a one-shot acknowledgement.
18
+ */
19
+ export declare const MCP_APP_PROXY_DOCUMENT = "<!doctype html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"referrer\" content=\"no-referrer\">\n<meta name=\"color-scheme\" content=\"light\">\n<style>html,body,#root{width:100%;height:100%;margin:0;overflow:hidden}iframe{width:100%;height:100%;display:block;border:0}</style>\n</head>\n<body>\n<div id=\"root\" aria-live=\"polite\"></div>\n<script>\n(() => {\n \"use strict\";\n const parentWindow = window.parent;\n const root = document.getElementById(\"root\");\n if (parentWindow === window || root === null) return;\n let config = null;\n let hostReady = false;\n let appFrame = null;\n let appFrameGeneration = 0;\n let readyAttempts = 0;\n let readyTimer = null;\n const byteLength = (value) => {\n try { return new TextEncoder().encode(JSON.stringify(value)).byteLength; }\n catch { return Number.POSITIVE_INFINITY; }\n };\n const isRecord = (value) => value !== null && typeof value === \"object\" && !Array.isArray(value);\n const isBoundedIdentity = (value) => typeof value === \"string\"\n && value.length > 0\n && value.length <= 512\n && !/[\\u0000-\\u001f\\u007f]/u.test(value);\n const isHostOrigin = (value) => {\n if (typeof value !== \"string\" || value === \"null\" || value.length > 2048) return false;\n try {\n const parsed = new URL(value);\n return (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") && parsed.origin === value;\n } catch {\n return false;\n }\n };\n const isConfiguration = (value) => {\n if (!isRecord(value) || byteLength(value) > 4096) return false;\n const keys = Object.keys(value);\n return keys.length === 5\n && keys.every((key) => key === \"type\" || key === \"nonce\" || key === \"invocationId\"\n || key === \"connectionId\" || key === \"clipboardWrite\")\n && value.type === \"mono-agent:mcp-app-proxy-config\"\n && isBoundedIdentity(value.nonce)\n && isBoundedIdentity(value.invocationId)\n && isBoundedIdentity(value.connectionId)\n && typeof value.clipboardWrite === \"boolean\";\n };\n const isRpc = (value) => isRecord(value)\n && value.jsonrpc === \"2.0\"\n && (typeof value.method === \"string\" || \"id\" in value);\n const identityMatches = (value) => config !== null\n && isRecord(value)\n && value.nonce === config.nonce\n && value.invocationId === config.invocationId\n && value.connectionId === config.connectionId;\n const exactSources = (directive, name) => {\n const prefix = name + \" \";\n if (!directive.startsWith(prefix)) return null;\n const value = directive.slice(prefix.length);\n if (value.length === 0 || value.trim() !== value || /\\s{2,}/u.test(value)) return null;\n return value.split(\" \");\n };\n const sameSources = (left, right) => left.length === right.length\n && left.every((value, index) => value === right[index]);\n const isSanitizedOrigin = (value) => {\n if (typeof value !== \"string\" || value.length > 2048) return false;\n try {\n const parsed = new URL(value);\n const localHttp = parsed.protocol === \"http:\"\n && (parsed.hostname === \"localhost\" || parsed.hostname === \"127.0.0.1\" || parsed.hostname === \"[::1]\");\n return (parsed.protocol === \"https:\" || localHttp)\n && parsed.origin === value\n && !parsed.username\n && !parsed.password\n && (parsed.pathname === \"/\" || parsed.pathname === \"\")\n && !parsed.search\n && !parsed.hash;\n } catch {\n return false;\n }\n };\n const isOriginSources = (sources) => sources.length === 1 && sources[0] === \"'none'\"\n || sources.length > 0\n && sources.length <= 64\n && new Set(sources).size === sources.length\n && sources.every(isSanitizedOrigin);\n const hasOnlyKeys = (value, required, optional = []) => {\n if (!isRecord(value)) return false;\n const keys = Object.keys(value);\n return keys.length >= required.length\n && keys.length <= required.length + optional.length\n && required.every((key) => keys.includes(key))\n && keys.every((key) => required.includes(key) || optional.includes(key));\n };\n const isOriginList = (value) => Array.isArray(value)\n && value.length <= 64\n && new Set(value).size === value.length\n && value.every(isSanitizedOrigin);\n const isSandboxCsp = (value) => hasOnlyKeys(value, [], [\n \"connectDomains\", \"resourceDomains\", \"frameDomains\", \"baseUriDomains\",\n ]) && Object.values(value).every(isOriginList);\n const isSandboxPermissions = (value) => hasOnlyKeys(value, [], [\"clipboardWrite\"])\n && (!(\"clipboardWrite\" in value)\n || hasOnlyKeys(value.clipboardWrite, []));\n const isCanonicalSecuredHtml = (html) => {\n const start = '<!doctype html><head><meta http-equiv=\"Content-Security-Policy\" content=\"';\n const end = '\"><meta name=\"referrer\" content=\"no-referrer\"></head>';\n if (!html.startsWith(start)) return false;\n const endIndex = html.indexOf(end, start.length);\n if (endIndex < 0) return false;\n const directives = html.slice(start.length, endIndex).split(\"; \");\n if (directives.length !== 15\n || directives[0] !== \"default-src 'none'\"\n || directives[1] !== \"script-src 'unsafe-inline'\"\n || directives[9] !== \"form-action 'none'\"\n || directives[10] !== \"object-src 'none'\"\n || directives[11] !== \"child-src 'none'\"\n || directives[12] !== \"worker-src 'none'\"\n || directives[13] !== \"manifest-src 'none'\"\n || directives[14] !== \"navigate-to 'none'\") return false;\n const styles = exactSources(directives[2], \"style-src\");\n const images = exactSources(directives[3], \"img-src\");\n const fonts = exactSources(directives[4], \"font-src\");\n const media = exactSources(directives[5], \"media-src\");\n const connects = exactSources(directives[6], \"connect-src\");\n const frames = exactSources(directives[7], \"frame-src\");\n const bases = exactSources(directives[8], \"base-uri\");\n if (styles === null || images === null || fonts === null || media === null\n || connects === null || frames === null || bases === null) return false;\n const resources = styles[0] === \"'unsafe-inline'\" ? styles.slice(1) : null;\n return resources !== null\n && resources.length <= 64\n && new Set(resources).size === resources.length\n && resources.every(isSanitizedOrigin)\n && sameSources(images, [\"data:\", \"blob:\", ...resources])\n && sameSources(fonts, [\"data:\", ...resources])\n && sameSources(media, [\"blob:\", ...resources])\n && isOriginSources(connects)\n && isOriginSources(frames)\n && isOriginSources(bases);\n };\n const isSandboxResourceReady = (value) => {\n if (!hasOnlyKeys(value, [\"jsonrpc\", \"method\", \"params\"])) return false;\n const params = value.params;\n if (value.jsonrpc !== \"2.0\"\n || value.method !== \"ui/notifications/sandbox-resource-ready\"\n || !hasOnlyKeys(params, [\"html\", \"sandbox\"], [\"csp\", \"permissions\"])\n || typeof params.html !== \"string\"\n || new TextEncoder().encode(params.html).byteLength > 2097152\n || params.sandbox !== \"allow-scripts\"\n || (\"csp\" in params && !isSandboxCsp(params.csp))\n || (\"permissions\" in params && !isSandboxPermissions(params.permissions))) return false;\n const clipboardDeclared = isRecord(params.permissions)\n && \"clipboardWrite\" in params.permissions;\n return config !== null\n && clipboardDeclared === config.clipboardWrite\n && isCanonicalSecuredHtml(params.html);\n };\n const sendHost = (value) => {\n if (config === null) return;\n try { parentWindow.postMessage(value, config.hostOrigin); }\n catch { /* A detached or navigated parent fails closed. */ }\n };\n const stopReadyAnnouncements = () => {\n if (readyTimer === null) return;\n window.clearInterval(readyTimer);\n readyTimer = null;\n };\n const announceReady = () => {\n if (config === null || hostReady || readyAttempts++ >= 20) {\n stopReadyAnnouncements();\n return;\n }\n sendHost({\n type: \"mono-agent:mcp-app-proxy-ready\",\n nonce: config.nonce,\n invocationId: config.invocationId,\n connectionId: config.connectionId,\n });\n };\n const armReadiness = () => {\n stopReadyAnnouncements();\n readyAttempts = 0;\n readyTimer = window.setInterval(announceReady, 250);\n announceReady();\n };\n const retireAppFrame = () => {\n const retired = appFrame;\n appFrame = null;\n appFrameGeneration += 1;\n retired?.remove();\n root.textContent = \"\";\n };\n const configure = (event) => {\n if (event.source !== parentWindow || !isHostOrigin(event.origin)) return;\n let candidate;\n try { candidate = event.data; }\n catch { return; }\n if (!isConfiguration(candidate)) return;\n if (config === null) {\n config = Object.freeze({\n nonce: candidate.nonce,\n invocationId: candidate.invocationId,\n connectionId: candidate.connectionId,\n clipboardWrite: candidate.clipboardWrite,\n hostOrigin: event.origin,\n });\n armReadiness();\n return;\n }\n if (event.origin !== config.hostOrigin || !identityMatches(candidate)\n || candidate.clipboardWrite !== config.clipboardWrite || !hostReady) return;\n // Configuration is the re-arm request. A delayed duplicate host-ready must\n // never retire a live app whose host bridge has no remaining ready listener.\n hostReady = false;\n retireAppFrame();\n armReadiness();\n };\n const mountResource = (message) => {\n if (config === null || appFrame !== null) return;\n if (!isSandboxResourceReady(message)) {\n root.textContent = \"The app resource was rejected.\";\n return;\n }\n const params = message.params;\n const frame = document.createElement(\"iframe\");\n frame.setAttribute(\"title\", \"MCP App content\");\n frame.setAttribute(\"sandbox\", \"allow-scripts\");\n if (config.clipboardWrite) frame.setAttribute(\"allow\", \"clipboard-write\");\n frame.referrerPolicy = \"no-referrer\";\n const generation = ++appFrameGeneration;\n let frameLoads = 0;\n frame.srcdoc = params.html;\n frame.addEventListener(\"load\", () => {\n if (appFrame !== frame || appFrameGeneration !== generation) return;\n frameLoads += 1;\n if (frameLoads <= 1) return;\n appFrame = null;\n appFrameGeneration += 1;\n frame.remove();\n root.textContent = \"App navigation was blocked.\";\n });\n appFrame = frame;\n root.replaceChildren(frame);\n };\n window.addEventListener(\"message\", (event) => {\n if (config === null) {\n configure(event);\n return;\n }\n if (event.source === parentWindow) {\n if (event.origin !== config.hostOrigin) return;\n if (event.data?.type === \"mono-agent:mcp-app-proxy-config\") {\n configure(event);\n return;\n }\n if (event.data?.type === \"mono-agent:mcp-app-host-ready\") {\n // Host-ready acknowledges only the current configuration arm. Repeated\n // or delayed copies are idempotently ignored while the app stays live.\n if (!identityMatches(event.data) || byteLength(event.data) > 4096 || hostReady) return;\n hostReady = true;\n stopReadyAnnouncements();\n sendHost({ jsonrpc: \"2.0\", method: \"ui/notifications/sandbox-proxy-ready\", params: {} });\n return;\n }\n if (!hostReady || !isRpc(event.data)) return;\n if (event.data.method === \"ui/notifications/sandbox-resource-ready\") {\n // The secured HTML is already bounded by decoded UTF-8 bytes. Validate\n // its small companion fields structurally so JSON escaping cannot make\n // a producer-accepted document disappear behind a generic wire cap.\n mountResource(event.data);\n return;\n }\n if (byteLength(event.data) > 1114112) return;\n appFrame?.contentWindow?.postMessage(event.data, \"*\");\n return;\n }\n if (!hostReady || appFrame === null || event.source !== appFrame.contentWindow || event.origin !== \"null\") return;\n if (!isRpc(event.data) || byteLength(event.data) > 1114112) return;\n if (event.data.method === \"ui/notifications/sandbox-proxy-ready\"\n || event.data.method === \"ui/notifications/sandbox-resource-ready\") return;\n sendHost(event.data);\n });\n})();\n</script>\n</body>\n</html>";
20
+ //# sourceMappingURL=mcp-app-proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-app-proxy.d.ts","sourceRoot":"","sources":["../src/mcp-app-proxy.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAI1D;;;;;;GAMG;AACH,eAAO,MAAM,qCAAqC,QAQtC,CAAC;AAEb;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,00YAmS3B,CAAC"}
@@ -0,0 +1,321 @@
1
+ import { MCP_APP_SECURED_HTML_MAX_BYTES } from "./mcp-app-document.js";
2
+ export const MCP_APP_PROXY_PATH = "/api/v1/mcp-app-proxy";
3
+ const BRIDGE_MESSAGE_MAX_BYTES = 1024 * 1024 + 64 * 1024;
4
+ /**
5
+ * This policy applies only to the fixed, opaque-origin proxy document. The
6
+ * nested app srcdoc inherits it, so capability directives belong exclusively
7
+ * to the canonical inner meta policy. With no default-src, the fixed proxy's
8
+ * inline bootstrap and layout style still work while this envelope retains
9
+ * non-clipping containment.
10
+ */
11
+ export const MCP_APP_PROXY_CONTENT_SECURITY_POLICY = [
12
+ "script-src 'unsafe-inline'",
13
+ "form-action 'none'",
14
+ "object-src 'none'",
15
+ "worker-src 'none'",
16
+ "manifest-src 'none'",
17
+ "navigate-to 'none'",
18
+ "frame-ancestors 'self'",
19
+ ].join("; ");
20
+ /**
21
+ * Fixed trusted outer proxy for the MCP Apps double-iframe model.
22
+ *
23
+ * Invocation-specific values never enter this response or its URL. The direct
24
+ * parent supplies bounded configuration after load; the proxy derives the
25
+ * parent origin from the browser-authenticated MessageEvent, permanently binds
26
+ * the first valid identity tuple, and accepts only an exact repeated
27
+ * configuration to re-arm it. Host-ready remains a one-shot acknowledgement.
28
+ */
29
+ export const MCP_APP_PROXY_DOCUMENT = `<!doctype html>
30
+ <html>
31
+ <head>
32
+ <meta charset="utf-8">
33
+ <meta name="referrer" content="no-referrer">
34
+ <meta name="color-scheme" content="light">
35
+ <style>html,body,#root{width:100%;height:100%;margin:0;overflow:hidden}iframe{width:100%;height:100%;display:block;border:0}</style>
36
+ </head>
37
+ <body>
38
+ <div id="root" aria-live="polite"></div>
39
+ <script>
40
+ (() => {
41
+ "use strict";
42
+ const parentWindow = window.parent;
43
+ const root = document.getElementById("root");
44
+ if (parentWindow === window || root === null) return;
45
+ let config = null;
46
+ let hostReady = false;
47
+ let appFrame = null;
48
+ let appFrameGeneration = 0;
49
+ let readyAttempts = 0;
50
+ let readyTimer = null;
51
+ const byteLength = (value) => {
52
+ try { return new TextEncoder().encode(JSON.stringify(value)).byteLength; }
53
+ catch { return Number.POSITIVE_INFINITY; }
54
+ };
55
+ const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
56
+ const isBoundedIdentity = (value) => typeof value === "string"
57
+ && value.length > 0
58
+ && value.length <= 512
59
+ && !/[\\u0000-\\u001f\\u007f]/u.test(value);
60
+ const isHostOrigin = (value) => {
61
+ if (typeof value !== "string" || value === "null" || value.length > 2048) return false;
62
+ try {
63
+ const parsed = new URL(value);
64
+ return (parsed.protocol === "http:" || parsed.protocol === "https:") && parsed.origin === value;
65
+ } catch {
66
+ return false;
67
+ }
68
+ };
69
+ const isConfiguration = (value) => {
70
+ if (!isRecord(value) || byteLength(value) > 4096) return false;
71
+ const keys = Object.keys(value);
72
+ return keys.length === 5
73
+ && keys.every((key) => key === "type" || key === "nonce" || key === "invocationId"
74
+ || key === "connectionId" || key === "clipboardWrite")
75
+ && value.type === "mono-agent:mcp-app-proxy-config"
76
+ && isBoundedIdentity(value.nonce)
77
+ && isBoundedIdentity(value.invocationId)
78
+ && isBoundedIdentity(value.connectionId)
79
+ && typeof value.clipboardWrite === "boolean";
80
+ };
81
+ const isRpc = (value) => isRecord(value)
82
+ && value.jsonrpc === "2.0"
83
+ && (typeof value.method === "string" || "id" in value);
84
+ const identityMatches = (value) => config !== null
85
+ && isRecord(value)
86
+ && value.nonce === config.nonce
87
+ && value.invocationId === config.invocationId
88
+ && value.connectionId === config.connectionId;
89
+ const exactSources = (directive, name) => {
90
+ const prefix = name + " ";
91
+ if (!directive.startsWith(prefix)) return null;
92
+ const value = directive.slice(prefix.length);
93
+ if (value.length === 0 || value.trim() !== value || /\\s{2,}/u.test(value)) return null;
94
+ return value.split(" ");
95
+ };
96
+ const sameSources = (left, right) => left.length === right.length
97
+ && left.every((value, index) => value === right[index]);
98
+ const isSanitizedOrigin = (value) => {
99
+ if (typeof value !== "string" || value.length > 2048) return false;
100
+ try {
101
+ const parsed = new URL(value);
102
+ const localHttp = parsed.protocol === "http:"
103
+ && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]");
104
+ return (parsed.protocol === "https:" || localHttp)
105
+ && parsed.origin === value
106
+ && !parsed.username
107
+ && !parsed.password
108
+ && (parsed.pathname === "/" || parsed.pathname === "")
109
+ && !parsed.search
110
+ && !parsed.hash;
111
+ } catch {
112
+ return false;
113
+ }
114
+ };
115
+ const isOriginSources = (sources) => sources.length === 1 && sources[0] === "'none'"
116
+ || sources.length > 0
117
+ && sources.length <= 64
118
+ && new Set(sources).size === sources.length
119
+ && sources.every(isSanitizedOrigin);
120
+ const hasOnlyKeys = (value, required, optional = []) => {
121
+ if (!isRecord(value)) return false;
122
+ const keys = Object.keys(value);
123
+ return keys.length >= required.length
124
+ && keys.length <= required.length + optional.length
125
+ && required.every((key) => keys.includes(key))
126
+ && keys.every((key) => required.includes(key) || optional.includes(key));
127
+ };
128
+ const isOriginList = (value) => Array.isArray(value)
129
+ && value.length <= 64
130
+ && new Set(value).size === value.length
131
+ && value.every(isSanitizedOrigin);
132
+ const isSandboxCsp = (value) => hasOnlyKeys(value, [], [
133
+ "connectDomains", "resourceDomains", "frameDomains", "baseUriDomains",
134
+ ]) && Object.values(value).every(isOriginList);
135
+ const isSandboxPermissions = (value) => hasOnlyKeys(value, [], ["clipboardWrite"])
136
+ && (!("clipboardWrite" in value)
137
+ || hasOnlyKeys(value.clipboardWrite, []));
138
+ const isCanonicalSecuredHtml = (html) => {
139
+ const start = '<!doctype html><head><meta http-equiv="Content-Security-Policy" content="';
140
+ const end = '"><meta name="referrer" content="no-referrer"></head>';
141
+ if (!html.startsWith(start)) return false;
142
+ const endIndex = html.indexOf(end, start.length);
143
+ if (endIndex < 0) return false;
144
+ const directives = html.slice(start.length, endIndex).split("; ");
145
+ if (directives.length !== 15
146
+ || directives[0] !== "default-src 'none'"
147
+ || directives[1] !== "script-src 'unsafe-inline'"
148
+ || directives[9] !== "form-action 'none'"
149
+ || directives[10] !== "object-src 'none'"
150
+ || directives[11] !== "child-src 'none'"
151
+ || directives[12] !== "worker-src 'none'"
152
+ || directives[13] !== "manifest-src 'none'"
153
+ || directives[14] !== "navigate-to 'none'") return false;
154
+ const styles = exactSources(directives[2], "style-src");
155
+ const images = exactSources(directives[3], "img-src");
156
+ const fonts = exactSources(directives[4], "font-src");
157
+ const media = exactSources(directives[5], "media-src");
158
+ const connects = exactSources(directives[6], "connect-src");
159
+ const frames = exactSources(directives[7], "frame-src");
160
+ const bases = exactSources(directives[8], "base-uri");
161
+ if (styles === null || images === null || fonts === null || media === null
162
+ || connects === null || frames === null || bases === null) return false;
163
+ const resources = styles[0] === "'unsafe-inline'" ? styles.slice(1) : null;
164
+ return resources !== null
165
+ && resources.length <= 64
166
+ && new Set(resources).size === resources.length
167
+ && resources.every(isSanitizedOrigin)
168
+ && sameSources(images, ["data:", "blob:", ...resources])
169
+ && sameSources(fonts, ["data:", ...resources])
170
+ && sameSources(media, ["blob:", ...resources])
171
+ && isOriginSources(connects)
172
+ && isOriginSources(frames)
173
+ && isOriginSources(bases);
174
+ };
175
+ const isSandboxResourceReady = (value) => {
176
+ if (!hasOnlyKeys(value, ["jsonrpc", "method", "params"])) return false;
177
+ const params = value.params;
178
+ if (value.jsonrpc !== "2.0"
179
+ || value.method !== "ui/notifications/sandbox-resource-ready"
180
+ || !hasOnlyKeys(params, ["html", "sandbox"], ["csp", "permissions"])
181
+ || typeof params.html !== "string"
182
+ || new TextEncoder().encode(params.html).byteLength > ${MCP_APP_SECURED_HTML_MAX_BYTES}
183
+ || params.sandbox !== "allow-scripts"
184
+ || ("csp" in params && !isSandboxCsp(params.csp))
185
+ || ("permissions" in params && !isSandboxPermissions(params.permissions))) return false;
186
+ const clipboardDeclared = isRecord(params.permissions)
187
+ && "clipboardWrite" in params.permissions;
188
+ return config !== null
189
+ && clipboardDeclared === config.clipboardWrite
190
+ && isCanonicalSecuredHtml(params.html);
191
+ };
192
+ const sendHost = (value) => {
193
+ if (config === null) return;
194
+ try { parentWindow.postMessage(value, config.hostOrigin); }
195
+ catch { /* A detached or navigated parent fails closed. */ }
196
+ };
197
+ const stopReadyAnnouncements = () => {
198
+ if (readyTimer === null) return;
199
+ window.clearInterval(readyTimer);
200
+ readyTimer = null;
201
+ };
202
+ const announceReady = () => {
203
+ if (config === null || hostReady || readyAttempts++ >= 20) {
204
+ stopReadyAnnouncements();
205
+ return;
206
+ }
207
+ sendHost({
208
+ type: "mono-agent:mcp-app-proxy-ready",
209
+ nonce: config.nonce,
210
+ invocationId: config.invocationId,
211
+ connectionId: config.connectionId,
212
+ });
213
+ };
214
+ const armReadiness = () => {
215
+ stopReadyAnnouncements();
216
+ readyAttempts = 0;
217
+ readyTimer = window.setInterval(announceReady, 250);
218
+ announceReady();
219
+ };
220
+ const retireAppFrame = () => {
221
+ const retired = appFrame;
222
+ appFrame = null;
223
+ appFrameGeneration += 1;
224
+ retired?.remove();
225
+ root.textContent = "";
226
+ };
227
+ const configure = (event) => {
228
+ if (event.source !== parentWindow || !isHostOrigin(event.origin)) return;
229
+ let candidate;
230
+ try { candidate = event.data; }
231
+ catch { return; }
232
+ if (!isConfiguration(candidate)) return;
233
+ if (config === null) {
234
+ config = Object.freeze({
235
+ nonce: candidate.nonce,
236
+ invocationId: candidate.invocationId,
237
+ connectionId: candidate.connectionId,
238
+ clipboardWrite: candidate.clipboardWrite,
239
+ hostOrigin: event.origin,
240
+ });
241
+ armReadiness();
242
+ return;
243
+ }
244
+ if (event.origin !== config.hostOrigin || !identityMatches(candidate)
245
+ || candidate.clipboardWrite !== config.clipboardWrite || !hostReady) return;
246
+ // Configuration is the re-arm request. A delayed duplicate host-ready must
247
+ // never retire a live app whose host bridge has no remaining ready listener.
248
+ hostReady = false;
249
+ retireAppFrame();
250
+ armReadiness();
251
+ };
252
+ const mountResource = (message) => {
253
+ if (config === null || appFrame !== null) return;
254
+ if (!isSandboxResourceReady(message)) {
255
+ root.textContent = "The app resource was rejected.";
256
+ return;
257
+ }
258
+ const params = message.params;
259
+ const frame = document.createElement("iframe");
260
+ frame.setAttribute("title", "MCP App content");
261
+ frame.setAttribute("sandbox", "allow-scripts");
262
+ if (config.clipboardWrite) frame.setAttribute("allow", "clipboard-write");
263
+ frame.referrerPolicy = "no-referrer";
264
+ const generation = ++appFrameGeneration;
265
+ let frameLoads = 0;
266
+ frame.srcdoc = params.html;
267
+ frame.addEventListener("load", () => {
268
+ if (appFrame !== frame || appFrameGeneration !== generation) return;
269
+ frameLoads += 1;
270
+ if (frameLoads <= 1) return;
271
+ appFrame = null;
272
+ appFrameGeneration += 1;
273
+ frame.remove();
274
+ root.textContent = "App navigation was blocked.";
275
+ });
276
+ appFrame = frame;
277
+ root.replaceChildren(frame);
278
+ };
279
+ window.addEventListener("message", (event) => {
280
+ if (config === null) {
281
+ configure(event);
282
+ return;
283
+ }
284
+ if (event.source === parentWindow) {
285
+ if (event.origin !== config.hostOrigin) return;
286
+ if (event.data?.type === "mono-agent:mcp-app-proxy-config") {
287
+ configure(event);
288
+ return;
289
+ }
290
+ if (event.data?.type === "mono-agent:mcp-app-host-ready") {
291
+ // Host-ready acknowledges only the current configuration arm. Repeated
292
+ // or delayed copies are idempotently ignored while the app stays live.
293
+ if (!identityMatches(event.data) || byteLength(event.data) > 4096 || hostReady) return;
294
+ hostReady = true;
295
+ stopReadyAnnouncements();
296
+ sendHost({ jsonrpc: "2.0", method: "ui/notifications/sandbox-proxy-ready", params: {} });
297
+ return;
298
+ }
299
+ if (!hostReady || !isRpc(event.data)) return;
300
+ if (event.data.method === "ui/notifications/sandbox-resource-ready") {
301
+ // The secured HTML is already bounded by decoded UTF-8 bytes. Validate
302
+ // its small companion fields structurally so JSON escaping cannot make
303
+ // a producer-accepted document disappear behind a generic wire cap.
304
+ mountResource(event.data);
305
+ return;
306
+ }
307
+ if (byteLength(event.data) > ${BRIDGE_MESSAGE_MAX_BYTES}) return;
308
+ appFrame?.contentWindow?.postMessage(event.data, "*");
309
+ return;
310
+ }
311
+ if (!hostReady || appFrame === null || event.source !== appFrame.contentWindow || event.origin !== "null") return;
312
+ if (!isRpc(event.data) || byteLength(event.data) > ${BRIDGE_MESSAGE_MAX_BYTES}) return;
313
+ if (event.data.method === "ui/notifications/sandbox-proxy-ready"
314
+ || event.data.method === "ui/notifications/sandbox-resource-ready") return;
315
+ sendHost(event.data);
316
+ });
317
+ })();
318
+ </script>
319
+ </body>
320
+ </html>`;
321
+ //# sourceMappingURL=mcp-app-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-app-proxy.js","sourceRoot":"","sources":["../src/mcp-app-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAC;AAEvE,MAAM,CAAC,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AAE1D,MAAM,wBAAwB,GAAG,IAAI,GAAG,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qCAAqC,GAAG;IACnD,4BAA4B;IAC5B,oBAAoB;IACpB,mBAAmB;IACnB,mBAAmB;IACnB,qBAAqB;IACrB,oBAAoB;IACpB,wBAAwB;CACzB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8DAyJwB,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCA6HvD,wBAAwB;;;;;yDAKJ,wBAAwB;;;;;;;;QAQzE,CAAC"}
@@ -1,18 +1,32 @@
1
- import type { WebNotificationTriggerKind } from "./contracts.js";
1
+ import type { AgentReplyPart, ProcessJobProjection } from "@mono-agent/agent-contracts";
2
+ import type { WebThreadNotificationTriggerKind } from "./contracts.js";
2
3
  import { type WebStatePathOptions } from "./state-paths.js";
3
- export interface DeliverWebNotificationInput {
4
+ export interface DeliverWebThreadNotificationInput {
4
5
  readonly sourceId: string;
5
- readonly triggerKind: WebNotificationTriggerKind;
6
+ readonly triggerKind: WebThreadNotificationTriggerKind;
6
7
  readonly deliveryKey: string;
7
8
  readonly text: string;
9
+ readonly jobId?: string;
10
+ readonly runId?: string;
8
11
  }
12
+ export interface DeliverWebProcessJobNotificationInput {
13
+ readonly sourceId: string;
14
+ readonly triggerKind: "job";
15
+ readonly deliveryKey: string;
16
+ readonly threadId: string;
17
+ readonly processJob: ProcessJobProjection;
18
+ readonly text?: string;
19
+ readonly parts?: readonly AgentReplyPart[];
20
+ }
21
+ export type DeliverWebNotificationInput = DeliverWebThreadNotificationInput | DeliverWebProcessJobNotificationInput;
9
22
  export interface DeliverWebNotificationOptions extends WebStatePathOptions {
10
23
  readonly fetchImpl?: typeof fetch;
11
24
  readonly timeoutMs?: number;
12
25
  }
13
26
  export interface DeliverWebNotificationResult {
14
- readonly threadId: string;
27
+ readonly threadId?: string;
15
28
  readonly duplicate: boolean;
29
+ readonly tombstoned?: true;
16
30
  }
17
31
  /** Deliver once to the active local web console. There is intentionally no retry or outbox. */
18
32
  export declare function deliverWebNotification(input: DeliverWebNotificationInput, options?: DeliverWebNotificationOptions): Promise<DeliverWebNotificationResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"notification-client.d.ts","sourceRoot":"","sources":["../src/notification-client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAQlF,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC;IACjD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,6BAA8B,SAAQ,mBAAmB;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAWD,+FAA+F;AAC/F,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,EAClC,OAAO,GAAE,6BAAkC,GAC1C,OAAO,CAAC,4BAA4B,CAAC,CA0CvC"}
1
+ {"version":3,"file":"notification-client.d.ts","sourceRoot":"","sources":["../src/notification-client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExF,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AAEvE,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAQlF,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,gCAAgC,CAAC;IACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,qCAAqC;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CAC5C;AAED,MAAM,MAAM,2BAA2B,GACnC,iCAAiC,GACjC,qCAAqC,CAAC;AAE1C,MAAM,WAAW,6BAA8B,SAAQ,mBAAmB;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC;CAC5B;AAWD,+FAA+F;AAC/F,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,EAClC,OAAO,GAAE,6BAAkC,GAC1C,OAAO,CAAC,4BAA4B,CAAC,CAiDvC"}
@@ -40,16 +40,23 @@ export async function deliverWebNotification(input, options = {}) {
40
40
  throw new WebConsoleError("invalid_notification_response", "The web notification ingress returned invalid JSON.", 502);
41
41
  }
42
42
  const result = asRecord(parsed);
43
- if (result === undefined || typeof result.threadId !== "string" || typeof result.duplicate !== "boolean") {
43
+ if (result === undefined
44
+ || (typeof result.threadId !== "string" && result.threadId !== null)
45
+ || typeof result.duplicate !== "boolean"
46
+ || (result.threadId === null && (result.duplicate !== true || result.tombstoned !== true))) {
44
47
  throw new WebConsoleError("invalid_notification_response", "The web notification ingress returned an invalid result.", 502);
45
48
  }
46
- return { threadId: result.threadId, duplicate: result.duplicate };
49
+ return {
50
+ ...(typeof result.threadId === "string" ? { threadId: result.threadId } : {}),
51
+ duplicate: result.duplicate,
52
+ ...(result.tombstoned === true ? { tombstoned: true } : {}),
53
+ };
47
54
  }
48
55
  async function readIngressRecord(path) {
49
56
  const info = await lstat(path).catch(() => undefined);
50
57
  const currentUid = typeof process.getuid === "function" ? process.getuid() : undefined;
51
58
  if (info === undefined || !info.isFile() || info.isSymbolicLink()
52
- || info.size <= 0 || info.size > MAX_INGRESS_RECORD_BYTES
59
+ || info.nlink !== 1 || info.size <= 0 || info.size > MAX_INGRESS_RECORD_BYTES
53
60
  || (currentUid !== undefined && info.uid !== currentUid)
54
61
  || (info.mode & 0o077) !== 0) {
55
62
  throw new WebConsoleError("notification_ingress_unavailable", "The owner-private web notification ingress record is unavailable.", 503);
@@ -58,7 +65,9 @@ async function readIngressRecord(path) {
58
65
  let contents;
59
66
  try {
60
67
  const opened = await handle.stat();
61
- if (!opened.isFile() || opened.dev !== info.dev || opened.ino !== info.ino || opened.size !== info.size) {
68
+ if (!opened.isFile() || opened.dev !== info.dev || opened.ino !== info.ino || opened.size !== info.size
69
+ || opened.nlink !== 1 || (currentUid !== undefined && opened.uid !== currentUid)
70
+ || (opened.mode & 0o077) !== 0) {
62
71
  throw new WebConsoleError("notification_ingress_unavailable", "The web notification ingress record changed while opening.", 503);
63
72
  }
64
73
  contents = await handle.readFile("utf8");
@@ -1 +1 @@
1
- {"version":3,"file":"notification-client.js","sourceRoot":"","sources":["../src/notification-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"notification-client.js","sourceRoot":"","sources":["../src/notification-client.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import { type AgentReplyPart, type ProcessJobProjection } from "@mono-agent/agent-contracts";
2
+ import { type WebThreadNotificationTriggerKind } from "./contracts.js";
1
3
  import type { WebService, WebServiceLogger } from "./service.js";
2
4
  declare const INGRESS_SCHEMA = 1;
3
5
  export interface WebNotificationIngressRecord {
@@ -13,5 +15,22 @@ export interface WebNotificationIngressHandle {
13
15
  stop(): Promise<void>;
14
16
  }
15
17
  export declare function startWebNotificationIngress(service: WebService, logger?: WebServiceLogger): Promise<WebNotificationIngressHandle>;
18
+ type ParsedNotificationRequest = {
19
+ readonly sourceId: string;
20
+ readonly triggerKind: WebThreadNotificationTriggerKind;
21
+ readonly deliveryKey: string;
22
+ readonly text: string;
23
+ readonly jobId?: string;
24
+ readonly runId?: string;
25
+ } | {
26
+ readonly sourceId: string;
27
+ readonly triggerKind: "job";
28
+ readonly deliveryKey: string;
29
+ readonly threadId: string;
30
+ readonly processJob: ProcessJobProjection;
31
+ readonly text?: string;
32
+ readonly parts?: readonly AgentReplyPart[];
33
+ };
34
+ export declare function parseNotificationRequest(body: unknown): ParsedNotificationRequest;
16
35
  export {};
17
36
  //# sourceMappingURL=notification-ingress.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"notification-ingress.d.ts","sourceRoot":"","sources":["../src/notification-ingress.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEjE,QAAA,MAAM,cAAc,IAAI,CAAC;AAMzB,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,MAAM,EAAE,OAAO,cAAc,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,UAAU,EACnB,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,4BAA4B,CAAC,CAmGvC"}
1
+ {"version":3,"file":"notification-ingress.d.ts","sourceRoot":"","sources":["../src/notification-ingress.ts"],"names":[],"mappings":"AAIA,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAAgC,KAAK,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AAErG,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEjE,QAAA,MAAM,cAAc,IAAI,CAAC;AAMzB,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,MAAM,EAAE,OAAO,cAAc,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,UAAU,EACnB,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,4BAA4B,CAAC,CAoGvC;AAED,KAAK,yBAAyB,GAAG;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,gCAAgC,CAAC;IACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG;IACF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CAC5C,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,GAAG,yBAAyB,CA+DjF"}