How many tools should an MCP server expose?
Exposing your whole API to an agent makes it worse, not more capable. Tool choice is a selection problem, and every extra option makes the selection harder.

The instinct when generating an MCP server from an OpenAPI document is to expose everything. You have 300 endpoints, the generator can emit 300 tools, and more capability sounds like more value.
It is the opposite, and the reason is worth understanding because it is not a limitation anyone is going to engineer away soon.
Tool choice is a selection problem
Every tool you expose is an option a model has to consider on every step. The tool list goes into context, competes for attention with the actual task, and gets re-evaluated each time the agent decides what to do next.
Three things degrade as that list grows.
Selection accuracy. With eight tools, picking the right one is easy. With two hundred, many of which are near-duplicates that differ in one parameter, the model is doing disambiguation rather than work. listUsers, listUsersByOrg, listActiveUsers and searchUsers are four plausible answers to one question, and the model has only the names and descriptions to go on.
Context budget. Tool definitions are not free. Each carries a name, a description and a parameter schema. Several hundred of those is a meaningful fraction of a context window spent before any work happens, and it is spent again on every turn.
Blast radius. More tools means more surface an agent can reach when it reasons its way somewhere unexpected. This is the safety argument, and it is real, but the accuracy argument bites first and bites everyone.
The rule of thumb, and its edges
The pattern the ecosystem has landed on in 2026 is roughly this: under about twenty endpoints, all of them relevant to what an agent would do, pure auto-generation is fine. Above that, generate and then curate.
That number is a proxy for something more useful. The real question is not how many endpoints you have. It is how many distinct things an agent might reasonably want to do.
An API with eighty endpoints where sixty are CRUD variations on the same eight resources probably has around a dozen agent-relevant operations. An API with fifteen endpoints that each do something genuinely different might want all fifteen.
Count intentions, not routes.
How to pick the subset
Start from what you would want an agent to accomplish, not from your endpoint list. Write down the three or four jobs someone would ask an assistant to do with your API. Then work backwards to the operations those jobs need.
What usually survives:
Reads that answer questions. Get one thing by id, list a collection with a filter, search. These are the tools an agent uses constantly and they are safe.
The one or two creates that represent your product's core action. Creating an invoice, opening a ticket, starting a job. The thing people integrate your API to do.
Anything an agent needs to check its own work. If a create returns an id, the read that resolves that id belongs in the set.
What usually should not:
CRUD completeness for its own sake. You do not need update, partialUpdate and replace as three tools. Pick the one a caller should use.
Every filter variant as its own operation. If listUsers takes a status parameter, you do not also need listActiveUsers. Parameters are cheaper than tools, because a parameter is a field the model fills in rather than a decision it has to make first.
Administrative and internal operations. Same list you excluded from your public SDK.
Anything irreversible. Deletes, refunds, anything that sends a message to a human. Not because an agent is careless but because the failure is unrecoverable and the value of automating it is close to zero.
Names and descriptions do more work than the count
Once the set is chosen, the text matters more than people expect. A tool description is not documentation. It is a decision aid read by a model choosing between options, and it should answer one question: when should I use this instead of the others?
Bad: "Lists users."
Good: "Lists users in an organisation, newest first. Use when you need
several users or do not know a specific id. To fetch one known
user, use get_user instead."That cross-reference is the part almost nobody writes, and it is the part that fixes the most selection errors. If two tools are frequently confused, saying so inside both descriptions is more effective than renaming either.
Names carry the same weight. A model reads create_invoice as an action. It reads postV1InvoicesCreate as a string it has to parse a transport detail out of. If your tool names come from operationIds that were written for a code generator, they are probably wrong for this audience.
Curation is not a one-time task
The set that is right at launch is not right six months later, because you will learn which tools agents actually reach for and which ones they never touch or always misuse.
Log the tool calls. The distribution is usually lopsided: a handful of tools carry nearly all the traffic and a long tail is never selected. That tail is costing you context on every turn and buying nothing, and removing it typically improves accuracy on the tools that matter.
Look also for the tools that get called and then immediately followed by a correction. That is a naming or description problem, not a capability problem.
Where the configuration should live
The practical version of all this is that curation should not be a separate artifact you maintain by hand, because a hand-maintained list drifts from the API it describes.
The version that holds up is one where the tool set derives from configuration you already keep: the endpoints you excluded from your public SDK stay excluded from the tools, the method names you overrode carry through, and a deprecated operation is surfaced as deprecated. One decision applied in both places, rather than an agent permissions system to keep in sync with a client library.
That is how Octri builds it: the MCP server is a projection of the same SDK configuration, so the curation you did once is the curation the agent gets. Generating an MCP server from an OpenAPI spec covers the setup, and what to exclude first covers the safety half of the same decision.
Start narrow. It is much easier to add a tool that people ask for than to work out which of your two hundred is the one confusing the model.



