@pcircle/footprint 1.1.1 → 1.2.1

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 (207) hide show
  1. package/README.md +165 -12
  2. package/SKILL.md +72 -15
  3. package/dist/src/analyzers/content-analyzer.d.ts +20 -0
  4. package/dist/src/analyzers/content-analyzer.d.ts.map +1 -0
  5. package/dist/src/analyzers/content-analyzer.js +169 -0
  6. package/dist/src/analyzers/content-analyzer.js.map +1 -0
  7. package/dist/src/index.d.ts +38 -0
  8. package/dist/src/index.d.ts.map +1 -0
  9. package/dist/src/index.js +243 -0
  10. package/dist/src/index.js.map +1 -0
  11. package/dist/src/lib/crypto/decrypt.d.ts.map +1 -0
  12. package/dist/{lib → src/lib}/crypto/decrypt.js +4 -0
  13. package/dist/src/lib/crypto/decrypt.js.map +1 -0
  14. package/dist/src/lib/crypto/encrypt.d.ts.map +1 -0
  15. package/dist/src/lib/crypto/encrypt.js.map +1 -0
  16. package/dist/{lib → src/lib}/crypto/index.d.ts +1 -1
  17. package/dist/src/lib/crypto/index.d.ts.map +1 -0
  18. package/dist/{lib → src/lib}/crypto/index.js +1 -1
  19. package/dist/src/lib/crypto/index.js.map +1 -0
  20. package/dist/{lib → src/lib}/crypto/key-derivation.d.ts +17 -3
  21. package/dist/src/lib/crypto/key-derivation.d.ts.map +1 -0
  22. package/dist/{lib → src/lib}/crypto/key-derivation.js +44 -3
  23. package/dist/src/lib/crypto/key-derivation.js.map +1 -0
  24. package/dist/src/lib/crypto/types.d.ts.map +1 -0
  25. package/dist/src/lib/crypto/types.js.map +1 -0
  26. package/dist/src/lib/errors/base-error.d.ts +15 -0
  27. package/dist/src/lib/errors/base-error.d.ts.map +1 -0
  28. package/dist/src/lib/errors/base-error.js +34 -0
  29. package/dist/src/lib/errors/base-error.js.map +1 -0
  30. package/dist/src/lib/errors/crypto-error.d.ts +29 -0
  31. package/dist/src/lib/errors/crypto-error.d.ts.map +1 -0
  32. package/dist/src/lib/errors/crypto-error.js +43 -0
  33. package/dist/src/lib/errors/crypto-error.js.map +1 -0
  34. package/dist/src/lib/errors/index.d.ts +26 -0
  35. package/dist/src/lib/errors/index.d.ts.map +1 -0
  36. package/dist/src/lib/errors/index.js +26 -0
  37. package/dist/src/lib/errors/index.js.map +1 -0
  38. package/dist/src/lib/errors/storage-error.d.ts +25 -0
  39. package/dist/src/lib/errors/storage-error.d.ts.map +1 -0
  40. package/dist/src/lib/errors/storage-error.js +38 -0
  41. package/dist/src/lib/errors/storage-error.js.map +1 -0
  42. package/dist/src/lib/errors/validation-error.d.ts +21 -0
  43. package/dist/src/lib/errors/validation-error.d.ts.map +1 -0
  44. package/dist/src/lib/errors/validation-error.js +29 -0
  45. package/dist/src/lib/errors/validation-error.js.map +1 -0
  46. package/dist/{lib → src/lib}/storage/database.d.ts +14 -2
  47. package/dist/src/lib/storage/database.d.ts.map +1 -0
  48. package/dist/{lib → src/lib}/storage/database.js +65 -29
  49. package/dist/src/lib/storage/database.js.map +1 -0
  50. package/dist/src/lib/storage/export.d.ts.map +1 -0
  51. package/dist/{lib → src/lib}/storage/export.js +16 -1
  52. package/dist/src/lib/storage/export.js.map +1 -0
  53. package/dist/{lib → src/lib}/storage/git.d.ts +1 -1
  54. package/dist/src/lib/storage/git.d.ts.map +1 -0
  55. package/dist/{lib → src/lib}/storage/git.js +5 -2
  56. package/dist/src/lib/storage/git.js.map +1 -0
  57. package/dist/{lib → src/lib}/storage/index.d.ts +1 -0
  58. package/dist/src/lib/storage/index.d.ts.map +1 -0
  59. package/dist/{lib → src/lib}/storage/index.js +1 -0
  60. package/dist/src/lib/storage/index.js.map +1 -0
  61. package/dist/src/lib/storage/salt-storage.d.ts +25 -0
  62. package/dist/src/lib/storage/salt-storage.d.ts.map +1 -0
  63. package/dist/src/lib/storage/salt-storage.js +66 -0
  64. package/dist/src/lib/storage/salt-storage.js.map +1 -0
  65. package/dist/src/lib/storage/schema.d.ts.map +1 -0
  66. package/dist/{lib → src/lib}/storage/schema.js +22 -1
  67. package/dist/src/lib/storage/schema.js.map +1 -0
  68. package/dist/src/lib/storage/types.d.ts.map +1 -0
  69. package/dist/src/lib/storage/types.js.map +1 -0
  70. package/dist/src/lib/tool-response.d.ts +84 -0
  71. package/dist/src/lib/tool-response.d.ts.map +1 -0
  72. package/dist/src/lib/tool-response.js +91 -0
  73. package/dist/src/lib/tool-response.js.map +1 -0
  74. package/dist/src/lib/tool-wrapper.d.ts +45 -0
  75. package/dist/src/lib/tool-wrapper.d.ts.map +1 -0
  76. package/dist/src/lib/tool-wrapper.js +73 -0
  77. package/dist/src/lib/tool-wrapper.js.map +1 -0
  78. package/dist/{test-helpers.d.ts → src/test-helpers.d.ts} +4 -4
  79. package/dist/src/test-helpers.d.ts.map +1 -0
  80. package/dist/{test-helpers.js → src/test-helpers.js} +2 -2
  81. package/dist/src/test-helpers.js.map +1 -0
  82. package/dist/src/tools/capture-footprint.d.ts +29 -0
  83. package/dist/src/tools/capture-footprint.d.ts.map +1 -0
  84. package/dist/src/tools/capture-footprint.js +94 -0
  85. package/dist/src/tools/capture-footprint.js.map +1 -0
  86. package/dist/src/tools/delete-footprints.d.ts +22 -0
  87. package/dist/src/tools/delete-footprints.d.ts.map +1 -0
  88. package/dist/src/tools/delete-footprints.js +33 -0
  89. package/dist/src/tools/delete-footprints.js.map +1 -0
  90. package/dist/src/tools/export-footprints.d.ts +33 -0
  91. package/dist/src/tools/export-footprints.d.ts.map +1 -0
  92. package/dist/src/tools/export-footprints.js +50 -0
  93. package/dist/src/tools/export-footprints.js.map +1 -0
  94. package/dist/src/tools/get-footprint.d.ts +51 -0
  95. package/dist/src/tools/get-footprint.d.ts.map +1 -0
  96. package/dist/src/tools/get-footprint.js +66 -0
  97. package/dist/src/tools/get-footprint.js.map +1 -0
  98. package/dist/src/tools/get-tag-stats.d.ts +30 -0
  99. package/dist/src/tools/get-tag-stats.d.ts.map +1 -0
  100. package/dist/src/tools/get-tag-stats.js +33 -0
  101. package/dist/src/tools/get-tag-stats.js.map +1 -0
  102. package/dist/src/tools/index.d.ts +16 -0
  103. package/dist/src/tools/index.d.ts.map +1 -0
  104. package/dist/src/tools/index.js +16 -0
  105. package/dist/src/tools/index.js.map +1 -0
  106. package/dist/src/tools/list-footprints.d.ts +57 -0
  107. package/dist/src/tools/list-footprints.d.ts.map +1 -0
  108. package/dist/src/tools/list-footprints.js +57 -0
  109. package/dist/src/tools/list-footprints.js.map +1 -0
  110. package/dist/src/tools/remove-tag.d.ts +22 -0
  111. package/dist/src/tools/remove-tag.d.ts.map +1 -0
  112. package/dist/src/tools/remove-tag.js +30 -0
  113. package/dist/src/tools/remove-tag.js.map +1 -0
  114. package/dist/src/tools/rename-tag.d.ts +24 -0
  115. package/dist/src/tools/rename-tag.d.ts.map +1 -0
  116. package/dist/src/tools/rename-tag.js +34 -0
  117. package/dist/src/tools/rename-tag.js.map +1 -0
  118. package/dist/src/tools/search-footprints.d.ts +60 -0
  119. package/dist/src/tools/search-footprints.d.ts.map +1 -0
  120. package/dist/src/tools/search-footprints.js +78 -0
  121. package/dist/src/tools/search-footprints.js.map +1 -0
  122. package/dist/src/tools/suggest-capture.d.ts +21 -0
  123. package/dist/src/tools/suggest-capture.d.ts.map +1 -0
  124. package/dist/src/tools/suggest-capture.js +37 -0
  125. package/dist/src/tools/suggest-capture.js.map +1 -0
  126. package/dist/src/tools/verify-footprint.d.ts +104 -0
  127. package/dist/src/tools/verify-footprint.d.ts.map +1 -0
  128. package/dist/src/tools/verify-footprint.js +102 -0
  129. package/dist/src/tools/verify-footprint.js.map +1 -0
  130. package/dist/{types.d.ts → src/types.d.ts} +1 -1
  131. package/dist/src/types.d.ts.map +1 -0
  132. package/dist/{lib/storage → src}/types.js.map +1 -1
  133. package/dist/src/ui/register.d.ts.map +1 -0
  134. package/dist/src/ui/register.js +94 -0
  135. package/dist/src/ui/register.js.map +1 -0
  136. package/dist/tests/error-handling.test.d.ts +2 -0
  137. package/dist/tests/error-handling.test.d.ts.map +1 -0
  138. package/dist/tests/error-handling.test.js +114 -0
  139. package/dist/tests/error-handling.test.js.map +1 -0
  140. package/dist/tests/fixtures.d.ts +87 -0
  141. package/dist/tests/fixtures.d.ts.map +1 -0
  142. package/dist/tests/fixtures.js +130 -0
  143. package/dist/tests/fixtures.js.map +1 -0
  144. package/dist/tests/integration.test.d.ts +2 -0
  145. package/dist/tests/integration.test.d.ts.map +1 -0
  146. package/dist/tests/integration.test.js +115 -0
  147. package/dist/tests/integration.test.js.map +1 -0
  148. package/dist/tests/resources.test.d.ts +2 -0
  149. package/dist/tests/resources.test.d.ts.map +1 -0
  150. package/dist/tests/resources.test.js +73 -0
  151. package/dist/tests/resources.test.js.map +1 -0
  152. package/dist/tests/setup.d.ts +8 -0
  153. package/dist/tests/setup.d.ts.map +1 -0
  154. package/dist/tests/setup.js +8 -0
  155. package/dist/tests/setup.js.map +1 -0
  156. package/dist/tests/tools.test.d.ts +2 -0
  157. package/dist/tests/tools.test.d.ts.map +1 -0
  158. package/dist/tests/tools.test.js +224 -0
  159. package/dist/tests/tools.test.js.map +1 -0
  160. package/dist/ui/dashboard.html +1 -1
  161. package/dist/ui/detail.html +1 -1
  162. package/dist/ui/export.html +1 -1
  163. package/dist/ui-tmp/ui/export.html +1 -1
  164. package/package.json +8 -8
  165. package/dist/index.d.ts +0 -19
  166. package/dist/index.d.ts.map +0 -1
  167. package/dist/index.js +0 -694
  168. package/dist/index.js.map +0 -1
  169. package/dist/lib/crypto/decrypt.d.ts.map +0 -1
  170. package/dist/lib/crypto/decrypt.js.map +0 -1
  171. package/dist/lib/crypto/encrypt.d.ts.map +0 -1
  172. package/dist/lib/crypto/encrypt.js.map +0 -1
  173. package/dist/lib/crypto/index.d.ts.map +0 -1
  174. package/dist/lib/crypto/index.js.map +0 -1
  175. package/dist/lib/crypto/key-derivation.d.ts.map +0 -1
  176. package/dist/lib/crypto/key-derivation.js.map +0 -1
  177. package/dist/lib/crypto/types.d.ts.map +0 -1
  178. package/dist/lib/crypto/types.js.map +0 -1
  179. package/dist/lib/storage/database.d.ts.map +0 -1
  180. package/dist/lib/storage/database.js.map +0 -1
  181. package/dist/lib/storage/export.d.ts.map +0 -1
  182. package/dist/lib/storage/export.js.map +0 -1
  183. package/dist/lib/storage/git.d.ts.map +0 -1
  184. package/dist/lib/storage/git.js.map +0 -1
  185. package/dist/lib/storage/index.d.ts.map +0 -1
  186. package/dist/lib/storage/index.js.map +0 -1
  187. package/dist/lib/storage/schema.d.ts.map +0 -1
  188. package/dist/lib/storage/schema.js.map +0 -1
  189. package/dist/lib/storage/types.d.ts.map +0 -1
  190. package/dist/test-helpers.d.ts.map +0 -1
  191. package/dist/test-helpers.js.map +0 -1
  192. package/dist/types.d.ts.map +0 -1
  193. package/dist/types.js.map +0 -1
  194. package/dist/ui/register.d.ts.map +0 -1
  195. package/dist/ui/register.js +0 -154
  196. package/dist/ui/register.js.map +0 -1
  197. /package/dist/{lib → src/lib}/crypto/decrypt.d.ts +0 -0
  198. /package/dist/{lib → src/lib}/crypto/encrypt.d.ts +0 -0
  199. /package/dist/{lib → src/lib}/crypto/encrypt.js +0 -0
  200. /package/dist/{lib → src/lib}/crypto/types.d.ts +0 -0
  201. /package/dist/{lib → src/lib}/crypto/types.js +0 -0
  202. /package/dist/{lib → src/lib}/storage/export.d.ts +0 -0
  203. /package/dist/{lib → src/lib}/storage/schema.d.ts +0 -0
  204. /package/dist/{lib → src/lib}/storage/types.d.ts +0 -0
  205. /package/dist/{lib → src/lib}/storage/types.js +0 -0
  206. /package/dist/{types.js → src/types.js} +0 -0
  207. /package/dist/{ui → src/ui}/register.d.ts +0 -0
