Adding tools to an agent is easy. Adding too many is how you break it.
Connect a database, wrap an API, publish a server: exposure is a few lines of config. Past a certain count, the agent slows down and starts picking the wrong tool. Anthropic has documented the mechanism: tool definitions alone can consume tens of thousands of tokens before the agent begins working.
Three problems emerge at scale: what you expose, how agents find it, and who controls access.
The most common production mistake is exposing generic technical operations:
execute_sql(query)
call_http(url, method, body)
run_shell(command)
This moves too much responsibility into probabilistic model reasoning. The model must figure out table names, understand schema relationships, construct valid queries, and avoid destructive operations. Every call is a fresh opportunity for hallucination.
A production tool exposes a business capability:
simulate_order_cancellation(order_id)
request_order_cancellation(order_id, reason)
create_refund_proposal(order_id, amount, evidence)
The domain service behind the tool enforces order state, refund limits, customer ownership, idempotency, and audit. The model chooses the capability. The business system validates the operation.
Your existing order service already handles authentication, validation, state checks, transactions, and event publication. Don't reimplement this inside an MCP server. Instead:
Agent → MCP call → thin adapter → HTTPS → Order service → DB + events
The MCP layer translates between agent-facing capability descriptions and existing service contracts. Business logic stays reusable across web, mobile, batch, and agent clients.
With hundreds of tools available, every model request becomes expensive and unreliable. The architecture must shift from "load everything" to "search and filter":
User goal → Capability search → Permission filter → Ranked tools → Model receives 5-10
A catalog entry needs more than a name and schema:
name: create_supplier_assessment
domain: procurement
owner: supplier-risk-team
version: 2.1
status: certified
intent: [assess supplier, evaluate procurement risk]
risk: { level: medium, side_effect: creates_draft }
permissions: [supplier-assessment:create]
approval: { invocation: not_required, publication: required }
data: { classification: confidential, freshness: 24_hours }
Tool design becomes product design. A good tool is easy to select correctly, hard to misuse, bounded in scope, explicit about side effects, clear about failure modes, and token-efficient in its response.
MCP includes an OAuth-based authorization framework. That handles protocol-level interoperability. It does not handle:
A valid token proves identity. It does not prove the agent may call this tool, the user authorized this action, or the requested amount is within policy.
An internal MCP registry should not become a list of URLs developers found online. Each production server needs governance:
name: procurement-capabilities
owner: procurement-platform-team
version: 2.3.1
authentication: { inbound: oauth, downstream: workload-identity }
classification: { max_data: confidential, side_effects: [create_draft, start_workflow] }
network: { allowed_egress: [procurement-api.internal] }
review: { security_review: passed, last_reviewed: 2026-06-20 }
status: certified
The platform has to own each server's full lifecycle: registration and ownership up front, a security review before it ships, then versioning and a clean path to deprecate and revoke. Same discipline you apply to any other dependency in your supply chain.
One universal gateway with 500 tools is a security anti-pattern and a catalog problem. Segment by domain and risk:
analytics-readonly-gateway → read-only data tools
developer-tools-gateway → code, docs, CI/CD
customer-service-gateway → CRM, order management
production-operations-gateway → requires elevated identity
The model should not see production-deletion tools just because it needs to query cost data. Gateway segmentation is both a security boundary and a tool-selection quality improvement: fewer irrelevant tools means better model choices.
Early agents: call one tool, return to model, call another, return, repeat. Each round trip burns tokens and adds latency.
Newer pattern: give the model a sandboxed execution environment:
Model → Sandboxed program
├── call tool A
├── call tool B in parallel
├── filter and join results
└── return compact evidence
This reduces round trips from 10+ to 1 for analytical tasks. The platform provides safe tools, resource limits, network restrictions, and output validation. The model writes the glue code.
The sandbox still needs isolation, CPU and memory caps, credential boundaries, package restrictions, and auditing. Code execution buys flexibility, not safety.
Audit your existing MCP servers. Does each have an owner, security review, data classification, and network boundaries? If not, it is not production-ready.
Check your tool count per request. If models receive 50+ tool definitions, you have a catalog problem. Implement search-based tool selection.
Segment gateways by trust zone. Map tools to domains and risk levels. Separate read-only analytics from write operations.
Review tool granularity. Each tool that exposes raw SQL, HTTP, or shell is a production incident waiting to happen. Wrap business capabilities, not infrastructure.
Previous in this series: Agent Identity and Durable Workflows: The Two Problems MCP Can't Solve — why identity and state persistence are the real enterprise gaps.