@cyanmycelium/mcp-broker 0.1.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.
Files changed (78) hide show
  1. package/.mcp-broker.example/README.md +53 -0
  2. package/.mcp-broker.example/config.json +32 -0
  3. package/.mcp-broker.example/grammars/claude/fr.json +7 -0
  4. package/LICENSE +201 -0
  5. package/README.md +253 -0
  6. package/dist/bin.d.ts +2 -0
  7. package/dist/bin.js +208 -0
  8. package/dist/bin.js.map +1 -0
  9. package/dist/broker/adapters/broker.adapter.info.d.ts +16 -0
  10. package/dist/broker/adapters/broker.adapter.info.js +43 -0
  11. package/dist/broker/adapters/broker.adapter.info.js.map +1 -0
  12. package/dist/broker/adapters/broker.adapter.providers.d.ts +18 -0
  13. package/dist/broker/adapters/broker.adapter.providers.js +61 -0
  14. package/dist/broker/adapters/broker.adapter.providers.js.map +1 -0
  15. package/dist/broker/behaviors/broker.behavior.info.d.ts +15 -0
  16. package/dist/broker/behaviors/broker.behavior.info.js +41 -0
  17. package/dist/broker/behaviors/broker.behavior.info.js.map +1 -0
  18. package/dist/broker/behaviors/broker.behavior.providers.d.ts +19 -0
  19. package/dist/broker/behaviors/broker.behavior.providers.js +69 -0
  20. package/dist/broker/behaviors/broker.behavior.providers.js.map +1 -0
  21. package/dist/broker/broker.context.d.ts +59 -0
  22. package/dist/broker/broker.context.js +2 -0
  23. package/dist/broker/broker.context.js.map +1 -0
  24. package/dist/broker/broker.grammars.d.ts +166 -0
  25. package/dist/broker/broker.grammars.js +258 -0
  26. package/dist/broker/broker.grammars.js.map +1 -0
  27. package/dist/broker/broker.server.d.ts +64 -0
  28. package/dist/broker/broker.server.js +111 -0
  29. package/dist/broker/broker.server.js.map +1 -0
  30. package/dist/broker/grammars/claude/en.json +16 -0
  31. package/dist/broker/grammars/claude/fr.json +16 -0
  32. package/dist/broker/grammars/default/en.json +32 -0
  33. package/dist/broker/grammars/default/fr.json +32 -0
  34. package/dist/broker/grammars/default/zh.json +32 -0
  35. package/dist/broker/index.d.ts +9 -0
  36. package/dist/broker/index.js +7 -0
  37. package/dist/broker/index.js.map +1 -0
  38. package/dist/config.d.ts +101 -0
  39. package/dist/config.js +61 -0
  40. package/dist/config.js.map +1 -0
  41. package/dist/index.d.ts +12 -0
  42. package/dist/index.js +11 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/stdio.upstream.d.ts +42 -0
  45. package/dist/stdio.upstream.js +85 -0
  46. package/dist/stdio.upstream.js.map +1 -0
  47. package/dist/version.d.ts +2 -0
  48. package/dist/version.js +9 -0
  49. package/dist/version.js.map +1 -0
  50. package/dist/ws.tunnel.builder.d.ts +133 -0
  51. package/dist/ws.tunnel.builder.js +197 -0
  52. package/dist/ws.tunnel.builder.js.map +1 -0
  53. package/dist/ws.tunnel.d.ts +310 -0
  54. package/dist/ws.tunnel.js +971 -0
  55. package/dist/ws.tunnel.js.map +1 -0
  56. package/package.json +86 -0
  57. package/scripts/copy-assets.mjs +34 -0
  58. package/scripts/gen-cert.mjs +94 -0
  59. package/src/bin.ts +231 -0
  60. package/src/broker/adapters/broker.adapter.info.ts +46 -0
  61. package/src/broker/adapters/broker.adapter.providers.ts +67 -0
  62. package/src/broker/behaviors/broker.behavior.info.ts +46 -0
  63. package/src/broker/behaviors/broker.behavior.providers.ts +82 -0
  64. package/src/broker/broker.context.ts +75 -0
  65. package/src/broker/broker.grammars.ts +336 -0
  66. package/src/broker/broker.server.ts +168 -0
  67. package/src/broker/grammars/claude/en.json +16 -0
  68. package/src/broker/grammars/claude/fr.json +16 -0
  69. package/src/broker/grammars/default/en.json +32 -0
  70. package/src/broker/grammars/default/fr.json +32 -0
  71. package/src/broker/grammars/default/zh.json +32 -0
  72. package/src/broker/index.ts +24 -0
  73. package/src/config.ts +155 -0
  74. package/src/index.ts +26 -0
  75. package/src/stdio.upstream.ts +114 -0
  76. package/src/version.ts +10 -0
  77. package/src/ws.tunnel.builder.ts +214 -0
  78. package/src/ws.tunnel.ts +1269 -0
