Files
Gitea-Tools/docs/mcp-tool-inventory.md
T
sysadminandClaude Opus 5 92615f474b feat(control-plane): add authoritative native MCP fleet inventory (#949)
Every pre-existing runtime surface is per-process. gitea_get_runtime_context
and gitea_assess_master_parity describe only the server answering the call,
and gitea_assess_mcp_namespace_health accepts process, probe_result and
registered_tools from the caller, so it cannot constrain the caller. The
control-plane sessions table records allocator task sessions, not server
processes. Five self-reports of one revision therefore never proved that five
processes exist, that no sixth exists, or that all five share one client
cohort.

Add gitea_assess_fleet_inventory, a strictly read-only capability that takes
no evidence parameters. It combines two sources that must agree:

- a control-plane runtime registry row each server writes about itself,
  from the official entrypoint, immediately after the native transport bind;
- a process observation the answering server performs, never the caller.

A member is running only when both agree and the observed process predates
its registration, so configuration alone never counts and a recycled PID
cannot impersonate an exited server. Classification is a pure function of the
snapshot, so gitea-controller and gitea-reconciler return the same verdict.

Missing, duplicate, unexpected, stale and unregistered members are reported
in separate fields rather than collapsed into one error, because each needs a
different operator action. single_cohort is derived only from recorded cohort
identity and stays null when unknown, so matching revisions never establish a
cohort. Any unreadable registry, unavailable listing, unregistered process,
unknown cohort or unknown revision sets inventory_complete and
mutation_gate_satisfied false with a specific blocked_reason.

The capability performs no restart, reconnect, drain, lease mutation, issue
mutation or process termination, never terminates a duplicate, and never
manufactures restart evidence. The only signal sent is signal 0.

Also resolves the fleet namespace from the expected roster:
role_namespace_gate.infer_mcp_namespace recognises only author and reviewer
and echoes the profile name otherwise, which would have mislabelled the
controller, merger and reconciler members. Widening that shared helper is
controller role-metadata work owned by #950 and is deliberately not done here.

Schema v5 to v6 is additive and idempotent: one new table, no existing table,
tool signature or result field changed. Two control-plane tests that pinned
the schema version to the literal 5 now assert against SCHEMA_VERSION.

#950 (controller role metadata), #951 (restart receipts) and #952 (stale-lease
consistency) remain separate and untouched.

Tests: 118 new across tests/test_mcp_fleet_inventory.py,
tests/test_control_plane_db_server_runtimes.py and
tests/test_fleet_inventory_tool.py, covering every acceptance criterion
including the multi-LLM duplicate-server regression that motivated the issue.

Closes #949

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01NBaQKcRRKeKbZuhk72MhEf
2026-07-27 23:25:45 -04:00

6.1 KiB

Registered MCP tool inventory

