@cyanmycelium/mcp-broker 0.2.0 → 0.3.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/.mcp-broker.example/README.md +23 -0
- package/.mcp-broker.example/config.json +11 -0
- package/README.md +1 -16
- package/dist/bin.js +30 -3
- package/dist/bin.js.map +1 -1
- package/dist/broker/aggregate/aggregate.catalog.d.ts +54 -0
- package/dist/broker/aggregate/aggregate.catalog.js +105 -0
- package/dist/broker/aggregate/aggregate.catalog.js.map +1 -0
- package/dist/broker/aggregate/aggregate.server.d.ts +47 -0
- package/dist/broker/aggregate/aggregate.server.js +151 -0
- package/dist/broker/aggregate/aggregate.server.js.map +1 -0
- package/dist/broker/aggregate/provider.client.session.d.ts +52 -0
- package/dist/broker/aggregate/provider.client.session.js +140 -0
- package/dist/broker/aggregate/provider.client.session.js.map +1 -0
- package/dist/broker/broker.server.js +12 -1
- package/dist/broker/broker.server.js.map +1 -1
- package/dist/config.d.ts +35 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcpb.loader.d.ts +24 -0
- package/dist/mcpb.loader.js +161 -0
- package/dist/mcpb.loader.js.map +1 -0
- package/dist/mcpb.unzip.d.ts +6 -0
- package/dist/mcpb.unzip.js +95 -0
- package/dist/mcpb.unzip.js.map +1 -0
- package/dist/remote.transports.d.ts +16 -0
- package/dist/remote.transports.js +297 -0
- package/dist/remote.transports.js.map +1 -0
- package/dist/remote.upstream.d.ts +36 -0
- package/dist/remote.upstream.js +52 -0
- package/dist/remote.upstream.js.map +1 -0
- package/dist/stdio.upstream.d.ts +4 -1
- package/dist/stdio.upstream.js.map +1 -1
- package/dist/upstream.d.ts +33 -0
- package/dist/upstream.js +2 -0
- package/dist/upstream.js.map +1 -0
- package/dist/ws.tunnel.builder.d.ts +14 -8
- package/dist/ws.tunnel.builder.js +17 -9
- package/dist/ws.tunnel.builder.js.map +1 -1
- package/dist/ws.tunnel.d.ts +67 -2
- package/dist/ws.tunnel.js +200 -79
- package/dist/ws.tunnel.js.map +1 -1
- package/package.json +3 -2
- package/scripts/pack-mcpb.mjs +84 -0
- package/scripts/sign-bundle.mjs +61 -0
- package/src/bin.ts +32 -3
- package/src/broker/aggregate/aggregate.catalog.ts +145 -0
- package/src/broker/aggregate/aggregate.server.ts +178 -0
- package/src/broker/aggregate/provider.client.session.ts +172 -0
- package/src/broker/broker.server.ts +12 -1
- package/src/config.ts +37 -0
- package/src/index.ts +8 -0
- package/src/mcpb.loader.ts +186 -0
- package/src/mcpb.unzip.ts +103 -0
- package/src/remote.transports.ts +316 -0
- package/src/remote.upstream.ts +75 -0
- package/src/stdio.upstream.ts +4 -1
- package/src/upstream.ts +33 -0
- package/src/ws.tunnel.builder.ts +19 -9
- package/src/ws.tunnel.ts +239 -74
|
@@ -15,6 +15,10 @@ cp -r .mcp-broker.example .mcp-broker
|
|
|
15
15
|
├── certs/ ← TLS material (optional, gitignore this)
|
|
16
16
|
│ ├── cert.pem
|
|
17
17
|
│ └── key.pem
|
|
18
|
+
├── bundles/ ← signed .mcpb bundles + trusted public key (optional)
|
|
19
|
+
│ ├── <bundle>.mcpb
|
|
20
|
+
│ ├── <bundle>.mcpb.sig
|
|
21
|
+
│ └── mcpb-signing.pub.pem
|
|
18
22
|
├── grammars/ ← local grammar overrides (optional)
|
|
19
23
|
│ └── <userAgent>/
|
|
20
24
|
│ └── <locale>.json
|
|
@@ -22,6 +26,9 @@ cp -r .mcp-broker.example .mcp-broker
|
|
|
22
26
|
└── index.html
|
|
23
27
|
```
|
|
24
28
|
|
|
29
|
+
A ready-made instance UI lives at [`node/web/`](../web/) — point a `www`
|
|
30
|
+
mount at it (`"dir": "../web"`) to serve it. See [`node/web/README.md`](../web/README.md).
|
|
31
|
+
|
|
25
32
|
## Path resolution
|
|
26
33
|
|
|
27
34
|
Paths inside `config.json` are resolved against the **directory of the
|
|
@@ -32,6 +39,22 @@ Env vars (`MCP_BROKER_TLS_CERT`, `MCP_BROKER_WWW_DIR`, ...) are still
|
|
|
32
39
|
resolved against `process.cwd()` — they are the deploy-time override
|
|
33
40
|
mechanism and not tied to the config file's location.
|
|
34
41
|
|
|
42
|
+
## `.mcpb` bundles
|
|
43
|
+
|
|
44
|
+
`mcpbBundles` entries load local `.mcpb` bundles as stdio provider slots.
|
|
45
|
+
Each bundle is verified against a **detached signature** before it is
|
|
46
|
+
unpacked and run — the broker never spawns an unverified bundle.
|
|
47
|
+
|
|
48
|
+
1. Generate a signing key pair (once):
|
|
49
|
+
`node ../scripts/sign-bundle.mjs keygen bundles`
|
|
50
|
+
2. Sign each bundle:
|
|
51
|
+
`node ../scripts/sign-bundle.mjs sign bundles/<bundle>.mcpb bundles/mcpb-signing.key.pem`
|
|
52
|
+
3. Reference the bundle, its `.sig` and the **public** key in `config.json`.
|
|
53
|
+
|
|
54
|
+
Keep the private key (`mcpb-signing.key.pem`) out of the config folder and
|
|
55
|
+
out of version control. `userConfig` supplies values for the manifest's
|
|
56
|
+
`${user_config.*}` placeholders.
|
|
57
|
+
|
|
35
58
|
## Grammar overrides
|
|
36
59
|
|
|
37
60
|
Drop a JSON at `grammars/<userAgent>/<locale>.json` to override individual
|
|
@@ -28,5 +28,16 @@
|
|
|
28
28
|
"command": "npx",
|
|
29
29
|
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
|
|
30
30
|
}
|
|
31
|
+
],
|
|
32
|
+
|
|
33
|
+
"mcpbBundles": [
|
|
34
|
+
{
|
|
35
|
+
"name": "weather",
|
|
36
|
+
"path": "bundles/weather.mcpb",
|
|
37
|
+
"publicKey": "bundles/mcpb-signing.pub.pem",
|
|
38
|
+
"signature": "bundles/weather.mcpb.sig",
|
|
39
|
+
"userConfig": { "apiKey": "your-key-here" },
|
|
40
|
+
"aggregate": true
|
|
41
|
+
}
|
|
31
42
|
]
|
|
32
43
|
}
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
WebSocket-based [Model Context Protocol](https://modelcontextprotocol.io/) broker. Aggregates multiple MCP providers behind a single endpoint, with WebSocket, Streamable HTTP, SSE, and stdio client transports.
|
|
12
12
|
|
|
13
|
-
> This is the Node/TypeScript implementation of the broker. Architecture, wire protocol, and
|
|
13
|
+
> This is the Node/TypeScript implementation of the broker. Architecture, wire protocol, and endpoints are documented language-neutrally in [../docs](../docs).
|
|
14
14
|
|
|
15
15
|
## Install and run
|
|
16
16
|
|
|
@@ -209,21 +209,6 @@ The broker can act as a stdio MCP server for Claude Desktop, bridging to any pro
|
|
|
209
209
|
|
|
210
210
|
In this mode all broker logging goes to stderr; stdout is reserved for the JSON-RPC stream Claude expects.
|
|
211
211
|
|
|
212
|
-
## What the broker does (and does not yet)
|
|
213
|
-
|
|
214
|
-
| Capability | Status |
|
|
215
|
-
|---|---|
|
|
216
|
-
| One named provider slot, multiple clients | ✅ |
|
|
217
|
-
| Provider transports: WS dedicated, WS multiplexed, stdio upstream | ✅ |
|
|
218
|
-
| Client transports: raw WS, Streamable HTTP (2025-03-26), legacy SSE, stdio bridge | ✅ |
|
|
219
|
-
| TLS via PEM files | ✅ |
|
|
220
|
-
| Static file serving (dev harness) | ✅ |
|
|
221
|
-
| Cross-provider tool aggregation (one client sees all providers' tools at once) | 🚧 v0.4 |
|
|
222
|
-
| Authentication / authorization | 🚧 v0.3 |
|
|
223
|
-
| Multi-tenant isolation | 🚧 v1.0 |
|
|
224
|
-
|
|
225
|
-
Full roadmap: [../docs/roadmap.md](../docs/roadmap.md).
|
|
226
|
-
|
|
227
212
|
## Development
|
|
228
213
|
|
|
229
214
|
```sh
|
package/dist/bin.js
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
*
|
|
16
16
|
* - Env-var paths (`MCP_BROKER_*_DIR`, `MCP_BROKER_TLS_*`) are resolved
|
|
17
17
|
* against `process.cwd()`.
|
|
18
|
-
* - Config-file paths (`tls.cert`, `www.mounts[*].dir`, `stdioUpstreams[*]
|
|
19
|
-
* are resolved against the **config file's directory** — so a config in
|
|
18
|
+
* - Config-file paths (`tls.cert`, `www.mounts[*].dir`, `stdioUpstreams[*]`,
|
|
19
|
+
* `mcpbBundles[*]`) are resolved against the **config file's directory** — so a config in
|
|
20
20
|
* `./.mcp-broker/config.json` referring to `"certs/cert.pem"` points at
|
|
21
21
|
* `./.mcp-broker/certs/cert.pem`. The folder is self-contained.
|
|
22
22
|
*
|
|
@@ -54,6 +54,7 @@ import * as path from "path";
|
|
|
54
54
|
import open from "open";
|
|
55
55
|
import { WsTunnelBuilder } from "./index.js";
|
|
56
56
|
import { loadBrokerConfig } from "./config.js";
|
|
57
|
+
import { loadMcpbBundle } from "./mcpb.loader.js";
|
|
57
58
|
// ---------------------------------------------------------------------------
|
|
58
59
|
// Configuration
|
|
59
60
|
// ---------------------------------------------------------------------------
|
|
@@ -153,7 +154,33 @@ async function main() {
|
|
|
153
154
|
// ── Stdio upstreams ──────────────────────────────────────────────────────
|
|
154
155
|
if (config.stdioUpstreams) {
|
|
155
156
|
for (const u of config.stdioUpstreams) {
|
|
156
|
-
builder.withStdioUpstream(
|
|
157
|
+
builder.withStdioUpstream({
|
|
158
|
+
name: u.name,
|
|
159
|
+
command: u.command,
|
|
160
|
+
args: u.args,
|
|
161
|
+
env: u.env,
|
|
162
|
+
aggregate: u.aggregate,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// ── Remote MCP server upstreams (reached by URL) ─────────────────────────
|
|
167
|
+
// Config-discovered remote servers join the `_all` aggregate by default;
|
|
168
|
+
// an explicit `aggregate: false` opts an entry out.
|
|
169
|
+
if (config.mcpServers) {
|
|
170
|
+
for (const s of config.mcpServers) {
|
|
171
|
+
builder.withRemoteUpstream({ ...s, aggregate: s.aggregate ?? true });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// ── Local `.mcpb` bundles ────────────────────────────────────────────────
|
|
175
|
+
// Each bundle is signature-verified and unpacked before it is wired in as a
|
|
176
|
+
// stdio upstream. A refused bundle is skipped (loadMcpbBundle logs why); it
|
|
177
|
+
// never spawns a process. Bundles join `_all` by default (opt-out per entry).
|
|
178
|
+
if (config.mcpbBundles) {
|
|
179
|
+
for (const b of config.mcpbBundles) {
|
|
180
|
+
const upstream = await loadMcpbBundle(b, baseDir);
|
|
181
|
+
if (upstream) {
|
|
182
|
+
builder.withStdioUpstream(upstream);
|
|
183
|
+
}
|
|
157
184
|
}
|
|
158
185
|
}
|
|
159
186
|
if (stdioProvider) {
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AggregateCatalog — merges the tool and prompt catalogs of several providers
|
|
3
|
+
* into a single namespaced view, and routes aggregated names back to their
|
|
4
|
+
* origin provider.
|
|
5
|
+
*
|
|
6
|
+
* Aggregated names use the `<provider>-<original>` shape. Routing never parses
|
|
7
|
+
* that string back: a forward lookup table is the single source of truth, so
|
|
8
|
+
* the `-` separator stays safe even when provider or tool names contain dashes.
|
|
9
|
+
*/
|
|
10
|
+
/** Minimal shape of an MCP tool entry. Extra fields are preserved as-is. */
|
|
11
|
+
export interface CatalogTool {
|
|
12
|
+
name: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
/** Minimal shape of an MCP prompt entry. Extra fields are preserved as-is. */
|
|
17
|
+
export interface CatalogPrompt {
|
|
18
|
+
name: string;
|
|
19
|
+
title?: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
/** One provider's raw contribution to the aggregate. */
|
|
24
|
+
export interface ProviderEntry {
|
|
25
|
+
tools: CatalogTool[];
|
|
26
|
+
prompts: CatalogPrompt[];
|
|
27
|
+
}
|
|
28
|
+
/** Where an aggregated name routes back to. */
|
|
29
|
+
export interface Route {
|
|
30
|
+
provider: string;
|
|
31
|
+
original: string;
|
|
32
|
+
}
|
|
33
|
+
export declare class AggregateCatalog {
|
|
34
|
+
private readonly _providers;
|
|
35
|
+
private _tools;
|
|
36
|
+
private _prompts;
|
|
37
|
+
private _toolRoutes;
|
|
38
|
+
private _promptRoutes;
|
|
39
|
+
/** Number of providers currently contributing to the aggregate. */
|
|
40
|
+
get providerCount(): number;
|
|
41
|
+
/** The merged, namespaced tool list. */
|
|
42
|
+
get tools(): CatalogTool[];
|
|
43
|
+
/** The merged, namespaced prompt list. */
|
|
44
|
+
get prompts(): CatalogPrompt[];
|
|
45
|
+
/** Adds or replaces a provider's contribution, then rebuilds the merged view. */
|
|
46
|
+
setProvider(provider: string, entry: ProviderEntry): void;
|
|
47
|
+
/** Drops a provider from the aggregate, then rebuilds. */
|
|
48
|
+
removeProvider(provider: string): void;
|
|
49
|
+
/** Resolves an aggregated tool name to its origin, or `undefined` if unknown. */
|
|
50
|
+
resolveTool(name: string): Route | undefined;
|
|
51
|
+
/** Resolves an aggregated prompt name to its origin, or `undefined` if unknown. */
|
|
52
|
+
resolvePrompt(name: string): Route | undefined;
|
|
53
|
+
private _rebuild;
|
|
54
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AggregateCatalog — merges the tool and prompt catalogs of several providers
|
|
3
|
+
* into a single namespaced view, and routes aggregated names back to their
|
|
4
|
+
* origin provider.
|
|
5
|
+
*
|
|
6
|
+
* Aggregated names use the `<provider>-<original>` shape. Routing never parses
|
|
7
|
+
* that string back: a forward lookup table is the single source of truth, so
|
|
8
|
+
* the `-` separator stays safe even when provider or tool names contain dashes.
|
|
9
|
+
*/
|
|
10
|
+
/** Separator between the provider prefix and the original name. */
|
|
11
|
+
const SEPARATOR = "-";
|
|
12
|
+
/** Anthropic API tool-name limit; aggregated tool names must fit inside it. */
|
|
13
|
+
const MAX_TOOL_NAME_LENGTH = 64;
|
|
14
|
+
export class AggregateCatalog {
|
|
15
|
+
_providers = new Map();
|
|
16
|
+
_tools = [];
|
|
17
|
+
_prompts = [];
|
|
18
|
+
_toolRoutes = new Map();
|
|
19
|
+
_promptRoutes = new Map();
|
|
20
|
+
/** Number of providers currently contributing to the aggregate. */
|
|
21
|
+
get providerCount() {
|
|
22
|
+
return this._providers.size;
|
|
23
|
+
}
|
|
24
|
+
/** The merged, namespaced tool list. */
|
|
25
|
+
get tools() {
|
|
26
|
+
return this._tools;
|
|
27
|
+
}
|
|
28
|
+
/** The merged, namespaced prompt list. */
|
|
29
|
+
get prompts() {
|
|
30
|
+
return this._prompts;
|
|
31
|
+
}
|
|
32
|
+
/** Adds or replaces a provider's contribution, then rebuilds the merged view. */
|
|
33
|
+
setProvider(provider, entry) {
|
|
34
|
+
this._providers.set(provider, entry);
|
|
35
|
+
this._rebuild();
|
|
36
|
+
}
|
|
37
|
+
/** Drops a provider from the aggregate, then rebuilds. */
|
|
38
|
+
removeProvider(provider) {
|
|
39
|
+
if (this._providers.delete(provider))
|
|
40
|
+
this._rebuild();
|
|
41
|
+
}
|
|
42
|
+
/** Resolves an aggregated tool name to its origin, or `undefined` if unknown. */
|
|
43
|
+
resolveTool(name) {
|
|
44
|
+
return this._toolRoutes.get(name);
|
|
45
|
+
}
|
|
46
|
+
/** Resolves an aggregated prompt name to its origin, or `undefined` if unknown. */
|
|
47
|
+
resolvePrompt(name) {
|
|
48
|
+
return this._promptRoutes.get(name);
|
|
49
|
+
}
|
|
50
|
+
_rebuild() {
|
|
51
|
+
const tools = [];
|
|
52
|
+
const prompts = [];
|
|
53
|
+
const toolRoutes = new Map();
|
|
54
|
+
const promptRoutes = new Map();
|
|
55
|
+
for (const [provider, entry] of this._providers) {
|
|
56
|
+
for (const tool of entry.tools) {
|
|
57
|
+
const name = unique(capToolName(prefixed(provider, tool.name)), toolRoutes);
|
|
58
|
+
toolRoutes.set(name, { provider, original: tool.name });
|
|
59
|
+
tools.push({ ...tool, name, description: tag(provider, tool.description) });
|
|
60
|
+
}
|
|
61
|
+
for (const prompt of entry.prompts) {
|
|
62
|
+
const name = unique(prefixed(provider, prompt.name), promptRoutes);
|
|
63
|
+
promptRoutes.set(name, { provider, original: prompt.name });
|
|
64
|
+
prompts.push({ ...prompt, name, description: tag(provider, prompt.description) });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
this._tools = tools;
|
|
68
|
+
this._prompts = prompts;
|
|
69
|
+
this._toolRoutes = toolRoutes;
|
|
70
|
+
this._promptRoutes = promptRoutes;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function prefixed(provider, original) {
|
|
74
|
+
return `${provider}${SEPARATOR}${original}`;
|
|
75
|
+
}
|
|
76
|
+
/** Tags a description with the origin provider so the model and user see the source. */
|
|
77
|
+
function tag(provider, description) {
|
|
78
|
+
const label = `[${provider}]`;
|
|
79
|
+
return description ? `${label} ${description}` : label;
|
|
80
|
+
}
|
|
81
|
+
/** Caps a tool name to the API limit, replacing the overflow with a stable hash. */
|
|
82
|
+
function capToolName(name) {
|
|
83
|
+
if (name.length <= MAX_TOOL_NAME_LENGTH)
|
|
84
|
+
return name;
|
|
85
|
+
const hash = djb2(name);
|
|
86
|
+
return name.slice(0, MAX_TOOL_NAME_LENGTH - hash.length - 1) + SEPARATOR + hash;
|
|
87
|
+
}
|
|
88
|
+
/** Disambiguates a name already present in `taken` by appending `-2`, `-3`, ... */
|
|
89
|
+
function unique(candidate, taken) {
|
|
90
|
+
if (!taken.has(candidate))
|
|
91
|
+
return candidate;
|
|
92
|
+
let n = 2;
|
|
93
|
+
while (taken.has(`${candidate}${SEPARATOR}${n}`))
|
|
94
|
+
n++;
|
|
95
|
+
return `${candidate}${SEPARATOR}${n}`;
|
|
96
|
+
}
|
|
97
|
+
/** Small deterministic string hash rendered as 8 base-36 characters. */
|
|
98
|
+
function djb2(input) {
|
|
99
|
+
let h = 5381;
|
|
100
|
+
for (let i = 0; i < input.length; i++) {
|
|
101
|
+
h = ((h << 5) + h + input.charCodeAt(i)) >>> 0;
|
|
102
|
+
}
|
|
103
|
+
return h.toString(36).padStart(8, "0").slice(-8);
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=aggregate.catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate.catalog.js","sourceRoot":"","sources":["../../../src/broker/aggregate/aggregate.catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { IMessageTransport } from "@cyanmycelium/mcp-core";
|
|
2
|
+
import type { InternalClient } from "../../ws.tunnel.js";
|
|
3
|
+
/** Opens an in-process client to a named provider slot. Supplied by WsTunnel. */
|
|
4
|
+
export type InternalClientFactory = (providerName: string) => InternalClient;
|
|
5
|
+
/**
|
|
6
|
+
* The `_all` aggregate MCP server. Presents the union of every opted-in
|
|
7
|
+
* provider's tools and prompts as a single MCP server, reachable on the
|
|
8
|
+
* reserved `_all` slot.
|
|
9
|
+
*
|
|
10
|
+
* It implements {@link IMessageTransport} so it can be registered on the
|
|
11
|
+
* WsTunnel as a loopback provider: `send` receives client requests, `onMessage`
|
|
12
|
+
* (assigned by the tunnel) carries responses and notifications back to clients.
|
|
13
|
+
*/
|
|
14
|
+
export declare class AggregateServer implements IMessageTransport {
|
|
15
|
+
/** Reserved provider slot the aggregate is published on. */
|
|
16
|
+
static readonly SLOT = "_all";
|
|
17
|
+
private readonly _catalog;
|
|
18
|
+
private readonly _sessions;
|
|
19
|
+
private readonly _openClient;
|
|
20
|
+
private _running;
|
|
21
|
+
onMessage: ((data: string) => void) | null;
|
|
22
|
+
onOpen: (() => void) | null;
|
|
23
|
+
onClose: (() => void) | null;
|
|
24
|
+
onError: ((error: Error) => void) | null;
|
|
25
|
+
constructor(openClient: InternalClientFactory);
|
|
26
|
+
get isOpen(): boolean;
|
|
27
|
+
/** Number of providers currently in the aggregate. */
|
|
28
|
+
get providerCount(): number;
|
|
29
|
+
/** Marks the aggregate transport open. Call before registering it. */
|
|
30
|
+
start(): void;
|
|
31
|
+
/** WsTunnel hands a client request for the `_all` slot here. */
|
|
32
|
+
send(data: string): void;
|
|
33
|
+
/** Closes every provider session and the aggregate transport. */
|
|
34
|
+
close(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Adds a provider to the aggregate: opens an internal client, runs the
|
|
37
|
+
* session handshake, and merges the provider's catalog. A no-op for an
|
|
38
|
+
* already-aggregated provider or the reserved `_all` slot itself.
|
|
39
|
+
*/
|
|
40
|
+
addProvider(name: string): Promise<void>;
|
|
41
|
+
/** Removes a provider from the aggregate. */
|
|
42
|
+
removeProvider(name: string): void;
|
|
43
|
+
private _handleClientMessage;
|
|
44
|
+
private _route;
|
|
45
|
+
private _reply;
|
|
46
|
+
private _emitListChanged;
|
|
47
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { AggregateCatalog } from "./aggregate.catalog.js";
|
|
2
|
+
import { ProviderClientSession } from "./provider.client.session.js";
|
|
3
|
+
/** MCP protocol version advertised by the aggregate server. */
|
|
4
|
+
const PROTOCOL_VERSION = "2024-11-05";
|
|
5
|
+
/**
|
|
6
|
+
* The `_all` aggregate MCP server. Presents the union of every opted-in
|
|
7
|
+
* provider's tools and prompts as a single MCP server, reachable on the
|
|
8
|
+
* reserved `_all` slot.
|
|
9
|
+
*
|
|
10
|
+
* It implements {@link IMessageTransport} so it can be registered on the
|
|
11
|
+
* WsTunnel as a loopback provider: `send` receives client requests, `onMessage`
|
|
12
|
+
* (assigned by the tunnel) carries responses and notifications back to clients.
|
|
13
|
+
*/
|
|
14
|
+
export class AggregateServer {
|
|
15
|
+
/** Reserved provider slot the aggregate is published on. */
|
|
16
|
+
static SLOT = "_all";
|
|
17
|
+
_catalog = new AggregateCatalog();
|
|
18
|
+
_sessions = new Map();
|
|
19
|
+
_openClient;
|
|
20
|
+
_running = false;
|
|
21
|
+
onMessage = null;
|
|
22
|
+
onOpen = null;
|
|
23
|
+
onClose = null;
|
|
24
|
+
onError = null;
|
|
25
|
+
constructor(openClient) {
|
|
26
|
+
this._openClient = openClient;
|
|
27
|
+
}
|
|
28
|
+
get isOpen() {
|
|
29
|
+
return this._running;
|
|
30
|
+
}
|
|
31
|
+
/** Number of providers currently in the aggregate. */
|
|
32
|
+
get providerCount() {
|
|
33
|
+
return this._sessions.size;
|
|
34
|
+
}
|
|
35
|
+
/** Marks the aggregate transport open. Call before registering it. */
|
|
36
|
+
start() {
|
|
37
|
+
this._running = true;
|
|
38
|
+
}
|
|
39
|
+
/** WsTunnel hands a client request for the `_all` slot here. */
|
|
40
|
+
send(data) {
|
|
41
|
+
void this._handleClientMessage(data);
|
|
42
|
+
}
|
|
43
|
+
/** Closes every provider session and the aggregate transport. */
|
|
44
|
+
close() {
|
|
45
|
+
if (!this._running)
|
|
46
|
+
return;
|
|
47
|
+
this._running = false;
|
|
48
|
+
for (const session of this._sessions.values())
|
|
49
|
+
session.close();
|
|
50
|
+
this._sessions.clear();
|
|
51
|
+
this.onClose?.();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Adds a provider to the aggregate: opens an internal client, runs the
|
|
55
|
+
* session handshake, and merges the provider's catalog. A no-op for an
|
|
56
|
+
* already-aggregated provider or the reserved `_all` slot itself.
|
|
57
|
+
*/
|
|
58
|
+
async addProvider(name) {
|
|
59
|
+
if (name === AggregateServer.SLOT || this._sessions.has(name))
|
|
60
|
+
return;
|
|
61
|
+
const session = new ProviderClientSession(name, this._openClient(name));
|
|
62
|
+
this._sessions.set(name, session);
|
|
63
|
+
session.onCatalogChanged = () => {
|
|
64
|
+
this._catalog.setProvider(name, { tools: session.tools, prompts: session.prompts });
|
|
65
|
+
this._emitListChanged();
|
|
66
|
+
};
|
|
67
|
+
session.onClosed = () => this.removeProvider(name);
|
|
68
|
+
try {
|
|
69
|
+
await session.initialize();
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
this.removeProvider(name);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Removes a provider from the aggregate. */
|
|
76
|
+
removeProvider(name) {
|
|
77
|
+
const session = this._sessions.get(name);
|
|
78
|
+
if (!session)
|
|
79
|
+
return;
|
|
80
|
+
this._sessions.delete(name);
|
|
81
|
+
session.close();
|
|
82
|
+
this._catalog.removeProvider(name);
|
|
83
|
+
this._emitListChanged();
|
|
84
|
+
}
|
|
85
|
+
async _handleClientMessage(data) {
|
|
86
|
+
let msg;
|
|
87
|
+
try {
|
|
88
|
+
msg = JSON.parse(data);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const id = msg.id;
|
|
94
|
+
if (id == null)
|
|
95
|
+
return; // client notification — nothing to answer
|
|
96
|
+
switch (msg.method) {
|
|
97
|
+
case "initialize":
|
|
98
|
+
this._reply(id, {
|
|
99
|
+
result: {
|
|
100
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
101
|
+
serverInfo: { name: AggregateServer.SLOT, version: "0" },
|
|
102
|
+
capabilities: { tools: { listChanged: true }, prompts: { listChanged: true } },
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
break;
|
|
106
|
+
case "ping":
|
|
107
|
+
this._reply(id, { result: {} });
|
|
108
|
+
break;
|
|
109
|
+
case "tools/list":
|
|
110
|
+
this._reply(id, { result: { tools: this._catalog.tools } });
|
|
111
|
+
break;
|
|
112
|
+
case "prompts/list":
|
|
113
|
+
this._reply(id, { result: { prompts: this._catalog.prompts } });
|
|
114
|
+
break;
|
|
115
|
+
case "tools/call":
|
|
116
|
+
await this._route(id, msg.params, "tool");
|
|
117
|
+
break;
|
|
118
|
+
case "prompts/get":
|
|
119
|
+
await this._route(id, msg.params, "prompt");
|
|
120
|
+
break;
|
|
121
|
+
default:
|
|
122
|
+
this._reply(id, { error: { code: -32601, message: `Method not found: ${msg.method ?? "(none)"}` } });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async _route(id, params, kind) {
|
|
126
|
+
const p = (params ?? {});
|
|
127
|
+
const route = p.name ? (kind === "tool" ? this._catalog.resolveTool(p.name) : this._catalog.resolvePrompt(p.name)) : undefined;
|
|
128
|
+
if (!route) {
|
|
129
|
+
this._reply(id, { error: { code: -32602, message: `Unknown aggregated ${kind}: ${p.name ?? "(none)"}` } });
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const session = this._sessions.get(route.provider);
|
|
133
|
+
if (!session) {
|
|
134
|
+
this._reply(id, { error: { code: -32000, message: `Provider "${route.provider}" is no longer connected` } });
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const args = p.arguments ?? {};
|
|
138
|
+
const outcome = kind === "tool" ? await session.callTool(route.original, args) : await session.getPrompt(route.original, args);
|
|
139
|
+
this._reply(id, outcome.error !== undefined ? { error: outcome.error } : { result: outcome.result });
|
|
140
|
+
}
|
|
141
|
+
_reply(id, body) {
|
|
142
|
+
this.onMessage?.(JSON.stringify({ jsonrpc: "2.0", id, ...body }));
|
|
143
|
+
}
|
|
144
|
+
_emitListChanged() {
|
|
145
|
+
if (!this._running)
|
|
146
|
+
return;
|
|
147
|
+
this.onMessage?.(JSON.stringify({ jsonrpc: "2.0", method: "notifications/tools/list_changed" }));
|
|
148
|
+
this.onMessage?.(JSON.stringify({ jsonrpc: "2.0", method: "notifications/prompts/list_changed" }));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=aggregate.server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate.server.js","sourceRoot":"","sources":["../../../src/broker/aggregate/aggregate.server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { InternalClient } from "../../ws.tunnel.js";
|
|
2
|
+
import type { CatalogTool, CatalogPrompt } from "./aggregate.catalog.js";
|
|
3
|
+
/** Outcome of a JSON-RPC request: exactly one of `result` / `error` is set. */
|
|
4
|
+
interface RpcOutcome {
|
|
5
|
+
result?: unknown;
|
|
6
|
+
error?: unknown;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A hand-rolled JSON-RPC client session to one aggregated provider, running
|
|
10
|
+
* over an in-process {@link InternalClient}.
|
|
11
|
+
*
|
|
12
|
+
* Performs the MCP `initialize` handshake, caches the provider's `tools/list`
|
|
13
|
+
* and `prompts/list`, and re-fetches them when the provider emits a
|
|
14
|
+
* `list_changed` notification. `tools/call` and `prompts/get` are forwarded and
|
|
15
|
+
* their raw result or error relayed back unchanged.
|
|
16
|
+
*/
|
|
17
|
+
export declare class ProviderClientSession {
|
|
18
|
+
readonly provider: string;
|
|
19
|
+
private readonly _client;
|
|
20
|
+
private readonly _idPrefix;
|
|
21
|
+
private readonly _pending;
|
|
22
|
+
private _nextId;
|
|
23
|
+
private _tools;
|
|
24
|
+
private _prompts;
|
|
25
|
+
private _closed;
|
|
26
|
+
/** Fires after the cached catalog changes (initial load or `list_changed`). */
|
|
27
|
+
onCatalogChanged: (() => void) | null;
|
|
28
|
+
/** Fires when the underlying provider slot disconnects. */
|
|
29
|
+
onClosed: (() => void) | null;
|
|
30
|
+
constructor(provider: string, client: InternalClient);
|
|
31
|
+
get tools(): CatalogTool[];
|
|
32
|
+
get prompts(): CatalogPrompt[];
|
|
33
|
+
/** Runs the `initialize` handshake and the first catalog fetch. */
|
|
34
|
+
initialize(): Promise<void>;
|
|
35
|
+
/** Forwards a `tools/call` to the provider, relaying the raw outcome. */
|
|
36
|
+
callTool(name: string, args: Record<string, unknown>): Promise<RpcOutcome>;
|
|
37
|
+
/** Forwards a `prompts/get` to the provider, relaying the raw outcome. */
|
|
38
|
+
getPrompt(name: string, args: Record<string, unknown>): Promise<RpcOutcome>;
|
|
39
|
+
/** Detaches the session and its internal client. */
|
|
40
|
+
close(): void;
|
|
41
|
+
private _refresh;
|
|
42
|
+
/**
|
|
43
|
+
* Calls a list method, following `nextCursor` pagination. A provider that
|
|
44
|
+
* does not implement the primitive answers with an error, which is treated
|
|
45
|
+
* as an empty list.
|
|
46
|
+
*/
|
|
47
|
+
private _listAll;
|
|
48
|
+
private _request;
|
|
49
|
+
private _handleMessage;
|
|
50
|
+
private _rejectAll;
|
|
51
|
+
}
|
|
52
|
+
export {};
|