@vinkius-core/mcp-fusion-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.
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Cloudflare Workers ExecutionContext.
3
+ *
4
+ * Provides `waitUntil()` for background tasks and `passThroughOnException()`.
5
+ * Defined inline to avoid requiring `@cloudflare/workers-types`.
6
+ *
7
+ * If `@cloudflare/workers-types` is installed, the user's types will
8
+ * merge with this via declaration merging.
9
+ */
10
+ export interface ExecutionContext {
11
+ waitUntil(promise: Promise<unknown>): void;
12
+ passThroughOnException(): void;
13
+ }
14
+ /**
15
+ * Duck-typed interface for MCP Fusion's ToolRegistry.
16
+ *
17
+ * Accepts any object with `attachToServer()` — decoupled from the
18
+ * concrete class to avoid importing the core package at type level.
19
+ */
20
+ export interface RegistryLike {
21
+ attachToServer(server: unknown, options?: Record<string, unknown>): Promise<unknown>;
22
+ }
23
+ /**
24
+ * Configuration for the Cloudflare Workers adapter.
25
+ *
26
+ * @typeParam TEnv - Cloudflare environment bindings (D1, KV, R2, secrets)
27
+ * @typeParam TContext - Application context type for Fusion handlers
28
+ */
29
+ export interface CloudflareAdapterOptions<TEnv, TContext> {
30
+ /**
31
+ * A pre-built `ToolRegistry` populated during Cold Start.
32
+ *
33
+ * The registry contains all tools with their Zod schemas,
34
+ * Presenters, and middleware already compiled. This avoids
35
+ * re-running reflection on every request.
36
+ */
37
+ readonly registry: RegistryLike;
38
+ /** MCP server name (visible in capabilities). Default: `'mcp-fusion-edge'` */
39
+ readonly serverName?: string;
40
+ /** MCP server version string. Default: `'1.0.0'` */
41
+ readonly serverVersion?: string;
42
+ /**
43
+ * Context factory — creates the application context per request.
44
+ *
45
+ * Receives the Cloudflare `Request`, `env` bindings, and `ExecutionContext`,
46
+ * allowing full access to D1 databases, KV namespaces, R2 buckets, and secrets.
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * contextFactory: async (req, env) => ({
51
+ * db: env.DB, // D1 binding
52
+ * tenantId: req.headers.get('x-tenant-id') || 'public',
53
+ * })
54
+ * ```
55
+ */
56
+ readonly contextFactory?: (req: Request, env: TEnv, ctx: ExecutionContext) => TContext | Promise<TContext>;
57
+ /**
58
+ * Additional options forwarded to `registry.attachToServer()`.
59
+ *
60
+ * Supports `filter`, `stateSync`, `observability`, etc.
61
+ */
62
+ readonly attachOptions?: Record<string, unknown>;
63
+ }
64
+ /**
65
+ * The object returned by `cloudflareWorkersAdapter()`.
66
+ *
67
+ * Implements the Cloudflare Workers ES Modules `fetch` handler signature.
68
+ *
69
+ * @typeParam TEnv - Cloudflare environment bindings
70
+ */
71
+ export interface CloudflareWorkerHandler<TEnv> {
72
+ fetch(request: Request, env: TEnv, ctx: ExecutionContext): Promise<Response>;
73
+ }
74
+ /**
75
+ * Create a Cloudflare Workers adapter for MCP Fusion.
76
+ *
77
+ * Returns an object with a `fetch()` method matching the Workers
78
+ * ES Modules export default interface. Each request creates an
79
+ * ephemeral `McpServer` + `WebStandardStreamableHTTPServerTransport`,
80
+ * wires the pre-compiled registry, and returns the MCP JSON-RPC response.
81
+ *
82
+ * @typeParam TEnv - Cloudflare environment bindings (typed by the developer)
83
+ * @typeParam TContext - Application context type for Fusion handlers
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * // worker.ts
88
+ * import { ToolRegistry } from '@vinkius-core/mcp-fusion';
89
+ * import { cloudflareWorkersAdapter } from '@vinkius-core/mcp-fusion-cloudflare';
90
+ * import { billing, projects } from './tools.js';
91
+ *
92
+ * // COLD START: Zod reflection + compilation (once)
93
+ * const registry = new ToolRegistry<MyContext>();
94
+ * registry.registerAll(billing, projects);
95
+ *
96
+ * export interface Env { DB: D1Database; KV: KVNamespace; }
97
+ *
98
+ * // WARM REQUEST: Only McpServer + Transport per invocation
99
+ * export default cloudflareWorkersAdapter<Env, MyContext>({
100
+ * registry,
101
+ * contextFactory: async (req, env) => ({
102
+ * db: env.DB,
103
+ * tenantId: req.headers.get('x-tenant-id') || 'public',
104
+ * }),
105
+ * });
106
+ * ```
107
+ */
108
+ export declare function cloudflareWorkersAdapter<TEnv = unknown, TContext = void>(options: CloudflareAdapterOptions<TEnv, TContext>): CloudflareWorkerHandler<TEnv>;
109
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAsCA;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC7B,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3C,sBAAsB,IAAI,IAAI,CAAC;CAClC;AAMD;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IACzB,cAAc,CACV,MAAM,EAAE,OAAO,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB,CAAC,IAAI,EAAE,QAAQ;IACpD;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAEhC,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B,oDAAoD;IACpD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEhC;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CACtB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,IAAI,EACT,GAAG,EAAE,gBAAgB,KACpB,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAElC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB,CAAC,IAAI;IACzC,KAAK,CACD,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,IAAI,EACT,GAAG,EAAE,gBAAgB,GACtB,OAAO,CAAC,QAAQ,CAAC,CAAC;CACxB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,GAAG,OAAO,EAAE,QAAQ,GAAG,IAAI,EACpE,OAAO,EAAE,wBAAwB,CAAC,IAAI,EAAE,QAAQ,CAAC,GAClD,uBAAuB,CAAC,IAAI,CAAC,CAwE/B"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * MCP Fusion — Cloudflare Workers Adapter
3
+ *
4
+ * Deploys an MCP Fusion ToolRegistry to Cloudflare Workers edge
5
+ * with zero configuration. Uses the MCP SDK's native WinterCG
6
+ * transport (`WebStandardStreamableHTTPServerTransport`).
7
+ *
8
+ * **Architecture**:
9
+ *
10
+ * - **Cold Start** (once): The developer builds and populates a
11
+ * `ToolRegistry` in the module's top-level scope. Zod reflection,
12
+ * Presenter compilation, and schema generation happen here —
13
+ * zero CPU cost on warm requests.
14
+ *
15
+ * - **Warm Request** (per invocation): Only `McpServer` + `Transport`
16
+ * are instantiated per request. `attachToServer()` is a trivial
17
+ * handler-routing layer — no reflection, no compilation.
18
+ *
19
+ * **Stateless JSON-RPC**: Cloudflare Workers are ephemeral. This
20
+ * adapter forces `enableJsonResponse: true` — no SSE, no sessions,
21
+ * no streaming notifications. Pure request/response. Compatible with
22
+ * backend orchestrators (LangChain, Vercel AI SDK, custom agents).
23
+ *
24
+ * **Cloudflare `env` Injection**: The `env` object (D1, KV, R2,
25
+ * secrets) is injected per-request via the Worker's `fetch()`
26
+ * signature. The adapter exposes it to the user's `contextFactory`.
27
+ *
28
+ * @module
29
+ */
30
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
31
+ import { WebStandardStreamableHTTPServerTransport, } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
32
+ // ============================================================================
33
+ // Adapter
34
+ // ============================================================================
35
+ /**
36
+ * Create a Cloudflare Workers adapter for MCP Fusion.
37
+ *
38
+ * Returns an object with a `fetch()` method matching the Workers
39
+ * ES Modules export default interface. Each request creates an
40
+ * ephemeral `McpServer` + `WebStandardStreamableHTTPServerTransport`,
41
+ * wires the pre-compiled registry, and returns the MCP JSON-RPC response.
42
+ *
43
+ * @typeParam TEnv - Cloudflare environment bindings (typed by the developer)
44
+ * @typeParam TContext - Application context type for Fusion handlers
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * // worker.ts
49
+ * import { ToolRegistry } from '@vinkius-core/mcp-fusion';
50
+ * import { cloudflareWorkersAdapter } from '@vinkius-core/mcp-fusion-cloudflare';
51
+ * import { billing, projects } from './tools.js';
52
+ *
53
+ * // COLD START: Zod reflection + compilation (once)
54
+ * const registry = new ToolRegistry<MyContext>();
55
+ * registry.registerAll(billing, projects);
56
+ *
57
+ * export interface Env { DB: D1Database; KV: KVNamespace; }
58
+ *
59
+ * // WARM REQUEST: Only McpServer + Transport per invocation
60
+ * export default cloudflareWorkersAdapter<Env, MyContext>({
61
+ * registry,
62
+ * contextFactory: async (req, env) => ({
63
+ * db: env.DB,
64
+ * tenantId: req.headers.get('x-tenant-id') || 'public',
65
+ * }),
66
+ * });
67
+ * ```
68
+ */
69
+ export function cloudflareWorkersAdapter(options) {
70
+ const { registry, serverName = 'mcp-fusion-edge', serverVersion = '1.0.0', contextFactory, attachOptions = {}, } = options;
71
+ return {
72
+ async fetch(request, env, ctx) {
73
+ // Only POST is valid for stateless MCP JSON-RPC
74
+ if (request.method !== 'POST') {
75
+ return new Response(JSON.stringify({
76
+ jsonrpc: '2.0',
77
+ error: {
78
+ code: -32600,
79
+ message: 'Only POST requests are accepted. This is a stateless MCP endpoint.',
80
+ },
81
+ }), {
82
+ status: 405,
83
+ headers: {
84
+ 'Content-Type': 'application/json',
85
+ 'Allow': 'POST',
86
+ },
87
+ });
88
+ }
89
+ // 1. Ephemeral McpServer (isolates concurrent requests)
90
+ const server = new McpServer({
91
+ name: serverName,
92
+ version: serverVersion,
93
+ });
94
+ // 2. Stateless WinterCG transport — JSON-RPC only, no SSE
95
+ const transport = new WebStandardStreamableHTTPServerTransport({
96
+ enableJsonResponse: true,
97
+ });
98
+ // 3. Build context from Cloudflare env (per-request)
99
+ const requestContext = contextFactory
100
+ ? await contextFactory(request, env, ctx)
101
+ : undefined;
102
+ // 4. Wire the pre-compiled registry to the ephemeral server
103
+ const mergedOptions = {
104
+ ...attachOptions,
105
+ };
106
+ if (requestContext !== undefined) {
107
+ mergedOptions['contextFactory'] = () => requestContext;
108
+ }
109
+ await registry.attachToServer(server, mergedOptions);
110
+ // 5. Connect transport and handle the request
111
+ await server.connect(transport);
112
+ try {
113
+ return await transport.handleRequest(request);
114
+ }
115
+ finally {
116
+ // Cleanup — release resources
117
+ await server.close();
118
+ }
119
+ },
120
+ };
121
+ }
122
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EACH,wCAAwC,GAC3C,MAAM,+DAA+D,CAAC;AAsGvE,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,UAAU,wBAAwB,CACpC,OAAiD;IAEjD,MAAM,EACF,QAAQ,EACR,UAAU,GAAG,iBAAiB,EAC9B,aAAa,GAAG,OAAO,EACvB,cAAc,EACd,aAAa,GAAG,EAAE,GACrB,GAAG,OAAO,CAAC;IAEZ,OAAO;QACH,KAAK,CAAC,KAAK,CACP,OAAgB,EAChB,GAAS,EACT,GAAqB;YAErB,gDAAgD;YAChD,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC5B,OAAO,IAAI,QAAQ,CACf,IAAI,CAAC,SAAS,CAAC;oBACX,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE;wBACH,IAAI,EAAE,CAAC,KAAK;wBACZ,OAAO,EAAE,oEAAoE;qBAChF;iBACJ,CAAC,EACF;oBACI,MAAM,EAAE,GAAG;oBACX,OAAO,EAAE;wBACL,cAAc,EAAE,kBAAkB;wBAClC,OAAO,EAAE,MAAM;qBAClB;iBACJ,CACJ,CAAC;YACN,CAAC;YAED,wDAAwD;YACxD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;gBACzB,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,aAAa;aACzB,CAAC,CAAC;YAEH,0DAA0D;YAC1D,MAAM,SAAS,GAAG,IAAI,wCAAwC,CAAC;gBAC3D,kBAAkB,EAAE,IAAI;aAC3B,CAAC,CAAC;YAEH,qDAAqD;YACrD,MAAM,cAAc,GAAG,cAAc;gBACjC,CAAC,CAAC,MAAM,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC;gBACzC,CAAC,CAAC,SAAS,CAAC;YAEhB,4DAA4D;YAC5D,MAAM,aAAa,GAA4B;gBAC3C,GAAG,aAAa;aACnB,CAAC;YACF,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBAC/B,aAAa,CAAC,gBAAgB,CAAC,GAAG,GAAG,EAAE,CAAC,cAAc,CAAC;YAC3D,CAAC;YAED,MAAM,QAAQ,CAAC,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YAErD,8CAA8C;YAC9C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAEhC,IAAI,CAAC;gBACD,OAAO,MAAM,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAClD,CAAC;oBAAS,CAAC;gBACP,8BAA8B;gBAC9B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACzB,CAAC;QACL,CAAC;KACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @vinkius-core/mcp-fusion-cloudflare
3
+ *
4
+ * Cloudflare Workers adapter for MCP Fusion.
5
+ *
6
+ * @module
7
+ */
8
+ export { cloudflareWorkersAdapter, type CloudflareAdapterOptions, type CloudflareWorkerHandler, type RegistryLike, } from './adapter.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACH,wBAAwB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,YAAY,GACpB,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @vinkius-core/mcp-fusion-cloudflare
3
+ *
4
+ * Cloudflare Workers adapter for MCP Fusion.
5
+ *
6
+ * @module
7
+ */
8
+ export { cloudflareWorkersAdapter, } from './adapter.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACH,wBAAwB,GAI3B,MAAM,cAAc,CAAC"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@vinkius-core/mcp-fusion-cloudflare",
3
+ "version": "1.0.0",
4
+ "description": "Cloudflare Workers adapter for MCP Fusion. Deploys your MCP server to the edge with zero config — stateless JSON-RPC, cold-start caching, and native env injection.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "keywords": [
19
+ "mcp",
20
+ "mcp-fusion",
21
+ "cloudflare",
22
+ "workers",
23
+ "edge",
24
+ "serverless",
25
+ "wintercg",
26
+ "ai",
27
+ "llm"
28
+ ],
29
+ "author": "Vinkius Labs",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/vinkius-labs/mcp-fusion.git",
33
+ "directory": "packages/cloudflare"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/vinkius-labs/mcp-fusion/issues"
37
+ },
38
+ "homepage": "https://mcp-fusion.vinkius.com/",
39
+ "files": [
40
+ "dist",
41
+ "README.md"
42
+ ],
43
+ "engines": {
44
+ "node": ">=18.0.0"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "peerDependencies": {
50
+ "@vinkius-core/mcp-fusion": "^2.0.0",
51
+ "@modelcontextprotocol/sdk": "^1.12.0"
52
+ },
53
+ "license": "Apache-2.0"
54
+ }