Back to KB
Difficulty
Intermediate
Read Time
9 min

MCP Threat Model Template for Agent Tools

By Codcompass Team··9 min read

Bounding Agent Authority: A Structured Threat Model for MCP Tool Surfaces

Current Situation Analysis

The Model Context Protocol (MCP) has accelerated the deployment of agent-driven architectures, but it has also introduced a critical security blind spot: developers are treating tool exposure as a functional concern rather than an authority boundary problem. In traditional API design, endpoints are secured by authentication, rate limiting, and explicit permission scopes. In MCP ecosystems, tools are dynamically discovered and invoked by language models that operate on probabilistic reasoning. When a model misinterprets context or selects an incorrect argument, the resulting blast radius is not determined by the prompt—it is determined by the authority surface you exposed.

This problem is consistently overlooked because teams default to binary classifications like read_only versus write. These labels are functionally meaningless when a tool can traverse host filesystems, resolve internal DNS, mutate tenant records, or trigger billable provider calls. The industry has spent excessive cycles hardening prompt injection defenses while leaving the actual execution context unbounded. Production incidents consistently show that the damage occurs not when the model hallucinates, but when it successfully invokes a tool with elevated privileges, incorrect scope, or unbounded retry behavior.

The evidence is structural: MCP tools are not uniform risk vectors. A filesystem reader, a network fetcher, a CRM updater, and a payment processor each exercise fundamentally different authority classes. Treating them as interchangeable functions guarantees that a single misrouted call can compromise host state, leak cross-tenant data, or exhaust budget ceilings. Security must shift from reactive prompt filtering to proactive route-by-route contracts that define exactly what a tool can touch, who can invoke it, how much it can spend, and what happens when it fails.

WOW Moment: Key Findings

The most impactful shift in MCP security is moving from natural-language classification to authority-surface mapping. The table below contrasts traditional tool categorization with a structured threat model approach across critical operational dimensions.

ApproachBlast Radius ControlAudit GranularityFailure DeterminismOperational Overhead
Traditional Read/Write ClassificationLow (relies on model intent)Low (generic success/fail logs)Unpredictable (silent retries, partial state)Low initially, high during incident response
Authority-Surface Threat ModelingHigh (explicit prefix/tenant/budget boundaries)High (policy decision, credential lane, cost owner)Deterministic (typed denials, fail-closed fixtures)Moderate upfront, near-zero during incidents

This finding matters because it transforms security from an abstract compliance exercise into an enforceable runtime contract. When you map authority surfaces instead of labeling read/write capabilities, you gain deterministic failure modes, precise audit trails, and predictable cost boundaries. More importantly, you enable negative testing: you can prove that adjacent paths, wrong tenants, or elevated spend amounts fail closed before production traffic ever reaches the tool. This shifts the security posture from reactive damage control to proactive boundary enforcement.

Core Solution

Implementing a robust MCP threat model requires binding seven structural fields to every tool route before production traffic is allowed. The following implementation demonstrates how to enforce these boundaries using a TypeScript-based guard pattern that wraps standard MCP tool registrations.

Step 1: Define Route Capability and Trust Class

Every tool must declare its exact capability ID, allowed input shape, and the trust class of the caller. Trust class determines whether the tool appears during discovery and what autonomy the caller possesses.

interface ToolRouteDefinition {
  capabilityId: string;
  allowedInputShape: Record<string, string>;
  sideEffectClass: 'none' | 'state-mutation' | 'external-call' | 'financial';
  trustClass: 'user-

🎉 Mid-Year Sale — Unlock Full Article

Base plan from just $4.99/mo or $49/yr

Sign in to read the full article and unlock all 635+ tutorials.

Sign In / Register — Start Free Trial

7-day free trial · Cancel anytime · 30-day money-back