This is the canonical list of tools the Gitea-Tools MCP server registers. It exists because documentation and the registered inventory drifted: the workflow documented a gitea_edit_issue tool that no namespace had ever registered, so a mutation could be planned against a tool that did not exist and only fail at execution time (#781).

The rule

Documentation must never name a tool an actor cannot reach.

Two guards enforce it, both in tests/test_issue_781_edit_issue_tool.py:

  1. The list below must equal the registered tool set exactly — sorted, no duplicates, nothing missing in either direction. Adding a tool without documenting it fails, and documenting a tool without registering it fails.
  2. Every backticked gitea_* / mcp_* identifier in skills/**/*.md must be a registered tool. Module and script names that share the prefix are listed explicitly in mcp_tool_inventory.NON_TOOL_IDENTIFIERS rather than being waved through by a looser pattern.

Updating this file

When you add or remove an @mcp.tool(), regenerate the block below:

PYTEST_CURRENT_TEST=1 venv/bin/python -c "
import mcp_server, mcp_tool_inventory
print(mcp_tool_inventory.render_inventory_block(
    mcp_server.mcp._tool_manager._tools))
"

Replace everything between the markers with that output. Do not hand-edit individual entries — the generator and the guard share one ordering rule.

Registered tools

Namespaces (gitea-tools, gitea-reviewer, gitea-merger, gitea-reconciler) register the same tool set; what differs per namespace is the execution profile that gates each call, not which tools exist.

  • gitea_abandon_workflow_lease
  • gitea_acquire_conflict_fix_lease
  • gitea_acquire_merger_pr_lease
  • gitea_acquire_reviewer_pr_lease
  • gitea_activate_profile
  • gitea_adopt_merger_pr_lease
  • gitea_adopt_workflow_lease
  • gitea_allocate_next_work
  • gitea_assess_already_landed_reconciliation
  • gitea_assess_conflict_fix_classification
  • gitea_assess_conflict_fix_push
  • gitea_assess_fleet_inventory
  • gitea_assess_gitea_operation_path
  • gitea_assess_master_parity
  • gitea_assess_mcp_namespace_health
  • gitea_assess_pr_sync_status
  • gitea_assess_review_merge_state_machine
  • gitea_assess_reviewer_pr_lease
  • gitea_assess_terminal_label_hygiene
  • gitea_assess_work_issue_duplicate
  • gitea_assess_worktree_cleanup_integrity
  • gitea_audit_config
  • gitea_audit_runtime_recovery_contamination
  • gitea_audit_stable_branch_contamination
  • gitea_audit_worktree_cleanup
  • gitea_authorize_reconciliation_cleanup_phase
  • gitea_authorize_review_correction
  • gitea_bootstrap_author_issue_worktree
  • gitea_capability_stop_terminal_report
  • gitea_capture_branches_worktree_snapshot
  • gitea_check_pr_eligibility
  • gitea_cleanup_merged_pr_branch
  • gitea_cleanup_obsolete_reviewer_comment_lease
  • gitea_cleanup_post_merge_moot_lease
  • gitea_cleanup_stale_claims
  • gitea_cleanup_stale_review_decision_lock
  • gitea_cleanup_terminal_pr_labels
  • gitea_close_issue
  • gitea_commit_files
  • gitea_consume_irrecoverable_decision_lock_provenance
  • gitea_create_issue
  • gitea_create_issue_comment
  • gitea_create_label
  • gitea_create_pr
  • gitea_delete_branch
  • gitea_diagnose_review_decision_lock
  • gitea_diagnose_reviewer_pr_lease_handoff
  • gitea_diagnose_terminal
  • gitea_dry_run_pr_review
  • gitea_edit_issue
  • gitea_edit_pr
  • gitea_expire_workflow_leases
  • gitea_get_authenticated_user
  • gitea_get_current_user
  • gitea_get_file
  • gitea_get_pr_review_feedback
  • gitea_get_profile
  • gitea_get_runtime_context
  • gitea_get_shell_health
  • gitea_heartbeat_issue_lock
  • gitea_heartbeat_reviewer_pr_lease
  • gitea_inspect_workflow_lease
  • gitea_issue_irrecoverable_provenance_authorization
  • gitea_list_dependency_edges
  • gitea_list_issue_comments
  • gitea_list_issues
  • gitea_list_labels
  • gitea_list_profiles
  • gitea_list_prs
  • gitea_list_workflow_leases
  • gitea_load_review_workflow
  • gitea_lock_issue
  • gitea_mark_final_review_decision
  • gitea_mark_issue
  • gitea_merge_pr
  • gitea_mirror_refs
  • gitea_observability_link_issue
  • gitea_observability_list_projects
  • gitea_observability_reconcile_incident
  • gitea_post_heartbeat
  • gitea_publish_unpublished_issue_branch
  • gitea_quarantine_contaminated_review
  • gitea_reclaim_expired_workflow_lease
  • gitea_reconcile_already_landed_pr
  • gitea_reconcile_issue_claims
  • gitea_reconcile_merged_cleanups
  • gitea_reconcile_superseded_by_merged_pr
  • gitea_record_daemon_process_kill_attempt
  • gitea_record_irrecoverable_decision_lock_provenance
  • gitea_record_pre_review_command
  • gitea_record_shell_spawn_outcome
  • gitea_record_stable_branch_push_attempt
  • gitea_release_merger_pr_lease
  • gitea_release_reviewer_pr_lease
  • gitea_release_workflow_lease
  • gitea_request_mcp_reconnect
  • gitea_request_mcp_restart
  • gitea_resolve_task_capability
  • gitea_resume_review_draft
  • gitea_review_pr
  • gitea_route_task_session
  • gitea_save_review_draft
  • gitea_scan_already_landed_open_prs
  • gitea_sentry_get_issue_events
  • gitea_sentry_link_gitea_issue
  • gitea_sentry_list_issues
  • gitea_sentry_reconcile_issue
  • gitea_sentry_watchdog
  • gitea_set_issue_labels
  • gitea_submit_pr_review
  • gitea_update_pr_branch_by_merge
  • gitea_validate_review_final_report
  • gitea_view_issue
  • gitea_view_pr
  • gitea_whoami
  • gitea_workflow_dashboard
  • mcp_check_workflow_skill_preflight
  • mcp_get_control_plane_guide
  • mcp_get_skill_guide
  • mcp_list_project_skills

Issue-content editing

gitea_edit_issue is the only path that changes an issue's title or body. It PATCHes the issue endpoint, refuses a pull-request number, sends only the fields the caller named, and proves the result by read-after-write — including that state, labels, assignees, and milestone did not move.

gitea_edit_pr remains pull-request-only. The two paths never merge: a single tool that accepted either kind would make the narrower capability reachable through the wider one.