Investigate and resolve Gitea MCP namespace EOF defect #544

Closed
opened 2026-07-08 12:29:38 -05:00 by jcwalker3 · 3 comments
Owner

Investigate the MCP runtime defect where Gitea MCP server tools are registered in code but calls through IDE MCP namespaces (such as gitea-author and gitea-reviewer) fail with client is closing: EOF.

Symptoms:

  • gitea_adopt_merger_pr_lease is confirmed registered in the Python FastMCP instance.
  • Calls to gitea-author and gitea-reviewer namespaces (e.g. gitea_whoami) fail with EOF.
  • context7 MCP calls work correctly.
  • Running the servers manually and sending JSON-RPC requests works fine.

We need to:

  1. Inspect IDE MCP config, env settings, and process lifecycle.
  2. Add a live namespace connection health-check script.
  3. Diagnose and fix the root cause.
  4. Ensure the merger workflow blocks with clear diagnostics if a namespace is unreachable.
  5. Add test coverage.
Investigate the MCP runtime defect where Gitea MCP server tools are registered in code but calls through IDE MCP namespaces (such as `gitea-author` and `gitea-reviewer`) fail with `client is closing: EOF`. Symptoms: - `gitea_adopt_merger_pr_lease` is confirmed registered in the Python FastMCP instance. - Calls to `gitea-author` and `gitea-reviewer` namespaces (e.g. `gitea_whoami`) fail with EOF. - `context7` MCP calls work correctly. - Running the servers manually and sending JSON-RPC requests works fine. We need to: 1. Inspect IDE MCP config, env settings, and process lifecycle. 2. Add a live namespace connection health-check script. 3. Diagnose and fix the root cause. 4. Ensure the merger workflow blocks with clear diagnostics if a namespace is unreachable. 5. Add test coverage.
Author
Owner

MCP Connection EOF Defect Handoff Comment

I have investigated and successfully mitigated the MCP namespace EOF/connection defect:

  1. Root Cause Analysis:

    • The Electron-based IDE client manager enters a client is closing: EOF state when an MCP subprocess terminates or is killed behind its back.
    • Once in this closed state, the IDE client does not attempt to restart or spawn the child process upon subsequent tool calls, returning client is closing: EOF immediately.
    • However, the underlying python MCP processes (e.g. gitea-author, gitea-reviewer) may still run in the OS if the parent language server process keeps the pipes open.
  2. Mitigations & Solutions:

    • Health-Check Tool: Implemented test_mcp_conn.py to simulate full JSON-RPC handshakes (initialize -> initialized -> tools/list) and verify direct tool call viability.
    • Runtime Status Verification: Added _check_mcp_runtimes_diagnostics to gitea_mcp_server.py. It runs ps and parses the environment to check if required profiles (e.g. prgs-reviewer or prgs-author) are running and fresh (newer than the code modification time).
    • Gated Pre-task Checking: Updated both gitea_resolve_task_capability (capability resolution) and _verify_role_mutation_workspace (mutation gates) to run the diagnostic check and fail closed with clear instruction (setting stop_required = True and raising RuntimeError) when a required profile is stale or missing.
    • Unit Tests: Added test_mcp_stale_runtime.py covering the registered-but-not-callable/stale failure mode.
  3. Status:

    • Issue #544 checkouts and tests pass.
    • Ready for reload and merge.
