@eventmodelers/cli 1.0.2 → 1.0.4
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/cli.js +53 -0
- package/package.json +1 -1
- package/shared/skills/connect/SKILL.md +10 -4
package/cli.js
CHANGED
|
@@ -932,6 +932,7 @@ async function installStack(stackKey, stackCfg, options = {}) {
|
|
|
932
932
|
// even without a token yet — the file only ever holds the env-var
|
|
933
933
|
// placeholder, never the literal secret (see connect/SKILL.md's Security notes).
|
|
934
934
|
ensureMcpRegistered(targetDir, config.baseUrl || DEFAULT_BASE_URL);
|
|
935
|
+
ensureEnvToken(targetDir, config.token);
|
|
935
936
|
|
|
936
937
|
// --- 6. Install manifest (drives precise `uninstall` later) ---
|
|
937
938
|
// Only the footprint listed here is ever removed by `uninstall` — the root
|
|
@@ -1155,6 +1156,57 @@ function ensureMcpRegistered(projectDir, baseUrl) {
|
|
|
1155
1156
|
writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
|
|
1156
1157
|
}
|
|
1157
1158
|
|
|
1159
|
+
// Companion to ensureMcpRegistered: that function deliberately never writes the
|
|
1160
|
+
// token itself, on the assumption the caller sets EVENTMODELERS_TOKEN in whatever
|
|
1161
|
+
// process spawns `claude` (true for `run --modeling`'s own spawn). It is NOT true
|
|
1162
|
+
// for an interactive session opened directly in the project right after
|
|
1163
|
+
// `init`/`init-config` — that `claude` process inherits the user's shell env,
|
|
1164
|
+
// which never had a reason to already have this var set.
|
|
1165
|
+
//
|
|
1166
|
+
// A plain `.env` file does NOT fix this — Claude Code never sources one; per its
|
|
1167
|
+
// own docs, an unresolved `.mcp.json` placeholder is left as the literal
|
|
1168
|
+
// `${EVENTMODELERS_TOKEN}` text, which fails auth and falls back to an OAuth
|
|
1169
|
+
// flow the eventmodelers server can't actually satisfy for this client. The
|
|
1170
|
+
// only things Claude Code itself resolves `.mcp.json` placeholders against are
|
|
1171
|
+
// the inherited shell env and its own settings files' `env` block. `.claude/
|
|
1172
|
+
// settings.local.json` is the documented per-user, gitignored-by-convention
|
|
1173
|
+
// scope for exactly this — same idea as `.eventmodelers/config.json` already
|
|
1174
|
+
// holding the raw token, just in the one file Claude Code's own process env
|
|
1175
|
+
// actually consults before expanding `.mcp.json`.
|
|
1176
|
+
function ensureEnvToken(targetDir, token) {
|
|
1177
|
+
if (!token) return;
|
|
1178
|
+
const claudeDir = join(targetDir, '.claude');
|
|
1179
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
1180
|
+
const settingsPath = join(claudeDir, 'settings.local.json');
|
|
1181
|
+
|
|
1182
|
+
let settings = {};
|
|
1183
|
+
if (existsSync(settingsPath)) {
|
|
1184
|
+
try {
|
|
1185
|
+
settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
1186
|
+
} catch {
|
|
1187
|
+
settings = {};
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
settings.env = settings.env || {};
|
|
1192
|
+
settings.env.EVENTMODELERS_TOKEN = token;
|
|
1193
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
1194
|
+
|
|
1195
|
+
// settings.local.json is gitignored by Claude Code's own convention, but make
|
|
1196
|
+
// sure nothing here relies on that silently — it now holds a live secret.
|
|
1197
|
+
const gitignorePath = join(targetDir, '.gitignore');
|
|
1198
|
+
const entry = '.claude/settings.local.json';
|
|
1199
|
+
if (existsSync(gitignorePath)) {
|
|
1200
|
+
const content = readFileSync(gitignorePath, 'utf-8');
|
|
1201
|
+
if (!content.split('\n').map((l) => l.trim()).includes(entry)) {
|
|
1202
|
+
appendFileSync(gitignorePath, `${content === '' || content.endsWith('\n') ? '' : '\n'}${entry}\n`);
|
|
1203
|
+
}
|
|
1204
|
+
} else {
|
|
1205
|
+
writeFileSync(gitignorePath, `${entry}\n`);
|
|
1206
|
+
}
|
|
1207
|
+
console.log(' ✓ Wrote EVENTMODELERS_TOKEN to .claude/settings.local.json (gitignored)');
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1158
1210
|
// `run --modeling`: modeling-kit's one and only runtime mode — there is no
|
|
1159
1211
|
// cold-spawn/tasks.json loop for this kit (that's a build-kit concept; see the
|
|
1160
1212
|
// `run` command's build-kit-vs-modeling-kit gate above). It keeps ONE Claude
|
|
@@ -1650,6 +1702,7 @@ credentialFlags(program
|
|
|
1650
1702
|
// stale MCP registration pointing at the wrong host is worse than none
|
|
1651
1703
|
// (see the beta-api protected-resource-metadata incident this fixed).
|
|
1652
1704
|
ensureMcpRegistered(targetDir, cfg.baseUrl || DEFAULT_BASE_URL);
|
|
1705
|
+
ensureEnvToken(targetDir, cfg.token);
|
|
1653
1706
|
}
|
|
1654
1707
|
});
|
|
1655
1708
|
|
package/package.json
CHANGED
|
@@ -150,7 +150,7 @@ Always run this step (not only when Step 3 ran) — it's idempotent and safe to
|
|
|
150
150
|
|
|
151
151
|
The eventmodelers backend exposes the same board capabilities as an MCP server at `<BASE_URL>/mcp`, authenticated with the same `TOKEN` via an `x-token` header. Register it in the project's `.mcp.json` so Claude Code (or any other MCP-aware host) can connect and expose tools as `mcp__eventmodelers__<tool_name>`.
|
|
152
152
|
|
|
153
|
-
**Do not put the raw token in `.mcp.json`** — that file is typically committed to share server config with the team. Instead reference an environment variable and
|
|
153
|
+
**Do not put the raw token in `.mcp.json`** — that file is typically committed to share server config with the team. Instead reference an environment variable and set the actual secret in `.claude/settings.local.json`'s `env` block:
|
|
154
154
|
|
|
155
155
|
1. Read the existing `.mcp.json` at the project root if present (it may already list other MCP servers, e.g. a browser-automation server used by `discover-storyboard` — merge into `mcpServers`, never replace the whole file). If absent, start from `{"mcpServers": {}}`.
|
|
156
156
|
2. Add or update the `eventmodelers` entry:
|
|
@@ -165,8 +165,14 @@ The eventmodelers backend exposes the same board capabilities as an MCP server a
|
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
167
|
```
|
|
168
|
-
3.
|
|
169
|
-
|
|
168
|
+
3. Read the existing `.claude/settings.local.json` if present and merge in — never clobber `permissions`/`enabledMcpjsonServers` or anything else already there. Ensure it has `EVENTMODELERS_TOKEN` set under `env` (create the file with just this key if it doesn't exist yet):
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"env": { "EVENTMODELERS_TOKEN": "<TOKEN>" }
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
A plain `.env` file does **not** work here — Claude Code never sources one, so a `${EVENTMODELERS_TOKEN}` placeholder in `.mcp.json` would be left unexpanded (sent as the literal `${EVENTMODELERS_TOKEN}` text), which fails auth and pushes the client into an OAuth flow the eventmodelers server can't satisfy for this client. `.claude/settings.local.json`'s `env` block — alongside the inherited shell environment — is the only thing Claude Code actually resolves `.mcp.json` placeholders against.
|
|
175
|
+
4. Ensure `.claude/settings.local.json` is listed in `.gitignore` (same check-then-append pattern as Step 3 uses for `.eventmodelers/config.json`) — it now holds the same secret and must never be committed. (Gitignored by Claude Code's own convention already, but don't rely on that silently.)
|
|
170
176
|
|
|
171
177
|
MCP tools only become visible to the current agent session after the host (re)connects to the server — a brand-new `.mcp.json` entry written mid-session may need the user to approve the new server or reconnect (e.g. Claude Code's `/mcp` command) before `mcp__eventmodelers__*` tools appear in the tool list. That's expected and not an error: tell the user once, then let every other skill fall back to curl automatically until the tools show up.
|
|
172
178
|
|
|
@@ -226,7 +232,7 @@ The `token` field is a secret. It is never logged or shown after initial confirm
|
|
|
226
232
|
|
|
227
233
|
## Security notes
|
|
228
234
|
|
|
229
|
-
- The config file (`.eventmodelers/config.json`) and
|
|
235
|
+
- The config file (`.eventmodelers/config.json`) and `.claude/settings.local.json` (holding `EVENTMODELERS_TOKEN` under `env`) are both workspace-local and gitignored — never commit either.
|
|
230
236
|
- `.mcp.json` itself is safe to commit — it only ever contains the `${EVENTMODELERS_TOKEN}` placeholder, never the literal token.
|
|
231
237
|
- The token grants write access to all boards in its organization — treat it like a password.
|
|
232
238
|
- If a skill receives a `401`/`403` (curl) or an access-denied tool error (MCP) mid-session, re-invoke this skill to refresh the config before retrying.
|