mcp-pacemaker 2.0.2 → 2.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.
Files changed (90) hide show
  1. package/CHANGELOG.md +171 -1
  2. package/CONTRIBUTING.md +46 -13
  3. package/README.md +109 -524
  4. package/THIRD_PARTY_NOTICES.txt +1 -28
  5. package/autostart/windows/account-task.ps1 +167 -0
  6. package/autostart/windows/inspect-task.ps1 +42 -0
  7. package/autostart/windows/inspect-worker-process-sessions.ps1 +155 -0
  8. package/autostart/windows/legacy-access.ps1 +359 -0
  9. package/autostart/windows/legacy-task.ps1 +301 -0
  10. package/autostart/windows/register-task.ps1 +11 -2
  11. package/bin/account-task-adapter.mjs +47 -0
  12. package/bin/account-upgrade-controller.mjs +198 -0
  13. package/bin/account-upgrade-worker.mjs +141 -0
  14. package/bin/account-worker-session.mjs +215 -0
  15. package/bin/cli-dispatch.mjs +154 -0
  16. package/bin/cli-main.mjs +1063 -0
  17. package/bin/cli-selection.mjs +43 -0
  18. package/bin/cli.mjs +7 -876
  19. package/bin/dependency-lock.json +642 -0
  20. package/bin/legacy-1.3.json +32 -0
  21. package/bin/legacy-access.mjs +73 -0
  22. package/bin/legacy-installation.mjs +273 -0
  23. package/bin/legacy-task.mjs +76 -0
  24. package/bin/legacy-upgrade.mjs +527 -0
  25. package/bin/managed-runtime.mjs +170 -0
  26. package/bin/managed-state.mjs +257 -0
  27. package/bin/managed-upgrade.mjs +581 -0
  28. package/bin/mcp-bridge.mjs +150 -4
  29. package/bin/pooling-batches.mjs +13 -0
  30. package/bin/pooling-writer.mjs +4 -0
  31. package/bin/prewarm.mjs +59 -25
  32. package/bin/runtime-context.mjs +100 -0
  33. package/bin/service-control.mjs +32 -4
  34. package/bin/stable-launcher.mjs +54 -0
  35. package/bin/task-only-controller.mjs +226 -0
  36. package/bin/task-scope.mjs +65 -0
  37. package/bin/task-transaction-protocol.mjs +173 -0
  38. package/bin/top.mjs +22 -10
  39. package/bin/update-check.mjs +13 -2
  40. package/bin/upgrade-autostart.mjs +47 -0
  41. package/bin/upgrade-capability.json +9 -0
  42. package/bin/upgrade-dependencies.mjs +183 -0
  43. package/bin/upgrade-package.mjs +205 -0
  44. package/bin/windows-legacy/LegacyProcessBroker.build.json +42 -0
  45. package/bin/windows-legacy/LegacyProcessBroker.exe +0 -0
  46. package/bin/windows-legacy/src/AssemblyInfo.cs +8 -0
  47. package/bin/windows-legacy/src/LegacyNative.cs +832 -0
  48. package/bin/windows-legacy/src/LegacyProcessBroker.cs +961 -0
  49. package/bin/windows-legacy-process.mjs +248 -0
  50. package/bin/windows-lifetime/ProcessLifetimeHelper.build.json +38 -0
  51. package/bin/windows-lifetime/ProcessLifetimeHelper.exe +0 -0
  52. package/bin/windows-lifetime/src/AssemblyInfo.cs +8 -0
  53. package/bin/windows-lifetime/src/ProcessLifetimeHelper.cs +468 -0
  54. package/bin/windows-process-lifetime.mjs +218 -0
  55. package/bin/windows-task-channel/TaskChannelGuard.build.json +45 -0
  56. package/bin/windows-task-channel/TaskChannelGuard.exe +0 -0
  57. package/bin/windows-task-channel/src/AssemblyInfo.cs +8 -0
  58. package/bin/windows-task-channel/src/ChannelCliContext.cs +210 -0
  59. package/bin/windows-task-channel/src/ChannelFiles.cs +231 -0
  60. package/bin/windows-task-channel/src/ChannelNative.cs +477 -0
  61. package/bin/windows-task-channel/src/ChannelSession.cs +203 -0
  62. package/bin/windows-task-channel/src/TaskChannelGuard.cs +686 -0
  63. package/bin/windows-task-channel.mjs +335 -0
  64. package/docs/account-upgrades.md +218 -0
  65. package/docs/compatibility.md +39 -0
  66. package/docs/configuration.md +146 -0
  67. package/docs/dashboards.md +125 -0
  68. package/docs/execution-context.md +119 -0
  69. package/docs/http-api.md +47 -0
  70. package/docs/install.md +52 -0
  71. package/docs/operations.md +99 -0
  72. package/docs/upgrades.md +324 -0
  73. package/package.json +19 -5
  74. package/supervisor/supervise.mjs +226 -40
  75. package/tools/account-upgrade/qualify-two-account.ps1 +66 -0
  76. package/tools/windows-legacy/README.md +251 -0
  77. package/tools/windows-legacy/build.ps1 +122 -0
  78. package/tools/windows-legacy/inventory.mjs +92 -0
  79. package/tools/windows-process-lifetime/README.md +119 -0
  80. package/tools/windows-process-lifetime/build.ps1 +122 -0
  81. package/tools/windows-process-lifetime/inventory.mjs +86 -0
  82. package/tools/windows-task-channel/README.md +329 -0
  83. package/tools/windows-task-channel/build.ps1 +107 -0
  84. package/tools/windows-task-channel/inventory.mjs +117 -0
  85. package/ui/dist/THIRD_PARTY_NOTICES.txt +1 -28
  86. package/ui/dist/assets/{index-CgPruWYi.js → index-CcwMo2sI.js} +1 -1
  87. package/ui/dist/assets/index-PVcuDNrN.css +1 -0
  88. package/ui/dist/index.html +2 -2
  89. package/ui/dist/third-party-manifest.json +37 -25
  90. package/ui/dist/assets/index-CaLPg0c-.css +0 -1
package/README.md CHANGED
@@ -1,43 +1,66 @@
1
1
  # mcp-pacemaker
2
2
 
