
Key takeaways
- A secure TypeScript agent built around Anthropic tooling should treat MCP servers and tool results as separate trust domains. Keep credentials out of prompts, allowlist servers and tools, validate every argument, require approval for consequential writes, and verify postconditions. Exact SDK APIs and package versions can change, so implementation details should be confirmed against current official documentation.
A secure TypeScript agent built around Anthropic tooling should treat MCP servers and tool results as separate trust domains. Keep credentials out of prompts, allowlist servers and tools, validate every argument, require approval for consequential writes, and verify postconditions. Exact SDK APIs and package versions can change, so implementation details should be confirmed against current official documentation.
Map the runtime before writing code
Draw the components first: user interface, agent runtime, model provider, MCP clients, MCP servers, local or remote tools, data stores, and approval service. Label where identity is established, where secrets live, and which component can cause external effects. This threat model is more useful than starting from a large tool list.
In TypeScript, define domain types for requests, tool inputs, results, errors, and approval receipts. Runtime validation is still required because static types disappear at process boundaries. A JSON Schema or validation library should reject unknown fields, invalid enums, oversized values, and unexpected URLs before a tool runs.
MCP boundaries and server trust
MCP standardizes context exchange, but a protocol connection is not an endorsement. Inventory every server, its owner, transport, version, available tools, and required data access. Prefer explicit configuration over automatic discovery. Pin dependencies and review changes to tool descriptions because descriptions influence model selection.
Use least privilege. A repository reader does not need shell access; a ticket summarizer does not need permission to edit tickets. Split read and write servers when practical. For remote transports, verify authentication, TLS, audience, and tenant boundaries from current official guidance. For local transports, protect executable paths, environment variables, and working directories.
Tool schemas, approvals, and transactions
A tool name should describe one action. Inputs should use tight enums and bounded strings rather than free-form commands. Resolve resource identifiers in trusted code. Do not let the model construct arbitrary filesystem paths, SQL, shell fragments, or callback URLs. Return a preview for writes so the user can inspect the exact target and payload.
Bind approval to that preview with a nonce, expiry, actor, and hash. If the payload changes, approval becomes invalid. Use idempotency keys and read-after-write verification. When a network timeout leaves the result uncertain, query current state before retrying. This protects against duplicate comments, orders, deployments, or deletions.
Secrets, context, and prompt injection

Secrets belong in a secret manager or protected process environment and should be injected only into the tool that needs them. Never place API keys in model context or logs. Redact headers, tokens, user data, and tool results before telemetry. Apply per-tool egress rules so a compromised server cannot send data to arbitrary destinations.
Treat all MCP-provided text as untrusted. A document can tell the agent to ignore instructions or call another tool. Preserve source labels and quote boundaries. System policy, user approval, and tool authorization must have higher precedence than retrieved content. Require evidence for sensitive decisions rather than accepting a document’s self-declared authority.
Observability and secure failure
Record a structured trace: request ID, model decision, selected tool, validated parameters, policy result, approval reference, tool receipt, and postcondition. Logs should support an incident review without retaining unnecessary prompt content. Separate security events from application debugging and define retention based on sensitivity.
Fail closed on missing identity, expired approval, schema mismatch, unknown server, and ambiguous postconditions. Retry only classified transient errors. Rate-limit per user and tool, cap loop steps, and expose a kill switch. An agent that cannot prove completion should report uncertainty instead of claiming success.
Test the control plane

Unit-test validators and authorization independently of the model. Add integration tests with mock MCP servers that return malformed schemas, injected instructions, oversized payloads, slow responses, and false success. Test cross-tenant identifiers and stale approval reuse. Red-team the descriptions as well as the returned content.
Before release, confirm the current Anthropic Agent SDK and MCP documentation, package versions, transport requirements, and security recommendations. This guide defines an architecture pattern, not a claim that a particular SDK version automatically enforces every control.
Implementation worksheet
Build a minimal test harness before connecting production data. Register one read-only MCP server, validate inputs at runtime, and capture a sanitized trace. Add a write tool only after prepare, approval, commit, and verification are represented as separate operations. Then test an unknown server, a changed tool schema, an expired token, injected document text, a duplicate request, and an uncertain timeout. Review current official SDK and protocol documentation during implementation because package names, APIs, and transport guidance can change.
Frequently Asked Questions
Is an MCP server automatically trusted?
No. Treat each server as a separate trust domain and verify its owner, transport, authentication, tools, data access, version, and update process.
Do TypeScript types secure tool input?
No. Static types help developers, but runtime validation and authorization are required at every process or network boundary.
How should an agent approve a write?
Prepare a preview, show the exact target and payload, bind approval to a hash and expiry, then commit with an idempotency key and verify the resulting state.
Where should API keys be stored?
Use a secret manager or protected runtime environment and expose credentials only to the specific tool process that needs them, never to model context.


