Your MCP Server Needs a Capability Budget, Not Just Auth A developer proposes that MCP servers need a 'capability budget' in addition to authentication, defining a short-lived contract that constrains tool actions, targets, resources, quantity, and expiry. The runtime should revalidate the budget at every stage, and a durable ledger is essential to handle interruptions and avoid duplicate calls. The approach aims to improve security and reliability for AI agent tool invocations. Most MCP security checklists stop at “is this caller authenticated?” That is necessary, but it does not answer the operational question: what is this tool allowed to do during this run? A useful boundary is a capability budget: a short-lived, explicit contract for each tool invocation. It should constrain the action, target, resource, quantity, and expiry. The model can request a tool, but the runtime decides whether the request fits the contract. Start with a deliberately boring schema: type CapabilityBudget = { runId: string; tool: string; actions: string ; resources: string ; maxCalls: number; maxBytes?: number; expiresAt: string; approval: "none" | "human"; policyVersion: string; }; For example, a code-review run might receive: { "runId": "run 8f2", "tool": "github.create comment", "actions": "comment" , "resources": "repo:acme/api:pull:481" , "maxCalls": 1, "expiresAt": "2026-08-14T03:00:00Z", "approval": "human", "policyVersion": "p17" } The important part is what is absent: no repository-wide write permission, no issue creation, and no unbounded retry allowance. Do not check the budget only when the agent plans the call. The queue, worker, and tool adapter should all treat the budget as untrusted input and revalidate it. A dispatch decision can be reduced to: If steps 4 and 5 cannot be made durable, a worker crash can turn one approved call into several attempts. That is a reliability bug as well as a security bug. Let the model propose a sequence, but make the runtime spend from the budget one reservation at a time. A plan such as “inspect, patch, test, notify” should not silently inherit write capability from the first step. A minimal ledger makes this visible: | reservation | tool | requested | decision | outcome | |---|---|---|---|---| | r1 | repo.read | 1 call | allowed | confirmed | | r2 | repo.write | 1 call | approval required | pending | | r3 | slack.send | 1 call | denied | not dispatched | Keep pending and unknown distinct. Pending means no dispatch has been recorded. Unknown means dispatch may have happened but confirmation was lost. Only the latter requires provider lookup or an idempotency-key reconciliation before retry. A capability budget is only real if it survives interruptions. Inject at least these cases: For every case, record the expected ledger state, whether a provider lookup is required, and whether a human must reapprove. A green test suite that never forces an unknown outcome is testing the happy path, not the boundary. If this runtime must stay available for queued work or browser-assisted tasks, hosting is part of the control plane. A managed runtime such as managed OpenClaw hosting on Ampere https://ampere.sh/?utm source=devto&utm medium=article&utm campaign=mcp-capability-budget can be evaluated as one deployment option, but it does not replace capability checks, prompt-injection defenses, credential scoping, or reconciliation logic. The questions to verify are practical: where durable run state lives, how workers restart, how credentials are mounted, how logs are retained, and how you rebuild the same policy version on a clean host. Treat the hosting choice as an availability and recovery decision, not as an authorization decision. Before calling an MCP integration production-ready, verify: Authentication answers “who is asking?” A capability budget adds “what may happen, where, how often, and until when?” That is the boundary worth reviewing.