Releases: getmcpm/cli
v0.3.2 — Cross-platform paths and security hardening
What's fixed
Cross-platform config paths (TODO #4)
Cursor and Windsurf store MCP configs in home-relative directories on all platforms — including Windows. The previous code incorrectly routed them through `%APPDATA%`, causing silent detection failures for Windows users with Cursor or Windsurf installed.
| Client | macOS | Linux | Windows (before) | Windows (now) |
|---|---|---|---|---|
| Claude Desktop | `~/Library/Application Support/Claude/` | `~/.config/Claude/` | `%APPDATA%\Claude\` | `%APPDATA%\Claude\` ✓ |
| Cursor | `~/.cursor/` | `~/.cursor/` | `%APPDATA%\.cursor\` ✗ | `~/.cursor/` ✓ |
| VS Code | `~/Library/Application Support/Code/User/` | `~/.config/Code/User/` | `%APPDATA%\Code\User\` | `%APPDATA%\Code\User\` ✓ |
| Windsurf | `~/.codeium/windsurf/` | `~/.codeium/windsurf/` | `%APPDATA%\.codeium\windsurf\` ✗ | `~/.codeium/windsurf/` ✓ |
Security hardening
- APPDATA traversal guard: `%APPDATA%` is now validated as an absolute Windows path via `path.win32.isAbsolute()` before use. Relative or traversal values (e.g. `../../etc`) fall back to homedir. Regression test added.
- Consistent clientId validation: `mcpm install --client ` now validates the client name against the known list before casting, matching the pattern used in other commands. Unknown client names fail fast with a clear error listing valid values.
Tests
822 tests passing.
v0.3.1 — Bug fixes for stack files
Bug fixes
Two bugs found during end-to-end testing of the v0.3.0 stack files feature:
Fixed: mcpm lock failing with `latest` version alias
mcpm export generates version: latest for servers without a pinned version. mcpm lock then couldn't resolve it because semver.valid('latest') returns null, causing "No versions available" errors.
The fix: resolveVersion() now handles "latest" as a first-class alias that returns the highest semver version from the available list.
Fixed: mcpm remove crashing with "Unexpected end of JSON input"
When a client config file was 0 bytes (e.g., VS Code creates an empty mcp.json on first run), BaseAdapter.readRaw() called JSON.parse("") which throws. The fix treats empty/whitespace-only files the same as missing files, returning {}.
Tests
821 tests passing. Two regression test cases added for each fix.
v0.3.0 — Stack Files (Compose for MCP)
Stack Files — docker-compose for MCP servers
Declare your project's MCP servers in mcpm.yaml, lock versions with trust snapshots, and let every team member replicate the setup with one command.
mcpm export > mcpm.yaml # dump current setup
mcpm lock # resolve versions + trust snapshot
mcpm up # install everything
mcpm diff # compare installed vs declaredNew Commands
| Command | Description |
|---|---|
mcpm export |
Export installed servers as an mcpm.yaml stack file |
mcpm lock |
Resolve semver ranges, run trust assessment, write mcpm-lock.yaml |
mcpm up |
Batch install from mcpm.yaml with trust policy enforcement |
mcpm diff |
Compare installed state vs mcpm.yaml + lock file |
Trust Policy
Stack files include a policy: block that gates mcpm up. If a server's trust score drops below the threshold, installation is blocked.
version: "1"
policy:
minTrustScore: 60
blockOnScoreDrop: true
servers:
io.github.domdomegg/filesystem-mcp:
version: "^1.0.0"Key Features
- Semver resolution — caret (
^1.0.0) and tilde (~1.2.0) ranges resolved against the MCP registry - Trust snapshots — lock file captures trust score at lock time;
mcpm updetects score drops using normalized percentages (works even when MCP-Scan availability differs across machines) - Parallel resolution — registry fetches and trust scans run concurrently per server
- Per-server error isolation — one server failing doesn't block others
- CI mode —
mcpm up --ciexits nonzero on trust violations or missing env vars - Profile support —
mcpm up --profile devinstalls only servers tagged for that profile - Strict mode —
mcpm up --strict --yesremoves servers not in mcpm.yaml - Env var resolution — process.env → .env file → default → interactive prompt
- URL servers — direct HTTP remotes supported (Cursor only, warns for other clients)
- MCP tool —
mcpm_upexposed viamcpm servefor AI agent access
Security
- Path traversal protection on MCP tool input
- Prototype poisoning protection in .env parser
- Single backup snapshot before batch writes
- Secrets never exported in mcpm.yaml (keys only, values omitted)
- All file writes use mode 0o600
Stats
- 816 tests, 80%+ line coverage
- 8 commits since v0.2.2
Full Changelog: v0.2.2...v0.3.0
v0.2.2 — security hardening (CSO audit fixes)
Security fixes
Findings from a full CSO audit, all resolved:
-
Health-check command allowlist (HIGH) —
spawn()in health checks now validates the command against an allowlist (npx,uvx,docker,node,python) before execution. Prevents RCE if a config file was tampered with after install. -
MCP tool input constraints (MEDIUM) — Added Zod bounds on all MCP server tool inputs:
querymax 200 chars,descriptionmax 1000 chars,limitmax 100,minTrustScorerange 0-100 on all schemas. Prevents oversized payloads and trust-gate bypass via negative values. -
Client ID validation in MCP server (MEDIUM) —
resolveClientsnow validates--clientagainstCLIENT_IDSallowlist before theas ClientIdcast, matching the pattern already used in CLI commands. -
Doctor command allowlist (MEDIUM) —
execCheckDefaultnow restricts which commands can be passed towhich/where. -
Warning listener fix (MEDIUM) — Removed
removeAllListeners("warning")which was suppressing Node.js security warnings. Now uses an additive filter for the cli-table3 noise only. -
Always validate server name (LOW) —
handleInstallnow validates the server name unconditionally, even when called fromhandleSetupwith pre-resolved entries.
Install / upgrade
npm install -g @getmcpm/cli@0.2.2Full changelog: v0.2.1...v0.2.2
v0.2.1 — version display fix
Fix
mcpm --versionnow shows the correct version. Previously the version was hardcoded in source. Now it's injected frompackage.jsonat build time via tsupdefine, so CI's tag-based version always matches what the user sees.
Install / upgrade
npm install -g @getmcpm/cli@0.2.1For the full feature release notes (disable/enable, aliases, completions), see v0.2.0.
v0.2.0 — disable/enable, aliases, and shell completions
What's new
New commands
-
mcpm disable <name>— Disable an MCP server across all (or a specific) client without removing it from config. The server stays in your config file but won't be loaded by the client. -
mcpm enable <name>— Re-enable a previously disabled server. -
mcpm alias— Create short aliases for long server names.mcpm alias fs io.github.domdomegg/filesystem-mcplets you usefsin future commands. Stored in~/.mcpm/aliases.json. -
mcpm completions <shell>— Generate tab-completion scripts for bash, zsh, and fish. Pipe into your shell config for instant command/option completion.
Improvements
-
mcpm listnow shows server status — Each server displays asactiveordisabledin a new Status column, so you can see at a glance what's running. -
--clientflag on disable/enable — Target a specific client (--client cursor) instead of toggling across all detected clients.
Security hardening
- MCP server tool path allowlist and health check environment sandboxing (#1)
- Client ID validation before type casts (rejects unknown
--clientvalues with clear error) - Strict alias name validation: alphanumeric + hyphens only, max 64 chars, blocks
__proto__/constructor/prototype --removepath validates alias names before filesystem operations
Internal
- Shared
toggle.tshandler eliminates duplication between disable/enable (single-pass config read per client) - 739 tests (up from 687), all passing
- Updated docs: README, ARCHITECTURE.md, CLAUDE.md
Install / upgrade
npm install -g @getmcpm/cli@0.2.0Full changelog: v0.1.3...v0.2.0
v0.1.3
Full Changelog: v0.1.2...v0.1.3
v0.1.2
Full Changelog: v0.1.1...v0.1.2