Skip to content

Mapping your tools

Verb inference handles most MCP tools well (get_* is READ, send_* is COMMUNICATION, delete_* is DELETE). For tools you rely on, an explicit mapping is better. It is faster to reason about, it can’t be fooled by a misleading name, and it tells AgentsFence which arguments carry recipients, URLs and paths.

Terminal window
agentsfence classify mcp_crm_update_contact '{"email": "ann@corp.com", "notes": "…"}'
{
"tool_name": "mcp_crm_update_contact",
"capability": "crm.write",
"risk": "EXTERNAL_WRITE",
"source": "inferred",
"targets": {"recipients": ["ann@corp.com"], "domains": [], "urls": [], "paths": [], "command": null}
}
~/.hermes/agentsfence/config.yaml
tools:
mcp_crm_update_contact:
capability: crm.write
risk: EXTERNAL_WRITE
recipient_args: [email]
mcp_tickets_run_query: # name says "run", but it's a read-only query
capability: tickets.read
risk: READ
mcp_wallet_get_quote_and_pay: # name starts with "get", but it pays
capability: payment.pay
risk: FINANCIAL
mcp_notes_manage: # one tool, several actions
capability: notes.write
risk: LOCAL_WRITE
arg_risk:
action: {list: READ, read: READ, delete: DELETE}
Key Meaning
capability the name used in policies and the audit log; keep <domain>.<verb>
risk one of the risk classes
arg_risk override the risk class by the value of one argument
recipient_args arguments holding people or channels (checked against allowed recipients)
domain_args arguments holding URLs (checked against allowed domains and the exfiltration heuristic)
path_args arguments holding file paths (checked against allowed paths and protected paths)
patterns:
- {match: "mcp_internalwiki_*", capability: wiki.read, risk: READ}
- {match: "mcp_*", risk: infer}
- {match: "*", risk: infer}

The first match wins. Keep the two infer catch-alls at the end.