Summary
The GitHub guard currently models a broader write surface than the official github-mcp-server README exposes, but that coverage is now stale in 39 places relative to the upstream MCP tool list. These entries still appear in guards/github-guard/rust-guard/src/tools.rs, yet they no longer appear in the upstream MCP server's published tool catalog. That drift makes the guard harder to audit and can hide real gaps behind synthetic or obsolete entries.
In addition, the stale entries largely correspond to GitHub CLI-only mutations. Those operations are still reachable via gh, but they are not represented by current upstream MCP tools, so they should be tracked explicitly as synthetic CLI coverage rather than blended into the MCP tool inventory.
- MCP tools scanned: 89
- CLI write commands scanned: 39
- Guard-covered write tools (
tools.rs): 141
- Tools with explicit DIFC rules (
tool_rules.rs): 257 string-matched names
- New gaps found this run: 39
Stale Guard Entries (tools.rs)
These entries are present in WRITE_OPERATIONS / READ_WRITE_OPERATIONS but are not present in the upstream github-mcp-server README tool list:
| Guard Entry |
Current Role |
Likely Source |
Recommended Action |
add_project_item |
deprecated alias |
legacy/synthetic Projects mapping |
Remove from canonical write lists or move to an explicit synthetic/alias section with comments and tests |
archive_repository |
blocked write |
CLI-only repo command |
Keep only if synthetic CLI coverage is intentional; otherwise remove from MCP-derived inventory |
cancel_workflow_run |
synthetic write |
gh run cancel |
Move to dedicated CLI synthetic coverage set |
copy_project |
synthetic write |
gh project copy |
Move to dedicated CLI synthetic coverage set |
create_agent_task |
blocked write |
gh agent-task create |
Keep only in a clearly named CLI-only/blocked section |
create_project |
synthetic write |
gh project create |
Move to dedicated CLI synthetic coverage set |
delete_actions_cache |
synthetic write |
gh cache delete |
Move to dedicated CLI synthetic coverage set |
delete_gist |
synthetic write |
gh gist delete |
Move to dedicated CLI synthetic coverage set |
delete_project |
synthetic write |
gh project delete |
Move to dedicated CLI synthetic coverage set |
delete_project_item |
deprecated alias |
legacy/synthetic Projects mapping |
Remove alias or isolate under compatibility handling |
delete_secret |
synthetic write |
gh secret delete |
Move to dedicated CLI synthetic coverage set |
delete_variable |
synthetic write |
gh variable delete |
Move to dedicated CLI synthetic coverage set |
delete_workflow_run_logs |
deprecated alias |
legacy workflow mapping |
Remove if no longer used by guard callers |
disable_workflow |
synthetic write |
gh workflow disable |
Move to dedicated CLI synthetic coverage set |
enable_toolset |
synthetic capability write |
guard/runtime-specific |
Keep outside upstream MCP comparison path |
enable_workflow |
synthetic write |
gh workflow enable |
Move to dedicated CLI synthetic coverage set |
force_cancel_workflow_run |
synthetic write |
gh run cancel --force |
Move to dedicated CLI synthetic coverage set |
link_project |
synthetic write |
gh project link |
Move to dedicated CLI synthetic coverage set |
mark_pull_request_as_draft |
synthetic write |
gh pr ready --undo |
Move to dedicated CLI synthetic coverage set |
mark_pull_request_as_ready_for_review |
synthetic write |
gh pr ready |
Move to dedicated CLI synthetic coverage set |
pin_issue |
synthetic write |
gh issue pin |
Move to dedicated CLI synthetic coverage set |
rebuild_codespace |
synthetic write |
gh codespace rebuild |
Move to dedicated CLI synthetic coverage set |
rename_repository |
blocked write |
gh repo rename |
Keep only in explicit CLI-only blocked coverage |
rerun_failed_jobs |
synthetic write |
gh run rerun --failed |
Move to dedicated CLI synthetic coverage set |
rerun_workflow_job |
synthetic write |
gh run rerun --job |
Move to dedicated CLI synthetic coverage set |
rerun_workflow_run |
synthetic write |
gh run rerun |
Move to dedicated CLI synthetic coverage set |
run_workflow |
deprecated alias |
legacy workflow mapping |
Remove alias or isolate under compatibility handling |
set_secret |
synthetic write |
gh secret set |
Move to dedicated CLI synthetic coverage set |
set_variable |
synthetic write |
gh variable set |
Move to dedicated CLI synthetic coverage set |
sync_fork |
synthetic write |
gh repo sync |
Move to dedicated CLI synthetic coverage set |
transfer_issue |
synthetic write |
gh issue transfer |
Move to dedicated CLI synthetic coverage set |
transfer_repository |
blocked write |
repo ownership transfer |
Keep only in explicit CLI-only blocked coverage |
unarchive_repository |
blocked write |
gh repo unarchive |
Keep only in explicit CLI-only blocked coverage |
unlink_project |
synthetic write |
gh project unlink |
Move to dedicated CLI synthetic coverage set |
unpin_issue |
synthetic write |
gh issue unpin |
Move to dedicated CLI synthetic coverage set |
update_codespace_port_visibility |
synthetic write |
gh codespace ports visibility |
Move to dedicated CLI synthetic coverage set |
update_project |
synthetic write |
gh project close/edit/reopen |
Move to dedicated CLI synthetic coverage set |
update_project_draft_issue |
synthetic write |
gh project item-edit --title/--body |
Move to dedicated CLI synthetic coverage set |
update_project_item |
deprecated alias |
legacy/synthetic Projects mapping |
Remove alias or isolate under compatibility handling |
Why this matters
Today the guard conflates three different concepts in the same classification lists:
- Actual upstream MCP tools from
github-mcp-server
- Synthetic CLI-only operations that have no upstream MCP counterpart
- Deprecated aliases / compatibility names
That makes automated coverage checks noisy and obscures whether a missing entry is a real upstream regression or just a local synthetic mapping.
Suggested remediation
1. Split the inventories in tools.rs
Create separate constants for upstream MCP tools vs. synthetic CLI-only coverage vs. deprecated aliases. For example:
pub const WRITE_OPERATIONS: &[&str] = &[
// upstream github-mcp-server write tools only
"actions_run_trigger",
"add_issue_comment",
"create_pull_request",
// ...
];
pub const CLI_WRITE_OPERATIONS: &[&str] = &[
// gh-only synthetic coverage
"cancel_workflow_run",
"copy_project",
"delete_actions_cache",
"set_secret",
"transfer_issue",
// ...
];
pub const DEPRECATED_WRITE_ALIASES: &[&str] = &[
"add_project_item",
"delete_project_item",
"delete_workflow_run_logs",
"run_workflow",
"update_project_item",
];
Then make is_write_operation() / is_read_write_operation() consult all relevant sets deliberately, instead of forcing every synthetic entry into the MCP-derived canonical lists.
2. Adjust the coverage checker contract
Treat only upstream MCP entries as candidates for MCP drift. Treat CLI_WRITE_OPERATIONS as a separate audited set compared against cli/cli write commands.
3. Keep DIFC rules, but point them at the split sets
The explicit match arms in tool_rules.rs for these operations are still useful. The issue is not that the labels are wrong; it is that the tool inventory mixes unrelated sources. Preserve the existing labeling rules, but document whether each rule is for:
- upstream MCP tools,
- synthetic CLI-only operations, or
- deprecated compatibility aliases.
4. Add an invariant test
Add a test that asserts every WRITE_OPERATIONS / READ_WRITE_OPERATIONS entry belongs to exactly one source bucket:
#[test]
fn write_entries_belong_to_a_single_source_bucket() {
// every write classification should be upstream MCP, synthetic CLI, or deprecated alias
// but not mixed implicitly in one canonical list
}
CLI mapping context
The stale entries above are not arbitrary; they map to real CLI mutations such as:
| CLI Command |
Guard Entry |
Notes |
gh cache delete |
delete_actions_cache |
CLI-only, no current upstream MCP tool |
gh workflow enable |
enable_workflow |
CLI-only, no current upstream MCP tool |
gh workflow disable |
disable_workflow |
CLI-only, no current upstream MCP tool |
gh issue transfer |
transfer_issue |
CLI-only, no current upstream MCP tool |
gh project copy |
copy_project |
CLI-only GraphQL mutation |
gh project link / unlink |
link_project / unlink_project |
CLI-only GraphQL mutation |
gh codespace rebuild |
rebuild_codespace |
CLI-only session mutation |
gh secret set / delete |
set_secret / delete_secret |
CLI-only secret mutation |
These should remain guardable, but they should not masquerade as current upstream MCP tools.
References
Generated by GitHub Guard Coverage Checker (MCP + CLI) · gpt54 · 86.1 AIC · ⊞ 34.9K · ◷
Summary
The GitHub guard currently models a broader write surface than the official
github-mcp-serverREADME exposes, but that coverage is now stale in 39 places relative to the upstream MCP tool list. These entries still appear inguards/github-guard/rust-guard/src/tools.rs, yet they no longer appear in the upstream MCP server's published tool catalog. That drift makes the guard harder to audit and can hide real gaps behind synthetic or obsolete entries.In addition, the stale entries largely correspond to GitHub CLI-only mutations. Those operations are still reachable via
gh, but they are not represented by current upstream MCP tools, so they should be tracked explicitly as synthetic CLI coverage rather than blended into the MCP tool inventory.tools.rs): 141tool_rules.rs): 257 string-matched namesStale Guard Entries (tools.rs)
These entries are present in
WRITE_OPERATIONS/READ_WRITE_OPERATIONSbut are not present in the upstreamgithub-mcp-serverREADME tool list:add_project_itemarchive_repositorycancel_workflow_rungh run cancelcopy_projectgh project copycreate_agent_taskgh agent-task createcreate_projectgh project createdelete_actions_cachegh cache deletedelete_gistgh gist deletedelete_projectgh project deletedelete_project_itemdelete_secretgh secret deletedelete_variablegh variable deletedelete_workflow_run_logsdisable_workflowgh workflow disableenable_toolsetenable_workflowgh workflow enableforce_cancel_workflow_rungh run cancel --forcelink_projectgh project linkmark_pull_request_as_draftgh pr ready --undomark_pull_request_as_ready_for_reviewgh pr readypin_issuegh issue pinrebuild_codespacegh codespace rebuildrename_repositorygh repo renamererun_failed_jobsgh run rerun --failedrerun_workflow_jobgh run rerun --jobrerun_workflow_rungh run rerunrun_workflowset_secretgh secret setset_variablegh variable setsync_forkgh repo synctransfer_issuegh issue transfertransfer_repositoryunarchive_repositorygh repo unarchiveunlink_projectgh project unlinkunpin_issuegh issue unpinupdate_codespace_port_visibilitygh codespace ports visibilityupdate_projectgh project close/edit/reopenupdate_project_draft_issuegh project item-edit --title/--bodyupdate_project_itemWhy this matters
Today the guard conflates three different concepts in the same classification lists:
github-mcp-serverThat makes automated coverage checks noisy and obscures whether a missing entry is a real upstream regression or just a local synthetic mapping.
Suggested remediation
1. Split the inventories in
tools.rsCreate separate constants for upstream MCP tools vs. synthetic CLI-only coverage vs. deprecated aliases. For example:
Then make
is_write_operation()/is_read_write_operation()consult all relevant sets deliberately, instead of forcing every synthetic entry into the MCP-derived canonical lists.2. Adjust the coverage checker contract
Treat only upstream MCP entries as candidates for MCP drift. Treat
CLI_WRITE_OPERATIONSas a separate audited set compared againstcli/cliwrite commands.3. Keep DIFC rules, but point them at the split sets
The explicit match arms in
tool_rules.rsfor these operations are still useful. The issue is not that the labels are wrong; it is that the tool inventory mixes unrelated sources. Preserve the existing labeling rules, but document whether each rule is for:4. Add an invariant test
Add a test that asserts every
WRITE_OPERATIONS/READ_WRITE_OPERATIONSentry belongs to exactly one source bucket:CLI mapping context
The stale entries above are not arbitrary; they map to real CLI mutations such as:
gh cache deletedelete_actions_cachegh workflow enableenable_workflowgh workflow disabledisable_workflowgh issue transfertransfer_issuegh project copycopy_projectgh project link/unlinklink_project/unlink_projectgh codespace rebuildrebuild_codespacegh secret set/deleteset_secret/delete_secretThese should remain guardable, but they should not masquerade as current upstream MCP tools.
References