Single-commit clean baseline after security scrub of niche-tells, project codenames, internal jargon, and contributor-email leaks. Contents: - 100 Rust crates (_primitives/_rust/) - 37 agent manifests (_manifests/) + generated specs (_generated/) - 67 user-invocable skills (skills/) - 33 hooks (hooks/) - Composition blocks (_blocks/) - Documentation (docs/, README.md) - TS adapter packages (_ts_packages/) - Assembler (_assembler/) - Roles (_roles/) - Templates (_templates/) - Forgejo CI (.forgejo/) Author: Denis Parfionovich <info@greendragon.info> License: see LICENSE.
3.6 KiB
Building a single-binary kei-mcp-server
KeiSeiKit v0.18 Phase 1 (exobrain) — ship the MCP server as a portable static binary so any machine without Node can run it off a USB drive.
Tooling
Compile via bun (bun build --compile). Bundles the Bun runtime + JS
into one static executable — no Node, no node_modules/ at runtime.
Requires bun >= 1.0. Docs (target list + flags):
[VERIFIED: https://bun.sh/docs/bundler/executables]
Supported targets
| Platform | Arch | --target= |
Output name |
|---|---|---|---|
| Linux | x64 | bun-linux-x64 |
kei-mcp-server-linux-x64 |
| Linux | arm64 | bun-linux-arm64 |
kei-mcp-server-linux-arm64 |
| macOS | x64 | bun-darwin-x64 |
kei-mcp-server-darwin-x64 |
| macOS | arm64 | bun-darwin-arm64 |
kei-mcp-server-darwin-arm64 |
| Windows | x64 | bun-windows-x64 |
kei-mcp-server-windows-x64.exe |
Local build
cd _ts_packages/packages/mcp-server
bun install
bun run build:native # host-native
bun run build:native:darwin-arm64 # explicit cross-target
Output lands in dist/. Size ~85–95 MB per binary (bundled runtime).
Release build (CI)
.github/workflows/release.yml → job build-mcp-binary runs the 5-target
matrix on tag push (v*) and attaches binaries + .sha256 sums to the
GitHub release. Runtime requirement: none (static).
Troubleshooting
- macOS Gatekeeper (“cannot be opened because Apple cannot check it for
malicious software”) — remove the quarantine attribute:
xattr -d com.apple.quarantine ./kei-mcp-server-darwin-arm64 - Windows SmartScreen / AV flags — not signed; right-click → Properties → Unblock, or add an AV exclusion for the binary path.
- Missing symbol at startup — usually a native-only dep that resolved
at runtime on Node but cannot be bundled. Re-run
bun install, thenbun build --compile ... --smolto surface the resolution error. .jsESM imports fail — the mcp-server source imports via.jssuffix (ESM canonical). Bun resolves these from the sibling.tsfile automatically; notscpre-step needed.
Lockfile
Since v0.19.1 the _ts_packages workspace ships a single bun.lock
at the workspace root (_ts_packages/bun.lock). Bun is a monorepo
tool — one lockfile covers all packages/* including mcp-server.
The release workflow runs bun install --frozen-lockfile from the
workspace root with NO fallback — a missing or out-of-date lockfile
fails the build on purpose. This is H4 supply-chain defense: every
release builds against the exact dependency tree recorded in the
committed lockfile, not whatever the npm registry serves that day.
Before every release tag:
cd _ts_packagesbun install(regeneratesbun.lockif anypackages/*/package.jsonchanged)- Commit
bun.lockif it changed - Tag the release
If you see the build fail with "lockfile out of sync" on a tag push:
you pushed the tag before committing an updated bun.lock. Fix:
generate the lockfile locally, commit, re-tag.
Coexistence with package-lock.json: the top-level CI (ci.yml)
still uses npm ci against package-lock.json for TypeScript tests.
Both lockfiles are committed. Audit finding L2 (dual-lockfile skew
risk) is tracked for a future v0.20 consolidation — pick one tool
across CI + release. Until then, re-run bun install AND
npm install whenever any packages/*/package.json changes.