@kya-os/create-mcpi-app 1.7.38-canary.2 → 1.7.38

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 (67) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.turbo/turbo-test$colon$coverage.log +755 -0
  3. package/.turbo/turbo-test.log +200 -0
  4. package/dist/helpers/fetch-cloudflare-mcpi-template.d.ts.map +1 -1
  5. package/dist/helpers/fetch-cloudflare-mcpi-template.js +35 -914
  6. package/dist/helpers/fetch-cloudflare-mcpi-template.js.map +1 -1
  7. package/dist/utils/fetch-remote-config.d.ts.map +1 -1
  8. package/dist/utils/fetch-remote-config.js +2 -2
  9. package/dist/utils/fetch-remote-config.js.map +1 -1
  10. package/package/package.json +77 -0
  11. package/package.json +1 -1
  12. package/ARCHITECTURE_ANALYSIS.md +0 -392
  13. package/CHANGELOG.md +0 -372
  14. package/DEPRECATION_WARNINGS_ANALYSIS.md +0 -192
  15. package/IMPLEMENTATION_SUMMARY.md +0 -108
  16. package/REMEDIATION_PLAN.md +0 -99
  17. package/dist/.tsbuildinfo +0 -1
  18. package/scripts/prepare-pack.js +0 -47
  19. package/scripts/validate-no-workspace.js +0 -79
  20. package/src/__tests__/cloudflare-template.test.ts +0 -490
  21. package/src/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts +0 -337
  22. package/src/__tests__/helpers/generate-config.test.ts +0 -312
  23. package/src/__tests__/helpers/generate-identity.test.ts +0 -271
  24. package/src/__tests__/helpers/install.test.ts +0 -370
  25. package/src/__tests__/helpers/validate-project-structure.test.ts +0 -467
  26. package/src/__tests__.bak/regression.test.ts +0 -434
  27. package/src/effects/index.ts +0 -80
  28. package/src/helpers/__tests__/config-builder.spec.ts +0 -231
  29. package/src/helpers/apply-identity-preset.ts +0 -209
  30. package/src/helpers/config-builder.ts +0 -165
  31. package/src/helpers/copy-template.ts +0 -11
  32. package/src/helpers/create.ts +0 -239
  33. package/src/helpers/fetch-cloudflare-mcpi-template.ts +0 -2404
  34. package/src/helpers/fetch-cloudflare-template.ts +0 -361
  35. package/src/helpers/fetch-mcpi-template.ts +0 -236
  36. package/src/helpers/fetch-xmcp-template.ts +0 -153
  37. package/src/helpers/generate-config.ts +0 -118
  38. package/src/helpers/generate-identity.ts +0 -163
  39. package/src/helpers/identity-manager.ts +0 -186
  40. package/src/helpers/install.ts +0 -79
  41. package/src/helpers/rename.ts +0 -17
  42. package/src/helpers/validate-project-structure.ts +0 -127
  43. package/src/index.ts +0 -520
  44. package/src/utils/__tests__/fetch-remote-config.test.ts +0 -271
  45. package/src/utils/check-node.ts +0 -17
  46. package/src/utils/fetch-remote-config.ts +0 -179
  47. package/src/utils/is-folder-empty.ts +0 -60
  48. package/src/utils/validate-project-name.ts +0 -132
  49. package/test-cloudflare/README.md +0 -164
  50. package/test-cloudflare/package.json +0 -28
  51. package/test-cloudflare/src/index.ts +0 -341
  52. package/test-cloudflare/src/tools/greet.ts +0 -19
  53. package/test-cloudflare/tests/cache-invalidation.test.ts +0 -410
  54. package/test-cloudflare/tests/cors-security.test.ts +0 -349
  55. package/test-cloudflare/tests/delegation.test.ts +0 -335
  56. package/test-cloudflare/tests/do-routing.test.ts +0 -314
  57. package/test-cloudflare/tests/integration.test.ts +0 -205
  58. package/test-cloudflare/tests/session-management.test.ts +0 -359
  59. package/test-cloudflare/tsconfig.json +0 -16
  60. package/test-cloudflare/vitest.config.ts +0 -9
  61. package/test-cloudflare/wrangler.toml +0 -37
  62. package/test-node/README.md +0 -44
  63. package/test-node/package.json +0 -23
  64. package/test-node/src/tools/greet.ts +0 -25
  65. package/test-node/xmcp.config.ts +0 -20
  66. package/tsconfig.json +0 -26
  67. package/vitest.config.ts +0 -14
