@bicon/mcp-composer 0.1.0 → 0.1.7

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 (3) hide show
  1. package/README.md +137 -72
  2. package/dist/index.mjs +2413 -228
  3. package/package.json +4 -2
package/README.md CHANGED
@@ -23,110 +23,175 @@ via API keys is a separate, security-reviewed phase.
23
23
 
24
24
  | Name | What it does |
25
25
  |---|---|
26
- | resource `initiative://schema` / tool `get_initiative_schema` | The field catalog: required fields, enum values, the four dimensions with their named sub-dimensions (EN/DE labels + help text), confidence scale, optional sections, and the handoff steps. **Read this first.** |
27
- | `assemble_initiative` | Compact spec (metadata + named sub-ratings 0–100 + confidence per dimension) → fully-formed initiative validated against the API contract (`CreateInitiativeBody` from `@workspace/api-zod`). Mints id/timestamps, **derives** the four dimension scores (mean of subs, like the app), returns `{ok, initiative, derivedScores, warnings, errors}` with precise per-field errors. |
28
- | `export_initiative_file` | Wraps an assembled initiative in the app's single-initiative JSON envelope; returns `{filename, json, importInstructions, derivedScores}`. |
29
-
30
- The score derivation is a test-pinned copy of the app's `scoring.ts`
31
- (golden test against the "Advisor Copilot" demo seed → 77 / 61 / 73 / 90),
32
- and a catalog-drift test fails the build if the OpenAPI contract's enums or
33
- sub-dimension keys change without a catalog update.
34
-
35
- ## Install for users (no clone, no build)
36
-
37
- The package is published to npm as `@bicon/mcp-composer` — a single
38
- self-contained bundle whose only runtime dependency is the MCP SDK. Any user
39
- with Node ≥ 20 adds this to Claude Desktop's `claude_desktop_config.json`
40
- (Settings → Developer → Edit Config) and restarts:
26
+ | resource `initiative://schema` / tool `get_initiative_schema` | The field catalog: required fields, enum values, the four dimensions with their named sub-dimensions (EN/DE labels + help text, plus the wording the app uses in digital / innovation portfolios), the exact shape of every optional section, the EU-AI-Act vocabularies, and the handoff steps. **Read this first.** |
27
+ | `assemble_initiative` | Compact spec (metadata + named sub-ratings 0–100 + confidence per dimension + optional sections) → fully-formed initiative validated against the API contract (`CreateInitiativeBody` from `@workspace/api-zod`). Mints id/timestamps, **derives** the four dimension scores (the app's own scoring function), returns `{ok, initiative, derivedScores, warnings, errors}`. |
28
+ | `export_initiative_file` | Takes the **same compact spec**, assembles it and wraps the result in the app's single-initiative JSON envelope; returns `{ok, filename, json, importInstructions, derivedScores, warnings}`. There is one pipeline — a hand-edited initiative object is not an input, so client-supplied scores or unknown keys can never bypass assembly. |
29
+ | `composer_version` | Returns `{composerVersion, capabilities}`. Every *successful* tool result also carries `composerVersion`. |
30
+
31
+ ### How validation works (and why it lives at the wire)
32
+
33
+ The MCP SDK validates every call with the registered schema **and hands the
34
+ handler the parsed value** — whatever the schema strips, the server never sees.
35
+ So the spec schema is registered as a full **strict** object, with every
36
+ optional section a **deep-strict copy of the API contract**: an unknown key
37
+ anywhere is rejected by the SDK with its exact path
38
+ (`Unrecognized key(s) in object: 'literacy' at aiAct`), enum values, date
39
+ formats (`YYYY-MM-DD`, real calendar dates), blank names and non-UUID ids are
40
+ caught with field paths, and the advertised JSON Schema
41
+ (`additionalProperties: false`, no `$ref` pointers) means what it says. A
42
+ section may also be sent as a **JSON string** (clients working from a stale
43
+ tool descriptor did that); it is parsed and validated identically. What a JSON
44
+ Schema cannot express — the 30 named ratings, the AI-Act controlled
45
+ vocabularies (`aiActVocabularies` in the descriptor; the app drops unknown
46
+ obligation keys and never shows unknown artifact keys), the score derivation —
47
+ is checked in the assembler, which reports **all** problems of a call at once
48
+ with the allowed values in the message.
49
+
50
+ Errors the SDK raises before a handler runs (`Input validation error: …`) carry
51
+ no `composerVersion` — that is normal. A *successful* result without it means an
52
+ old build is answering (see next section).
53
+
54
+ ### Stale instances (reinstall is not enough — quit the app)
55
+
56
+ Claude Desktop runs an extension in **two** places: a chat-UI instance, which
57
+ every reinstall restarts, and a session-facing instance
58
+ (`LocalMcpServerManager` in Desktop's `main.log`) that serves Claude Code,
59
+ Cowork and remote claude.ai chats reaching the device. The session-facing
60
+ instance is started once at app launch and is only replaced on a **full app
61
+ quit** — reinstalling or disabling/enabling the extension leaves it running
62
+ the old code. Observed on 2026-08-18: five reinstalls, the chat-UI copy was
63
+ current every time, and every session still got the original build.
64
+
65
+ Tell: a successful tool result without `composerVersion`, or
66
+ `composer_version` missing from the tool list. Fix: install the new `.mcpb`,
67
+ then **quit Claude Desktop completely** (tray icon → Quit — closing the window
68
+ is not enough), reopen, and check with `composer_version`.
69
+
70
+ ### One source for the domain
71
+
72
+ The Composer imports the app's own domain leaf, `@workspace/initiative-model`
73
+ (types and value lists incl. the AI-Act vocabularies, the score derivation, the
74
+ portfolio-mode wording overlays, the backup-format version) — the same package
75
+ the web app renders and validates with — and derives its enum lists from the
76
+ generated API contract. The only hand-listed part is the 30 sub-dimension keys
77
+ with the app's base wording; `catalog-drift.test.ts` pins them to the
78
+ contract in both directions. `server.test.ts` drives the real server through
79
+ the real SDK client over an in-memory transport, so what is asserted is what a
80
+ client sees.
81
+
82
+ ## Install for users
83
+
84
+ ### Claude Desktop — the extension (recommended, no Node needed)
85
+
86
+ Download **`bicon-composer.mcpb`** from the BICon app (Import/Export → *Set
87
+ up initiatives with an AI assistant*, or directly at
88
+ `https://www.bicon.digital/downloads/bicon-composer.mcpb`) and open it —
89
+ double-click, or Claude Desktop → Settings → Extensions → Install. Claude
90
+ Desktop runs the server on its own built-in Node runtime, so there is nothing
91
+ else to install and no configuration file to edit. Then **quit Claude Desktop
92
+ completely and reopen** (see *Stale instances*), start a **new chat** and ask:
93
+ *"Use the BICon Initiative Composer to help me set up a new initiative."*
94
+
95
+ Why the extension is primary: current Claude Desktop builds manage local MCP
96
+ servers as Desktop Extensions and treat `claude_desktop_config.json` as their
97
+ own preferences store — a hand-pasted `mcpServers` block there is silently
98
+ overwritten. There is no supported config-file route for Claude Desktop.
99
+
100
+ ### Other MCP clients — the npm package
101
+
102
+ `@bicon/mcp-composer` on npm is a single self-contained bundle whose only
103
+ runtime dependency is the MCP SDK. Any MCP-capable client with Node ≥ 20 can
104
+ run it; for a client that reads a `mcpServers` config, add this and restart
105
+ the client:
41
106
 
42
107
  ```json
43
108
  {
44
109
  "mcpServers": {
45
110
  "bicon-composer": {
46
111
  "command": "npx",
47
- "args": ["-y", "@bicon/mcp-composer"]
112
+ "args": ["-y", "@bicon/mcp-composer@latest"]
48
113
  }
49
114
  }
50
115
  }
51
116
  ```
52
117
 
53
- That's the whole install. `npx -y` fetches (and caches) the published version;
54
- no repository, no terminal work.
118
+ `@latest` matters: an unpinned `npx` spec keeps serving whatever it cached
119
+ first. Check what you got with the `composer_version` tool — the registry
120
+ version and the extension version are released together (see *Publishing*);
121
+ if npm is behind, use the extension.
122
+
123
+ **Prerequisite:** Node.js ≥ 20 on the **same operating system as the client**.
124
+ On Windows with Node only inside WSL, launch the server *through* WSL:
125
+ `"command": "wsl.exe", "args": ["-d", "Ubuntu", "--", "/path/to/npx", "-y",
126
+ "@bicon/mcp-composer@latest"]` (replace `/path/to/npx` with the output of
127
+ `which npx` in WSL). Restart the client afterwards.
55
128
 
56
129
  ## Build & run from source (contributors)
57
130
 
58
131
  ```bash
59
- pnpm --filter @bicon/mcp-composer run build # → dist/index.mjs (single ESM bundle)
60
- pnpm --filter @bicon/mcp-composer run test # vitest
61
- node lib/integrations/mcp/dist/index.mjs # stdio server (used by the client, not by hand)
132
+ pnpm --filter @bicon/mcp-composer run build # → dist/index.mjs (npm bundle) + dist/mcpb/composer-<v>.mjs (extension bundle)
133
+ pnpm --filter @bicon/mcp-composer run test # vitest, incl. the SDK-boundary suite (builds the bundles itself)
134
+ pnpm --filter @bicon/mcp-composer run build:mcpb # → dist/bicon-composer.mcpb, copied to the web app's public/downloads
135
+ node lib/integrations/mcp/dist/index.mjs # stdio server (used by a client, not by hand)
62
136
  ```
63
137
 
64
- Point Claude Desktop at the local build with the **absolute path**:
65
-
66
- ```json
67
- {
68
- "mcpServers": {
69
- "bicon-composer": {
70
- "command": "node",
71
- "args": ["/ABSOLUTE/PATH/TO/lib/integrations/mcp/dist/index.mjs"]
72
- }
73
- }
74
- }
75
- ```
76
-
77
- On Windows with the repo in WSL, run the server **inside WSL** so it sees the
78
- Linux `node`:
79
-
80
- ```json
81
- {
82
- "mcpServers": {
83
- "bicon-composer": {
84
- "command": "wsl.exe",
85
- "args": ["-d", "Ubuntu", "--", "/home/<user>/.nvm/versions/node/<version>/bin/node",
86
- "/home/<user>/projects/ai-portfolio-steering/lib/integrations/mcp/dist/index.mjs"]
87
- }
88
- }
89
- }
90
- ```
91
-
92
- Restart Claude Desktop; the tools appear under the tools menu.
138
+ For a client that reads a `mcpServers` config, point it at the local build
139
+ with an absolute path (`"command": "node", "args": ["/ABSOLUTE/PATH/TO/lib/integrations/mcp/dist/index.mjs"]`;
140
+ on Windows with the repo in WSL, run through `wsl.exe` with the WSL `node`).
141
+ For Claude Desktop, build and install the extension instead.
142
+
143
+ `build:mcpb` stages the manifest (version, entry point and launch args written
144
+ from `package.json` — the checked-in `mcpb/manifest.json` carries
145
+ placeholders), adds the single self-contained bundle, and — before zipping —
146
+ boots the staged server and drives it through the protocol: `initialize`
147
+ (version), `tools/list` (four tools, no `$ref`), `composer_version`,
148
+ `resources/list`, and an `assemble_initiative` call with an unknown AI-Act key
149
+ that must be rejected by name. It then copies the `.mcpb` to
150
+ `artifacts/bicon-portfolio/public/downloads/` and writes
151
+ `src/lib/composer-extension.json` (version + path), which the Import/Export
152
+ card imports. Requires `python3` for the zip container.
93
153
 
94
154
  ## Using it (the interview → import flow)
95
155
 
96
156
  1. Ask Claude: *"Help me set up a new initiative in BICon."* It reads
97
157
  `initiative://schema` and interviews you — metadata first, then the 30
98
- sub-dimensions with the app's own help text, then a confidence per dimension.
99
- 2. Claude calls `assemble_initiative` and shows you the **derived scores** as a
100
- sanity check (fix and re-run if anything looks off).
101
- 3. Claude calls `export_initiative_file` → save the returned JSON under the
102
- suggested filename (`initiative-<name>-<date>.json`).
103
- 4. In the app (signed in to the target organisation): **Import/Export →
104
- Single initiative** card → drop the file → the preview should show
105
- **0 warnings** → **Add as new** → **Confirm**.
158
+ sub-dimensions with the app's own help text (ask which portfolio mode you
159
+ work in; digital and innovation portfolios use different wording for some
160
+ of them), then a confidence per dimension.
161
+ 2. Claude calls `assemble_initiative` and shows you the **derived scores** and
162
+ any warnings as a sanity check (fix and re-run if anything looks off).
163
+ 3. Claude calls `export_initiative_file` with the same spec → save the returned
164
+ JSON under the suggested filename (`initiative-<name>-<date>.json`).
165
+ 4. In the app (signed in to the target organisation): if the initiative carries
166
+ EU-AI-Act data, make sure the portfolio is in **AI mode** (the app strips
167
+ AI-Act fields on import when it is not — the file's `sourceMode` is
168
+ informational and cannot override that). Then **Import/Export → Single
169
+ initiative** card → drop the file → the preview should show **0 warnings**
170
+ → **Add as new** → **Confirm**.
106
171
  5. The initiative appears in the Inventory with exactly the scores Claude
107
172
  reported.
108
173
 
109
- `sourceMode` (default `ai`) must match the target portfolio's mode, otherwise the
110
- importer strips the AI-Act fields.
111
-
112
174
  ## Publishing (maintainers)
113
175
 
114
- The bundle inlines `zod` and `@workspace/api-zod` (a workspace-only
115
- devDependency the registry cannot resolve), so what ships is
116
- `dist/index.mjs` + this README with `@modelcontextprotocol/sdk` as the sole
117
- runtime dependency — `publish-shape.test.ts` guards exactly that. Publish under
118
- the BICon npm account (business identity, 2FA on):
176
+ Release = extension + npm together, from one version:
119
177
 
120
178
  ```bash
121
179
  cd lib/integrations/mcp
122
- pnpm run pack:check # builds, then `npm pack --dry-run` — inspect the file list
123
- npm login # once, as the BICon npm account
124
- npm version patch|minor # bumps package.json version + creates a git tag
125
- npm publish # prepack runs the build; publishConfig.access is public
180
+ npm version patch|minor # bumps package.json — the ONLY place the version is written
181
+ pnpm run test # incl. the SDK-boundary suite
182
+ pnpm run build:mcpb # bundles, ship-gate smoke, copies the .mcpb + version JSON into the web app
183
+ npm login # once, as the BICon npm account (business identity, 2FA on)
184
+ npm publish # prepack builds; publishConfig.access is public
126
185
  ```
127
186
 
128
- Then verify from a clean machine: `npx -y @bicon/mcp-composer` should start
129
- (it waits for stdio input; Ctrl-C to exit).
187
+ Then commit (the `.mcpb` and `composer-extension.json` are part of the
188
+ release commit) and verify from a clean machine:
189
+ `npx -y @bicon/mcp-composer@latest` starts and `composer_version` reports the
190
+ new version. The bundle inlines `zod`, `@workspace/api-zod` and
191
+ `@workspace/initiative-model` (workspace-only packages the registry cannot
192
+ resolve), so what ships is `dist/index.mjs` + this README with
193
+ `@modelcontextprotocol/sdk` as the sole runtime dependency —
194
+ `publish-shape.test.ts` guards exactly that.
130
195
 
131
196
  ## Not in scope (Phase 2)
132
197