3
- **A local process supervisor and transport bridge for your MCP servers.** Manage server
4
- lifetime outside your editor or CLI, with opt-in pre-warming and compatible session sharing.
5
- The long-running bridge has no third-party runtime dependencies; the setup CLI and dashboards
6
- have their own dependencies.
3
+ **Keep your MCP servers running outside the editor or CLI.** One long-lived local bridge runs your MCP servers and every editor and agent CLI connects to it, so a CLI exiting no longer kills them.
4
+
5
+ ![Demo: two isolated launches, one shared launch, none added on reconnect](docs/media/demo-2.1.0.gif)
6
+
7
+ ```bash
8
+ npm install -g mcp-pacemaker # Node 22 or 24, run as a normal user
9
+ mcp-pacemaker init # imports your servers, asks before rewiring any host
10
+ ```
7
11
 
8
12
  [Install from npm](https://www.npmjs.com/package/mcp-pacemaker) ·
9
13
  [Report a problem](https://github.com/girishkvs/mcp-pacemaker/issues) ·
10
- [Release notes](https://github.com/girishkvs/mcp-pacemaker/releases)
14
+ [Release notes](https://github.com/girishkvs/mcp-pacemaker/releases) ·
15
+ [Demo and design write-up](https://girishkonda.com/projects/mcp-pacemaker/)
16
+
17
+ > This README describes **2.1.1**.
18
+ > See the [release changes](CHANGELOG.md).
19
+
20
+ ## What it does
11
21
 
12
22
  MCP hosts — editors (VS Code, Cursor, Claude Desktop) **and** CLIs (Claude Code, Copilot CLI,
13
23
  Codex, Gemini) — run stdio MCP servers as child processes. When the host restarts, crashes, or
14
- exits (every one-shot CLI run), **those servers die**. `mcp-pacemaker` runs your servers as
15
- children of a small, long-lived bridge and exposes each over the MCP HTTP+SSE / Streamable HTTP
16
- transport. Multiple hosts use one bridge, with an isolated child per session by default.
17
- Opt into pre-warming or reuse one initialized child for compatible stateless tools sessions
18
- with [shared mode](#shared-mode). Wire hosts to one bridge, or give each its own.
19
- A cross-platform supervisor + OS auto-start keep the bridge itself alive across reboots and
20
- sleep/wake, and a pluggable auth layer injects a fresh token per request for HTTP servers.
21
-
22
- After a restart, a returning client can reuse a recorded session ID to re-establish its handshake
23
- against a fresh server. This does not restore arbitrary tool state or preserve TCP connections.
24
- Clients that stop retrying after a dropped connection may still need a reload; socket handoff
25
- is separate planned work.
24
+ exits (every one-shot CLI run), **those servers die**.
25
+
26
+ - **Keeps servers running.** `mcp-pacemaker` runs your servers as children of a small,
27
+ long-lived bridge and exposes each over the MCP HTTP+SSE / Streamable HTTP transport.
28
+ - **Shares one bridge.** Multiple hosts use one bridge, with an isolated child per session by
29
+ default. Opt into pre-warming or reuse one initialized child for compatible stateless tools
30
+ sessions with [shared mode](docs/configuration.md#shared-mode). Wire hosts to one bridge, or
31
+ give each its own.
32
+ - **Survives reboots and token expiry.** A cross-platform supervisor + OS auto-start keep the
33
+ bridge itself alive across reboots and sleep/wake, and a pluggable auth layer injects a fresh
34
+ token per request for HTTP servers.
35
+ - **Reconnects returning clients.** After a restart, a returning client can reuse a recorded
36
+ session ID to re-establish its handshake against a fresh server. This does not restore
37
+ arbitrary tool state or preserve TCP connections. Clients that stop retrying after a dropped
38
+ connection may still need a reload; socket handoff is separate planned work.
39
+ - **Shows what is running.** `status`, `top` and a web dashboard show whether each server is up
40
+ and which clients use it. See [dashboards](docs/dashboards.md).
26
41
 
27
42
  ## Quick start
28
43
 
29
- Install **mcp-pacemaker 2.0.2** from npm. Use a maintained **Node.js 22 or 24**
44
+ Install **mcp-pacemaker 2.1.1** from npm. Use a maintained **Node.js 22 or 24**
30
45
  release; Windows also needs PowerShell 7 and Windows Script Host.
31
- See [installation requirements](#install) before setup.
46
+ See [installation requirements](docs/install.md) before setup.
32
47
 
33
48
  ```bash
34
- npm install -g mcp-pacemaker@2.0.2
49
+ npm view mcp-pacemaker@2.1.1 version
50
+ npm install -g mcp-pacemaker@2.1.1
35
51
  mcp-pacemaker --version
36
52
  ```
37
53
 
38
- The version check prints `2.0.2` without running setup.
54
+ The version check prints `2.1.1` without running setup.
55
+
56
+ > **Run it as an ordinary user.** From 2.1.0 the bridge, supervisor and default upgrades
57
+ > refuse a privileged caller *at startup* — a non-administrator terminal on Windows and a
58
+ > **non-root** session on Linux/macOS, including the default `root` user in most containers.
59
+ > A refused start prints `User-runtime execution refused: …`. There is no override; run as a
60
+ > normal user instead. See the [user-runtime contract](docs/execution-context.md).
61
+
39
62
  Before setup, have a readable JSON host configuration containing server definitions, or
40
- prepare [`~/.mcp-pacemaker/servers.json`](#serversjson). Supported import sources are
63
+ prepare [`~/.mcp-pacemaker/servers.json`](docs/configuration.md#serversjson). Supported import sources are
41
64
  `vscode`, `cursor`, `claude` (Claude Desktop), `copilot-cli` and `gemini`.
42
65
  Codex and Claude Code are wiring destinations, not import sources.
43
66
 
@@ -97,6 +120,19 @@ them in.
97
120
 
98
121
  </details>
99
122
 
123
+ ## Everyday commands
124
+
125
+ | Command | What it does |
126
+ |---|---|
127
+ | `init [--from source] [--client a,b] [--yes]` | Interactive setup: import one source, wire selected hosts, auto-start, launch |
128
+ | `status` | Bridges, wired hosts, servers, and any server currently failing |
129
+ | `top` / `dashboard` | Live terminal UI / web dashboard |
130
+ | `doctor` | Diagnose config, bridge reachability, host wiring |
131
+ | `uninstall` | Stop managed bridges, remove auto-start, restore available host-file `.bak` copies; native entries are not restored |
132
+
133
+ The [command reference](docs/operations.md#command-reference) lists every command, including
134
+ `reload`, `logs`, `prewarm`, `upgrade` and `--instance`.
135
+
100
136
  ## Which process-sharing mode?
101
137
 
102
138
  Sharing a bridge does not automatically share a server process.
@@ -109,20 +145,7 @@ Sharing a bridge does not automatically share a server process.
109
145
 
110
146
  Shared clients must send identical initialization parameters, including `clientInfo`, and
111
147
  empty client capabilities. It is not automatic cross-editor sharing. See
112
- [shared-mode limits](#shared-mode) before enabling it.
113
-
114
- ## Choosing a transport tool
115
-
116
- Documentation checked September 27, 2026; this is a use-case guide, not a feature benchmark.
117
-
118
- | Tool | Consider it when |
119
- |---|---|
120
- | [Supergateway](https://github.com/supercorp-ai/supergateway) | You want command-line conversion between stdio and HTTP/SSE/WebSocket transports |
121
- | [mcp-proxy](https://github.com/sparfenyuk/mcp-proxy) | You want a Python-based adapter between local stdio clients/servers and remote MCP transports |
122
- | **mcp-pacemaker** | You want workstation process supervision, host wiring, auto-start, lifecycle diagnostics and explicit isolation/pooling/sharing policies |
123
-
124
- These projects have overlapping capabilities. Reconnecting to a fresh server is not recovery
125
- of arbitrary application state, and a transport bridge is not a sandbox for untrusted tools.
148
+ [shared-mode limits](docs/configuration.md#shared-mode) before enabling it.
126
149
 
127
150
  ## Supported hosts
128
151
 
@@ -144,531 +167,93 @@ loopback.
144
167
  **Topologies:** wire every host to one shared bridge (default), or give each host its own bridge
145
168
  (`install --client X --port N`) — or any mix. `status`/`doctor` report all bridges + wired hosts.
146
169
 
147
- ## Install
148
-
149
- Use a maintained **Node.js 22 or 24** release. Node 20 remains a compatibility target but is
150
- end-of-life, not a recommended secure runtime. The bridge has no npm runtime dependencies;
151
- the setup CLI and dashboard have their own dependencies.
152
-
153
- Install the released package from [npm](https://www.npmjs.com/package/mcp-pacemaker).
154
- Its repository link should point to
155
- [`girishkvs/mcp-pacemaker`](https://github.com/girishkvs/mcp-pacemaker).
156
- Use an exact version for a repeatable installation:
157
-
158
- ```bash
159
- npm install -g mcp-pacemaker@2.0.2
160
- mcp-pacemaker --version
161
- ```
162
-
163
- The current line uses the `latest` npm channel; the maintenance line uses `legacy` when that
164
- channel has been published. Check the actual registry values before choosing a channel:
170
+ ## Choosing a transport tool
165
171
 
166
- ```bash
167
- npm view mcp-pacemaker dist-tags --json
168
- ```
172
+ Documentation checked September 27, 2026; this is a use-case guide, not a feature benchmark.
169
173
 
170
- GitHub tags and npm publication are separate: a tag does not establish that the same
171
- version or channel is available on npm, or that its package bytes are identical.
172
- `@1` and `@2` are version ranges, not the maintained channels. They can select a version
173
- withdrawn from a channel. `upgrade --self` resolves the installed major's channel and prints
174
- an exact-version command; it never installs or downgrades anything.
174
+ | Tool | Consider it when |
175
+ |---|---|
176
+ | [Supergateway](https://github.com/supercorp-ai/supergateway) | You want command-line conversion between stdio and HTTP/SSE/WebSocket transports |
177
+ | [mcp-proxy](https://github.com/sparfenyuk/mcp-proxy) | You want a Python-based adapter between local stdio clients/servers and remote MCP transports |
178
+ | **mcp-pacemaker** | You want workstation process supervision, host wiring, auto-start, lifecycle diagnostics and explicit isolation/pooling/sharing policies |
175
179
 
176
- Use a durable installation directory for a long-running service. Do not register autostart
177
- from an `npx` cache: that cache may be removed later. Bare CLI invocation can enter the setup
178
- wizard; use `--version` for a read-only installation check.
180
+ These projects have overlapping capabilities. Reconnecting to a fresh server is not recovery
181
+ of arbitrary application state, and a transport bridge is not a sandbox for untrusted tools.
179
182
 
180
- Windows setup also needs PowerShell 7 (`pwsh`) and Windows Script Host for its launcher.
181
- Automatic configuration edits need .NET Framework 4.6.2 or newer. The bundled helper is
182
- unsigned; npm provenance is not Authenticode signing or an application-control allowlist.
183
- Windows ARM64 is not validated.
183
+ ## Upgrades
184
184
 
185
- ### Version compatibility
185
+ > Package installation alone does not upgrade a running backend. Use explicit `upgrade --to`
186
+ > for managed replacement. Bare `upgrade` retains the older host-repair behavior.
186
187
 
187
- This README describes **2.0.x**. For 1.3.x immediate-save behavior, see the
188
- [legacy documentation](https://github.com/girishkvs/mcp-pacemaker/blob/v1.3.1/README.md)
189
- and [support policy](SECURITY.md#supported-versions). Those documents do not establish
190
- that a legacy version is available on npm.
188
+ Managed upgrades need **2.1.0 or newer** and must run as an ordinary user. Start with
189
+ `mcp-pacemaker upgrade --to <exact-version> --plan`, which changes nothing. `--sxs` keeps the
190
+ old instance and starts an isolated new one. Do not overwrite a package directory while its
191
+ supervisor or bridge is running. An upgrade may end open sessions and calls in progress;
192
+ clients reconnect, and no call is retried. It never changes `servers.json` or your client setup.
191
193
 
192
- The historical baselines remain **1.3.0 / 2.0.0**. The earlier **1.3.1 / 2.0.1**
193
- patch-pair evidence is not transferable to a new release. The selected **1.3.1 / 2.0.2**
194
- pair requires fresh exact-byte compatibility and service-replacement gates.
195
- A 2.x client handles legacy immediate saves. A 1.x client cannot write pooling settings to a
196
- 2.x bridge: update the CLI and refresh old dashboard tabs. Before downgrading, settle pending
197
- or interrupted transactions with 2.x. See the [real-version gates](CONTRIBUTING.md#real-version-compatibility-gates)
198
- for exact pairs; only the exact executed pairs are covered.
194
+ The [one-time Windows 1.3 restart migration](docs/upgrades.md#one-time-windows-13-restart-migration)
195
+ restarts **Pacemaker, not Windows**. It stops the 1.3 bridge and the processes it started, so
196
+ open sessions end. Confirm it at the prompt or with `--yes`. Run it from a separate durable
197
+ package; do not overwrite the running 1.3 package first. If 1.3 was set up from an
198
+ administrator terminal, run `mcp-pacemaker upgrade --fix-legacy-access` once from an
199
+ administrator terminal first; see [that section](docs/upgrades.md#13-installs-set-up-from-an-administrator-terminal).
199
200
 
200
- ### Command reference
201
+ See [upgrades and rollback](docs/upgrades.md) for recovery, rollback and side-by-side instances.
201
202
 
202
- | Command | What it does |
203
- |---|---|
204
- | `init [--from source] [--client a,b] [--yes]` | Interactive setup: import one source, wire selected hosts, auto-start, launch |
205
- | `status` | Bridges, wired hosts, servers, and any server currently failing |
206
- | `reload` | Re-read `servers.json` into the running bridge without restarting it |
207
- | `doctor` | Diagnose config, bridge reachability, host wiring |
208
- | `prewarm [--port N] [--json]` | One view of stdio candidates, pools, shared-child state and measured process starts |
209
- | `prewarm --enable <server> [--count N]` | Explicitly enable warm slots; `--disable <server>` turns them off |
210
- | `logs [--follow] [--since 2h] [--server name] [--grep text]` | Read and filter durable logs, including retained rotation |
211
- | `top` / `dashboard` | Live terminal UI / web dashboard |
212
- | `plan --client <host>` | Dry run — show exactly what `install` would change |
213
- | `import --from <source>` | Build `~/.mcp-pacemaker/servers.json` from one supported JSON host config |
214
- | `install --client <host> [--port N]` | Wire one host (its own `--port` gives it its own bridge) |
215
- | `emit --client <host>` | Print the config entries without writing anything |
216
- | `start` / `stop` | Start or stop bridges (`--port` for one, else all) |
217
- | `upgrade [--self]` | Re-wire hosts; `--self` only prints same-major, exact-version installation guidance |
218
- | `update-check [--json]` | Compare the installed version with its maintained npm channel |
219
- | `uninstall` | Stop managed bridges, remove auto-start, restore available host-file `.bak` copies; native entries are not restored |
220
-
221
- > Package installation does not upgrade a running backend. `upgrade` rewires host configuration;
222
- > it does not replace package files, restart an adopted backend, or update its autostart path.
223
-
224
- > On start, pacemaker **probes the port**: it *adopts* an existing pacemaker bridge and *refuses to collide* with a foreign service (the wizard offers another port).
225
-
226
- For a supervisor created by these patch releases, `stop --port N` verifies the matching
227
- installation/configuration identity, waits for shutdown, and holds managed autostart until an
228
- explicit `start --port N`. Normal OS shutdown does not create that hold. Use the matching
229
- installation's CLI. Older or directly launched bridges have no managed stop record and are
230
- refused rather than reported as stopped; disable their OS autostart and verify shutdown first.
231
-
232
- On Linux/macOS the control socket lives beside the configuration, independent of `TMPDIR`.
233
- Its complete path must fit within 103 UTF-8 bytes. `install` and `init` check this before
234
- changing configuration or autostart; use a shorter configuration location rather than
235
- relying on an implicit socket-location fallback.
236
-
237
- Isolated and pooled stdio servers support HTTP+SSE (`/<name>/sse`) and Streamable HTTP
238
- (`/<name>/mcp`). Shared mode requires Streamable HTTP.
203
+ ## Uninstall
239
204
 
240
205
  `install` backs up an existing JSON/TOML host file to `.bak`; repeating it replaces that backup.
241
206
  `uninstall` restores available host-file backups, leaves files without backups as-is, and
242
207
  keeps `servers.json`. Native Claude Code registrations are not backed up or automatically
243
208
  restored; record their original definitions separately and restore them through Claude Code.
244
209
 
245
- ### Replacing or rolling back a running installation
246
-
247
- Do not overwrite a package directory while its supervisor or bridge is running. Workers and
248
- native helpers can load later, and dashboard assets are read from disk: replacement can mix
249
- old and new code even when the original process still reports its old version.
250
-
251
- Identify the selected port, installation directory, configuration directory and OS autostart
252
- entry first. Settle or cancel 2.x batches, recover interrupted transactions with 2.x, and keep
253
- a protected configuration backup. Disable the selected autostart entry and stop its supervisor
254
- and bridge before replacing files; prove they cannot restart during replacement. Keep the
255
- known-good installation until the new backend's version and instance identity are confirmed.
256
- Re-register the intended autostart path, refresh dashboard tabs, and confirm host wiring.
257
-
258
- One global npm prefix holds one package version and its shared command names. Installing the
259
- other major there replaces it. Separate ports do not isolate credentials, nonces, logs or
260
- session files: manual side-by-side operation needs separate durable code roots and separate
261
- configuration directories, plus separate host/HOME state for CLI-managed setup.
262
- `init/import --config` selects a source host configuration, not an isolated runtime profile.
263
- There is no package `--profile` or `MCP_HOME` switch. Do not use an unscoped stop/uninstall
264
- operation when another instance must remain running.
265
-
266
- ## Dashboards
267
-
268
- Two views of the same live state. Neither is required — the bridge runs headless — but both are
269
- useful for answering "is this server actually up, and who is using it?"
270
-
271
- ### Web dashboard
272
-
273
- `mcp-pacemaker dashboard`, or open `http://127.0.0.1:<port>/ui`. It streams over SSE, so it
274
- updates on its own without polling or a refresh.
275
-
276
- ![Web dashboard: one card per server, showing sessions, warm pool, pids and connected agents](docs/images/dashboard.png)
277
-
278
- Per server it shows the transport (`stdio` / `http`), the sharing policy (`pool` when pre-warming),
279
- live sessions against the cap, request count, the actual OS pids, the warm-pool count, how long
280
- ago it was last used, and **which clients are connected** — above, one server is shared by
281
- VS Code and Claude Code while others are held by Copilot, Cursor and Codex. `Recycle` restarts
282
- that server's processes; it is disabled for servers with no session to restart. The live log at
283
- the bottom is the bridge's own log, filterable.
284
-
285
- ### Pre-warming controls
286
-
287
- The **Pre-Warming** tab puts every stdio candidate, current pool and shared server in one table.
288
- It shows cold-start p50/p95, observed peak sessions, process starts, warm/target counts,
289
- shared-child state and pending work, and an action.
290
- HTTP proxies are excluded because the bridge does not launch their processes.
291
-
292
- Choose **Enable pre-warming (N)** on a slow-server card or in the table. The button shows
293
- the exact warm count and the extra resident-process cost before you click. Nothing enables
294
- it automatically. **Disable pre-warming** removes idle warm children without killing active
295
- sessions after the change is applied.
296
-
297
- Changes are batched in a **complete pending copy** of `servers.json`. Every accepted change
298
- resets a five-second countdown. When editing stops, reload validates the pending copy, retains
299
- the original as `servers.previous.json`, flips the pending file into place, and activates the
300
- new settings. The dashboard shows **Pending** or **Applying** until that succeeds; active
301
- mode and warm counts are not changed early. **Reload now** flushes the same batch immediately.
302
-
303
- **Cancel batch** discards a pending batch without changing active settings. **Undo batch**
304
- stages the full previous configuration for another five-second batch, only if no intervening
305
- active-file edit has occurred. These actions affect the entire batch; the dashboard names all
306
- affected servers. An unrelated pending batch must be cancelled or applied before Undo.
307
-
308
- The same controls are available without a browser:
309
-
310
- ```sh
311
- mcp-pacemaker prewarm --port 8791
312
- mcp-pacemaker prewarm --port 8791 --enable filesystem --count 2
313
- mcp-pacemaker prewarm --port 8791 --disable filesystem
314
- # Changes are queued; the printed command cancels a pending batch or undoes it after application.
315
- ```
316
-
317
- Use `--config <path>` when the bridge's config and admin nonce are outside the default
318
- directory. `--json` returns the measured snapshot. The CLI and UI use the same server
319
- eligibility and recommendation data; a missing latency sample is not reported as a zero-cost
320
- startup. The CLI returns after staging, so consecutive commands can join the same batch.
321
- `prewarm` shows pending settings separately from active values. Config remains strict JSON,
322
- not JSONC; the pending copy preserves unrelated JSON and requires a matching active revision.
323
- Conflicts are reported rather than overwriting someone else's edit.
324
-
325
- On Windows, saves run with the normal bridge account and use **directory-inherited auditing**.
326
- The dashboard gives a non-blocking notice: custom per-file audit rules may not carry forward
327
- to the new active copy. The retained original keeps its original metadata. No audit-read
328
- privilege, UAC prompt, or permanently elevated bridge is required.
329
-
330
- This does not permit broader access to configuration data. Candidates must have appropriate
331
- access restrictions before any configuration bytes are written, and supported integrity
332
- protections must be retained. Actual source write denial or unsupported protection remains
333
- an error. Configuration operations run in a serialized worker so file inspection does not
334
- block MCP traffic.
335
-
336
- Windows security inspection uses the bundled, own-source .NET Framework helper rather than
337
- starting PowerShell or compiling code on each write. Automatic edits require .NET Framework
338
- 4.6.2 or later; modern Windows includes it. The helper's source, build instructions and
339
- integrity metadata are [included in the package](tools/windows-security-helper/README.md).
340
- Windows ARM64 execution is not yet validated.
341
-
342
- Staging requests and file commits each have a bounded execution budget; the acknowledged
343
- five-second batching delay does not keep the original HTTP request open. A commit already in
344
- progress can finish after its deadline. The result distinguishes a pre-commit failure from
345
- a committed or unknown outcome; it never automatically retries or claims a timed-out write
346
- was rolled back.
347
-
348
- The two file moves are not an atomic exchange. Reload coordinates them with validated recovery
349
- state and non-replacing destination placement. Existing MCP traffic continues using the
350
- previous in-memory configuration during the flip; an external reader can briefly find the
351
- active path absent. Recovery must not overwrite a file created by an external editor.
352
- Reread the settings after an uncertain result.
353
-
354
- ### Upgrading from 1.3.0
355
-
356
- Version 2.0.0 changes the configuration-save protocol; it does not require a new `servers.json`
357
- format. Update the bridge and CLI together, then reload any open dashboard pages. A 1.3.0
358
- client with a current nonce gets HTTP 409 before staging, with an instruction to update the
359
- client. An already-open tab retains the old nonce after a bridge restart and gets HTTP 401;
360
- refresh it to load the new dashboard and admin session.
361
-
362
- Custom API clients must send `x-mcp-pooling-batch: 1`. Treat HTTP 202 as acceptance, not
363
- completion, and follow the returned batch ID in `prewarm.batches` until it is applied,
364
- cancelled or failed. CLI scripts must likewise wait for application before relying on new
365
- settings. Undo now restores the complete batch and may affect several servers.
366
- Updated clients still understand the immediate HTTP 200 response from a 1.3.0 bridge.
367
-
368
- Before downgrading, cancel or apply pending changes with 2.0 and resolve any interrupted
369
- transaction using 2.0 recovery. Stop that bridge before starting 1.3.0 with the active config.
370
- Do not use a 1.3.0 binary to recover 2.0 transaction files or delete those files to bypass a
371
- recovery error. Keep a protected backup of the configuration before changing versions.
372
- If the writer worker exits, further automatic edits are refused until the bridge restarts;
373
- existing MCP sessions continue.
374
-
375
- ### Health
376
-
377
- The `Health` tab runs the same checks as `mcp-pacemaker doctor`, so you can see them without a
378
- terminal.
379
-
380
- ![Health tab: Node version, config validity, per-server status and the admin nonce path](docs/images/health.png)
381
-
382
- It checks the Node version, that the config parses, every server definition (including a stdio
383
- server whose relative path will not resolve from the directory it would run in — a failure that
384
- is otherwise silent until a client first calls it, and a server named after one of the bridge's
385
- own routes, which is unreachable), any server currently failing, and that the admin nonce file
386
- exists.
387
-
388
- ### Terminal dashboard
389
-
390
- `mcp-pacemaker top` is the same data as an Ink TUI, for when a browser is inconvenient:
391
-
392
- ```
393
- 🫀 mcp-pacemaker top ● :8850 · up 176s · v1.1.0
394
- SERVER TYPE HEALTH SESS WARM REQ PID TOKEN ERROR / CLIENTS
395
- filesystem stdio ok 2 1/1 8 186276,12 - ⇄ Visual Studio Code,Claude Code
396
- github stdio ok 1 - 2 146436 - ⇄ GitHub Copilot
397
- sqlite stdio ok 1 - 2 102108 - ⇄ Cursor
398
- slow-tool stdio ok 1 - 2 103776 - ⇄ Codex CLI
399
- search-api http FAIL×3 0 - 4 - 42m upstream rejected the crede
400
- docs-api http ? 0 - 0 - -
401
- ↑↓ select · r recycle · q quit
402
- ```
403
-
404
- `HEALTH` is `ok` when the last request to that server succeeded, `FAIL×n` after n consecutive
405
- failures, and `?` when nothing has called it yet — deliberately not `ok`, since no evidence is not
406
- the same as working. `WARM` shows `warm/minWarm` for pooled servers and `-` for the rest, `TOKEN`
407
- the time left on a cached credential, and the last column either the connected clients or the last
408
- error. `↑↓` selects a row and `r` recycles it.
409
-
410
- ## Reading durable logs
411
-
412
- ```sh
413
- mcp-pacemaker logs --since 2h --server filesystem
414
- mcp-pacemaker logs --follow --grep timeout
415
- mcp-pacemaker logs --config /path/to/servers.json --since 2026-09-07T12:00:00Z
416
- ```
417
-
418
- `logs` reads `bridge.log.1` then `bridge.log` beside the selected config, including when
419
- the bridge is stopped. `--since` accepts durations in seconds/minutes/hours/days or an ISO
420
- timestamp with timezone. `--server` matches the exact log-header server name; `--grep` is
421
- a case-insensitive literal match, not a regular expression. Matching multiline records retain
422
- their header and context.
423
-
424
- `--follow` handles complete new lines, split UTF-8 writes, truncation and rollover until
425
- interrupted. It warns if rotation has already discarded an unread generation. Only retained
426
- history is available; it cannot recover logs the bridge has deleted. Individual lines over
427
- 1 MiB fail explicitly rather than being silently truncated.
428
-
429
- ## Editing servers.json while it runs
430
-
431
- Save the file and the bridge picks it up. Servers whose definition did not change are left
432
- completely alone — same processes, same live sessions — so adding one server does not cost you the
433
- fourteen that were already working:
434
-
435
- ```bash
436
- $ mcp-pacemaker reload # or just save the file; the bridge watches it
437
- ✓ reloaded /Users/you/.mcp-pacemaker/servers.json on :8850
438
- · added: postgres
439
- · changed: github
440
- · 2 session(s) restarted; untouched servers kept theirs
441
- ```
442
-
443
- A file that does not parse, or a server with neither `command` nor `url`, is **rejected whole** —
444
- the bridge logs why and keeps serving the last good config, so a half-written save cannot take your
445
- servers down. Set `MCP_CONFIG_WATCH=0` to require an explicit `reload` instead of watching.
446
-
447
- ## Server health
448
-
449
- Every server carries a health verdict in `/api/status`, `doctor`, `top` and the dashboard:
450
-
451
- | State | Meaning |
452
- |---|---|
453
- | `ok` | The last request to this server succeeded |
454
- | `failing` | Recent requests are failing, with a count of how many in a row |
455
- | `unknown` | Nothing has called it yet |
456
-
457
- This is passive and free — it is derived from traffic the bridge is already proxying. A JSON-RPC
458
- error *from* the server counts as healthy (it answered); a 401/403, a 5xx, a spawn failure or a
459
- non-zero exit counts as failing, and the state clears the moment a request succeeds again.
460
-
461
- A server nobody calls stays `unknown` forever, which is honest but not much help if its credential
462
- quietly expires overnight. `MCP_HEALTH_INTERVAL_MS` adds a periodic probe for HTTP servers so they
463
- get a verdict without waiting for a client:
464
-
465
210
  ```bash
466
- MCP_HEALTH_INTERVAL_MS=300000 mcp-pacemaker start # probe every 5 minutes
211
+ mcp-pacemaker uninstall # use the CLI from the matching installed version
467
212
  ```
468
213
 
469
- It is off by default because a probe is a real request to somebody else's service. Set
470
- `"healthIntervalMinutes": 0` on a server to exclude just that one, or a number to give it its own
471
- interval. stdio servers are not probed: a probe would mean spawning a process, which costs more
472
- than the request it is meant to pre-empt.
473
-
474
- ## HTTP API
475
-
476
- Everything the dashboards show is plain HTTP on the same loopback port, so you can script it.
477
- Read endpoints need no auth; administrative writes require a nonce.
214
+ This stops managed bridges, removes auto-start entries and restores available host-file
215
+ backups. It leaves files without backups and native Claude Code registrations unchanged.
216
+ It is not scoped to one port; review [replacement and rollback](docs/upgrades.md#replacing-or-rolling-back-a-running-installation)
217
+ first if another instance must remain running. Do not fetch a different CLI with `npx`
218
+ to remove an existing installation.
478
219
 
479
- | Endpoint | Method | Returns |
480
- |---|---|---|
481
- | `/status` | GET | Tiny liveness probe: `ok`, `service`, `version`, `port` and the server names. Used to tell a pacemaker bridge apart from a foreign service on the same port |
482
- | `/api/status` | GET | Full snapshot — every server with sessions, pids, warm count, request count, `health`, `lastError`, connected clients |
483
- | `/api/doctor` | GET | The health checks, as JSON |
484
- | `/api/events` | GET (SSE) | The same snapshot pushed every 2s — what the dashboard consumes |
485
- | `/api/logs` | GET (SSE) | Bridge log: replays the last 100 lines, then streams. For anything older, read `bridge.log` next to your config |
486
- | `/admin/recycle/<name>` | POST | Restart a server's processes. Omit `<name>` to recycle everything |
487
- | `/admin/reload` | POST | Flush a pending configuration batch, or re-read an externally edited `servers.json`. Only changed definitions are reconfigured |
488
- | `/admin/servers/<name>/pooling` | POST | Stage enable/disable or batch cancel/undo with admin nonce, bounded input and a matching config revision |
489
- | `/<name>/mcp` | POST/GET/DELETE | Streamable HTTP transport for that server |
490
- | `/<name>/sse` | GET | HTTP+SSE transport for that server |
491
- | `/.well-known/oauth-protected-resource/<name>` | GET | OAuth discovery relayed from the upstream, for HTTP servers where the client authenticates |
492
-
493
- Pooling mutations require `x-mcp-pooling-batch: 1`. A staged change returns **HTTP 202** with
494
- `pending: true`, a batch ID, a private cancel/undo receipt, and the public snapshot. Acceptance
495
- is not activation. `prewarm.batches` in the snapshot reports bounded pending, applying and
496
- completed outcomes; it does not expose receipt tokens or full configurations.
497
- Clients without the batch header are rejected before a change is queued, rather than letting
498
- an older client report a queued save as already enabled.
499
- Rich snapshots carry an instance-scoped `snapshotVersion` so a delayed HTTP response or older
500
- SSE frame cannot replace newer active settings or prematurely expire a batch receipt.
220
+ After the installed service has been removed successfully, remove the global npm package:
501
221
 
502
222
  ```bash
503
- # is a server actually running, and who is using it?
504
- curl -s http://127.0.0.1:8850/api/status | jq '.servers[] | {name, sessions, pids, clients}'
505
-
506
- # watch the bridge log
507
- curl -N http://127.0.0.1:8850/api/logs
508
-
509
- # force a restart of one server (nonce is written next to servers.json)
510
- curl -X POST http://127.0.0.1:8850/admin/recycle/filesystem \
511
- -H "x-mcp-nonce: $(cat ~/.mcp-pacemaker/admin.nonce)"
512
- ```
513
-
514
- `/admin/*` is guarded twice: the request must arrive on loopback, **and** carry the nonce that the
515
- bridge writes to `admin.nonce` next to your config at startup. The nonce is new on every start, so
516
- only same-box tooling that can read that file — the CLI, and the dashboard the bridge itself
517
- served — can change anything.
518
-
519
- ## servers.json
520
-
521
- Config lives at `~/.mcp-pacemaker/servers.json`. `import` fills it from your existing client
522
- config and **carries over `audience`/`auth`/`headers`**, so HTTP servers usually need no hand-editing.
523
- See [`examples/servers.example.json`](examples/servers.example.json).
524
-
525
- ```jsonc
526
- {
527
- "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "."] },
528
-
529
- "my-api": {
530
- "type": "http",
531
- "url": "https://my-service.example.com/mcp",
532
- "auth": { "type": "command", "command": "my-cli print-token", "refreshMinutes": 50 }
533
- }
534
- }
535
- ```
536
-
537
- **Auth options** (per HTTP server):
538
-
539
- | `auth.type` | Behavior |
540
- |---|---|
541
- | `command` | Runs any command that prints a token on stdout; the result is cached and auto-refreshed (`refreshMinutes`). Provider-agnostic — see below. |
542
- | `env` | Uses `process.env[var]`. |
543
- | `static` | Fixed `header` + `value`. |
544
- | `none` | No header is added — the **client** authenticates, and the bridge relays OAuth discovery and challenges for it. |
545
-
546
- `auth.type: "command"` is deliberately just "run this and use what it prints", so it works with
547
- whatever issues tokens in your environment. Some examples — none of these are special-cased:
548
-
549
- ```jsonc
550
- // Azure
551
- { "type": "command", "command": "az account get-access-token --resource api://<id> --query accessToken -o tsv" }
552
- // Google Cloud
553
- { "type": "command", "command": "gcloud auth print-access-token" }
554
- // AWS (e.g. a signed token from your own helper)
555
- { "type": "command", "command": "aws-token-helper --profile prod" }
556
- // HashiCorp Vault
557
- { "type": "command", "command": "vault read -field=token secret/my-api" }
558
- // 1Password / any secret manager
559
- { "type": "command", "command": "op read op://vault/my-api/token" }
560
- // A plain script
561
- { "type": "command", "command": "./scripts/get-token.sh" }
223
+ npm uninstall -g mcp-pacemaker
562
224
  ```
563
225
 
564
- By default the token is sent as `Authorization: Bearer <token>`; set `header` to send it
565
- somewhere else (for example `{ "header": "X-Api-Key" }`).
566
-
567
- **How long a credential is cached.** If the command returns a JWT, its `exp` claim decides —
568
- `refreshMinutes` is only an upper bound and a fallback for opaque credentials. This matters
569
- because token CLIs serve from their own cache: `az account get-access-token` will hand back a
570
- token it minted earlier that may be nearly spent, and trusting a flat window would keep a dead
571
- token in play. If the upstream rejects a credential the bridge supplied, that 401 is reported on
572
- the server (`doctor`, `/api/status` → `lastError`) and the credential is discarded rather than
573
- reused — the client is never asked to log in for a server the bridge authenticates.
574
-
575
- > **Azure shorthand.** A bare `"audience": "<res>"` expands to
576
- > `az account get-access-token --resource <res> …`. That is a convenience for Azure users only —
577
- > every other provider uses `auth.command` above.
578
-
579
226
  ## Security
580
227
 
581
228
  - The bridge binds **`127.0.0.1` only** (local loopback) — not reachable off-box.
582
229
  - Tokens are **minted from your own already-authenticated CLI** and cached in memory; **never written to disk**.
583
230
  - The **bridge** (the process that runs 24/7) has **zero third-party dependencies**; the setup CLI uses `commander` / `@clack/prompts` / `picocolors` / `smol-toml`, and the TUI adds `ink` / `react`.
584
231
 
585
- ## Multi-agent & resource controls
586
-
587
- Multiple hosts/agents can share one bridge — each gets its own isolated session by default,
588
- and HTTP servers share the cached token across all of them. The dashboard, `top`, and
589
- `mcp-pacemaker status` show **which agents are connected** to each server.
590
-
591
- | Control | Env / config | Default | Effect |
592
- |---|---|---|---|
593
- | Idle reaper | `MCP_IDLE_TIMEOUT_MS` | `1800000` (30 min) | free Streamable HTTP children idle past the timeout. Safe by default because a returning client's session is transparently re-established. `0` disables |
594
- | Concurrency cap | `MCP_MAX_SESSIONS_PER_SERVER`, or per-server `maxSessions` | `0` (unlimited) | reject new sessions past the cap (HTTP 503) |
595
- | Queue at the cap | `MCP_QUEUE_TIMEOUT_MS` | `10000` (10s) | at the cap, wait this long for a slot before returning 503, so a burst is absorbed rather than failed. `0` rejects immediately |
596
- | Sharing policy | per-server `sharing` (+ `minWarm`) | `isolated` | `isolated` = one child per session; `pool` pre-starts exclusive children; `shared` reuses one initialized child for compatible stateless tools sessions. Both alternatives require explicit activation |
597
- | Cold-start gate | `MCP_MAX_CONCURRENT_SPAWNS`, `MCP_SPAWN_GATE_WAIT_MS` | `2`, `15000` | how many package-manager-backed servers may cold-start at once. `npx`, `uvx`, `dnx` and friends share one cache, and starting several together can corrupt it — this queues them. Detected from the command, or forced either way with per-server `sharedPackageCache`. Servers that use no package manager are never gated. If no slot frees within the wait, the spawn proceeds ungated rather than hold a client request. `0` disables |
598
- | Pooling advice | `MCP_POOL_ADVICE_MS`, `MCP_WARM_MAX` | 2s, 8 | recommend pooling once a server's measured cold start passes this, and cap the suggested (and auto-sized) pool here. Advice only — the bridge never enables pooling on its own |
599
- | Session resume | `MCP_RESUME`, `MCP_RESUME_TTL_MS` | on, 24h | re-establish a session id the bridge has not seen — after a restart, recycle or idle reap. `MCP_RESUME=0` disables |
600
- | Scheduled recycle | per-server `recycleMinutes`, or `MCP_RECYCLE_MINUTES` | off | restart a server periodically, for servers holding a credential they can only refresh interactively |
601
- | Request timeouts | `MCP_REQUEST_TIMEOUT_MS` / `MCP_INIT_TIMEOUT_MS` | 30s / 180s | `initialize` also pays for spawning the server, so it gets a longer budget than ordinary calls |
602
- | Credential refresh | `MCP_TOKEN_REFRESH_LEAD_MS` | `300000` (5 min) | renew a cached token before it expires instead of discovering the expiry on a request. A JWT's own `exp` still caps how long it is cached |
603
- | Durable log | `MCP_LOG_MAX_BYTES` | `5242880` (5 MB) | `bridge.log` next to your config, rolled to `bridge.log.1` at this size. `0` disables. The dashboard only keeps the last few hundred lines in memory, which a chatty client fills in minutes |
604
- | Config watching | `MCP_CONFIG_WATCH` | on | reload `servers.json` when it is saved. `0` requires an explicit `mcp-pacemaker reload`. Either way, only servers whose definition changed are restarted, and an unparseable file is rejected without disturbing anything |
605
- | Health probing | `MCP_HEALTH_INTERVAL_MS`, or per-server `healthIntervalMinutes` | off | periodically call an HTTP server so it has a health verdict before a client needs it. Passive health from real traffic is always on and costs nothing |
606
-
607
- ### Measuring process churn
608
-
609
- For stdio servers, `/api/status` reports `spawn.total` (successful process launches),
610
- `spawn.attempts`, `spawn.failures`, `spawn.warmAdoptions`, `spawn.sessionStarts`, and
611
- `spawn.sessionResumes`. Launches include classic SSE, Streamable HTTP, warm-pool refill,
612
- and replacements after recycle or resume. Adopting an existing warm child does not count
613
- as another launch. The unit is one bridge-launched process, not all of its descendants.
614
-
615
- These cumulative counters do not share the 50-sample latency limit. They reset when the
616
- bridge process restarts; compare snapshots only within the same `instanceId`. `startedAt`
617
- identifies that interval. Save the final snapshot before a planned restart for a before/after
618
- comparison. HTTP-proxied servers have no local process counters (`spawn: null`).
619
-
620
- `spawn.samples` and p50/p95/max still describe the latest 50 directly observed, successful
621
- cold initializations, not all launches. Latencies are `null` until observed; a warm child's
622
- idle lifetime is not a cold-start sample. The existing `requests` count covers routed HTTP
623
- requests, not just `tools/call`; do not label it as a tool-call count.
624
-
625
- ### Shared mode
626
-
627
- Set `"sharing": "shared"` on a stdio server only when its tools are stateless, operate on
628
- explicit inputs and use one common credential context. This is an operator assertion, not
629
- something latency or matching capabilities can prove. Leave workspace-, conversation- or
630
- client-account-dependent servers isolated.
631
-
632
- Compatible sessions have identical full initialization parameters, including `clientInfo`,
633
- and empty client capabilities. One child receives one real initialization; each virtual session
634
- gets its own IDs, progress, cancellation and tools-list cursors. Only the upstream's actual
635
- tools capability is exposed. Roots, sampling, elicitation, tasks, resource subscriptions and
636
- other stateful methods are not supported. Incompatible clients fail explicitly, without
637
- silently falling back to a different mode.
638
-
639
- Deleting one session leaves the others running. The initialized child is retained between
640
- compatible reconnects for up to `sharedLingerMs` (30 minutes by default). Recycle drains work,
641
- then replaces the generation on later use. A timeout or child exit never triggers automatic
642
- replay of a potentially executed tool call.
643
-
644
- The server keeps its existing credential provider and configured `recycleMinutes`. Shared
645
- mode does not promise silent credential renewal. The dashboard and `prewarm` CLI show the
646
- actual shared-child state, members, queued work and cumulative process launches.
647
- See [the shared-session contract](docs/shared-sessions.md) for limits and failure semantics.
232
+ See [SECURITY.md](SECURITY.md) for the threat model and how to report a vulnerability. The
233
+ [HTTP API](docs/http-api.md) page explains how administrative requests are guarded.
648
234
 
649
- ## Uninstall
235
+ ## Documentation
650
236
 
651
- ```bash
652
- mcp-pacemaker uninstall # use the CLI from the matching installed version
653
- ```
654
-
655
- This stops managed bridges, removes auto-start entries and restores available host-file
656
- backups. It leaves files without backups and native Claude Code registrations unchanged.
657
- It is not scoped to one port; review [replacement and rollback](#replacing-or-rolling-back-a-running-installation)
658
- first if another instance must remain running. Do not fetch a different CLI with `npx`
659
- to remove an existing installation.
660
-
661
- After the installed service has been removed successfully, remove the global npm package:
662
-
663
- ```bash
664
- npm uninstall -g mcp-pacemaker
665
- ```
237
+ - [Install details](docs/install.md) — Node and Windows requirements, the ordinary-user rule and npm channels
238
+ - [Configuration](docs/configuration.md) — `servers.json`, auth, live edits, resource controls and shared mode
239
+ - [Commands and operations](docs/operations.md) — every command, start and stop, durable logs and server health
240
+ - [Dashboards](docs/dashboards.md) — the web dashboard, pre-warming controls, the health tab and `top`
241
+ - [HTTP API](docs/http-api.md) — endpoints, pooling batches and the admin nonce
242
+ - [Upgrades and rollback](docs/upgrades.md) — managed upgrades, `--sxs`, recovery and the Windows 1.3 migration
243
+ - [Version compatibility](docs/compatibility.md) — 1.3.x and 2.x pairs, and upgrading from 1.3.0
244
+ - [User-runtime contract](docs/execution-context.md) — what the ordinary-user check verifies
245
+ - [Shared sessions](docs/shared-sessions.md) — the full shared-mode contract
246
+ - [Account upgrades](docs/account-upgrades.md) — explicit original-account upgrades on Windows
247
+ - [Roadmap](docs/roadmap.md) — planned work, including socket handoff
666
248
 
667
249
  ## Project
668
250
 
669
251
  - [CHANGELOG.md](CHANGELOG.md) — release notes
670
252
  - [CONTRIBUTING.md](CONTRIBUTING.md) — development setup and how regression tests are expected to be proven
671
253
  - [SECURITY.md](SECURITY.md) — threat model and how to report a vulnerability
254
+ - Publishing and qualification: [npm publishing](docs/npm-publishing.md),
255
+ [local publication gate](docs/local-publication-gate.md) and
256
+ [cross-host live validation](docs/cross-host-live-validation.md)
672
257
 
673
258
  ## License
674
259