@kya-os/create-mcpi-app 1.7.38-canary.2 → 1.7.39-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-test$colon$coverage.log +378 -0
- package/.turbo/turbo-test.log +164 -0
- package/dist/helpers/config-builder.d.ts +4 -10
- package/dist/helpers/config-builder.d.ts.map +1 -1
- package/dist/helpers/config-builder.js +7 -64
- package/dist/helpers/config-builder.js.map +1 -1
- package/dist/helpers/fetch-cloudflare-mcpi-template.d.ts.map +1 -1
- package/dist/helpers/fetch-cloudflare-mcpi-template.js +35 -914
- package/dist/helpers/fetch-cloudflare-mcpi-template.js.map +1 -1
- package/dist/utils/fetch-remote-config.d.ts.map +1 -1
- package/dist/utils/fetch-remote-config.js +2 -2
- package/dist/utils/fetch-remote-config.js.map +1 -1
- package/package/package.json +77 -0
- package/package.json +5 -3
- package/ARCHITECTURE_ANALYSIS.md +0 -392
- package/CHANGELOG.md +0 -372
- package/DEPRECATION_WARNINGS_ANALYSIS.md +0 -192
- package/IMPLEMENTATION_SUMMARY.md +0 -108
- package/REMEDIATION_PLAN.md +0 -99
- package/dist/.tsbuildinfo +0 -1
- package/scripts/prepare-pack.js +0 -47
- package/scripts/validate-no-workspace.js +0 -79
- package/src/__tests__/cloudflare-template.test.ts +0 -490
- package/src/__tests__/helpers/fetch-cloudflare-mcpi-template.test.ts +0 -337
- package/src/__tests__/helpers/generate-config.test.ts +0 -312
- package/src/__tests__/helpers/generate-identity.test.ts +0 -271
- package/src/__tests__/helpers/install.test.ts +0 -370
- package/src/__tests__/helpers/validate-project-structure.test.ts +0 -467
- package/src/__tests__.bak/regression.test.ts +0 -434
- package/src/effects/index.ts +0 -80
- package/src/helpers/__tests__/config-builder.spec.ts +0 -231
- package/src/helpers/apply-identity-preset.ts +0 -209
- package/src/helpers/config-builder.ts +0 -165
- package/src/helpers/copy-template.ts +0 -11
- package/src/helpers/create.ts +0 -239
- package/src/helpers/fetch-cloudflare-mcpi-template.ts +0 -2404
- package/src/helpers/fetch-cloudflare-template.ts +0 -361
- package/src/helpers/fetch-mcpi-template.ts +0 -236
- package/src/helpers/fetch-xmcp-template.ts +0 -153
- package/src/helpers/generate-config.ts +0 -118
- package/src/helpers/generate-identity.ts +0 -163
- package/src/helpers/identity-manager.ts +0 -186
- package/src/helpers/install.ts +0 -79
- package/src/helpers/rename.ts +0 -17
- package/src/helpers/validate-project-structure.ts +0 -127
- package/src/index.ts +0 -520
- package/src/utils/__tests__/fetch-remote-config.test.ts +0 -271
- package/src/utils/check-node.ts +0 -17
- package/src/utils/fetch-remote-config.ts +0 -179
- package/src/utils/is-folder-empty.ts +0 -60
- package/src/utils/validate-project-name.ts +0 -132
- package/test-cloudflare/README.md +0 -164
- package/test-cloudflare/package.json +0 -28
- package/test-cloudflare/src/index.ts +0 -341
- package/test-cloudflare/src/tools/greet.ts +0 -19
- package/test-cloudflare/tests/cache-invalidation.test.ts +0 -410
- package/test-cloudflare/tests/cors-security.test.ts +0 -349
- package/test-cloudflare/tests/delegation.test.ts +0 -335
- package/test-cloudflare/tests/do-routing.test.ts +0 -314
- package/test-cloudflare/tests/integration.test.ts +0 -205
- package/test-cloudflare/tests/session-management.test.ts +0 -359
- package/test-cloudflare/tsconfig.json +0 -16
- package/test-cloudflare/vitest.config.ts +0 -9
- package/test-cloudflare/wrangler.toml +0 -37
- package/test-node/README.md +0 -44
- package/test-node/package.json +0 -23
- package/test-node/src/tools/greet.ts +0 -25
- package/test-node/xmcp.config.ts +0 -20
- package/tsconfig.json +0 -26
- 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
|
-
});
|