May 2026
mcp tool governance for production agents
MCP makes agents more useful by expanding what they can reach. That is exactly why production MCP usage needs a policy layer.
The Model Context Protocol turns external systems into agent-accessible tools, resources, prompts, and data surfaces. That is powerful, but it also changes the security shape of an agent application. A single MCP connection can expose dozens of actions with different risks.
Treating MCP as “just another tool call” is too coarse. The policy question should be more precise: which MCP server, which MCP tool, which resource, which arguments, which tenant, which environment, and which agent workflow?
MCP turns integration into capability sprawl
A normal hand-written tool is visible in your codebase. MCP tools may arrive from an external server, an internal platform team, or a third-party connector. The action surface can grow faster than your agent code changes.
This is why Brane's capability model matters. Instead of treating a whole MCP server as one permission, Brane can model individual MCP actions as governed capabilities. The docs describe this in the MCP Tool Governance guide and the underlying Capability concept.
Useful naming conventions
Namespaced capability names make MCP policy easier to reason about:
mcp.github.create_pr
mcp.github.merge_pr
mcp.slack.send_message
mcp.postgres.query
mcp.filesystem.read_file
mcp.notion.update_pageExact names let you write targeted policies. Prefixes and wildcard policies let you apply global control to high-risk surfaces.
Governance questions MCP teams should ask
- Can this agent call every tool exposed by the MCP server?
- Are write tools separated from read tools?
- Can production agents call destructive tools?
- Are tenant and principal identities passed into policy?
- Are file paths, repository names, channels, or database queries inspected?
- Are MCP denials audited with enough context to explain what happened?
Example: block high-risk MCP writes in production
@runtime.before_capability("*")
def block_mcp_writes_in_prod(ctx):
if (
ctx.is_prod
and ctx.capability.name.startswith("mcp.")
and ctx.is_high_risk
):
return Decision(type="deny", reason="High-risk MCP action blocked in prod")
return Decision(type="allow")Example: read-only MCP database access
Many MCP servers expose database access. In production, a common policy is to restrict those calls to read-only queries:
@runtime.before_capability("mcp.postgres.query")
def mcp_sql_read_only(ctx):
query = ctx.arg("query", "").strip().lower()
if not query.startswith("select"):
return Decision(type="deny", reason="Only SELECT queries are allowed")
return Decision(type="allow")The same pattern appears in the SQL Read-Only Recipe; MCP changes the adapter boundary, not the policy logic.
How this compares to MCP server permissions
Server-side permissions are still necessary. They protect the MCP server and backing services. Runtime policy adds a decision layer in the agent application: it can reason about the current agent, tenant, task, environment, and arguments before a call leaves the agent process.
Brane Core supports the local policy model today. Dedicated MCP adapters are on the roadmap; until then, teams can wrap MCP-facing functions or adapter boundaries directly. See the Roadmap for planned adapter work.
The MCP permission problem is not only authentication
Authentication tells the MCP server who is connecting. Authorization can decide whether that connection may access a server-side resource. But an agent application often needs another question answered: should this particular agent workflow be allowed to call this particular tool with these arguments right now?
That question depends on runtime context the MCP server may not know: the user's current task, the tenant, the environment, the agent's plan, the preceding actions in the trace, and the application's own policy metadata. That is why MCP governance belongs both at the server boundary and at the agent runtime boundary.
Threats that become more important with MCP
- Tool confusion: similar tool names make it easy for agents or users to select the wrong operation.
- Overbroad servers: one MCP server exposes both read and write capabilities.
- Prompt injection through resources: retrieved content tries to influence future tool use.
- Cross-tenant leakage: a resource call omits or rewrites tenant filters.
- Silent side effects: a tool appears harmless but updates external state.
- Credential reachability: the agent gains indirect access to systems through server credentials.
None of these require MCP to be poorly designed. They appear because MCP makes integration easier, and easier integration increases the number of reachable actions.
Compare three governance points
| Control point | What it sees | What it misses |
|---|---|---|
| MCP server policy | Server resources, server credentials, protocol request | Agent workflow intent and local application context |
| Agent prompt rules | Natural-language task constraints | Reliable enforcement before side effects |
| Runtime capability policy | Agent, tenant, environment, capability, arguments, trace | Server-internal authorization details |
The right answer is layered. Server policy should protect the server. Runtime policy should protect the agent application. Prompts should express intent, not carry the whole enforcement burden.
A rollout strategy
- Inventory MCP servers and tools exposed to each agent.
- Name each MCP tool as a capability with a namespace.
- Classify risk: read-only, write, destructive, secret-bearing, external.
- Add global policies for high-risk actions in production.
- Add exact policies for database, file, messaging, and repository tools.
- Log every denied action with action id, agent id, tenant, tool name, and reason.
- Move from deny-only policies to approvals and transformations as the runtime supports them.
This lets teams adopt MCP without treating every new tool as an implicit trust expansion.
A policy matrix for MCP tools
A useful MCP governance exercise is to build a matrix before wiring every tool into an agent. Put tool names on one axis and policy questions on the other:
| Question | Why it matters |
|---|---|
| Is the tool read-only? | Write tools need stronger controls and audit. |
| Can the tool reach customer data? | Tenant and principal context must be enforced. |
| Can the tool call external systems? | Side effects may leave your trust boundary. |
| Can the tool expose secrets? | Output policy and redaction become important. |
| Can the tool modify code, tickets, messages, or files? | Approval or scoped execution may be necessary. |
The matrix turns a vague concern — “MCP is powerful” — into specific capability metadata and policy decisions. Some tools can be available broadly. Others should be available only in development, only for read-only workflows, or only after approval.
Separate discovery from execution
Agents often need to know what tools exist before they know which tool to use. That discovery step should not imply execution permission. A model may see that mcp.github.merge_pr exists, but the runtime should still be able to deny the actual merge attempt.
This separation is especially important for MCP because the protocol is designed to make tool and resource discovery easier. Discovery helps agents plan. Runtime policy decides what they can actually do.
This is the kind of problem we're solving with Brane — policy-as-code for AI agents. Write Python policies that run before agent actions execute. Block or allow high-risk capability use, with an audit-ready decision trace.