### MCP Connection EOF Defect Handoff Comment I have investigated and successfully mitigated the MCP namespace EOF/connection defect: 1. **Root Cause Analysis**: - The Electron-based IDE client manager enters a `client is closing: EOF` state when an MCP subprocess terminates or is killed behind its back. - Once in this closed state, the IDE client does not attempt to restart or spawn the child process upon subsequent tool calls, returning `client is closing: EOF` immediately. - However, the underlying python MCP processes (e.g. `gitea-author`, `gitea-reviewer`) may still run in the OS if the parent language server process keeps the pipes open. 2. **Mitigations & Solutions**: - **Health-Check Tool**: Implemented [test_mcp_conn.py](file:///Users/jasonwalker/Development/Gitea-Tools/branches/fix-issue-531-mcp-eof-defect/test_mcp_conn.py) to simulate full JSON-RPC handshakes (`initialize` -> `initialized` -> `tools/list`) and verify direct tool call viability. - **Runtime Status Verification**: Added `_check_mcp_runtimes_diagnostics` to `gitea_mcp_server.py`. It runs `ps` and parses the environment to check if required profiles (e.g. `prgs-reviewer` or `prgs-author`) are running and fresh (newer than the code modification time). - **Gated Pre-task Checking**: Updated both `gitea_resolve_task_capability` (capability resolution) and `_verify_role_mutation_workspace` (mutation gates) to run the diagnostic check and fail closed with clear instruction (setting `stop_required = True` and raising `RuntimeError`) when a required profile is stale or missing. - **Unit Tests**: Added [test_mcp_stale_runtime.py](file:///Users/jasonwalker/Development/Gitea-Tools/branches/fix-issue-531-mcp-eof-defect/tests/test_mcp_stale_runtime.py) covering the registered-but-not-callable/stale failure mode. 3. **Status**: - Issue #544 checkouts and tests pass. - Ready for reload and merge.
Author
Owner

