Skip to content

feat(mcp): register headroom MCP server with dsh (DeepSeek Harness) - #3036

Open
Zenjibad wants to merge 31 commits into
headroomlabs-ai:mainfrom
Zenjibad:feat/dsh-mcp
Open

feat(mcp): register headroom MCP server with dsh (DeepSeek Harness)#3036
Zenjibad wants to merge 31 commits into
headroomlabs-ai:mainfrom
Zenjibad:feat/dsh-mcp

Conversation

@Zenjibad

@Zenjibad Zenjibad commented Aug 14, 2026

Copy link
Copy Markdown

Description

Adds a DshRegistrar so headroom mcp install also registers headroom's MCP server (headroom_compress / headroom_retrieve / headroom_stats) with DeepSeek Harness. It writes the @deepseek-ai/dsh-mcp-client row into dsh's $DSH_HOME/cordis.patch.yml.

Depends on #2994.

Closes # (no issue)

Type of Change

  • New feature (non-breaking change that adds functionality)

Changes Made

  • New headroom/mcp_registry/dsh.pyDshRegistrar (detect/register/unregister, marker-fenced YAML block).
  • headroom/mcp_registry/install.py — register DshRegistrar in get_all_registrars().
  • New tests/test_mcp_registry_dsh.py — 7 unit tests.

Testing

  • Unit tests pass (pytest)
  • Linting passes (ruff check .)
  • Formatting passes (ruff format --check .)
  • New tests added for new functionality

Test Output

$ uv run python -m pytest tests/test_mcp_registry_dsh.py -q
7 passed

$ uv run ruff check headroom/mcp_registry/dsh.py headroom/mcp_registry/install.py tests/test_mcp_registry_dsh.py
All checks passed!

Real Behavior Proof

  • Environment: Windows 10, Python 3.13.
  • Exact command / steps: uv run python -m pytest tests/test_mcp_registry_dsh.py -q; a live DshRegistrar().register_server(...) against a temp $DSH_HOME; and dsh --profile headless --patch <patch>.
  • Observed result: 7/7 unit tests pass; the YAML matches dsh's memorix.cordis.yml shape; get_server round-trips. Live boot: @deepseek-ai/dsh-mcp-client spawns headroom mcp serve; the model lists mcp__headroom__headroom_compress|retrieve|stats and, with a real key, calls headroom_compress and returns the compressed output + hash (a76e1fa6…).
  • Not tested: headroom_retrieve/headroom_stats against a live proxy (they need the proxy running).

Runtime Rollout Safety

  • Rollout-managed feature(s): none.
  • Minimum rollout channel: n/a.
  • Stable/default behavior changed: no — the new registrar is additive; existing registrars untouched.
  • Kill switch / disable path: headroom mcp uninstall.
  • Unsafe override required: no.
  • Qualification impact: none.
  • Rollback path: headroom mcp uninstall.

Review Readiness

  • I have performed a self-review
  • This PR is ready for human review

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my feature works
  • New and existing unit tests pass locally with my changes
  • I did not edit CHANGELOG.md

Additional Notes

  • Depends on feat(dsh): add DeepSeek Harness wrap support #2994 — merge that first.
  • @deepseek-ai/dsh-mcp-client ships with @deepseek-ai/dsh (verified — a dependency, no separate install). headroom mcp serve needs the [mcp] extra (included in the [proxy] extra); retrieve/stats need the proxy running.

Ali and others added 25 commits August 13, 2026 20:00

@JerrettDavis JerrettDavis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The happy-path registrar tests pass, but the file parser needs to fail safely before this is ready. _read_block() assumes that any start marker has a matching end marker and calls text.index(_MARKER_END, start) unguarded. A realistic interrupted/truncated prior write makes both headroom mcp install and uninstall raise ValueError instead of returning a controlled FAILED result. I reproduced this with a cordis.patch.yml containing only # --- Headroom MCP server ---; register_server() crashes at dsh.py:77.

Malformed fenced YAML is also currently treated as “no existing server,” after which registration appends a second managed block. The first corrupt block remains first, so future reads keep seeing it and the user file is made harder to recover. Please treat an incomplete or unparsable owned block as corrupt managed state: refuse to append/overwrite without explicit force (and return a useful FAILED/MISMATCH detail), make unregister handle it deliberately, and add regressions for an unmatched start marker and malformed fenced YAML while proving unrelated patch bytes remain unchanged. Since this mutates a user-owned config, an atomic replacement for rewrite paths would also avoid creating the exact truncated state on interruption.

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

