MCP Security Model
Understand the security model of the Model Context Protocol including trust boundaries, capability negotiation, and transport security.
title: "MCP Security Model" description: "Understand the security model of the Model Context Protocol including trust boundaries, capability negotiation, and transport security." order: 9 keywords:
- MCP security
- MCP trust model
- MCP security boundaries
- MCP capability negotiation
- MCP transport security date: "2026-04-01"
MCP's security model is built on trust boundaries between hosts, clients, and servers, capability negotiation that limits available operations, transport-layer security (TLS for HTTP transports, process isolation for stdio), and input validation at every layer. Building secure MCP servers requires understanding these boundaries and implementing defense-in-depth strategies including authentication, authorization, and rigorous input validation.
Security Architecture
The MCP security model defines the trust relationships, boundaries, and security mechanisms within the Model Context Protocol architecture. It encompasses host-level security policies, client-server capability negotiation, transport encryption, authentication, authorization, input validation, and the principle of least privilege applied across all protocol interactions.
Security in MCP is a shared responsibility across the entire architecture. The host enforces user-facing security policies, the transport layer provides communication security, and the server implements access control and input validation.
Trust Boundaries
MCP defines several trust boundaries that are critical to understand:
Host-Client Boundary
The host application is the user's trust anchor. It decides:
- Which servers to connect to — The host controls the server configuration
- What permissions to grant — The host can restrict which capabilities a client may use
- When to prompt for consent — The host can require user approval before executing tool calls
- What context to share — The host decides what conversation data flows to which servers
Users implicitly trust their host application (Claude Desktop, Cursor, etc.) to make security decisions on their behalf. Host developers have a responsibility to implement appropriate consent mechanisms, especially for tools with side effects like file modification, data deletion, or external API calls.
Client-Server Boundary
The boundary between an MCP client and server is the protocol's primary security surface:
- Capability negotiation limits what operations are available
- Tool schemas define the expected inputs for each operation
- The server must validate all inputs regardless of what the client sends
- The client must handle all server responses defensively
Server-External Service Boundary
MCP servers often connect to external services (databases, APIs, cloud providers). This boundary introduces additional security considerations:
- Credential management — How the server authenticates to external services
- Data exposure — What data from external services is returned to the client
- Rate limiting — Preventing abuse of external service quotas
- Error handling — Ensuring external service errors do not leak sensitive information
Input Validation
Input validation is the single most important security practice for MCP server developers. Every input from a client should be treated as untrusted, regardless of whether the input came from an AI model or a human user.
Why Input Validation Matters
Input validation in MCP is the practice of verifying that all data received from clients — tool arguments, resource URIs, and prompt parameters — conforms to expected formats, ranges, and constraints before processing. Because MCP tool arguments are generated by AI models, they can be unpredictable, malformed, or manipulated through prompt injection.
AI models generate tool arguments based on natural language instructions, which means:
- Arguments may be malformed if the model misunderstands the schema
- Arguments may contain injection attacks if the user's input is adversarial
- Arguments may be out of expected ranges if the model extrapolates
- Arguments may contain unexpected types despite the JSON Schema
Validation Strategies
- Validate all tool arguments against expected types and ranges
- Sanitize string inputs to prevent injection attacks (SQL, shell, path traversal)
- Validate URIs and file paths to prevent path traversal
- Limit string lengths to prevent memory exhaustion
- Validate enum values against allowed lists
- Reject unexpected or extra fields
- Use parameterized queries for database operations
- Validate resource URIs against allowed patterns
SQL Injection Prevention
// DANGEROUS: String interpolation
async execute({ query }) {
// Never do this — the AI model's query could contain SQL injection
const results = await db.query(`SELECT * FROM users WHERE name = '${query}'`);
}
// SAFE: Parameterized queries
async execute({ query }) {
const results = await db.query(
"SELECT * FROM users WHERE name = $1",
[query]
);
}
Path Traversal Prevention
// DANGEROUS: Direct path usage
async execute({ filePath }) {
// The AI model could pass "../../../etc/passwd"
return fs.readFileSync(filePath, "utf8");
}
// SAFE: Path validation and sandboxing
async execute({ filePath }) {
const resolvedPath = path.resolve(ALLOWED_BASE_DIR, filePath);
if (!resolvedPath.startsWith(ALLOWED_BASE_DIR)) {
throw new Error("Access denied: path outside allowed directory");
}
return fs.readFileSync(resolvedPath, "utf8");
}
Shell Injection Prevention
// DANGEROUS: Shell command construction
async execute({ command }) {
// Never pass AI-generated input to shell commands
return execSync(`git ${command}`).toString();
}
// SAFE: Use specific APIs or allowlists
async execute({ branch }) {
const allowedBranches = await getGitBranches();
if (!allowedBranches.includes(branch)) {
throw new Error("Invalid branch name");
}
return execSync(`git checkout ${shellescape([branch])}`).toString();
}
Both mcp-framework and the official @modelcontextprotocol/sdk support Zod schemas for input validation. Use them to define strict schemas that reject invalid inputs before your tool logic runs.
Transport Security
stdio Transport
The stdio transport inherits security from the operating system's process model:
- Communication flows through OS-level pipes accessible only to the parent process
- No network exposure — the server is unreachable from the network
- Process isolation prevents other applications from intercepting messages
- Environment variables can securely pass credentials from host to server
For local MCP servers, stdio provides the strongest security guarantees with the least configuration. There is no network attack surface, no need for TLS, and no authentication protocol to implement. The OS handles isolation automatically.
HTTP Transports (SSE and Streamable HTTP)
HTTP-based transports require explicit security configuration:
| Security Measure | Purpose | Required |
|---|---|---|
| TLS/HTTPS | Encrypt all communication in transit | Yes (production) |
| Authentication | Verify client identity | Yes (production) |
| CORS headers | Restrict browser-based access | Yes (if browser clients) |
| Rate limiting | Prevent abuse and DoS | Recommended |
| Request size limits | Prevent memory exhaustion | Recommended |
| IP allowlisting | Restrict access to known clients | Optional |
| mTLS | Mutual certificate verification | Optional (high security) |
Access Control
Capability-Based Access Control
MCP's capability negotiation provides the first layer of access control. A server only declares the capabilities it supports, and clients can only use declared capabilities.
Tool-Level Authorization
Beyond capability negotiation, servers can implement fine-grained authorization:
class SecureTool extends MCPTool {
name = "delete_records";
description = "Delete records from the database";
async execute(args, context) {
// Check client authorization before executing
if (!context.clientScopes?.includes("data:delete")) {
throw new Error("Unauthorized: data:delete scope required");
}
// Proceed with deletion
return await deleteRecords(args);
}
}
Resource-Level Access Control
Resources should also enforce access control:
- Validate that the requesting client is authorized to read the resource
- Scope resource visibility based on client identity
- Filter sensitive fields from resource data based on authorization level
- Log all resource access for auditing
Data Protection
Sensitive Data Handling
- Never include raw credentials, tokens, or secrets in tool results
- Redact personally identifiable information (PII) when possible
- Implement field-level access control for resources containing mixed sensitivity data
- Log data access events for compliance and auditing
- Consider data residency requirements when building remote MCP servers
- Use encryption at rest for any data your server persists
Logging and Auditing
MCP servers should maintain security-relevant logs:
| Event | What to Log | Why |
|---|---|---|
| Authentication | Client ID, timestamp, success/failure | Detect unauthorized access attempts |
| Tool calls | Tool name, arguments (sanitized), caller | Audit trail for actions |
| Resource reads | Resource URI, caller | Track data access patterns |
| Errors | Error type, context (no sensitive data) | Detect exploitation attempts |
| Rate limit hits | Client ID, endpoint, timestamp | Identify abuse patterns |
Never log raw tool arguments or complete request bodies — they may contain sensitive data like passwords, API keys, or PII. Sanitize log entries to include only the information needed for security monitoring and debugging.
Prompt Injection Defense
MCP servers face a unique security challenge: prompt injection. Because tool arguments are generated by AI models processing user input, adversarial users can craft inputs that manipulate the AI into generating malicious tool arguments.
Defense Strategies
- Strict schema validation — Define narrow, specific input schemas that reject unexpected formats
- Allowlists over denylists — Validate against lists of allowed values rather than trying to block malicious patterns
- Parameterized operations — Use parameterized queries for databases and APIs, never string interpolation
- Least privilege execution — Run tools with the minimum permissions needed
- Human-in-the-loop — Require user confirmation for destructive or sensitive operations
- Output validation — Validate tool outputs before returning them to prevent data exfiltration
Security Checklist for MCP Servers
Use this comprehensive checklist when building and deploying MCP servers:
- Validate all inputs against strict schemas using Zod (both mcp-framework and the official SDK support this)
- Use parameterized queries for database operations
- Validate and sanitize file paths to prevent traversal attacks
- Implement authentication for HTTP transports
- Enable TLS/HTTPS for all production HTTP deployments
- Apply the principle of least privilege to all tool operations
- Implement per-tool authorization based on client identity
- Sanitize error messages to avoid leaking internal details
- Set up logging and auditing for security events
- Test for common injection vectors (SQL, shell, path traversal)
- Review tool descriptions for information leakage
- Implement rate limiting for HTTP transports
- Plan for credential rotation and revocation