mcp-pacemaker 2.0.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 (47) hide show
  1. package/CHANGELOG.md +452 -0
  2. package/CONTRIBUTING.md +222 -0
  3. package/LICENSE +21 -0
  4. package/README.md +621 -0
  5. package/SECURITY.md +120 -0
  6. package/THIRD_PARTY_NOTICES.txt +366 -0
  7. package/autostart/windows/launcher.vbs +11 -0
  8. package/autostart/windows/register-task.ps1 +63 -0
  9. package/bin/cli.mjs +880 -0
  10. package/bin/config-checks.mjs +62 -0
  11. package/bin/logs.mjs +465 -0
  12. package/bin/mcp-bridge.mjs +2162 -0
  13. package/bin/pooling-batch-scheduler.mjs +129 -0
  14. package/bin/pooling-batches.mjs +270 -0
  15. package/bin/pooling-config.mjs +577 -0
  16. package/bin/pooling-editor.mjs +128 -0
  17. package/bin/pooling-errors.mjs +23 -0
  18. package/bin/pooling-execution.mjs +104 -0
  19. package/bin/pooling-files.mjs +541 -0
  20. package/bin/pooling-trace.mjs +218 -0
  21. package/bin/pooling-writer.mjs +242 -0
  22. package/bin/prewarm.mjs +233 -0
  23. package/bin/server-metrics.mjs +69 -0
  24. package/bin/service-control.mjs +124 -0
  25. package/bin/shared-sessions.mjs +1083 -0
  26. package/bin/top.mjs +115 -0
  27. package/bin/update-check.mjs +153 -0
  28. package/bin/windows/PoolingSecurityHelper.build.json +42 -0
  29. package/bin/windows/PoolingSecurityHelper.exe +0 -0
  30. package/bin/windows/src/AssemblyInfo.cs +11 -0
  31. package/bin/windows/src/PoolingNativeFiles.cs +678 -0
  32. package/bin/windows/src/PoolingSecurityHelper.cs +178 -0
  33. package/bin/windows/src/PoolingSecurityReader.cs +50 -0
  34. package/docs/shared-sessions.md +181 -0
  35. package/examples/servers.example.json +31 -0
  36. package/package.json +77 -0
  37. package/supervisor/bridge-child.mjs +14 -0
  38. package/supervisor/supervise.mjs +172 -0
  39. package/supervisor/supervise.ps1 +23 -0
  40. package/supervisor/supervise.sh +11 -0
  41. package/tools/windows-security-helper/README.md +238 -0
  42. package/tools/windows-security-helper/build.ps1 +262 -0
  43. package/ui/dist/THIRD_PARTY_NOTICES.txt +366 -0
  44. package/ui/dist/assets/index-CaLPg0c-.css +1 -0
  45. package/ui/dist/assets/index-CgPruWYi.js +9 -0
  46. package/ui/dist/index.html +14 -0
  47. package/ui/dist/third-party-manifest.json +597 -0
