@kya-os/create-mcpi-app 1.7.38-canary.2 → 1.7.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +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 +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 -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,164 +0,0 @@
|
|
|
1
|
-
# test-cloudflare
|
|
2
|
-
|
|
3
|
-
MCP-I server running on Cloudflare Workers with identity verification.
|
|
4
|
-
|
|
5
|
-
## Quick Start
|
|
6
|
-
|
|
7
|
-
### 1. Install Dependencies
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
### 2. Create KV Namespace
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
npm run kv:create
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
This runs: `wrangler kv namespace create NONCE_CACHE`
|
|
20
|
-
|
|
21
|
-
Copy the `id` from the output and update `wrangler.toml`:
|
|
22
|
-
|
|
23
|
-
```toml
|
|
24
|
-
[[kv_namespaces]]
|
|
25
|
-
binding = "NONCE_CACHE"
|
|
26
|
-
id = "your-actual-kv-id-here" # ← Update this
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### 3. Test Locally
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
npm run dev
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
**Endpoints:**
|
|
36
|
-
- MCP: http://localhost:8787/mcp
|
|
37
|
-
- Verify: http://localhost:8787/verify
|
|
38
|
-
- Health: http://localhost:8787/health
|
|
39
|
-
|
|
40
|
-
### 4. Deploy to Cloudflare
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
# Login to Cloudflare (first time only)
|
|
44
|
-
npx wrangler login
|
|
45
|
-
|
|
46
|
-
# Deploy to development
|
|
47
|
-
npm run deploy
|
|
48
|
-
|
|
49
|
-
# Deploy to production
|
|
50
|
-
npm run deploy --env production
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Connect with Claude Desktop
|
|
54
|
-
|
|
55
|
-
Add to your `claude_desktop_config.json`:
|
|
56
|
-
|
|
57
|
-
```json
|
|
58
|
-
{
|
|
59
|
-
"mcpServers": {
|
|
60
|
-
"test-cloudflare": {
|
|
61
|
-
"command": "npx",
|
|
62
|
-
"args": [
|
|
63
|
-
"mcp-remote",
|
|
64
|
-
"https://your-worker.workers.dev/mcp"
|
|
65
|
-
]
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Adding Tools
|
|
72
|
-
|
|
73
|
-
Create new tools in `src/tools/`:
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
// src/tools/example.ts
|
|
77
|
-
import { z } from "zod";
|
|
78
|
-
import type { RequestHandlerExtra } from "@modelcontextprotocol/sdk/types.js";
|
|
79
|
-
|
|
80
|
-
export const exampleTool = {
|
|
81
|
-
name: "example",
|
|
82
|
-
description: "Example tool description",
|
|
83
|
-
inputSchema: z.object({
|
|
84
|
-
input: z.string().describe("Input parameter"),
|
|
85
|
-
}),
|
|
86
|
-
handler: async (args: { [key: string]: any }, extra: RequestHandlerExtra<any, any>) => {
|
|
87
|
-
const { input } = args as { input: string };
|
|
88
|
-
return {
|
|
89
|
-
content: [
|
|
90
|
-
{
|
|
91
|
-
type: "text" as const,
|
|
92
|
-
text: `Result: ${input}`
|
|
93
|
-
}
|
|
94
|
-
],
|
|
95
|
-
};
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
Register in `src/index.ts`:
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
import { exampleTool } from "./tools/example";
|
|
104
|
-
|
|
105
|
-
async init() {
|
|
106
|
-
this.server.tool(
|
|
107
|
-
exampleTool.name,
|
|
108
|
-
exampleTool.description,
|
|
109
|
-
exampleTool.inputSchema.shape,
|
|
110
|
-
exampleTool.handler
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## API Endpoints
|
|
116
|
-
|
|
117
|
-
### `GET /health`
|
|
118
|
-
Health check endpoint.
|
|
119
|
-
|
|
120
|
-
**Response:**
|
|
121
|
-
```json
|
|
122
|
-
{
|
|
123
|
-
"status": "healthy",
|
|
124
|
-
"timestamp": "2024-10-10T12:00:00.000Z"
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### `POST /mcp`
|
|
129
|
-
MCP protocol endpoint for tool calls.
|
|
130
|
-
|
|
131
|
-
### `POST /verify`
|
|
132
|
-
Verify MCP-I cryptographic proofs.
|
|
133
|
-
|
|
134
|
-
**Request:**
|
|
135
|
-
```json
|
|
136
|
-
{
|
|
137
|
-
"proof": {
|
|
138
|
-
"agentDid": "did:web:example.com",
|
|
139
|
-
"timestamp": 1234567890,
|
|
140
|
-
"nonce": "abc123",
|
|
141
|
-
"signature": "...",
|
|
142
|
-
"publicKey": "..."
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
**Response:**
|
|
148
|
-
```json
|
|
149
|
-
{
|
|
150
|
-
"verified": true,
|
|
151
|
-
"agent": {
|
|
152
|
-
"did": "did:web:example.com",
|
|
153
|
-
"keyId": "key-123",
|
|
154
|
-
"scopes": ["read", "write"],
|
|
155
|
-
"session": "session-456"
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
## Learn More
|
|
161
|
-
|
|
162
|
-
- [MCP-I Documentation](https://github.com/kya-os/xmcp-i)
|
|
163
|
-
- [Cloudflare Workers](https://developers.cloudflare.com/workers/)
|
|
164
|
-
- [agents/mcp](https://www.npmjs.com/package/agents)
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "test-cloudflare",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"scripts": {
|
|
6
|
-
"deploy": "wrangler deploy",
|
|
7
|
-
"dev": "wrangler dev",
|
|
8
|
-
"start": "wrangler dev",
|
|
9
|
-
"test": "vitest run",
|
|
10
|
-
"test:watch": "vitest",
|
|
11
|
-
"kv:create": "wrangler kv namespace create NONCE_CACHE",
|
|
12
|
-
"kv:list": "wrangler kv namespace list",
|
|
13
|
-
"type-check": "tsc --noEmit"
|
|
14
|
-
},
|
|
15
|
-
"dependencies": {
|
|
16
|
-
"@kya-os/mcp-i-cloudflare": "^1.0.0",
|
|
17
|
-
"@modelcontextprotocol/sdk": "^1.19.1",
|
|
18
|
-
"agents": "^0.2.8",
|
|
19
|
-
"hono": "^4.9.10",
|
|
20
|
-
"zod": "^3.25.76"
|
|
21
|
-
},
|
|
22
|
-
"devDependencies": {
|
|
23
|
-
"@cloudflare/workers-types": "^4.20240925.0",
|
|
24
|
-
"typescript": "^5.6.2",
|
|
25
|
-
"vitest": "^2.1.8",
|
|
26
|
-
"wrangler": "^4.42.2"
|
|
27
|
-
}
|
|
28
|
-
}
|
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
-
import { McpAgent } from "agents/mcp";
|
|
3
|
-
import { Hono } from "hono";
|
|
4
|
-
import { cors } from "hono/cors";
|
|
5
|
-
import { createCloudflareRuntime, KVProofArchive } from "@kya-os/mcp-i-cloudflare";
|
|
6
|
-
import type { MCPIRuntimeBase } from "@kya-os/mcp-i-core";
|
|
7
|
-
import { WELL_KNOWN_CORS_HEADERS } from "@kya-os/mcp-i-core";
|
|
8
|
-
import { greetTool } from "./tools/greet";
|
|
9
|
-
|
|
10
|
-
interface Env {
|
|
11
|
-
MCP_OBJECT: DurableObjectNamespace;
|
|
12
|
-
NONCE_CACHE: KVNamespace;
|
|
13
|
-
PROOF_ARCHIVE?: KVNamespace;
|
|
14
|
-
XMCP_I_TS_SKEW_SEC?: string;
|
|
15
|
-
XMCP_I_SESSION_TTL?: string;
|
|
16
|
-
ADMIN_PROOFS_ENABLED?: string;
|
|
17
|
-
MCP_IDENTITY_PRIVATE_KEY?: string;
|
|
18
|
-
MCP_IDENTITY_PUBLIC_KEY?: string;
|
|
19
|
-
MCP_IDENTITY_AGENT_DID?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class CloudflareMCP extends McpAgent {
|
|
23
|
-
private mcpiRuntime?: MCPIRuntimeBase;
|
|
24
|
-
private proofArchive?: KVProofArchive;
|
|
25
|
-
private sessionId?: string;
|
|
26
|
-
|
|
27
|
-
constructor(state: DurableObjectState, env: Env) {
|
|
28
|
-
super(state, env);
|
|
29
|
-
|
|
30
|
-
this.mcpiRuntime = createCloudflareRuntime({
|
|
31
|
-
env: env as any,
|
|
32
|
-
environment: 'development',
|
|
33
|
-
timestampSkewSeconds: parseInt(env.XMCP_I_TS_SKEW_SEC || '120'),
|
|
34
|
-
sessionTtlMinutes: parseInt(env.XMCP_I_SESSION_TTL || '1800') / 60,
|
|
35
|
-
audit: {
|
|
36
|
-
enabled: true
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
if (env.PROOF_ARCHIVE) {
|
|
41
|
-
this.proofArchive = new KVProofArchive(env.PROOF_ARCHIVE, {
|
|
42
|
-
ttl: 86400 * 30
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async init() {
|
|
48
|
-
await this.mcpiRuntime?.initialize();
|
|
49
|
-
|
|
50
|
-
this.server.tool(
|
|
51
|
-
greetTool.name,
|
|
52
|
-
greetTool.description,
|
|
53
|
-
greetTool.inputSchema.shape,
|
|
54
|
-
async (args: any) => {
|
|
55
|
-
const identity = await this.mcpiRuntime!.getIdentity();
|
|
56
|
-
const sessionId = await this.ensureSessionId();
|
|
57
|
-
const establishedAt = await this.state.storage.get<number>("establishedAt") ?? Date.now();
|
|
58
|
-
const nonce = await this.mcpiRuntime!.issueNonce(sessionId);
|
|
59
|
-
|
|
60
|
-
const sessionContext = {
|
|
61
|
-
sessionId,
|
|
62
|
-
agentDid: identity.did,
|
|
63
|
-
kid: identity.kid,
|
|
64
|
-
establishedAt,
|
|
65
|
-
lastActivityAt: Date.now(),
|
|
66
|
-
nonce,
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const result = await this.mcpiRuntime!.processToolCall(
|
|
70
|
-
greetTool.name,
|
|
71
|
-
args,
|
|
72
|
-
greetTool.handler,
|
|
73
|
-
sessionContext
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
if (this.proofArchive) {
|
|
77
|
-
const proof = this.mcpiRuntime!.getLastProof();
|
|
78
|
-
if (proof) {
|
|
79
|
-
await this.proofArchive.store(proof, { toolName: greetTool.name, sessionId });
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return result;
|
|
84
|
-
}
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
private async ensureSessionId(): Promise<string> {
|
|
89
|
-
if (!this.sessionId) {
|
|
90
|
-
this.sessionId = await this.state.storage.get<string>("sessionId");
|
|
91
|
-
if (!this.sessionId) {
|
|
92
|
-
this.sessionId = crypto.randomUUID();
|
|
93
|
-
await this.state.storage.put("sessionId", this.sessionId);
|
|
94
|
-
await this.state.storage.put("establishedAt", Date.now());
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return this.sessionId;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async fetch(request: Request): Promise<Response> {
|
|
101
|
-
const url = new URL(request.url);
|
|
102
|
-
|
|
103
|
-
if (url.pathname === '/_internal/identity') {
|
|
104
|
-
const identity = await this.mcpiRuntime!.getIdentity();
|
|
105
|
-
return new Response(JSON.stringify({
|
|
106
|
-
did: identity.did,
|
|
107
|
-
publicKey: identity.publicKey,
|
|
108
|
-
kid: identity.kid
|
|
109
|
-
}), {
|
|
110
|
-
headers: { 'Content-Type': 'application/json' }
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (url.pathname.startsWith('/_internal/well-known/')) {
|
|
115
|
-
const handler = this.mcpiRuntime!.createWellKnownHandler({
|
|
116
|
-
serviceName: 'test-cloudflare',
|
|
117
|
-
serviceEndpoint: request.headers.get('X-Service-Origin') || url.origin
|
|
118
|
-
});
|
|
119
|
-
const path = url.pathname.replace('/_internal/well-known/', '/.well-known/');
|
|
120
|
-
const result = await handler(path);
|
|
121
|
-
|
|
122
|
-
if (result?.status && result?.headers && result?.body) {
|
|
123
|
-
return new Response(result.body, {
|
|
124
|
-
status: result.status,
|
|
125
|
-
headers: result.headers
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return new Response(JSON.stringify(result), {
|
|
130
|
-
headers: { 'Content-Type': 'application/json' }
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (url.pathname === '/_internal/verify') {
|
|
135
|
-
const body = await request.json() as { data: any; proof: any };
|
|
136
|
-
const isValid = await this.mcpiRuntime!.verifyProof(body.data, body.proof);
|
|
137
|
-
return new Response(JSON.stringify({ valid: isValid }), {
|
|
138
|
-
headers: { 'Content-Type': 'application/json' }
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (url.pathname === '/_internal/proofs') {
|
|
143
|
-
if (!this.proofArchive) {
|
|
144
|
-
return new Response(JSON.stringify({ error: 'Proof archive not initialized' }), {
|
|
145
|
-
status: 500,
|
|
146
|
-
headers: { 'Content-Type': 'application/json' }
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const limit = parseInt(url.searchParams.get('limit') || '10');
|
|
151
|
-
const sessionId = url.searchParams.get('sessionId');
|
|
152
|
-
|
|
153
|
-
const proofs = sessionId
|
|
154
|
-
? await this.proofArchive.getBySession(sessionId, limit)
|
|
155
|
-
: await this.proofArchive.getRecent(limit);
|
|
156
|
-
|
|
157
|
-
return new Response(JSON.stringify({ proofs }), {
|
|
158
|
-
headers: { 'Content-Type': 'application/json' }
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (url.pathname === '/_internal/proofs/tail') {
|
|
163
|
-
if (!this.proofArchive) {
|
|
164
|
-
return new Response(JSON.stringify({ error: 'Proof archive not initialized' }), {
|
|
165
|
-
status: 500,
|
|
166
|
-
headers: { 'Content-Type': 'application/json' }
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const sessionId = url.searchParams.get('session') ?? '';
|
|
171
|
-
const limit = parseInt(url.searchParams.get('limit') || '10');
|
|
172
|
-
let iv: ReturnType<typeof setInterval> | undefined;
|
|
173
|
-
|
|
174
|
-
const stream = new ReadableStream({
|
|
175
|
-
start: async (controller) => {
|
|
176
|
-
const enc = new TextEncoder();
|
|
177
|
-
let lastSeenId: string | null = null;
|
|
178
|
-
|
|
179
|
-
const send = (p: any) => {
|
|
180
|
-
const data = `event: mcpi-proof\ndata: ${JSON.stringify(p)}\n\n`;
|
|
181
|
-
controller.enqueue(enc.encode(data));
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
const poll = async () => {
|
|
185
|
-
try {
|
|
186
|
-
const list = sessionId
|
|
187
|
-
? await this.proofArchive!.getBySession(sessionId, limit)
|
|
188
|
-
: await this.proofArchive!.getRecent(limit);
|
|
189
|
-
|
|
190
|
-
for (const p of list) {
|
|
191
|
-
if (!lastSeenId || p.id > lastSeenId) {
|
|
192
|
-
send(p);
|
|
193
|
-
lastSeenId = p.id;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
} catch (error) {
|
|
197
|
-
console.error('Error polling proofs:', error);
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
await poll();
|
|
202
|
-
iv = setInterval(poll, 500);
|
|
203
|
-
},
|
|
204
|
-
cancel() {
|
|
205
|
-
if (iv) clearInterval(iv);
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
return new Response(stream, {
|
|
210
|
-
headers: {
|
|
211
|
-
'Content-Type': 'text/event-stream',
|
|
212
|
-
'Cache-Control': 'no-cache',
|
|
213
|
-
'Connection': 'keep-alive'
|
|
214
|
-
}
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return super.fetch(request);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const app = new Hono<{ Bindings: Env }>();
|
|
223
|
-
|
|
224
|
-
app.use("/*", cors({
|
|
225
|
-
origin: "*",
|
|
226
|
-
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
|
227
|
-
allowHeaders: ["Content-Type", "Authorization", "mcp-session-id", "mcp-protocol-version"],
|
|
228
|
-
exposeHeaders: ["mcp-session-id"],
|
|
229
|
-
}));
|
|
230
|
-
|
|
231
|
-
app.get("/health", (c) => c.json({
|
|
232
|
-
status: 'healthy',
|
|
233
|
-
timestamp: new Date().toISOString(),
|
|
234
|
-
transport: { sse: '/sse', streamableHttp: '/mcp' }
|
|
235
|
-
}));
|
|
236
|
-
|
|
237
|
-
app.get("/.well-known/did.json", async (c) => {
|
|
238
|
-
const stub = c.env.MCP_OBJECT.get(c.env.MCP_OBJECT.idFromName("singleton"));
|
|
239
|
-
const origin = new URL(c.req.url).origin;
|
|
240
|
-
const response = await stub.fetch("https://do/_internal/well-known/did.json", {
|
|
241
|
-
headers: { 'X-Service-Origin': origin }
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
return new Response(response.body, {
|
|
245
|
-
status: response.status,
|
|
246
|
-
headers: {
|
|
247
|
-
...Object.fromEntries(response.headers),
|
|
248
|
-
...WELL_KNOWN_CORS_HEADERS
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
app.get("/.well-known/agent.json", async (c) => {
|
|
254
|
-
const stub = c.env.MCP_OBJECT.get(c.env.MCP_OBJECT.idFromName("singleton"));
|
|
255
|
-
const origin = new URL(c.req.url).origin;
|
|
256
|
-
const response = await stub.fetch("https://do/_internal/well-known/agent.json", {
|
|
257
|
-
headers: { 'X-Service-Origin': origin }
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
return new Response(response.body, {
|
|
261
|
-
status: response.status,
|
|
262
|
-
headers: {
|
|
263
|
-
...Object.fromEntries(response.headers),
|
|
264
|
-
...WELL_KNOWN_CORS_HEADERS
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
app.get("/.well-known/mcp-identity", async (c) => {
|
|
270
|
-
const stub = c.env.MCP_OBJECT.get(c.env.MCP_OBJECT.idFromName("singleton"));
|
|
271
|
-
const origin = new URL(c.req.url).origin;
|
|
272
|
-
const response = await stub.fetch("https://do/_internal/well-known/mcp-identity", {
|
|
273
|
-
headers: { 'X-Service-Origin': origin }
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
return new Response(response.body, {
|
|
277
|
-
status: response.status,
|
|
278
|
-
headers: {
|
|
279
|
-
...Object.fromEntries(response.headers),
|
|
280
|
-
...WELL_KNOWN_CORS_HEADERS
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
app.post("/verify", async (c) => {
|
|
286
|
-
const stub = c.env.MCP_OBJECT.get(c.env.MCP_OBJECT.idFromName("singleton"));
|
|
287
|
-
const body = await c.req.json();
|
|
288
|
-
|
|
289
|
-
const response = await stub.fetch("https://do/_internal/verify", {
|
|
290
|
-
method: 'POST',
|
|
291
|
-
headers: { 'Content-Type': 'application/json' },
|
|
292
|
-
body: JSON.stringify(body)
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
return c.json(await response.json());
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
app.get("/admin/proofs", async (c) => {
|
|
299
|
-
if (c.env.ADMIN_PROOFS_ENABLED !== 'true') {
|
|
300
|
-
return c.json({ error: 'Admin endpoint disabled' }, 403);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
const stub = c.env.MCP_OBJECT.get(c.env.MCP_OBJECT.idFromName("singleton"));
|
|
304
|
-
const limit = c.req.query('limit') || '10';
|
|
305
|
-
const sessionId = c.req.query('sessionId');
|
|
306
|
-
|
|
307
|
-
const url = new URL("https://do/_internal/proofs");
|
|
308
|
-
url.searchParams.set('limit', limit);
|
|
309
|
-
if (sessionId) {
|
|
310
|
-
url.searchParams.set('sessionId', sessionId);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const response = await stub.fetch(url.toString());
|
|
314
|
-
return c.json(await response.json());
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
app.get("/proofs", async (c) => {
|
|
318
|
-
const stub = c.env.MCP_OBJECT.get(c.env.MCP_OBJECT.idFromName("singleton"));
|
|
319
|
-
const sessionId = c.req.query('session') ?? '';
|
|
320
|
-
const limit = c.req.query('limit') || '10';
|
|
321
|
-
|
|
322
|
-
const url = new URL("https://do/_internal/proofs/tail");
|
|
323
|
-
url.searchParams.set('session', sessionId);
|
|
324
|
-
url.searchParams.set('limit', limit);
|
|
325
|
-
|
|
326
|
-
const response = await stub.fetch(url.toString());
|
|
327
|
-
|
|
328
|
-
return new Response(response.body, {
|
|
329
|
-
headers: {
|
|
330
|
-
'Content-Type': 'text/event-stream',
|
|
331
|
-
'Cache-Control': 'no-cache',
|
|
332
|
-
'Connection': 'keep-alive',
|
|
333
|
-
'Access-Control-Allow-Origin': '*'
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
app.mount("/sse", CloudflareMCP.serveSSE("/sse").fetch, { replaceRequest: false });
|
|
339
|
-
app.mount("/mcp", CloudflareMCP.serve("/mcp").fetch, { replaceRequest: false });
|
|
340
|
-
|
|
341
|
-
export default app;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
export const greetTool = {
|
|
4
|
-
name: "greet",
|
|
5
|
-
description: "Greet a user by name",
|
|
6
|
-
inputSchema: z.object({
|
|
7
|
-
name: z.string().describe("The name of the user to greet")
|
|
8
|
-
}),
|
|
9
|
-
handler: async ({ name }: { name: string }) => {
|
|
10
|
-
return {
|
|
11
|
-
content: [
|
|
12
|
-
{
|
|
13
|
-
type: "text" as const,
|
|
14
|
-
text: `Hello, ${name}! Welcome to your Cloudflare MCP server.`
|
|
15
|
-
}
|
|
16
|
-
]
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
};
|