@@ -1,490 +0,0 @@
1
- /**
2
- * Cloudflare Template Tests
3
- *
4
- * Tests for Cloudflare Worker template generation, including file structure,
5
- * configuration, KV namespace setup, and tool protection configuration.
6
- */
7
-
8
- import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
9
- import fs from "fs-extra";
10
- import path from "path";
11
- import { fetchCloudflareMcpiTemplate } from "../helpers/fetch-cloudflare-mcpi-template";
12
-
13
- describe("Cloudflare Template Generation", () => {
14
- let tempDir: string;
15
- const originalConsoleLog = console.log;
16
- const originalConsoleError = console.error;
17
-
18
- beforeEach(() => {
19
- // Create temporary directory for each test
20
- tempDir = path.join(
21
- process.cwd(),
22
- "test-temp",
23
- `test-${Date.now()}-${Math.random().toString(36).substring(7)}`
24
- );
25
- fs.ensureDirSync(tempDir);
26
-
27
- // Suppress console output during tests
28
- console.log = vi.fn();
29
- console.error = vi.fn();
30
- });
31
-
32
- afterEach(async () => {
33
- // Clean up temporary directory
34
- if (fs.existsSync(tempDir)) {
35
- try {
36
- fs.removeSync(tempDir);
37
- } catch (error) {
38
- // Ignore errors if directory is already being cleaned up by another test
39
- }
40
- }
41
-
42
- // Only try to remove parent directory if it exists and is empty
43
- const testTempDir = path.join(process.cwd(), "test-temp");
44
- if (fs.existsSync(testTempDir)) {
45
- try {
46
- const testTempContents = fs.readdirSync(testTempDir);
47
- if (testTempContents.length === 0) {
48
- fs.removeSync(testTempDir);
49
- }
50
- } catch (error) {
51
- // Ignore errors if directory is being modified by another test
52
- }
53
- }
54
-
55
- // Restore console
56
- console.log = originalConsoleLog;
57
- console.error = originalConsoleError;
58
- });
59
-
60
- describe("Basic template structure", () => {
61
- it("should create all required files and directories", async () => {
62
- await fetchCloudflareMcpiTemplate(tempDir, {
63
- packageManager: "npm",
64
- projectName: "test-project",
65
- skipIdentity: false,
66
- });
67
-
68
- // Check package.json exists
69
- expect(fs.existsSync(path.join(tempDir, "package.json"))).toBe(true);
70
-
71
- // Check src directory structure
72
- expect(fs.existsSync(path.join(tempDir, "src"))).toBe(true);
73
- expect(fs.existsSync(path.join(tempDir, "src", "tools"))).toBe(true);
74
- expect(
75
- fs.existsSync(path.join(tempDir, "src", "tools", "greet.ts"))
76
- ).toBe(true);
77
-
78
- // Check scripts directory
79
- expect(fs.existsSync(path.join(tempDir, "scripts"))).toBe(true);
80
- expect(fs.existsSync(path.join(tempDir, "scripts", "setup.js"))).toBe(
81
- true
82
- );
83
-
84
- // Check configuration files
85
- expect(fs.existsSync(path.join(tempDir, "wrangler.toml"))).toBe(true);
86
- expect(fs.existsSync(path.join(tempDir, "tsconfig.json"))).toBe(true);
87
- expect(fs.existsSync(path.join(tempDir, ".gitignore"))).toBe(true);
88
- expect(fs.existsSync(path.join(tempDir, "README.md"))).toBe(true);
89
- expect(fs.existsSync(path.join(tempDir, "vitest.config.ts"))).toBe(true);
90
- });
91
-
92
- it("should create mcpi-runtime-config.ts with correct structure", async () => {
93
- await fetchCloudflareMcpiTemplate(tempDir, {
94
- packageManager: "npm",
95
- projectName: "test-project",
96
- });
97
-
98
- const configPath = path.join(tempDir, "src", "mcpi-runtime-config.ts");
99
- expect(fs.existsSync(configPath)).toBe(true);
100
-
101
- const configContent = fs.readFileSync(configPath, "utf-8");
102
- expect(configContent).toContain("getRuntimeConfig");
103
- expect(configContent).toContain("buildBaseConfig");
104
- expect(configContent).toContain("CloudflareRuntimeConfig");
105
- });
106
-
107
- it("should create index.ts with correct structure", async () => {
108
- await fetchCloudflareMcpiTemplate(tempDir, {
109
- packageManager: "npm",
110
- projectName: "test-project",
111
- });
112
-
113
- const indexPath = path.join(tempDir, "src", "index.ts");
114
- expect(fs.existsSync(indexPath)).toBe(true);
115
-
116
- const indexContent = fs.readFileSync(indexPath, "utf-8");
117
- expect(indexContent).toContain("McpAgent");
118
- expect(indexContent).toContain("createCloudflareRuntime");
119
- expect(indexContent).toContain("class");
120
- });
121
- });
122
-
123
- describe("MCP_SERVER_URL configuration", () => {
124
- it("should include MCP_SERVER_URL placeholder in wrangler.toml", async () => {
125
- await fetchCloudflareMcpiTemplate(tempDir, {
126
- packageManager: "npm",
127
- projectName: "test-project",
128
- });
129
-
130
- const wranglerPath = path.join(tempDir, "wrangler.toml");
131
- const wranglerContent = fs.readFileSync(wranglerPath, "utf-8");
132
-
133
- expect(wranglerContent).toContain("MCP_SERVER_URL");
134
- expect(wranglerContent).toContain(
135
- "Optional: MCP Server URL for tool discovery"
136
- );
137
- });
138
-
139
- it("should log warning when MCP_SERVER_URL not configured", async () => {
140
- await fetchCloudflareMcpiTemplate(tempDir, {
141
- packageManager: "npm",
142
- projectName: "test-project",
143
- });
144
-
145
- const indexPath = path.join(tempDir, "src", "index.ts");
146
- const indexContent = fs.readFileSync(indexPath, "utf-8");
147
-
148
- // Check that auto-detection message is logged in index.ts when MCP_SERVER_URL not configured
149
- expect(indexContent).toContain(
150
- "MCP Server URL will be auto-detected from request"
151
- );
152
- });
153
-
154
- it("should store MCP_SERVER_URL in class property", async () => {
155
- await fetchCloudflareMcpiTemplate(tempDir, {
156
- packageManager: "npm",
157
- projectName: "test-project",
158
- });
159
-
160
- const indexPath = path.join(tempDir, "src", "index.ts");
161
- const indexContent = fs.readFileSync(indexPath, "utf-8");
162
-
163
- expect(indexContent).toContain("this.mcpServerUrl");
164
- expect(indexContent).toContain("env.MCP_SERVER_URL");
165
- });
166
- });
167
-
168
- describe("KV namespace setup", () => {
169
- it("should include all required KV namespace bindings in wrangler.toml", async () => {
170
- await fetchCloudflareMcpiTemplate(tempDir, {
171
- packageManager: "npm",
172
- projectName: "TestProject",
173
- });
174
-
175
- const wranglerPath = path.join(tempDir, "wrangler.toml");
176
- const wranglerContent = fs.readFileSync(wranglerPath, "utf-8");
177
-
178
- // Check for all KV namespace bindings (using className TESTPROJECT)
179
- expect(wranglerContent).toContain("TESTPROJECT_NONCE_CACHE");
180
- expect(wranglerContent).toContain("TESTPROJECT_PROOF_ARCHIVE");
181
- expect(wranglerContent).toContain("TESTPROJECT_IDENTITY_STORAGE");
182
- expect(wranglerContent).toContain("TESTPROJECT_DELEGATION_STORAGE");
183
- expect(wranglerContent).toContain("TESTPROJECT_TOOL_PROTECTION_KV");
184
- });
185
-
186
- it("should create KV namespace creation scripts in package.json", async () => {
187
- await fetchCloudflareMcpiTemplate(tempDir, {
188
- packageManager: "npm",
189
- projectName: "test-project",
190
- });
191
-
192
- const packageJsonPath = path.join(tempDir, "package.json");
193
- const packageJson = fs.readJsonSync(packageJsonPath);
194
-
195
- expect(packageJson.scripts).toHaveProperty("kv:create");
196
- expect(packageJson.scripts).toHaveProperty("kv:create-nonce");
197
- expect(packageJson.scripts).toHaveProperty("kv:create-proof");
198
- expect(packageJson.scripts).toHaveProperty("kv:create-identity");
199
- expect(packageJson.scripts).toHaveProperty("kv:create-delegation");
200
- expect(packageJson.scripts).toHaveProperty("kv:create-tool-protection");
201
- });
202
-
203
- it("should create KV namespace listing scripts", async () => {
204
- await fetchCloudflareMcpiTemplate(tempDir, {
205
- packageManager: "npm",
206
- projectName: "test-project",
207
- });
208
-
209
- const packageJsonPath = path.join(tempDir, "package.json");
210
- const packageJson = fs.readJsonSync(packageJsonPath);
211
-
212
- expect(packageJson.scripts).toHaveProperty("kv:list");
213
- expect(packageJson.scripts).toHaveProperty("kv:keys-nonce");
214
- expect(packageJson.scripts).toHaveProperty("kv:keys-proof");
215
- expect(packageJson.scripts).toHaveProperty("kv:keys-identity");
216
- expect(packageJson.scripts).toHaveProperty("kv:keys-delegation");
217
- expect(packageJson.scripts).toHaveProperty("kv:keys-tool-protection");
218
- });
219
- });
220
-
221
- describe("Tool protection setup", () => {
222
- it("should include tool protection configuration in runtime config", async () => {
223
- await fetchCloudflareMcpiTemplate(tempDir, {
224
- packageManager: "npm",
225
- projectName: "test-project",
226
- apikey: "test-api-key",
227
- });
228
-
229
- const configPath = path.join(tempDir, "src", "mcpi-runtime-config.ts");
230
- const configContent = fs.readFileSync(configPath, "utf-8");
231
-
232
- expect(configContent).toContain("toolProtection");
233
- expect(configContent).toContain("CloudflareRuntime");
234
- });
235
-
236
- it("should include CloudflareRuntime import for tool protection", async () => {
237
- await fetchCloudflareMcpiTemplate(tempDir, {
238
- packageManager: "npm",
239
- projectName: "test-project",
240
- });
241
-
242
- const configPath = path.join(tempDir, "src", "mcpi-runtime-config.ts");
243
- const configContent = fs.readFileSync(configPath, "utf-8");
244
-
245
- expect(configContent).toContain("CloudflareRuntime");
246
- expect(configContent).toContain('from "@kya-os/mcp-i-cloudflare"');
247
- });
248
-
249
- it("should conditionally enable tool protection KV when API key provided", async () => {
250
- await fetchCloudflareMcpiTemplate(tempDir, {
251
- packageManager: "npm",
252
- projectName: "test-project",
253
- apikey: "test-api-key",
254
- });
255
-
256
- const wranglerPath = path.join(tempDir, "wrangler.toml");
257
- const wranglerContent = fs.readFileSync(wranglerPath, "utf-8");
258
-
259
- // When API key is provided, TOOL_PROTECTION_KV should not be commented out
260
- const lines = wranglerContent.split("\n");
261
- const toolProtectionLines = lines.filter((line) =>
262
- line.includes("TOOL_PROTECTION_KV")
263
- );
264
- const commentedLines = toolProtectionLines.filter((line) =>
265
- line.trim().startsWith("#")
266
- );
267
-
268
- // Should have some non-commented lines for TOOL_PROTECTION_KV
269
- expect(toolProtectionLines.length).toBeGreaterThan(0);
270
- });
271
-
272
- it("should comment out tool protection KV when no API key provided", async () => {
273
- await fetchCloudflareMcpiTemplate(tempDir, {
274
- packageManager: "npm",
275
- projectName: "test-project",
276
- });
277
-
278
- const wranglerPath = path.join(tempDir, "wrangler.toml");
279
- const wranglerContent = fs.readFileSync(wranglerPath, "utf-8");
280
-
281
- // Tool protection KV is always included (not conditionally commented)
282
- // The namespace is automatically created by the setup script
283
- const lines = wranglerContent.split("\n");
284
- const bindingLine = lines.find(
285
- (line) =>
286
- line.includes("binding =") && line.includes("TOOL_PROTECTION_KV")
287
- );
288
-
289
- // Should be present and not commented out
290
- expect(bindingLine).toBeDefined();
291
- expect(bindingLine?.trim().startsWith("#")).toBe(false);
292
- });
293
- });
294
-
295
- describe("Identity provider configuration", () => {
296
- it("should generate identity when skipIdentity is false", async () => {
297
- const generateIdentitySpy = vi.spyOn(
298
- await import("../helpers/generate-identity"),
299
- "generateIdentity"
300
- );
301
- generateIdentitySpy.mockResolvedValue({
302
- did: "did:key:ztest123",
303
- kid: "did:key:ztest123#key-1",
304
- privateKey: "test-private-key",
305
- publicKey: "test-public-key",
306
- createdAt: new Date().toISOString(),
307
- type: "development",
308
- });
309
-
310
- await fetchCloudflareMcpiTemplate(tempDir, {
311
- packageManager: "npm",
312
- projectName: "test-project",
313
- skipIdentity: false,
314
- });
315
-
316
- // Check that identity was generated (would be in .dev.vars)
317
- const devVarsPath = path.join(tempDir, ".dev.vars");
318
- if (fs.existsSync(devVarsPath)) {
319
- const devVarsContent = fs.readFileSync(devVarsPath, "utf-8");
320
- expect(devVarsContent).toContain("MCP_IDENTITY_PRIVATE_KEY");
321
- expect(devVarsContent).toContain("MCP_IDENTITY_PUBLIC_KEY");
322
- }
323
-
324
- generateIdentitySpy.mockRestore();
325
- });
326
-
327
- it("should skip identity generation when skipIdentity is true", async () => {
328
- await fetchCloudflareMcpiTemplate(tempDir, {
329
- packageManager: "npm",
330
- projectName: "test-project",
331
- skipIdentity: true,
332
- });
333
-
334
- // Identity should not be generated
335
- const devVarsPath = path.join(tempDir, ".dev.vars");
336
- // When skipIdentity is true, .dev.vars might not exist or might not have identity
337
- // This is expected behavior
338
- });
339
-
340
- it("should include identity variables in wrangler.toml", async () => {
341
- await fetchCloudflareMcpiTemplate(tempDir, {
342
- packageManager: "npm",
343
- projectName: "test-project",
344
- });
345
-
346
- const wranglerPath = path.join(tempDir, "wrangler.toml");
347
- const wranglerContent = fs.readFileSync(wranglerPath, "utf-8");
348
-
349
- expect(wranglerContent).toContain("MCP_IDENTITY_AGENT_DID");
350
- expect(wranglerContent).toContain("MCP_IDENTITY_PRIVATE_KEY");
351
- expect(wranglerContent).toContain("MCP_IDENTITY_PUBLIC_KEY");
352
- });
353
-
354
- it("should create .dev.vars.example template", async () => {
355
- await fetchCloudflareMcpiTemplate(tempDir, {
356
- packageManager: "npm",
357
- projectName: "test-project",
358
- });
359
-
360
- const examplePath = path.join(tempDir, ".dev.vars.example");
361
- expect(fs.existsSync(examplePath)).toBe(true);
362
-
363
- const exampleContent = fs.readFileSync(examplePath, "utf-8");
364
- expect(exampleContent).toContain("MCP_IDENTITY_PRIVATE_KEY");
365
- expect(exampleContent).toContain("your-private-key-here");
366
- });
367
- });
368
-
369
- describe("Error handling", () => {
370
- it("should handle file system errors gracefully", async () => {
371
- // Create a read-only directory to simulate permission errors
372
- const readOnlyDir = path.join(tempDir, "readonly");
373
- fs.ensureDirSync(readOnlyDir);
374
- fs.chmodSync(readOnlyDir, 0o444); // Read-only
375
-
376
- try {
377
- await fetchCloudflareMcpiTemplate(readOnlyDir, {
378
- packageManager: "npm",
379
- projectName: "test-project",
380
- });
381
- // Should throw or handle error
382
- } catch (error) {
383
- expect(error).toBeDefined();
384
- } finally {
385
- // Restore permissions for cleanup
386
- fs.chmodSync(readOnlyDir, 0o755);
387
- }
388
- });
389
-
390
- it("should handle invalid project names", async () => {
391
- await fetchCloudflareMcpiTemplate(tempDir, {
392
- packageManager: "npm",
393
- projectName: "123invalid-name!!!",
394
- skipIdentity: true,
395
- });
396
-
397
- // Should sanitize project name for class names
398
- const indexPath = path.join(tempDir, "src", "index.ts");
399
- if (fs.existsSync(indexPath)) {
400
- const indexContent = fs.readFileSync(indexPath, "utf-8");
401
- // Class name should be sanitized
402
- expect(indexContent).toMatch(/class\s+\w+MCP/);
403
- }
404
- });
405
- });
406
-
407
- describe("Package manager configuration", () => {
408
- it("should use correct package manager in scripts", async () => {
409
- await fetchCloudflareMcpiTemplate(tempDir, {
410
- packageManager: "pnpm",
411
- projectName: "test-project",
412
- });
413
-
414
- const packageJsonPath = path.join(tempDir, "package.json");
415
- const packageJson = fs.readJsonSync(packageJsonPath);
416
-
417
- // Scripts should use pnpm commands
418
- expect(packageJson.scripts.setup).toContain("node");
419
- // Other scripts should use pnpm
420
- expect(packageJson.scripts.dev).toBe("wrangler dev");
421
- });
422
-
423
- it("should create correct package.json structure", async () => {
424
- await fetchCloudflareMcpiTemplate(tempDir, {
425
- packageManager: "npm",
426
- projectName: "test-project",
427
- });
428
-
429
- const packageJsonPath = path.join(tempDir, "package.json");
430
- const packageJson = fs.readJsonSync(packageJsonPath);
431
-
432
- expect(packageJson.name).toBe("test-project");
433
- expect(packageJson.version).toBe("0.1.0");
434
- expect(packageJson.private).toBe(true);
435
- expect(packageJson.dependencies).toBeDefined();
436
- expect(packageJson.devDependencies).toBeDefined();
437
- });
438
- });
439
-
440
- describe("Template files content", () => {
441
- it("should create greet tool with correct structure", async () => {
442
- await fetchCloudflareMcpiTemplate(tempDir, {
443
- packageManager: "npm",
444
- projectName: "test-project",
445
- });
446
-
447
- const greetPath = path.join(tempDir, "src", "tools", "greet.ts");
448
- const greetContent = fs.readFileSync(greetPath, "utf-8");
449
-
450
- expect(greetContent).toContain("greetTool");
451
- expect(greetContent).toContain('name: "greet"');
452
- expect(greetContent).toContain("inputSchema");
453
- expect(greetContent).toContain("handler");
454
- });
455
-
456
- it("should create test files with correct structure", async () => {
457
- await fetchCloudflareMcpiTemplate(tempDir, {
458
- packageManager: "npm",
459
- projectName: "test-project",
460
- });
461
-
462
- const testsDir = path.join(tempDir, "tests");
463
- expect(fs.existsSync(testsDir)).toBe(true);
464
-
465
- const delegationTestPath = path.join(testsDir, "delegation.test.ts");
466
- expect(fs.existsSync(delegationTestPath)).toBe(true);
467
-
468
- const delegationTestContent = fs.readFileSync(
469
- delegationTestPath,
470
- "utf-8"
471
- );
472
- expect(delegationTestContent).toContain("Delegation Management");
473
- expect(delegationTestContent).toContain("describe");
474
- });
475
-
476
- it("should create README with project name", async () => {
477
- await fetchCloudflareMcpiTemplate(tempDir, {
478
- packageManager: "npm",
479
- projectName: "my-awesome-project",
480
- });
481
-
482
- const readmePath = path.join(tempDir, "README.md");
483
- const readmeContent = fs.readFileSync(readmePath, "utf-8");
484
-
485
- expect(readmeContent).toContain("my-awesome-project");
486
- expect(readmeContent).toContain("Quick Start");
487
- expect(readmeContent).toContain("Features");
488
- });
489
- });
490
- });