@@ -0,0 +1,222 @@
1
+ # Contributing
2
+
3
+ Thanks for taking a look. This is a small, deliberately dependency-light project, so a few
4
+ constraints matter more than they might elsewhere.
5
+
6
+ ## Getting set up
7
+
8
+ ```bash
9
+ git clone https://github.com/girishkvs/mcp-pacemaker
10
+ cd mcp-pacemaker
11
+ npm ci
12
+ npm test
13
+ ```
14
+
15
+ Node 20 or newer. The bridge itself (`bin/mcp-bridge.mjs`) has **zero npm runtime dependencies**
16
+ and must stay that way; it runs 24/7 on a developer's machine and its dependency surface is
17
+ part of its security posture. The setup CLI and the dashboard may use dependencies.
18
+
19
+ ## Lockfiles must resolve to the public registry
20
+
21
+ CI fails any lockfile containing a `resolved` URL outside `registry.npmjs.org`. If you work
22
+ behind a private mirror, re-resolve before committing:
23
+
24
+ ```bash
25
+ npm install --registry https://registry.npmjs.org
26
+ ```
27
+
28
+ ## Tests
29
+
30
+ ```bash
31
+ npm test
32
+ ```
33
+
34
+ Tests are `node:test` only, no framework. Each test file that starts a bridge owns its own
35
+ ports, because files run in parallel; the current allocation is listed at the top of
36
+ `test/auth-token.test.mjs`. Pick unused ones for a new file.
37
+
38
+ Before submitting, run the complete `npm test` command with its normal file concurrency.
39
+ Focused or serialized runs help diagnose failures but do not replace that run. Record the
40
+ exact Node and npm versions, OS, architecture, and command; matching only the Node major is
41
+ not enough to reproduce a CI failure.
42
+
43
+ Filesystem coverage must include native POSIX absolute paths, macOS temporary-directory
44
+ aliases, and Windows 8.3 temporary paths as well as canonical paths. Preserve those inputs
45
+ when reproducing a failure instead of normalizing the whole test environment. Canonicalize
46
+ owned scratch roots and native watcher inputs at their boundaries; keep rejecting unexpected
47
+ links, replaced directories, and files outside the approved inventory. A Windows-only pass
48
+ does not establish Linux or macOS correctness; the hosted platform matrix remains required.
49
+
50
+ Windows configuration-write coverage must exercise the normal interactive startup token,
51
+ not only a test process inheriting an elevated runner. Validate both the actual token context
52
+ and successful staging/activation. Security-oracle fixtures may use already-authorized test
53
+ authority to establish and inspect their own files; production saves must not depend on it.
54
+ Directory-inherited auditing is the default. Test ordinary access restrictions, integrity,
55
+ custom-audit behavior, contender files and crash recovery separately.
56
+
57
+ Windows automatic edits use the packaged .NET Framework 4.6.2 helper. Changes to its source
58
+ must rebuild the executable and metadata with
59
+ `tools/windows-security-helper/build.ps1`, then pass `-Verify` with the recorded compiler
60
+ and reference assemblies. See the [helper build instructions](tools/windows-security-helper/README.md).
61
+ The portable Node suite checks normalized source/build-script and binary hashes on every CI
62
+ platform; Windows also exercises the real executable. Those checks do not replace the
63
+ byte-for-byte rebuild, and a rolling CI image may not contain the recorded compiler.
64
+ No compiler or PowerShell host runs in the production config-write path.
65
+
66
+ Batch tests must cover the full five-second trailing debounce, merging complete snapshots,
67
+ Reload now, requests during a flip, stale active revisions, whole-batch Cancel/Undo and late
68
+ commit outcomes. Use controlled clocks for scheduling boundaries and real file/HTTP cases for
69
+ integration. A skipped second move is not proof of recovery after actual process termination.
70
+
71
+ **A regression test must be shown to fail without its fix.** Revert the fix, watch the test
72
+ fail, restore it, watch it pass. Several bugs in this repo were originally "covered" by tests
73
+ that passed against the broken code — a test that cannot fail is worse than no test, because
74
+ it also stops anyone else from looking. If a bug involves process lifetime or timing, prefer
75
+ observing a real signal (a heartbeat file, a recorded request) over enumerating processes or
76
+ sleeping a fixed interval.
77
+
78
+ ## Real-version compatibility gates
79
+
80
+ These are separate, mandatory CI gates, not substitutes for `npm test`. The root CI job runs
81
+ CLI/API pairs on Windows, Linux and macOS with Node 20, 22 and 24. The Linux/Node 22 UI
82
+ job runs one Chromium browser matrix after building the dashboard.
83
+
84
+ ```bash
85
+ npm ci
86
+ npm run compat:prepare
87
+ npm run test:compat
88
+ npm run compat:clean
89
+
90
+ # Browser gate: build before packing the candidate.
91
+ npm --prefix ui ci
92
+ npm --prefix ui run build
93
+ cd ui
94
+ npx --no-install playwright install --with-deps chromium
95
+ cd ..
96
+ npm run compat:prepare
97
+ npm run test:compat:browser
98
+ npm run compat:clean
99
+ ```
100
+
101
+ For an already installed local Chrome, set `MCP_COMPAT_BROWSER_CHANNEL=chrome` in your shell
102
+ instead of installing bundled Chromium. CI uses bundled Chromium, not that override.
103
+ Both standalone test commands **fail** when preparation is missing or candidate bytes have
104
+ changed. Clean and prepare again after changing package files, built assets, or Node major.
105
+
106
+ Scope is explicitly **1.3.0, 1.3.1, 2.0.0 and 2.0.1**, not arbitrary compatible-looking versions.
107
+ The same harness runs in both maintained branches:
108
+
109
+ | Preparation | Selected legacy / current pair |
110
+ |---|---|
111
+ | Default in the 2.0.1 checkout | Immutable 1.3.0 / packed 2.0.1 |
112
+ | Default in the 1.3.1 checkout | Packed 1.3.1 / immutable 2.0.0 |
113
+ | `npm run compat:prepare:baseline` | Immutable 1.3.0 / immutable 2.0.0 |
114
+ | `npm run compat:prepare -- --peer-root <opposite-patch-checkout>` | Packed 1.3.1 / packed 2.0.1 |
115
+
116
+ Run both API and browser gates for the explicit patch pair before publishing either complete
117
+ dual-major release set. The two default CI pairs alone do not establish that combined result.
118
+ Run `compat:clean` before selecting another pair.
119
+
120
+ Publication artifact gates add `--candidate-tarball <absolute.tgz> --candidate-sha256 <digest>`.
121
+ This supplies the checkout's own candidate role without repacking it, including the legacy
122
+ role when invoked from 1.3.1. The archive must match every package input and the supplied digest;
123
+ historical mode cannot substitute it. The manifest also records the exact npm CLI version.
124
+
125
+ Release sources are pinned to `2d525f4ced01b978a5aeb83aef69145e96cced05` (1.3.0) and
126
+ `db4812a1cbfb8546c814a656397b9a48ccf0f32c` (2.0.0). Missing commits are fetched read-only by
127
+ exact SHA into an owned temporary repository, never through a moving tag or into checkout refs.
128
+ Git archive uses canonical Git line endings and the committed attributes. Local candidates
129
+ are packed with lifecycle scripts disabled and compared against their actual source files.
130
+
131
+ Each selected package uses its own unchanged producer lock via `npm ci --omit=dev --ignore-scripts`.
132
+ This is producer-locked compatibility, not fresh consumer resolution. The manifest records the
133
+ selection mode, exact versions and release references, per-role archive/file hashes, source
134
+ inputs and Node major. Editing either candidate invalidates prepared fixtures. No patch is
135
+ relabeled as the original historical bytes. Git, tar, Node and npm must be available.
136
+
137
+ For local restores through an approved registry, preparation honors the caller's resolved
138
+ `npm_config_registry` and `npm_config_replace_registry_host` settings (and npm cache).
139
+ For example, in a POSIX shell:
140
+
141
+ ```bash
142
+ npm_config_registry=https://approved-registry.example.test/npm/ \
143
+ npm_config_replace_registry_host=npmjs npm run compat:prepare
144
+ ```
145
+
146
+ Use your approved registry URL, not the example. These settings are forwarded to isolated
147
+ `npm ci` calls without changing npmrc files or recording registry settings in the manifest.
148
+ CI sets no override and uses the public registry. Both committed lockfiles and the fixture
149
+ lockfiles must retain public URLs; preparation verifies that restore leaves fixture locks
150
+ byte-identical. Registry policy or quarantine rejections fail preparation without a fallback.
151
+
152
+ Fixtures, private baseline code, configuration and fake HOME/state live in owned OS temporary
153
+ directories, never the user's active configuration. Only a manifest pointer is kept under
154
+ ignored `node_modules/.cache`. This manifest is also the prepared fixture's ownership marker:
155
+ it is created before restore, keeps its identity when preparation finishes, and is removed
156
+ only after its temporary tree is gone. A failed manifest unlink remains retryable. Other
157
+ temporary test directories use adjacent ownership markers. Ports are allocated dynamically.
158
+ Cleanup checks directory and marker identities and removes only owned files without following
159
+ links. Bridge/browser failures retain their original error and diagnostic logs in test output;
160
+ cleanup errors do not replace
161
+ the original failure. Run cleanup before another root `npm ci`, which removes the pointer.
162
+
163
+ | Pair/case | Required result |
164
+ |---|---|
165
+ | Selected 2.x CLI/API and built UI to selected 1.x backend | Legacy HTTP 200 enable and Undo; original config bytes restored |
166
+ | Selected 1.x CLI/API and built UI to selected 2.x backend, fresh nonce | Protocol HTTP 409, no queued write or config change |
167
+ | Already-open selected 1.x tab through an actual bridge restart | Old nonce gets HTTP 401; refresh loads the selected 2.x assets and can stage/cancel |
168
+ | Selected 2.x CLI and UI to selected 2.x backend | Queued save, Cancel, actual application and whole-batch Undo |
169
+ | Settled selected 1.x / 2.x / 1.x configuration | Edits/Undo and both restarts preserve the expected active bytes |
170
+ | Actual selected 1.x writes before and after that roundtrip, unchanged authority | Supported write/Undo must remain supported; known Windows audit-unavailable refusal must remain HTTP 403 with no change |
171
+
172
+ **Test-only UI asset serving:** the two mixed UI/backend cases serve exact old/new built
173
+ `ui/dist` files through Playwright, substituting only the current nonce in the HTML. All
174
+ API, admin mutation, SSE and MCP requests go to the real backend, without response mocks.
175
+ Nested JS assets are included. The old-tab upgrade case does not substitute assets: it stops
176
+ the actual selected 1.x process and starts the selected 2.x process on the same port before refresh.
177
+
178
+ No other version compatibility is claimed. Writable downgrade is checked on a fresh
179
+ synthetic config with default ownership and inherited security. The test does not change
180
+ tokens, elevate, or set ACLs. It checks unchanged caller authority and, on Windows, the actual
181
+ selected 1.x helper's full/partial audit visibility. Caller-context hashes are not direct measurements
182
+ of individual bridge tokens. Only the legacy HTTP 403 audit-unavailable
183
+ condition is accepted as unsupported; unexpected errors and any new HTTP 500 fail the gate.
184
+ The Windows 2.x writer retains a source owner matching the caller user or token default
185
+ owner; other owners still use checked transfer, and source write access remains required.
186
+ These gates do not test a downgrade with an unresolved transaction, installer/service
187
+ replacement, arbitrary Windows ACLs or authority changes, or all host integrations; their
188
+ separate tests and operational checks still apply.
189
+
190
+ ## npm consumer validation
191
+
192
+ `npm run consumer:check -- --tarball <absolute-file> --sha256 <digest> --version <version> --name mcp-pacemaker`
193
+ installs the exact packed candidate into an owned disposable consumer project without a copied
194
+ producer lock, records the resolved graph, checks a separate global-prefix command shim, and
195
+ starts the real packaged bridge against synthetic servers and private state. It checks the
196
+ packaged UI assets and CLI status, then removes only its owned fixtures.
197
+
198
+ Run it with normal npm install-script policy and again with `--ignore-scripts`. It never uses
199
+ the user's global prefix, host configuration, live bridge, or npm credentials. It honors the
200
+ resolved caller registry/cache and offline setting without a mirror fallback. Registry
201
+ signatures and provenance are separate post-publication checks, not inferred from this smoke test.
202
+
203
+ ## Changing how a host is wired
204
+
205
+ Host adapters live in `HOSTS` in `bin/cli.mjs`. Each one declares where that host's config
206
+ lives, the JSON key its servers sit under, and how a bridged entry is serialized. When you add
207
+ or change one:
208
+
209
+ - Add a case to `test/cli.test.mjs` asserting the exact entry shape.
210
+ - Never write a host config without backing it up first, and make sure `plan` reports the
211
+ change accurately — it is what people rely on before letting the tool touch their setup.
212
+ - Re-run `mcp-pacemaker plan` against a real config afterwards. It should report no changes
213
+ for a setup that is already correctly wired; anything else means the adapter and the
214
+ reconciliation logic disagree.
215
+
216
+ ## Pull requests
217
+
218
+ - One concern per PR.
219
+ - Explain what broke and how you proved it fixed, not just what you changed.
220
+ - Comment only what needs clarifying — why something is done a particular way, not what the
221
+ line does.
222
+ - Update `CHANGELOG.md` under an `Unreleased` heading.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Girish Konda
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.