PR governance

This PR follows the template and is marked ready for human review.

@Zenjibad

Copy link
Copy Markdown
Author

Addressed the review feedback:

  • _read_managed_block() now distinguishes absent / clean / corrupt state — an unmatched start marker (truncated write) no longer raises ValueError.
  • Malformed fenced YAML (and a block missing the headroom entry) is now treated as corrupt managed state, not "no existing server" — register_server returns FAILED without force instead of appending a second block.
  • unregister_server now removes a truncated block (start marker to EOF) deliberately and preserves unrelated bytes exactly.
  • All write paths use atomic temp-file + os.replace.

Regressions added in tests/test_mcp_registry_dsh.py:

  • test_register_fails_on_truncated_block
  • test_register_fails_on_malformed_yaml_block
  • test_force_overwrites_truncated_block
  • test_unregister_preserves_unrelated_bytes_exactly
  • test_unregister_truncated_block_preserves_unrelated

12 tests pass; ruff check clean; mypy headroom/mcp_registry/ clean.

@Zenjibad
Zenjibad marked this pull request as ready for review August 14, 2026 20:11
@Zenjibad
Zenjibad requested a review from JerrettDavis August 14, 2026 20:11
@github-actions github-actions Bot added status: needs author action Pull request body or readiness checklist still needs author updates status: ready for review Pull request body is complete and the author marked it ready for human review and removed status: needs author action Pull request body or readiness checklist still needs author updates status: ready for review Pull request body is complete and the author marked it ready for human review labels Aug 14, 2026
@Zenjibad Zenjibad changed the title feat(mcp): register headroom MCP server with dsh feat(mcp): register headroom MCP server with dsh (DeepSeek Harness) Aug 14, 2026
@github-actions github-actions Bot added status: ready for review Pull request body is complete and the author marked it ready for human review status: needs author action Pull request body or readiness checklist still needs author updates and removed status: ready for review Pull request body is complete and the author marked it ready for human review status: needs author action Pull request body or readiness checklist still needs author updates labels Aug 14, 2026
@github-actions github-actions Bot added status: ready for review Pull request body is complete and the author marked it ready for human review and removed status: ready for review Pull request body is complete and the author marked it ready for human review labels Aug 14, 2026
@Zenjibad

Copy link
Copy Markdown
Author

Also added full Serena parity on top of the corrupt-state fixes (addressing the same reviewer thread, plus the 'full parity' scope):

  • DshRegistrar is now a generic multi-server registrar (headroom + serena) — one marker-fenced insert list keyed id = mcp-{name}, atomic writes, corrupt-state handling preserved.
  • headroom wrap dsh registers Serena code memory (--code-memory, context agent); unwrap dsh removes it (ledger-guarded).
  • DshRegistrar exported from headroom.mcp_registry (was missing).
  • 16 tests (multi-server round-trip, sibling byte-exact preservation, per-name idempotency, corrupt-state regressions); ruff/format/mypy clean.

@github-actions github-actions Bot added status: ready for review Pull request body is complete and the author marked it ready for human review and removed status: ready for review Pull request body is complete and the author marked it ready for human review labels Aug 14, 2026
@codecov-commenter

codecov-commenter commented Aug 15, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 78.49462% with 60 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
headroom/mcp_registry/dsh.py 81.41% 14 Missing and 15 partials ⚠️
headroom/cli/wrap.py 56.25% 19 Missing and 9 partials ⚠️
headroom/providers/dsh/runtime.py 92.30% 1 Missing and 1 partial ⚠️
headroom/providers/registry.py 83.33% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

The marker-fenced block is appended directly after the existing patch
text. When cordis.patch.yml does not end with a newline, the start marker
glues onto the last line ('...3080# --- Headroom MCP server ---') and the
marker becomes part of a YAML comment. Normalize the base text to end with
a newline before appending in both register_server and unregister_server.
@github-actions github-actions Bot added status: ready for review Pull request body is complete and the author marked it ready for human review and removed status: ready for review Pull request body is complete and the author marked it ready for human review labels Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants