Files
Gitea-Tools/docs/mcp-namespace-health.md
T
sysadmin 2b3f5baaeb fix(mcp): invalidate review session state on cross-profile activation (Closes #690)
A mid-run profile switch (reviewer -> author -> reviewer) left workflow-load
proof, reviewer lease binding, the review decision lock, live namespace
health, and preflight identity/capability stamps intact, so a formal verdict
could be recorded under contaminated session state.

- gitea_activate_profile now invalidates all review-critical session state
  on a cross-profile switch, in memory and in durable state keyed by either
  profile identity, and reports the invalidation + re-preflight requirement.
- Full reviewer preflight (whoami, load_review_workflow,
  resolve_task_capability(review_pr), head re-pin, lease re-acquire) is
  required before any formal verdict after a switch; switching back cannot
  resurrect the stale run.
- Namespace provenance: optional launcher-declared GITEA_MCP_NAMESPACE is
  reported by whoami/runtime context/capability resolution, and a declared
  namespace that disagrees with a task's required namespace fails closed.
- Docs: supported pattern is separate session/namespace per role, not
  in-process profile hopping mid-review.
2026-07-25 19:17:19 -04:00

4.6 KiB

MCP namespace health diagnostics (#543)

Gitea MCP tools can be registered in the Python FastMCP server while the IDE's live MCP namespace is still unusable. The failure usually appears as client is closing: EOF, transport closed, or an empty response when calling a tool such as gitea_whoami.

Do not treat static tool registration as proof that review or merge workflows can proceed. A reviewer or merger flow must have client-namespace evidence that the required tool is callable through the configured IDE MCP namespace.

Probe sources (do not confuse them)

Source How obtained Proves IDE namespace?
client_namespace Tool call through the IDE-managed MCP client Yes
offline_spawn test_mcp_conn.py subprocess JSON-RPC handshake No (offline only)

gitea_assess_mcp_namespace_health accepts probe_source and only sets ide_namespace_proven=true for client_namespace success. Offline spawn success never clears review/merge mutation gates.

Client-namespace health check (canonical)

  1. Through the IDE client, call a cheap tool on the target namespace (gitea_whoami or gitea_list_profiles).
  2. Feed the live result into:
gitea_assess_mcp_namespace_health(
    namespace="gitea-merger",          # or reviewer / author / tools
    registered_tools=[...],            # optional static list
    probe_result={"success": true, "result": {...}},
    probe_source="client_namespace",
)
  1. A healthy client-namespace assessment is recorded in the MCP session and consulted by live gitea_submit_pr_review / gitea_merge_pr gates.
  2. If the probe fails with EOF, recover via client reconnect only — see docs/mcp-namespace-eof-recovery.md. Do not kill PIDs or touch MCP config mtimes as a recovery procedure.

Offline spawn probe (non-authoritative)

python3 test_mcp_conn.py --config ~/.gemini/config/mcp_config.json

This script spawns a separate server process from config, performs JSON-RPC initializetools/listtools/call, and classifies the result with probe_source=offline_spawn. Use it for offline debugging of launch command / registration. It does not prove the IDE-managed namespace is healthy.

By default the script checks:

Namespace Required tool
gitea-author gitea_whoami
gitea-reviewer gitea_whoami
gitea-merger gitea_whoami
gitea-tools gitea_list_profiles

Recovery (canonical)

When a namespace returns EOF, follow docs/mcp-namespace-eof-recovery.md in order:

  1. Confirm blast radius (Gitea namespace vs all MCP servers).
  2. Reconnect the namespace through the client (IDE reconnect / relaunch).
  3. Do not repair via shell imports, raw JSON-RPC, PID kills, or config mtime touches — those do not restore the client's closed transport.
  4. Re-verify the specific required tool through the target namespace.
  5. Resume review/merge only after a successful client_namespace assessment.

Enforcement

  1. State machine (read-only): feed blocks_merge_workflow from a client_namespace assessment into gitea_assess_review_merge_state_machine(live_namespace_broken=...).
  2. Live mutations: gitea_submit_pr_review and gitea_merge_pr call _live_namespace_health_gate and fail closed when the session has a recorded unhealthy or non-client probe for the required namespace (gitea-reviewer for review, gitea-merger for merge).

When blocked, repair the IDE namespace and re-record a healthy client_namespace assessment before retrying the mutation.

Namespace provenance (#690)

A server process cannot derive the name of the client-managed namespace it is registered under, so the launcher may declare it with the GITEA_MCP_NAMESPACE environment variable (e.g. GITEA_MCP_NAMESPACE=gitea-reviewer).

  • gitea_whoami, gitea_get_runtime_context, and gitea_resolve_task_capability report namespace_provenance: the declared client namespace, the active execution profile, and — for tasks with a required namespace (review_pr/submit_reviewgitea-reviewer, merge_prgitea-merger) — a mismatch verdict.
  • A declared namespace that disagrees with the requested task's required namespace fails closed (allowed_in_current_session=false with a STOP guidance entry).
  • An undeclared namespace is reported as namespace_source="unknown" and is never treated as proof either way.
  • A profile switch via gitea_activate_profile clears all recorded live namespace-health assessments; re-probe through the client before further review/merge mutations.