@cyanmycelium/mcp-broker 0.4.0 → 1.2.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/CONFIGURATION-EN.md +861 -0
- package/.mcp-broker.example/CONFIGURATION-FR.md +871 -0
- package/.mcp-broker.example/README.md +8 -3
- package/.mcp-broker.example/config.json +86 -0
- package/README.md +122 -3
- package/dist/bin.d.ts +0 -1
- package/dist/bin.js +180 -208
- package/dist/bin.js.map +1 -1
- package/dist/chunk-FTDKH2C4.js +3670 -0
- package/dist/chunk-FTDKH2C4.js.map +1 -0
- package/dist/{broker/grammars → grammars}/claude/en.json +1 -1
- package/dist/{broker/grammars → grammars}/claude/fr.json +1 -1
- package/dist/index.d.ts +1790 -18
- package/dist/index.js +2 -14
- package/dist/index.js.map +1 -1
- package/package.json +14 -8
- package/scripts/copy-assets.mjs +16 -10
- package/scripts/gen-cert.mjs +5 -5
- package/scripts/pack-mcpb.mjs +5 -5
- package/scripts/sign-bundle.mjs +6 -6
- package/src/auth/auth.config.ts +98 -0
- package/src/auth/auth.types.ts +120 -0
- package/src/auth/http.auth.ts +128 -0
- package/src/auth/index.ts +34 -0
- package/src/auth/jwt.validator.ts +63 -0
- package/src/auth/provider.auth.ts +114 -0
- package/src/auth/resource.metadata.ts +34 -0
- package/src/authorization/audit.ts +35 -0
- package/src/authorization/capability.classifier.ts +114 -0
- package/src/authorization/index.ts +37 -0
- package/src/authorization/policy.engine.ts +212 -0
- package/src/authorization/policy.types.ts +105 -0
- package/src/authorization/resource.path.ts +126 -0
- package/src/authorization/runtime.ts +56 -0
- package/src/authorization/slot.resource.ts +50 -0
- package/src/authorization/subject.mapper.ts +81 -0
- package/src/bin.ts +90 -7
- package/src/broker/adapters/broker.adapter.info.ts +3 -3
- package/src/broker/adapters/broker.adapter.providers.ts +3 -3
- package/src/broker/aggregate/aggregate.catalog.ts +49 -21
- package/src/broker/aggregate/aggregate.server.ts +149 -19
- package/src/broker/aggregate/provider.client.session.ts +22 -22
- package/src/broker/behaviors/broker.behavior.info.ts +4 -4
- package/src/broker/behaviors/broker.behavior.providers.ts +6 -6
- package/src/broker/broker.context.ts +10 -4
- package/src/broker/broker.grammars.ts +16 -13
- package/src/broker/broker.server.ts +12 -9
- package/src/broker/grammars/claude/en.json +1 -1
- package/src/broker/grammars/claude/fr.json +1 -1
- package/src/broker/index.ts +9 -9
- package/src/config.ts +81 -8
- package/src/index.ts +121 -20
- package/src/{mcpb.loader.ts → mcpb/mcpb.loader.ts} +24 -21
- package/src/{mcpb.unzip.ts → mcpb/mcpb.unzip.ts} +2 -2
- package/src/remote.transports.ts +11 -8
- package/src/remote.upstream.ts +11 -8
- package/src/stdio.upstream.ts +9 -6
- package/src/upstream.ts +6 -3
- package/src/ws/ws.interfaces.ts +357 -0
- package/src/{ws.tunnel.builder.ts → ws/ws.tunnel.builder.ts} +112 -9
- package/src/{ws.tunnel.ts → ws/ws.tunnel.ts} +646 -457
- package/web/README.md +94 -0
- package/web/assets/logo.png +0 -0
- package/web/broker-self-mcp.html +338 -0
- package/web/css/styles.css +580 -0
- package/web/demos/DemoPlaceholder.html +258 -0
- package/web/demos/broker-explorer/css/app.css +393 -0
- package/web/demos/broker-explorer/index.html +94 -0
- package/web/demos/broker-explorer/js/app.js +271 -0
- package/web/demos/broker-explorer/js/mcp-ws-client.js +132 -0
- package/web/demos/oauth-lab/README.md +94 -0
- package/web/demos/oauth-lab/config.json +117 -0
- package/web/demos/oauth-lab/css/app.css +1097 -0
- package/web/demos/oauth-lab/index.html +323 -0
- package/web/demos/oauth-lab/js/app.js +654 -0
- package/web/demos/oauth-lab/server/auth-server.mjs +426 -0
- package/web/demos/oauth-lab/server/factory-provider.mjs +269 -0
- package/web/demos/oauth-lab/server/smoke-test.mjs +308 -0
- package/web/demos/oauth-lab/server/start.mjs +106 -0
- package/web/demos/provider-tunnel/css/app.css +384 -0
- package/web/demos/provider-tunnel/index.html +99 -0
- package/web/demos/provider-tunnel/js/app.js +226 -0
- package/web/demos/provider-tunnel/js/toolbox-server.js +186 -0
- package/web/index.html +558 -0
- package/web/js/lib/broker-tunnel.js +173 -0
- package/dist/broker/adapters/broker.adapter.info.d.ts +0 -16
- package/dist/broker/adapters/broker.adapter.info.js +0 -43
- package/dist/broker/adapters/broker.adapter.info.js.map +0 -1
- package/dist/broker/adapters/broker.adapter.providers.d.ts +0 -18
- package/dist/broker/adapters/broker.adapter.providers.js +0 -61
- package/dist/broker/adapters/broker.adapter.providers.js.map +0 -1
- package/dist/broker/aggregate/aggregate.catalog.d.ts +0 -54
- package/dist/broker/aggregate/aggregate.catalog.js +0 -105
- package/dist/broker/aggregate/aggregate.catalog.js.map +0 -1
- package/dist/broker/aggregate/aggregate.server.d.ts +0 -47
- package/dist/broker/aggregate/aggregate.server.js +0 -151
- package/dist/broker/aggregate/aggregate.server.js.map +0 -1
- package/dist/broker/aggregate/provider.client.session.d.ts +0 -52
- package/dist/broker/aggregate/provider.client.session.js +0 -140
- package/dist/broker/aggregate/provider.client.session.js.map +0 -1
- package/dist/broker/behaviors/broker.behavior.info.d.ts +0 -15
- package/dist/broker/behaviors/broker.behavior.info.js +0 -41
- package/dist/broker/behaviors/broker.behavior.info.js.map +0 -1
- package/dist/broker/behaviors/broker.behavior.providers.d.ts +0 -19
- package/dist/broker/behaviors/broker.behavior.providers.js +0 -69
- package/dist/broker/behaviors/broker.behavior.providers.js.map +0 -1
- package/dist/broker/broker.context.d.ts +0 -59
- package/dist/broker/broker.context.js +0 -2
- package/dist/broker/broker.context.js.map +0 -1
- package/dist/broker/broker.grammars.d.ts +0 -130
- package/dist/broker/broker.grammars.js +0 -229
- package/dist/broker/broker.grammars.js.map +0 -1
- package/dist/broker/broker.server.d.ts +0 -66
- package/dist/broker/broker.server.js +0 -73
- package/dist/broker/broker.server.js.map +0 -1
- package/dist/broker/index.d.ts +0 -9
- package/dist/broker/index.js +0 -7
- package/dist/broker/index.js.map +0 -1
- package/dist/config.d.ts +0 -136
- package/dist/config.js +0 -61
- package/dist/config.js.map +0 -1
- package/dist/mcpb.loader.d.ts +0 -24
- package/dist/mcpb.loader.js +0 -161
- package/dist/mcpb.loader.js.map +0 -1
- package/dist/mcpb.unzip.d.ts +0 -6
- package/dist/mcpb.unzip.js +0 -95
- package/dist/mcpb.unzip.js.map +0 -1
- package/dist/remote.transports.d.ts +0 -16
- package/dist/remote.transports.js +0 -297
- package/dist/remote.transports.js.map +0 -1
- package/dist/remote.upstream.d.ts +0 -36
- package/dist/remote.upstream.js +0 -52
- package/dist/remote.upstream.js.map +0 -1
- package/dist/stdio.upstream.d.ts +0 -45
- package/dist/stdio.upstream.js +0 -85
- package/dist/stdio.upstream.js.map +0 -1
- package/dist/upstream.d.ts +0 -33
- package/dist/upstream.js +0 -2
- package/dist/upstream.js.map +0 -1
- package/dist/version.d.ts +0 -2
- package/dist/version.js +0 -9
- package/dist/version.js.map +0 -1
- package/dist/ws.tunnel.builder.d.ts +0 -139
- package/dist/ws.tunnel.builder.js +0 -205
- package/dist/ws.tunnel.builder.js.map +0 -1
- package/dist/ws.tunnel.d.ts +0 -373
- package/dist/ws.tunnel.js +0 -1090
- package/dist/ws.tunnel.js.map +0 -1
- /package/dist/{broker/grammars → grammars}/default/en.json +0 -0
- /package/dist/{broker/grammars → grammars}/default/fr.json +0 -0
- /package/dist/{broker/grammars → grammars}/default/zh.json +0 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* broker-tunnel.js, connect an MCP server to @cyanmycelium/mcp-broker.
|
|
3
|
+
*
|
|
4
|
+
* This is the ONLY broker-specific code you need to tunnel an MCP server
|
|
5
|
+
* (browser-side or anywhere a WebSocket is available) to the broker. Copy
|
|
6
|
+
* this file as-is; it has zero dependencies.
|
|
7
|
+
*
|
|
8
|
+
* The broker's provider model is "the server dials out": an MCP server opens
|
|
9
|
+
* an outbound WebSocket to `/provider/<name>` and the broker relays every MCP
|
|
10
|
+
* client that targets that slot. No shipped MCP SDK transport covers that
|
|
11
|
+
* direction, so `BrokerTunnelTransport` below is a thin shim implementing the
|
|
12
|
+
* SDK's structural `Transport` interface (start / send / close / onmessage /
|
|
13
|
+
* onclose / onerror) over a browser `WebSocket`. The MCP protocol itself is
|
|
14
|
+
* untouched: any standard MCP server works through it.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* import { Server } from "https://esm.sh/@modelcontextprotocol/sdk@1.12.3/server/index.js";
|
|
18
|
+
* import { BrokerTunnelTransport } from "./lib/broker-tunnel.js";
|
|
19
|
+
*
|
|
20
|
+
* const server = new Server({ name: "my-provider", version: "1.0.0" },
|
|
21
|
+
* { capabilities: { tools: {} } });
|
|
22
|
+
* // server.setRequestHandler(...), your tools and resources
|
|
23
|
+
*
|
|
24
|
+
* const transport = new BrokerTunnelTransport("ws://localhost:3000/provider/my-provider");
|
|
25
|
+
* transport.onTunnelClose = (code, reason) =>
|
|
26
|
+
* console.log(describeTunnelClose(code, reason));
|
|
27
|
+
* await server.connect(transport);
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* MCP SDK transport backed by an outbound WebSocket to the broker.
|
|
32
|
+
*
|
|
33
|
+
* The MCP SDK owns `onmessage` / `onclose` / `onerror` (it assigns them inside
|
|
34
|
+
* `Server.connect`). The page observes the raw socket through the separate
|
|
35
|
+
* `onTunnelOpen` / `onTunnelClose` / `onTunnelError` hooks, so application code
|
|
36
|
+
* and the SDK never overwrite each other's callbacks.
|
|
37
|
+
*/
|
|
38
|
+
export class BrokerTunnelTransport {
|
|
39
|
+
/**
|
|
40
|
+
* @param {string} url Full provider URL, e.g. `ws://host:3000/provider/<name>`.
|
|
41
|
+
* @param {{ aggregate?: boolean }} [options] When `aggregate` is true, the
|
|
42
|
+
* transport sends a broker registration frame on open so this server
|
|
43
|
+
* joins the broker's `_all` aggregate slot.
|
|
44
|
+
*/
|
|
45
|
+
constructor(url, options = {}) {
|
|
46
|
+
this.url = url;
|
|
47
|
+
this._ws = null;
|
|
48
|
+
this._aggregate = options.aggregate === true;
|
|
49
|
+
|
|
50
|
+
// Set by the MCP SDK inside Server.connect(), do not assign these yourself.
|
|
51
|
+
this.onmessage = null;
|
|
52
|
+
this.onclose = null;
|
|
53
|
+
this.onerror = null;
|
|
54
|
+
|
|
55
|
+
// Page-owned observation hooks, assign these before Server.connect().
|
|
56
|
+
/** @type {null | (() => void)} */
|
|
57
|
+
this.onTunnelOpen = null;
|
|
58
|
+
/** @type {null | ((code: number, reason: string) => void)} */
|
|
59
|
+
this.onTunnelClose = null;
|
|
60
|
+
/** @type {null | ((error: Error) => void)} */
|
|
61
|
+
this.onTunnelError = null;
|
|
62
|
+
|
|
63
|
+
// Last close code/reason, useful for diagnostics after the fact.
|
|
64
|
+
this.closeCode = null;
|
|
65
|
+
this.closeReason = "";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Opens the WebSocket. Called by `Server.connect()`. The returned promise
|
|
70
|
+
* resolves once the broker accepts the WebSocket upgrade.
|
|
71
|
+
*
|
|
72
|
+
* Note: a successful upgrade is not yet a usable slot: the broker may
|
|
73
|
+
* still reject the slot at the application layer with a 1008 close (name
|
|
74
|
+
* already taken, or reserved) a few milliseconds later. Watch
|
|
75
|
+
* `onTunnelClose` for that case.
|
|
76
|
+
*
|
|
77
|
+
* @returns {Promise<void>}
|
|
78
|
+
*/
|
|
79
|
+
start() {
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
let opened = false;
|
|
82
|
+
const ws = new WebSocket(this.url);
|
|
83
|
+
this._ws = ws;
|
|
84
|
+
|
|
85
|
+
ws.onopen = () => {
|
|
86
|
+
opened = true;
|
|
87
|
+
// Optional broker registration frame: it MUST precede any MCP
|
|
88
|
+
// traffic, so it is sent here before start() resolves.
|
|
89
|
+
if (this._aggregate) {
|
|
90
|
+
ws.send(JSON.stringify({ type: "register", aggregate: true }));
|
|
91
|
+
}
|
|
92
|
+
this.onTunnelOpen?.();
|
|
93
|
+
resolve();
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
ws.onerror = () => {
|
|
97
|
+
const err = new Error(`WebSocket error on ${this.url}`);
|
|
98
|
+
this.onTunnelError?.(err);
|
|
99
|
+
this.onerror?.(err);
|
|
100
|
+
// Reject start() only if the socket never opened: a post-open
|
|
101
|
+
// error is a runtime failure, not a connect failure.
|
|
102
|
+
if (!opened) reject(err);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
ws.onclose = (ev) => {
|
|
106
|
+
this.closeCode = ev.code;
|
|
107
|
+
this.closeReason = ev.reason;
|
|
108
|
+
this.onTunnelClose?.(ev.code, ev.reason);
|
|
109
|
+
this.onclose?.();
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
ws.onmessage = (ev) => {
|
|
113
|
+
let parsed;
|
|
114
|
+
try {
|
|
115
|
+
parsed = JSON.parse(typeof ev.data === "string" ? ev.data : "");
|
|
116
|
+
} catch {
|
|
117
|
+
return; // not JSON, drop
|
|
118
|
+
}
|
|
119
|
+
this.onmessage?.(parsed);
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Sends one JSON-RPC message. Called by the MCP SDK.
|
|
126
|
+
* @param {object} message
|
|
127
|
+
* @returns {Promise<void>}
|
|
128
|
+
*/
|
|
129
|
+
send(message) {
|
|
130
|
+
if (this._ws && this._ws.readyState === WebSocket.OPEN) {
|
|
131
|
+
this._ws.send(JSON.stringify(message));
|
|
132
|
+
}
|
|
133
|
+
return Promise.resolve();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Closes the WebSocket. Called by `Server.close()`.
|
|
138
|
+
* @returns {Promise<void>}
|
|
139
|
+
*/
|
|
140
|
+
close() {
|
|
141
|
+
this._ws?.close();
|
|
142
|
+
return Promise.resolve();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** WebSocket close code the broker uses to reject a provider slot. */
|
|
147
|
+
export const BROKER_REJECT_CODE = 1008;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Turns a tunnel WebSocket close into a human-readable diagnosis: the
|
|
151
|
+
* "handshake check". Three cases matter when tunnelling to the broker:
|
|
152
|
+
*
|
|
153
|
+
* - 1008 → the broker rejected the slot (name already connected, or reserved).
|
|
154
|
+
* - closed before the tunnel was ever up → the broker is unreachable.
|
|
155
|
+
* - any other close while up → the tunnel dropped unexpectedly.
|
|
156
|
+
*
|
|
157
|
+
* @param {number} code WebSocket close code.
|
|
158
|
+
* @param {string} reason WebSocket close reason (may be empty).
|
|
159
|
+
* @param {boolean} wasOpen Whether the tunnel had reached a usable state.
|
|
160
|
+
* @returns {{ level: "error" | "warn", message: string }}
|
|
161
|
+
*/
|
|
162
|
+
export function describeTunnelClose(code, reason, wasOpen) {
|
|
163
|
+
if (code === BROKER_REJECT_CODE) {
|
|
164
|
+
return { level: "error", message: `Broker rejected the provider slot: ${reason || "policy violation (1008)"}` };
|
|
165
|
+
}
|
|
166
|
+
if (!wasOpen) {
|
|
167
|
+
return { level: "error", message: "Broker unreachable: the WebSocket closed before the tunnel opened." };
|
|
168
|
+
}
|
|
169
|
+
if (code && code !== 1000 && code !== 1005) {
|
|
170
|
+
return { level: "warn", message: `Tunnel closed unexpectedly (code ${code}${reason ? ", " + reason : ""}).` };
|
|
171
|
+
}
|
|
172
|
+
return { level: "warn", message: "Tunnel closed." };
|
|
173
|
+
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { McpAdapterBase } from "@cyanmycelium/mcp-core";
|
|
2
|
-
import type { McpResourceContent, McpToolResult } from "@cyanmycelium/mcp-core";
|
|
3
|
-
import type { BrokerContext } from "../broker.context.js";
|
|
4
|
-
/** URI of the static resource backing the `broker_info` snapshot. */
|
|
5
|
-
export declare const BROKER_INFO_URI = "broker://info";
|
|
6
|
-
/**
|
|
7
|
-
* Read-only adapter that produces a snapshot of the broker's identity and
|
|
8
|
-
* configuration. Backed by the live {@link BrokerContext}.
|
|
9
|
-
*/
|
|
10
|
-
export declare class BrokerInfoAdapter extends McpAdapterBase {
|
|
11
|
-
private readonly _context;
|
|
12
|
-
constructor(_context: BrokerContext);
|
|
13
|
-
readResourceAsync(uri: string): Promise<McpResourceContent | undefined>;
|
|
14
|
-
executeToolAsync(_uri: string, toolName: string, _args: Record<string, unknown>): Promise<McpToolResult>;
|
|
15
|
-
private _snapshot;
|
|
16
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { McpAdapterBase, McpToolResults } from "@cyanmycelium/mcp-core";
|
|
2
|
-
/** URI of the static resource backing the `broker_info` snapshot. */
|
|
3
|
-
export const BROKER_INFO_URI = "broker://info";
|
|
4
|
-
/**
|
|
5
|
-
* Read-only adapter that produces a snapshot of the broker's identity and
|
|
6
|
-
* configuration. Backed by the live {@link BrokerContext}.
|
|
7
|
-
*/
|
|
8
|
-
export class BrokerInfoAdapter extends McpAdapterBase {
|
|
9
|
-
_context;
|
|
10
|
-
constructor(_context) {
|
|
11
|
-
super("broker");
|
|
12
|
-
this._context = _context;
|
|
13
|
-
}
|
|
14
|
-
async readResourceAsync(uri) {
|
|
15
|
-
if (uri !== BROKER_INFO_URI)
|
|
16
|
-
return undefined;
|
|
17
|
-
return {
|
|
18
|
-
uri,
|
|
19
|
-
mimeType: "application/json",
|
|
20
|
-
text: JSON.stringify(this._snapshot()),
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
async executeToolAsync(_uri, toolName, _args) {
|
|
24
|
-
if (toolName !== "broker_info") {
|
|
25
|
-
return McpToolResults.error(`Unknown tool: ${toolName}`);
|
|
26
|
-
}
|
|
27
|
-
return McpToolResults.json(this._snapshot());
|
|
28
|
-
}
|
|
29
|
-
_snapshot() {
|
|
30
|
-
const c = this._context;
|
|
31
|
-
return {
|
|
32
|
-
name: c.name,
|
|
33
|
-
version: c.version,
|
|
34
|
-
startedAt: c.startedAt?.toISOString() ?? null,
|
|
35
|
-
uptimeSeconds: c.uptimeSeconds,
|
|
36
|
-
host: c.host ?? "0.0.0.0",
|
|
37
|
-
port: c.port,
|
|
38
|
-
tls: c.tls,
|
|
39
|
-
paths: c.paths,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=broker.adapter.info.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"broker.adapter.info.js","sourceRoot":"","sources":["../../../src/broker/adapters/broker.adapter.info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAIxE,qEAAqE;AACrE,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC;AAE/C;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,cAAc;IACpB;IAA7B,YAA6B,QAAuB;QAChD,KAAK,CAAC,QAAQ,CAAC,CAAC;QADS,aAAQ,GAAR,QAAQ,CAAe;IAEpD,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,GAAW;QACtC,IAAI,GAAG,KAAK,eAAe;YAAE,OAAO,SAAS,CAAC;QAC9C,OAAO;YACH,GAAG;YACH,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;SACzC,CAAC;IACN,CAAC;IAEM,KAAK,CAAC,gBAAgB,CAAC,IAAY,EAAE,QAAgB,EAAE,KAA8B;QACxF,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;YAC7B,OAAO,cAAc,CAAC,KAAK,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IACjD,CAAC;IAEO,SAAS;QACb,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;QACxB,OAAO;YACH,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,IAAI;YAC7C,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,SAAS;YACzB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,KAAK,EAAE,CAAC,CAAC,KAAK;SACjB,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { McpAdapterBase } from "@cyanmycelium/mcp-core";
|
|
2
|
-
import type { McpResourceContent, McpToolResult } from "@cyanmycelium/mcp-core";
|
|
3
|
-
import type { BrokerContext } from "../broker.context.js";
|
|
4
|
-
/** URI of the static resource that lists every provider slot. */
|
|
5
|
-
export declare const PROVIDERS_URI = "broker://providers";
|
|
6
|
-
/** RFC 6570 URI template for one specific provider slot. */
|
|
7
|
-
export declare const PROVIDER_URI_TEMPLATE = "broker://providers/{name}";
|
|
8
|
-
/**
|
|
9
|
-
* Adapter that exposes the broker's current provider slots, both as a list
|
|
10
|
-
* (read of `broker://providers`) and individually (`broker://providers/<name>`).
|
|
11
|
-
*/
|
|
12
|
-
export declare class BrokerProvidersAdapter extends McpAdapterBase {
|
|
13
|
-
private readonly _context;
|
|
14
|
-
constructor(_context: BrokerContext);
|
|
15
|
-
readResourceAsync(uri: string): Promise<McpResourceContent | undefined>;
|
|
16
|
-
executeToolAsync(_uri: string, toolName: string, args: Record<string, unknown>): Promise<McpToolResult>;
|
|
17
|
-
private _listSnapshot;
|
|
18
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { McpAdapterBase, McpToolResults } from "@cyanmycelium/mcp-core";
|
|
2
|
-
/** URI of the static resource that lists every provider slot. */
|
|
3
|
-
export const PROVIDERS_URI = "broker://providers";
|
|
4
|
-
/** RFC 6570 URI template for one specific provider slot. */
|
|
5
|
-
export const PROVIDER_URI_TEMPLATE = "broker://providers/{name}";
|
|
6
|
-
/**
|
|
7
|
-
* Adapter that exposes the broker's current provider slots, both as a list
|
|
8
|
-
* (read of `broker://providers`) and individually (`broker://providers/<name>`).
|
|
9
|
-
*/
|
|
10
|
-
export class BrokerProvidersAdapter extends McpAdapterBase {
|
|
11
|
-
_context;
|
|
12
|
-
constructor(_context) {
|
|
13
|
-
super("broker");
|
|
14
|
-
this._context = _context;
|
|
15
|
-
}
|
|
16
|
-
async readResourceAsync(uri) {
|
|
17
|
-
if (uri === PROVIDERS_URI) {
|
|
18
|
-
return {
|
|
19
|
-
uri,
|
|
20
|
-
mimeType: "application/json",
|
|
21
|
-
text: JSON.stringify(this._listSnapshot()),
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
// broker://providers/<name>
|
|
25
|
-
const match = /^broker:\/\/providers\/([^/]+)$/.exec(uri);
|
|
26
|
-
if (match) {
|
|
27
|
-
const name = decodeURIComponent(match[1]);
|
|
28
|
-
const info = this._context.getProviderInfo(name);
|
|
29
|
-
if (!info)
|
|
30
|
-
return undefined;
|
|
31
|
-
return {
|
|
32
|
-
uri,
|
|
33
|
-
mimeType: "application/json",
|
|
34
|
-
text: JSON.stringify(info),
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
return undefined;
|
|
38
|
-
}
|
|
39
|
-
async executeToolAsync(_uri, toolName, args) {
|
|
40
|
-
switch (toolName) {
|
|
41
|
-
case "providers_list":
|
|
42
|
-
return McpToolResults.json(this._listSnapshot());
|
|
43
|
-
case "provider_status": {
|
|
44
|
-
const name = typeof args.name === "string" ? args.name : "";
|
|
45
|
-
if (!name)
|
|
46
|
-
return McpToolResults.error('Missing required argument: "name" (string).');
|
|
47
|
-
const info = this._context.getProviderInfo(name);
|
|
48
|
-
if (!info)
|
|
49
|
-
return McpToolResults.error(`Unknown provider: "${name}".`);
|
|
50
|
-
return McpToolResults.json(info);
|
|
51
|
-
}
|
|
52
|
-
default:
|
|
53
|
-
return McpToolResults.error(`Unknown tool: ${toolName}`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
_listSnapshot() {
|
|
57
|
-
const providers = this._context.getProvidersInfo();
|
|
58
|
-
return { count: providers.length, providers };
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
//# sourceMappingURL=broker.adapter.providers.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"broker.adapter.providers.js","sourceRoot":"","sources":["../../../src/broker/adapters/broker.adapter.providers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAIxE,iEAAiE;AACjE,MAAM,CAAC,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAElD,4DAA4D;AAC5D,MAAM,CAAC,MAAM,qBAAqB,GAAG,2BAA2B,CAAC;AAEjE;;;GAGG;AACH,MAAM,OAAO,sBAAuB,SAAQ,cAAc;IACzB;IAA7B,YAA6B,QAAuB;QAChD,KAAK,CAAC,QAAQ,CAAC,CAAC;QADS,aAAQ,GAAR,QAAQ,CAAe;IAEpD,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,GAAW;QACtC,IAAI,GAAG,KAAK,aAAa,EAAE,CAAC;YACxB,OAAO;gBACH,GAAG;gBACH,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;aAC7C,CAAC;QACN,CAAC;QAED,4BAA4B;QAC5B,MAAM,KAAK,GAAG,iCAAiC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1D,IAAI,KAAK,EAAE,CAAC;YACR,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACjD,IAAI,CAAC,IAAI;gBAAE,OAAO,SAAS,CAAC;YAC5B,OAAO;gBACH,GAAG;gBACH,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC7B,CAAC;QACN,CAAC;QAED,OAAO,SAAS,CAAC;IACrB,CAAC;IAEM,KAAK,CAAC,gBAAgB,CAAC,IAAY,EAAE,QAAgB,EAAE,IAA6B;QACvF,QAAQ,QAAQ,EAAE,CAAC;YACf,KAAK,gBAAgB;gBACjB,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;YAErD,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACrB,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5D,IAAI,CAAC,IAAI;oBAAE,OAAO,cAAc,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;gBACtF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;gBACjD,IAAI,CAAC,IAAI;oBAAE,OAAO,cAAc,CAAC,KAAK,CAAC,sBAAsB,IAAI,IAAI,CAAC,CAAC;gBACvE,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrC,CAAC;YAED;gBACI,OAAO,cAAc,CAAC,KAAK,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;QACjE,CAAC;IACL,CAAC;IAEO,aAAa;QACjB,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QACnD,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC;IAClD,CAAC;CACJ"}
|
|
@@ -1,54 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"aggregate.catalog.js","sourceRoot":"","sources":["../../../src/broker/aggregate/aggregate.catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,47 +0,0 @@
|
|
|
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
|
-
}
|