Files
Gitea-Tools/docs/mcp-tool-inventory.md
T
sysadminandClaude Opus 4.8 0589ec8069 feat(control-plane): persist allocator dependency edges as durable state (Closes #784)
Umbrella #628 scope item 6 requires dependencies to be durable structured
state carrying source, target, type, blocking condition, completion
condition, current state, and evidence. Nothing stored any of that.

Dependency knowledge existed only as a per-run computation:
allocator_dependencies re-parsed the Depends: declaration out of every
issue body on every allocation, _allocator_candidates_from_gitea resolved
each reference against live issue state, and the result collapsed into two
in-memory WorkCandidate fields that classify_skip consumed and discarded.
Three consequences followed. Nothing could answer "what is waiting on #N"
without re-listing every open issue and re-parsing every body, so the
reverse edge automatic resumption needs did not exist in any form. Only
issue-blocked-by-issue was expressible, leaving the other six #628
relationships with nowhere to live. And no observation was recorded, so a
transient lookup failure and a real block were indistinguishable after the
fact.

Add the store:

- dependency_edges table under schema v4. Creating the table is itself the
  v3 to v4 migration: additive, idempotent, and it never touches the
  existing tables. Uniqueness is (scope, source, target, edge_type), so
  re-observation updates one row rather than appending duplicates.
- dependency_graph.py owns the vocabulary: the seven #628 relationship
  types, the three states, and fail-closed normalization for both plus
  endpoint kinds. An unrecognized value writes nothing rather than landing
  as unqueryable free text. Evidence is sanitized before storage, so no
  credential or endpoint URL can be persisted or read back.
- upsert_dependency_edge, list_dependency_edges, and
  record_dependency_edge_observation on ControlPlaneDB. Filtering by target
  makes reverse lookup a single query. State transitions append to the
  existing events table rather than a parallel audit table.
- The allocator persists what it already resolved. States map one-to-one
  from the resolver's met/unmet/unavailable partitions, so nothing is
  re-classified and unavailable evidence is never recorded as met.
- gitea_list_dependency_edges exposes stored edges read-only, gated on
  gitea.read, and is added to the documented inventory the #781 drift guard
  checks.

Selection is deliberately untouched: classify_skip still consumes the
in-memory dependency_unmet field. The write is best-effort and reports
failures through reasons, so a broken or absent store leaves allocation
behaving exactly as it did before — proven by allocating the same candidate
set through a store whose writes all raise and comparing the selection,
skip set, and candidate count.

Automatic blocking and resumption (#628 item 7), non-issue edge creation,
and defect auto-linking are later slices; this one only makes the graph
durable and queryable.

Tests: 31 new cases covering fresh-schema creation, a real v3-to-v4
migration with row retention, idempotent re-migration, enum rejection,
upsert idempotence, forward and reverse lookup, scope isolation, transition
events, redaction at rest, live allocation-run ingestion, write-failure
tolerance, and the tool's permission gate.

Verification: 4126 passed in the branch worktree. The 11 failures in
test_commit_payloads, test_issue_702_review_findings_f1_f6, test_mcp_server,
test_post_merge_moot_lease, and test_reconciler_supersession_close reproduce
identically on a clean detached checkout of master at 300e8acd, so they are
pre-existing and proven by baseline run, not introduced here.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-21 18:07:21 -04:00

5.8 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_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_stable_branch_contamination
  • gitea_audit_worktree_cleanup
  • gitea_authorize_reconciliation_cleanup_phase
  • gitea_authorize_review_correction
  • 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_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_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_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_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.