@frontmcp/edge 0.0.1
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/LICENSE +201 -0
- package/README.md +83 -0
- package/esm/index.mjs +4030 -0
- package/esm/package.json +63 -0
- package/index.d.ts +122 -0
- package/index.js +4011 -0
- package/kv-cache.d.ts +82 -0
- package/managed.d.ts +69 -0
- package/package.json +63 -0
- package/session-host.d.ts +41 -0
- package/skill-index-cache.d.ts +51 -0
package/esm/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@frontmcp/edge",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Run a FrontMCP MCP server on Cloudflare Workers / V8 isolates from a plain config — no decorators, no build step",
|
|
5
|
+
"author": "AgentFront <info@agentfront.dev>",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"frontmcp",
|
|
9
|
+
"mcp",
|
|
10
|
+
"cloudflare",
|
|
11
|
+
"cloudflare-workers",
|
|
12
|
+
"workerd",
|
|
13
|
+
"edge",
|
|
14
|
+
"deno",
|
|
15
|
+
"bun",
|
|
16
|
+
"fetch",
|
|
17
|
+
"v8-isolate"
|
|
18
|
+
],
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/agentfront/frontmcp.git",
|
|
22
|
+
"directory": "libs/edge"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/agentfront/frontmcp/issues"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/agentfront/frontmcp/blob/main/libs/edge/README.md",
|
|
28
|
+
"type": "module",
|
|
29
|
+
"main": "../index.js",
|
|
30
|
+
"module": "./index.mjs",
|
|
31
|
+
"types": "../index.d.ts",
|
|
32
|
+
"sideEffects": false,
|
|
33
|
+
"exports": {
|
|
34
|
+
"./package.json": "../package.json",
|
|
35
|
+
".": {
|
|
36
|
+
"require": {
|
|
37
|
+
"types": "../index.d.ts",
|
|
38
|
+
"default": "../index.js"
|
|
39
|
+
},
|
|
40
|
+
"import": {
|
|
41
|
+
"types": "../index.d.ts",
|
|
42
|
+
"default": "./index.mjs"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"./esm": null
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=24.0.0"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"@frontmcp/plugin-skilled-openapi": "1.4.0",
|
|
52
|
+
"@frontmcp/sdk": "1.4.0"
|
|
53
|
+
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"@frontmcp/plugin-skilled-openapi": {
|
|
56
|
+
"optional": true
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@types/node": "^24.0.0",
|
|
61
|
+
"typescript": "^5.0.0"
|
|
62
|
+
}
|
|
63
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@frontmcp/edge` — run a FrontMCP server on a V8-isolate runtime
|
|
3
|
+
* (Cloudflare Workers, Deno Deploy, Bun) from a plain config object.
|
|
4
|
+
*
|
|
5
|
+
* No `@FrontMcp` decorator, no `frontmcp build` step: the edge entry imports
|
|
6
|
+
* this package, passes a config, and exports the returned `fetch` handler. The
|
|
7
|
+
* bundler (wrangler/esbuild) handles the rest.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* // worker.ts (~10 lines)
|
|
11
|
+
* import { createEdgeMcp } from '@frontmcp/edge';
|
|
12
|
+
* import { MyApp } from './apps';
|
|
13
|
+
*
|
|
14
|
+
* export default createEdgeMcp({
|
|
15
|
+
* info: { name: 'my-worker', version: '1.0.0' },
|
|
16
|
+
* apps: [MyApp],
|
|
17
|
+
* tasks: { enabled: false }, // edge has no Redis here
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* **Managed mode** (auto-updating): point it at a SaaS endpoint serving a
|
|
22
|
+
* signed skilled-openapi bundle (OpenAPI → skills + tools), pulled on boot and
|
|
23
|
+
* refreshed by polling — no redeploy on capability changes.
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* export default createEdgeMcp({
|
|
27
|
+
* info: { name: 'my-worker', version: '1.0.0' },
|
|
28
|
+
* apps: [],
|
|
29
|
+
* tasks: { enabled: false },
|
|
30
|
+
* managed: {
|
|
31
|
+
* endpoint: 'https://cloud.frontmcp.dev/v1/bundles/acme',
|
|
32
|
+
* authToken: env.FRONTMCP_PULL_TOKEN,
|
|
33
|
+
* expectedAudience: 'acme-mcp',
|
|
34
|
+
* jwksUrl: 'https://cloud.frontmcp.dev/.well-known/jwks.json',
|
|
35
|
+
* expectedIssuer: 'https://cloud.frontmcp.dev',
|
|
36
|
+
* },
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
import { FrontMcpInstance } from '@frontmcp/sdk';
|
|
41
|
+
import { type ManagedEdgeOptions } from './managed';
|
|
42
|
+
import { type EdgeSkillIndexCacheFactory } from './skill-index-cache';
|
|
43
|
+
export type { ManagedEdgeOptions } from './managed';
|
|
44
|
+
export { buildManagedOpenApiPluginOptions } from './managed';
|
|
45
|
+
export { createKvBundleCache, kvBundleCacheFromEnv, type EdgeBundleCacheFactory, type EdgeBundleCacheStore, type EdgeKvNamespace, type KvBundleCacheOptions, } from './kv-cache';
|
|
46
|
+
export { createKvSkillIndexCache, kvSkillIndexCacheFromEnv, type EdgeSkillIndexCacheFactory, type KvSkillIndexCacheOptions, } from './skill-index-cache';
|
|
47
|
+
/** The plain FrontMCP config the SDK accepts (same shape `@FrontMcp(...)` takes). */
|
|
48
|
+
type BaseConfig = Parameters<typeof FrontMcpInstance.createForGraph>[0];
|
|
49
|
+
/**
|
|
50
|
+
* Config accepted by {@link createEdgeMcp} — the FrontMCP config plus an
|
|
51
|
+
* optional `managed` block for the auto-updating skilled-openapi path.
|
|
52
|
+
*/
|
|
53
|
+
export type EdgeMcpConfig = BaseConfig & {
|
|
54
|
+
/**
|
|
55
|
+
* Managed mode — pull an auto-updating skilled-openapi bundle from a SaaS
|
|
56
|
+
* endpoint. Requires the optional peer `@frontmcp/plugin-skilled-openapi`.
|
|
57
|
+
*/
|
|
58
|
+
managed?: ManagedEdgeOptions;
|
|
59
|
+
/**
|
|
60
|
+
* Enable **stateful MCP sessions** via a Cloudflare Durable Object, so the
|
|
61
|
+
* Streamable HTTP standalone GET notification stream stays open across
|
|
62
|
+
* requests and a `tools/call`'s notifications reach it (the stateless worker
|
|
63
|
+
* can't do this). Export the returned {@link EdgeMcp.SessionDurableObject} and
|
|
64
|
+
* bind it in `wrangler.toml` under this `binding` name (default
|
|
65
|
+
* `FRONTMCP_SESSIONS`). When omitted, the worker is stateless.
|
|
66
|
+
*/
|
|
67
|
+
sessions?: {
|
|
68
|
+
binding?: string;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Enable a **KV-backed skill search-index cache** for fast cold starts. The
|
|
72
|
+
* built TF-IDF/BM25 index (embeddings + IDF model) is persisted to a Cloudflare
|
|
73
|
+
* KV namespace keyed by a content hash of the indexed skills, so a cold start
|
|
74
|
+
* restores it instead of recomputing the whole corpus. Bind a KV namespace in
|
|
75
|
+
* `wrangler.toml` under this `binding` name (default `FRONTMCP_SKILL_INDEX`).
|
|
76
|
+
*
|
|
77
|
+
* Accepts either a `{ binding }` (resolved from `env` at request time) or a
|
|
78
|
+
* ready factory `(env) => SkillIndexCache | undefined`. When omitted, or when
|
|
79
|
+
* the binding is absent on `env`, the index is rebuilt each cold start.
|
|
80
|
+
*/
|
|
81
|
+
skillIndex?: {
|
|
82
|
+
binding?: string;
|
|
83
|
+
ttlSeconds?: number;
|
|
84
|
+
} | EdgeSkillIndexCacheFactory;
|
|
85
|
+
};
|
|
86
|
+
/** An edge module: `export default createEdgeMcp(config)`. */
|
|
87
|
+
export interface EdgeMcp {
|
|
88
|
+
fetch: (request: Request, env?: unknown, ctx?: unknown) => Promise<Response>;
|
|
89
|
+
/**
|
|
90
|
+
* Cloudflare **Cron Trigger** entrypoint — present only in managed mode.
|
|
91
|
+
* Wire a `[triggers] crontabs = ["*/5 * * * *"]` in `wrangler.toml` and
|
|
92
|
+
* the runtime calls this on schedule; it pulls a fresh bundle and hot-swaps
|
|
93
|
+
* it (Workers have no background timers, so this replaces internal polling).
|
|
94
|
+
*/
|
|
95
|
+
scheduled?: (event?: unknown, env?: unknown, ctx?: unknown) => Promise<void>;
|
|
96
|
+
/**
|
|
97
|
+
* The **Durable Object class** for stateful sessions. Always present; re-export
|
|
98
|
+
* it from the worker entry and bind it in `wrangler.toml` (with a migration)
|
|
99
|
+
* to enable stateful sessions:
|
|
100
|
+
*
|
|
101
|
+
* ```ts
|
|
102
|
+
* const mcp = createEdgeMcp({ ..., sessions: {} });
|
|
103
|
+
* export default mcp;
|
|
104
|
+
* export const FrontMcpSession = mcp.SessionDurableObject;
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
SessionDurableObject: new (state: unknown, env: unknown) => {
|
|
108
|
+
fetch(request: Request): Promise<Response>;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Build an edge module (`{ fetch }`) from a FrontMCP config.
|
|
113
|
+
*
|
|
114
|
+
* The FrontMCP scope is built **lazily on the first request** and memoized —
|
|
115
|
+
* V8 isolates forbid timers / random / I-O at module-eval (global) scope, and
|
|
116
|
+
* scope initialization legitimately does those; deferring to the first `fetch`
|
|
117
|
+
* runs that work inside a request context, where it is allowed.
|
|
118
|
+
*
|
|
119
|
+
* Durable Object classes (sessions/event store) are not part of this skeleton
|
|
120
|
+
* yet — the handler is stateless. They arrive with `@frontmcp/adapters/cloudflare`.
|
|
121
|
+
*/
|
|
122
|
+
export declare function createEdgeMcp(config: EdgeMcpConfig): EdgeMcp;
|