althor
All writing
Pattern · 2026

Drawing the right boundaries for an MCP server

An MCP server is a security boundary, not a convenience layer. Six rules that keep tool surfaces narrow enough to defend without making them too narrow to use.

The Model Context Protocol gives agents a clean way to reach into the rest of your stack — databases, dashboards, ticket systems, file stores. The protocol itself is small and well-specified. The interesting work is upstream of it: deciding what an MCP server is allowed to do, what shape its tools take, and where the boundary sits between the agent and your production systems.

Treat each MCP server as a security boundary, not a convenience layer. The rules below come from running production agents against real internal systems and watching where the failure modes show up.

Six rules

01 · One server, one trust boundary

An MCP server bundles a set of tools that share an auth context. Don't mix concerns. A "homelab tools" server that exposes infrastructure controls, secret reads, and media-library queries is three servers pretending to be one. When something goes wrong, you can't revoke just the part that misbehaved. Split servers along blast-radius lines: infra, observability, data, library — each with its own credentials and its own scope of what it's allowed to touch.

02 · Read-only by default; writes are explicit and tagged

The cheapest control is the one you don't have to revoke. A server with only read tools is unsurprising. The moment you introduce a write tool, the server's threat model changes — every read tool is now a potential reconnaissance step before a write. Mark write tools clearly in their names (create_, delete_, update_) so the agent's planner can see them and so policy gates can intercept them.

03 · Tool names describe intent, not implementation

prom_query beats http_get. list_open_tickets beats db_select. The name is a contract with the model — it's how the planner reasons about which tool to reach for. A generic transport-shaped tool is a foot-cannon: it forces the model to invent the right query, and gives you nowhere to put a guardrail. Wrap the transport in a domain-shaped tool and put the guardrail inside the wrapper.

04 · Bounded outputs, always

Every tool result lands in the model's context window. An unbounded tool — one that can return a thousand log lines, or a database row at any size — turns a single tool call into a context-budget exhaustion event. Paginate by default. Truncate large fields with an explicit marker. Document the maximums in the tool description so the model knows when to ask for more rather than re-running the same query and hoping for less.

05 · Errors are first-class

A failed tool call is not a stack trace. Return a structured error with a code, a short human description, and — when relevant — a suggested next action. Raw exception text is at best noise and at worst a leak of internal paths, hostnames, or schemas. The model handles structured errors gracefully; it spirals on unstructured ones.

06 · Auth at the server boundary, not the tool

MCP isn't a permissions system. It's a transport. The server is where you decide which tools exist for this caller, what the caller's identity is, and what credentials each tool will use downstream. Don't pass agent-supplied tokens into tool implementations. Don't read auth headers inside the tool. Establish the trust context once, at the server boundary, and let the tools execute against an already-resolved identity.

What good looks like

agent
   │
   │  stdio / sseMCP server (one trust boundary)
   │
   ├── auth resolution — shared secret · workload identity · OBO
   │
   ├── tool: prom_query     read · bounded
   ├── tool: prom_alerts    read · bounded
   └── tool: silence_alert  write · policy-gated
            │
            ▼
        downstream system (narrow API wrapper, never raw SDK)

The combination is what matters. A server with the right boundary, the right tool shapes, the right output bounds, and the right auth model is something you can hand to an agent without losing sleep. Get any of the six wrong and the failure mode shows up in production, where it's expensive to fix.

The protocol itself is the easy part. The discipline of where to draw the line — that's the work.

All writing