Skip to content
v0.1.0 ReleasedStar us on GitHub
MCP Governance

How to Add Governance to Model Context Protocol (MCP) Servers

A deep, practical guide to policy checks, approvals, constraints, and audit trails for MCP tools and resources.

January 27, 202614 min readMCP, Governance, Security

Model Context Protocol (MCP) makes it easy to connect models to tools and data. That ease is the problem. Without governance, MCP servers become a new layer of unreviewed privileges that can read data, change systems, and leak secrets.

This guide shows how to add governance to MCP servers and clients. You will learn a threat model, a reference architecture, concrete policy patterns, and a checklist for secure MCP client implementations. If you are new to MCP, start with the MCP guide first.

1. Why MCP governance matters now

MCP is trending because it solves real integration pain. It standardizes how models discover tools, invoke actions, and read resources. The result is a flood of MCP servers in production environments with real data.

The governance gap shows up fast: tools are deployed before security reviews, write actions run without approvals, and no one can answer basic questions like "who approved this tool call?" or "which policy allowed this access?". MCP governance is the immediate win because the ecosystem is moving fast and the risk surface is still small enough to tame.

Governance is a decision layer

Governance is not a compliance checklist. It is a deterministic decision made before every MCP tool call, with approvals and audit trails when risk is high.

2. Threat model for MCP servers

MCP expands the model's reach into your systems. Treat MCP servers like production APIs and apply the same threat model you would for a privileged integration.

Prompt injection into tool calls

Critical

Malicious inputs cause the model to call high-impact tools or bypass guardrails.

Resource overreach and data exfiltration

High

Wide-open resources allow models to read sensitive data and leak it in outputs.

Credential and scope drift

High

MCP servers accumulate powerful tokens that are not scoped to each request.

Unbounded write actions

Critical

Tools that modify systems of record run without approvals or constraints.

3. Governance objectives

Governance for MCP should be explicit and practical. The objective is not to slow down every tool call; it is to separate the safe path from the risky path.

Policy before execution

Every MCP tool call is evaluated before it runs.

Least privilege

Scope tools, resources, and tokens to the smallest safe unit.

Human approvals

Require explicit approval for writes, high-risk tools, or sensitive resources.

Runtime constraints

Apply budgets, timeouts, and allowed toolchains to prevent runaway actions.

Audit trail

Record decisions, approvals, and outputs for compliance and incident review.

Server inventory

Track which MCP servers exist, what they expose, and who can call them.

4. Reference architecture

The simplest way to govern MCP is to insert a decision layer between the client and the server. That layer normalizes tool calls, evaluates policy, and decides whether to allow, deny, or require approval.

MCP Client
  | tool call (JSON-RPC)
  v
Governance Layer
  | policy check -> decision
  v
Scheduler / Router
  | dispatch to MCP server
  v
MCP Server
  | result
  v
Audit + Timeline

You can implement the governance layer as a proxy, a gateway, or a control plane. The key is that every MCP tool call goes through policy before it reaches the MCP server.

5. Step-by-step implementation

Step 1: Normalize tool calls into a policy envelope

MCP uses JSON-RPC, but governance needs a consistent envelope. Convert each MCP tool call into a job-like payload that includes the tool, resource, and actor identity.

{
  "topic": "job.mcp.tool",
  "labels": {
    "mcp.server": "github",
    "mcp.tool": "create_issue",
    "mcp.resource": "repo:cordum-io/cordum",
    "mcp.action": "write"
  },
  "meta": {
    "capability": "repo.write",
    "risk_tags": ["prod", "external"],
    "requires": ["github", "network:egress"],
    "actor_id": "user_123",
    "actor_type": "human"
  },
  "context": {
    "title": "Fix broken build",
    "body": "We should patch the CI config."
  }
}

Step 2: Attach MCP metadata explicitly

Governance cannot infer intent. You must label MCP calls with structured metadata. The minimum set is:

  • mcp.server - the server name or identifier
  • mcp.tool - the tool being invoked
  • mcp.resource - the target resource (repo, table, dataset)
  • mcp.action - read, write, or admin
  • capability - the business capability being exercised
  • risk_tags - tags like "prod", "secrets", or "external"

Step 3: Evaluate policy and return a decision

A governance layer should return one of four decisions:

  • ALLOW - safe to run
  • DENY - blocked with a reason
  • REQUIRE_APPROVAL - human approval needed
  • ALLOW_WITH_CONSTRAINTS - allowed with limits

This decision is what lets you move fast on safe actions while holding the risky path for review.

Step 4: Require approvals for risky actions

Writes and admin actions should not be automatic. When the decision is REQUIRE_APPROVAL, pause the tool call and notify the approver. Store the policy snapshot that required the approval so you can audit later.

Step 5: Apply constraints before dispatch

Constraints reduce blast radius. Examples include runtime budgets, retry limits, or tool allowlists. The constraints travel with the request and are enforced by the runtime or worker.

Step 6: Record an audit trail

Governance without audit is not governance. Record the MCP call, policy decision, approval metadata, and final result. This is your evidence layer for security reviews and incident response.

6. Policy example

Here is a practical policy example that allows read-only MCP calls, requires approval for writes, and adds constraints for production resources.

version: "2026-01-27"
rules:
  - id: mcp-read-allow
    match:
      labels:
        mcp.action: "read"
      mcp:
        allow_servers: ["github", "confluence", "snowflake"]
    decision: allow
    reason: "Read-only MCP access"

  - id: mcp-write-approval
    match:
      labels:
        mcp.action: "write"
    decision: require_approval
    reason: "Human approval required for write actions"

  - id: mcp-prod-constraints
    match:
      risk_tags: ["prod"]
    decision: allow_with_constraints
    reason: "Production writes must be bounded"
    constraints:
      budgets:
        max_runtime_ms: 30000
        max_retries: 1
        max_concurrent_jobs: 1

7. Secure MCP client checklist

Governance is not only a server-side concern. MCP clients must do their part by tagging requests, enforcing limits, and preventing silent privilege escalation.

Allowlist MCP servers and pin endpoints per environment.
Scope tokens per server and per action, not per app.
Attach actor identity and tenant metadata to every request.
Classify actions as read or write and label them explicitly.
Set strict timeouts, retries, and cancellation handling.
Log every tool call with decision, approval, and outcome.
Redact or truncate sensitive outputs before returning to the model.

8. How Cordum helps

Cordum is a control plane for governed automation. If you route MCP calls through Cordum, the Safety Kernel evaluates policy before any tool runs, approvals are bound to policy snapshots, and every decision is recorded in the run timeline.

Cordum policies can match MCP labels like mcp.server, mcp.tool,mcp.resource, and mcp.action. That gives you precise governance without hardcoding tool rules in the client.

Key takeaway

MCP is a powerful connector, but it is not a governance system. Add a policy layer, require approvals for risky actions, and record every decision. That is how you keep MCP fast for safe tasks and accountable for high-risk ones.