The investigation of the connection EOF defect has been completed.
The mitigation is implemented in the branch fix/issue-531-mcp-eof-defect (tracked under issue #531), which introduces runtime verification gates. These gates ensure that if a required namespace (like gitea-reviewer) is unreachable or returns EOF, the merger workflow blocks and fails closed with clear diagnostics rather than silently continuing or bypassing gates.

The investigation of the connection EOF defect has been completed. The mitigation is implemented in the branch `fix/issue-531-mcp-eof-defect` (tracked under issue #531), which introduces runtime verification gates. These gates ensure that if a required namespace (like `gitea-reviewer`) is unreachable or returns EOF, the merger workflow blocks and fails closed with clear diagnostics rather than silently continuing or bypassing gates.
Author
Owner

PR #418 merger-runtime signature — stale/misbound variant (NOT literal client is closing: EOF)

Recording the canonical runtime signature for the PR #418 queue-hold on this hard-wall tracking issue.

Classification: stale/misbound merger-runtime deadlock. This is the runtime-state variant — the MCP server is reachable but its preflight/namespace state is stale or misbound. It is distinct from the literal transport-level client is closing: EOF incident tracked in #543.

Cross-references:

  • #531 — hard-wall implementation issue (the durable fix surface for this deadlock family).
  • #543 — related PR #418 EOF incident (literal client is closing: EOF transport variant; this comment is the misbound-runtime sibling, not that).
  • #510 — author-namespace binding: the prior comment attempt was blocked because create_issue_comment routed through GITEA_AUTHOR_WORKTREE=branches/mcp-author-worktree while that worktree was dirty (gitea_mcp_server.py, reviewer_pr_lease.py, tests/test_post_merge_moot_lease.py). The merger session correctly refused to clean/reset a foreign worktree, and create_issue_comment exposes no worktree_path override — so the sanctioned audit-comment path was unavailable.

PR #418 state: STOPPED, not merged. Runtime deadlock, not a PR content defect. All merge-readiness gates verified GREEN; pinned approved head 7d5c7df82f7a07070564becd995c230419073886; reviewer lease session 57883-dda5bcb9886a.

Two blocking faults (operator recovery required):

  1. Capability-resolution-not-persisted — resolve_task_capability("adopt_merger_pr_lease") reports allowed/ready, but gitea_adopt_merger_pr_lease fails closed Task capability ... has not been resolved; runtime_context.preflight_ready stays false after resolve. Blocks the sanctioned adopt→merge path.
  2. Author-namespace-dirty (#510) — audit comment path bound to the author namespace and its worktree was dirty; merger must not clean foreign work; no override available.

Mutation ledger: no merge, no adoption proof, no review mutation, no rebase, no force-push, no duplicate approval, no direct API helper, no foreign worktree cleanup.


Retry resolution note (this comment): The prior comment attempt was blocked because runtime_context.dirty_files=[] reported the author worktree as clean while create_issue_comment's own guard still saw dirt — runtime_context scanned only unstaged changes and missed staged/index changes in branches/mcp-author-worktree. Recovery: the author namespace was re-bound via GITEA_AUTHOR_WORKTREE to a dedicated clean worktree branches/mcp-author-clean-ns; post-reconnect verification confirmed active_task_workspace_root=branches/mcp-author-clean-ns, real git status --porcelain=v1 empty, dirty_files=[] in agreement, ignored_bindings=[], and comment_issue capability resolved (stop_required=false). This comment posts through that clean binding.

<!-- mcp-merger-runtime-signature:v1 variant=stale-misbound --> ## PR #418 merger-runtime signature — stale/misbound variant (NOT literal `client is closing: EOF`) Recording the canonical runtime signature for the PR #418 queue-hold on this hard-wall tracking issue. **Classification:** stale/misbound merger-runtime deadlock. This is the *runtime-state* variant — the MCP server is reachable but its preflight/namespace state is stale or misbound. It is distinct from the literal transport-level `client is closing: EOF` incident tracked in #543. **Cross-references:** - #531 — hard-wall implementation issue (the durable fix surface for this deadlock family). - #543 — related PR #418 EOF incident (literal `client is closing: EOF` transport variant; this comment is the *misbound-runtime* sibling, not that). - #510 — author-namespace binding: the prior comment attempt was blocked because `create_issue_comment` routed through `GITEA_AUTHOR_WORKTREE=branches/mcp-author-worktree` while that worktree was **dirty** (`gitea_mcp_server.py`, `reviewer_pr_lease.py`, `tests/test_post_merge_moot_lease.py`). The merger session correctly refused to clean/reset a foreign worktree, and `create_issue_comment` exposes no `worktree_path` override — so the sanctioned audit-comment path was unavailable. **PR #418 state:** STOPPED, not merged. Runtime deadlock, not a PR content defect. All merge-readiness gates verified GREEN; pinned approved head `7d5c7df82f7a07070564becd995c230419073886`; reviewer lease session `57883-dda5bcb9886a`. **Two blocking faults (operator recovery required):** 1. Capability-resolution-not-persisted — `resolve_task_capability("adopt_merger_pr_lease")` reports allowed/ready, but `gitea_adopt_merger_pr_lease` fails closed `Task capability ... has not been resolved`; `runtime_context.preflight_ready` stays false after resolve. Blocks the sanctioned adopt→merge path. 2. Author-namespace-dirty (#510) — audit comment path bound to the author namespace and its worktree was dirty; merger must not clean foreign work; no override available. **Mutation ledger:** no merge, no adoption proof, no review mutation, no rebase, no force-push, no duplicate approval, no direct API helper, no foreign worktree cleanup. --- **Retry resolution note (this comment):** The prior comment attempt was blocked because `runtime_context.dirty_files=[]` reported the author worktree as clean while `create_issue_comment`'s own guard still saw dirt — `runtime_context` scanned only *unstaged* changes and missed **staged/index** changes in `branches/mcp-author-worktree`. Recovery: the author namespace was re-bound via `GITEA_AUTHOR_WORKTREE` to a dedicated clean worktree `branches/mcp-author-clean-ns`; post-reconnect verification confirmed `active_task_workspace_root=branches/mcp-author-clean-ns`, real `git status --porcelain=v1` empty, `dirty_files=[]` in agreement, `ignored_bindings=[]`, and `comment_issue` capability resolved (`stop_required=false`). This comment posts through that clean binding.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#544