@kya-os/mcp-i-cloudflare 1.0.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/README.md +458 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +103 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/crypto.d.ts +38 -0
- package/dist/providers/crypto.d.ts.map +1 -0
- package/dist/providers/crypto.js +132 -0
- package/dist/providers/crypto.js.map +1 -0
- package/dist/providers/identity.d.ts +33 -0
- package/dist/providers/identity.d.ts.map +1 -0
- package/dist/providers/identity.js +62 -0
- package/dist/providers/identity.js.map +1 -0
- package/dist/providers/nonce-cache.d.ts +17 -0
- package/dist/providers/nonce-cache.d.ts.map +1 -0
- package/dist/providers/nonce-cache.js +58 -0
- package/dist/providers/nonce-cache.js.map +1 -0
- package/dist/providers/storage.d.ts +62 -0
- package/dist/providers/storage.d.ts.map +1 -0
- package/dist/providers/storage.js +201 -0
- package/dist/providers/storage.js.map +1 -0
- package/dist/runtime/index.d.ts +31 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +72 -0
- package/dist/runtime/index.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
# @kya-os/mcp-i-cloudflare
|
|
2
|
+
|
|
3
|
+
Cloudflare Workers runtime for MCP-I (Model Context Protocol with Identity). Deploy cryptographically-signed MCP servers to Cloudflare's edge network with full identity support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ **Full MCP-I Support**: Cryptographic signing of all tool responses
|
|
8
|
+
- ✅ **Edge-Native**: Built for Cloudflare Workers with Web Crypto API
|
|
9
|
+
- ✅ **Identity Management**: DID-based identity with Ed25519 keys
|
|
10
|
+
- ✅ **Session Management**: Stateless sessions with nonce protection
|
|
11
|
+
- ✅ **KV Storage**: Use Workers KV for nonce cache and identity
|
|
12
|
+
- ✅ **Secrets Management**: Store private keys securely with Wrangler secrets
|
|
13
|
+
- ✅ **Progressive Verification**: Optimized for edge performance
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### 1. Create a new project
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx @kya-os/create-mcpi-app my-agent --platform cloudflare --mode mcp-i
|
|
21
|
+
cd my-agent
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. Install dependencies
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 3. Configure KV Namespace
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Create KV namespace for nonce cache
|
|
34
|
+
npm run kv:create
|
|
35
|
+
|
|
36
|
+
# Copy the ID from output and update wrangler.toml
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 4. Set Identity Secrets
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Generate identity locally (for development)
|
|
43
|
+
npx mcpi init
|
|
44
|
+
|
|
45
|
+
# Set secrets for production
|
|
46
|
+
wrangler secret put MCP_IDENTITY_PRIVATE_KEY
|
|
47
|
+
wrangler secret put MCP_IDENTITY_PUBLIC_KEY
|
|
48
|
+
wrangler secret put MCP_IDENTITY_DID
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 5. Deploy
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm run deploy
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Manual Setup
|
|
58
|
+
|
|
59
|
+
### Installation
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install @kya-os/mcp-i-cloudflare @modelcontextprotocol/sdk hono zod
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Worker Implementation
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// src/index.ts
|
|
69
|
+
import { Hono } from 'hono';
|
|
70
|
+
import { cors } from 'hono/cors';
|
|
71
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
72
|
+
import { createMCPIServer, MCPICloudflareEnv } from '@kya-os/mcp-i-cloudflare';
|
|
73
|
+
import { z } from 'zod';
|
|
74
|
+
|
|
75
|
+
interface Env extends MCPICloudflareEnv {
|
|
76
|
+
NONCE_CACHE: KVNamespace;
|
|
77
|
+
// Optional for development
|
|
78
|
+
IDENTITY_KV?: KVNamespace;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const app = new Hono<{ Bindings: Env }>();
|
|
82
|
+
|
|
83
|
+
// Enable CORS
|
|
84
|
+
app.use('/*', cors({
|
|
85
|
+
origin: '*',
|
|
86
|
+
allowMethods: ['GET', 'POST', 'OPTIONS'],
|
|
87
|
+
allowHeaders: ['Content-Type', 'Authorization'],
|
|
88
|
+
}));
|
|
89
|
+
|
|
90
|
+
// Initialize MCP-I runtime
|
|
91
|
+
let mcpiRuntime: ReturnType<typeof createMCPIServer> | null = null;
|
|
92
|
+
let mcpServer: McpServer | null = null;
|
|
93
|
+
|
|
94
|
+
const initialize = async (env: Env) => {
|
|
95
|
+
if (!mcpiRuntime) {
|
|
96
|
+
// Create MCP-I runtime
|
|
97
|
+
mcpiRuntime = createMCPIServer(env);
|
|
98
|
+
await mcpiRuntime.initialize();
|
|
99
|
+
|
|
100
|
+
// Create MCP server
|
|
101
|
+
mcpServer = new McpServer({
|
|
102
|
+
name: 'my-agent',
|
|
103
|
+
version: '1.0.0'
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Register tools with automatic signing
|
|
107
|
+
mcpServer.tool(
|
|
108
|
+
'greet',
|
|
109
|
+
'Greet a user',
|
|
110
|
+
z.object({ name: z.string() }),
|
|
111
|
+
async (args: any) => {
|
|
112
|
+
// Get session (in production, from request headers)
|
|
113
|
+
const session = await mcpiRuntime!.getCurrentSession();
|
|
114
|
+
|
|
115
|
+
// Process with automatic proof generation
|
|
116
|
+
return mcpiRuntime!.processToolCall(
|
|
117
|
+
'greet',
|
|
118
|
+
args,
|
|
119
|
+
async ({ name }) => ({
|
|
120
|
+
content: [{
|
|
121
|
+
type: 'text',
|
|
122
|
+
text: `Hello, ${name}!`
|
|
123
|
+
}]
|
|
124
|
+
}),
|
|
125
|
+
session
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
return { mcpiRuntime, mcpServer };
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Health check
|
|
134
|
+
app.get('/health', (c) => {
|
|
135
|
+
return c.json({
|
|
136
|
+
status: 'healthy',
|
|
137
|
+
timestamp: new Date().toISOString()
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Identity endpoint
|
|
142
|
+
app.get('/.well-known/mcp-identity', async (c) => {
|
|
143
|
+
const { mcpiRuntime } = await initialize(c.env);
|
|
144
|
+
const identity = await mcpiRuntime!.getIdentity();
|
|
145
|
+
|
|
146
|
+
return c.json({
|
|
147
|
+
did: identity.did,
|
|
148
|
+
keyId: identity.keyId,
|
|
149
|
+
publicKey: identity.publicKey
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// MCP endpoint
|
|
154
|
+
app.post('/mcp', async (c) => {
|
|
155
|
+
const { mcpServer } = await initialize(c.env);
|
|
156
|
+
const request = await c.req.json();
|
|
157
|
+
|
|
158
|
+
// Process MCP request
|
|
159
|
+
const response = await mcpServer!.handleRequest(request);
|
|
160
|
+
|
|
161
|
+
return c.json(response);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
export default app;
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### wrangler.toml Configuration
|
|
168
|
+
|
|
169
|
+
```toml
|
|
170
|
+
name = "my-mcp-agent"
|
|
171
|
+
main = "src/index.ts"
|
|
172
|
+
compatibility_date = "2025-01-01"
|
|
173
|
+
compatibility_flags = ["nodejs_compat"]
|
|
174
|
+
|
|
175
|
+
# KV Namespace for nonce cache (required)
|
|
176
|
+
[[kv_namespaces]]
|
|
177
|
+
binding = "NONCE_CACHE"
|
|
178
|
+
id = "your-kv-namespace-id"
|
|
179
|
+
|
|
180
|
+
# Optional: KV for identity storage (development)
|
|
181
|
+
# [[kv_namespaces]]
|
|
182
|
+
# binding = "IDENTITY_KV"
|
|
183
|
+
# id = "your-identity-kv-id"
|
|
184
|
+
|
|
185
|
+
# Environment variables
|
|
186
|
+
[vars]
|
|
187
|
+
XMCP_I_TS_SKEW_SEC = "120"
|
|
188
|
+
XMCP_I_SESSION_TTL = "1800"
|
|
189
|
+
|
|
190
|
+
# Production environment
|
|
191
|
+
[env.production]
|
|
192
|
+
name = "my-mcp-agent-production"
|
|
193
|
+
|
|
194
|
+
[[env.production.kv_namespaces]]
|
|
195
|
+
binding = "NONCE_CACHE"
|
|
196
|
+
id = "your-production-kv-id"
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Identity Management
|
|
200
|
+
|
|
201
|
+
### Development
|
|
202
|
+
|
|
203
|
+
For development, you can store identity in KV:
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// Identity stored in IDENTITY_KV namespace
|
|
207
|
+
const env = {
|
|
208
|
+
IDENTITY_KV: kvNamespace,
|
|
209
|
+
NONCE_CACHE: nonceNamespace
|
|
210
|
+
};
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Production
|
|
214
|
+
|
|
215
|
+
For production, use Wrangler secrets:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# Generate identity locally
|
|
219
|
+
npx mcpi init
|
|
220
|
+
|
|
221
|
+
# Copy values from .mcpi/identity.json
|
|
222
|
+
wrangler secret put MCP_IDENTITY_PRIVATE_KEY
|
|
223
|
+
wrangler secret put MCP_IDENTITY_PUBLIC_KEY
|
|
224
|
+
wrangler secret put MCP_IDENTITY_DID
|
|
225
|
+
wrangler secret put MCP_IDENTITY_KEY_ID
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Tool Development
|
|
229
|
+
|
|
230
|
+
Tools have the same format as Node.js MCP-I:
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
// src/tools/weather.ts
|
|
234
|
+
import { z } from 'zod';
|
|
235
|
+
|
|
236
|
+
export const weatherTool = {
|
|
237
|
+
name: 'get_weather',
|
|
238
|
+
description: 'Get weather for a location',
|
|
239
|
+
inputSchema: z.object({
|
|
240
|
+
location: z.string(),
|
|
241
|
+
units: z.enum(['celsius', 'fahrenheit']).optional()
|
|
242
|
+
}),
|
|
243
|
+
handler: async ({ location, units = 'celsius' }) => {
|
|
244
|
+
// Tool implementation
|
|
245
|
+
const weather = await fetchWeather(location, units);
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
content: [{
|
|
249
|
+
type: 'text',
|
|
250
|
+
text: `Weather in ${location}: ${weather.temp}°${units[0].toUpperCase()}`
|
|
251
|
+
}]
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Verification Endpoints
|
|
258
|
+
|
|
259
|
+
The runtime provides built-in verification endpoints:
|
|
260
|
+
|
|
261
|
+
### Identity Verification
|
|
262
|
+
```bash
|
|
263
|
+
GET /.well-known/mcp-identity
|
|
264
|
+
|
|
265
|
+
Response:
|
|
266
|
+
{
|
|
267
|
+
"did": "did:key:z6MkhaXgBZD...",
|
|
268
|
+
"keyId": "did:key:z6MkhaXgBZD...#key-1",
|
|
269
|
+
"publicKey": "base64..."
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Proof Verification
|
|
274
|
+
```bash
|
|
275
|
+
POST /verify
|
|
276
|
+
|
|
277
|
+
Request:
|
|
278
|
+
{
|
|
279
|
+
"data": { ... },
|
|
280
|
+
"proof": { ... }
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
Response:
|
|
284
|
+
{
|
|
285
|
+
"valid": true,
|
|
286
|
+
"metadata": { ... }
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Performance Optimization
|
|
291
|
+
|
|
292
|
+
### Edge Caching
|
|
293
|
+
|
|
294
|
+
Use KV with TTL for efficient caching:
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
// Cache DID documents
|
|
298
|
+
await env.CACHE_KV.put(
|
|
299
|
+
`did:${did}`,
|
|
300
|
+
JSON.stringify(document),
|
|
301
|
+
{ expirationTtl: 3600 } // 1 hour
|
|
302
|
+
);
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Progressive Verification
|
|
306
|
+
|
|
307
|
+
The runtime supports progressive verification for optimal edge performance:
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
// Stage-1: Quick offline checks (no network)
|
|
311
|
+
const quickCheck = await runtime.verifyOffline(data);
|
|
312
|
+
|
|
313
|
+
// Stage-2: Full verification (may use network)
|
|
314
|
+
if (quickCheck.valid) {
|
|
315
|
+
const fullCheck = await runtime.verifyOnline(data);
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Monitoring
|
|
320
|
+
|
|
321
|
+
### Metrics
|
|
322
|
+
|
|
323
|
+
Track MCP-I operations:
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
// In your worker
|
|
327
|
+
app.use('*', async (c, next) => {
|
|
328
|
+
const start = Date.now();
|
|
329
|
+
await next();
|
|
330
|
+
|
|
331
|
+
// Log to Analytics Engine or Workers Analytics
|
|
332
|
+
c.env.ANALYTICS.writeDataPoint({
|
|
333
|
+
endpoint: c.req.path,
|
|
334
|
+
duration: Date.now() - start,
|
|
335
|
+
status: c.res.status
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Audit Logging
|
|
341
|
+
|
|
342
|
+
Enable audit logging for security:
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
const runtime = createMCPIServer({
|
|
346
|
+
...env,
|
|
347
|
+
audit: {
|
|
348
|
+
enabled: true,
|
|
349
|
+
logFunction: (record) => {
|
|
350
|
+
// Send to Logflare, Datadog, etc.
|
|
351
|
+
env.LOGGER.log(record);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Deployment
|
|
358
|
+
|
|
359
|
+
### Local Development
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
# Start local dev server
|
|
363
|
+
npm run dev
|
|
364
|
+
|
|
365
|
+
# Test endpoints
|
|
366
|
+
curl http://localhost:8787/health
|
|
367
|
+
curl http://localhost:8787/.well-known/mcp-identity
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Production Deployment
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
# Deploy to Cloudflare
|
|
374
|
+
npm run deploy
|
|
375
|
+
|
|
376
|
+
# Deploy to specific environment
|
|
377
|
+
npm run deploy -- --env production
|
|
378
|
+
|
|
379
|
+
# Check deployment
|
|
380
|
+
wrangler tail
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Security Best Practices
|
|
384
|
+
|
|
385
|
+
1. **Never commit private keys** - Use Wrangler secrets
|
|
386
|
+
2. **Rotate keys regularly** - Use `mcpi rotate` command
|
|
387
|
+
3. **Limit KV access** - Use least privilege bindings
|
|
388
|
+
4. **Enable audit logging** - Track all operations
|
|
389
|
+
5. **Use CORS properly** - Restrict origins in production
|
|
390
|
+
6. **Monitor rate limits** - Implement request throttling
|
|
391
|
+
|
|
392
|
+
## Troubleshooting
|
|
393
|
+
|
|
394
|
+
### Common Issues
|
|
395
|
+
|
|
396
|
+
**Error: No identity found**
|
|
397
|
+
- Ensure secrets are set: `wrangler secret list`
|
|
398
|
+
- Check KV binding in wrangler.toml
|
|
399
|
+
|
|
400
|
+
**Error: Nonce already used**
|
|
401
|
+
- Check KV namespace is configured
|
|
402
|
+
- Verify TTL settings
|
|
403
|
+
|
|
404
|
+
**Error: Timestamp outside window**
|
|
405
|
+
- Check clock skew settings
|
|
406
|
+
- Ensure client/server time sync
|
|
407
|
+
|
|
408
|
+
## API Reference
|
|
409
|
+
|
|
410
|
+
### MCPICloudflareRuntime
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
class MCPICloudflareRuntime {
|
|
414
|
+
constructor(env: MCPICloudflareEnv);
|
|
415
|
+
|
|
416
|
+
async initialize(): Promise<void>;
|
|
417
|
+
async getIdentity(): Promise<AgentIdentity>;
|
|
418
|
+
async handleHandshake(request: HandshakeRequest): Promise<HandshakeResponse>;
|
|
419
|
+
async processToolCall(
|
|
420
|
+
toolName: string,
|
|
421
|
+
args: any,
|
|
422
|
+
handler: Function,
|
|
423
|
+
session: SessionContext
|
|
424
|
+
): Promise<any>;
|
|
425
|
+
async verifyProof(data: any, proof: any): Promise<boolean>;
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Environment Types
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
interface MCPICloudflareEnv {
|
|
433
|
+
// Required
|
|
434
|
+
NONCE_CACHE: KVNamespace;
|
|
435
|
+
|
|
436
|
+
// Identity (use secrets in production)
|
|
437
|
+
MCP_IDENTITY_DID?: string;
|
|
438
|
+
MCP_IDENTITY_KEY_ID?: string;
|
|
439
|
+
MCP_IDENTITY_PRIVATE_KEY?: string;
|
|
440
|
+
MCP_IDENTITY_PUBLIC_KEY?: string;
|
|
441
|
+
|
|
442
|
+
// Optional
|
|
443
|
+
IDENTITY_KV?: KVNamespace;
|
|
444
|
+
STORAGE_KV?: KVNamespace;
|
|
445
|
+
|
|
446
|
+
// Configuration
|
|
447
|
+
XMCP_I_TS_SKEW_SEC?: string;
|
|
448
|
+
XMCP_I_SESSION_TTL?: string;
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
## Examples
|
|
453
|
+
|
|
454
|
+
See the [examples](../../examples/cloudflare-mcpi) directory for complete working examples.
|
|
455
|
+
|
|
456
|
+
## License
|
|
457
|
+
|
|
458
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @kya-os/mcp-i-cloudflare
|
|
3
|
+
*
|
|
4
|
+
* Cloudflare Workers implementation of MCP-I framework.
|
|
5
|
+
* Provides Web Crypto and KV-based providers for edge runtime.
|
|
6
|
+
*/
|
|
7
|
+
import { MCPIRuntimeBase } from '@kya-os/mcp-i-core';
|
|
8
|
+
import { WebCryptoProvider } from './providers/crypto';
|
|
9
|
+
import { KVStorageProvider, KVNonceCacheProvider, WorkersClockProvider, WorkersFetchProvider, WorkersIdentityProvider } from './providers/storage';
|
|
10
|
+
export { WebCryptoProvider, KVStorageProvider, KVNonceCacheProvider, WorkersClockProvider, WorkersFetchProvider, WorkersIdentityProvider };
|
|
11
|
+
export type { AgentIdentity } from '@kya-os/mcp-i-core';
|
|
12
|
+
export interface CloudflareEnv {
|
|
13
|
+
NONCE_CACHE: KVNamespace;
|
|
14
|
+
IDENTITY_STORAGE?: KVNamespace;
|
|
15
|
+
MCP_IDENTITY_PRIVATE_KEY?: string;
|
|
16
|
+
MCP_IDENTITY_PUBLIC_KEY?: string;
|
|
17
|
+
MCP_IDENTITY_AGENT_DID?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface MCPICloudflareConfig {
|
|
20
|
+
env: CloudflareEnv;
|
|
21
|
+
environment?: 'development' | 'production';
|
|
22
|
+
timestampSkewSeconds?: number;
|
|
23
|
+
sessionTtlMinutes?: number;
|
|
24
|
+
audit?: {
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
logFunction?: (record: string) => void;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create MCP-I runtime for Cloudflare Workers
|
|
31
|
+
*/
|
|
32
|
+
export declare function createCloudflareRuntime(config: MCPICloudflareConfig): MCPIRuntimeBase;
|
|
33
|
+
/**
|
|
34
|
+
* MCP-I handler for Cloudflare Workers
|
|
35
|
+
*/
|
|
36
|
+
export declare function createMCPIHandler(config: MCPICloudflareConfig): {
|
|
37
|
+
fetch(request: Request): Promise<Response>;
|
|
38
|
+
};
|
|
39
|
+
export { MCPIRuntimeBase as CloudflareRuntime } from '@kya-os/mcp-i-core';
|
|
40
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAwC,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACxB,CAAC;AAGF,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,CAAC,EAAE,WAAW,CAAC;IAC/B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,aAAa,CAAC;IACnB,WAAW,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC;IAC3C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE;QACN,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;KACxC,CAAC;CACH;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,oBAAoB,GAAG,eAAe,CAwBrF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,oBAAoB;mBAIrC,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;EAiEnD;AAGD,OAAO,EAAE,eAAe,IAAI,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @kya-os/mcp-i-cloudflare
|
|
3
|
+
*
|
|
4
|
+
* Cloudflare Workers implementation of MCP-I framework.
|
|
5
|
+
* Provides Web Crypto and KV-based providers for edge runtime.
|
|
6
|
+
*/
|
|
7
|
+
import { MCPIRuntimeBase } from '@kya-os/mcp-i-core';
|
|
8
|
+
import { WebCryptoProvider } from './providers/crypto';
|
|
9
|
+
import { KVStorageProvider, KVNonceCacheProvider, WorkersClockProvider, WorkersFetchProvider, WorkersIdentityProvider } from './providers/storage';
|
|
10
|
+
// Re-export providers
|
|
11
|
+
export { WebCryptoProvider, KVStorageProvider, KVNonceCacheProvider, WorkersClockProvider, WorkersFetchProvider, WorkersIdentityProvider };
|
|
12
|
+
/**
|
|
13
|
+
* Create MCP-I runtime for Cloudflare Workers
|
|
14
|
+
*/
|
|
15
|
+
export function createCloudflareRuntime(config) {
|
|
16
|
+
const cryptoProvider = new WebCryptoProvider();
|
|
17
|
+
const clockProvider = new WorkersClockProvider();
|
|
18
|
+
const fetchProvider = new WorkersFetchProvider();
|
|
19
|
+
const storageProvider = new KVStorageProvider(config.env.IDENTITY_STORAGE || config.env.NONCE_CACHE);
|
|
20
|
+
const nonceCacheProvider = new KVNonceCacheProvider(config.env.NONCE_CACHE);
|
|
21
|
+
const identityProvider = new WorkersIdentityProvider(config.env, cryptoProvider);
|
|
22
|
+
const runtimeConfig = {
|
|
23
|
+
cryptoProvider,
|
|
24
|
+
clockProvider,
|
|
25
|
+
fetchProvider,
|
|
26
|
+
storageProvider,
|
|
27
|
+
nonceCacheProvider,
|
|
28
|
+
identityProvider,
|
|
29
|
+
environment: config.environment || 'production',
|
|
30
|
+
timestampSkewSeconds: config.timestampSkewSeconds || 120,
|
|
31
|
+
sessionTtlMinutes: config.sessionTtlMinutes || 30,
|
|
32
|
+
audit: config.audit
|
|
33
|
+
};
|
|
34
|
+
return new MCPIRuntimeBase(runtimeConfig);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* MCP-I handler for Cloudflare Workers
|
|
38
|
+
*/
|
|
39
|
+
export function createMCPIHandler(config) {
|
|
40
|
+
const runtime = createCloudflareRuntime(config);
|
|
41
|
+
return {
|
|
42
|
+
async fetch(request) {
|
|
43
|
+
// Initialize runtime on first request
|
|
44
|
+
if (!runtime.getIdentity) {
|
|
45
|
+
await runtime.initialize();
|
|
46
|
+
}
|
|
47
|
+
const url = new URL(request.url);
|
|
48
|
+
// Handle well-known endpoints
|
|
49
|
+
if (url.pathname.startsWith('/.well-known/')) {
|
|
50
|
+
const handler = runtime.createWellKnownHandler();
|
|
51
|
+
const result = await handler(url.pathname);
|
|
52
|
+
if (result) {
|
|
53
|
+
return new Response(JSON.stringify(result), {
|
|
54
|
+
headers: {
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
'Access-Control-Allow-Origin': '*'
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Handle MCP requests
|
|
62
|
+
if (request.method === 'POST') {
|
|
63
|
+
try {
|
|
64
|
+
const body = await request.json();
|
|
65
|
+
// Handle handshake
|
|
66
|
+
if (body.method === 'handshake') {
|
|
67
|
+
const result = await runtime.handleHandshake(body.params);
|
|
68
|
+
return new Response(JSON.stringify(result), {
|
|
69
|
+
headers: { 'Content-Type': 'application/json' }
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
// Handle tool calls
|
|
73
|
+
if (body.method === 'tools/call') {
|
|
74
|
+
// This would integrate with actual MCP SDK
|
|
75
|
+
return new Response(JSON.stringify({
|
|
76
|
+
result: 'Tool call handled'
|
|
77
|
+
}), {
|
|
78
|
+
headers: { 'Content-Type': 'application/json' }
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return new Response(JSON.stringify({
|
|
82
|
+
error: 'Unknown method'
|
|
83
|
+
}), {
|
|
84
|
+
status: 400,
|
|
85
|
+
headers: { 'Content-Type': 'application/json' }
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
return new Response(JSON.stringify({
|
|
90
|
+
error: error.message || 'Internal error'
|
|
91
|
+
}), {
|
|
92
|
+
status: 500,
|
|
93
|
+
headers: { 'Content-Type': 'application/json' }
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return new Response('Method not allowed', { status: 405 });
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// Export the runtime class for advanced usage
|
|
102
|
+
export { MCPIRuntimeBase as CloudflareRuntime } from '@kya-os/mcp-i-core';
|
|
103
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web Crypto Provider for Cloudflare Workers
|
|
3
|
+
*
|
|
4
|
+
* Implements CryptoProvider using the Web Crypto API available in Workers.
|
|
5
|
+
*/
|
|
6
|
+
import { CryptoProvider } from '@kya-os/mcp-i-core';
|
|
7
|
+
export declare class WebCryptoProvider extends CryptoProvider {
|
|
8
|
+
/**
|
|
9
|
+
* Sign data using Ed25519
|
|
10
|
+
*/
|
|
11
|
+
sign(data: Uint8Array, privateKeyBase64: string): Promise<Uint8Array>;
|
|
12
|
+
/**
|
|
13
|
+
* Verify Ed25519 signature
|
|
14
|
+
*/
|
|
15
|
+
verify(data: Uint8Array, signature: Uint8Array, publicKeyBase64: string): Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* Generate Ed25519 key pair
|
|
18
|
+
*/
|
|
19
|
+
generateKeyPair(): Promise<{
|
|
20
|
+
privateKey: string;
|
|
21
|
+
publicKey: string;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Calculate SHA-256 hash
|
|
25
|
+
*/
|
|
26
|
+
hash(data: Uint8Array): Promise<Uint8Array>;
|
|
27
|
+
/**
|
|
28
|
+
* Generate random bytes
|
|
29
|
+
*/
|
|
30
|
+
randomBytes(length: number): Promise<Uint8Array>;
|
|
31
|
+
private wrapPrivateKeyPKCS8;
|
|
32
|
+
private wrapPublicKeySPKI;
|
|
33
|
+
private extractRawPrivateKey;
|
|
34
|
+
private extractRawPublicKey;
|
|
35
|
+
private base64ToBytes;
|
|
36
|
+
private bytesToBase64;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/providers/crypto.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,qBAAa,iBAAkB,SAAQ,cAAc;IACnD;;OAEG;IACG,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA0B3E;;OAEG;IACG,MAAM,CACV,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,UAAU,EACrB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,OAAO,CAAC;IA6BnB;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAwB3E;;OAEG;IACG,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAKjD;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAQtD,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,aAAa;CAOtB"}
|