AuthZ for MCP servers: how to block, allow, and rate-limit MCP tools

MCP servers hand powerful capabilities to AI agents — file access, shell execution, database queries, HTTP calls. Authorization is how you decide which of those an agent is actually allowed to invoke, and how often.

Published · Updated

Why MCP authorization matters

Most MCP servers are binary: either the agent can call every tool the server exposes, or it can't connect at all. That's fine for a read-only docs server. It's not fine for a filesystem server with a write_file tool, a shell-exec server with a run_command tool, or a database server that can drop tables.

A few concrete scenarios where authz matters:

Authentication vs authorization in MCP

Two related concepts that often get conflated:

In a local-first workflow, where every MCP server runs on your machine, the interesting unit of authz is the tool, not the user. You know who's calling (it's you, or an agent you started). The question is which tools you want that agent to have.

Two enforcement models

Blocklist mode

Default-allow, with specific tools denied. Most permissive. Best when you mostly trust a server but want to rule out a few dangerous calls. Example: allow everything from a filesystem MCP server except delete_file and move_file.

Allowlist mode

Default-deny, with specific tools enabled. Most restrictive. Best when you're auditing a new server or when you only need one or two tools from a larger surface. Example: from a GitHub MCP server that exposes 20 tools, only allow search_repositories and get_file_contents.

Both modes are per-server. You can run one server in allowlist mode and another in blocklist mode in the same hub.

Rate limiting

Independently of block/allow, you can cap how many times a specific tool is called per minute. Rate limiting matters for two reasons:

When a rate limit trips, the tool returns an error to the agent. Most agents will back off and try a different approach instead of spinning on the failure.

AuthZ in AppContext's MCP Hub

AppContext's MCP Hub is a natural place to enforce authz because every tool call from every connected AI client routes through it. AppContext stores policies in ~/.appcontext/policies.json and evaluates them in-process before forwarding calls to upstream servers.

Per-server mode + per-tool toggles

In the Servers tab of the app window, each server has a mode toggle (blocklist / allowlist) and a list of its tools. Click a tool name to flip its authorization. Blocked tools return a structured POLICY_BLOCKED error to the AI client.

Per-tool rate limits

Each tool can be assigned a max-calls-per-minute limit. When the limit is exceeded, the tool returns a rate-limit error. The limit resets on a rolling 60-second window.

Readable and writable from the agent side

Policies aren't only a UI concept. AppContext exposes a hub_policies tool over MCP with a list action that returns each server's mode, its per-tool state, and its rate limit, plus block_tool, unblock_tool, and set_rate_limit actions. That means you can ask a connected agent "which tools are currently blocked?" and get an answer without opening the app window — and the agent's own attempts to widen its permissions are subject to the same licensing checks as the UI.

Persisted and portable

Policies live in a JSON file at ~/.appcontext/policies.json. They survive app restarts and can be committed to a dotfiles repo if you want to share authz configuration between machines.

Why enforce authz at the hub, not the server?

If you enforce at the server, you have to configure it N times for N servers — and not every server supports authz anyway. Enforcing at the hub gives you one consistent policy surface across every MCP server you use, whether or not the upstream supports authz natively.

A worked example

Suppose you've added three upstream MCP servers to your hub:

A sensible default policy for a coding session might be:

Set a rate limit of 10 calls/minute on anything that hits a remote API, so an agent loop can't drain quota.

What's coming next

The current policy engine is per-tool and per-server. On the roadmap:

If any of those would be valuable to your workflow, we'd love to hear about it — contact@appcontext.dev.

Frequently asked questions

What's the difference between authentication and authorization in MCP?

Authentication answers who is calling a tool. The MCP specification defines an optional OAuth 2.1-based authorization flow for HTTP transports, while stdio servers are expected to take credentials from their environment instead. Authorization answers whether a caller may invoke a specific tool right now — in a local-first setup, that per-tool decision is usually the one you actually need.

Should I use blocklist or allowlist mode?

Blocklist mode is default-allow with specific tools denied — use it when you broadly trust a server but want to rule out a few destructive calls. Allowlist mode is default-deny — use it when auditing a new server or when you only need one or two tools from a large surface. Modes are set per server, so you can mix them.

Where are the policies stored?

In ~/.appcontext/policies.json. Policies survive app restarts and can be committed to a dotfiles repo to share authorization configuration between machines.

Control what your AI can do

Download AppContext and set authz policies across every MCP server you use.

Get AppContext Free