@@ -0,0 +1,224 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { FootprintServer, FootprintTestHelpers } from "../src/index.js";
3
+ import * as fs from "fs";
4
+ import * as path from "path";
5
+ import { tmpdir } from "node:os";
6
+ describe("MCP Tools", () => {
7
+ let server;
8
+ let helpers;
9
+ let testDbPath;
10
+ let tempDir;
11
+ const testPassword = "test-password-123";
12
+ beforeEach(() => {
13
+ // Create unique temporary directory for each test
14
+ tempDir = fs.mkdtempSync(path.join(tmpdir(), "evidence-mcp-test-"));
15
+ testDbPath = path.join(tempDir, "test-evidence.db");
16
+ // Clean up any existing test database
17
+ if (fs.existsSync(testDbPath)) {
18
+ fs.unlinkSync(testDbPath);
19
+ }
20
+ const config = {
21
+ dbPath: testDbPath,
22
+ password: testPassword,
23
+ };
24
+ server = new FootprintServer(config);
25
+ helpers = new FootprintTestHelpers(server);
26
+ });
27
+ afterEach(() => {
28
+ // Clean up test database and directory
29
+ try {
30
+ if (server) {
31
+ // Close any database connections if the server has them
32
+ }
33
+ }
34
+ catch (error) {
35
+ // Ignore close errors
36
+ }
37
+ try {
38
+ if (tempDir && fs.existsSync(tempDir)) {
39
+ fs.rmSync(tempDir, { recursive: true, force: true });
40
+ }
41
+ }
42
+ catch (error) {
43
+ // Ignore cleanup errors
44
+ }
45
+ });
46
+ describe("capture-footprint tool", () => {
47
+ it("should capture and encrypt conversation evidence", async () => {
48
+ // This test will fail initially - tool not registered yet
49
+ const tools = await helpers.getTools();
50
+ expect(tools).toContainEqual(expect.objectContaining({
51
+ name: "capture-footprint",
52
+ description: expect.stringContaining("conversation"),
53
+ }));
54
+ });
55
+ });
56
+ describe("list-footprints tool", () => {
57
+ it("should list all evidences", async () => {
58
+ const tools = await helpers.getTools();
59
+ expect(tools).toContainEqual(expect.objectContaining({
60
+ name: "list-footprints",
61
+ }));
62
+ });
63
+ });
64
+ describe("export-footprints tool", () => {
65
+ it("should export evidences to ZIP", async () => {
66
+ const tools = await helpers.getTools();
67
+ expect(tools).toContainEqual(expect.objectContaining({
68
+ name: "export-footprints",
69
+ }));
70
+ });
71
+ });
72
+ describe("get-footprint tool", () => {
73
+ it("should retrieve and decrypt specific evidence", async () => {
74
+ const tools = await helpers.getTools();
75
+ expect(tools).toContainEqual(expect.objectContaining({
76
+ name: "get-footprint",
77
+ }));
78
+ });
79
+ });
80
+ describe("search-footprints tool", () => {
81
+ it("should be registered as a tool", async () => {
82
+ const tools = await helpers.getTools();
83
+ expect(tools).toContainEqual(expect.objectContaining({
84
+ name: "search-footprints",
85
+ description: expect.stringContaining("Search and filter footprints"),
86
+ }));
87
+ });
88
+ it("should have correct input schema", async () => {
89
+ const tools = await helpers.getTools();
90
+ const searchTool = tools.find((t) => t.name === "search-footprints");
91
+ expect(searchTool).toBeDefined();
92
+ // The helper only returns name and description, not the full schema
93
+ expect(searchTool?.name).toBe("search-footprints");
94
+ expect(searchTool?.description).toContain("Search and filter footprints");
95
+ });
96
+ it("should return empty results for no matches", async () => {
97
+ const result = await helpers.callTool("search-footprints", {
98
+ query: "nonexistent-conversation",
99
+ });
100
+ expect(result).toHaveProperty("structuredContent");
101
+ expect(result.structuredContent).toHaveProperty("evidences");
102
+ expect(result.structuredContent).toHaveProperty("total");
103
+ expect(result.structuredContent.evidences).toHaveLength(0);
104
+ expect(result.structuredContent.total).toBe(0);
105
+ });
106
+ it("should validate limit parameter", async () => {
107
+ await expect(helpers.callTool("search-footprints", { limit: 0 })).rejects.toThrow("Limit must be positive");
108
+ await expect(helpers.callTool("search-footprints", { limit: -1 })).rejects.toThrow("Limit must be positive");
109
+ });
110
+ it("should validate offset parameter", async () => {
111
+ await expect(helpers.callTool("search-footprints", { offset: -1 })).rejects.toThrow("Offset cannot be negative");
112
+ });
113
+ it("should validate date parameters", async () => {
114
+ await expect(helpers.callTool("search-footprints", { dateFrom: "invalid-date" })).rejects.toThrow("dateFrom must be a valid ISO date string");
115
+ await expect(helpers.callTool("search-footprints", { dateTo: "invalid-date" })).rejects.toThrow("dateTo must be a valid ISO date string");
116
+ });
117
+ });
118
+ describe("verify-footprint tool", () => {
119
+ it("should verify evidence integrity", async () => {
120
+ // First capture an evidence
121
+ const captureResult = await helpers.callTool("capture-footprint", {
122
+ conversationId: "test-verify",
123
+ llmProvider: "Test LLM",
124
+ content: "Test content for verification",
125
+ messageCount: 1,
126
+ });
127
+ const evidenceId = captureResult.structuredContent.id;
128
+ // Then verify it
129
+ const verifyResult = await helpers.callTool("verify-footprint", {
130
+ id: evidenceId,
131
+ });
132
+ expect(verifyResult.structuredContent.verified).toBe(true);
133
+ expect(verifyResult.structuredContent.checks.contentIntegrity.passed).toBe(true);
134
+ });
135
+ });
136
+ describe("suggest-capture tool", () => {
137
+ it("should be registered as a tool", async () => {
138
+ const tools = await helpers.getTools();
139
+ expect(tools).toContainEqual(expect.objectContaining({
140
+ name: "suggest-capture",
141
+ description: expect.stringContaining("Analyze conversation content"),
142
+ }));
143
+ });
144
+ it("should suggest capture for IP-related content", async () => {
145
+ const result = await helpers.callTool("suggest-capture", {
146
+ summary: "We discussed the new caching algorithm patent and its implementation details. The invention uses a novel approach for memory management.",
147
+ });
148
+ expect(result.structuredContent).toHaveProperty("shouldCapture", true);
149
+ expect(result.structuredContent).toHaveProperty("reason", expect.stringContaining("IP"));
150
+ expect(result.structuredContent).toHaveProperty("suggestedTags");
151
+ expect(result.structuredContent.suggestedTags).toContain("ip");
152
+ expect(result.structuredContent).toHaveProperty("suggestedConversationId", expect.any(String));
153
+ expect(result.structuredContent).toHaveProperty("confidence", expect.any(Number));
154
+ expect(result.structuredContent.confidence).toBeGreaterThan(0.7);
155
+ });
156
+ it("should suggest capture for legal content", async () => {
157
+ const result = await helpers.callTool("suggest-capture", {
158
+ summary: "We reviewed the software license agreement and contract terms for the new vendor partnership.",
159
+ });
160
+ expect(result.structuredContent.shouldCapture).toBe(true);
161
+ expect(result.structuredContent.reason).toContain("legal");
162
+ expect(result.structuredContent.suggestedTags).toContain("legal");
163
+ expect(result.structuredContent.confidence).toBeGreaterThan(0.7);
164
+ });
165
+ it("should suggest capture for business decisions", async () => {
166
+ const result = await helpers.callTool("suggest-capture", {
167
+ summary: "The team made a critical decision about the product milestone and approved the final deliverable for Q1.",
168
+ });
169
+ expect(result.structuredContent.shouldCapture).toBe(true);
170
+ expect(result.structuredContent.reason).toContain("business");
171
+ expect(result.structuredContent.suggestedTags).toContain("decision");
172
+ expect(result.structuredContent.confidence).toBeGreaterThan(0.7);
173
+ });
174
+ it("should suggest capture for research content", async () => {
175
+ const result = await helpers.callTool("suggest-capture", {
176
+ summary: "Our research findings show clear evidence supporting our hypothesis about machine learning performance.",
177
+ });
178
+ expect(result.structuredContent.shouldCapture).toBe(true);
179
+ expect(result.structuredContent.reason).toContain("research");
180
+ expect(result.structuredContent.suggestedTags).toContain("research");
181
+ expect(result.structuredContent.confidence).toBeGreaterThan(0.7);
182
+ });
183
+ it("should suggest capture for compliance content", async () => {
184
+ const result = await helpers.callTool("suggest-capture", {
185
+ summary: "We need to document this for audit purposes and ensure compliance with the new regulations.",
186
+ });
187
+ expect(result.structuredContent.shouldCapture).toBe(true);
188
+ expect(result.structuredContent.reason).toContain("compliance");
189
+ expect(result.structuredContent.suggestedTags).toContain("audit");
190
+ expect(result.structuredContent.confidence).toBeGreaterThan(0.7);
191
+ });
192
+ it("should not suggest capture for casual conversation", async () => {
193
+ const result = await helpers.callTool("suggest-capture", {
194
+ summary: "We chatted about the weather and discussed weekend plans. Nothing important was covered.",
195
+ });
196
+ expect(result.structuredContent.shouldCapture).toBe(false);
197
+ expect(result.structuredContent.reason).toContain("casual");
198
+ expect(result.structuredContent.confidence).toBeLessThan(0.5);
199
+ });
200
+ it("should generate appropriate conversation ID", async () => {
201
+ const result = await helpers.callTool("suggest-capture", {
202
+ summary: "Discussing patent application for the new AI algorithm invention.",
203
+ });
204
+ expect(result.structuredContent.suggestedConversationId).toMatch(/^[a-z0-9-]+$/);
205
+ expect(result.structuredContent.suggestedConversationId).toContain("patent");
206
+ expect(result.structuredContent.suggestedConversationId).toContain(new Date().toISOString().slice(0, 10));
207
+ });
208
+ it("should validate input parameters", async () => {
209
+ await expect(helpers.callTool("suggest-capture", {})).rejects.toThrow();
210
+ await expect(helpers.callTool("suggest-capture", { summary: "" })).rejects.toThrow("Summary cannot be empty");
211
+ });
212
+ it("should handle multiple keyword categories", async () => {
213
+ const result = await helpers.callTool("suggest-capture", {
214
+ summary: "We discussed the patent license agreement and our research findings for compliance documentation.",
215
+ });
216
+ expect(result.structuredContent.shouldCapture).toBe(true);
217
+ expect(result.structuredContent.suggestedTags.length).toBeGreaterThan(1);
218
+ expect(result.structuredContent.suggestedTags).toContain("ip");
219
+ expect(result.structuredContent.suggestedTags).toContain("legal");
220
+ expect(result.structuredContent.confidence).toBeGreaterThan(0.8);
221
+ });
222
+ });
223
+ });
224
+ //# sourceMappingURL=tools.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.test.js","sourceRoot":"","sources":["../../tests/tools.test.ts"],"names":[],"mappings":"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"}
@@ -764,7 +764,7 @@ Note: This type uses \`Record<K, string | undefined>\` rather than \`Partial<Rec
764
764
  for compatibility with Zod schema generation. Both are functionally equivalent for validation.`);c.object({method:c.literal("ui/open-link"),params:c.object({url:c.string().describe("URL to open in the host's browser")})});var gI=c.object({isError:c.boolean().optional().describe("True if the host failed to open the URL (e.g., due to security policy).")}).passthrough(),$I=c.object({isError:c.boolean().optional().describe("True if the host rejected or failed to deliver the message.")}).passthrough();c.object({method:c.literal("ui/notifications/sandbox-proxy-ready"),params:c.object({})});var lo=c.object({connectDomains:c.array(c.string()).optional().describe("Origins for network requests (fetch/XHR/WebSocket)."),resourceDomains:c.array(c.string()).optional().describe("Origins for static resources (scripts, images, styles, fonts)."),frameDomains:c.array(c.string()).optional().describe("Origins for nested iframes (frame-src directive)."),baseUriDomains:c.array(c.string()).optional().describe("Allowed base URIs for the document (base-uri directive).")}),co=c.object({camera:c.object({}).optional().describe("Request camera access (Permission Policy `camera` feature)."),microphone:c.object({}).optional().describe("Request microphone access (Permission Policy `microphone` feature)."),geolocation:c.object({}).optional().describe("Request geolocation access (Permission Policy `geolocation` feature)."),clipboardWrite:c.object({}).optional().describe("Request clipboard write access (Permission Policy `clipboard-write` feature).")});c.object({method:c.literal("ui/notifications/size-changed"),params:c.object({width:c.number().optional().describe("New width in pixels."),height:c.number().optional().describe("New height in pixels.")})});var _I=c.object({method:c.literal("ui/notifications/tool-input"),params:c.object({arguments:c.record(c.string(),c.unknown().describe("Complete tool call arguments as key-value pairs.")).optional().describe("Complete tool call arguments as key-value pairs.")})}),bI=c.object({method:c.literal("ui/notifications/tool-input-partial"),params:c.object({arguments:c.record(c.string(),c.unknown().describe("Partial tool call arguments (incomplete, may change).")).optional().describe("Partial tool call arguments (incomplete, may change).")})}),yI=c.object({method:c.literal("ui/notifications/tool-cancelled"),params:c.object({reason:c.string().optional().describe('Optional reason for the cancellation (e.g., "user action", "timeout").')})}),kI=c.object({fonts:c.string().optional()}),II=c.object({variables:hI.optional().describe("CSS variables for theming the app."),css:kI.optional().describe("CSS blocks that apps can inject.")}),wI=c.object({method:c.literal("ui/resource-teardown"),params:c.object({})});c.record(c.string(),c.unknown());var is=c.object({text:c.object({}).optional().describe("Host supports text content blocks."),image:c.object({}).optional().describe("Host supports image content blocks."),audio:c.object({}).optional().describe("Host supports audio content blocks."),resource:c.object({}).optional().describe("Host supports resource content blocks."),resourceLink:c.object({}).optional().describe("Host supports resource link content blocks."),structuredContent:c.object({}).optional().describe("Host supports structured content.")}),xI=c.object({experimental:c.object({}).optional().describe("Experimental features (structure TBD)."),openLinks:c.object({}).optional().describe("Host supports opening external URLs."),serverTools:c.object({listChanged:c.boolean().optional().describe("Host supports tools/list_changed notifications.")}).optional().describe("Host can proxy tool calls to the MCP server."),serverResources:c.object({listChanged:c.boolean().optional().describe("Host supports resources/list_changed notifications.")}).optional().describe("Host can proxy resource reads to the MCP server."),logging:c.object({}).optional().describe("Host accepts log messages."),sandbox:c.object({permissions:co.optional().describe("Permissions granted by the host (camera, microphone, geolocation)."),csp:lo.optional().describe("CSP domains approved by the host.")}).optional().describe("Sandbox configuration applied by the host."),updateModelContext:is.optional().describe("Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns."),message:is.optional().describe("Host supports receiving content messages (ui/message) from the view.")}),SI=c.object({experimental:c.object({}).optional().describe("Experimental features (structure TBD)."),tools:c.object({listChanged:c.boolean().optional().describe("App supports tools/list_changed notifications.")}).optional().describe("App exposes MCP-style tools that the host can call."),availableDisplayModes:c.array(wt).optional().describe("Display modes the app supports.")});c.object({method:c.literal("ui/notifications/initialized"),params:c.object({}).optional()});c.object({csp:lo.optional().describe("Content Security Policy configuration."),permissions:co.optional().describe("Sandbox permissions requested by the UI."),domain:c.string().optional().describe("Dedicated origin for view sandbox."),prefersBorder:c.boolean().optional().describe("Visual boundary preference - true if UI prefers a visible border.")});c.object({method:c.literal("ui/request-display-mode"),params:c.object({mode:wt.describe("The display mode being requested.")})});var zI=c.object({mode:wt.describe("The display mode that was actually set. May differ from requested if not supported.")}).passthrough(),ZI=c.union([c.literal("model"),c.literal("app")]).describe("Tool visibility scope - who can access the tool.");c.object({resourceUri:c.string().optional(),visibility:c.array(ZI).optional().describe(`Who can access this tool. Default: ["model", "app"]
765
765
  - "model": Tool visible to and callable by the agent
766
766
  - "app": Tool callable by the app from this server only`)});c.object({mimeTypes:c.array(c.string()).optional().describe('Array of supported MIME types for UI resources.\nMust include `"text/html;profile=mcp-app"` for MCP Apps support.')});c.object({method:c.literal("ui/message"),params:c.object({role:c.literal("user").describe('Message role, currently only "user" is supported.'),content:c.array(jt).describe("Message content blocks (text, image, etc.).")})});c.object({method:c.literal("ui/notifications/sandbox-resource-ready"),params:c.object({html:c.string().describe("HTML content to load into the inner iframe."),sandbox:c.string().optional().describe("Optional override for the inner iframe's sandbox attribute."),csp:lo.optional().describe("CSP configuration from resource metadata."),permissions:co.optional().describe("Sandbox permissions from resource metadata.")})});var TI=c.object({method:c.literal("ui/notifications/tool-result"),params:Rn.describe("Standard MCP tool execution result.")}),Df=c.object({toolInfo:c.object({id:Tt.optional().describe("JSON-RPC id of the tools/call request."),tool:fr.describe("Tool definition including name, inputSchema, etc.")}).optional().describe("Metadata of the tool call that instantiated this App."),theme:pI.optional().describe("Current color theme preference."),styles:II.optional().describe("Style configuration for theming the app."),displayMode:wt.optional().describe("How the UI is currently displayed."),availableDisplayModes:c.array(wt).optional().describe("Display modes the host supports."),containerDimensions:c.union([c.object({height:c.number().describe("Fixed container height in pixels.")}),c.object({maxHeight:c.union([c.number(),c.undefined()]).optional().describe("Maximum container height in pixels.")})]).and(c.union([c.object({width:c.number().describe("Fixed container width in pixels.")}),c.object({maxWidth:c.union([c.number(),c.undefined()]).optional().describe("Maximum container width in pixels.")})])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
767
- container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:c.string().optional().describe("User's language and region preference in BCP 47 format."),timeZone:c.string().optional().describe("User's timezone in IANA format."),userAgent:c.string().optional().describe("Host application identifier."),platform:c.union([c.literal("web"),c.literal("desktop"),c.literal("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:c.object({touch:c.boolean().optional().describe("Whether the device supports touch input."),hover:c.boolean().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:c.object({top:c.number().describe("Top safe area inset in pixels."),right:c.number().describe("Right safe area inset in pixels."),bottom:c.number().describe("Bottom safe area inset in pixels."),left:c.number().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),UI=c.object({method:c.literal("ui/notifications/host-context-changed"),params:Df.describe("Partial context update containing only changed fields.")});c.object({method:c.literal("ui/update-model-context"),params:c.object({content:c.array(jt).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:c.record(c.string(),c.unknown().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});c.object({method:c.literal("ui/initialize"),params:c.object({appInfo:jn.describe("App identification (name and version)."),appCapabilities:SI.describe("Features and capabilities this app provides."),protocolVersion:c.string().describe("Protocol version this app supports.")})});var EI=c.object({protocolVersion:c.string().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:jn.describe("Host application identification and version."),hostCapabilities:xI.describe("Features and capabilities provided by the host."),hostContext:Df.describe("Rich context about the host environment.")}).passthrough();class OI extends N_{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(t,i={},r={autoResize:!0}){super(r),this._appInfo=t,this._capabilities=i,this.options=r,this.setRequestHandler(Dn,n=>(console.log("Received ping:",n.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(t){this.setNotificationHandler(_I,i=>t(i.params))}set ontoolinputpartial(t){this.setNotificationHandler(bI,i=>t(i.params))}set ontoolresult(t){this.setNotificationHandler(TI,i=>t(i.params))}set ontoolcancelled(t){this.setNotificationHandler(yI,i=>t(i.params))}set onhostcontextchanged(t){this.setNotificationHandler(UI,i=>{this._hostContext={...this._hostContext,...i.params},t(i.params)})}set onteardown(t){this.setRequestHandler(wI,(i,r)=>t(i.params,r))}set oncalltool(t){this.setRequestHandler(Vs,(i,r)=>t(i.params,r))}set onlisttools(t){this.setRequestHandler(Bs,(i,r)=>t(i.params,r))}assertCapabilityForMethod(t){}assertRequestHandlerCapability(t){switch(t){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${t})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${t} registered`)}}assertNotificationCapability(t){}assertTaskCapability(t){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(t){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(t,i){return await this.request({method:"tools/call",params:t},Rn,i)}sendMessage(t,i){return this.request({method:"ui/message",params:t},$I,i)}sendLog(t){return this.notification({method:"notifications/message",params:t})}updateModelContext(t,i){return this.request({method:"ui/update-model-context",params:t},Yi,i)}openLink(t,i){return this.request({method:"ui/open-link",params:t},gI,i)}sendOpenLink=this.openLink;requestDisplayMode(t,i){return this.request({method:"ui/request-display-mode",params:t},zI,i)}sendSizeChanged(t){return this.notification({method:"ui/notifications/size-changed",params:t})}setupSizeChangedNotifications(){let t=!1,i=0,r=0,n=()=>{t||(t=!0,requestAnimationFrame(()=>{t=!1;let o=document.documentElement,s=o.style.width,u=o.style.height;o.style.width="fit-content",o.style.height="fit-content";let l=o.getBoundingClientRect();o.style.width=s,o.style.height=u;let d=window.innerWidth-o.clientWidth,f=Math.ceil(l.width+d),p=Math.ceil(l.height);(f!==i||p!==r)&&(i=f,r=p,this.sendSizeChanged({width:f,height:p}))}))};n();let a=new ResizeObserver(n);return a.observe(document.documentElement),a.observe(document.body),()=>a.disconnect()}async connect(t=new j_(window.parent,window.parent),i){await super.connect(t);try{let r=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:D_}},EI,i);if(r===void 0)throw Error(`Server sent invalid initialize result: ${r}`);this._hostCapabilities=r.hostCapabilities,this._hostInfo=r.hostInfo,this._hostContext=r.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(r){throw this.close(),r}}}const Re=new OI({name:"Footprint Dashboard",version:"0.3.0"});let hn=null,oe=new Set,pt="AND",ze=[],vt=null,Ye=null,xt=!1,me=new Set,se="";function NI(e){const t=["B","KB","MB","GB"];let i=e,r=0;for(;i>=1024&&r<t.length-1;)i/=1024,r++;return`${i.toFixed(1)}${t[r]}`}function PI(e){try{return new Date(e).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return e}}function Rf(e){const t=new Set;return e.forEach(i=>{i.tags?.forEach(r=>t.add(r))}),Array.from(t).sort()}function Cf(e){let t=0;for(let r=0;r<e.length;r++)t=e.charCodeAt(r)+((t<<5)-t);const i=["#3b82f6","#ef4444","#10b981","#f59e0b","#8b5cf6","#06b6d4","#f97316","#84cc16","#ec4899","#6366f1"];return i[Math.abs(t)%i.length]}function mo(e,t={}){const{isActive:i=!1,isClickable:r=!0,showClose:n=!1,color:a}=t,o=a||Cf(e),s=`tag-chip ${i?"active":""} ${r?"clickable":""}`,u=i?"":`border-color: ${o}20; background: ${o}10; color: ${o}`,l=n?`<span class="tag-close" data-tag="${e}">&times;</span>`:"";return`<span class="${s}" data-tag="${e}" style="${u}">${e}${l}</span>`}function Af(e){let t=e;if(se.trim()){const i=se.toLowerCase().trim();t=t.filter(r=>[r.id,r.conversationId,r.llmProvider,...r.tags||[]].join(" ").toLowerCase().includes(i))}return oe.size>0&&(t=t.filter(i=>{const r=i.tags||[],n=Array.from(oe);return pt==="AND"?n.every(a=>r.includes(a)):n.some(a=>r.includes(a))})),t}function Oi(e,t){if(!t.trim())return e;const i=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`(${i})`,"gi");return e.replace(r,'<span class="highlight">$1</span>')}function jI(e,t){const i=document.getElementById("search-results-info");i&&(se.trim()?t===0?i.textContent=`No results found for "${se}"`:t<e?i.textContent=`Showing ${t} of ${e} evidence (filtered by search)`:i.textContent=`${t} results`:i.textContent="")}function DI(){const e=document.getElementById("tag-filter-chips"),t=document.getElementById("clear-filters-btn");if(!e||!t)return;const i=Rf(ze);e.innerHTML=i.map(r=>mo(r,{isActive:oe.has(r),showClose:oe.has(r)})).join(""),t.style.display=oe.size>0?"block":"none",e.addEventListener("click",r=>{const n=r.target;if(n.classList.contains("tag-close")){const a=n.getAttribute("data-tag");a&&(oe.delete(a),xe())}else if(n.classList.contains("tag-chip")){const a=n.getAttribute("data-tag");a&&Lf(a)}})}function Lf(e){oe.has(e)?oe.delete(e):oe.add(e),xe()}function xe(){if(!ze.length)return;const e=Af(ze);po(e),vo(e),Mf({evidences:e}),DI()}function RI(){const e=document.getElementById("tag-modal"),t=document.getElementById("tag-list");!e||!t||(e.classList.add("show"),fo())}function rs(){const e=document.getElementById("tag-modal");e&&e.classList.remove("show")}function fo(){const e=document.getElementById("tag-list");if(!e)return;const t=Rf(ze);if(t.length===0){e.innerHTML='<div class="no-tags">No tags found</div>';return}const i=new Map;ze.forEach(r=>{r.tags?.forEach(n=>{i.set(n,(i.get(n)||0)+1)})}),e.innerHTML=t.map(r=>{const n=i.get(r)||0,a=Cf(r);return`
767
+ container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:c.string().optional().describe("User's language and region preference in BCP 47 format."),timeZone:c.string().optional().describe("User's timezone in IANA format."),userAgent:c.string().optional().describe("Host application identifier."),platform:c.union([c.literal("web"),c.literal("desktop"),c.literal("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:c.object({touch:c.boolean().optional().describe("Whether the device supports touch input."),hover:c.boolean().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:c.object({top:c.number().describe("Top safe area inset in pixels."),right:c.number().describe("Right safe area inset in pixels."),bottom:c.number().describe("Bottom safe area inset in pixels."),left:c.number().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),UI=c.object({method:c.literal("ui/notifications/host-context-changed"),params:Df.describe("Partial context update containing only changed fields.")});c.object({method:c.literal("ui/update-model-context"),params:c.object({content:c.array(jt).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:c.record(c.string(),c.unknown().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});c.object({method:c.literal("ui/initialize"),params:c.object({appInfo:jn.describe("App identification (name and version)."),appCapabilities:SI.describe("Features and capabilities this app provides."),protocolVersion:c.string().describe("Protocol version this app supports.")})});var EI=c.object({protocolVersion:c.string().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:jn.describe("Host application identification and version."),hostCapabilities:xI.describe("Features and capabilities provided by the host."),hostContext:Df.describe("Rich context about the host environment.")}).passthrough();class OI extends N_{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(t,i={},r={autoResize:!0}){super(r),this._appInfo=t,this._capabilities=i,this.options=r,this.setRequestHandler(Dn,n=>(console.log("Received ping:",n.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(t){this.setNotificationHandler(_I,i=>t(i.params))}set ontoolinputpartial(t){this.setNotificationHandler(bI,i=>t(i.params))}set ontoolresult(t){this.setNotificationHandler(TI,i=>t(i.params))}set ontoolcancelled(t){this.setNotificationHandler(yI,i=>t(i.params))}set onhostcontextchanged(t){this.setNotificationHandler(UI,i=>{this._hostContext={...this._hostContext,...i.params},t(i.params)})}set onteardown(t){this.setRequestHandler(wI,(i,r)=>t(i.params,r))}set oncalltool(t){this.setRequestHandler(Vs,(i,r)=>t(i.params,r))}set onlisttools(t){this.setRequestHandler(Bs,(i,r)=>t(i.params,r))}assertCapabilityForMethod(t){}assertRequestHandlerCapability(t){switch(t){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${t})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${t} registered`)}}assertNotificationCapability(t){}assertTaskCapability(t){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(t){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(t,i){return await this.request({method:"tools/call",params:t},Rn,i)}sendMessage(t,i){return this.request({method:"ui/message",params:t},$I,i)}sendLog(t){return this.notification({method:"notifications/message",params:t})}updateModelContext(t,i){return this.request({method:"ui/update-model-context",params:t},Yi,i)}openLink(t,i){return this.request({method:"ui/open-link",params:t},gI,i)}sendOpenLink=this.openLink;requestDisplayMode(t,i){return this.request({method:"ui/request-display-mode",params:t},zI,i)}sendSizeChanged(t){return this.notification({method:"ui/notifications/size-changed",params:t})}setupSizeChangedNotifications(){let t=!1,i=0,r=0,n=()=>{t||(t=!0,requestAnimationFrame(()=>{t=!1;let o=document.documentElement,s=o.style.width,u=o.style.height;o.style.width="fit-content",o.style.height="fit-content";let l=o.getBoundingClientRect();o.style.width=s,o.style.height=u;let d=window.innerWidth-o.clientWidth,f=Math.ceil(l.width+d),p=Math.ceil(l.height);(f!==i||p!==r)&&(i=f,r=p,this.sendSizeChanged({width:f,height:p}))}))};n();let a=new ResizeObserver(n);return a.observe(document.documentElement),a.observe(document.body),()=>a.disconnect()}async connect(t=new j_(window.parent,window.parent),i){await super.connect(t);try{let r=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:D_}},EI,i);if(r===void 0)throw Error(`Server sent invalid initialize result: ${r}`);this._hostCapabilities=r.hostCapabilities,this._hostInfo=r.hostInfo,this._hostContext=r.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(r){throw this.close(),r}}}const Re=new OI({name:"Footprint Dashboard",version:"1.1.1"});let hn=null,oe=new Set,pt="AND",ze=[],vt=null,Ye=null,xt=!1,me=new Set,se="";function NI(e){const t=["B","KB","MB","GB"];let i=e,r=0;for(;i>=1024&&r<t.length-1;)i/=1024,r++;return`${i.toFixed(1)}${t[r]}`}function PI(e){try{return new Date(e).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return e}}function Rf(e){const t=new Set;return e.forEach(i=>{i.tags?.forEach(r=>t.add(r))}),Array.from(t).sort()}function Cf(e){let t=0;for(let r=0;r<e.length;r++)t=e.charCodeAt(r)+((t<<5)-t);const i=["#3b82f6","#ef4444","#10b981","#f59e0b","#8b5cf6","#06b6d4","#f97316","#84cc16","#ec4899","#6366f1"];return i[Math.abs(t)%i.length]}function mo(e,t={}){const{isActive:i=!1,isClickable:r=!0,showClose:n=!1,color:a}=t,o=a||Cf(e),s=`tag-chip ${i?"active":""} ${r?"clickable":""}`,u=i?"":`border-color: ${o}20; background: ${o}10; color: ${o}`,l=n?`<span class="tag-close" data-tag="${e}">&times;</span>`:"";return`<span class="${s}" data-tag="${e}" style="${u}">${e}${l}</span>`}function Af(e){let t=e;if(se.trim()){const i=se.toLowerCase().trim();t=t.filter(r=>[r.id,r.conversationId,r.llmProvider,...r.tags||[]].join(" ").toLowerCase().includes(i))}return oe.size>0&&(t=t.filter(i=>{const r=i.tags||[],n=Array.from(oe);return pt==="AND"?n.every(a=>r.includes(a)):n.some(a=>r.includes(a))})),t}function Oi(e,t){if(!t.trim())return e;const i=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`(${i})`,"gi");return e.replace(r,'<span class="highlight">$1</span>')}function jI(e,t){const i=document.getElementById("search-results-info");i&&(se.trim()?t===0?i.textContent=`No results found for "${se}"`:t<e?i.textContent=`Showing ${t} of ${e} evidence (filtered by search)`:i.textContent=`${t} results`:i.textContent="")}function DI(){const e=document.getElementById("tag-filter-chips"),t=document.getElementById("clear-filters-btn");if(!e||!t)return;const i=Rf(ze);e.innerHTML=i.map(r=>mo(r,{isActive:oe.has(r),showClose:oe.has(r)})).join(""),t.style.display=oe.size>0?"block":"none",e.addEventListener("click",r=>{const n=r.target;if(n.classList.contains("tag-close")){const a=n.getAttribute("data-tag");a&&(oe.delete(a),xe())}else if(n.classList.contains("tag-chip")){const a=n.getAttribute("data-tag");a&&Lf(a)}})}function Lf(e){oe.has(e)?oe.delete(e):oe.add(e),xe()}function xe(){if(!ze.length)return;const e=Af(ze);po(e),vo(e),Mf({evidences:e}),DI()}function RI(){const e=document.getElementById("tag-modal"),t=document.getElementById("tag-list");!e||!t||(e.classList.add("show"),fo())}function rs(){const e=document.getElementById("tag-modal");e&&e.classList.remove("show")}function fo(){const e=document.getElementById("tag-list");if(!e)return;const t=Rf(ze);if(t.length===0){e.innerHTML='<div class="no-tags">No tags found</div>';return}const i=new Map;ze.forEach(r=>{r.tags?.forEach(n=>{i.set(n,(i.get(n)||0)+1)})}),e.innerHTML=t.map(r=>{const n=i.get(r)||0,a=Cf(r);return`
768
768
  <div class="tag-item">
769
769
  <div class="tag-item-info">
770
770
  ${mo(r,{isClickable:!1,color:a})}
@@ -257,7 +257,7 @@ Note: This type uses \`Record<K, string | undefined>\` rather than \`Partial<Rec
257
257
  for compatibility with Zod schema generation. Both are functionally equivalent for validation.`);c.object({method:c.literal("ui/open-link"),params:c.object({url:c.string().describe("URL to open in the host's browser")})});var Gk=c.object({isError:c.boolean().optional().describe("True if the host failed to open the URL (e.g., due to security policy).")}).passthrough(),Kk=c.object({isError:c.boolean().optional().describe("True if the host rejected or failed to deliver the message.")}).passthrough();c.object({method:c.literal("ui/notifications/sandbox-proxy-ready"),params:c.object({})});var Ya=c.object({connectDomains:c.array(c.string()).optional().describe("Origins for network requests (fetch/XHR/WebSocket)."),resourceDomains:c.array(c.string()).optional().describe("Origins for static resources (scripts, images, styles, fonts)."),frameDomains:c.array(c.string()).optional().describe("Origins for nested iframes (frame-src directive)."),baseUriDomains:c.array(c.string()).optional().describe("Allowed base URIs for the document (base-uri directive).")}),Qa=c.object({camera:c.object({}).optional().describe("Request camera access (Permission Policy `camera` feature)."),microphone:c.object({}).optional().describe("Request microphone access (Permission Policy `microphone` feature)."),geolocation:c.object({}).optional().describe("Request geolocation access (Permission Policy `geolocation` feature)."),clipboardWrite:c.object({}).optional().describe("Request clipboard write access (Permission Policy `clipboard-write` feature).")});c.object({method:c.literal("ui/notifications/size-changed"),params:c.object({width:c.number().optional().describe("New width in pixels."),height:c.number().optional().describe("New height in pixels.")})});var Xk=c.object({method:c.literal("ui/notifications/tool-input"),params:c.object({arguments:c.record(c.string(),c.unknown().describe("Complete tool call arguments as key-value pairs.")).optional().describe("Complete tool call arguments as key-value pairs.")})}),Yk=c.object({method:c.literal("ui/notifications/tool-input-partial"),params:c.object({arguments:c.record(c.string(),c.unknown().describe("Partial tool call arguments (incomplete, may change).")).optional().describe("Partial tool call arguments (incomplete, may change).")})}),Qk=c.object({method:c.literal("ui/notifications/tool-cancelled"),params:c.object({reason:c.string().optional().describe('Optional reason for the cancellation (e.g., "user action", "timeout").')})}),eI=c.object({fonts:c.string().optional()}),tI=c.object({variables:Bk.optional().describe("CSS variables for theming the app."),css:eI.optional().describe("CSS blocks that apps can inject.")}),iI=c.object({method:c.literal("ui/resource-teardown"),params:c.object({})});c.record(c.string(),c.unknown());var Fo=c.object({text:c.object({}).optional().describe("Host supports text content blocks."),image:c.object({}).optional().describe("Host supports image content blocks."),audio:c.object({}).optional().describe("Host supports audio content blocks."),resource:c.object({}).optional().describe("Host supports resource content blocks."),resourceLink:c.object({}).optional().describe("Host supports resource link content blocks."),structuredContent:c.object({}).optional().describe("Host supports structured content.")}),nI=c.object({experimental:c.object({}).optional().describe("Experimental features (structure TBD)."),openLinks:c.object({}).optional().describe("Host supports opening external URLs."),serverTools:c.object({listChanged:c.boolean().optional().describe("Host supports tools/list_changed notifications.")}).optional().describe("Host can proxy tool calls to the MCP server."),serverResources:c.object({listChanged:c.boolean().optional().describe("Host supports resources/list_changed notifications.")}).optional().describe("Host can proxy resource reads to the MCP server."),logging:c.object({}).optional().describe("Host accepts log messages."),sandbox:c.object({permissions:Qa.optional().describe("Permissions granted by the host (camera, microphone, geolocation)."),csp:Ya.optional().describe("CSP domains approved by the host.")}).optional().describe("Sandbox configuration applied by the host."),updateModelContext:Fo.optional().describe("Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns."),message:Fo.optional().describe("Host supports receiving content messages (ui/message) from the view.")}),rI=c.object({experimental:c.object({}).optional().describe("Experimental features (structure TBD)."),tools:c.object({listChanged:c.boolean().optional().describe("App supports tools/list_changed notifications.")}).optional().describe("App exposes MCP-style tools that the host can call."),availableDisplayModes:c.array(gt).optional().describe("Display modes the app supports.")});c.object({method:c.literal("ui/notifications/initialized"),params:c.object({}).optional()});c.object({csp:Ya.optional().describe("Content Security Policy configuration."),permissions:Qa.optional().describe("Sandbox permissions requested by the UI."),domain:c.string().optional().describe("Dedicated origin for view sandbox."),prefersBorder:c.boolean().optional().describe("Visual boundary preference - true if UI prefers a visible border.")});c.object({method:c.literal("ui/request-display-mode"),params:c.object({mode:gt.describe("The display mode being requested.")})});var aI=c.object({mode:gt.describe("The display mode that was actually set. May differ from requested if not supported.")}).passthrough(),oI=c.union([c.literal("model"),c.literal("app")]).describe("Tool visibility scope - who can access the tool.");c.object({resourceUri:c.string().optional(),visibility:c.array(oI).optional().describe(`Who can access this tool. Default: ["model", "app"]
258
258
  - "model": Tool visible to and callable by the agent
259
259
  - "app": Tool callable by the app from this server only`)});c.object({mimeTypes:c.array(c.string()).optional().describe('Array of supported MIME types for UI resources.\nMust include `"text/html;profile=mcp-app"` for MCP Apps support.')});c.object({method:c.literal("ui/message"),params:c.object({role:c.literal("user").describe('Message role, currently only "user" is supported.'),content:c.array(zt).describe("Message content blocks (text, image, etc.).")})});c.object({method:c.literal("ui/notifications/sandbox-resource-ready"),params:c.object({html:c.string().describe("HTML content to load into the inner iframe."),sandbox:c.string().optional().describe("Optional override for the inner iframe's sandbox attribute."),csp:Ya.optional().describe("CSP configuration from resource metadata."),permissions:Qa.optional().describe("Sandbox permissions from resource metadata.")})});var sI=c.object({method:c.literal("ui/notifications/tool-result"),params:zi.describe("Standard MCP tool execution result.")}),yf=c.object({toolInfo:c.object({id:yt.optional().describe("JSON-RPC id of the tools/call request."),tool:ir.describe("Tool definition including name, inputSchema, etc.")}).optional().describe("Metadata of the tool call that instantiated this App."),theme:Wk.optional().describe("Current color theme preference."),styles:tI.optional().describe("Style configuration for theming the app."),displayMode:gt.optional().describe("How the UI is currently displayed."),availableDisplayModes:c.array(gt).optional().describe("Display modes the host supports."),containerDimensions:c.union([c.object({height:c.number().describe("Fixed container height in pixels.")}),c.object({maxHeight:c.union([c.number(),c.undefined()]).optional().describe("Maximum container height in pixels.")})]).and(c.union([c.object({width:c.number().describe("Fixed container width in pixels.")}),c.object({maxWidth:c.union([c.number(),c.undefined()]).optional().describe("Maximum container width in pixels.")})])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
260
- container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:c.string().optional().describe("User's language and region preference in BCP 47 format."),timeZone:c.string().optional().describe("User's timezone in IANA format."),userAgent:c.string().optional().describe("Host application identifier."),platform:c.union([c.literal("web"),c.literal("desktop"),c.literal("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:c.object({touch:c.boolean().optional().describe("Whether the device supports touch input."),hover:c.boolean().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:c.object({top:c.number().describe("Top safe area inset in pixels."),right:c.number().describe("Right safe area inset in pixels."),bottom:c.number().describe("Bottom safe area inset in pixels."),left:c.number().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),uI=c.object({method:c.literal("ui/notifications/host-context-changed"),params:yf.describe("Partial context update containing only changed fields.")});c.object({method:c.literal("ui/update-model-context"),params:c.object({content:c.array(zt).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:c.record(c.string(),c.unknown().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});c.object({method:c.literal("ui/initialize"),params:c.object({appInfo:Si.describe("App identification (name and version)."),appCapabilities:rI.describe("Features and capabilities this app provides."),protocolVersion:c.string().describe("Protocol version this app supports.")})});var lI=c.object({protocolVersion:c.string().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:Si.describe("Host application identification and version."),hostCapabilities:nI.describe("Features and capabilities provided by the host."),hostContext:yf.describe("Rich context about the host environment.")}).passthrough();class cI extends d${_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(t,n={},a={autoResize:!0}){super(a),this._appInfo=t,this._capabilities=n,this.options=a,this.setRequestHandler(xi,i=>(console.log("Received ping:",i.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(t){this.setNotificationHandler(Xk,n=>t(n.params))}set ontoolinputpartial(t){this.setNotificationHandler(Yk,n=>t(n.params))}set ontoolresult(t){this.setNotificationHandler(sI,n=>t(n.params))}set ontoolcancelled(t){this.setNotificationHandler(Qk,n=>t(n.params))}set onhostcontextchanged(t){this.setNotificationHandler(uI,n=>{this._hostContext={...this._hostContext,...n.params},t(n.params)})}set onteardown(t){this.setRequestHandler(iI,(n,a)=>t(n.params,a))}set oncalltool(t){this.setRequestHandler(Ts,(n,a)=>t(n.params,a))}set onlisttools(t){this.setRequestHandler(Os,(n,a)=>t(n.params,a))}assertCapabilityForMethod(t){}assertRequestHandlerCapability(t){switch(t){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${t})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${t} registered`)}}assertNotificationCapability(t){}assertTaskCapability(t){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(t){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(t,n){return await this.request({method:"tools/call",params:t},zi,n)}sendMessage(t,n){return this.request({method:"ui/message",params:t},Kk,n)}sendLog(t){return this.notification({method:"notifications/message",params:t})}updateModelContext(t,n){return this.request({method:"ui/update-model-context",params:t},Mn,n)}openLink(t,n){return this.request({method:"ui/open-link",params:t},Gk,n)}sendOpenLink=this.openLink;requestDisplayMode(t,n){return this.request({method:"ui/request-display-mode",params:t},aI,n)}sendSizeChanged(t){return this.notification({method:"ui/notifications/size-changed",params:t})}setupSizeChangedNotifications(){let t=!1,n=0,a=0,i=()=>{t||(t=!0,requestAnimationFrame(()=>{t=!1;let o=document.documentElement,s=o.style.width,u=o.style.height;o.style.width="fit-content",o.style.height="fit-content";let l=o.getBoundingClientRect();o.style.width=s,o.style.height=u;let d=window.innerWidth-o.clientWidth,f=Math.ceil(l.width+d),p=Math.ceil(l.height);(f!==n||p!==a)&&(n=f,a=p,this.sendSizeChanged({width:f,height:p}))}))};i();let r=new ResizeObserver(i);return r.observe(document.documentElement),r.observe(document.body),()=>r.disconnect()}async connect(t=new f$(window.parent,window.parent),n){await super.connect(t);try{let a=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:p$}},lI,n);if(a===void 0)throw Error(`Server sent invalid initialize result: ${a}`);this._hostCapabilities=a.hostCapabilities,this._hostInfo=a.hostInfo,this._hostContext=a.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(a){throw this.close(),a}}}const Pe=new cI({name:"Footprint Detail View",version:"0.3.0"});let be=null;function we(e){const t=document.getElementById("error-container");t&&(t.innerHTML=`
260
+ container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:c.string().optional().describe("User's language and region preference in BCP 47 format."),timeZone:c.string().optional().describe("User's timezone in IANA format."),userAgent:c.string().optional().describe("Host application identifier."),platform:c.union([c.literal("web"),c.literal("desktop"),c.literal("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:c.object({touch:c.boolean().optional().describe("Whether the device supports touch input."),hover:c.boolean().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:c.object({top:c.number().describe("Top safe area inset in pixels."),right:c.number().describe("Right safe area inset in pixels."),bottom:c.number().describe("Bottom safe area inset in pixels."),left:c.number().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),uI=c.object({method:c.literal("ui/notifications/host-context-changed"),params:yf.describe("Partial context update containing only changed fields.")});c.object({method:c.literal("ui/update-model-context"),params:c.object({content:c.array(zt).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:c.record(c.string(),c.unknown().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});c.object({method:c.literal("ui/initialize"),params:c.object({appInfo:Si.describe("App identification (name and version)."),appCapabilities:rI.describe("Features and capabilities this app provides."),protocolVersion:c.string().describe("Protocol version this app supports.")})});var lI=c.object({protocolVersion:c.string().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:Si.describe("Host application identification and version."),hostCapabilities:nI.describe("Features and capabilities provided by the host."),hostContext:yf.describe("Rich context about the host environment.")}).passthrough();class cI extends d${_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(t,n={},a={autoResize:!0}){super(a),this._appInfo=t,this._capabilities=n,this.options=a,this.setRequestHandler(xi,i=>(console.log("Received ping:",i.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(t){this.setNotificationHandler(Xk,n=>t(n.params))}set ontoolinputpartial(t){this.setNotificationHandler(Yk,n=>t(n.params))}set ontoolresult(t){this.setNotificationHandler(sI,n=>t(n.params))}set ontoolcancelled(t){this.setNotificationHandler(Qk,n=>t(n.params))}set onhostcontextchanged(t){this.setNotificationHandler(uI,n=>{this._hostContext={...this._hostContext,...n.params},t(n.params)})}set onteardown(t){this.setRequestHandler(iI,(n,a)=>t(n.params,a))}set oncalltool(t){this.setRequestHandler(Ts,(n,a)=>t(n.params,a))}set onlisttools(t){this.setRequestHandler(Os,(n,a)=>t(n.params,a))}assertCapabilityForMethod(t){}assertRequestHandlerCapability(t){switch(t){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${t})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${t} registered`)}}assertNotificationCapability(t){}assertTaskCapability(t){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(t){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(t,n){return await this.request({method:"tools/call",params:t},zi,n)}sendMessage(t,n){return this.request({method:"ui/message",params:t},Kk,n)}sendLog(t){return this.notification({method:"notifications/message",params:t})}updateModelContext(t,n){return this.request({method:"ui/update-model-context",params:t},Mn,n)}openLink(t,n){return this.request({method:"ui/open-link",params:t},Gk,n)}sendOpenLink=this.openLink;requestDisplayMode(t,n){return this.request({method:"ui/request-display-mode",params:t},aI,n)}sendSizeChanged(t){return this.notification({method:"ui/notifications/size-changed",params:t})}setupSizeChangedNotifications(){let t=!1,n=0,a=0,i=()=>{t||(t=!0,requestAnimationFrame(()=>{t=!1;let o=document.documentElement,s=o.style.width,u=o.style.height;o.style.width="fit-content",o.style.height="fit-content";let l=o.getBoundingClientRect();o.style.width=s,o.style.height=u;let d=window.innerWidth-o.clientWidth,f=Math.ceil(l.width+d),p=Math.ceil(l.height);(f!==n||p!==a)&&(n=f,a=p,this.sendSizeChanged({width:f,height:p}))}))};i();let r=new ResizeObserver(i);return r.observe(document.documentElement),r.observe(document.body),()=>r.disconnect()}async connect(t=new f$(window.parent,window.parent),n){await super.connect(t);try{let a=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:p$}},lI,n);if(a===void 0)throw Error(`Server sent invalid initialize result: ${a}`);this._hostCapabilities=a.hostCapabilities,this._hostInfo=a.hostInfo,this._hostContext=a.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(a){throw this.close(),a}}}const Pe=new cI({name:"Footprint Detail View",version:"1.1.1"});let be=null;function we(e){const t=document.getElementById("error-container");t&&(t.innerHTML=`
261
261
  <div class="error">
262
262
  ❌ Error: ${e}
263
263
  </div>
@@ -298,7 +298,7 @@ Note: This type uses \`Record<K, string | undefined>\` rather than \`Partial<Rec
298
298
  for compatibility with Zod schema generation. Both are functionally equivalent for validation.`);c.object({method:c.literal("ui/open-link"),params:c.object({url:c.string().describe("URL to open in the host's browser")})});var eI=c.object({isError:c.boolean().optional().describe("True if the host failed to open the URL (e.g., due to security policy).")}).passthrough(),tI=c.object({isError:c.boolean().optional().describe("True if the host rejected or failed to deliver the message.")}).passthrough();c.object({method:c.literal("ui/notifications/sandbox-proxy-ready"),params:c.object({})});var Qa=c.object({connectDomains:c.array(c.string()).optional().describe("Origins for network requests (fetch/XHR/WebSocket)."),resourceDomains:c.array(c.string()).optional().describe("Origins for static resources (scripts, images, styles, fonts)."),frameDomains:c.array(c.string()).optional().describe("Origins for nested iframes (frame-src directive)."),baseUriDomains:c.array(c.string()).optional().describe("Allowed base URIs for the document (base-uri directive).")}),eo=c.object({camera:c.object({}).optional().describe("Request camera access (Permission Policy `camera` feature)."),microphone:c.object({}).optional().describe("Request microphone access (Permission Policy `microphone` feature)."),geolocation:c.object({}).optional().describe("Request geolocation access (Permission Policy `geolocation` feature)."),clipboardWrite:c.object({}).optional().describe("Request clipboard write access (Permission Policy `clipboard-write` feature).")});c.object({method:c.literal("ui/notifications/size-changed"),params:c.object({width:c.number().optional().describe("New width in pixels."),height:c.number().optional().describe("New height in pixels.")})});var iI=c.object({method:c.literal("ui/notifications/tool-input"),params:c.object({arguments:c.record(c.string(),c.unknown().describe("Complete tool call arguments as key-value pairs.")).optional().describe("Complete tool call arguments as key-value pairs.")})}),nI=c.object({method:c.literal("ui/notifications/tool-input-partial"),params:c.object({arguments:c.record(c.string(),c.unknown().describe("Partial tool call arguments (incomplete, may change).")).optional().describe("Partial tool call arguments (incomplete, may change).")})}),rI=c.object({method:c.literal("ui/notifications/tool-cancelled"),params:c.object({reason:c.string().optional().describe('Optional reason for the cancellation (e.g., "user action", "timeout").')})}),aI=c.object({fonts:c.string().optional()}),oI=c.object({variables:Qk.optional().describe("CSS variables for theming the app."),css:aI.optional().describe("CSS blocks that apps can inject.")}),sI=c.object({method:c.literal("ui/resource-teardown"),params:c.object({})});c.record(c.string(),c.unknown());var Fo=c.object({text:c.object({}).optional().describe("Host supports text content blocks."),image:c.object({}).optional().describe("Host supports image content blocks."),audio:c.object({}).optional().describe("Host supports audio content blocks."),resource:c.object({}).optional().describe("Host supports resource content blocks."),resourceLink:c.object({}).optional().describe("Host supports resource link content blocks."),structuredContent:c.object({}).optional().describe("Host supports structured content.")}),uI=c.object({experimental:c.object({}).optional().describe("Experimental features (structure TBD)."),openLinks:c.object({}).optional().describe("Host supports opening external URLs."),serverTools:c.object({listChanged:c.boolean().optional().describe("Host supports tools/list_changed notifications.")}).optional().describe("Host can proxy tool calls to the MCP server."),serverResources:c.object({listChanged:c.boolean().optional().describe("Host supports resources/list_changed notifications.")}).optional().describe("Host can proxy resource reads to the MCP server."),logging:c.object({}).optional().describe("Host accepts log messages."),sandbox:c.object({permissions:eo.optional().describe("Permissions granted by the host (camera, microphone, geolocation)."),csp:Qa.optional().describe("CSP domains approved by the host.")}).optional().describe("Sandbox configuration applied by the host."),updateModelContext:Fo.optional().describe("Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns."),message:Fo.optional().describe("Host supports receiving content messages (ui/message) from the view.")}),lI=c.object({experimental:c.object({}).optional().describe("Experimental features (structure TBD)."),tools:c.object({listChanged:c.boolean().optional().describe("App supports tools/list_changed notifications.")}).optional().describe("App exposes MCP-style tools that the host can call."),availableDisplayModes:c.array(gt).optional().describe("Display modes the app supports.")});c.object({method:c.literal("ui/notifications/initialized"),params:c.object({}).optional()});c.object({csp:Qa.optional().describe("Content Security Policy configuration."),permissions:eo.optional().describe("Sandbox permissions requested by the UI."),domain:c.string().optional().describe("Dedicated origin for view sandbox."),prefersBorder:c.boolean().optional().describe("Visual boundary preference - true if UI prefers a visible border.")});c.object({method:c.literal("ui/request-display-mode"),params:c.object({mode:gt.describe("The display mode being requested.")})});var cI=c.object({mode:gt.describe("The display mode that was actually set. May differ from requested if not supported.")}).passthrough(),dI=c.union([c.literal("model"),c.literal("app")]).describe("Tool visibility scope - who can access the tool.");c.object({resourceUri:c.string().optional(),visibility:c.array(dI).optional().describe(`Who can access this tool. Default: ["model", "app"]
299
299
  - "model": Tool visible to and callable by the agent
300
300
  - "app": Tool callable by the app from this server only`)});c.object({mimeTypes:c.array(c.string()).optional().describe('Array of supported MIME types for UI resources.\nMust include `"text/html;profile=mcp-app"` for MCP Apps support.')});c.object({method:c.literal("ui/message"),params:c.object({role:c.literal("user").describe('Message role, currently only "user" is supported.'),content:c.array(Zt).describe("Message content blocks (text, image, etc.).")})});c.object({method:c.literal("ui/notifications/sandbox-resource-ready"),params:c.object({html:c.string().describe("HTML content to load into the inner iframe."),sandbox:c.string().optional().describe("Optional override for the inner iframe's sandbox attribute."),csp:Qa.optional().describe("CSP configuration from resource metadata."),permissions:eo.optional().describe("Sandbox permissions from resource metadata.")})});var mI=c.object({method:c.literal("ui/notifications/tool-result"),params:Zi.describe("Standard MCP tool execution result.")}),bf=c.object({toolInfo:c.object({id:kt.optional().describe("JSON-RPC id of the tools/call request."),tool:nr.describe("Tool definition including name, inputSchema, etc.")}).optional().describe("Metadata of the tool call that instantiated this App."),theme:Xk.optional().describe("Current color theme preference."),styles:oI.optional().describe("Style configuration for theming the app."),displayMode:gt.optional().describe("How the UI is currently displayed."),availableDisplayModes:c.array(gt).optional().describe("Display modes the host supports."),containerDimensions:c.union([c.object({height:c.number().describe("Fixed container height in pixels.")}),c.object({maxHeight:c.union([c.number(),c.undefined()]).optional().describe("Maximum container height in pixels.")})]).and(c.union([c.object({width:c.number().describe("Fixed container width in pixels.")}),c.object({maxWidth:c.union([c.number(),c.undefined()]).optional().describe("Maximum container width in pixels.")})])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
301
- container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:c.string().optional().describe("User's language and region preference in BCP 47 format."),timeZone:c.string().optional().describe("User's timezone in IANA format."),userAgent:c.string().optional().describe("Host application identifier."),platform:c.union([c.literal("web"),c.literal("desktop"),c.literal("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:c.object({touch:c.boolean().optional().describe("Whether the device supports touch input."),hover:c.boolean().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:c.object({top:c.number().describe("Top safe area inset in pixels."),right:c.number().describe("Right safe area inset in pixels."),bottom:c.number().describe("Bottom safe area inset in pixels."),left:c.number().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),fI=c.object({method:c.literal("ui/notifications/host-context-changed"),params:bf.describe("Partial context update containing only changed fields.")});c.object({method:c.literal("ui/update-model-context"),params:c.object({content:c.array(Zt).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:c.record(c.string(),c.unknown().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});c.object({method:c.literal("ui/initialize"),params:c.object({appInfo:xi.describe("App identification (name and version)."),appCapabilities:lI.describe("Features and capabilities this app provides."),protocolVersion:c.string().describe("Protocol version this app supports.")})});var pI=c.object({protocolVersion:c.string().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:xi.describe("Host application identification and version."),hostCapabilities:uI.describe("Features and capabilities provided by the host."),hostContext:bf.describe("Rich context about the host environment.")}).passthrough();class vI extends h_{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(t,n={},r={autoResize:!0}){super(r),this._appInfo=t,this._capabilities=n,this.options=r,this.setRequestHandler(zi,i=>(console.log("Received ping:",i.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(t){this.setNotificationHandler(iI,n=>t(n.params))}set ontoolinputpartial(t){this.setNotificationHandler(nI,n=>t(n.params))}set ontoolresult(t){this.setNotificationHandler(mI,n=>t(n.params))}set ontoolcancelled(t){this.setNotificationHandler(rI,n=>t(n.params))}set onhostcontextchanged(t){this.setNotificationHandler(fI,n=>{this._hostContext={...this._hostContext,...n.params},t(n.params)})}set onteardown(t){this.setRequestHandler(sI,(n,r)=>t(n.params,r))}set oncalltool(t){this.setRequestHandler(Os,(n,r)=>t(n.params,r))}set onlisttools(t){this.setRequestHandler(Us,(n,r)=>t(n.params,r))}assertCapabilityForMethod(t){}assertRequestHandlerCapability(t){switch(t){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${t})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${t} registered`)}}assertNotificationCapability(t){}assertTaskCapability(t){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(t){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(t,n){return await this.request({method:"tools/call",params:t},Zi,n)}sendMessage(t,n){return this.request({method:"ui/message",params:t},tI,n)}sendLog(t){return this.notification({method:"notifications/message",params:t})}updateModelContext(t,n){return this.request({method:"ui/update-model-context",params:t},Fn,n)}openLink(t,n){return this.request({method:"ui/open-link",params:t},eI,n)}sendOpenLink=this.openLink;requestDisplayMode(t,n){return this.request({method:"ui/request-display-mode",params:t},cI,n)}sendSizeChanged(t){return this.notification({method:"ui/notifications/size-changed",params:t})}setupSizeChangedNotifications(){let t=!1,n=0,r=0,i=()=>{t||(t=!0,requestAnimationFrame(()=>{t=!1;let o=document.documentElement,s=o.style.width,u=o.style.height;o.style.width="fit-content",o.style.height="fit-content";let l=o.getBoundingClientRect();o.style.width=s,o.style.height=u;let d=window.innerWidth-o.clientWidth,f=Math.ceil(l.width+d),p=Math.ceil(l.height);(f!==n||p!==r)&&(n=f,r=p,this.sendSizeChanged({width:f,height:p}))}))};i();let a=new ResizeObserver(i);return a.observe(document.documentElement),a.observe(document.body),()=>a.disconnect()}async connect(t=new $_(window.parent,window.parent),n){await super.connect(t);try{let r=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:__}},pI,n);if(r===void 0)throw Error(`Server sent invalid initialize result: ${r}`);this._hostCapabilities=r.hostCapabilities,this._hostInfo=r.hostInfo,this._hostContext=r.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(r){throw this.close(),r}}}const it=new vI({name:"Footprint Export View",version:"0.3.0"});let $t=[],Ee=null;function Fe(e){const t=document.getElementById("error-container");t&&(t.innerHTML=`
301
+ container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:c.string().optional().describe("User's language and region preference in BCP 47 format."),timeZone:c.string().optional().describe("User's timezone in IANA format."),userAgent:c.string().optional().describe("Host application identifier."),platform:c.union([c.literal("web"),c.literal("desktop"),c.literal("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:c.object({touch:c.boolean().optional().describe("Whether the device supports touch input."),hover:c.boolean().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:c.object({top:c.number().describe("Top safe area inset in pixels."),right:c.number().describe("Right safe area inset in pixels."),bottom:c.number().describe("Bottom safe area inset in pixels."),left:c.number().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),fI=c.object({method:c.literal("ui/notifications/host-context-changed"),params:bf.describe("Partial context update containing only changed fields.")});c.object({method:c.literal("ui/update-model-context"),params:c.object({content:c.array(Zt).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:c.record(c.string(),c.unknown().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});c.object({method:c.literal("ui/initialize"),params:c.object({appInfo:xi.describe("App identification (name and version)."),appCapabilities:lI.describe("Features and capabilities this app provides."),protocolVersion:c.string().describe("Protocol version this app supports.")})});var pI=c.object({protocolVersion:c.string().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:xi.describe("Host application identification and version."),hostCapabilities:uI.describe("Features and capabilities provided by the host."),hostContext:bf.describe("Rich context about the host environment.")}).passthrough();class vI extends h_{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(t,n={},r={autoResize:!0}){super(r),this._appInfo=t,this._capabilities=n,this.options=r,this.setRequestHandler(zi,i=>(console.log("Received ping:",i.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(t){this.setNotificationHandler(iI,n=>t(n.params))}set ontoolinputpartial(t){this.setNotificationHandler(nI,n=>t(n.params))}set ontoolresult(t){this.setNotificationHandler(mI,n=>t(n.params))}set ontoolcancelled(t){this.setNotificationHandler(rI,n=>t(n.params))}set onhostcontextchanged(t){this.setNotificationHandler(fI,n=>{this._hostContext={...this._hostContext,...n.params},t(n.params)})}set onteardown(t){this.setRequestHandler(sI,(n,r)=>t(n.params,r))}set oncalltool(t){this.setRequestHandler(Os,(n,r)=>t(n.params,r))}set onlisttools(t){this.setRequestHandler(Us,(n,r)=>t(n.params,r))}assertCapabilityForMethod(t){}assertRequestHandlerCapability(t){switch(t){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${t})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${t} registered`)}}assertNotificationCapability(t){}assertTaskCapability(t){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(t){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(t,n){return await this.request({method:"tools/call",params:t},Zi,n)}sendMessage(t,n){return this.request({method:"ui/message",params:t},tI,n)}sendLog(t){return this.notification({method:"notifications/message",params:t})}updateModelContext(t,n){return this.request({method:"ui/update-model-context",params:t},Fn,n)}openLink(t,n){return this.request({method:"ui/open-link",params:t},eI,n)}sendOpenLink=this.openLink;requestDisplayMode(t,n){return this.request({method:"ui/request-display-mode",params:t},cI,n)}sendSizeChanged(t){return this.notification({method:"ui/notifications/size-changed",params:t})}setupSizeChangedNotifications(){let t=!1,n=0,r=0,i=()=>{t||(t=!0,requestAnimationFrame(()=>{t=!1;let o=document.documentElement,s=o.style.width,u=o.style.height;o.style.width="fit-content",o.style.height="fit-content";let l=o.getBoundingClientRect();o.style.width=s,o.style.height=u;let d=window.innerWidth-o.clientWidth,f=Math.ceil(l.width+d),p=Math.ceil(l.height);(f!==n||p!==r)&&(n=f,r=p,this.sendSizeChanged({width:f,height:p}))}))};i();let a=new ResizeObserver(i);return a.observe(document.documentElement),a.observe(document.body),()=>a.disconnect()}async connect(t=new $_(window.parent,window.parent),n){await super.connect(t);try{let r=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:__}},pI,n);if(r===void 0)throw Error(`Server sent invalid initialize result: ${r}`);this._hostCapabilities=r.hostCapabilities,this._hostInfo=r.hostInfo,this._hostContext=r.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(r){throw this.close(),r}}}const it=new vI({name:"Footprint Export View",version:"1.1.1"});let $t=[],Ee=null;function Fe(e){const t=document.getElementById("error-container");t&&(t.innerHTML=`
302
302
  <div class="error">
303
303
  ❌ Error: ${e}
304
304
  </div>
@@ -298,7 +298,7 @@ Note: This type uses \`Record<K, string | undefined>\` rather than \`Partial<Rec
298
298
  for compatibility with Zod schema generation. Both are functionally equivalent for validation.`);c.object({method:c.literal("ui/open-link"),params:c.object({url:c.string().describe("URL to open in the host's browser")})});var eI=c.object({isError:c.boolean().optional().describe("True if the host failed to open the URL (e.g., due to security policy).")}).passthrough(),tI=c.object({isError:c.boolean().optional().describe("True if the host rejected or failed to deliver the message.")}).passthrough();c.object({method:c.literal("ui/notifications/sandbox-proxy-ready"),params:c.object({})});var Qa=c.object({connectDomains:c.array(c.string()).optional().describe("Origins for network requests (fetch/XHR/WebSocket)."),resourceDomains:c.array(c.string()).optional().describe("Origins for static resources (scripts, images, styles, fonts)."),frameDomains:c.array(c.string()).optional().describe("Origins for nested iframes (frame-src directive)."),baseUriDomains:c.array(c.string()).optional().describe("Allowed base URIs for the document (base-uri directive).")}),eo=c.object({camera:c.object({}).optional().describe("Request camera access (Permission Policy `camera` feature)."),microphone:c.object({}).optional().describe("Request microphone access (Permission Policy `microphone` feature)."),geolocation:c.object({}).optional().describe("Request geolocation access (Permission Policy `geolocation` feature)."),clipboardWrite:c.object({}).optional().describe("Request clipboard write access (Permission Policy `clipboard-write` feature).")});c.object({method:c.literal("ui/notifications/size-changed"),params:c.object({width:c.number().optional().describe("New width in pixels."),height:c.number().optional().describe("New height in pixels.")})});var iI=c.object({method:c.literal("ui/notifications/tool-input"),params:c.object({arguments:c.record(c.string(),c.unknown().describe("Complete tool call arguments as key-value pairs.")).optional().describe("Complete tool call arguments as key-value pairs.")})}),nI=c.object({method:c.literal("ui/notifications/tool-input-partial"),params:c.object({arguments:c.record(c.string(),c.unknown().describe("Partial tool call arguments (incomplete, may change).")).optional().describe("Partial tool call arguments (incomplete, may change).")})}),rI=c.object({method:c.literal("ui/notifications/tool-cancelled"),params:c.object({reason:c.string().optional().describe('Optional reason for the cancellation (e.g., "user action", "timeout").')})}),aI=c.object({fonts:c.string().optional()}),oI=c.object({variables:Qk.optional().describe("CSS variables for theming the app."),css:aI.optional().describe("CSS blocks that apps can inject.")}),sI=c.object({method:c.literal("ui/resource-teardown"),params:c.object({})});c.record(c.string(),c.unknown());var Fo=c.object({text:c.object({}).optional().describe("Host supports text content blocks."),image:c.object({}).optional().describe("Host supports image content blocks."),audio:c.object({}).optional().describe("Host supports audio content blocks."),resource:c.object({}).optional().describe("Host supports resource content blocks."),resourceLink:c.object({}).optional().describe("Host supports resource link content blocks."),structuredContent:c.object({}).optional().describe("Host supports structured content.")}),uI=c.object({experimental:c.object({}).optional().describe("Experimental features (structure TBD)."),openLinks:c.object({}).optional().describe("Host supports opening external URLs."),serverTools:c.object({listChanged:c.boolean().optional().describe("Host supports tools/list_changed notifications.")}).optional().describe("Host can proxy tool calls to the MCP server."),serverResources:c.object({listChanged:c.boolean().optional().describe("Host supports resources/list_changed notifications.")}).optional().describe("Host can proxy resource reads to the MCP server."),logging:c.object({}).optional().describe("Host accepts log messages."),sandbox:c.object({permissions:eo.optional().describe("Permissions granted by the host (camera, microphone, geolocation)."),csp:Qa.optional().describe("CSP domains approved by the host.")}).optional().describe("Sandbox configuration applied by the host."),updateModelContext:Fo.optional().describe("Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns."),message:Fo.optional().describe("Host supports receiving content messages (ui/message) from the view.")}),lI=c.object({experimental:c.object({}).optional().describe("Experimental features (structure TBD)."),tools:c.object({listChanged:c.boolean().optional().describe("App supports tools/list_changed notifications.")}).optional().describe("App exposes MCP-style tools that the host can call."),availableDisplayModes:c.array(gt).optional().describe("Display modes the app supports.")});c.object({method:c.literal("ui/notifications/initialized"),params:c.object({}).optional()});c.object({csp:Qa.optional().describe("Content Security Policy configuration."),permissions:eo.optional().describe("Sandbox permissions requested by the UI."),domain:c.string().optional().describe("Dedicated origin for view sandbox."),prefersBorder:c.boolean().optional().describe("Visual boundary preference - true if UI prefers a visible border.")});c.object({method:c.literal("ui/request-display-mode"),params:c.object({mode:gt.describe("The display mode being requested.")})});var cI=c.object({mode:gt.describe("The display mode that was actually set. May differ from requested if not supported.")}).passthrough(),dI=c.union([c.literal("model"),c.literal("app")]).describe("Tool visibility scope - who can access the tool.");c.object({resourceUri:c.string().optional(),visibility:c.array(dI).optional().describe(`Who can access this tool. Default: ["model", "app"]
299
299
  - "model": Tool visible to and callable by the agent
300
300
  - "app": Tool callable by the app from this server only`)});c.object({mimeTypes:c.array(c.string()).optional().describe('Array of supported MIME types for UI resources.\nMust include `"text/html;profile=mcp-app"` for MCP Apps support.')});c.object({method:c.literal("ui/message"),params:c.object({role:c.literal("user").describe('Message role, currently only "user" is supported.'),content:c.array(Zt).describe("Message content blocks (text, image, etc.).")})});c.object({method:c.literal("ui/notifications/sandbox-resource-ready"),params:c.object({html:c.string().describe("HTML content to load into the inner iframe."),sandbox:c.string().optional().describe("Optional override for the inner iframe's sandbox attribute."),csp:Qa.optional().describe("CSP configuration from resource metadata."),permissions:eo.optional().describe("Sandbox permissions from resource metadata.")})});var mI=c.object({method:c.literal("ui/notifications/tool-result"),params:Zi.describe("Standard MCP tool execution result.")}),bf=c.object({toolInfo:c.object({id:kt.optional().describe("JSON-RPC id of the tools/call request."),tool:nr.describe("Tool definition including name, inputSchema, etc.")}).optional().describe("Metadata of the tool call that instantiated this App."),theme:Xk.optional().describe("Current color theme preference."),styles:oI.optional().describe("Style configuration for theming the app."),displayMode:gt.optional().describe("How the UI is currently displayed."),availableDisplayModes:c.array(gt).optional().describe("Display modes the host supports."),containerDimensions:c.union([c.object({height:c.number().describe("Fixed container height in pixels.")}),c.object({maxHeight:c.union([c.number(),c.undefined()]).optional().describe("Maximum container height in pixels.")})]).and(c.union([c.object({width:c.number().describe("Fixed container width in pixels.")}),c.object({maxWidth:c.union([c.number(),c.undefined()]).optional().describe("Maximum container width in pixels.")})])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
301
- container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:c.string().optional().describe("User's language and region preference in BCP 47 format."),timeZone:c.string().optional().describe("User's timezone in IANA format."),userAgent:c.string().optional().describe("Host application identifier."),platform:c.union([c.literal("web"),c.literal("desktop"),c.literal("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:c.object({touch:c.boolean().optional().describe("Whether the device supports touch input."),hover:c.boolean().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:c.object({top:c.number().describe("Top safe area inset in pixels."),right:c.number().describe("Right safe area inset in pixels."),bottom:c.number().describe("Bottom safe area inset in pixels."),left:c.number().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),fI=c.object({method:c.literal("ui/notifications/host-context-changed"),params:bf.describe("Partial context update containing only changed fields.")});c.object({method:c.literal("ui/update-model-context"),params:c.object({content:c.array(Zt).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:c.record(c.string(),c.unknown().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});c.object({method:c.literal("ui/initialize"),params:c.object({appInfo:xi.describe("App identification (name and version)."),appCapabilities:lI.describe("Features and capabilities this app provides."),protocolVersion:c.string().describe("Protocol version this app supports.")})});var pI=c.object({protocolVersion:c.string().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:xi.describe("Host application identification and version."),hostCapabilities:uI.describe("Features and capabilities provided by the host."),hostContext:bf.describe("Rich context about the host environment.")}).passthrough();class vI extends h_{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(t,n={},r={autoResize:!0}){super(r),this._appInfo=t,this._capabilities=n,this.options=r,this.setRequestHandler(zi,i=>(console.log("Received ping:",i.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(t){this.setNotificationHandler(iI,n=>t(n.params))}set ontoolinputpartial(t){this.setNotificationHandler(nI,n=>t(n.params))}set ontoolresult(t){this.setNotificationHandler(mI,n=>t(n.params))}set ontoolcancelled(t){this.setNotificationHandler(rI,n=>t(n.params))}set onhostcontextchanged(t){this.setNotificationHandler(fI,n=>{this._hostContext={...this._hostContext,...n.params},t(n.params)})}set onteardown(t){this.setRequestHandler(sI,(n,r)=>t(n.params,r))}set oncalltool(t){this.setRequestHandler(Os,(n,r)=>t(n.params,r))}set onlisttools(t){this.setRequestHandler(Us,(n,r)=>t(n.params,r))}assertCapabilityForMethod(t){}assertRequestHandlerCapability(t){switch(t){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${t})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${t} registered`)}}assertNotificationCapability(t){}assertTaskCapability(t){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(t){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(t,n){return await this.request({method:"tools/call",params:t},Zi,n)}sendMessage(t,n){return this.request({method:"ui/message",params:t},tI,n)}sendLog(t){return this.notification({method:"notifications/message",params:t})}updateModelContext(t,n){return this.request({method:"ui/update-model-context",params:t},Fn,n)}openLink(t,n){return this.request({method:"ui/open-link",params:t},eI,n)}sendOpenLink=this.openLink;requestDisplayMode(t,n){return this.request({method:"ui/request-display-mode",params:t},cI,n)}sendSizeChanged(t){return this.notification({method:"ui/notifications/size-changed",params:t})}setupSizeChangedNotifications(){let t=!1,n=0,r=0,i=()=>{t||(t=!0,requestAnimationFrame(()=>{t=!1;let o=document.documentElement,s=o.style.width,u=o.style.height;o.style.width="fit-content",o.style.height="fit-content";let l=o.getBoundingClientRect();o.style.width=s,o.style.height=u;let d=window.innerWidth-o.clientWidth,f=Math.ceil(l.width+d),p=Math.ceil(l.height);(f!==n||p!==r)&&(n=f,r=p,this.sendSizeChanged({width:f,height:p}))}))};i();let a=new ResizeObserver(i);return a.observe(document.documentElement),a.observe(document.body),()=>a.disconnect()}async connect(t=new $_(window.parent,window.parent),n){await super.connect(t);try{let r=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:__}},pI,n);if(r===void 0)throw Error(`Server sent invalid initialize result: ${r}`);this._hostCapabilities=r.hostCapabilities,this._hostInfo=r.hostInfo,this._hostContext=r.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(r){throw this.close(),r}}}const it=new vI({name:"Footprint Export View",version:"0.3.0"});let $t=[],Ee=null;function Fe(e){const t=document.getElementById("error-container");t&&(t.innerHTML=`
301
+ container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:c.string().optional().describe("User's language and region preference in BCP 47 format."),timeZone:c.string().optional().describe("User's timezone in IANA format."),userAgent:c.string().optional().describe("Host application identifier."),platform:c.union([c.literal("web"),c.literal("desktop"),c.literal("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:c.object({touch:c.boolean().optional().describe("Whether the device supports touch input."),hover:c.boolean().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:c.object({top:c.number().describe("Top safe area inset in pixels."),right:c.number().describe("Right safe area inset in pixels."),bottom:c.number().describe("Bottom safe area inset in pixels."),left:c.number().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),fI=c.object({method:c.literal("ui/notifications/host-context-changed"),params:bf.describe("Partial context update containing only changed fields.")});c.object({method:c.literal("ui/update-model-context"),params:c.object({content:c.array(Zt).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:c.record(c.string(),c.unknown().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});c.object({method:c.literal("ui/initialize"),params:c.object({appInfo:xi.describe("App identification (name and version)."),appCapabilities:lI.describe("Features and capabilities this app provides."),protocolVersion:c.string().describe("Protocol version this app supports.")})});var pI=c.object({protocolVersion:c.string().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:xi.describe("Host application identification and version."),hostCapabilities:uI.describe("Features and capabilities provided by the host."),hostContext:bf.describe("Rich context about the host environment.")}).passthrough();class vI extends h_{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(t,n={},r={autoResize:!0}){super(r),this._appInfo=t,this._capabilities=n,this.options=r,this.setRequestHandler(zi,i=>(console.log("Received ping:",i.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(t){this.setNotificationHandler(iI,n=>t(n.params))}set ontoolinputpartial(t){this.setNotificationHandler(nI,n=>t(n.params))}set ontoolresult(t){this.setNotificationHandler(mI,n=>t(n.params))}set ontoolcancelled(t){this.setNotificationHandler(rI,n=>t(n.params))}set onhostcontextchanged(t){this.setNotificationHandler(fI,n=>{this._hostContext={...this._hostContext,...n.params},t(n.params)})}set onteardown(t){this.setRequestHandler(sI,(n,r)=>t(n.params,r))}set oncalltool(t){this.setRequestHandler(Os,(n,r)=>t(n.params,r))}set onlisttools(t){this.setRequestHandler(Us,(n,r)=>t(n.params,r))}assertCapabilityForMethod(t){}assertRequestHandlerCapability(t){switch(t){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${t})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${t} registered`)}}assertNotificationCapability(t){}assertTaskCapability(t){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(t){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(t,n){return await this.request({method:"tools/call",params:t},Zi,n)}sendMessage(t,n){return this.request({method:"ui/message",params:t},tI,n)}sendLog(t){return this.notification({method:"notifications/message",params:t})}updateModelContext(t,n){return this.request({method:"ui/update-model-context",params:t},Fn,n)}openLink(t,n){return this.request({method:"ui/open-link",params:t},eI,n)}sendOpenLink=this.openLink;requestDisplayMode(t,n){return this.request({method:"ui/request-display-mode",params:t},cI,n)}sendSizeChanged(t){return this.notification({method:"ui/notifications/size-changed",params:t})}setupSizeChangedNotifications(){let t=!1,n=0,r=0,i=()=>{t||(t=!0,requestAnimationFrame(()=>{t=!1;let o=document.documentElement,s=o.style.width,u=o.style.height;o.style.width="fit-content",o.style.height="fit-content";let l=o.getBoundingClientRect();o.style.width=s,o.style.height=u;let d=window.innerWidth-o.clientWidth,f=Math.ceil(l.width+d),p=Math.ceil(l.height);(f!==n||p!==r)&&(n=f,r=p,this.sendSizeChanged({width:f,height:p}))}))};i();let a=new ResizeObserver(i);return a.observe(document.documentElement),a.observe(document.body),()=>a.disconnect()}async connect(t=new $_(window.parent,window.parent),n){await super.connect(t);try{let r=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:__}},pI,n);if(r===void 0)throw Error(`Server sent invalid initialize result: ${r}`);this._hostCapabilities=r.hostCapabilities,this._hostInfo=r.hostInfo,this._hostContext=r.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(r){throw this.close(),r}}}const it=new vI({name:"Footprint Export View",version:"1.1.1"});let $t=[],Ee=null;function Fe(e){const t=document.getElementById("error-container");t&&(t.innerHTML=`
302
302
  <div class="error">
303
303
  ❌ Error: ${e}
304
304
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pcircle/footprint",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "description": "MCP server for Footprint - automatic audit trails and encrypted evidence for AI conversations",
5
5
  "keywords": [
6
6
  "mcp",
@@ -18,10 +18,10 @@
18
18
  "author": "PCIRCLE, LLC",
19
19
  "license": "MIT",
20
20
  "type": "module",
21
- "main": "./dist/index.js",
22
- "types": "./dist/index.d.ts",
21
+ "main": "./dist/src/index.js",
22
+ "types": "./dist/src/index.d.ts",
23
23
  "bin": {
24
- "footprint": "./dist/index.js"
24
+ "footprint": "./dist/src/index.js"
25
25
  },
26
26
  "files": [
27
27
  "dist",
@@ -31,15 +31,15 @@
31
31
  ],
32
32
  "repository": {
33
33
  "type": "git",
34
- "url": "https://github.com/PCIRCLE-AI/footprint.git"
34
+ "url": "https://github.com/PCIRCLE-AI/footprint-mcp.git"
35
35
  },
36
36
  "bugs": {
37
- "url": "https://github.com/PCIRCLE-AI/footprint/issues"
37
+ "url": "https://github.com/PCIRCLE-AI/footprint-mcp/issues"
38
38
  },
39
39
  "homepage": "https://footprint.memesh.ai",
40
40
  "scripts": {
41
41
  "build": "pnpm build:ui && tsc",
42
- "build:ui": "pnpm build:ui:dashboard && pnpm build:ui:detail && pnpm build:ui:export",
42
+ "build:ui": "mkdir -p dist/ui && pnpm build:ui:dashboard && pnpm build:ui:detail && pnpm build:ui:export",
43
43
  "build:ui:dashboard": "cross-env INPUT=ui/dashboard.html vite build --outDir dist/ui-tmp && cp dist/ui-tmp/ui/dashboard.html dist/ui/dashboard.html",
44
44
  "build:ui:detail": "cross-env INPUT=ui/detail.html vite build --outDir dist/ui-tmp && cp dist/ui-tmp/ui/detail.html dist/ui/detail.html",
45
45
  "build:ui:export": "cross-env INPUT=ui/export.html vite build --outDir dist/ui-tmp && cp dist/ui-tmp/ui/export.html dist/ui/export.html",
@@ -51,7 +51,7 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@modelcontextprotocol/ext-apps": "^1.0.1",
54
- "@modelcontextprotocol/sdk": "^1.0.4",
54
+ "@modelcontextprotocol/sdk": "^1.25.3",
55
55
  "@noble/ciphers": "^0.5.2",
56
56
  "@noble/hashes": "^1.3.3",
57
57
  "better-sqlite3": "^12.6.2",
package/dist/index.d.ts DELETED
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env node
2
- import type { ServerConfig } from './types.js';
3
- /**
4
- * EvidenceMCP Server - Captures LLM conversations as encrypted footprint
5
- * with Git timestamps and export capabilities.
6
- */
7
- export declare class EvidenceMCPServer {
8
- private server;
9
- private config;
10
- private db;
11
- private derivedKey;
12
- constructor(config: ServerConfig);
13
- private getDerivedKey;
14
- private registerTools;
15
- private registerResources;
16
- start(): Promise<void>;
17
- }
18
- export { EvidenceMCPTestHelpers } from './test-helpers.js';
19
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AASA,OAAO,KAAK,EAAE,YAAY,EAAyB,MAAM,YAAY,CAAC;AAMtE;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,EAAE,CAAmB;IAC7B,OAAO,CAAC,UAAU,CAA2B;gBAEjC,MAAM,EAAE,YAAY;YAqBlB,aAAa;IAQ3B,OAAO,CAAC,aAAa;IAqrBrB,OAAO,CAAC,iBAAiB;IA6BnB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B;AA6BD,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC"}