A task-level agent API explains what an operation accomplishes, when to use it, when not to use it, and what effect it can have. An endpoint shape alone explains how to send a request. Models selecting tools need both.
The word semantic can sound grander than the job. The practical change is simple: design tools around user tasks instead of database tables and internal service boundaries.
A valid endpoint can still be ambiguous
Consider this REST operation:
POST /users/{id}/status
{"value":"inactive"}
The method, path, body, and response can be fully documented. The contract still does not say whether inactive suspends login, stops billing, removes assignments, schedules deletion, or merely changes a CRM label.
A human developer reads surrounding docs and resolves that ambiguity once. A model may choose among several tools again on every run.
Put intent in the callable contract
Weak tool:
set_user_status
Set a user's status.
Task-level tool:
suspend_workspace_member
Temporarily block one member from signing in to this workspace.
Use when an administrator asks to suspend access without deleting the account.
Do not use for billing cancellation, workspace deletion, or permanent data removal.
The second description tells the model the task, authority, effect, and exclusions. Its schema should still identify the workspace, member, reason, and approval or operation ID where required.
The MCP tool specification gives every tool a name, description, input schema, optional output schema, and annotations. It does not write those boundaries for you.
Map one task to the minimum useful result
An agent choosing its next step rarely needs the backend's complete response. Return the fields that decide what happens next.
For an order lookup, that may be:
{
"orderId": "1842",
"status": "shipped",
"estimatedDelivery": "2026-09-02",
"canCancel": false
}
Do not return internal database columns, provider tokens, or a 200 KB payload and ask the model to rediscover the answer. The REST-to-MCP guide shows the translation layer that can combine several internal calls into one task result.
State side effects and failure behavior
For every tool, document:
- whether it reads, writes, spends, sends, or deletes;
- which caller and resource authorization applies;
- whether approval is required;
- whether the operation is safe to retry;
- which stable failures change the next action;
- which result fields are authoritative.
Tool annotations can help a client present risk, but clients must treat annotations from untrusted servers as untrusted. Enforce the real restriction in policy and the backend.
Keep similar tools distinct
Overlapping tools need explicit exclusions. If the server exposes search_customers, find_contacts, and query_accounts, each description should say which entity and task it owns. If you cannot write a clear distinction, combine the tools or remove one.
The guide to debugging wrong tool selection starts with the tool list and call trace before changing the system prompt.
Test selection separately from execution
Create prompts that should choose each tool and prompts that should choose neither. Freeze the tool list, descriptions, model, and settings. Record selection before executing anything.
Then test execution with valid, invalid, unauthorized, and repeated inputs. A tool can be easy to select and still unsafe to call.
Rewrite the closest pair first
Find the two tools whose descriptions share the most words. Write the task, use condition, exclusion, side effect, and next-step result for each. If the distinction remains fuzzy, the implementation boundary is probably leaking into the agent interface.
The prompt below performs that ambiguity test and creates a focused evaluation set.