@kya-os/create-mcpi-app 1.3.5-canary.1 → 1.3.5-canary.11
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/dist/.tsbuildinfo +1 -1
- package/dist/helpers/create.d.ts +1 -0
- package/dist/helpers/create.d.ts.map +1 -1
- package/dist/helpers/create.js +2 -1
- package/dist/helpers/create.js.map +1 -1
- package/dist/helpers/fetch-cloudflare-mcpi-template.d.ts +1 -0
- package/dist/helpers/fetch-cloudflare-mcpi-template.d.ts.map +1 -1
- package/dist/helpers/fetch-cloudflare-mcpi-template.js +560 -59
- package/dist/helpers/fetch-cloudflare-mcpi-template.js.map +1 -1
- package/dist/helpers/fetch-cloudflare-template.js +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ import chalk from "chalk";
|
|
|
6
6
|
* Uses McpAgent from agents/mcp for MCP protocol support
|
|
7
7
|
*/
|
|
8
8
|
export async function fetchCloudflareMcpiTemplate(projectPath, options = {}) {
|
|
9
|
-
const { packageManager = "npm", projectName = path.basename(projectPath) } = options;
|
|
9
|
+
const { packageManager = "npm", projectName = path.basename(projectPath), apikey } = options;
|
|
10
10
|
// Sanitize project name for class names
|
|
11
11
|
const className = projectName
|
|
12
12
|
.replace(/[^a-zA-Z0-9]/g, "")
|
|
@@ -23,16 +23,31 @@ export async function fetchCloudflareMcpiTemplate(projectPath, options = {}) {
|
|
|
23
23
|
deploy: "wrangler deploy",
|
|
24
24
|
dev: "wrangler dev",
|
|
25
25
|
start: "wrangler dev",
|
|
26
|
-
"kv:create": "npm run kv:create-nonce && npm run kv:create-proof",
|
|
27
|
-
"kv:create-nonce": `wrangler kv namespace create
|
|
28
|
-
"kv:create-proof": `wrangler kv namespace create
|
|
29
|
-
"kv:
|
|
30
|
-
"kv:
|
|
26
|
+
"kv:create": "npm run kv:create-nonce && npm run kv:create-proof && npm run kv:create-identity && npm run kv:create-delegation && npm run kv:create-tool-protection",
|
|
27
|
+
"kv:create-nonce": `wrangler kv namespace create ${className.toUpperCase()}_NONCE_CACHE`,
|
|
28
|
+
"kv:create-proof": `wrangler kv namespace create ${className.toUpperCase()}_PROOF_ARCHIVE`,
|
|
29
|
+
"kv:create-identity": `wrangler kv namespace create ${className.toUpperCase()}_IDENTITY_STORAGE`,
|
|
30
|
+
"kv:create-delegation": `wrangler kv namespace create ${className.toUpperCase()}_DELEGATION_STORAGE`,
|
|
31
|
+
"kv:create-tool-protection": `wrangler kv namespace create ${className.toUpperCase()}_TOOL_PROTECTION_KV`,
|
|
32
|
+
"kv:list": "wrangler kv namespace list | grep -E '(NONCE|PROOF|IDENTITY|DELEGATION|TOOL_PROTECTION|MCPI)' || wrangler kv namespace list",
|
|
33
|
+
"kv:keys-nonce": `wrangler kv key list --binding=${className.toUpperCase()}_NONCE_CACHE`,
|
|
34
|
+
"kv:keys-proof": `wrangler kv key list --binding=${className.toUpperCase()}_PROOF_ARCHIVE`,
|
|
35
|
+
"kv:keys-identity": `wrangler kv key list --binding=${className.toUpperCase()}_IDENTITY_STORAGE`,
|
|
36
|
+
"kv:keys-delegation": `wrangler kv key list --binding=${className.toUpperCase()}_DELEGATION_STORAGE`,
|
|
37
|
+
"kv:keys-tool-protection": `wrangler kv key list --binding=${className.toUpperCase()}_TOOL_PROTECTION_KV`,
|
|
38
|
+
"kv:delete-nonce": `wrangler kv namespace delete --binding=${className.toUpperCase()}_NONCE_CACHE`,
|
|
39
|
+
"kv:delete-proof": `wrangler kv namespace delete --binding=${className.toUpperCase()}_PROOF_ARCHIVE`,
|
|
40
|
+
"kv:delete-identity": `wrangler kv namespace delete --binding=${className.toUpperCase()}_IDENTITY_STORAGE`,
|
|
41
|
+
"kv:delete-delegation": `wrangler kv namespace delete --binding=${className.toUpperCase()}_DELEGATION_STORAGE`,
|
|
42
|
+
"kv:delete-tool-protection": `wrangler kv namespace delete --binding=${className.toUpperCase()}_TOOL_PROTECTION_KV`,
|
|
43
|
+
"kv:delete": "npm run kv:delete-nonce && npm run kv:delete-proof && npm run kv:delete-identity && npm run kv:delete-delegation && npm run kv:delete-tool-protection",
|
|
44
|
+
"kv:reset": "npm run kv:delete && npm run kv:create",
|
|
45
|
+
"kv:setup": "echo 'KV Commands: kv:create (create all), kv:list (list all), kv:keys-* (view keys), kv:delete (delete all), kv:reset (delete+recreate)'",
|
|
31
46
|
"cf-typegen": "wrangler types",
|
|
32
47
|
"type-check": "tsc --noEmit",
|
|
33
48
|
},
|
|
34
49
|
dependencies: {
|
|
35
|
-
"@kya-os/mcp-i-cloudflare": "
|
|
50
|
+
"@kya-os/mcp-i-cloudflare": "1.2.3-canary.8",
|
|
36
51
|
"@modelcontextprotocol/sdk": "^1.19.1",
|
|
37
52
|
"agents": "^0.2.8",
|
|
38
53
|
"hono": "^4.9.10",
|
|
@@ -53,6 +68,31 @@ export async function fetchCloudflareMcpiTemplate(projectPath, options = {}) {
|
|
|
53
68
|
// Create greet tool
|
|
54
69
|
const greetToolContent = `import { z } from "zod";
|
|
55
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Greet Tool - Example MCP tool with AgentShield integration
|
|
73
|
+
*
|
|
74
|
+
* This tool demonstrates proper scopeId configuration for tool auto-discovery.
|
|
75
|
+
*
|
|
76
|
+
* Configure the corresponding scope in mcpi-runtime-config.ts:
|
|
77
|
+
* \`\`\`typescript
|
|
78
|
+
* toolProtections: {
|
|
79
|
+
* greet: {
|
|
80
|
+
* requiresDelegation: false,
|
|
81
|
+
* requiredScopes: ["greet:execute"], // ← This becomes the scopeId in proofs
|
|
82
|
+
* }
|
|
83
|
+
* }
|
|
84
|
+
* \`\`\`
|
|
85
|
+
*
|
|
86
|
+
* The scopeId format is "toolName:action":
|
|
87
|
+
* - Tool name: "greet" (extracted before the ":")
|
|
88
|
+
* - Action: "execute" (extracted after the ":")
|
|
89
|
+
* - Risk level: Auto-determined from action keyword (execute = high)
|
|
90
|
+
*
|
|
91
|
+
* Other scopeId examples:
|
|
92
|
+
* - "files:read" → Medium risk
|
|
93
|
+
* - "files:write" → High risk
|
|
94
|
+
* - "database:delete" → Critical risk
|
|
95
|
+
*/
|
|
56
96
|
export const greetTool = {
|
|
57
97
|
name: "greet",
|
|
58
98
|
description: "Greet a user by name",
|
|
@@ -72,13 +112,166 @@ export const greetTool = {
|
|
|
72
112
|
};
|
|
73
113
|
`;
|
|
74
114
|
fs.writeFileSync(path.join(toolsDir, "greet.ts"), greetToolContent);
|
|
115
|
+
// Create mcpi-runtime-config.ts for AgentShield integration
|
|
116
|
+
const runtimeConfigContent = `import type { MCPIRuntimeConfig } from "@kya-os/mcp-i-cloudflare";
|
|
117
|
+
${apikey ? 'import { CloudflareRuntime } from "@kya-os/mcp-i-cloudflare"; // Auto-enabled: Tool Protection Service' : '// import { CloudflareRuntime } from "@kya-os/mcp-i-cloudflare"; // Uncomment to enable Tool Protection Service'}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Runtime configuration for MCP-I server
|
|
121
|
+
*
|
|
122
|
+
* This file configures runtime features like proof submission to AgentShield,
|
|
123
|
+
* delegation verification, and audit logging.
|
|
124
|
+
*
|
|
125
|
+
* Environment variables are automatically injected from wrangler.toml (Cloudflare)
|
|
126
|
+
* or .env (Node.js). Configure them there:
|
|
127
|
+
* - AGENTSHIELD_API_URL: AgentShield API base URL
|
|
128
|
+
* - AGENTSHIELD_API_KEY: Your AgentShield API key
|
|
129
|
+
* - AGENTSHIELD_PROJECT_ID: Your AgentShield project ID
|
|
130
|
+
* - MCPI_ENV: "development" or "production"
|
|
131
|
+
*/
|
|
132
|
+
export function getRuntimeConfig(): MCPIRuntimeConfig {
|
|
133
|
+
const env = process.env;
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
// Identity configuration
|
|
137
|
+
identity: {
|
|
138
|
+
environment: (env.MCPI_ENV as "development" | "production") || "development",
|
|
139
|
+
devIdentityPath: ".mcpi/identity.json"
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
// Proof submission configuration
|
|
143
|
+
proofing: {
|
|
144
|
+
enabled: true,
|
|
145
|
+
batchQueue: {
|
|
146
|
+
destinations: [
|
|
147
|
+
{
|
|
148
|
+
type: "agentshield" as const,
|
|
149
|
+
apiUrl: env.AGENTSHIELD_API_URL || "https://kya.vouched.id",
|
|
150
|
+
apiKey: env.AGENTSHIELD_API_KEY || ""
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
maxBatchSize: 10,
|
|
154
|
+
flushIntervalMs: 5000,
|
|
155
|
+
maxRetries: 3,
|
|
156
|
+
debug: env.MCPI_ENV === "development"
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
// Delegation verification (AgentShield API)
|
|
161
|
+
delegation: {
|
|
162
|
+
enabled: true,
|
|
163
|
+
enforceDelegations: true, // ✅ NEW: Enable enforcement of delegation requirements
|
|
164
|
+
verifier: {
|
|
165
|
+
type: "agentshield-api",
|
|
166
|
+
agentshield: {
|
|
167
|
+
apiUrl: env.AGENTSHIELD_API_URL || "https://kya.vouched.id",
|
|
168
|
+
apiKey: env.AGENTSHIELD_API_KEY || ""
|
|
169
|
+
},
|
|
170
|
+
cacheTtl: 60000, // 1 minute cache
|
|
171
|
+
debug: env.MCPI_ENV === "development"
|
|
172
|
+
},
|
|
173
|
+
authorization: {
|
|
174
|
+
authorizationUrl: env.AUTHORIZATION_URL || \`\${env.AGENTSHIELD_API_URL}/authorize\`,
|
|
175
|
+
resumeTokenTtl: 600000, // 10 minutes
|
|
176
|
+
minReputationScore: 76
|
|
177
|
+
},
|
|
178
|
+
// ⚠️ DEPRECATED (if using dynamic tool protection):
|
|
179
|
+
// Tool protection rules - Configure scopes for auto-discovery in AgentShield
|
|
180
|
+
//
|
|
181
|
+
// NOTE: These are now managed via AgentShield dashboard and fetched dynamically
|
|
182
|
+
// when you enable the Tool Protection Service (see below). This fallback config
|
|
183
|
+
// is only used if:
|
|
184
|
+
// 1. Tool Protection Service is not configured, OR
|
|
185
|
+
// 2. AgentShield API is unavailable
|
|
186
|
+
toolProtections: {
|
|
187
|
+
// Example: Public tool with execution scope
|
|
188
|
+
greet: {
|
|
189
|
+
requiresDelegation: false, // No delegation needed for low-risk tool
|
|
190
|
+
requiredScopes: ["greet:execute"] // ✅ Enables tool discovery in AgentShield
|
|
191
|
+
}
|
|
192
|
+
// Add more tools as needed:
|
|
193
|
+
// High-risk tool requiring delegation:
|
|
194
|
+
// checkout: {
|
|
195
|
+
// requiresDelegation: true, // User must explicitly delegate
|
|
196
|
+
// requiredScopes: ["checkout:execute"] // Scope for tool discovery
|
|
197
|
+
// },
|
|
198
|
+
// delete_file: {
|
|
199
|
+
// requiresDelegation: true,
|
|
200
|
+
// requiredScopes: ["files:delete"] // Action-based scope for better categorization
|
|
201
|
+
// }
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
// 🆕 Dynamic Tool Protection Service (Dashboard-Controlled)
|
|
206
|
+
//
|
|
207
|
+
// When AgentShield API key is configured, tool delegation requirements
|
|
208
|
+
// are fetched from the dashboard in real-time (5-minute cache).
|
|
209
|
+
//
|
|
210
|
+
// Benefits:
|
|
211
|
+
// - Toggle "Require Delegation" for any tool in dashboard - no code changes
|
|
212
|
+
// - Changes apply in real-time (5-minute cache via KV)
|
|
213
|
+
// - Automatic tool discovery from proof submissions
|
|
214
|
+
//
|
|
215
|
+
// Performance: 1 API call per 5 minutes, all other requests use KV cache
|
|
216
|
+
${apikey ? `toolProtectionService: env.TOOL_PROTECTION_KV
|
|
217
|
+
? CloudflareRuntime.createToolProtectionService(
|
|
218
|
+
env.TOOL_PROTECTION_KV, // KV namespace from wrangler.toml
|
|
219
|
+
{
|
|
220
|
+
apiUrl: env.AGENTSHIELD_API_URL || "https://kya.vouched.id",
|
|
221
|
+
apiKey: env.AGENTSHIELD_API_KEY || "",
|
|
222
|
+
projectId: env.AGENTSHIELD_PROJECT_ID || "",
|
|
223
|
+
cacheTtl: 300000, // 5 minutes (in milliseconds)
|
|
224
|
+
debug: env.MCPI_ENV === "development",
|
|
225
|
+
// Fallback to local config if API unavailable
|
|
226
|
+
fallbackConfig: {
|
|
227
|
+
toolProtections: {
|
|
228
|
+
greet: {
|
|
229
|
+
requiresDelegation: false,
|
|
230
|
+
requiredScopes: ["greet:execute"],
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
}
|
|
235
|
+
)
|
|
236
|
+
: undefined,` : `// toolProtectionService: env.TOOL_PROTECTION_KV
|
|
237
|
+
// ? CloudflareRuntime.createToolProtectionService(
|
|
238
|
+
// env.TOOL_PROTECTION_KV,
|
|
239
|
+
// {
|
|
240
|
+
// apiUrl: env.AGENTSHIELD_API_URL || "https://kya.vouched.id",
|
|
241
|
+
// apiKey: env.AGENTSHIELD_API_KEY || "",
|
|
242
|
+
// projectId: env.AGENTSHIELD_PROJECT_ID || "",
|
|
243
|
+
// cacheTtl: 300000, // 5 minutes
|
|
244
|
+
// debug: env.MCPI_ENV === "development",
|
|
245
|
+
// fallbackConfig: {
|
|
246
|
+
// toolProtections: {
|
|
247
|
+
// greet: {
|
|
248
|
+
// requiresDelegation: false,
|
|
249
|
+
// requiredScopes: ["greet:execute"],
|
|
250
|
+
// },
|
|
251
|
+
// },
|
|
252
|
+
// },
|
|
253
|
+
// }
|
|
254
|
+
// )
|
|
255
|
+
// : undefined,`}
|
|
256
|
+
|
|
257
|
+
// Audit logging
|
|
258
|
+
audit: {
|
|
259
|
+
enabled: true
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export default getRuntimeConfig();
|
|
265
|
+
`;
|
|
266
|
+
fs.writeFileSync(path.join(srcDir, "mcpi-runtime-config.ts"), runtimeConfigContent);
|
|
75
267
|
// Create main index.ts using McpAgent with MCP-I runtime
|
|
76
268
|
const indexContent = `import { McpAgent } from "agents/mcp";
|
|
77
269
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
78
|
-
import { createCloudflareRuntime, type CloudflareEnv, KVProofArchive } from "@kya-os/mcp-i-cloudflare";
|
|
270
|
+
import { createCloudflareRuntime, type CloudflareEnv, KVProofArchive, type DetachedProof } from "@kya-os/mcp-i-cloudflare";
|
|
79
271
|
import { Hono } from "hono";
|
|
80
272
|
import { cors } from "hono/cors";
|
|
81
273
|
import { greetTool } from "./tools/greet";
|
|
274
|
+
import { getRuntimeConfig } from "./mcpi-runtime-config";
|
|
82
275
|
|
|
83
276
|
export class ${pascalClassName}MCP extends McpAgent {
|
|
84
277
|
server = new McpServer({
|
|
@@ -88,27 +281,136 @@ export class ${pascalClassName}MCP extends McpAgent {
|
|
|
88
281
|
|
|
89
282
|
private mcpiRuntime?: any;
|
|
90
283
|
private proofArchive?: KVProofArchive;
|
|
284
|
+
private agentShieldConfig?: { apiUrl: string; apiKey: string };
|
|
91
285
|
private env: CloudflareEnv;
|
|
92
286
|
|
|
93
287
|
constructor(state: DurableObjectState, env: CloudflareEnv) {
|
|
94
288
|
super(state, env);
|
|
95
289
|
this.env = env;
|
|
96
290
|
|
|
291
|
+
// Load runtime configuration for AgentShield integration
|
|
292
|
+
const runtimeConfig = getRuntimeConfig();
|
|
293
|
+
|
|
294
|
+
// Create CloudflareEnv adapter to map prefixed KV bindings to expected names
|
|
295
|
+
// This allows multiple agents to be deployed without KV namespace conflicts
|
|
296
|
+
const mappedEnv: CloudflareEnv = {
|
|
297
|
+
// Map prefixed bindings to standard names expected by createCloudflareRuntime
|
|
298
|
+
NONCE_CACHE: (env as any).${className.toUpperCase()}_NONCE_CACHE,
|
|
299
|
+
PROOF_ARCHIVE: (env as any).${className.toUpperCase()}_PROOF_ARCHIVE,
|
|
300
|
+
IDENTITY_STORAGE: (env as any).${className.toUpperCase()}_IDENTITY_STORAGE,
|
|
301
|
+
TOOL_PROTECTION_KV: (env as any).${className.toUpperCase()}_TOOL_PROTECTION_KV,
|
|
302
|
+
// Pass through environment variables unchanged
|
|
303
|
+
MCP_IDENTITY_PRIVATE_KEY: (env as any).MCP_IDENTITY_PRIVATE_KEY,
|
|
304
|
+
MCP_IDENTITY_PUBLIC_KEY: (env as any).MCP_IDENTITY_PUBLIC_KEY,
|
|
305
|
+
MCP_IDENTITY_AGENT_DID: (env as any).MCP_IDENTITY_AGENT_DID,
|
|
306
|
+
};
|
|
307
|
+
|
|
97
308
|
// Initialize MCP-I runtime for cryptographic proofs and identity
|
|
98
309
|
this.mcpiRuntime = createCloudflareRuntime({
|
|
99
|
-
env:
|
|
310
|
+
env: mappedEnv,
|
|
100
311
|
audit: {
|
|
101
|
-
enabled: true,
|
|
102
|
-
logFunction: (record) => console.log('[MCP-I Audit]', record)
|
|
312
|
+
enabled: runtimeConfig.audit?.enabled ?? true,
|
|
313
|
+
logFunction: runtimeConfig.audit?.logFunction || ((record) => console.log('[MCP-I Audit]', record))
|
|
103
314
|
}
|
|
104
315
|
});
|
|
105
316
|
|
|
106
317
|
// Initialize proof archive if PROOF_ARCHIVE KV is available
|
|
107
|
-
if (
|
|
108
|
-
this.proofArchive = new KVProofArchive(
|
|
109
|
-
console.log('[MCP-I] Proof archive enabled
|
|
110
|
-
}
|
|
111
|
-
|
|
318
|
+
if (mappedEnv.PROOF_ARCHIVE) {
|
|
319
|
+
this.proofArchive = new KVProofArchive(mappedEnv.PROOF_ARCHIVE);
|
|
320
|
+
console.log('[MCP-I] Proof archive enabled');
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Load AgentShield config for proof submission
|
|
324
|
+
if (runtimeConfig.proofing?.enabled && runtimeConfig.proofing.batchQueue) {
|
|
325
|
+
const agentShieldDest = runtimeConfig.proofing.batchQueue.destinations?.find(
|
|
326
|
+
(dest) => dest.type === "agentshield" && dest.apiKey
|
|
327
|
+
);
|
|
328
|
+
if (agentShieldDest) {
|
|
329
|
+
this.agentShieldConfig = {
|
|
330
|
+
apiUrl: agentShieldDest.apiUrl,
|
|
331
|
+
apiKey: agentShieldDest.apiKey!
|
|
332
|
+
};
|
|
333
|
+
console.log('[MCP-I] AgentShield enabled:', agentShieldDest.apiUrl);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Submit proof to AgentShield API
|
|
340
|
+
* Uses the proof.jws directly (full JWS format from CloudflareRuntime)
|
|
341
|
+
*
|
|
342
|
+
* Also submits optional context for AgentShield dashboard integration.
|
|
343
|
+
* Context provides plaintext tool/args data while proof provides cryptographic verification.
|
|
344
|
+
*/
|
|
345
|
+
private async submitProofToAgentShield(
|
|
346
|
+
proof: DetachedProof,
|
|
347
|
+
session: any,
|
|
348
|
+
toolName: string,
|
|
349
|
+
args: any,
|
|
350
|
+
result: any
|
|
351
|
+
): Promise<void> {
|
|
352
|
+
if (!this.agentShieldConfig || !proof.jws || !proof.meta) return;
|
|
353
|
+
|
|
354
|
+
const { apiUrl, apiKey } = this.agentShieldConfig;
|
|
355
|
+
|
|
356
|
+
// Get tool call context from runtime (if available)
|
|
357
|
+
const toolCallContext = this.mcpiRuntime?.getLastToolCallContext();
|
|
358
|
+
|
|
359
|
+
// Proof already has correct format from CloudflareRuntime
|
|
360
|
+
// Adding optional context for AgentShield dashboard (Option A architecture)
|
|
361
|
+
const requestBody = {
|
|
362
|
+
session_id: session.id,
|
|
363
|
+
delegation_id: null,
|
|
364
|
+
proofs: [{
|
|
365
|
+
jws: proof.jws, // Already in full JWS format
|
|
366
|
+
meta: proof.meta // Already has all required fields
|
|
367
|
+
}],
|
|
368
|
+
// ✅ NEW: Optional context for dashboard integration
|
|
369
|
+
context: {
|
|
370
|
+
toolCalls: toolCallContext ? [toolCallContext] : [{
|
|
371
|
+
// Fallback if context not available from runtime
|
|
372
|
+
tool: toolName,
|
|
373
|
+
args: args,
|
|
374
|
+
result: result,
|
|
375
|
+
scopeId: proof.meta.scopeId || \`\${toolName}:execute\`
|
|
376
|
+
}],
|
|
377
|
+
// ✅ NEW: MCP server URL for tool discovery (optional, only needed once)
|
|
378
|
+
mcpServerUrl: env.MCP_SERVER_URL
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
console.log('[AgentShield] Submitting proof with context:', {
|
|
383
|
+
did: proof.meta.did,
|
|
384
|
+
sessionId: proof.meta.sessionId,
|
|
385
|
+
jwsFormat: proof.jws.split('.').length === 3 ? 'valid (3 parts)' : 'invalid',
|
|
386
|
+
contextTool: requestBody.context.toolCalls[0]?.tool,
|
|
387
|
+
contextScopeId: requestBody.context.toolCalls[0]?.scopeId,
|
|
388
|
+
mcpServerUrl: requestBody.context.mcpServerUrl || 'not-set'
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
const response = await fetch(\`\${apiUrl}/api/v1/bouncer/proofs\`, {
|
|
392
|
+
method: 'POST',
|
|
393
|
+
headers: {
|
|
394
|
+
'Content-Type': 'application/json',
|
|
395
|
+
'Authorization': \`Bearer \${apiKey}\`
|
|
396
|
+
},
|
|
397
|
+
body: JSON.stringify(requestBody)
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
if (!response.ok) {
|
|
401
|
+
const errorText = await response.text();
|
|
402
|
+
console.error('[AgentShield] Submission failed:', response.status, errorText);
|
|
403
|
+
throw new Error(\`AgentShield error: \${response.status}\`);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const responseData = await response.json() as any;
|
|
407
|
+
console.log('[AgentShield] Response:', responseData);
|
|
408
|
+
|
|
409
|
+
if (responseData.accepted) {
|
|
410
|
+
console.log('[AgentShield] ✅ Proofs accepted:', responseData.accepted);
|
|
411
|
+
}
|
|
412
|
+
if (responseData.rejected) {
|
|
413
|
+
console.log('[AgentShield] ❌ Proofs rejected:', responseData.rejected);
|
|
112
414
|
}
|
|
113
415
|
}
|
|
114
416
|
|
|
@@ -131,7 +433,7 @@ export class ${pascalClassName}MCP extends McpAgent {
|
|
|
131
433
|
const timestamp = Date.now();
|
|
132
434
|
const session = {
|
|
133
435
|
id: \`ephemeral-\${timestamp}-\${Math.random().toString(36).substring(2, 10)}\`,
|
|
134
|
-
audience: '
|
|
436
|
+
audience: 'https://kya.vouched.id', // CRITICAL: Must match AgentShield domain
|
|
135
437
|
agentDid: (await this.mcpiRuntime.getIdentity()).did,
|
|
136
438
|
createdAt: timestamp,
|
|
137
439
|
expiresAt: timestamp + (30 * 60 * 1000) // 30 minutes
|
|
@@ -145,41 +447,52 @@ export class ${pascalClassName}MCP extends McpAgent {
|
|
|
145
447
|
session
|
|
146
448
|
);
|
|
147
449
|
|
|
148
|
-
// Get
|
|
149
|
-
const proof = this.mcpiRuntime.getLastProof();
|
|
450
|
+
// Get proof in DetachedProof format
|
|
451
|
+
const proof = this.mcpiRuntime.getLastProof() as DetachedProof;
|
|
150
452
|
|
|
151
|
-
if (proof) {
|
|
453
|
+
if (proof && proof.jws && proof.meta) {
|
|
454
|
+
// Log proof details (using DetachedProof format)
|
|
152
455
|
console.log('[MCP-I Proof]', {
|
|
153
456
|
tool: greetTool.name,
|
|
154
|
-
did: proof.did,
|
|
155
|
-
timestamp: proof.
|
|
156
|
-
|
|
457
|
+
did: proof.meta.did,
|
|
458
|
+
timestamp: proof.meta.ts,
|
|
459
|
+
jws: proof.jws.substring(0, 50) + '...',
|
|
460
|
+
jwsValid: proof.jws.split('.').length === 3
|
|
157
461
|
});
|
|
158
462
|
|
|
159
|
-
// Store
|
|
463
|
+
// Store in KV archive
|
|
160
464
|
if (this.proofArchive) {
|
|
161
465
|
try {
|
|
162
466
|
await this.proofArchive.store(proof, {
|
|
163
|
-
toolName: greetTool.name
|
|
164
|
-
sessionId: session.id
|
|
467
|
+
toolName: greetTool.name
|
|
165
468
|
});
|
|
166
|
-
console.log('[MCP-I] Proof stored in
|
|
469
|
+
console.log('[MCP-I] Proof stored in archive');
|
|
167
470
|
} catch (archiveError) {
|
|
168
|
-
console.error('[MCP-I]
|
|
169
|
-
|
|
471
|
+
console.error('[MCP-I] Archive error:', archiveError);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Submit to AgentShield with context
|
|
476
|
+
if (this.agentShieldConfig) {
|
|
477
|
+
try {
|
|
478
|
+
await this.submitProofToAgentShield(proof, session, greetTool.name, args, result);
|
|
479
|
+
} catch (err: any) {
|
|
480
|
+
console.error('[MCP-I] AgentShield failed:', err.message);
|
|
170
481
|
}
|
|
171
482
|
}
|
|
172
483
|
|
|
173
|
-
// Attach proof to result for MCP Inspector
|
|
174
|
-
// Following MCP-I pattern: { content: [...], _meta: { proof: {...} } }
|
|
484
|
+
// Attach proof to result for MCP Inspector
|
|
175
485
|
if (result && typeof result === 'object') {
|
|
176
486
|
(result as any)._meta = {
|
|
177
487
|
proof: {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
488
|
+
jws: proof.jws,
|
|
489
|
+
did: proof.meta.did,
|
|
490
|
+
kid: proof.meta.kid,
|
|
491
|
+
timestamp: proof.meta.ts,
|
|
492
|
+
nonce: proof.meta.nonce,
|
|
493
|
+
sessionId: proof.meta.sessionId,
|
|
494
|
+
requestHash: proof.meta.requestHash,
|
|
495
|
+
responseHash: proof.meta.responseHash
|
|
183
496
|
}
|
|
184
497
|
};
|
|
185
498
|
}
|
|
@@ -221,7 +534,7 @@ app.mount("/mcp", ${pascalClassName}MCP.serve("/mcp").fetch, { replaceRequest: f
|
|
|
221
534
|
export default app;
|
|
222
535
|
`;
|
|
223
536
|
fs.writeFileSync(path.join(srcDir, "index.ts"), indexContent);
|
|
224
|
-
// Create wrangler.toml
|
|
537
|
+
// Create wrangler.toml with optional API key
|
|
225
538
|
const wranglerContent = `#:schema node_modules/wrangler/config-schema.json
|
|
226
539
|
name = "${projectName}"
|
|
227
540
|
main = "src/index.ts"
|
|
@@ -246,8 +559,8 @@ new_sqlite_classes = ["${pascalClassName}MCP"]
|
|
|
246
559
|
#
|
|
247
560
|
# Then replace the id below with the namespace ID from the output
|
|
248
561
|
[[kv_namespaces]]
|
|
249
|
-
binding = "
|
|
250
|
-
id = "
|
|
562
|
+
binding = "${className.toUpperCase()}_NONCE_CACHE"
|
|
563
|
+
id = "your_nonce_kv_namespace_id" # Replace with actual namespace ID
|
|
251
564
|
|
|
252
565
|
# KV Namespace for proof archive (RECOMMENDED for auditability)
|
|
253
566
|
#
|
|
@@ -259,12 +572,67 @@ id = "your-nonce-kv-namespace-id" # Replace with actual namespace ID
|
|
|
259
572
|
#
|
|
260
573
|
# Note: Comment out if you don't need proof archiving
|
|
261
574
|
[[kv_namespaces]]
|
|
262
|
-
binding = "
|
|
263
|
-
id = "
|
|
575
|
+
binding = "${className.toUpperCase()}_PROOF_ARCHIVE"
|
|
576
|
+
id = "your_proof_kv_namespace_id" # Replace with actual namespace ID
|
|
577
|
+
|
|
578
|
+
# KV Namespace for identity storage (RECOMMENDED for persistent agent identity)
|
|
579
|
+
#
|
|
580
|
+
# Stores the agent's cryptographic identity (DID, keys) in KV
|
|
581
|
+
# Ensures consistent identity across Worker restarts and deployments
|
|
582
|
+
#
|
|
583
|
+
# Run: npm run kv:create-identity (creates IDENTITY_STORAGE namespace)
|
|
584
|
+
# Then replace the id below with the namespace ID from the output
|
|
585
|
+
#
|
|
586
|
+
[[kv_namespaces]]
|
|
587
|
+
binding = "${className.toUpperCase()}_IDENTITY_STORAGE"
|
|
588
|
+
id = "your_identity_kv_namespace_id" # Replace with actual namespace ID
|
|
589
|
+
|
|
590
|
+
# KV Namespace for delegation storage (REQUIRED for OAuth/delegation flows)
|
|
591
|
+
#
|
|
592
|
+
# Stores active delegations from users to agents
|
|
593
|
+
# Enables OAuth consent flows and scope-based authorization
|
|
594
|
+
#
|
|
595
|
+
# Run: npm run kv:create-delegation (creates DELEGATION_STORAGE namespace)
|
|
596
|
+
# Then replace the id below with the namespace ID from the output
|
|
597
|
+
#
|
|
598
|
+
[[kv_namespaces]]
|
|
599
|
+
binding = "${className.toUpperCase()}_DELEGATION_STORAGE"
|
|
600
|
+
id = "your_delegation_kv_namespace_id" # Replace with actual namespace ID
|
|
601
|
+
|
|
602
|
+
# KV Namespace for tool protection config (${apikey ? 'ENABLED' : 'OPTIONAL'} for dashboard-controlled delegation)
|
|
603
|
+
#
|
|
604
|
+
# 🆕 Enables dynamic tool protection configuration from AgentShield dashboard
|
|
605
|
+
# Caches which tools require user delegation based on dashboard toggle switches
|
|
606
|
+
#
|
|
607
|
+
# Benefits:
|
|
608
|
+
# - Control tool permissions from AgentShield dashboard without code changes
|
|
609
|
+
# - Update delegation requirements in real-time (5-minute cache)
|
|
610
|
+
# - No redeployments needed to change tool permissions
|
|
611
|
+
#
|
|
612
|
+
# Setup:
|
|
613
|
+
# 1. Run: npm run kv:create-tool-protection
|
|
614
|
+
# 2. Copy the namespace ID from output
|
|
615
|
+
# 3. Replace "your_tool_protection_kv_id" below with the actual ID
|
|
616
|
+
# 4. Deploy and toggle delegation in AgentShield dashboard
|
|
617
|
+
#
|
|
618
|
+
${apikey ? '' : '# '}[[kv_namespaces]]
|
|
619
|
+
${apikey ? '' : '# '}binding = "${className.toUpperCase()}_TOOL_PROTECTION_KV"
|
|
620
|
+
${apikey ? '' : '# '}id = "your_tool_protection_kv_id" # Replace with actual namespace ID
|
|
264
621
|
|
|
265
622
|
[vars]
|
|
266
623
|
XMCP_I_TS_SKEW_SEC = "120"
|
|
267
624
|
XMCP_I_SESSION_TTL = "1800"
|
|
625
|
+
|
|
626
|
+
# AgentShield Integration (https://kya.vouched.id)
|
|
627
|
+
# ${apikey ? 'Configure' : 'Uncomment and configure'} these variables to enable proof submission to AgentShield
|
|
628
|
+
AGENTSHIELD_API_URL = "https://kya.vouched.id"
|
|
629
|
+
${apikey ? `AGENTSHIELD_API_KEY = "${apikey}" # Provided via --apikey flag` : '# AGENTSHIELD_API_KEY = "sk_your_api_key_here" # Get from https://kya.vouched.id/dashboard'}
|
|
630
|
+
${apikey ? 'AGENTSHIELD_PROJECT_ID = "your-project-id" # Replace with your project ID from dashboard' : '# AGENTSHIELD_PROJECT_ID = "your-project-id" # Get from https://kya.vouched.id/dashboard'}
|
|
631
|
+
MCPI_ENV = "development"
|
|
632
|
+
|
|
633
|
+
# Optional: MCP Server URL for tool discovery
|
|
634
|
+
# Uncomment to explicitly set your MCP server URL (auto-detected if not set)
|
|
635
|
+
# MCP_SERVER_URL = "https://your-worker.workers.dev/mcp"
|
|
268
636
|
`;
|
|
269
637
|
fs.writeFileSync(path.join(projectPath, "wrangler.toml"), wranglerContent);
|
|
270
638
|
// Create tsconfig.json
|
|
@@ -319,37 +687,49 @@ ${packageManager} install
|
|
|
319
687
|
|
|
320
688
|
### 2. Create KV Namespaces
|
|
321
689
|
|
|
322
|
-
#### Create
|
|
690
|
+
#### Create All KV Namespaces (Recommended)
|
|
323
691
|
|
|
324
692
|
\`\`\`bash
|
|
325
|
-
${packageManager === "npm" ? "npm run" : packageManager} kv:create
|
|
693
|
+
${packageManager === "npm" ? "npm run" : packageManager} kv:create
|
|
326
694
|
\`\`\`
|
|
327
695
|
|
|
328
|
-
|
|
696
|
+
This creates all 5 KV namespaces at once:
|
|
697
|
+
- \`NONCE_CACHE\` - Replay attack prevention (Required)
|
|
698
|
+
- \`PROOF_ARCHIVE\` - Cryptographic proof storage (Recommended)
|
|
699
|
+
- \`IDENTITY_STORAGE\` - Agent identity persistence (Recommended)
|
|
700
|
+
- \`DELEGATION_STORAGE\` - OAuth delegation storage (Required for delegation)
|
|
701
|
+
- \`TOOL_PROTECTION_KV\` - Dashboard-controlled permissions (Optional)
|
|
702
|
+
|
|
703
|
+
Copy the namespace IDs from the output and update each one in \`wrangler.toml\`:
|
|
329
704
|
|
|
330
705
|
\`\`\`toml
|
|
331
706
|
[[kv_namespaces]]
|
|
332
707
|
binding = "NONCE_CACHE"
|
|
333
|
-
id = "
|
|
334
|
-
\`\`\`
|
|
335
|
-
|
|
336
|
-
#### Create Proof Archive (Recommended)
|
|
708
|
+
id = "your_nonce_kv_id_here" # ← Update this
|
|
337
709
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
710
|
+
[[kv_namespaces]]
|
|
711
|
+
binding = "PROOF_ARCHIVE"
|
|
712
|
+
id = "your_proof_kv_id_here" # ← Update this
|
|
341
713
|
|
|
342
|
-
|
|
714
|
+
[[kv_namespaces]]
|
|
715
|
+
binding = "IDENTITY_STORAGE"
|
|
716
|
+
id = "your_identity_kv_id_here" # ← Update this
|
|
343
717
|
|
|
344
|
-
|
|
718
|
+
[[kv_namespaces]]
|
|
719
|
+
binding = "DELEGATION_STORAGE"
|
|
720
|
+
id = "your_delegation_kv_id_here" # ← Update this
|
|
345
721
|
|
|
346
|
-
\`\`\`toml
|
|
347
722
|
[[kv_namespaces]]
|
|
348
|
-
binding = "
|
|
349
|
-
id = "
|
|
723
|
+
binding = "TOOL_PROTECTION_KV"
|
|
724
|
+
id = "your_tool_protection_kv_id_here" # ← Update this
|
|
350
725
|
\`\`\`
|
|
351
726
|
|
|
352
|
-
**Note:**
|
|
727
|
+
**Note:** You can also create namespaces individually:
|
|
728
|
+
- \`${packageManager === "npm" ? "npm run" : packageManager} kv:create-nonce\` - Create nonce cache only
|
|
729
|
+
- \`${packageManager === "npm" ? "npm run" : packageManager} kv:create-proof\` - Create proof archive only
|
|
730
|
+
- \`${packageManager === "npm" ? "npm run" : packageManager} kv:create-identity\` - Create identity storage only
|
|
731
|
+
- \`${packageManager === "npm" ? "npm run" : packageManager} kv:create-delegation\` - Create delegation storage only
|
|
732
|
+
- \`${packageManager === "npm" ? "npm run" : packageManager} kv:create-tool-protection\` - Create tool protection cache only
|
|
353
733
|
|
|
354
734
|
### 3. Test Locally
|
|
355
735
|
|
|
@@ -444,10 +824,10 @@ If you configured the \`PROOF_ARCHIVE\` KV namespace, proofs are also stored for
|
|
|
444
824
|
|
|
445
825
|
\`\`\`bash
|
|
446
826
|
# List all proofs
|
|
447
|
-
wrangler kv:key list --namespace-id=
|
|
827
|
+
wrangler kv:key list --namespace-id=your_proof_kv_id
|
|
448
828
|
|
|
449
829
|
# View a specific proof
|
|
450
|
-
wrangler kv:key get "proof_1234567890_abcd" --namespace-id=
|
|
830
|
+
wrangler kv:key get "proof_1234567890_abcd" --namespace-id=your_proof_kv_id
|
|
451
831
|
\`\`\`
|
|
452
832
|
|
|
453
833
|
## Identity Management
|
|
@@ -462,6 +842,105 @@ The identity includes:
|
|
|
462
842
|
- \`publicKey\`: Ed25519 public key for signature verification
|
|
463
843
|
- \`privateKey\`: Ed25519 private key (secured in Durable Object state)
|
|
464
844
|
|
|
845
|
+
## AgentShield Integration
|
|
846
|
+
|
|
847
|
+
This project is configured to send cryptographic proofs to AgentShield for audit trails and compliance monitoring.
|
|
848
|
+
|
|
849
|
+
### Setup
|
|
850
|
+
|
|
851
|
+
1. **Get your AgentShield API key**:
|
|
852
|
+
- Sign up at https://kya.vouched.id
|
|
853
|
+
- Create a project
|
|
854
|
+
- Copy your API key from the dashboard
|
|
855
|
+
|
|
856
|
+
2. **Update \`wrangler.toml\`**:
|
|
857
|
+
\`\`\`toml
|
|
858
|
+
[vars]
|
|
859
|
+
AGENTSHIELD_API_URL = "https://kya.vouched.id"
|
|
860
|
+
AGENTSHIELD_API_KEY = "sk_your_actual_key_here" # ← Replace this
|
|
861
|
+
AGENTSHIELD_PROJECT_ID = "your-project-id" # ← Replace this
|
|
862
|
+
MCPI_ENV = "development"
|
|
863
|
+
\`\`\`
|
|
864
|
+
|
|
865
|
+
3. **Test proof submission**:
|
|
866
|
+
\`\`\`bash
|
|
867
|
+
${packageManager === "npm" ? "npm run" : packageManager} dev
|
|
868
|
+
\`\`\`
|
|
869
|
+
|
|
870
|
+
Call a tool and check the logs:
|
|
871
|
+
\`\`\`
|
|
872
|
+
[AgentShield] Submitting proof: { did: 'did:web:...', sessionId: '...', jwsFormat: 'valid (3 parts)' }
|
|
873
|
+
[AgentShield] ✅ Proofs accepted: 1
|
|
874
|
+
\`\`\`
|
|
875
|
+
|
|
876
|
+
4. **View proofs in dashboard**:
|
|
877
|
+
- Go to https://kya.vouched.id/dashboard
|
|
878
|
+
- Select your project
|
|
879
|
+
- Click "Interactions" tab
|
|
880
|
+
- See your proofs in real-time
|
|
881
|
+
|
|
882
|
+
### Configuration
|
|
883
|
+
|
|
884
|
+
The AgentShield integration is configured in \`src/mcpi-runtime-config.ts\`. You can customize:
|
|
885
|
+
- Proof batch size (\`maxBatchSize\`)
|
|
886
|
+
- Flush interval (\`flushIntervalMs\`)
|
|
887
|
+
- Retry policy (\`maxRetries\`)
|
|
888
|
+
- Tool protection rules (\`toolProtections\`)
|
|
889
|
+
|
|
890
|
+
### Dashboard-Controlled Tool Protection (Advanced)
|
|
891
|
+
|
|
892
|
+
🆕 **NEW**: Control which tools require user delegation directly from the AgentShield dashboard - no code changes needed!
|
|
893
|
+
|
|
894
|
+
Instead of hardcoding \`requiresDelegation\` in your config, enable dynamic tool protection:
|
|
895
|
+
|
|
896
|
+
1. **Create Tool Protection KV namespace**:
|
|
897
|
+
\`\`\`bash
|
|
898
|
+
${packageManager === "npm" ? "npm run" : packageManager} kv:create-tool-protection
|
|
899
|
+
\`\`\`
|
|
900
|
+
|
|
901
|
+
2. **Uncomment TOOL_PROTECTION_KV in \`wrangler.toml\`**:
|
|
902
|
+
\`\`\`toml
|
|
903
|
+
[[kv_namespaces]]
|
|
904
|
+
binding = "TOOL_PROTECTION_KV"
|
|
905
|
+
id = "your_tool_protection_kv_id" # ← Add the ID from step 1
|
|
906
|
+
\`\`\`
|
|
907
|
+
|
|
908
|
+
3. **Enable Tool Protection Service in \`src/mcpi-runtime-config.ts\`**:
|
|
909
|
+
- Uncomment the import: \`import { CloudflareRuntime } from "@kya-os/mcp-i-cloudflare";\`
|
|
910
|
+
- Uncomment the \`toolProtectionService\` configuration block
|
|
911
|
+
|
|
912
|
+
4. **Deploy and test**:
|
|
913
|
+
\`\`\`bash
|
|
914
|
+
${packageManager === "npm" ? "npm run" : packageManager} deploy
|
|
915
|
+
\`\`\`
|
|
916
|
+
|
|
917
|
+
5. **Control delegation from dashboard**:
|
|
918
|
+
- Go to https://kya.vouched.id/dashboard
|
|
919
|
+
- Select your project → "Tools" tab
|
|
920
|
+
- Toggle "Require Delegation" for any tool
|
|
921
|
+
- Changes apply in real-time (5-minute cache)
|
|
922
|
+
|
|
923
|
+
**Benefits:**
|
|
924
|
+
- Update tool permissions without redeploying
|
|
925
|
+
- Test delegation flows instantly
|
|
926
|
+
- Different requirements per environment (dev vs prod)
|
|
927
|
+
- Automatic tool discovery from proof submissions
|
|
928
|
+
|
|
929
|
+
**Note:** The first time a tool is called, it auto-discovers in the dashboard. The \`requiresDelegation\` toggle will appear after the first proof is submitted.
|
|
930
|
+
|
|
931
|
+
### Disable AgentShield (Optional)
|
|
932
|
+
|
|
933
|
+
If you don't want to use AgentShield, edit \`src/mcpi-runtime-config.ts\`:
|
|
934
|
+
|
|
935
|
+
\`\`\`typescript
|
|
936
|
+
proofing: {
|
|
937
|
+
enabled: false, // Disable proof submission
|
|
938
|
+
// ...
|
|
939
|
+
}
|
|
940
|
+
\`\`\`
|
|
941
|
+
|
|
942
|
+
Or simply don't configure the \`AGENTSHIELD_API_KEY\` environment variable.
|
|
943
|
+
|
|
465
944
|
## References
|
|
466
945
|
|
|
467
946
|
- [Cloudflare Agents MCP](https://developers.cloudflare.com/agents/model-context-protocol/)
|
|
@@ -470,6 +949,28 @@ The identity includes:
|
|
|
470
949
|
`;
|
|
471
950
|
fs.writeFileSync(path.join(projectPath, "README.md"), readmeContent);
|
|
472
951
|
console.log(chalk.green("✅ Cloudflare Worker MCP server created"));
|
|
952
|
+
console.log();
|
|
953
|
+
if (apikey) {
|
|
954
|
+
console.log(chalk.green("🔑 AgentShield API key configured in wrangler.toml"));
|
|
955
|
+
console.log(chalk.dim(" Your API key has been added to the [vars] section"));
|
|
956
|
+
console.log(chalk.dim(" Remember to add your AGENTSHIELD_PROJECT_ID before deployment"));
|
|
957
|
+
console.log();
|
|
958
|
+
}
|
|
959
|
+
else {
|
|
960
|
+
console.log(chalk.yellow("⚠️ No AgentShield API key provided"));
|
|
961
|
+
console.log(chalk.dim(" Add your API key to wrangler.toml [vars] section before deployment"));
|
|
962
|
+
console.log(chalk.dim(" Get your key at: https://kya.vouched.id/dashboard"));
|
|
963
|
+
console.log();
|
|
964
|
+
}
|
|
965
|
+
console.log(chalk.bold("📦 All KV Namespaces Configured"));
|
|
966
|
+
console.log(chalk.dim(" - NONCE_CACHE: Replay attack prevention"));
|
|
967
|
+
console.log(chalk.dim(" - PROOF_ARCHIVE: Cryptographic proof storage"));
|
|
968
|
+
console.log(chalk.dim(" - IDENTITY_STORAGE: Agent identity persistence"));
|
|
969
|
+
console.log(chalk.dim(" - DELEGATION_STORAGE: OAuth delegation storage"));
|
|
970
|
+
console.log(chalk.dim(" - TOOL_PROTECTION_KV: Dashboard-controlled permissions"));
|
|
971
|
+
console.log();
|
|
972
|
+
console.log(chalk.cyan(" Run 'npm run kv:create' to create all namespaces"));
|
|
973
|
+
console.log();
|
|
473
974
|
}
|
|
474
975
|
catch (error) {
|
|
475
976
|
console.error(chalk.red("Failed to set up Cloudflare Worker MCP server:"), error);
|