An MCP server is often introduced as a convenient adapter between an assistant and an API. Security-wise, it is a privileged gateway accepting model-influenced requests.
The important question is not whether a tool is called read_dashboard or fix_incident. It is which identities, resources, side effects, and networks the implementation can reach.
Inventory authority per tool
| Tool | Read scope | Write scope | Credential | Approval |
|---|---|---|---|---|
get_metric |
one tenant, named metric | none | read-only service token | none |
create_ticket |
incident summary | ticket system | create-only token | preview |
restart_service |
service status | one deployment | short-lived workload token | exact-call approval |
Do not give every tool the server process's full credential. Split read and write identities, scope them to a tenant and resource class, and mint short-lived tokens near execution.
Treat arguments as untrusted
const Restart = z.object({
service: z.enum(["api", "worker"]),
environment: z.literal("staging"),
reason: z.string().min(20).max(500),
operationId: z.string().uuid(),
}).strict();
Strict schemas reject unexpected fields. Server-side authorization must still verify the caller, tenant, current resource state, and policy version. Never turn a model-provided URL, path, shell fragment, SQL clause, or header into raw authority.
For consequential calls, show a preview generated from validated arguments. Bind approval to the user, tool name, canonical arguments, policy version, resource version, and expiry. If any changes, ask again.
Log evidence, not secrets
Record request ID, actor, tool, canonical argument hash, target resource, policy decision, credential identity, result class, and timing. Redact tokens, cookies, prompts containing credentials, and raw third-party responses. Make duplicate operationId calls return the original result instead of repeating a side effect.
Test prompt injection in tool output, cross-tenant IDs, unknown arguments, stale approval, duplicate delivery, timeout after a successful remote write, credential revocation, and log redaction.
The public MonkeyCode repository describes model management, AI tasks, development environments, and private deployment. MCP-style integrations may be relevant to such platforms, but this article neither claims a current MonkeyCode MCP implementation nor reports a security test of one.
Disclosure: I contribute to the MonkeyCode project. Product context comes from public documentation; the threat model is tool-independent.
Naming a capability as a tool does not reduce its authority. Design the gateway as though untrusted input can reach every exposed schema—because eventually it will.
Top comments (0)