Tool calling, MCP and secure agent execution
Design tool contracts and control external actions with permissions, idempotency, approval and auditability.
Tool contracts
A good description says when a tool should be used, which arguments it accepts, what it returns and when it must not be called.
{
"name": "get_order_status",
"description": "Read an order visible to the current user",
"parameters": {
"type": "object",
"properties": { "order_id": { "type": "string" } },
"required": ["order_id"],
"additionalProperties": false
}
}- Use short, stable, verb-object names.
- Describe limits and side effects, not only the happy path.
- Require explicit fields and reject unknown arguments.
- Return stable success and error structures.
- Derive authorization from the server-side session.
Tool-calling flow
The application declares tools, the model returns a name and arguments, the server validates and executes them, then returns a structured result for the model to continue or explain failure.
Goal -> model selects tool -> server validates schema, identity and permissions -> tool executes -> server records result and trace -> model continues or delivers an answerIndependent read-only calls may run in parallel, but writes and shared state need ordering, concurrency limits and cancellation.
Server-side implementation
Treat model output as untrusted input. A minimum executor needs an allowlist, schema validation, authorization, timeout, normalized errors and tracing.
async def execute_call(call, user):
if call.name not in ALLOWED_TOOLS:
return error("tool_not_allowed")
args = validate_schema(call.arguments)
authorize(user, call.name, args)
return await run_with_timeout(call.name, args, seconds=3)Side-effecting tools need an idempotency key such as user_id + operation + client_request_id so retries cannot duplicate payment, orders, messages or deletion.
MCP concepts
- Host: the agent application that owns the session and security policy.
- Client: the connection to a particular MCP server.
- Server: exposes tools, resources or prompts for an external system.
- Transport: carries protocol messages, commonly local STDIO or a remote HTTP-style transport.
- Authorization: determines access and must never be delegated to the model.
Function calling is usually a tool contract inside one model request. MCP adds cross-application discovery, connections, resources and server boundaries. An MCP server can be an adapter layer, but it still needs internal authentication.
Permissions, security and approval
- Derive tenant identity from the session instead of trusting a model argument.
- Require confirmation or human approval for deletion, payment, notifications and other high-impact writes.
- Isolate web or document content from system instructions to reduce prompt injection risk.
- Minimize, redact, audit and expire sensitive data.
- Review third-party MCP servers, allowlist tools and lock versions.
Failure recovery and idempotency
- Schema errors: fix arguments or re-plan; do not blindly retry.
- Network timeouts: use bounded exponential backoff with the same idempotency key.
- Rate limits: honor retry guidance, queue or degrade.
- Permission failures: stop and request authorization.
- Business conflicts: reread state before deciding whether a retry is safe.
Tool design checklist
- Clear name, description, schema and return structure.
- Server-enforced allowlist, permissions and tenant isolation.
- Idempotency, audit records and compensation for every side effect.
- Separate timeout and retry policies for model, tool and task.
- Structured human approval for high-risk actions.
- MCP servers, third-party APIs and document content treated as untrusted input.
Continue with agent evaluation and productionization.