Designing MCP Tools for Business Systems

Table of contents
The fastest way to make an MCP tool useless is to wrap an entire API in one tool and call it done. It compiles. It even works in a demo. Then an agent calls it with the wrong combination of twelve optional parameters, gets back a response too large to reason about, and the whole thing falls apart the first time it meets a real question.
A good MCP tool is shaped like a task, not like an API endpoint.
The problem with API-shaped tools
Most teams design their first MCP tool by taking a REST client and exposing its methods directly: callSalesforceApi(method, path, body), or queryDatabase(sql). This feels efficient because it’s one tool that can do anything the underlying system can do. That’s exactly the problem. An agent now has to figure out, from scratch, on every call, which method, which path, which fields matter, and what a well-formed request even looks like for this specific question.
Nothing about that is an MCP tool’s job. It’s an API client’s job, and the agent is now doing the work the client library used to do, worse, one guess at a time.
Name tools after the task, not the system
Nexus’s MCP tools are search, search_slack, search_code, search_wiki, who_knows, recent_prs, and ripgrep_code. Every one of them answers a specific question an engineer would actually ask. None of them is named after a table, an endpoint, or a parameter. That naming isn’t cosmetic: it’s what lets an orchestrating agent pick the right tool from its name and a one-line description, without needing to understand the system underneath at all.
If you can’t name a tool after the question it answers, it’s probably still shaped like an API, not a task.
Keep inputs and outputs narrow
A task-shaped tool takes the handful of inputs that question actually needs, nothing more. search_slack(query, channel?) is reasonable. search_slack(query, channel, author, date_from, date_to, thread_only, sort_by, limit, offset, include_reactions) is an API again, just with a friendlier name on top.
The same discipline applies to the output side. Cap list results. Return the fields the task needs, not the whole underlying record. An agent that gets back 200 rows with 40 fields each has to spend its own reasoning figuring out what matters, which is work the tool should have already done.
One tool, one job, no mode flags
Watch for a tool that takes a mode or action parameter and behaves like three or four different tools depending on its value. That’s a sign the tool boundary is in the wrong place. Split it. sync_source(mode: "full" | "incremental" | "dry_run") is really three tools wearing one name, and an agent has to correctly guess which mode fits before it can even start.
Nexus avoids this everywhere it can. recent_prs only returns recent pull requests. It does not also create one, close one, or merge one under a flag. A tool that always does exactly one thing is a tool an agent can call without a round of trial and error first.
flowchart TB
accTitle: Task-shaped tool versus API-shaped tool
accDescr: An API-shaped tool exposes raw methods and parameters and leaves the agent to figure out a well-formed request on every call. A task-shaped tool answers one specific question with narrow inputs and bounded output, so the agent can call it correctly on the first try.
subgraph API["API-shaped"]
direction TB
A1["callApi(method, path, body, headers, ...)"]
A2[Agent guesses the right request]
A3[Large, unbounded response]
A1 --> A2 --> A3
end
subgraph TASK["Task-shaped"]
direction TB
B1["search_slack(query, channel?)"]
B2[Narrow, obvious inputs]
B3[Bounded, relevant output]
B1 --> B2 --> B3
end
Keep the tool LLM-free where you can
A tool that does its own scoring, filtering, and ranking internally, in plain code, is faster and cheaper than one that dumps raw data and asks the calling agent to make sense of it. Nexus’s retrieval tools run full-text search, vector search and reranking entirely inside the tool, with no model call required to use them. The agent decides which tool to call and what to do with the answer. The tool itself stays deterministic.
That split matters for cost and for reliability. An LLM-free tool behaves the same way every time it’s called with the same input, which makes it something you can actually test.
Pitfalls
- Tool sprawl. Dozens of narrow tools is still better than one giant one, but past a certain count, an agent’s attention starts to fragment across tools it rarely needs. If you’re hitting that ceiling, it’s usually a sign to split into separate, domain-specific agents rather than adding yet another tool to one agent’s list.
- Descriptions that describe the implementation instead of the task. “Runs a parameterized SQL query against the orders table” tells an agent nothing about when to use it. “Looks up an order’s current status by order ID” does.
- Silent truncation. If a tool caps its results, say so in the response, not just in a comment in the code. An agent that doesn’t know it got a partial answer will treat it as complete.
Wrapping up
An MCP tool earns its place by answering one real question, with inputs an agent can guess correctly and output it can use without extra cleanup. Start from the task a person actually asks, not from the system’s API surface, and most of the rest follows from that one decision.
FAQ
How many MCP tools is too many for one agent?
There’s no fixed number, but if you find yourself writing tool descriptions just to help the agent tell two similar tools apart, that’s the signal. At that point it’s usually healthier to split the work across multiple narrower agents than to keep adding tools to one.
Should a tool call another tool internally?
It can, as long as that composition is deterministic and hidden from the calling agent, who just sees one clean input and output. What you want to avoid is a tool that itself makes an LLM call to decide what to do next; that’s agent behavior wearing a tool’s name.
Is it better to have fewer tools with more parameters, or more tools with fewer parameters?
More tools with fewer parameters, almost always. A parameter an agent has to infer correctly is a chance to get it wrong. A separate tool with an obvious name removes that guess entirely.