@@ -0,0 +1,166 @@
1
+ import type { McpClientInfo } from "@cyanmycelium/mcp-core";
2
+ import { McpGrammar } from "@cyanmycelium/mcp-core";
3
+ /**
4
+ * Locale identifier used to look up a grammar JSON file under
5
+ * `<userAgent>/<locale>.json`. Open string: an application can introduce any
6
+ * value its custom resolver and JSON resources support.
7
+ *
8
+ * The {@link defaultBrokerLocaleResolver} returns the ISO 639-1 prefix of a
9
+ * BCP-47 tag (`"fr-CA"` → `"fr"`, `"zh-Hans"` → `"zh"`).
10
+ */
11
+ export type BrokerLocale = string;
12
+ /**
13
+ * User-agent family identifier used to look up a grammar JSON file under
14
+ * `<userAgent>/<locale>.json`. Open string. The {@link defaultBrokerUserAgentResolver}
15
+ * recognizes the common LLM families and returns `"default"` for everything else.
16
+ */
17
+ export type BrokerUserAgent = string;
18
+ /**
19
+ * Picks an **ordered fallback chain** of {@link BrokerLocale} values from a raw
20
+ * input. Typically the raw input is `process.env.MCP_BROKER_LOCALE`, but any
21
+ * string source works (HTTP header, session metadata, etc.).
22
+ *
23
+ * The returned array is consumed by the broker server most-specific-first, so
24
+ * the resolver controls the BCP-47 narrowing policy. The default resolver
25
+ * follows the standard `lang-region` → `lang` → `en` shape:
26
+ *
27
+ * ```
28
+ * raw = "fr-CA" → ["fr-ca", "fr", "en"]
29
+ * raw = "en-US" → ["en-us", "en"]
30
+ * raw = "zh" → ["zh", "en"]
31
+ * raw = "" → ["en"]
32
+ * ```
33
+ *
34
+ * A custom resolver may shape the chain however it wants — e.g. inject a
35
+ * project-specific dialect first, skip the bare language prefix, or pull
36
+ * candidates from a session config.
37
+ */
38
+ export type BrokerLocaleResolver = (raw: string | undefined) => BrokerLocale[];
39
+ /**
40
+ * Picks a {@link BrokerUserAgent} from the connecting client's identity. Called
41
+ * by the embedded broker `McpServer` once per session, during the MCP
42
+ * `initialize` handshake.
43
+ */
44
+ export type BrokerUserAgentResolver = (clientInfo: McpClientInfo | undefined) => BrokerUserAgent;
45
+ /**
46
+ * Default locale resolver — emits the BCP-47 narrowing chain for a raw locale
47
+ * tag, from most specific to least specific, always ending with the universal
48
+ * `"en"` fallback.
49
+ *
50
+ * Steps for an input `raw`:
51
+ * 1. Lowercase the input.
52
+ * 2. Push it as the most-specific candidate (only if non-empty).
53
+ * 3. If it contains a `-` separator, push its bare language prefix next.
54
+ * 4. Always push `"en"` last as the universal fallback.
55
+ *
56
+ * The broker server tries each candidate in turn against `<userAgent>/<locale>.json`
57
+ * — so dropping a `claude/fr-ca.json` lets Canadian-French Claude clients
58
+ * pick up that specific dialect, while clients with `fr` or `fr-FR` fall back
59
+ * to `claude/fr.json` or `default/fr.json` automatically.
60
+ *
61
+ * Examples:
62
+ * - `"fr-CA"` → `["fr-ca", "fr", "en"]`
63
+ * - `"fr"` → `["fr", "en"]`
64
+ * - `"zh-CN"` → `["zh-cn", "zh", "en"]`
65
+ * - `"en-US"` → `["en-us", "en"]`
66
+ * - `""` / `undefined` → `["en"]`
67
+ */
68
+ export declare const defaultBrokerLocaleResolver: BrokerLocaleResolver;
69
+ /**
70
+ * Default user-agent resolver — substring match on `clientInfo.name` against
71
+ * a list of known LLM family hints. Unknown clients fall through to
72
+ * `"default"` which is the universal baseline.
73
+ *
74
+ * This is intentionally a heuristic: MCP does not yet standardize an
75
+ * agent-family field in `clientInfo`. Override the resolver in the broker
76
+ * options if you need richer logic (header inspection, allow-list, etc.).
77
+ */
78
+ export declare const defaultBrokerUserAgentResolver: BrokerUserAgentResolver;
79
+ /** @deprecated Use {@link defaultBrokerLocaleResolver}. Kept as backward-compat alias. */
80
+ export declare const resolveBrokerLocale: BrokerLocaleResolver;
81
+ /** @deprecated Use {@link defaultBrokerUserAgentResolver}. Kept as backward-compat alias. */
82
+ export declare const resolveBrokerUserAgent: (clientName: string | undefined) => BrokerUserAgent;
83
+ /**
84
+ * Builds the canonical grammar key for the `(userAgent, locale)` matrix.
85
+ *
86
+ * Pattern: `"<userAgent>:<locale>"` — e.g. `"claude:fr"`, `"default:en"`.
87
+ * The colon separator is reserved for this composition and never appears in
88
+ * user-agent or locale identifiers.
89
+ */
90
+ export declare function brokerGrammarKey(userAgent: BrokerUserAgent, locale: BrokerLocale): string;
91
+ /**
92
+ * Loads and caches the grammar for a given `(userAgent, locale)` combination.
93
+ * Returns `undefined` (instead of throwing) when the resource file is missing,
94
+ * so the caller can implement a fallback chain.
95
+ */
96
+ export declare function loadBrokerGrammar(userAgent: BrokerUserAgent, locale: BrokerLocale): McpGrammar | undefined;
97
+ /**
98
+ * Walks a grammars directory and yields every `(userAgent, locale)` pair
99
+ * found on disk. The directory must follow the layout
100
+ * `<dir>/<userAgent>/<locale>.json`.
101
+ *
102
+ * Used by the broker server at startup to bulk-register both the packaged
103
+ * grammars and any local overrides. No hard-coded list of supported
104
+ * user-agents or locales — adding a new grammar is dropping a JSON file.
105
+ */
106
+ export declare function iterBrokerGrammarsFrom(grammarsDir: string): Generator<{
107
+ userAgent: BrokerUserAgent;
108
+ locale: BrokerLocale;
109
+ key: string;
110
+ grammar: McpGrammar;
111
+ }>;
112
+ /**
113
+ * Walks the **packaged** grammars directory (the one shipped with the
114
+ * mcp-broker package). Equivalent to `iterBrokerGrammarsFrom(<packaged-dir>)`.
115
+ *
116
+ * For local user overrides, see {@link iterBrokerGrammarsFrom} with a custom
117
+ * directory — typically `.mcp-broker/grammars/` next to the config file.
118
+ */
119
+ export declare function iterAvailableBrokerGrammars(): Generator<{
120
+ userAgent: BrokerUserAgent;
121
+ locale: BrokerLocale;
122
+ key: string;
123
+ grammar: McpGrammar;
124
+ }>;
125
+ /**
126
+ * Returns the baseline grammar used by the broker behaviors as their
127
+ * source-of-truth for inline tool / property descriptions.
128
+ *
129
+ * Conventionally this is `default:en`. Session-specific grammars selected by
130
+ * the resolver override individual entries on top of this baseline.
131
+ *
132
+ * Throws if the JSON resource is missing — the broker behaviors cannot be
133
+ * built without baseline descriptions.
134
+ */
135
+ export declare function brokerBaselineGrammar(): McpGrammar;
136
+ /**
137
+ * Convenience accessor for a baseline tool description. Throws when the
138
+ * tool is not listed in the baseline grammar — i.e. the JSON file is missing
139
+ * an entry for a tool the code knows about.
140
+ */
141
+ export declare function brokerBaselineToolDescription(toolName: string): string;
142
+ /**
143
+ * Convenience accessor for a baseline property description. Throws when the
144
+ * property is not listed under the tool in the baseline grammar.
145
+ */
146
+ export declare function brokerBaselinePropertyDescription(toolName: string, propertyName: string): string;
147
+ /**
148
+ * Convenience accessor for a baseline resource name. Throws when the resource
149
+ * URI has no entry in the baseline grammar.
150
+ */
151
+ export declare function brokerBaselineResourceName(uri: string): string;
152
+ /**
153
+ * Convenience accessor for a baseline resource description. Throws when the
154
+ * resource URI has no entry in the baseline grammar.
155
+ */
156
+ export declare function brokerBaselineResourceDescription(uri: string): string;
157
+ /**
158
+ * Convenience accessor for a baseline resource template name. Throws when the
159
+ * template URI has no entry in the baseline grammar.
160
+ */
161
+ export declare function brokerBaselineResourceTemplateName(uriTemplate: string): string;
162
+ /**
163
+ * Convenience accessor for a baseline resource template description. Throws
164
+ * when the template URI has no entry in the baseline grammar.
165
+ */
166
+ export declare function brokerBaselineResourceTemplateDescription(uriTemplate: string): string;
@@ -0,0 +1,258 @@
1
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { McpGrammar } from "@cyanmycelium/mcp-core";
5
+ // ---------------------------------------------------------------------------
6
+ // Default resolvers
7
+ // ---------------------------------------------------------------------------
8
+ /**
9
+ * Default locale resolver — emits the BCP-47 narrowing chain for a raw locale
10
+ * tag, from most specific to least specific, always ending with the universal
11
+ * `"en"` fallback.
12
+ *
13
+ * Steps for an input `raw`:
14
+ * 1. Lowercase the input.
15
+ * 2. Push it as the most-specific candidate (only if non-empty).
16
+ * 3. If it contains a `-` separator, push its bare language prefix next.
17
+ * 4. Always push `"en"` last as the universal fallback.
18
+ *
19
+ * The broker server tries each candidate in turn against `<userAgent>/<locale>.json`
20
+ * — so dropping a `claude/fr-ca.json` lets Canadian-French Claude clients
21
+ * pick up that specific dialect, while clients with `fr` or `fr-FR` fall back
22
+ * to `claude/fr.json` or `default/fr.json` automatically.
23
+ *
24
+ * Examples:
25
+ * - `"fr-CA"` → `["fr-ca", "fr", "en"]`
26
+ * - `"fr"` → `["fr", "en"]`
27
+ * - `"zh-CN"` → `["zh-cn", "zh", "en"]`
28
+ * - `"en-US"` → `["en-us", "en"]`
29
+ * - `""` / `undefined` → `["en"]`
30
+ */
31
+ export const defaultBrokerLocaleResolver = (raw) => {
32
+ const a = [];
33
+ if (raw) {
34
+ const sep = "-";
35
+ raw = raw.toLowerCase();
36
+ a.push(raw);
37
+ if (raw.indexOf(sep) !== -1) {
38
+ a.push(raw.split(sep)[0]);
39
+ }
40
+ }
41
+ a.push("en");
42
+ return a;
43
+ };
44
+ /**
45
+ * Default user-agent resolver — substring match on `clientInfo.name` against
46
+ * a list of known LLM family hints. Unknown clients fall through to
47
+ * `"default"` which is the universal baseline.
48
+ *
49
+ * This is intentionally a heuristic: MCP does not yet standardize an
50
+ * agent-family field in `clientInfo`. Override the resolver in the broker
51
+ * options if you need richer logic (header inspection, allow-list, etc.).
52
+ */
53
+ export const defaultBrokerUserAgentResolver = (clientInfo) => {
54
+ const n = (clientInfo?.name ?? "").toLowerCase();
55
+ if (n.includes("claude"))
56
+ return "claude";
57
+ if (n.includes("gpt") || n.includes("openai"))
58
+ return "gpt";
59
+ if (n.includes("mistral"))
60
+ return "mistral";
61
+ if (n.includes("copilot"))
62
+ return "copilot";
63
+ return "default";
64
+ };
65
+ /** @deprecated Use {@link defaultBrokerLocaleResolver}. Kept as backward-compat alias. */
66
+ export const resolveBrokerLocale = defaultBrokerLocaleResolver;
67
+ /** @deprecated Use {@link defaultBrokerUserAgentResolver}. Kept as backward-compat alias. */
68
+ export const resolveBrokerUserAgent = (clientName) => defaultBrokerUserAgentResolver({ name: clientName ?? "", version: "" });
69
+ // ---------------------------------------------------------------------------
70
+ // Canonical grammar key
71
+ // ---------------------------------------------------------------------------
72
+ /**
73
+ * Builds the canonical grammar key for the `(userAgent, locale)` matrix.
74
+ *
75
+ * Pattern: `"<userAgent>:<locale>"` — e.g. `"claude:fr"`, `"default:en"`.
76
+ * The colon separator is reserved for this composition and never appears in
77
+ * user-agent or locale identifiers.
78
+ */
79
+ export function brokerGrammarKey(userAgent, locale) {
80
+ return `${userAgent}:${locale}`;
81
+ }
82
+ // ---------------------------------------------------------------------------
83
+ // JSON resource loading
84
+ // ---------------------------------------------------------------------------
85
+ /**
86
+ * Absolute path of the directory holding the grammar JSON resources.
87
+ *
88
+ * Layout (one folder per user-agent family, one JSON file per locale):
89
+ * ```
90
+ * <GRAMMARS_DIR>/
91
+ * ├── default/
92
+ * │ ├── en.json
93
+ * │ ├── fr.json
94
+ * │ └── zh.json
95
+ * └── claude/
96
+ * ├── en.json
97
+ * └── fr.json
98
+ * ```
99
+ *
100
+ * JSON files live alongside this module in `src/broker/grammars/` during
101
+ * development and are mirrored under `dist/broker/grammars/` at build time
102
+ * by `scripts/copy-assets.mjs`. Adding a new `(userAgent, locale)` pair is
103
+ * just a matter of dropping a new JSON file — no code change required.
104
+ */
105
+ const GRAMMARS_DIR = join(dirname(fileURLToPath(import.meta.url)), "grammars");
106
+ const _cache = new Map();
107
+ /**
108
+ * Loads and caches the grammar for a given `(userAgent, locale)` combination.
109
+ * Returns `undefined` (instead of throwing) when the resource file is missing,
110
+ * so the caller can implement a fallback chain.
111
+ */
112
+ export function loadBrokerGrammar(userAgent, locale) {
113
+ const key = brokerGrammarKey(userAgent, locale);
114
+ const cached = _cache.get(key);
115
+ if (cached)
116
+ return cached;
117
+ const path = join(GRAMMARS_DIR, userAgent, `${locale}.json`);
118
+ if (!existsSync(path))
119
+ return undefined;
120
+ const raw = readFileSync(path, "utf-8");
121
+ const data = JSON.parse(raw);
122
+ const grammar = McpGrammar.fromJSON(data);
123
+ _cache.set(key, grammar);
124
+ return grammar;
125
+ }
126
+ /**
127
+ * Walks a grammars directory and yields every `(userAgent, locale)` pair
128
+ * found on disk. The directory must follow the layout
129
+ * `<dir>/<userAgent>/<locale>.json`.
130
+ *
131
+ * Used by the broker server at startup to bulk-register both the packaged
132
+ * grammars and any local overrides. No hard-coded list of supported
133
+ * user-agents or locales — adding a new grammar is dropping a JSON file.
134
+ */
135
+ export function* iterBrokerGrammarsFrom(grammarsDir) {
136
+ if (!existsSync(grammarsDir))
137
+ return;
138
+ const userAgents = readdirSync(grammarsDir).sort();
139
+ for (const userAgent of userAgents) {
140
+ const uaDir = join(grammarsDir, userAgent);
141
+ if (!statSync(uaDir).isDirectory())
142
+ continue;
143
+ const files = readdirSync(uaDir).sort();
144
+ for (const file of files) {
145
+ if (!file.endsWith(".json"))
146
+ continue;
147
+ const locale = file.slice(0, -".json".length);
148
+ const path = join(uaDir, file);
149
+ try {
150
+ const raw = readFileSync(path, "utf-8");
151
+ const data = JSON.parse(raw);
152
+ const grammar = McpGrammar.fromJSON(data);
153
+ yield { userAgent, locale, key: brokerGrammarKey(userAgent, locale), grammar };
154
+ }
155
+ catch (err) {
156
+ process.stderr.write(`[mcp-broker] Failed to load grammar ${path}: ${err.message}\n`);
157
+ }
158
+ }
159
+ }
160
+ }
161
+ /**
162
+ * Walks the **packaged** grammars directory (the one shipped with the
163
+ * mcp-broker package). Equivalent to `iterBrokerGrammarsFrom(<packaged-dir>)`.
164
+ *
165
+ * For local user overrides, see {@link iterBrokerGrammarsFrom} with a custom
166
+ * directory — typically `.mcp-broker/grammars/` next to the config file.
167
+ */
168
+ export function* iterAvailableBrokerGrammars() {
169
+ yield* iterBrokerGrammarsFrom(GRAMMARS_DIR);
170
+ }
171
+ // ---------------------------------------------------------------------------
172
+ // Baseline helpers (used by behaviors to source their inline descriptions)
173
+ // ---------------------------------------------------------------------------
174
+ /**
175
+ * Returns the baseline grammar used by the broker behaviors as their
176
+ * source-of-truth for inline tool / property descriptions.
177
+ *
178
+ * Conventionally this is `default:en`. Session-specific grammars selected by
179
+ * the resolver override individual entries on top of this baseline.
180
+ *
181
+ * Throws if the JSON resource is missing — the broker behaviors cannot be
182
+ * built without baseline descriptions.
183
+ */
184
+ export function brokerBaselineGrammar() {
185
+ const g = loadBrokerGrammar("default", "en");
186
+ if (!g) {
187
+ throw new Error(`Required baseline broker grammar "default:en" is missing — expected at ${join(GRAMMARS_DIR, "default", "en.json")}.`);
188
+ }
189
+ return g;
190
+ }
191
+ /**
192
+ * Convenience accessor for a baseline tool description. Throws when the
193
+ * tool is not listed in the baseline grammar — i.e. the JSON file is missing
194
+ * an entry for a tool the code knows about.
195
+ */
196
+ export function brokerBaselineToolDescription(toolName) {
197
+ const desc = brokerBaselineGrammar().getToolDescription(toolName);
198
+ if (!desc) {
199
+ throw new Error(`Missing baseline description for tool "${toolName}" in default/en.json.`);
200
+ }
201
+ return desc;
202
+ }
203
+ /**
204
+ * Convenience accessor for a baseline property description. Throws when the
205
+ * property is not listed under the tool in the baseline grammar.
206
+ */
207
+ export function brokerBaselinePropertyDescription(toolName, propertyName) {
208
+ const desc = brokerBaselineGrammar().getPropertyDescription(toolName, propertyName);
209
+ if (!desc) {
210
+ throw new Error(`Missing baseline description for property "${propertyName}" of tool "${toolName}" in default/en.json.`);
211
+ }
212
+ return desc;
213
+ }
214
+ /**
215
+ * Convenience accessor for a baseline resource name. Throws when the resource
216
+ * URI has no entry in the baseline grammar.
217
+ */
218
+ export function brokerBaselineResourceName(uri) {
219
+ const name = brokerBaselineGrammar().getResourceName(uri);
220
+ if (!name) {
221
+ throw new Error(`Missing baseline name for resource "${uri}" in default/en.json.`);
222
+ }
223
+ return name;
224
+ }
225
+ /**
226
+ * Convenience accessor for a baseline resource description. Throws when the
227
+ * resource URI has no entry in the baseline grammar.
228
+ */
229
+ export function brokerBaselineResourceDescription(uri) {
230
+ const desc = brokerBaselineGrammar().getResourceDescription(uri);
231
+ if (!desc) {
232
+ throw new Error(`Missing baseline description for resource "${uri}" in default/en.json.`);
233
+ }
234
+ return desc;
235
+ }
236
+ /**
237
+ * Convenience accessor for a baseline resource template name. Throws when the
238
+ * template URI has no entry in the baseline grammar.
239
+ */
240
+ export function brokerBaselineResourceTemplateName(uriTemplate) {
241
+ const name = brokerBaselineGrammar().getResourceTemplateName(uriTemplate);
242
+ if (!name) {
243
+ throw new Error(`Missing baseline name for resource template "${uriTemplate}" in default/en.json.`);
244
+ }
245
+ return name;
246
+ }
247
+ /**
248
+ * Convenience accessor for a baseline resource template description. Throws
249
+ * when the template URI has no entry in the baseline grammar.
250
+ */
251
+ export function brokerBaselineResourceTemplateDescription(uriTemplate) {
252
+ const desc = brokerBaselineGrammar().getResourceTemplateDescription(uriTemplate);
253
+ if (!desc) {
254
+ throw new Error(`Missing baseline description for resource template "${uriTemplate}" in default/en.json.`);
255
+ }
256
+ return desc;
257
+ }
258
+ //# sourceMappingURL=broker.grammars.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"broker.grammars.js","sourceRoot":"","sources":["../../src/broker/broker.grammars.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import type { IMcpServer, IMessageTransport } from "@cyanmycelium/mcp-core";
2
+ import type { BrokerLocaleResolver, BrokerUserAgentResolver } from "./broker.grammars.js";
3
+ import type { BrokerContext } from "./broker.context.js";
4
+ /**
5
+ * Reserved provider slot name under which the broker exposes itself as an MCP
6
+ * server. Clients reach it via `<host>/_broker/mcp` (or any other client transport).
7
+ *
8
+ * Prefixed with `_` to make it unambiguously a system slot, and to reduce the
9
+ * chance of collision with user-supplied provider names.
10
+ */
11
+ export declare const BROKER_PROVIDER_NAME = "_broker";
12
+ /**
13
+ * Optional knobs passed to {@link startBrokerServer}. Lets the embedder
14
+ * replace either resolver with custom logic without touching mcp-broker
15
+ * internals.
16
+ */
17
+ export interface StartBrokerServerOptions {
18
+ /**
19
+ * Picks a locale (BCP-47 base language, by convention) for the current
20
+ * session. Defaults to {@link defaultBrokerLocaleResolver} which reads
21
+ * `MCP_BROKER_LOCALE` and keeps the ISO 639-1 prefix.
22
+ */
23
+ localeResolver?: BrokerLocaleResolver;
24
+ /**
25
+ * Picks a user-agent family for the connecting client. Defaults to
26
+ * {@link defaultBrokerUserAgentResolver} which substring-matches
27
+ * `clientInfo.name` against known LLM families.
28
+ */
29
+ userAgentResolver?: BrokerUserAgentResolver;
30
+ /**
31
+ * Source of the raw locale string fed to the locale resolver. Defaults
32
+ * to `process.env.MCP_BROKER_LOCALE`. Override when the locale lives
33
+ * somewhere else (config file, session metadata, HTTP header proxy, ...).
34
+ */
35
+ localeSource?: () => string | undefined;
36
+ /**
37
+ * Path to a user-supplied grammars directory whose `<userAgent>/<locale>.json`
38
+ * files are merged **on top of** the packaged grammars. Local entries win
39
+ * on conflicts; missing entries fall through to the packaged values.
40
+ *
41
+ * When `undefined` (default), only the packaged grammars are used.
42
+ */
43
+ localGrammarsDir?: string;
44
+ }
45
+ /**
46
+ * Constructs the broker's own MCP server (the Tier-1 introspection behaviors)
47
+ * and returns the running server plus the loopback transport that must be
48
+ * registered against the {@link WsTunnel} as the `_broker` provider slot.
49
+ *
50
+ * Usage from {@link WsTunnel.start}:
51
+ * ```ts
52
+ * const { server, clientTransport } = await startBrokerServer(this, { ... });
53
+ * this._registerLoopbackProvider(BROKER_PROVIDER_NAME, clientTransport);
54
+ * ```
55
+ *
56
+ * @param context Read-only view of the broker's state.
57
+ * @param options Optional resolver overrides.
58
+ * @returns The running {@link IMcpServer} (call `.stop()` on shutdown) and the
59
+ * loopback transport to attach to the tunnel.
60
+ */
61
+ export declare function startBrokerServer(context: BrokerContext, options?: StartBrokerServerOptions): Promise<{
62
+ server: IMcpServer;
63
+ clientTransport: IMessageTransport;
64
+ }>;
@@ -0,0 +1,111 @@
1
+ import { McpGrammar, McpServerBuilder, LoopbackTransport } from "@cyanmycelium/mcp-core";
2
+ import { BrokerInfoBehavior } from "./behaviors/broker.behavior.info.js";
3
+ import { BrokerProvidersBehavior } from "./behaviors/broker.behavior.providers.js";
4
+ import { brokerGrammarKey, defaultBrokerLocaleResolver, defaultBrokerUserAgentResolver, iterAvailableBrokerGrammars, iterBrokerGrammarsFrom } from "./broker.grammars.js";
5
+ /**
6
+ * Reserved provider slot name under which the broker exposes itself as an MCP
7
+ * server. Clients reach it via `<host>/_broker/mcp` (or any other client transport).
8
+ *
9
+ * Prefixed with `_` to make it unambiguously a system slot, and to reduce the
10
+ * chance of collision with user-supplied provider names.
11
+ */
12
+ export const BROKER_PROVIDER_NAME = "_broker";
13
+ /**
14
+ * Constructs the broker's own MCP server (the Tier-1 introspection behaviors)
15
+ * and returns the running server plus the loopback transport that must be
16
+ * registered against the {@link WsTunnel} as the `_broker` provider slot.
17
+ *
18
+ * Usage from {@link WsTunnel.start}:
19
+ * ```ts
20
+ * const { server, clientTransport } = await startBrokerServer(this, { ... });
21
+ * this._registerLoopbackProvider(BROKER_PROVIDER_NAME, clientTransport);
22
+ * ```
23
+ *
24
+ * @param context Read-only view of the broker's state.
25
+ * @param options Optional resolver overrides.
26
+ * @returns The running {@link IMcpServer} (call `.stop()` on shutdown) and the
27
+ * loopback transport to attach to the tunnel.
28
+ */
29
+ export async function startBrokerServer(context, options = {}) {
30
+ const localeResolver = options.localeResolver ?? defaultBrokerLocaleResolver;
31
+ const userAgentResolver = options.userAgentResolver ?? defaultBrokerUserAgentResolver;
32
+ const localeSource = options.localeSource ?? (() => process.env["MCP_BROKER_LOCALE"]);
33
+ const [serverEnd, clientEnd] = LoopbackTransport.createPair();
34
+ const builder = new McpServerBuilder().withName(BROKER_PROVIDER_NAME).withTransport(serverEnd).register(new BrokerInfoBehavior(context), new BrokerProvidersBehavior(context));
35
+ // Discover every grammar by scanning two directories:
36
+ // 1. The packaged grammars shipped with the broker.
37
+ // 2. Optionally, a user-supplied directory whose entries are merged
38
+ // ON TOP of the packaged ones (local wins on conflicts).
39
+ //
40
+ // Then build the (userAgent × locale) matrix. Within each user-agent,
41
+ // the grammar cascades on top of "default:<locale>" so per-user-agent
42
+ // files can stay partial.
43
+ const defaults = new Map(); // locale → grammar
44
+ const overrides = new Map(); // userAgent → locale → grammar
45
+ function ingest(entry, isOverride) {
46
+ if (entry.userAgent === "default") {
47
+ const existing = defaults.get(entry.locale);
48
+ const merged = existing && isOverride ? McpGrammar.merge(existing, entry.grammar) : entry.grammar;
49
+ defaults.set(entry.locale, merged);
50
+ }
51
+ else {
52
+ let byLocale = overrides.get(entry.userAgent);
53
+ if (!byLocale) {
54
+ byLocale = new Map();
55
+ overrides.set(entry.userAgent, byLocale);
56
+ }
57
+ const existing = byLocale.get(entry.locale);
58
+ const merged = existing && isOverride ? McpGrammar.merge(existing, entry.grammar) : entry.grammar;
59
+ byLocale.set(entry.locale, merged);
60
+ }
61
+ }
62
+ for (const entry of iterAvailableBrokerGrammars())
63
+ ingest(entry, false);
64
+ if (options.localGrammarsDir) {
65
+ for (const entry of iterBrokerGrammarsFrom(options.localGrammarsDir))
66
+ ingest(entry, true);
67
+ }
68
+ const availableKeys = new Set();
69
+ // Register every "default:<locale>" as-is.
70
+ for (const [locale, grammar] of defaults) {
71
+ const key = brokerGrammarKey("default", locale);
72
+ builder.withGrammar(key, grammar);
73
+ availableKeys.add(key);
74
+ }
75
+ // Register every "<userAgent>:<locale>" as merge(default:<locale>, ua:<locale>).
76
+ // The user-agent grammar wins per entry; missing entries cascade from default.
77
+ for (const [agent, byLocale] of overrides) {
78
+ for (const [locale, uaGrammar] of byLocale) {
79
+ const baseline = defaults.get(locale);
80
+ const merged = baseline ? McpGrammar.merge(baseline, uaGrammar) : uaGrammar;
81
+ const key = brokerGrammarKey(agent, locale);
82
+ builder.withGrammar(key, merged);
83
+ availableKeys.add(key);
84
+ }
85
+ }
86
+ builder.withGrammarResolver((clientInfo) => {
87
+ // localeResolver returns the full fallback chain (most specific first),
88
+ // ending with the universal "en". The user-agent axis is the broker's
89
+ // own concern: per locale, prefer the user-agent-specific grammar, then
90
+ // fall back to the "default" agent.
91
+ const locales = localeResolver(localeSource());
92
+ const userAgent = userAgentResolver(clientInfo);
93
+ const userAgents = userAgent === "default" ? ["default"] : [userAgent, "default"];
94
+ for (const locale of locales) {
95
+ for (const ua of userAgents) {
96
+ const key = brokerGrammarKey(ua, locale);
97
+ if (availableKeys.has(key))
98
+ return key;
99
+ }
100
+ }
101
+ // None of the candidates is on disk → return an empty key. McpServer
102
+ // then falls back to the behavior's baseline descriptions (English).
103
+ return "";
104
+ });
105
+ // No reconnect policy → the McpServer does not attempt to reopen the loopback
106
+ // when WsTunnel.stop() closes it. Clean shutdown.
107
+ const server = builder.build();
108
+ await server.start();
109
+ return { server, clientTransport: clientEnd };
110
+ }
111
+ //# sourceMappingURL=broker.server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"broker.server.js","sourceRoot":"","sources":["../../src/broker/broker.server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ {
2
+ "tools": {
3
+ "broker_info": {
4
+ "description": "Get the broker's identity: name, version, uptime, host, port, TLS, and URL paths. Call this first when you need to know what you are talking to."
5
+ },
6
+ "providers_list": {
7
+ "description": "List every provider slot on this broker, connected or not. Each entry tells you the transport kind, current client count, and how many requests are in flight. Use this to discover what you can route to."
8
+ },
9
+ "provider_status": {
10
+ "description": "Get the full status of one provider slot by name. Returns an error if the slot does not exist — start with providers_list if you are not sure of the name.",
11
+ "properties": {
12
+ "name": "The exact provider slot name. Case-sensitive. Use providers_list to discover valid values."
13
+ }
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "tools": {
3
+ "broker_info": {
4
+ "description": "Récupère l'identité du broker : nom, version, uptime, hôte, port, TLS et chemins URL. À appeler en premier pour savoir à qui tu parles."
5
+ },
6
+ "providers_list": {
7
+ "description": "Liste tous les emplacements de providers de ce broker, connectés ou non. Chaque entrée indique le type de transport, le nombre de clients actuels et le nombre de requêtes en cours. Utilise-le pour découvrir vers qui tu peux router."
8
+ },
9
+ "provider_status": {
10
+ "description": "Récupère le statut complet d'un emplacement de provider par son nom. Retourne une erreur si l'emplacement n'existe pas — commence par providers_list si tu n'es pas sûr du nom.",
11
+ "properties": {
12
+ "name": "Le nom exact de l'emplacement provider. Sensible à la casse. Utilise providers_list pour découvrir les valeurs valides."
13
+ }
14
+ }
15
+ }
16
+ }