alexcinovoj.devby TechTide AI
Back to AI notes
Pattern · AI agent testing

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.

Short answer

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.
Read-only tool declaration
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

Related patterns

I explain this method here. Current service scope, prices, and terms are on TechTide AI.

Systems Decision Audit at TechTide AI