@vantageos/mcp-boilerplate 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,51 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@vantageos/mcp-boilerplate` are documented in this file.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.1] - 2026-08-07
11
+
12
+ Hardening pass on the published template — packaging and documentation
13
+ hygiene, no behavioral changes to the server layers.
14
+
15
+ ### Added
16
+
17
+ - Bilingual `README.fr.md` + `description_fr` in `package.json` (T1).
18
+ - This `CHANGELOG.md`, shipped inside the npm package (T2).
19
+ - Eval suite hardened to >=3 evals/tool, with an opt-in tenant toggle (T3).
20
+ - Fleet `biome.json` shipped at source, normalized to 0 lint errors (from #2).
21
+
22
+ ### Changed
23
+
24
+ - Template hygiene: `mosaic-card` vendored into the template instead of an
25
+ external dependency; alpha-only devDependency dropped (T4).
26
+
27
+ ## [0.1.0] - 2026-08-04
28
+
29
+ Initial published release.
30
+
31
+ ### Added
32
+
33
+ - Dual-transport MCP server bootstrap built exclusively on the official
34
+ `@modelcontextprotocol/sdk` transports: stdio (`StdioServerTransport`) and
35
+ stateless Streamable HTTP (`WebStandardStreamableHTTPServerTransport`).
36
+ - `@vantageos/mcp-protocol-kit` wiring for shared result types.
37
+ - OAuth 2.1 resource-server auth layer (`@vantageos/mcp-auth-kit`), with a
38
+ public no-auth tier alongside the authenticated tier.
39
+ - Multi-tenant scoping layer with proven tenant isolation.
40
+ - MCP Apps UI extension: `ui://` resource serving a bundled widget
41
+ (`src/ui/Widget.tsx`, Vite single-file build).
42
+ - Bilingual i18n (FR/EN) via `@vantageos/mosaic-i18n`, covering tool
43
+ descriptions and the UI resource.
44
+ - Evals harness (`evals/`) exercising the tool surface end-to-end.
45
+ - Example `ping` tool proving the handshake on both transports.
46
+ - Reproducible build via `npm ci`; 52/52 tests passing at release time.
47
+ - MIT license, clonable as a starter template.
48
+
49
+ [Unreleased]: https://github.com/elpiarthera/vantage-mcp-boilerplate/compare/v0.1.1...HEAD
50
+ [0.1.1]: https://github.com/elpiarthera/vantage-mcp-boilerplate/compare/v0.1.0...v0.1.1
51
+ [0.1.0]: https://github.com/elpiarthera/vantage-mcp-boilerplate/releases/tag/v0.1.0
package/README.fr.md ADDED
@@ -0,0 +1,193 @@
1
+ # @vantageos/mcp-boilerplate
2
+
3
+ Un squelette de serveur MCP clonable : bootstrap double-transport (stdio +
4
+ Streamable HTTP, sans état) construit exclusivement sur les transports
5
+ officiels du [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk).
6
+ Aucune route REST personnalisée ne se place jamais devant un appel d'outil.
7
+
8
+ Ceci est une fondation, pas un produit fini : il embarque un outil d'exemple
9
+ trivial (`ping`) dont le seul but est de prouver que la poignée de main MCP
10
+ fonctionne sur les deux transports. Les couches ultérieures (types de résultat
11
+ protocol-kit, authentification, scoping multi-tenant, extensions UI, i18n) se
12
+ construisent au-dessus de ce bootstrap sans modifier le câblage du transport.
13
+
14
+ ## Structure
15
+
16
+ ```
17
+ src/
18
+ mcpServerFactory.ts # définition unique du serveur MCP, partagée par les deux transports
19
+ stdio.ts # point d'entrée StdioServerTransport du SDK officiel
20
+ http.ts # adaptateur Node http.Server autour de l'app Hono
21
+ httpApp.ts # WebStandardStreamableHTTPServerTransport du SDK officiel (sans état)
22
+ auth.ts # câblage OAuth 2.1 resource-server (@vantageos/mcp-auth-kit)
23
+ config.ts # chargeurs AuthMode + AuthConfig dérivés de l'environnement
24
+ index.ts # exports du package
25
+ tests/
26
+ helpers/mcpRpc.ts # helpers de requête JSON-RPC pour le transport HTTP
27
+ helpers/authFixtures.ts # fixtures de signature JWT RS256 réservées aux tests
28
+ httpHandshake.test.ts # initialize -> tools/list -> tools/call sur Streamable HTTP
29
+ stdioHandshake.test.ts # même poignée de main sur un vrai process enfant stdio
30
+ oauth.test.ts # les deux paliers d'authentification : gate oauth + palier public sans auth
31
+ docs/
32
+ architecture.md # posture du protocole : version au niveau outil vs au niveau transport
33
+ ```
34
+
35
+ ## Démarrage rapide
36
+
37
+ ```bash
38
+ npm install
39
+ npm run build
40
+
41
+ # stdio (config client local, ex. Claude Code / Cursor) — jamais gardé,
42
+ # le process local qui invoque stdio EST l'appelant.
43
+ npm run start:stdio
44
+
45
+ # Streamable HTTP (distant, sans état) — gate OAuth 2.1 par défaut :
46
+ MCP_OAUTH_ISSUER=https://your-tenant.example.com \
47
+ MCP_OAUTH_AUDIENCE=https://your-mcp-server.example.com \
48
+ PORT=8787 npm run start:http
49
+
50
+ # Streamable HTTP, palier "Public MCP" sans authentification (local/self-host, appelant de confiance) :
51
+ AUTH_MODE=public PORT=8787 npm run start:http
52
+ ```
53
+
54
+ ## Paliers d'authentification
55
+
56
+ Deux paliers, selon `mcp-standard.md` "Authentication & Authorization" :
57
+
58
+ | `AUTH_MODE` | Comportement |
59
+ |---|---|
60
+ | `oauth` (par défaut) | Resource server OAuth 2.1 (`@vantageos/mcp-auth-kit`) : chaque appel HTTP `/mcp` exige un Bearer JWT RS256 valide, lié à l'audience/l'émetteur. Token manquant/invalide -> `401` + `WWW-Authenticate`. Les métadonnées RFC 9728 Protected Resource sont servies sur `/.well-known/oauth-protected-resource`. `/health` reste sans token. Nécessite `MCP_OAUTH_ISSUER` + `MCP_OAUTH_AUDIENCE`. |
61
+ | `public` | Aucun gate sur le transport HTTP — pour un usage local/self-host où l'appelant est déjà de confiance. Reprend le modèle de confiance du transport stdio (stdio n'a jamais eu de gate). Aucun document `.well-known/oauth-protected-resource` n'est servi dans ce mode (il n'y a pas de serveur d'autorisation à décrire). |
62
+
63
+ Le transport stdio (`stdio.ts`) n'est jamais gardé, dans aucun des deux modes
64
+ — le process local qui l'invoque EST l'appelant, selon le modèle de confiance
65
+ de `mcp-standard.md` pour les outils locaux/self-host.
66
+
67
+ `buildHttpApp()` appelé sans argument revient par défaut au palier `public` —
68
+ c'est ce que les tests du squelette de transport (`httpHandshake.test.ts`,
69
+ `protocolKitWiring.test.ts`) exercent, donc ils n'ont besoin d'aucune
70
+ configuration OAuth. Le point d'entrée de production (`http.ts`) résout
71
+ toujours `AUTH_MODE` depuis l'environnement via `config.ts`, avec `oauth`
72
+ comme valeur par défaut si non défini.
73
+
74
+ ## i18n côté serveur (messages d'erreur FR/EN)
75
+
76
+ `src/i18n.ts` localise les messages d'erreur/validation MCP (rejet
77
+ d'authentification, refus de tenant, validation d'entrée d'outil) selon le
78
+ mandat bilingue de `mcp-standard.md` (§Bilingual) : le client envoie
79
+ `X-MCP-Locale: fr` ou `X-MCP-Locale: en` (par défaut `en` si absent), et
80
+ `src/httpApp.ts` + `src/mcpServerFactory.ts` acheminent le message
81
+ correspondant via `t(locale, key)`.
82
+
83
+ Les deux fichiers de ressources (`src/locales/{en,fr}.json`) suivent
84
+ exactement la convention de ressource à espace de noms livrée par
85
+ `@vantageos/mosaic-i18n@0.1.1`
86
+ (`node_modules/@vantageos/mosaic-i18n/src/locales/{en,fr}.json`) : un objet
87
+ plat `<Namespace>.<catégorie>.<clé>` -> chaîne, FR et EN maintenus clé pour
88
+ clé en parfait alignement. `mosaic-i18n` lui-même est un package
89
+ React/`react-i18next` et ne peut pas être appelé directement depuis un
90
+ serveur JSON-RPC, donc son API d'exécution n'est pas importée ici — la forme
91
+ de son fichier de ressources est réutilisée à la place, sous le namespace
92
+ `Mcp` propre à ce boilerplate.
93
+
94
+ ## Tests
95
+
96
+ ```bash
97
+ npm test
98
+ ```
99
+
100
+ Exécute les deux transports contre les vrais chemins de code du SDK officiel :
101
+ la suite HTTP pilote l'app Hono en mémoire ; la suite stdio lance le binaire
102
+ `dist/stdio.js` compilé comme un vrai process enfant via `StdioClientTransport`.
103
+
104
+ ## Ajouter un outil
105
+
106
+ Enregistrez-le une seule fois dans `src/mcpServerFactory.ts` — il devient
107
+ alors disponible automatiquement sur les deux transports. Il n'y a aucune
108
+ route REST séparée à ajouter.
109
+
110
+ ## Packaging & distribution
111
+
112
+ Ce boilerplate est lui-même un package npm publiable/clonable. Deux
113
+ artefacts portent son identité de distribution :
114
+
115
+ - `package.json` — le package npm. `files` ne livre que l'arbre `dist/`
116
+ compilé (serveur compilé + `dist/locales/` + `dist/ui-bundle/widget.html`),
117
+ le `README.md`, la `LICENSE`, le manifeste de plugin, et la config client
118
+ d'exemple — jamais `src/`, les tests, ou l'outillage. `main`/`types`/`exports`
119
+ pointent vers `dist/index.js` ; le bin `mcp-boilerplate` pointe vers
120
+ `dist/stdio.js`. `publishConfig.access = public` est requis pour le scope
121
+ `@vantageos`.
122
+ - `.claude-plugin/plugin.json` — le manifeste de catalogue Claude Code
123
+ marketplace / VantageRegistry, suivant la convention fleet des serveurs MCP
124
+ (miroir de `vantage-frameworks-mcp` / `vantage-agent-composer-mcp`) :
125
+ `name`, `version`, `description` bilingue + `description_fr`, `author`,
126
+ `license`, `homepage`, `category: "mcp-server"`, `bilingual: true`,
127
+ `keywords`.
128
+
129
+ ### Scaffold → build → publish
130
+
131
+ ```bash
132
+ # 1. Scaffold : clonez ce repo (ou le tarball npm) comme squelette de votre serveur.
133
+ git clone https://github.com/elpiarthera/vantage-mcp-boilerplate.git my-mcp
134
+ cd my-mcp && npm install --legacy-peer-deps # voir la note de skew peer-range dev ci-dessous
135
+
136
+ # 2. Renommer : définissez "name"/"bin" dans package.json et "name" dans
137
+ # .claude-plugin/plugin.json pour votre serveur, puis ajoutez des outils dans src/mcpServerFactory.ts.
138
+
139
+ # 3. Build + vérification depuis un arbre propre (ce que CI et prepublishOnly imposent) :
140
+ rm -rf dist node_modules/.vite && npm run build && npm test && npm run evals
141
+
142
+ # 4. Inspectez le tarball avant publication — confirmez que dist/ est bien livré et que rien ne fuit :
143
+ npm pack --dry-run
144
+
145
+ # 5. Publiez sur les deux canaux :
146
+ npm publish # registre npm (prepublishOnly relance build+test+evals)
147
+ # Catalogue VantageRegistry : enregistrez .claude-plugin/plugin.json via
148
+ # le skill fleet create-plugin / generate-marketplace (upsert VR).
149
+ ```
150
+
151
+ `prepublishOnly` relance `build → build:ui → test → evals` pour qu'un
152
+ tarball cassé ou contenant uniquement `src` ne puisse jamais atteindre npm.
153
+ Les canaux de distribution sont **npm** (le package exécutable) et le
154
+ **catalogue VantageRegistry / Claude Code marketplace** (découverte, via
155
+ `plugin.json`).
156
+
157
+ ## Couche UI MCP Apps
158
+
159
+ `render_items_ui` affiche `EXAMPLE_ITEMS` comme un widget interactif via
160
+ l'officiel `@modelcontextprotocol/ext-apps/server` (`registerAppTool` +
161
+ `registerAppResource`), forme imbriquée GA `_meta.ui.resourceUri` (stable
162
+ depuis le 2026-01-26) — jamais la clé plate dépréciée `_meta["ui/resourceUri"]`.
163
+ Un repli markdown est toujours présent dans `content[0]`, même pour les
164
+ clients qui ne négocient jamais l'extension `io.modelcontextprotocol/ui`.
165
+
166
+ Le widget (`src/ui/`) réutilise une famille `MosaicCard` vendorisée
167
+ (`src/ui/mosaic-card.tsx` — atomes présentationnels, aucune dépendance
168
+ d'exécution) et est empaqueté en un seul fichier HTML autonome
169
+ (`vite-plugin-singlefile`, `dist/ui-bundle/widget.html`, ~70 Ko gzippé,
170
+ aucun fetch d'exécution externe). `npm run build:ui` produit ce bundle
171
+ indépendamment de `npm run build` (tsc), sur un chemin de sortie sans
172
+ collision (`dist/ui-bundle/` vs `dist/ui/` de tsc) — les deux étapes de
173
+ build écrivent sur des arbres `dist/ui*` d'apparence similaire mais jamais
174
+ sur le même répertoire, si bien que `emptyOutDir` côté vite ne peut jamais
175
+ supprimer un module serveur compilé par tsc.
176
+
177
+ **Hygiène du template** : les atomes `MosaicCard` sont vendorisés
178
+ localement plutôt qu'importés depuis `@vantageos/mosaic-blocks`, un paquet
179
+ interne sans version stable (non-alpha) publiée sur npm. Une
180
+ devDependency de template épinglée sur un tag alpha mouvant casse au
181
+ prochain bump alpha ; vendoriser les quatre primitives présentationnelles
182
+ réellement utilisées par le widget élimine ce mode de défaillance.
183
+
184
+ **Ordre de publication (exigence stricte)** : ce boilerplate dépend de
185
+ `@vantageos/mcp-protocol-kit@^0.2.0`. Le câblage de `tools/list` utilise
186
+ `buildToolsListResult` du kit, qui existe UNIQUEMENT à partir du kit 0.2.0+.
187
+ En semver 0.x, `^0.2.0` n'accepte PAS le 0.1.x, donc un `npm install` frais
188
+ depuis le registre résout la version du kit dont le code a réellement
189
+ besoin. Par conséquent, **le kit `@vantageos/mcp-protocol-kit` 0.2.0 DOIT
190
+ être publié sur npm AVANT que ce boilerplate puisse être installé ou publié
191
+ depuis le registre.** C'est un ordre strict, non optionnel : publiez d'abord
192
+ le kit, confirmez que 0.2.0 est en ligne sur le registre, puis publiez le
193
+ boilerplate.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # @vantageos/mcp-boilerplate
2
2
 
3
+ SELLABLE AS: `mcp-boilerplate` — a clonable MCP server starter for the Claude Code marketplace / VantageRegistry catalogue, published as `@vantageos/mcp-boilerplate` on npm.
4
+
3
5
  A clonable MCP server skeleton: dual-transport bootstrap (stdio + Streamable
4
6
  HTTP, stateless) built exclusively on the official
5
7
  [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk)
@@ -155,8 +157,9 @@ official `@modelcontextprotocol/ext-apps/server` (`registerAppTool` +
155
157
  markdown fallback is always present in `content[0]`, even for clients that
156
158
  never negotiate the `io.modelcontextprotocol/ui` extension.
157
159
 
158
- The widget (`src/ui/`) reuses `@vantageos/mosaic-blocks`' `MosaicCard`
159
- family and is bundled to a single self-contained HTML file
160
+ The widget (`src/ui/`) reuses a vendored `MosaicCard` family
161
+ (`src/ui/mosaic-card.tsx` — style-only presentational atoms, no runtime
162
+ dependency) and is bundled to a single self-contained HTML file
160
163
  (`vite-plugin-singlefile`, `dist/ui-bundle/widget.html`, ~70 KB gzipped, no
161
164
  external runtime fetch). `npm run build:ui` produces this bundle
162
165
  independently of `npm run build` (tsc), on a non-colliding output path
@@ -165,13 +168,12 @@ same-looking `dist/ui*` tree but never share a directory, so
165
168
  `emptyOutDir` on the vite side can never delete a tsc-compiled server
166
169
  module.
167
170
 
168
- **Known dev peer-range skew**: `@vantageos/mosaic-blocks@0.5.34-alpha`
169
- declares `peerOptional @vantageos/cloud-identity@^0.2`, while this
170
- boilerplate's own dependency is `^0.3.0` (via `@vantageos/mcp-auth-kit`).
171
- `npm install` currently needs `--legacy-peer-deps` to resolve. This is a
172
- dev-only peer-range mismatch (mosaic-blocks is a devDependency, used only
173
- to build the widget bundle) — the full test suite is green from a clean
174
- build under the `^0.3.0` runtime dependency, proving no runtime conflict.
171
+ **Template hygiene**: the `MosaicCard` atoms are vendored locally rather
172
+ than pulled from `@vantageos/mosaic-blocks`, an internal package with no
173
+ stable (non-alpha) npm release. A fork-template devDependency pinned to a
174
+ moving alpha tag breaks on the next alpha bump; vendoring the four
175
+ presentational primitives the widget actually uses removes that failure
176
+ mode entirely.
175
177
 
176
178
  **Publish ordering (hard requirement)**: this boilerplate depends on
177
179
  `@vantageos/mcp-protocol-kit@^0.2.0`. The `tools/list` wiring uses the kit's
package/dist/stdio.js CHANGED
@@ -8,7 +8,14 @@
8
8
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
9
  import { createBoilerplateMcpServer } from "./mcpServerFactory.js";
10
10
  export async function startStdioServer() {
11
- const server = createBoilerplateMcpServer();
11
+ // `requireTenant` is otherwise only reachable from the OAuth-tier HTTP
12
+ // transport (see httpApp.ts). This env toggle exists solely so the eval
13
+ // suite (evals/evals.json "list-items-requires-tenant-refusal") can
14
+ // exercise the ALREADY-EXISTING `list_items` tenant-refusal branch in
15
+ // mcpServerFactory.ts through the real stdio transport, without adding a
16
+ // new code path. Unset by default — normal stdio usage is unaffected.
17
+ const requireTenant = process.env.MCP_BOILERPLATE_REQUIRE_TENANT === "1";
18
+ const server = createBoilerplateMcpServer({ requireTenant });
12
19
  const transport = new StdioServerTransport();
13
20
  await server.connect(transport);
14
21
  process.stderr.write("[mcp-boilerplate] stdio server started — 1 tool available\n");