MCP tool permissions
A Model Context Protocol server exposes tools an AI client can request. I declare each tool’s permissions and enforce access in the handler. Read-only annotations describe intended behavior; they do not enforce permissions on their own.
How do I restrict an MCP caller’s tool access?
A Model Context Protocol server exposes tools an AI client can request. I declare each tool’s permissions and enforce access in the handler.
Implementation
- Declare each tool's read/write nature in its annotations and enforce it in the handler.
- Deny network egress a tool has not declared.
- Never read ambient credentials inside a tool that a public caller can reach.
- Return structured content with a fixed schema and treat all returned text as untrusted data.
- Log every invocation with caller identity, arguments, and duration.
defineTool({
name: "list_projects",
inputSchema: {},
annotations: {
readOnlyHint: true,
idempotentHint: true,
openWorldHint: false,
},
handler: () => ({ structuredContent: { projects } }),
})What can go wrong
- A tool can expose credentials if it includes environment values in an error message.
- Public write tools without caller verification can permit unauthorized changes.
- Tool output can contain untrusted instructions that a client mistakes for commands.
Checks to try
- Enumerate the live tool list and confirm every entry is intentional.
- Attempt an undeclared operation and confirm it is refused.
Questions this pattern answers
How do I restrict an MCP caller’s tool access?
A Model Context Protocol server exposes tools an AI client can request. I declare each tool’s permissions and enforce access in the handler.
What steps does this method use?
Declare each tool's read/write nature in its annotations and enforce it in the handler. Deny network egress a tool has not declared. Never read ambient credentials inside a tool that a public caller can reach. Return structured content with a fixed schema and treat all returned text as untrusted data. Log every invocation with caller identity, arguments, and duration.
How can I check the result?
Enumerate the live tool list and confirm every entry is intentional. Attempt an undeclared operation and confirm it is refused.
What can go wrong with this approach?
A tool can expose credentials if it includes environment values in an error message. Public write tools without caller verification can permit unauthorized changes. Tool output can contain untrusted instructions that a client mistakes for commands.
Related projects
ClawKeeper →
ClawKeeper checks proposed Claude agent actions against explicit rules before a model call. Autonomous spend defaults to zero, and the database enforces an append-only audit log.
TechTide Harness Kit →
TechTide Harness Kit uses JSON Schema to declare skill permissions, risk tiers, network access, and approval requirements. Automated checks validate declarations and run prompt-injection fixtures.
CipherClaw →
CipherClaw analyzes recorded agent activity without model calls. It builds causal graphs, scores possible causes, and flags failure patterns.
Swarm 357 →
357 Claude agent roles across six business layers, with portable memory, enforced cost caps, a bash policy gate, and durable checkpoints.
Related patterns
Acceptance tests for agent work →
Executable checks test the task and detect regressions.
Evaluation tests for releases →
A fixed evaluation suite checks release requirements.
Recording agent runs →
A shared trace ID connects the records of a run.
Spending limits for agent runs →
Budget checks run before provider requests.
I explain this method here. Current service scope, prices, and terms are on TechTide AI.
Systems Decision Audit at TechTide AI→© 2026 Alex Cinovoj · TechTide AI · Columbus, OH