Zero-dependency MCP server for engineering-board: a git-committed kanban board your AI agents run and remember.
Project description
engineering-board MCP server
A zero-dependency Model Context Protocol server
that exposes the engineering-board plugin's markdown board as MCP tools. It lets
any MCP client (Claude Code, Claude Desktop, …) scaffold boards, create/list/update
entries, rebuild the index, capture scratch findings, and claim/release entry locks —
all against the exact on-disk format the plugin's hooks and skills expect.
Design constraints
- Pure
python3, zero third-party dependencies. Nomcppip SDK, nopydantic. The MCP stdio/JSON-RPC protocol is implemented directly, so the server runs under the samebash+python3+ coreutils toolchain as the rest of the plugin (CI has no install step). - Transport: stdio, JSON-RPC 2.0, newline-delimited messages, protocolVersion
2025-06-18. Only JSON-RPC messages go to stdout; diagnostics go to stderr. - Locking is not reimplemented —
board_claim/board_releaseshell out to the plugin's existinghooks/scripts/board-claim-acquire.sh/board-claim-release.sh. - Timestamps are real UTC ISO-8601 (second precision) via
datetime.now(timezone.utc).
The board location for a project is resolved via engineering-board/BOARD-ROUTER.md
(then the pre-1.1.0 docs/boards/BOARD-ROUTER.md compat path), falling back to
engineering-board/<project>/. The repo root defaults to $CLAUDE_PROJECT_DIR, then
the current working directory, and can be overridden per-call with a root argument.
Tools
| Tool | What it does |
|---|---|
board_init |
Scaffold a project board (router row, BOARD.md, ARCHIVE.md, 5 subdirs + .gitkeep). Idempotent — never clobbers. Optional agents_md (default true) writes a marker-fenced usage block into the repo's AGENTS.md for hook-less agents. |
board_list_projects |
List projects from BOARD-ROUTER.md (id, path, affects prefix). |
board_create_entry |
Create a valid entry (bug/feature/question/observation/learning) with correct frontmatter + required body sections, allocate the next zero-padded id, rebuild the index. Output passes board-validate-entry.sh. Optional parent links a subtask to an existing entry. |
board_list_entries |
List entries with parsed frontmatter; filters: project, type, status, needs, ready. ready: true is the deterministic ready queue — open entries whose existing blocked_by targets are all resolved (dangling ids warn, never block). |
board_get_entry |
Full markdown of one entry by id (+ parsed frontmatter). |
board_update_entry |
Update frontmatter (status, needs, priority, blocked_by, parent) and/or append a body section; validate the status transition; rebuild the index. Optional comment: {author, text} appends a server-timestamped line to the entry's ## Comments section. |
board_rebuild |
Deterministically regenerate BOARD.md from entry files (P0→P3 ordering, ⊘ Q### when blocked, ↳ child rows under parents, resolved omitted). Idempotent. |
board_capture_finding |
Append a finding to the scratch inbox _sessions/mcp-<UTC-date>.md. |
board_claim |
Acquire an entry lock (shells out to board-claim-acquire.sh; 0=acquired, 1=contended, 2=stale). |
board_release |
Release an entry lock (shells out to board-claim-release.sh; 0=released, 3=owner mismatch/missing, 4=retries exhausted). |
board_remember |
Save a durable insight straight to learnings/L###-<slug>.md (source: remember) and rebuild the index — explicit intent bypasses the curator's recurrence-≥3 threshold. |
board_status |
Overview: per-type open counts, in_progress ids, blocked ids, the ready queue (capped at 20) with dangling-blocker warnings, un-promoted scratch count. |
All 12 tools from the spec are implemented; none were dropped.
Configuration
The server is published to PyPI as
engineering-board-mcp
(available with the v1.7.0 release), so the primary install is one uvx line — no clone,
no absolute path. The clone path still works everywhere and is the fallback.
Note (PyPI installs):
board_claim/board_releaseshell out to the plugin'shooks/scripts/board-claim-*.sh, which the PyPI package does not ship; on a PyPI install those two tools return a clean error unless the plugin (or a repo clone) is present. All other tools are self-contained.
Claude Code (CLI)
# primary — uvx (available with the v1.7.0 release)
claude mcp add engineering-board -- uvx engineering-board-mcp
Fallback — run from a clone:
git clone https://github.com/GhostlyGawd/engineering-board
claude mcp add engineering-board -- python3 "$(pwd)/engineering-board/mcp-server/engineering_board_mcp.py"
Codex CLI
Add to ~/.codex/config.toml:
[mcp_servers.engineering-board]
command = "uvx"
args = ["engineering-board-mcp"]
Or one line: codex mcp add engineering-board -- uvx engineering-board-mcp.
Gemini CLI
Add to ~/.gemini/settings.json (or per-project .gemini/settings.json):
{
"mcpServers": {
"engineering-board": {
"command": "uvx",
"args": ["engineering-board-mcp"]
}
}
}
Or one line: gemini mcp add engineering-board uvx engineering-board-mcp.
Cursor
Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json in the project:
{
"mcpServers": {
"engineering-board": {
"command": "uvx",
"args": ["engineering-board-mcp"]
}
}
}
Claude Desktop
Add to claude_desktop_config.json (macOS:
~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"engineering-board": {
"command": "uvx",
"args": ["engineering-board-mcp"]
}
}
}
(Clone fallback: "command": "python3", "args": ["/abs/path/to/engineering-board/mcp-server/engineering_board_mcp.py"].)
Bundled with the plugin (automatic)
Installing the engineering-board plugin auto-registers this server via the
repo-root .mcp.json, which resolves the script through
${CLAUDE_PLUGIN_ROOT}:
{
"mcpServers": {
"engineering-board": {
"command": "python3",
"args": ["${CLAUDE_PLUGIN_ROOT}/mcp-server/engineering_board_mcp.py"]
}
}
}
No separate install step is needed when the plugin is installed.
Distribution channels
The server ships from this repo tree (it shells out to sibling
hooks/scripts/board-claim-*.sh for locking; every other tool is
self-contained). Beyond cloning the repo, the packaged channels:
- PyPI (
engineering-board-mcp) — the uvx one-liner above. Published from v1.7.0 by the release workflow via PyPI trusted publishing (OIDC, no stored secret);pyproject.tomlis the package manifest. - MCP bundle (
.mcpb) —bash mcp-server/build-mcpb.shproducesdist/engineering-board-mcp.mcpb, a self-contained bundle (server + the hook scripts it calls +manifest.json) for one-click install in MCP-bundle-aware clients. The bundle is a release asset, not committed source. - MCP Registry — live — published as
io.github.GhostlyGawd/engineering-board;server.jsonis the registry manifest, pointing at the.mcpbrelease asset. Listings auto-syndicate to PulseMCP / Glama / mcp.so. - Smithery —
smithery.yamldescribes the stdio launch forsmithery mcp publish.
server.json, manifest.json, and smithery.yaml are version-locked to
plugin.json and validated by the MCP test suite so they cannot silently drift.
Multi-client: two clients, one board
Driving the same board from two MCP clients simultaneously (e.g. Claude Code
and Claude Desktop) is supported and CI-proven (eb-self Q001): the test suite
spawns two independent server processes on one board and races them for the
same entry's claim — exactly one acquires (exit_code 0), the other sees clean
contention (exit_code 1), and after the winner releases, the loser can
acquire. There is no cache layer to go stale: every read hits the same
committed markdown, and locking is the plugin's atomic mkdir claim protocol.
Use distinct session_ids per client (each client's claims are owned by its
session id).
Tests
bash mcp-server/run-tests.sh
test_mcp_server.py (pure python3, no deps) runs two suites:
- A real end-to-end stdio session — spawns the server as a subprocess and drives
initialize→notifications/initialized→tools/list→ severaltools/call, asserting on the JSON-RPC responses (including-32601/-32602error paths). - A full board lifecycle in a temp repo —
board_init→board_create_entry(bug + question + feature + learning) →board_list_entries→board_update_entry→board_rebuild→board_status→board_capture_finding→board_claim/board_release, asserting every created file passes the realhooks/scripts/board-validate-entry.sh.
Exit 0 on all-pass; non-zero with detail on the first failure.
Notes
- The server never writes to stdout except JSON-RPC responses (a hard MCP requirement).
- Entry filenames are
<ID>-<kebab-slug>.md(e.g.B001-export-drops-final-row.md). board_create_entryandboard_update_entryrebuildBOARD.mdas their final step so a freshly written entry's id is always present in the index (whichboard-validate-entry.shchecks).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file engineering_board_mcp-1.7.0.tar.gz.
File metadata
- Download URL: engineering_board_mcp-1.7.0.tar.gz
- Upload date:
- Size: 25.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d31da8179a3816fc13e8743060e43e9a967faf9d8b3fb2ce99dd785135f711b1
|
|
| MD5 |
c7ef291735645b4ad937f4ea2d2dcacb
|
|
| BLAKE2b-256 |
c8b5ff583adf763f7e3375fb93adc85e7a6cdcddd1bbeeff2f1a1e29a7f52f66
|
Provenance
The following attestation bundles were made for engineering_board_mcp-1.7.0.tar.gz:
Publisher:
release.yml on GhostlyGawd/engineering-board
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
engineering_board_mcp-1.7.0.tar.gz -
Subject digest:
d31da8179a3816fc13e8743060e43e9a967faf9d8b3fb2ce99dd785135f711b1 - Sigstore transparency entry: 2139201354
- Sigstore integration time:
-
Permalink:
GhostlyGawd/engineering-board@9a15833dabcd58a0d5c01a7e56eff5142fe37440 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/GhostlyGawd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9a15833dabcd58a0d5c01a7e56eff5142fe37440 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file engineering_board_mcp-1.7.0-py3-none-any.whl.
File metadata
- Download URL: engineering_board_mcp-1.7.0-py3-none-any.whl
- Upload date:
- Size: 25.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2fadcf908abe721f1d4287eb4563d1887e7a9902b2bb48de05352df7e0b8f5c0
|
|
| MD5 |
ab3df2206c0a380c7b5965fe66769409
|
|
| BLAKE2b-256 |
9bed362f022e8a39a58e08b5163c23bc550a9d9f1c93472f2b468dfa66d22ac0
|
Provenance
The following attestation bundles were made for engineering_board_mcp-1.7.0-py3-none-any.whl:
Publisher:
release.yml on GhostlyGawd/engineering-board
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
engineering_board_mcp-1.7.0-py3-none-any.whl -
Subject digest:
2fadcf908abe721f1d4287eb4563d1887e7a9902b2bb48de05352df7e0b8f5c0 - Sigstore transparency entry: 2139201363
- Sigstore integration time:
-
Permalink:
GhostlyGawd/engineering-board@9a15833dabcd58a0d5c01a7e56eff5142fe37440 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/GhostlyGawd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9a15833dabcd58a0d5c01a7e56eff5142fe37440 -
Trigger Event:
workflow_dispatch
-
Statement type: