@kya-os/create-mcpi-app 1.7.38-canary.1 → 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.
- package/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-test$colon$coverage.log +755 -0
- package/.turbo/turbo-test.log +200 -0
- package/dist/helpers/fetch-cloudflare-mcpi-template.d.ts.map +1 -1
- package/dist/helpers/fetch-cloudflare-mcpi-template.js +43 -912
- 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 +1 -1
- 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 -2393
- 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,361 +0,0 @@
|
|
|
1
|
-
import fs from "fs-extra";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import chalk from "chalk";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
|
-
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = path.dirname(__filename);
|
|
8
|
-
|
|
9
|
-
interface CloudflareTemplateOptions {
|
|
10
|
-
verifierVersion?: string;
|
|
11
|
-
packageManager?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Scaffold Cloudflare Worker verifier project
|
|
16
|
-
* This creates a standalone Worker verifier with KV nonce caching
|
|
17
|
-
*/
|
|
18
|
-
export async function fetchCloudflareTemplate(
|
|
19
|
-
projectPath: string,
|
|
20
|
-
options: CloudflareTemplateOptions = {}
|
|
21
|
-
): Promise<void> {
|
|
22
|
-
const { verifierVersion = "^1.3.0", packageManager = "npm" } = options;
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
console.log(
|
|
26
|
-
chalk.blue(`📦 Setting up Cloudflare Worker verifier with @kya-os/verifier@${verifierVersion}...`)
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
// Create package.json for Cloudflare Worker
|
|
30
|
-
const packageJson = {
|
|
31
|
-
name: path.basename(projectPath),
|
|
32
|
-
version: "1.0.0",
|
|
33
|
-
type: "module",
|
|
34
|
-
private: true,
|
|
35
|
-
scripts: {
|
|
36
|
-
dev: "wrangler dev",
|
|
37
|
-
deploy: "wrangler deploy",
|
|
38
|
-
"deploy:production": "wrangler deploy --env production",
|
|
39
|
-
"kv:create": "wrangler kv namespace create NONCE_CACHE",
|
|
40
|
-
"kv:create:preview": "wrangler kv namespace create NONCE_CACHE --preview",
|
|
41
|
-
tail: "wrangler tail",
|
|
42
|
-
test: "vitest",
|
|
43
|
-
},
|
|
44
|
-
dependencies: {
|
|
45
|
-
"@kya-os/verifier": verifierVersion,
|
|
46
|
-
},
|
|
47
|
-
devDependencies: {
|
|
48
|
-
"@cloudflare/workers-types": "^4.20240925.0",
|
|
49
|
-
"@cloudflare/vitest-pool-workers": "^0.5.0",
|
|
50
|
-
typescript: "^5.6.2",
|
|
51
|
-
vitest: "^2.1.5",
|
|
52
|
-
wrangler: "^4.42.2",
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
// Write package.json
|
|
57
|
-
fs.ensureDirSync(projectPath);
|
|
58
|
-
fs.writeJsonSync(path.join(projectPath, "package.json"), packageJson, { spaces: 2 });
|
|
59
|
-
|
|
60
|
-
// Create src directory
|
|
61
|
-
const srcDir = path.join(projectPath, "src");
|
|
62
|
-
fs.ensureDirSync(srcDir);
|
|
63
|
-
|
|
64
|
-
// Create Worker implementation
|
|
65
|
-
const workerContent = `import {
|
|
66
|
-
verifyWorker,
|
|
67
|
-
applyVerificationToResponse,
|
|
68
|
-
createConfigFromEnv,
|
|
69
|
-
type WorkerEnv,
|
|
70
|
-
} from "@kya-os/verifier/worker";
|
|
71
|
-
|
|
72
|
-
export default {
|
|
73
|
-
async fetch(request: Request, env: WorkerEnv): Promise<Response> {
|
|
74
|
-
const url = new URL(request.url);
|
|
75
|
-
|
|
76
|
-
// Health check endpoint
|
|
77
|
-
if (url.pathname === "/health") {
|
|
78
|
-
return new Response(
|
|
79
|
-
JSON.stringify({
|
|
80
|
-
status: "healthy",
|
|
81
|
-
timestamp: new Date().toISOString(),
|
|
82
|
-
}),
|
|
83
|
-
{
|
|
84
|
-
headers: { "Content-Type": "application/json" },
|
|
85
|
-
}
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Verification endpoint
|
|
90
|
-
if (url.pathname === "/verify") {
|
|
91
|
-
// Create config from environment variables
|
|
92
|
-
const config = createConfigFromEnv(env, {
|
|
93
|
-
allowMockData: false,
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// Verify the proof
|
|
97
|
-
const result = await verifyWorker(request, config);
|
|
98
|
-
|
|
99
|
-
// If verification failed, return error response
|
|
100
|
-
if (!result.success) {
|
|
101
|
-
return applyVerificationToResponse(result);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Success - extract agent context
|
|
105
|
-
const agent = result.agentContext;
|
|
106
|
-
|
|
107
|
-
// Check required scopes (example)
|
|
108
|
-
const requiredScopes = ["cart:add", "checkout"];
|
|
109
|
-
const hasRequiredScope = requiredScopes.some((scope) =>
|
|
110
|
-
agent?.scopes?.includes(scope)
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
if (!hasRequiredScope) {
|
|
114
|
-
return new Response(
|
|
115
|
-
JSON.stringify({
|
|
116
|
-
verified: false,
|
|
117
|
-
error: "Insufficient permissions",
|
|
118
|
-
requiredScopes,
|
|
119
|
-
providedScopes: agent?.scopes || [],
|
|
120
|
-
}),
|
|
121
|
-
{
|
|
122
|
-
status: 403,
|
|
123
|
-
headers: { "Content-Type": "application/json" },
|
|
124
|
-
}
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Success response with agent context
|
|
129
|
-
return new Response(
|
|
130
|
-
JSON.stringify({
|
|
131
|
-
verified: true,
|
|
132
|
-
agent: {
|
|
133
|
-
did: agent?.did,
|
|
134
|
-
kid: agent?.kid,
|
|
135
|
-
scopes: agent?.scopes,
|
|
136
|
-
session: agent?.session,
|
|
137
|
-
},
|
|
138
|
-
timestamp: new Date().toISOString(),
|
|
139
|
-
}),
|
|
140
|
-
{
|
|
141
|
-
headers: { "Content-Type": "application/json" },
|
|
142
|
-
}
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return new Response("Not Found", { status: 404 });
|
|
147
|
-
},
|
|
148
|
-
};
|
|
149
|
-
`;
|
|
150
|
-
fs.writeFileSync(path.join(srcDir, "index.ts"), workerContent);
|
|
151
|
-
|
|
152
|
-
// Create wrangler.toml
|
|
153
|
-
const wranglerContent = `#:schema node_modules/wrangler/config-schema.json
|
|
154
|
-
name = "${path.basename(projectPath)}"
|
|
155
|
-
main = "src/index.ts"
|
|
156
|
-
compatibility_date = "2024-09-25"
|
|
157
|
-
node_compat = true
|
|
158
|
-
|
|
159
|
-
# KV Namespace for nonce cache
|
|
160
|
-
# Run: wrangler kv:namespace create NONCE_CACHE
|
|
161
|
-
# Then replace the id below with the output
|
|
162
|
-
[[kv_namespaces]]
|
|
163
|
-
binding = "NONCE_CACHE"
|
|
164
|
-
id = "YOUR_KV_NAMESPACE_ID"
|
|
165
|
-
|
|
166
|
-
# Environment variables (non-sensitive)
|
|
167
|
-
[vars]
|
|
168
|
-
KYA_API_URL = "https://knowthat.ai"
|
|
169
|
-
XMCP_I_TS_SKEW_SEC = "120"
|
|
170
|
-
XMCP_I_SESSION_TTL = "1800"
|
|
171
|
-
|
|
172
|
-
# Production environment
|
|
173
|
-
[env.production]
|
|
174
|
-
name = "${path.basename(projectPath)}-production"
|
|
175
|
-
vars = { KYA_API_URL = "https://knowthat.ai", XMCP_I_TS_SKEW_SEC = "60" }
|
|
176
|
-
|
|
177
|
-
[[env.production.kv_namespaces]]
|
|
178
|
-
binding = "NONCE_CACHE"
|
|
179
|
-
id = "YOUR_PRODUCTION_KV_NAMESPACE_ID"
|
|
180
|
-
`;
|
|
181
|
-
fs.writeFileSync(path.join(projectPath, "wrangler.toml"), wranglerContent);
|
|
182
|
-
|
|
183
|
-
// Create tsconfig.json
|
|
184
|
-
const tsconfigContent = {
|
|
185
|
-
compilerOptions: {
|
|
186
|
-
target: "ES2022",
|
|
187
|
-
module: "ES2022",
|
|
188
|
-
lib: ["ES2022"],
|
|
189
|
-
types: ["@cloudflare/workers-types"],
|
|
190
|
-
moduleResolution: "bundler",
|
|
191
|
-
resolveJsonModule: true,
|
|
192
|
-
allowSyntheticDefaultImports: true,
|
|
193
|
-
esModuleInterop: true,
|
|
194
|
-
strict: true,
|
|
195
|
-
skipLibCheck: true,
|
|
196
|
-
forceConsistentCasingInFileNames: true,
|
|
197
|
-
},
|
|
198
|
-
include: ["src/**/*"],
|
|
199
|
-
};
|
|
200
|
-
fs.writeJsonSync(path.join(projectPath, "tsconfig.json"), tsconfigContent, { spaces: 2 });
|
|
201
|
-
|
|
202
|
-
// Create .gitignore
|
|
203
|
-
const gitignoreContent = `node_modules/
|
|
204
|
-
dist/
|
|
205
|
-
.wrangler/
|
|
206
|
-
.dev.vars
|
|
207
|
-
.env
|
|
208
|
-
.env.local
|
|
209
|
-
*.log
|
|
210
|
-
`;
|
|
211
|
-
fs.writeFileSync(path.join(projectPath, ".gitignore"), gitignoreContent);
|
|
212
|
-
|
|
213
|
-
// Create README.md
|
|
214
|
-
const readmeContent = `# ${path.basename(projectPath)}
|
|
215
|
-
|
|
216
|
-
MCP-I proof verifier deployed on Cloudflare Workers with KV nonce caching.
|
|
217
|
-
|
|
218
|
-
## Quick Start
|
|
219
|
-
|
|
220
|
-
### 1. Install Dependencies
|
|
221
|
-
|
|
222
|
-
\`\`\`bash
|
|
223
|
-
${packageManager} install
|
|
224
|
-
\`\`\`
|
|
225
|
-
|
|
226
|
-
### 2. Create KV Namespace
|
|
227
|
-
|
|
228
|
-
\`\`\`bash
|
|
229
|
-
${packageManager === "npm" ? "npm run" : packageManager} kv:create
|
|
230
|
-
\`\`\`
|
|
231
|
-
|
|
232
|
-
Copy the \`id\` from the output and update \`wrangler.toml\`:
|
|
233
|
-
|
|
234
|
-
\`\`\`toml
|
|
235
|
-
[[kv_namespaces]]
|
|
236
|
-
binding = "NONCE_CACHE"
|
|
237
|
-
id = "your-kv-namespace-id-here" # ← Update this
|
|
238
|
-
\`\`\`
|
|
239
|
-
|
|
240
|
-
### 3. Test Locally
|
|
241
|
-
|
|
242
|
-
\`\`\`bash
|
|
243
|
-
${packageManager === "npm" ? "npm run" : packageManager} dev
|
|
244
|
-
\`\`\`
|
|
245
|
-
|
|
246
|
-
Visit http://localhost:8787/health to verify it's running.
|
|
247
|
-
|
|
248
|
-
### 4. Deploy to Cloudflare
|
|
249
|
-
|
|
250
|
-
\`\`\`bash
|
|
251
|
-
# Login to Cloudflare (first time only)
|
|
252
|
-
npx wrangler login
|
|
253
|
-
|
|
254
|
-
# Deploy to development
|
|
255
|
-
${packageManager === "npm" ? "npm run" : packageManager} deploy
|
|
256
|
-
|
|
257
|
-
# Deploy to production
|
|
258
|
-
${packageManager === "npm" ? "npm run" : packageManager} deploy:production
|
|
259
|
-
\`\`\`
|
|
260
|
-
|
|
261
|
-
## API Endpoints
|
|
262
|
-
|
|
263
|
-
### \`GET /health\`
|
|
264
|
-
Health check endpoint.
|
|
265
|
-
|
|
266
|
-
**Response:**
|
|
267
|
-
\`\`\`json
|
|
268
|
-
{
|
|
269
|
-
"status": "healthy",
|
|
270
|
-
"timestamp": "2024-10-09T12:00:00.000Z"
|
|
271
|
-
}
|
|
272
|
-
\`\`\`
|
|
273
|
-
|
|
274
|
-
### \`POST /verify\`
|
|
275
|
-
Verify MCP-I cryptographic proof.
|
|
276
|
-
|
|
277
|
-
**Request:**
|
|
278
|
-
\`\`\`json
|
|
279
|
-
{
|
|
280
|
-
"proof": {
|
|
281
|
-
"agentDid": "did:web:example.com",
|
|
282
|
-
"timestamp": 1234567890,
|
|
283
|
-
"nonce": "abc123",
|
|
284
|
-
"signature": "...",
|
|
285
|
-
"publicKey": "..."
|
|
286
|
-
},
|
|
287
|
-
"requiredScopes": ["cart:add"]
|
|
288
|
-
}
|
|
289
|
-
\`\`\`
|
|
290
|
-
|
|
291
|
-
**Response (Success):**
|
|
292
|
-
\`\`\`json
|
|
293
|
-
{
|
|
294
|
-
"verified": true,
|
|
295
|
-
"agentDid": "did:web:example.com",
|
|
296
|
-
"timestamp": "2024-10-09T12:00:00.000Z"
|
|
297
|
-
}
|
|
298
|
-
\`\`\`
|
|
299
|
-
|
|
300
|
-
**Response (Failed):**
|
|
301
|
-
\`\`\`json
|
|
302
|
-
{
|
|
303
|
-
"verified": false,
|
|
304
|
-
"error": "Invalid signature"
|
|
305
|
-
}
|
|
306
|
-
\`\`\`
|
|
307
|
-
|
|
308
|
-
## Configuration
|
|
309
|
-
|
|
310
|
-
### Environment Variables (wrangler.toml)
|
|
311
|
-
|
|
312
|
-
- \`KYA_API_URL\` - KYA API endpoint (default: https://knowthat.ai)
|
|
313
|
-
- \`XMCP_I_TS_SKEW_SEC\` - Clock skew tolerance in seconds (default: 120)
|
|
314
|
-
- \`XMCP_I_SESSION_TTL\` - Session timeout in seconds (default: 1800)
|
|
315
|
-
|
|
316
|
-
### KV Namespace
|
|
317
|
-
|
|
318
|
-
The Worker uses Cloudflare KV for distributed nonce caching to prevent replay attacks.
|
|
319
|
-
|
|
320
|
-
Create separate namespaces for development and production:
|
|
321
|
-
|
|
322
|
-
\`\`\`bash
|
|
323
|
-
# Development
|
|
324
|
-
${packageManager === "npm" ? "npm run" : packageManager} kv:create
|
|
325
|
-
|
|
326
|
-
# Production (after deploying once)
|
|
327
|
-
wrangler kv:namespace create NONCE_CACHE --env production
|
|
328
|
-
\`\`\`
|
|
329
|
-
|
|
330
|
-
## Testing
|
|
331
|
-
|
|
332
|
-
Send a test request:
|
|
333
|
-
|
|
334
|
-
\`\`\`bash
|
|
335
|
-
curl -X POST https://your-worker.workers.dev/verify \\
|
|
336
|
-
-H "Content-Type: application/json" \\
|
|
337
|
-
-d '{
|
|
338
|
-
"proof": {
|
|
339
|
-
"agentDid": "did:web:example.com",
|
|
340
|
-
"timestamp": 1234567890,
|
|
341
|
-
"nonce": "test123",
|
|
342
|
-
"signature": "...",
|
|
343
|
-
"publicKey": "..."
|
|
344
|
-
}
|
|
345
|
-
}'
|
|
346
|
-
\`\`\`
|
|
347
|
-
|
|
348
|
-
## Learn More
|
|
349
|
-
|
|
350
|
-
- [MCP-I Documentation](https://github.com/kya-os/xmcp-i)
|
|
351
|
-
- [Cloudflare Workers Docs](https://developers.cloudflare.com/workers/)
|
|
352
|
-
- [Cloudflare KV Docs](https://developers.cloudflare.com/kv/)
|
|
353
|
-
`;
|
|
354
|
-
fs.writeFileSync(path.join(projectPath, "README.md"), readmeContent);
|
|
355
|
-
|
|
356
|
-
console.log(chalk.green("✅ Cloudflare Worker verifier structure created"));
|
|
357
|
-
} catch (error) {
|
|
358
|
-
console.error(chalk.red("Failed to set up Cloudflare Worker verifier:"), error);
|
|
359
|
-
throw error;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import { execSync } from "child_process";
|
|
2
|
-
import fs from "fs-extra";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import os from "os";
|
|
5
|
-
import chalk from "chalk";
|
|
6
|
-
import { generateIdentity } from "./generate-identity.js";
|
|
7
|
-
|
|
8
|
-
interface ScaffoldTemplateOptions {
|
|
9
|
-
mcpiVersion?: string;
|
|
10
|
-
packageManager?: string;
|
|
11
|
-
skipIdentity?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Scaffold MCP-I project using @kya-os/mcp-i package
|
|
16
|
-
* This creates a standalone MCP server with built-in identity features
|
|
17
|
-
*/
|
|
18
|
-
export async function fetchMCPITemplate(
|
|
19
|
-
projectPath: string,
|
|
20
|
-
options: ScaffoldTemplateOptions = {}
|
|
21
|
-
): Promise<void> {
|
|
22
|
-
const {
|
|
23
|
-
mcpiVersion = "^1.3.2",
|
|
24
|
-
packageManager = "npm",
|
|
25
|
-
skipIdentity = false,
|
|
26
|
-
} = options;
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
console.log(
|
|
30
|
-
chalk.blue(
|
|
31
|
-
`📦 Setting up MCP-I project with @kya-os/mcp-i@${mcpiVersion}...`
|
|
32
|
-
)
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
// Create package.json matching our working test-mcpi structure
|
|
36
|
-
const packageJson = {
|
|
37
|
-
name: path.basename(projectPath),
|
|
38
|
-
version: "0.1.0",
|
|
39
|
-
dependencies: {
|
|
40
|
-
"@kya-os/cli": "^1.2.7",
|
|
41
|
-
"@kya-os/mcp-i": mcpiVersion,
|
|
42
|
-
zod: "^3.24.4",
|
|
43
|
-
},
|
|
44
|
-
scripts: {
|
|
45
|
-
dev: "mcpi dev",
|
|
46
|
-
build: "mcpi build",
|
|
47
|
-
start: "mcpi start",
|
|
48
|
-
init: "mcpi init",
|
|
49
|
-
register: "mcpi register",
|
|
50
|
-
"keys:rotate": "mcpi rotate",
|
|
51
|
-
"identity:clean": "rm -rf .mcpi",
|
|
52
|
-
status: "mcpi status",
|
|
53
|
-
},
|
|
54
|
-
devDependencies: {
|
|
55
|
-
"@modelcontextprotocol/inspector": "^0.16.6",
|
|
56
|
-
"swc-loader": "^0.2.6",
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
// Write package.json
|
|
61
|
-
fs.ensureDirSync(projectPath);
|
|
62
|
-
fs.writeJsonSync(path.join(projectPath, "package.json"), packageJson, {
|
|
63
|
-
spaces: 2,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Create basic MCP-I project structure
|
|
67
|
-
const srcDir = path.join(projectPath, "src");
|
|
68
|
-
const toolsDir = path.join(srcDir, "tools");
|
|
69
|
-
|
|
70
|
-
// Create required directories
|
|
71
|
-
fs.ensureDirSync(toolsDir);
|
|
72
|
-
|
|
73
|
-
// Optional directories (not created by default - users can add as needed)
|
|
74
|
-
// These are typically only needed for:
|
|
75
|
-
// - scenarios/: Demo/testing scenarios (like bouncer-demo)
|
|
76
|
-
// - lib/: Shared utilities (if project grows complex)
|
|
77
|
-
// - scripts/: Build/utility scripts (if needed)
|
|
78
|
-
// - docs/: Documentation (if maintaining separate docs)
|
|
79
|
-
|
|
80
|
-
// Create a basic greet tool (MCP-I default)
|
|
81
|
-
// CRITICAL: Import from @kya-os/mcp-i (not xmcp)
|
|
82
|
-
const greetToolContent = `import { z } from "zod";
|
|
83
|
-
import { type InferSchema, type ToolMetadata } from "@kya-os/mcp-i";
|
|
84
|
-
|
|
85
|
-
// Define the schema for tool parameters
|
|
86
|
-
export const schema = {
|
|
87
|
-
name: z.string().describe("The name of the user to greet"),
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
// Define tool metadata
|
|
91
|
-
export const metadata: ToolMetadata = {
|
|
92
|
-
name: "greet",
|
|
93
|
-
description: "Greet the user",
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
// Tool implementation
|
|
97
|
-
export default async function greet({ name }: InferSchema<typeof schema>) {
|
|
98
|
-
return {
|
|
99
|
-
content: [
|
|
100
|
-
{
|
|
101
|
-
type: "text" as const,
|
|
102
|
-
text: \`Hello, \${name}!\`,
|
|
103
|
-
},
|
|
104
|
-
],
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
`;
|
|
108
|
-
|
|
109
|
-
fs.writeFileSync(path.join(toolsDir, "greet.ts"), greetToolContent);
|
|
110
|
-
|
|
111
|
-
// IMPORTANT: DO NOT create tools/index.ts
|
|
112
|
-
// This would cause duplicate tool registration in webpack bundling
|
|
113
|
-
|
|
114
|
-
// Create xmcp.config.ts with identity features enabled (matching test-mcpi)
|
|
115
|
-
const configContent = `import type { XmcpConfig } from "@kya-os/mcp-i";
|
|
116
|
-
|
|
117
|
-
const config: XmcpConfig = {
|
|
118
|
-
// Point to the tools directory
|
|
119
|
-
paths: {
|
|
120
|
-
tools: "./src/tools",
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
// Enable MCP-I identity features
|
|
124
|
-
identity: {
|
|
125
|
-
enabled: true,
|
|
126
|
-
environment: "development",
|
|
127
|
-
debug: true,
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
// Enable STDIO transport for Claude Desktop
|
|
131
|
-
stdio: true,
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
export default config;
|
|
135
|
-
`;
|
|
136
|
-
fs.writeFileSync(path.join(projectPath, "xmcp.config.ts"), configContent);
|
|
137
|
-
|
|
138
|
-
// Create .gitignore
|
|
139
|
-
const gitignoreContent = `node_modules/
|
|
140
|
-
dist/
|
|
141
|
-
.env
|
|
142
|
-
.env.local
|
|
143
|
-
.mcpi/
|
|
144
|
-
`;
|
|
145
|
-
fs.writeFileSync(path.join(projectPath, ".gitignore"), gitignoreContent);
|
|
146
|
-
|
|
147
|
-
// Create README.md with quick start instructions
|
|
148
|
-
const readmeContent = `# ${path.basename(projectPath)}
|
|
149
|
-
|
|
150
|
-
MCP-I server with cryptographic identity built-in.
|
|
151
|
-
|
|
152
|
-
## Getting Started
|
|
153
|
-
|
|
154
|
-
1. Install dependencies:
|
|
155
|
-
\`\`\`bash
|
|
156
|
-
npm install
|
|
157
|
-
\`\`\`
|
|
158
|
-
|
|
159
|
-
2. Initialize identity (generates cryptographic keys):
|
|
160
|
-
\`\`\`bash
|
|
161
|
-
npm run init
|
|
162
|
-
\`\`\`
|
|
163
|
-
|
|
164
|
-
3. Start development server:
|
|
165
|
-
\`\`\`bash
|
|
166
|
-
npm run dev
|
|
167
|
-
\`\`\`
|
|
168
|
-
|
|
169
|
-
## Scripts
|
|
170
|
-
|
|
171
|
-
- \`npm run dev\` - Start development server with hot reload
|
|
172
|
-
- \`npm run build\` - Build production bundle
|
|
173
|
-
- \`npm run start\` - Start production server
|
|
174
|
-
- \`npm run init\` - Initialize agent identity
|
|
175
|
-
- \`npm run status\` - Check identity and server status
|
|
176
|
-
- \`npm run keys:rotate\` - Rotate cryptographic keys
|
|
177
|
-
|
|
178
|
-
## Project Structure
|
|
179
|
-
|
|
180
|
-
\`\`\`
|
|
181
|
-
├── src/
|
|
182
|
-
│ └── tools/ # MCP tools
|
|
183
|
-
│ └── greet.ts # Example tool
|
|
184
|
-
├── xmcp.config.ts # MCP-I configuration
|
|
185
|
-
└── .mcpi/ # Identity files (git-ignored)
|
|
186
|
-
\`\`\`
|
|
187
|
-
|
|
188
|
-
**Optional directories** (add as needed):
|
|
189
|
-
- \`src/scenarios/\` - Demo/testing scenarios
|
|
190
|
-
- \`src/lib/\` - Shared utilities
|
|
191
|
-
- \`scripts/\` - Build/utility scripts
|
|
192
|
-
- \`docs/\` - Documentation
|
|
193
|
-
|
|
194
|
-
## Learn More
|
|
195
|
-
|
|
196
|
-
- [MCP-I Documentation](https://github.com/modelcontextprotocol-identity/mcp-i)
|
|
197
|
-
- [Model Context Protocol](https://modelcontextprotocol.io)
|
|
198
|
-
`;
|
|
199
|
-
fs.writeFileSync(path.join(projectPath, "README.md"), readmeContent);
|
|
200
|
-
|
|
201
|
-
console.log(chalk.green("✅ MCP-I project structure created"));
|
|
202
|
-
|
|
203
|
-
// Generate persistent identity for Node.js MCP-I server
|
|
204
|
-
if (!skipIdentity) {
|
|
205
|
-
console.log(chalk.cyan("🔐 Generating persistent identity..."));
|
|
206
|
-
try {
|
|
207
|
-
const identity = await generateIdentity();
|
|
208
|
-
|
|
209
|
-
// Create .mcpi directory
|
|
210
|
-
const mcpiDir = path.join(projectPath, ".mcpi");
|
|
211
|
-
fs.ensureDirSync(mcpiDir);
|
|
212
|
-
|
|
213
|
-
// Save identity to .mcpi/identity.json
|
|
214
|
-
const identityPath = path.join(mcpiDir, "identity.json");
|
|
215
|
-
fs.writeJsonSync(identityPath, identity, { spaces: 2 });
|
|
216
|
-
|
|
217
|
-
console.log(chalk.green("✅ Generated persistent identity"));
|
|
218
|
-
console.log(chalk.dim(` DID: ${identity.did}`));
|
|
219
|
-
console.log(chalk.dim(` Saved to: .mcpi/identity.json`));
|
|
220
|
-
} catch (error: any) {
|
|
221
|
-
console.log(
|
|
222
|
-
chalk.yellow("⚠️ Failed to generate identity:"),
|
|
223
|
-
error.message
|
|
224
|
-
);
|
|
225
|
-
console.log(
|
|
226
|
-
chalk.dim(
|
|
227
|
-
" You can generate identity later by running: npm run init"
|
|
228
|
-
)
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
} catch (error) {
|
|
233
|
-
console.error(chalk.red("Failed to set up MCP-I project:"), error);
|
|
234
|
-
throw error;
|
|
235
|
-
}
|
|
236
|
-
}
|