boondmanager-mcp-server 2.9.0 → 2.11.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/README.md +73 -7
- package/dist/config/access-policy.d.ts +5 -0
- package/dist/config/access-policy.d.ts.map +1 -1
- package/dist/config/access-policy.js +36 -1
- package/dist/config/access-policy.js.map +1 -1
- package/dist/config/env-flags.d.ts +11 -0
- package/dist/config/env-flags.d.ts.map +1 -0
- package/dist/config/env-flags.js +16 -0
- package/dist/config/env-flags.js.map +1 -0
- package/dist/config/profiles.d.ts +71 -0
- package/dist/config/profiles.d.ts.map +1 -0
- package/dist/config/profiles.js +115 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/icons.d.ts +79 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +169 -0
- package/dist/icons.js.map +1 -0
- package/dist/instructions.d.ts +21 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +56 -0
- package/dist/instructions.js.map +1 -0
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +6 -0
- package/dist/resources/index.js.map +1 -1
- package/dist/schemas/filter-aliases.d.ts +69 -0
- package/dist/schemas/filter-aliases.d.ts.map +1 -0
- package/dist/schemas/filter-aliases.js +225 -0
- package/dist/schemas/filter-aliases.js.map +1 -0
- package/dist/schemas/index.d.ts +22 -22
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +54 -43
- package/dist/schemas/index.js.map +1 -1
- package/dist/server.d.ts +25 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +61 -16
- package/dist/server.js.map +1 -1
- package/dist/services/boond-client.d.ts.map +1 -1
- package/dist/services/boond-client.js +17 -2
- package/dist/services/boond-client.js.map +1 -1
- package/dist/tools/candidates.d.ts.map +1 -1
- package/dist/tools/candidates.js +1 -4
- package/dist/tools/candidates.js.map +1 -1
- package/dist/tools/companies.d.ts.map +1 -1
- package/dist/tools/companies.js +1 -4
- package/dist/tools/companies.js.map +1 -1
- package/dist/tools/contacts.d.ts.map +1 -1
- package/dist/tools/contacts.js +1 -4
- package/dist/tools/contacts.js.map +1 -1
- package/dist/tools/crud-factory.d.ts +0 -8
- package/dist/tools/crud-factory.d.ts.map +1 -1
- package/dist/tools/crud-factory.js +67 -15
- package/dist/tools/crud-factory.js.map +1 -1
- package/dist/tools/opportunities.d.ts.map +1 -1
- package/dist/tools/opportunities.js +1 -4
- package/dist/tools/opportunities.js.map +1 -1
- package/dist/tools/projects.d.ts.map +1 -1
- package/dist/tools/projects.js +1 -4
- package/dist/tools/projects.js.map +1 -1
- package/dist/tools/registration-decorators.d.ts +35 -0
- package/dist/tools/registration-decorators.d.ts.map +1 -0
- package/dist/tools/registration-decorators.js +30 -0
- package/dist/tools/registration-decorators.js.map +1 -0
- package/dist/tools/resources.d.ts.map +1 -1
- package/dist/tools/resources.js +1 -4
- package/dist/tools/resources.js.map +1 -1
- package/dist/tools/validation-wrapper.d.ts +43 -0
- package/dist/tools/validation-wrapper.d.ts.map +1 -0
- package/dist/tools/validation-wrapper.js +108 -0
- package/dist/tools/validation-wrapper.js.map +1 -0
- package/dist/transports/http.d.ts +57 -3
- package/dist/transports/http.d.ts.map +1 -1
- package/dist/transports/http.js +145 -9
- package/dist/transports/http.js.map +1 -1
- package/manifest.json +9 -2
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -206,7 +206,7 @@ Exemples d'invocation des prompts ressources / competences / CV :
|
|
|
206
206
|
|
|
207
207
|
## Prerequis
|
|
208
208
|
|
|
209
|
-
- Node.js >=
|
|
209
|
+
- Node.js >= 22
|
|
210
210
|
- Un compte BoondManager avec acces API active
|
|
211
211
|
- L'option "Allow API Rest calls using BasicAuth authentication" activee dans la configuration BoondManager (si BasicAuth)
|
|
212
212
|
|
|
@@ -216,7 +216,52 @@ Exemples d'invocation des prompts ressources / competences / CV :
|
|
|
216
216
|
|
|
217
217
|
Telechargez le fichier `.mcpb` depuis la [derniere release GitHub](https://github.com/fauguste/boondmanager-mcp-server/releases/latest), puis dans Claude Desktop : **Fichier > Installer une extension...** et selectionnez le fichier. Les identifiants sont demandes a l'installation et stockes de maniere chiffree (Keychain macOS / Credential Manager Windows).
|
|
218
218
|
|
|
219
|
-
### Claude Code
|
|
219
|
+
### Claude Code (plugin, recommande)
|
|
220
|
+
|
|
221
|
+
Meme confort que le one-click Desktop : un formulaire de configuration, aucune
|
|
222
|
+
variable d'environnement a poser soi-meme.
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
/plugin marketplace add fauguste/boondmanager-mcp-server
|
|
226
|
+
/plugin install boondmanager-mcp@boondmanager
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Claude Code affiche alors le formulaire des 14 options (identifiants, URL de
|
|
230
|
+
base, restrictions d'acces). Tout est optionnel a l'ecran, mais il faut
|
|
231
|
+
renseigner **un** des trois modes d'authentification : le trio `User Token` +
|
|
232
|
+
`Client Token` + `Client Key` (JWT genere automatiquement, recommande), ou le
|
|
233
|
+
`Token JWT` pre-construit, ou le couple `Utilisateur` + `Mot de passe`
|
|
234
|
+
(BasicAuth). Les champs laisses vides retombent sur les valeurs par defaut.
|
|
235
|
+
|
|
236
|
+
Si le serveur n'apparait pas immediatement dans `/mcp`, un `/reload-plugins`
|
|
237
|
+
suffit — inutile de relancer Claude Code.
|
|
238
|
+
|
|
239
|
+
Details utiles :
|
|
240
|
+
|
|
241
|
+
- **Ou vont les secrets** : les 5 champs sensibles (`User Token`, `Client
|
|
242
|
+
Token`, `Client Key`, `Token JWT`, `Mot de passe`) vont dans le Keychain macOS
|
|
243
|
+
(ou `~/.claude/.credentials.json` a defaut), **pas** dans `settings.json`. Les
|
|
244
|
+
options non sensibles (URL, restrictions) sont stockees en clair dans
|
|
245
|
+
`pluginConfigs` de votre `~/.claude/settings.json`.
|
|
246
|
+
- **Nommage des outils** : cote client les outils sont prefixes
|
|
247
|
+
`mcp__boondmanager__`, par exemple `mcp__boondmanager__boond_candidates_search`.
|
|
248
|
+
C'est ce nom qu'il faut utiliser dans une allow-list de permissions.
|
|
249
|
+
- **Version** : le plugin lance la version npm epinglee dans son manifeste. Pour
|
|
250
|
+
passer a une nouvelle release : `/plugin marketplace update boondmanager` puis
|
|
251
|
+
reinstaller le plugin.
|
|
252
|
+
- **Restreindre la surface** : les champs *Restriction* du formulaire mappent sur
|
|
253
|
+
les variables `BOOND_MCP_*` (profil metier, domaines, operations, lecture
|
|
254
|
+
seule). Voir [docs/access-control.md](./docs/access-control.md).
|
|
255
|
+
- **Suppressions** : Claude Code supporte l'elicitation MCP, donc chaque
|
|
256
|
+
`boond_*_delete` demande une confirmation avant d'agir (option *Confirmer les
|
|
257
|
+
suppressions*, activee par defaut).
|
|
258
|
+
|
|
259
|
+
Pour desinstaller : `/plugin uninstall boondmanager-mcp@boondmanager`.
|
|
260
|
+
|
|
261
|
+
### Claude Code (manuel, `claude mcp add`)
|
|
262
|
+
|
|
263
|
+
A privilegier si vous voulez piloter vous-meme les variables d'environnement,
|
|
264
|
+
ou epingler une version differente de celle du plugin.
|
|
220
265
|
|
|
221
266
|
```bash
|
|
222
267
|
# Avec un token API (recommande)
|
|
@@ -523,7 +568,7 @@ L'API BoondManager n'expose qu'un seul endpoint `/application/dictionary` qui re
|
|
|
523
568
|
|----------|--------|-------------|
|
|
524
569
|
| `BOOND_DICTIONARY_TTL_MS` | `3600000` (1 h) | Durée de vie du cache du dictionnaire, en millisecondes. Une valeur non numérique ou ≤ 0 retombe sur le défaut. |
|
|
525
570
|
|
|
526
|
-
### Restriction d'accès (domaines / lecture seule)
|
|
571
|
+
### Restriction d'accès (profils / domaines / lecture seule)
|
|
527
572
|
|
|
528
573
|
Vous pouvez restreindre **ce que l'IA voit et peut faire**, entièrement par
|
|
529
574
|
variables d'environnement : exposer seulement certains domaines (ex. la
|
|
@@ -531,6 +576,7 @@ comptabilité), et/ou bloquer les écritures et suppressions.
|
|
|
531
576
|
|
|
532
577
|
| Variable | Effet |
|
|
533
578
|
|----------|-------|
|
|
579
|
+
| `BOOND_MCP_PROFILE` | Profil préconfiguré : `recruiting`, `sales`, `finance`, `delivery`, `admin` (CSV = union). Raccourci pour ne pas lister les domaines à la main. Ignoré si `BOOND_MCP_DOMAINS` est défini. |
|
|
534
580
|
| `BOOND_MCP_DOMAINS` | Liste blanche de domaines (CSV). Absente = tous. Ex. `invoices,payments,application` |
|
|
535
581
|
| `BOOND_MCP_EXCLUDE_DOMAINS` | Liste noire de domaines (CSV), appliquée après la liste blanche. Ex. `candidates,resources` |
|
|
536
582
|
| `BOOND_MCP_OPERATIONS` | Opérations autorisées (CSV) parmi `read,create,update,delete`. Absente = toutes. |
|
|
@@ -542,7 +588,26 @@ comptabilité), et/ou bloquer les écritures et suppressions.
|
|
|
542
588
|
> BoondManager (lecture seule, périmètre comptable…) ; ce filtre vient en
|
|
543
589
|
> complément (économie de tokens, garde-fou anti-action accidentelle).
|
|
544
590
|
|
|
545
|
-
|
|
591
|
+
Exemple — tout le périmètre gestion, en lecture seule :
|
|
592
|
+
|
|
593
|
+
```bash
|
|
594
|
+
export BOOND_MCP_PROFILE=finance
|
|
595
|
+
export BOOND_MCP_READ_ONLY=true
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
Guide complet, règles de résolution, contenu de chaque profil (et le nombre
|
|
599
|
+
d'outils qui en résulte) : [docs/access-control.md](docs/access-control.md).
|
|
600
|
+
|
|
601
|
+
### Icônes (SEP-973)
|
|
602
|
+
|
|
603
|
+
Les outils, prompts et ressources portent une icône par domaine (SVG inline en
|
|
604
|
+
`data:` URI, aucun asset à héberger). Coût mesuré : **~40 Kio, soit ~14 % du
|
|
605
|
+
payload `tools/list`**. Les déploiements qui ne les affichent pas (passerelles,
|
|
606
|
+
clients texte) peuvent les supprimer :
|
|
607
|
+
|
|
608
|
+
| Variable | Defaut | Description |
|
|
609
|
+
|----------|--------|-------------|
|
|
610
|
+
| `BOOND_MCP_ICONS` | activé | `0`/`false`/`no`/`off` : n'annonce aucune icône (outils, prompts, ressources). |
|
|
546
611
|
|
|
547
612
|
### Libellés personnalisés du dictionnaire
|
|
548
613
|
|
|
@@ -574,7 +639,7 @@ Le serveur supporte deux transports MCP, selectionnables via la variable d'envir
|
|
|
574
639
|
|
|
575
640
|
### Streamable HTTP (pour les gateways MCP)
|
|
576
641
|
|
|
577
|
-
Depuis la v1.4.0, le serveur peut etre expose en HTTP (
|
|
642
|
+
Depuis la v1.4.0, le serveur peut etre expose en HTTP (transport MCP Streamable HTTP) afin d'etre branche derriere une passerelle MCP ou deploye comme service. La revision de protocole negociee est celle du SDK installe (`2025-11-25`).
|
|
578
643
|
|
|
579
644
|
> **Authentification BoondManager : OAuth2 protected resource.** Le serveur HTTP **ne detient aucun secret** (ni `client_secret`, ni refresh token, ni stockage utilisateur). Chaque requete MCP doit porter `Authorization: Bearer <boond_access_token>` ; le serveur transmet le token tel quel a BoondManager. C'est le **client MCP** (Claude Desktop, Claude Code, gateway…) qui fait la danse OAuth contre BoondManager et qui gere le refresh. Procedure complete : [docs/oauth.md](docs/oauth.md).
|
|
580
645
|
|
|
@@ -608,6 +673,7 @@ npx boondmanager-mcp-server
|
|
|
608
673
|
| `MCP_HTTP_SESSION_TTL_MS` | `1800000` (30 min) | En mode stateful, duree d'inactivite au-dela de laquelle une session est fermee. |
|
|
609
674
|
| `MCP_HTTP_SESSION_SWEEP_INTERVAL_MS` | `300000` (5 min) | Frequence de balayage des sessions inactives. |
|
|
610
675
|
| `MCP_HTTP_ALLOWED_HOSTS` | _(auto)_ | Liste blanche du header `Host` (anti DNS rebinding, CVE-2025-66414). `*` pour desactiver explicitement. |
|
|
676
|
+
| `MCP_HTTP_ALLOWED_ORIGINS` | _(auto)_ | Liste blanche du header `Origin` (scheme + host + port) pour les clients navigateur ; un `Origin` hors liste recoit un `403` (exigence spec 2025-11-25). Defaut quand le serveur ecoute en loopback = **toute origine loopback, quel que soit le port** (`http`/`https` sur `localhost` / `127.0.0.1` / `[::1]`) plus l'origine de `MCP_HTTP_PUBLIC_URL` si elle est definie — MCP Inspector (`:6274`) ou un serveur de dev (`:5173`) fonctionnent sans configuration, et une origine distante recoit toujours un `403`. Validation desactivee sinon. Une liste explicite est en revanche comparee a l'identique (port compris). **Une requete sans `Origin` est toujours acceptee** (curl, gateways, clients MCP non-navigateur), et le document de decouverte `/.well-known/oauth-protected-resource` est exempte. `*` pour desactiver explicitement ; une valeur vide n'est pas une desactivation. |
|
|
611
677
|
|
|
612
678
|
**Variables OAuth2 — discovery (toutes optionnelles)**
|
|
613
679
|
|
|
@@ -841,13 +907,13 @@ npm run typecheck
|
|
|
841
907
|
|
|
842
908
|
### Stack technique
|
|
843
909
|
|
|
844
|
-
- **Runtime** : Node.js >=
|
|
910
|
+
- **Runtime** : Node.js >= 22 (ES2022)
|
|
845
911
|
- **Langage** : TypeScript 5.8+ (mode strict)
|
|
846
912
|
- **MCP SDK** : @modelcontextprotocol/sdk 1.12+
|
|
847
913
|
- **Validation** : Zod 4
|
|
848
914
|
- **Tests** : Vitest 4 + couverture V8
|
|
849
915
|
- **Lint** : ESLint 10 + typescript-eslint
|
|
850
|
-
- **Transports** : stdio (defaut) + Streamable HTTP (MCP 2025-
|
|
916
|
+
- **Transports** : stdio (defaut) + Streamable HTTP (spec MCP 2025-11-25)
|
|
851
917
|
|
|
852
918
|
## Ressources
|
|
853
919
|
|
|
@@ -17,9 +17,14 @@ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
17
17
|
*
|
|
18
18
|
* Env vars (all optional; absent = no restriction = current behaviour):
|
|
19
19
|
* - `BOOND_MCP_DOMAINS` CSV allow-list of domains. Absent = all.
|
|
20
|
+
* - `BOOND_MCP_PROFILE` CSV of pre-composed profiles (union). Ignored if DOMAINS is set.
|
|
20
21
|
* - `BOOND_MCP_EXCLUDE_DOMAINS` CSV deny-list. Applied AFTER the allow-list.
|
|
21
22
|
* - `BOOND_MCP_OPERATIONS` CSV of `read,create,update,delete`. Absent = all.
|
|
22
23
|
* - `BOOND_MCP_READ_ONLY` Boolean shortcut, equivalent to OPERATIONS=read.
|
|
24
|
+
*
|
|
25
|
+
* Precedence on the domain axis: `DOMAINS` (explicit) > `PROFILE` (bundle) >
|
|
26
|
+
* everything allowed; `EXCLUDE_DOMAINS` then applies in all three cases (deny
|
|
27
|
+
* always wins). The operation axis is orthogonal to all of this.
|
|
23
28
|
*/
|
|
24
29
|
export type Operation = "read" | "create" | "update" | "delete";
|
|
25
30
|
export declare const ALL_OPERATIONS: readonly Operation[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access-policy.d.ts","sourceRoot":"","sources":["../../src/config/access-policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"access-policy.d.ts","sourceRoot":"","sources":["../../src/config/access-policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhE,eAAO,MAAM,cAAc,EAAE,SAAS,SAAS,EAA2C,CAAC;AAE3F,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,gHAAgH;IAChH,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IACnC,qFAAqF;IACrF,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,kDAAkD;IAClD,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;CAC5B;AAuGD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,YAAY,CAyDtF;AAED,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAK7E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,eAAe,GAAG,SAAS,GAAG,SAAS,CAK/E;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,GAAG,SAAS,GAAG,OAAO,CAE1G;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,SAAS,CAwB7E"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { REGISTERED_DOMAINS } from "../constants.js";
|
|
2
2
|
import { logger } from "../services/logger.js";
|
|
3
|
+
import { PROFILE_NAMES, resolveProfile } from "./profiles.js";
|
|
3
4
|
export const ALL_OPERATIONS = ["read", "create", "update", "delete"];
|
|
4
5
|
// --- Env parsing helpers (mirroring the patterns already used across the
|
|
5
6
|
// codebase: see transports/http.ts, services/oauth.ts, services/update-checker.ts) ---
|
|
@@ -42,6 +43,32 @@ function normalizeAndValidateDomains(items, known, varName, log) {
|
|
|
42
43
|
}
|
|
43
44
|
return out;
|
|
44
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Union of the domains of every valid profile named in `BOOND_MCP_PROFILE`.
|
|
48
|
+
* Returns `null` when nothing usable was configured, so the caller can tell
|
|
49
|
+
* "no profile" from "a profile that resolved to nothing" — an unknown profile
|
|
50
|
+
* is warned-and-ignored (same resilience rule as unknown domains), never fatal
|
|
51
|
+
* and never a silently empty surface.
|
|
52
|
+
*/
|
|
53
|
+
function resolveProfileDomains(items, log) {
|
|
54
|
+
if (items.length === 0)
|
|
55
|
+
return null;
|
|
56
|
+
const out = new Set();
|
|
57
|
+
for (const raw of items) {
|
|
58
|
+
const domains = resolveProfile(raw);
|
|
59
|
+
if (domains === undefined) {
|
|
60
|
+
log.warn({ value: raw, known: PROFILE_NAMES }, `BOOND_MCP_PROFILE: unknown profile "${raw}" ignored (expected one of ${PROFILE_NAMES.join(", ")})`);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
for (const d of domains)
|
|
64
|
+
out.add(d);
|
|
65
|
+
}
|
|
66
|
+
if (out.size === 0) {
|
|
67
|
+
log.warn("BOOND_MCP_PROFILE contained no valid profile; falling back to the full domain surface");
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
45
72
|
function validateOperations(items, log) {
|
|
46
73
|
const out = new Set();
|
|
47
74
|
for (const raw of items) {
|
|
@@ -70,8 +97,15 @@ export function resolveAccessPolicy(env = process.env) {
|
|
|
70
97
|
const known = new Set(REGISTERED_DOMAINS);
|
|
71
98
|
// --- Domains ---
|
|
72
99
|
const allowItems = parseList(readEnv(env, "BOOND_MCP_DOMAINS"));
|
|
100
|
+
const profileItems = parseList(readEnv(env, "BOOND_MCP_PROFILE"));
|
|
73
101
|
const excludeItems = parseList(readEnv(env, "BOOND_MCP_EXCLUDE_DOMAINS"));
|
|
74
|
-
|
|
102
|
+
// Explicit domains win over a profile bundle: the operator who listed
|
|
103
|
+
// domains by hand is the one who knows exactly what they want exposed.
|
|
104
|
+
const profileDomains = resolveProfileDomains(profileItems, log);
|
|
105
|
+
if (allowItems.length > 0 && profileDomains !== null) {
|
|
106
|
+
log.warn("Both BOOND_MCP_DOMAINS and BOOND_MCP_PROFILE are set; BOOND_MCP_DOMAINS takes precedence");
|
|
107
|
+
}
|
|
108
|
+
const allowedDomains = allowItems.length > 0 ? normalizeAndValidateDomains(allowItems, known, "BOOND_MCP_DOMAINS", log) : profileDomains;
|
|
75
109
|
const excludedDomains = normalizeAndValidateDomains(excludeItems, known, "BOOND_MCP_EXCLUDE_DOMAINS", log);
|
|
76
110
|
// --- Operations ---
|
|
77
111
|
const opItems = parseList(readEnv(env, "BOOND_MCP_OPERATIONS"));
|
|
@@ -97,6 +131,7 @@ export function resolveAccessPolicy(env = process.env) {
|
|
|
97
131
|
log.warn("Domain `application` is filtered out; dictionary lookups (state/type labels) and current-user resolution will be unavailable, degrading many tools/resources");
|
|
98
132
|
}
|
|
99
133
|
log.info({
|
|
134
|
+
...(profileItems.length > 0 ? { profiles: profileItems } : {}),
|
|
100
135
|
allowedDomains: allowedDomains ? [...allowedDomains] : "all",
|
|
101
136
|
excludedDomains: [...excludedDomains],
|
|
102
137
|
operations: [...operations],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access-policy.js","sourceRoot":"","sources":["../../src/config/access-policy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"access-policy.js","sourceRoot":"","sources":["../../src/config/access-policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared parsing for the `BOOND_MCP_*` opt-out switches.
|
|
3
|
+
*
|
|
4
|
+
* Both toggles (`BOOND_MCP_ICONS`, `BOOND_MCP_CONFIRM_DELETE`) are
|
|
5
|
+
* "on unless explicitly turned off", and both accepted the same four spellings
|
|
6
|
+
* through two identical copies of this function. One copy means the accepted
|
|
7
|
+
* vocabulary can't drift between switches.
|
|
8
|
+
*/
|
|
9
|
+
/** Is this env var explicitly set to an "off" value? Absent/empty = not disabled. */
|
|
10
|
+
export declare function isFeatureDisabled(raw: string | undefined): boolean;
|
|
11
|
+
//# sourceMappingURL=env-flags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-flags.d.ts","sourceRoot":"","sources":["../../src/config/env-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGlE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared parsing for the `BOOND_MCP_*` opt-out switches.
|
|
3
|
+
*
|
|
4
|
+
* Both toggles (`BOOND_MCP_ICONS`, `BOOND_MCP_CONFIRM_DELETE`) are
|
|
5
|
+
* "on unless explicitly turned off", and both accepted the same four spellings
|
|
6
|
+
* through two identical copies of this function. One copy means the accepted
|
|
7
|
+
* vocabulary can't drift between switches.
|
|
8
|
+
*/
|
|
9
|
+
const OFF_VALUES = ["0", "false", "no", "off"];
|
|
10
|
+
/** Is this env var explicitly set to an "off" value? Absent/empty = not disabled. */
|
|
11
|
+
export function isFeatureDisabled(raw) {
|
|
12
|
+
if (!raw)
|
|
13
|
+
return false;
|
|
14
|
+
return OFF_VALUES.includes(raw.trim().toLowerCase());
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=env-flags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-flags.js","sourceRoot":"","sources":["../../src/config/env-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;AAE/C,qFAAqF;AACrF,MAAM,UAAU,iBAAiB,CAAC,GAAuB;IACvD,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,OAAO,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { DomainName } from "../constants.js";
|
|
2
|
+
/**
|
|
3
|
+
* Pre-composed domain sets ("profiles") for `BOOND_MCP_PROFILE`.
|
|
4
|
+
*
|
|
5
|
+
* Why: `BOOND_MCP_DOMAINS` is the precise tool, but composing it means knowing
|
|
6
|
+
* all 38 domain names *and* which ones a job actually needs (a recruiter needs
|
|
7
|
+
* `positionings` and `actions`, not just `candidates`). With on-demand tool
|
|
8
|
+
* discovery in clients, narrowing the surface is still the highest-leverage
|
|
9
|
+
* knob — so it has to be usable in one env var, without a trip to TOOLS.md.
|
|
10
|
+
*
|
|
11
|
+
* Each profile is a job-shaped bundle, not a security tier: see
|
|
12
|
+
* `docs/access-control.md`, this layer hides tools from the model, it does not
|
|
13
|
+
* revoke BoondManager rights. Combine with `BOOND_MCP_READ_ONLY` /
|
|
14
|
+
* `BOOND_MCP_OPERATIONS` (orthogonal axis) to bound what can be written.
|
|
15
|
+
*
|
|
16
|
+
* `application` is in every profile on purpose: it backs dictionary resolution
|
|
17
|
+
* (state/type labels) and `current-user`, which many tools and prompts depend
|
|
18
|
+
* on. `workflows` is listed wherever prompt mirrors make sense; it is not
|
|
19
|
+
* strictly required (workflow tools follow their source prompt's domains, not
|
|
20
|
+
* the allow-list), but keeping it explicit documents the intent and survives a
|
|
21
|
+
* future change of that rule.
|
|
22
|
+
*
|
|
23
|
+
* There is no blanket "`resources` everywhere" rule — the rule is **per
|
|
24
|
+
* profile, check the prompt count**. 8 of the 11 prompts orchestrate
|
|
25
|
+
* `resources` (`synthese_equipe`, `staffing_disponible`, `fiche_consultant`,
|
|
26
|
+
* `recherche_profil_competences`, …) and a prompt is cut as soon as ONE of its
|
|
27
|
+
* domains is filtered out, so leaving `resources` out of `recruiting` / `sales`
|
|
28
|
+
* bought ~10 fewer tools and cost most of their runbooks — the wrong trade for a
|
|
29
|
+
* layer whose whole point is ergonomics. It is also what those jobs actually
|
|
30
|
+
* need: a recruiter matches candidates against internal staff, a salesperson
|
|
31
|
+
* staffs a deal. `finance` and `admin` deliberately do NOT include it: neither
|
|
32
|
+
* has a runbook that touches `resources` (`finance`'s only prompt,
|
|
33
|
+
* `factures_a_relancer`, spans `invoices` + `application`), so it would add
|
|
34
|
+
* tools and no capability. When adding a profile, count the prompts it keeps —
|
|
35
|
+
* not just the tools.
|
|
36
|
+
*/
|
|
37
|
+
declare const PROFILE_TABLE: {
|
|
38
|
+
/** Recrutement / sourcing : viviers, positionnements, suivi d'activité. */
|
|
39
|
+
readonly recruiting: readonly ["candidates", "positionings", "opportunities", "contacts", "companies", "documents", "actions", "resources", "application", "workflows"];
|
|
40
|
+
/** Avant-vente / commerce : pipeline, comptes, commandes. */
|
|
41
|
+
readonly sales: readonly ["opportunities", "companies", "contacts", "actions", "projects", "orders", "products", "reporting", "resources", "application", "workflows"];
|
|
42
|
+
/** Gestion / compta : facturation client et fournisseur, encaissements. */
|
|
43
|
+
readonly finance: readonly ["invoices", "payments", "orders", "purchases", "provider-invoices", "expenses", "projects", "companies", "reporting", "application", "workflows"];
|
|
44
|
+
/** Delivery / staffing : missions, CRA, absences, validations. */
|
|
45
|
+
readonly delivery: readonly ["projects", "deliveries", "resources", "timesheets", "absences", "planning-absences", "validations", "application", "workflows"];
|
|
46
|
+
/** Administration de l'outil : référentiels d'organisation et journaux. */
|
|
47
|
+
readonly admin: readonly ["accounts", "agencies", "business-units", "poles", "roles", "logs", "webhooks", "flags", "application"];
|
|
48
|
+
};
|
|
49
|
+
/** Profile name literals (`"recruiting" | "sales" | …`). */
|
|
50
|
+
export type ProfileName = keyof typeof PROFILE_TABLE;
|
|
51
|
+
/**
|
|
52
|
+
* The profile bundles. Keyed by `string` for iteration/lookup convenience;
|
|
53
|
+
* `ProfileName` above keeps the literal union available for typed callers (an
|
|
54
|
+
* index signature on the exported value would erase it).
|
|
55
|
+
*/
|
|
56
|
+
export declare const PROFILES: Readonly<Record<string, readonly DomainName[]>>;
|
|
57
|
+
/** Canonical list of profile names, for error messages and docs. */
|
|
58
|
+
export declare const PROFILE_NAMES: readonly ProfileName[];
|
|
59
|
+
/**
|
|
60
|
+
* Case-insensitive profile lookup (`Finance`, `FINANCE` → `finance`).
|
|
61
|
+
*
|
|
62
|
+
* `Object.hasOwn` is what makes this safe: a plain `PROFILES[name]` returns
|
|
63
|
+
* `Object.prototype`'s own properties for `BOOND_MCP_PROFILE=constructor`
|
|
64
|
+
* (`toString`, `valueOf`, `hasOwnProperty`, `__proto__`…) — a truthy non-array
|
|
65
|
+
* that skips the caller's warn-and-ignore branch and then throws
|
|
66
|
+
* `TypeError: … is not iterable` at startup, i.e. a dead server instead of the
|
|
67
|
+
* documented warning.
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolveProfile(name: string): readonly DomainName[] | undefined;
|
|
70
|
+
export {};
|
|
71
|
+
//# sourceMappingURL=profiles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../../src/config/profiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,QAAA,MAAM,aAAa;IACjB,2EAA2E;;IAa3E,6DAA6D;;IAc7D,2EAA2E;;IAc3E,kEAAkE;;IAYlE,2EAA2E;;CAEnB,CAAC;AAE3D,4DAA4D;AAC5D,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,aAAa,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,CAAiB,CAAC;AAEvF,oEAAoE;AACpE,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EAAgD,CAAC;AAEjG;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,UAAU,EAAE,GAAG,SAAS,CAG9E"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-composed domain sets ("profiles") for `BOOND_MCP_PROFILE`.
|
|
3
|
+
*
|
|
4
|
+
* Why: `BOOND_MCP_DOMAINS` is the precise tool, but composing it means knowing
|
|
5
|
+
* all 38 domain names *and* which ones a job actually needs (a recruiter needs
|
|
6
|
+
* `positionings` and `actions`, not just `candidates`). With on-demand tool
|
|
7
|
+
* discovery in clients, narrowing the surface is still the highest-leverage
|
|
8
|
+
* knob — so it has to be usable in one env var, without a trip to TOOLS.md.
|
|
9
|
+
*
|
|
10
|
+
* Each profile is a job-shaped bundle, not a security tier: see
|
|
11
|
+
* `docs/access-control.md`, this layer hides tools from the model, it does not
|
|
12
|
+
* revoke BoondManager rights. Combine with `BOOND_MCP_READ_ONLY` /
|
|
13
|
+
* `BOOND_MCP_OPERATIONS` (orthogonal axis) to bound what can be written.
|
|
14
|
+
*
|
|
15
|
+
* `application` is in every profile on purpose: it backs dictionary resolution
|
|
16
|
+
* (state/type labels) and `current-user`, which many tools and prompts depend
|
|
17
|
+
* on. `workflows` is listed wherever prompt mirrors make sense; it is not
|
|
18
|
+
* strictly required (workflow tools follow their source prompt's domains, not
|
|
19
|
+
* the allow-list), but keeping it explicit documents the intent and survives a
|
|
20
|
+
* future change of that rule.
|
|
21
|
+
*
|
|
22
|
+
* There is no blanket "`resources` everywhere" rule — the rule is **per
|
|
23
|
+
* profile, check the prompt count**. 8 of the 11 prompts orchestrate
|
|
24
|
+
* `resources` (`synthese_equipe`, `staffing_disponible`, `fiche_consultant`,
|
|
25
|
+
* `recherche_profil_competences`, …) and a prompt is cut as soon as ONE of its
|
|
26
|
+
* domains is filtered out, so leaving `resources` out of `recruiting` / `sales`
|
|
27
|
+
* bought ~10 fewer tools and cost most of their runbooks — the wrong trade for a
|
|
28
|
+
* layer whose whole point is ergonomics. It is also what those jobs actually
|
|
29
|
+
* need: a recruiter matches candidates against internal staff, a salesperson
|
|
30
|
+
* staffs a deal. `finance` and `admin` deliberately do NOT include it: neither
|
|
31
|
+
* has a runbook that touches `resources` (`finance`'s only prompt,
|
|
32
|
+
* `factures_a_relancer`, spans `invoices` + `application`), so it would add
|
|
33
|
+
* tools and no capability. When adding a profile, count the prompts it keeps —
|
|
34
|
+
* not just the tools.
|
|
35
|
+
*/
|
|
36
|
+
const PROFILE_TABLE = {
|
|
37
|
+
/** Recrutement / sourcing : viviers, positionnements, suivi d'activité. */
|
|
38
|
+
recruiting: [
|
|
39
|
+
"candidates",
|
|
40
|
+
"positionings",
|
|
41
|
+
"opportunities",
|
|
42
|
+
"contacts",
|
|
43
|
+
"companies",
|
|
44
|
+
"documents",
|
|
45
|
+
"actions",
|
|
46
|
+
"resources",
|
|
47
|
+
"application",
|
|
48
|
+
"workflows",
|
|
49
|
+
],
|
|
50
|
+
/** Avant-vente / commerce : pipeline, comptes, commandes. */
|
|
51
|
+
sales: [
|
|
52
|
+
"opportunities",
|
|
53
|
+
"companies",
|
|
54
|
+
"contacts",
|
|
55
|
+
"actions",
|
|
56
|
+
"projects",
|
|
57
|
+
"orders",
|
|
58
|
+
"products",
|
|
59
|
+
"reporting",
|
|
60
|
+
"resources",
|
|
61
|
+
"application",
|
|
62
|
+
"workflows",
|
|
63
|
+
],
|
|
64
|
+
/** Gestion / compta : facturation client et fournisseur, encaissements. */
|
|
65
|
+
finance: [
|
|
66
|
+
"invoices",
|
|
67
|
+
"payments",
|
|
68
|
+
"orders",
|
|
69
|
+
"purchases",
|
|
70
|
+
"provider-invoices",
|
|
71
|
+
"expenses",
|
|
72
|
+
"projects",
|
|
73
|
+
"companies",
|
|
74
|
+
"reporting",
|
|
75
|
+
"application",
|
|
76
|
+
"workflows",
|
|
77
|
+
],
|
|
78
|
+
/** Delivery / staffing : missions, CRA, absences, validations. */
|
|
79
|
+
delivery: [
|
|
80
|
+
"projects",
|
|
81
|
+
"deliveries",
|
|
82
|
+
"resources",
|
|
83
|
+
"timesheets",
|
|
84
|
+
"absences",
|
|
85
|
+
"planning-absences",
|
|
86
|
+
"validations",
|
|
87
|
+
"application",
|
|
88
|
+
"workflows",
|
|
89
|
+
],
|
|
90
|
+
/** Administration de l'outil : référentiels d'organisation et journaux. */
|
|
91
|
+
admin: ["accounts", "agencies", "business-units", "poles", "roles", "logs", "webhooks", "flags", "application"],
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* The profile bundles. Keyed by `string` for iteration/lookup convenience;
|
|
95
|
+
* `ProfileName` above keeps the literal union available for typed callers (an
|
|
96
|
+
* index signature on the exported value would erase it).
|
|
97
|
+
*/
|
|
98
|
+
export const PROFILES = PROFILE_TABLE;
|
|
99
|
+
/** Canonical list of profile names, for error messages and docs. */
|
|
100
|
+
export const PROFILE_NAMES = Object.keys(PROFILE_TABLE);
|
|
101
|
+
/**
|
|
102
|
+
* Case-insensitive profile lookup (`Finance`, `FINANCE` → `finance`).
|
|
103
|
+
*
|
|
104
|
+
* `Object.hasOwn` is what makes this safe: a plain `PROFILES[name]` returns
|
|
105
|
+
* `Object.prototype`'s own properties for `BOOND_MCP_PROFILE=constructor`
|
|
106
|
+
* (`toString`, `valueOf`, `hasOwnProperty`, `__proto__`…) — a truthy non-array
|
|
107
|
+
* that skips the caller's warn-and-ignore branch and then throws
|
|
108
|
+
* `TypeError: … is not iterable` at startup, i.e. a dead server instead of the
|
|
109
|
+
* documented warning.
|
|
110
|
+
*/
|
|
111
|
+
export function resolveProfile(name) {
|
|
112
|
+
const key = name.toLowerCase().trim();
|
|
113
|
+
return Object.hasOwn(PROFILES, key) ? PROFILES[key] : undefined;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=profiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../src/config/profiles.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,aAAa,GAAG;IACpB,2EAA2E;IAC3E,UAAU,EAAE;QACV,YAAY;QACZ,cAAc;QACd,eAAe;QACf,UAAU;QACV,WAAW;QACX,WAAW;QACX,SAAS;QACT,WAAW;QACX,aAAa;QACb,WAAW;KACZ;IACD,6DAA6D;IAC7D,KAAK,EAAE;QACL,eAAe;QACf,WAAW;QACX,UAAU;QACV,SAAS;QACT,UAAU;QACV,QAAQ;QACR,UAAU;QACV,WAAW;QACX,WAAW;QACX,aAAa;QACb,WAAW;KACZ;IACD,2EAA2E;IAC3E,OAAO,EAAE;QACP,UAAU;QACV,UAAU;QACV,QAAQ;QACR,WAAW;QACX,mBAAmB;QACnB,UAAU;QACV,UAAU;QACV,WAAW;QACX,WAAW;QACX,aAAa;QACb,WAAW;KACZ;IACD,kEAAkE;IAClE,QAAQ,EAAE;QACR,UAAU;QACV,YAAY;QACZ,WAAW;QACX,YAAY;QACZ,UAAU;QACV,mBAAmB;QACnB,aAAa;QACb,aAAa;QACb,WAAW;KACZ;IACD,2EAA2E;IAC3E,KAAK,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,CAAC;CACvD,CAAC;AAK3D;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAoD,aAAa,CAAC;AAEvF,oEAAoE;AACpE,MAAM,CAAC,MAAM,aAAa,GAA2B,MAAM,CAAC,IAAI,CAAC,aAAa,CAAkB,CAAC;AAEjG;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IACtC,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAClE,CAAC"}
|
package/dist/icons.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { DomainName } from "./constants.js";
|
|
3
|
+
import type { RegistrationIndex } from "./tools/registration-decorators.js";
|
|
4
|
+
/**
|
|
5
|
+
* Protocol-level icons (SEP-973, spec 2025-11-25) for tools, prompts and
|
|
6
|
+
* resources.
|
|
7
|
+
*
|
|
8
|
+
* ## Scope: one icon per *domain*, not per tool
|
|
9
|
+
*
|
|
10
|
+
* 180 hand-picked icons would be unmaintainable and would triple the byte cost
|
|
11
|
+
* below. Every tool of a domain shares that domain's glyph, which is also what
|
|
12
|
+
* a client UI wants: the icon groups the catalogue, the name distinguishes
|
|
13
|
+
* inside the group.
|
|
14
|
+
*
|
|
15
|
+
* ## Byte cost
|
|
16
|
+
*
|
|
17
|
+
* `icons` rides on every entry of `tools/list`, so it competes with the tool
|
|
18
|
+
* catalogue itself. Two consequences baked into the format below:
|
|
19
|
+
*
|
|
20
|
+
* - inline `data:` SVG only (no network fetch from the client, no asset to
|
|
21
|
+
* host, no CSP question);
|
|
22
|
+
* - a deliberately spartan glyph vocabulary — 16×16 viewBox, single `<path>`,
|
|
23
|
+
* no `mimeType`/`sizes` fields (the data URI already carries the type, and an
|
|
24
|
+
* SVG is scalable by definition). `descriptions.test.ts` caps both the
|
|
25
|
+
* per-icon size and the total added to `tools/list`.
|
|
26
|
+
*
|
|
27
|
+
* ## Why a response decorator and not a `registerTool` option
|
|
28
|
+
*
|
|
29
|
+
* `@modelcontextprotocol/sdk@1.30` types `icons` on `Tool`/`Prompt`/`Resource`
|
|
30
|
+
* but its `McpServer` never emits them: the `tools/list` and `prompts/list`
|
|
31
|
+
* handlers build their entries field by field and drop anything else
|
|
32
|
+
* (`server/mcp.js`). Resources are the exception — their listing spreads the
|
|
33
|
+
* whole registration config, so `registerResource` can carry `icons` natively
|
|
34
|
+
* (see `resources/index.ts`).
|
|
35
|
+
*
|
|
36
|
+
* So for tools and prompts we decorate the *responses*: `installProtocolIcons`
|
|
37
|
+
* wraps the handlers the SDK installs, using only the public
|
|
38
|
+
* `Server.setRequestHandler` API plus schema identity. When the SDK gains
|
|
39
|
+
* first-class support, this whole shim can be deleted in favour of passing
|
|
40
|
+
* `icons` in the registration config — `src/icons.test.ts` fails loudly if the
|
|
41
|
+
* shim ever stops producing icons.
|
|
42
|
+
*/
|
|
43
|
+
export interface Icon {
|
|
44
|
+
src: string;
|
|
45
|
+
mimeType?: string;
|
|
46
|
+
sizes?: string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Domain → icons. Every entry of `REGISTERED_DOMAINS` must be present
|
|
50
|
+
* (asserted in `icons.test.ts`), so adding a domain without an icon fails CI
|
|
51
|
+
* rather than shipping a half-iconified catalogue.
|
|
52
|
+
*/
|
|
53
|
+
export declare const DOMAIN_ICONS: Readonly<Record<DomainName, Icon[]>>;
|
|
54
|
+
/**
|
|
55
|
+
* Icons for the dictionary / reference resources (`boond://…`). Resolved
|
|
56
|
+
* through a function, not a constant, because `registerAllResources` runs at
|
|
57
|
+
* startup and must honour `BOOND_MCP_ICONS` too.
|
|
58
|
+
*/
|
|
59
|
+
export declare function referenceIcons(): Icon[] | undefined;
|
|
60
|
+
/** Icons for the `current-user` resource. */
|
|
61
|
+
export declare function identityIcons(): Icon[] | undefined;
|
|
62
|
+
export declare function iconsForDomain(domain: DomainName | undefined): Icon[] | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Prompt → icons, from the first domain the prompt orchestrates (its subject:
|
|
65
|
+
* `factures_a_relancer` → invoices, `synthese_equipe` → resources).
|
|
66
|
+
*/
|
|
67
|
+
export declare function iconsForPrompt(name: string): Icon[] | undefined;
|
|
68
|
+
/** Total byte cost of an icon payload, for the cap test and the docs. */
|
|
69
|
+
export declare function iconsByteSize(icons: readonly Icon[] | undefined): number;
|
|
70
|
+
/**
|
|
71
|
+
* Attach domain icons to `tools/list` and `prompts/list` responses.
|
|
72
|
+
*
|
|
73
|
+
* MUST be called before the first `registerTool` / `registerPrompt` on this
|
|
74
|
+
* server: it works by intercepting the `setRequestHandler` calls the SDK makes
|
|
75
|
+
* when it lazily installs those handlers. `index` is read at request time, so
|
|
76
|
+
* it can still be empty at install time.
|
|
77
|
+
*/
|
|
78
|
+
export declare function installProtocolIcons(server: McpServer, index: RegistrationIndex): void;
|
|
79
|
+
//# sourceMappingURL=icons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,MAAM,WAAW,IAAI;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAmED;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAuC7D,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,IAAI,EAAE,GAAG,SAAS,CAEnD;AAED,6CAA6C;AAC7C,wBAAgB,aAAa,IAAI,IAAI,EAAE,GAAG,SAAS,CAElD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI,EAAE,GAAG,SAAS,CAGjF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,SAAS,CAG/D;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,SAAS,GAAG,MAAM,CAExE;AAQD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,GAAG,IAAI,CA4BtF"}
|