Should you wire every vendor MCP server into the agent, or put a consolidation layer in front? When two or more sources can answer the same kind of question, put a consolidation layer in front. The layer exposes a small number of larger tools shaped around the questions your users ask, and it decides in code which source is authoritative for each one. It returns structured JSON, authenticates every request as the user, and logs every call. A direct wire stays reasonable for one read-only source with a single owner, and it stops being reasonable once a second source for the same question arrives.
The default goes the other way because each vendor server is built to be complete for its own product. It mirrors the vendor's API, so it ships many small tools, one per endpoint, and if you connect six of those the agent holds the union of their definitions on every turn. Every question then starts with the same unpaid work of deciding which system has the answer and whose version to trust. The model does that work in tokens, differently each time, and when it picks wrong nothing in the answer says so.
This guide covers what the direct approach costs, what the consolidation layer should own, and how large one tool should be. It then covers structured output, authentication, rate limits and logging, and how the call log decides the next change. Two other guides sit on either side of this one. How to scope AI agent permissions covers who may call a tool. Agent playbooks as MCP tools covers how an agent finds the right workflow in a large catalog.
What does wiring every vendor server cost?
Every MCP tool definition the client loads is text in the context window, on every request, whether the task needs it or not. With one server that cost stays small enough to ignore. With several servers of many tools each, the definitions become a large share of what the model reads before the user's question. Several of them describe near-identical operations from different vendors, and the model has to tell them apart from their descriptions alone.
The token cost is the visible part, and the expensive part is the decision each question now carries. Scale Venture Partners described this in their write-up of the MCP server behind their investment research:
If we simply connected 12 vendor MCPs to Claude Cowork, every time a user asked a question, the model would burn tokens trying to figure out which to use, who's data to trust, and how to go forward.
We saw the failure behind that sentence on Solarpunk, a product that works across more than a hundred tools. With every tool in context, selection held until somewhere around thirty tools and then went quietly wrong. The model returned a confident result from the wrong system, and that error cost more than the context did because it did not look like an error.
Maintenance degrades in the same arrangement, for a different reason. Each direct wire brings its own error shapes and its own quirks into the agent's prompt, and a vendor change breaks something unrelated, days later. On Solarpunk the fix was one uniform tool layer with nothing wired point-to-point, and vendor changes stayed contained to a single integration after that.
This figure is an illustrative model, and the six sources and four tool names are examples chosen to show the shape. They are not a count from any system, and the figure does not claim that the problem starts at six.
The two halves reach the same data, and they differ in where the choice of source is made. In the top half the model makes that choice on every question, while in the bottom half an engineer makes it once, in code someone reviewed. The model asks a question and gets an answer from the source the team already decided to trust.
What should the consolidation layer own?
Think of this layer as an MCP server your team runs between the agents and the vendor systems. A proxy that re-exports each vendor's tools under one name does not count, because that moves the long tool list without shortening it. The layer owns the decisions that the agent would otherwise make badly and inconsistently.
| Responsibility | What the layer does | What happens when the agent does it instead |
|---|---|---|
| Source selection | A rule in code for each question type: which system is authoritative, and which is the fallback | The model re-decides per question, and two users get answers from different sources |
| Entity resolution | Resolves a fuzzy name to one record ID before any lookup | Answers blend two records for similar names, each correctly sourced and about the wrong entity |
| Output shape | Returns JSON with defined fields, units and as-of dates | The model parses prose and misreads a figure |
| Identity | Authenticates every request as the calling user | A shared key reaches the data, and the audit trail cannot say who asked |
| Rate limits | Limits by user and by tool, before the upstream vendor does | A reasoning loop spends the vendor quota for everyone |
| Call log | Records every call, allowed or refused | Nobody can see what the model actually asked for |
| Writes | Returns a preview before committing a change | The model commits a change nobody reviewed |
Entity resolution is the row teams underestimate most often. On Prospex, our prospect research engine, the hard problem was never collection. It was resolving one company or person across four sources whose schemas share nothing, where a single wrong merge carries into every later lookup. A profile can come out coherent and well sourced, and still describe the wrong person. Put resolution in the layer as its own step, and make every other tool take the resolved ID rather than a name.
The write row follows from our MCP servers practice of declaring each operation as a named tool with a typed contract, where a general-purpose escape hatch does not qualify. Keep reads and writes in separate tools, so a permission policy can allow one without the other. A write tool that previews first gives the guardrails and the human reviewer a concrete change to approve.
How large should one tool be?
A tool should match a question a user asks, not an endpoint a vendor ships. The vendor's API is organized around its data model, with separate calls for the company, its funding rounds, the investors in a round, and notes. A user's question crosses those boundaries, so a server that mirrors them makes the model plan and join four calls to answer one question.
Here is the same question answered with each of the two shapes:
| Skinny, endpoint-shaped tools | Larger, question-shaped tool | |
|---|---|---|
| Example | get_company, list_rounds, list_round_investors, search_notes | company_profile with an include list |
| Calls per question | Several, planned by the model | One, planned by your code |
| Where the join happens | In the model's reasoning, in tokens | In the server, in code you can test |
| Definitions in context | One per endpoint, per vendor | One per question type |
| Typical failure | A step skipped, or two results joined on the wrong key | The tool returns more than the question needed |
Scale's lessons section says the same from their production use:
The user experience has been much better with fewer, larger tools than with lots of little API style tools.
Larger does not mean general. A run_sql tool or a call_api tool that takes any endpoint is one tool in the list and every operation in practice. The model has to write the query, the policy cannot tell a read from a destructive write, and the log records a string instead of an intent. Keep the tool's scope to one question type, with typed options such as which sections to include, a date range, and an enum for the region.
This is roughly what a question-shaped tool's contract looks like, with illustrative fields:
{
"name": "company_profile",
"description": "One company's profile from our authoritative sources. Use after find_company has returned a company_id. Not for comparing several companies; use compare_companies.",
"input_schema": {
"type": "object",
"required": ["company_id"],
"properties": {
"company_id": { "type": "string" },
"include": {
"type": "array",
"items": { "enum": ["funding", "investors", "notes", "scores"] }
},
"since": { "type": "string", "format": "date" }
}
}
}The description names the prerequisite and the near-miss, and both earn their place. When two tools could plausibly answer a question, the description is all the model has to tell them apart. The line "not for comparing several companies" prevents a wrong pick that a longer list of the tool's features would not.
Split a tool when two uses need different permissions, different rate limits or different owners. A tool that reads CRM notes and a tool that writes them should never be one tool with a mode flag, since the permission check would then depend on an argument the model chose.
Why return structured JSON and not prose?
A model reasons more reliably over defined fields than over descriptive text, and every figure it quotes needs a source it can cite. Scale reported that early versions of their server returned richer, descriptive text from some endpoints. The model reasoned over it less reliably than over clean JSON, and tightening the schemas improved answer quality. We see the same with structured output on the generation side, and the argument runs the same way for tool results.
Give every group of fields a source and an as-of date, so the agent can say where a number came from. Return explicit statuses for the cases that are not data: not_found, not_permitted, stale and rate_limited. An empty array is ambiguous, and the model will often read it as "none exist" and tell the user so, when the truth was that the caller could not see the records.
Keep result sizes bounded, whatever the source holds. A tool that returns every note on a company since founding pushes the rest of the conversation out of the context window. Accept a since date or a limit, and when there is more, return a count and a continuation token so the agent can ask for the next page on purpose.
How should the layer authenticate, limit, and log?
One server in front of every source holds more reach than any one vendor server, so its controls have to be tighter. Scale's post describes validating the caller on every request, not once per session:
Every request to our server requires OAuth via Google, with OIDC token validation on every request, not just at session start.
Checking at session start only is the common shortcut, and it means a revoked user keeps access for as long as the session lives. On the tool layers we build for clients we also issue a short-lived, scoped token per run, so the credential expires with the run and the agent never holds the application's own credential. The upstream vendor credential stays inside the layer, and the model never sees it.
Rate-limit by user and by tool, inside your own layer. A reasoning loop can fire a burst of calls in seconds. Without a limit in your layer, the first thing to stop it is the vendor's quota, which then fails for every user at once. When the layer limits a caller, return rate_limited with a retry time, so the agent waits where it would otherwise switch to a worse source to get an answer.
Log every call, allowed or refused, with at least these fields:
- the tool and its version;
- the calling user and the agent or client;
- the validated inputs;
- the sources the layer read;
- latency and result size;
- the status returned, including refusals.
The refusals in that log matter as much as the successes. A tool that is refused often is either mis-permissioned or mis-described, and without the refused calls in the log you cannot tell which. Keep the log in the same observability stack as the rest of your services, because the question after an incident is usually which tool call touched which record.
How does the call log change the tools?
The call log shows how the model actually uses your tools, which is rarely how you expected when you wrote them. Scale's post describes agents reading the logs to find tool design improvements. In one case they saw users making repeated calls over a tool and added a batch mode. Build that loop on purpose.
This figure is a framework showing the order of work we run on a schedule. It does not report measurements from any system.
These are the patterns we look for, and the change each one usually calls for:
| Pattern in the log | What it means | Change |
|---|---|---|
| One tool called many times in a session with different IDs | The question is about a set, and the tool only takes one | Add a batch mode that takes a list |
| Two tools alternate for the same question type, and one result is discarded | Their purposes overlap | Merge them, or rewrite both descriptions with the near-miss |
| The agent fetches a large result and uses a few fields | The tool returns more than the question needs | Add an include list or filters |
| Validation errors cluster on one argument | The schema is unclear | Use an enum, add an example, or make the field required |
| An empty result followed by a retry with a different spelling | Entity resolution is missing | Add a resolve step and require the ID |
| A tool nobody calls | It costs context and answers nothing | Remove it |
After each change, re-run a fixed set of real questions and compare the tool paths, not only the final answers. A change that keeps the answers correct and doubles the calls per question has made the system slower. An answer-only check will not show it. Our evals guide covers how to build that question set from real failures.
When is wiring a vendor server directly the right call?
Consolidation has a cost: a service to run, an owner, and a release process for tool changes. For some setups it is not worth it, and the flowchart below is the order in which we ask.
This figure is a framework, and its questions are the order we ask them in. The "few dozen tools" threshold in the third question is a range reported by practitioners and consistent with what we saw on Solarpunk, and it is not a measured cutoff.
A direct wire is fine for one read-only source with one clear owner, provided the vendor's server already authenticates as the user and you can read its logs. A prototype that proves a workflow is worth building also qualifies. Revisit the choice when a second source for the same kind of question appears, since from then on the model chooses between sources on every question and that choice belongs in code.
How do you build the first version?
Start the first version from questions, not from vendors. The inventory of vendor endpoints tells you what is possible, and the questions tell you what to build.
- Collect the questions users actually ask the agent, from chat history or from the people who will use it. Group them into question types.
- For each question type, write down which source is authoritative and which is the fallback. That rule becomes code, and the model no longer has to make it.
- Build entity resolution first, as its own tool, and make every other tool take the resolved ID.
- Write one question-shaped tool per question type, with typed options and a description that names its near-misses.
- Return JSON with sources, as-of dates and explicit statuses. Separate reads from writes, and preview every write.
- Authenticate every request as the user, rate-limit by user and tool, and log every call from the first release.
- Review the call log on a schedule, change the tools, and re-run the question set after each change.
The agents calling this layer may also need shared definitions, so that "active customer" means the same thing in every client. That is a context problem as much as a tool problem, and our guide on one governed business-context layer covers it. We build the consolidation layer for clients as part of our MCP servers work.
Questions buyers ask
Should we connect every vendor's MCP server to our agent?#
Only when each vendor answers a different kind of question and you have few of them. When two or more sources answer the same question, the model has to pick a source and decide whose data to trust on every request. That costs tokens and produces inconsistent answers. Put a consolidation layer in front instead, and make the source choice once, in code.
What is an MCP consolidation layer?#
It is an MCP server your team runs between your agents and the vendor systems. It exposes a small set of question-shaped tools and decides which source is authoritative for each question. It resolves names to record IDs, returns structured JSON, authenticates each request as the user, applies rate limits, and logs every call. It does not re-export each vendor's tools under one name, because that keeps the long tool list.
How many tools should a consolidation MCP expose?#
Start with one tool per question type your users actually ask, plus a resolve tool for entities. There is no fixed limit, but on our Solarpunk build direct tool calling degraded somewhere around thirty tools, and practitioners report similar ranges. If the list is heading past a few dozen, add discovery or merge overlapping tools, and remove any tool the call log shows nobody uses.
Does fewer, larger tools mean one general query tool?#
No. A tool that runs any SQL or calls any endpoint is one entry in the list and every operation in practice. The model has to write the query, and the permission policy cannot tell a read from a destructive write. Keep each tool scoped to one question type with typed options, and keep reads and writes in separate tools.
How should a consolidation MCP handle authentication?#
Authenticate every request as the calling user and validate the token on every request, not only at session start, so a revoked user loses access immediately. Prefer short-lived tokens scoped to the run, and keep vendor credentials inside the layer where the model never sees them. Record the user on every call so the audit trail can say who asked for what.
How do we know when to change a tool?#
Read the call log on a schedule and look for patterns. Repeated calls over one tool with different IDs call for a batch mode. Two tools alternating for the same question call for a merge or better descriptions. Validation errors on one argument call for a clearer schema. After each change, re-run a fixed set of real questions and compare the tool paths as well as the answers.
Further reading
- Agent playbooks as MCP tools. How an agent finds the right workflow once the catalog is large.
- How to scope AI agent permissions. Who may call a tool, with which credential, for which action.
- One governed business-context layer for agent sprawl. Shared definitions behind one entry point.
- Dynamic tool discovery across 100+ integrations. Our Solarpunk build write-up, including the single tool layer.
- MCP servers and tool layers. Scoped tokens, per-tool permissions and an invocation record.
- Will McGinnis, Scale Venture Partners, How we built a Model Context Protocol server for investment research, 20 September 2026. The consolidation layer, OAuth per request, structured JSON, and call logs that led to a batch mode.