I opened issue #24246 the night I added my fifth MCP server. The title says "more than 128 tools" gives a 400; the body says "more than 400 tools." The same page disagrees with itself about the number.
So the first thing I'd like to say is that as far as I could confirm, the limit isn't documented anywhere official. The issue was filed in March 2026, was still open when I read it, and has no error text or reproduction steps attached.
Even so, there's something worth doing. Without a settled number, the direction still helps with diagnosis: the more tools you load, the closer you get to failure.
First, find out how many tools are loaded
Running /mcp shows each server's status and the tools it loaded. Counting them by eye is tedious, and a server without includeTools loads every tool it exposes.
The docs also say tool names take the form mcp_{serverName}_{toolName}, that names over 63 characters are shortened with ... in the middle, and that on a collision the last registered tool overwrites the earlier one. More tools means more chances for that to happen.
I was thinking "more servers, more convenience" and registered whatever came to mind, and I've regretted it since. The result wasn't good. When it stopped, I couldn't tell which server to remove.
Decide the task's kit with includeTools
According to the official docs, includeTools means only the listed tools are available from that server, and excludeTools takes precedence if a name appears in both.
{
"mcpServers": {
"repo": {
"command": "npx",
"args": ["-y", "YOUR_REPO_MCP_SERVER"],
"includeTools": ["search_code", "read_file", "list_commits"],
"excludeTools": ["delete_branch"]
},
"tracker": {
"httpUrl": "https://example.com/mcp",
"includeTools": ["get_issue", "add_comment"]
}
}
}What this solves, in one line: read-only work doesn't carry write tools. Dropping write tools up front shrinks the count and also removes the chance of mis-clicking a confirmation.
Avoid underscores in server names. The docs note that the policy parser splits on the first underscore after mcp_, so my-repo is safer.
Turn the count into a budget, and count from the file
Instead of counting in the /mcp screen, count from the settings file. This script subtracts excludeTools from includeTools per server, sums them, and exits with 1 if the total is over budget or any server has no includeTools.
#!/usr/bin/env python3
"""Read mcpServers from settings.json and compare includeTools counts to a budget."""
import json, sys
BUDGET = 40 # my own line, not an official limit
def count(path: str) -> int:
with open(path, encoding="utf-8") as f:
servers = json.load(f).get("mcpServers", {})
total, unknown = 0, []
for name, cfg in servers.items():
inc = cfg.get("includeTools")
if inc is None:
unknown.append(name) # no includeTools = every tool is loaded
continue
n = len([t for t in inc if t not in cfg.get("excludeTools", [])])
print(f"{name:<20} {n:>3} tools")
total += n
for name in unknown:
print(f"{name:<20} everything (count unknown)")
print(f"known total {total} / budget {BUDGET}")
return 1 if (unknown or total > BUDGET) else 0
if __name__ == "__main__":
sys.exit(count(sys.argv[1] if len(sys.argv) > 1 else ".gemini/settings.json"))I ran it against a small sample config to confirm the totals and exit code. The 40 is a line I drew for my own work, not an official number. If a real limit is confirmed, that one line is all you change.
Treating "count unknown" as a failure is deliberate: servers without includeTools are the ones most likely to inflate the count behind your back.
Swap settings per task
Go one step further and keep one settings file per kind of work, such as profiles/review.json and profiles/triage.json, copying one into the project before you start.
#!/usr/bin/env bash
# Usage: ./use-profile.sh review
set -euo pipefail
name="${1:?give a profile name}"
src="profiles/${name}.json"
[ -f "$src" ] || { echo "not found: $src" >&2; exit 2; }
mkdir -p .gemini
cp "$src" .gemini/settings.json
python3 mcp_budget.py .gemini/settings.jsonBecause the budget check runs right after the copy, an over-budget profile shows up before you launch the CLI. The order changes from "stop, then hunt for the cause" to "count before it can stop."
Restart the CLI after swapping, since MCP loading happens at startup. Startup MCP errors are silent by default; if you see MCP issues detected. Run /mcp list for status., open /mcp list first.
If you still get a 400
If you're within budget and still see a 400, look beyond the count.
- Run
/mcp listand look for any DISCONNECTED server - Add the most recently added server to
mcp.excludedand see if it still reproduces - Run the same task with a single server configured
- If it still reproduces, report it with the error text and tool count
A "stopped" CLI can also be a wrong model name; I wrote up that check in checking the model name first when 404 and 429 appear together, and closing non-exception failures with types covers sorting failures in code.
Issue #24246 lacks exactly the error text and reproduction steps. If you can reproduce it, adding your tool count and model name would help whoever reads it next.
Decide the kit per task, not per server. I'd rather stop adding things because they look handy and carry only what today's work needs. That's a line I intend to keep.
As a next step, open /mcp, pick one server without includeTools, and narrow it to the tool names you actually use.