Gemini CLI says MCP is connected: why the tools are still missing
An MCP server is a separate process or remote service that advertises tools to Gemini CLI over the Model Context Protocol. Gemini CLI reads the server list from mcpServers in settings.json, connects when the session starts, and registers each tool it finds under a name like mcp_github_create_issue.
"Connected" describes the connection. It says nothing about whether the tool list reached the model.
Run gemini --version first. This page describes the stable v0.65.0 line; the discovery code changed several times in 2026, and some older failures are already fixed.
Checked against Gemini CLI's documentation on 27 October 2026.
Status, 27 October 2026: in the source read for this page (commit 363a131), a server is marked CONNECTED before tool discovery, and a discovery error does not reset the status. The policy page also still warns that workspace policies have no effect (#18186, open). Unpaid-tier and Google One users were moved to Antigravity CLI on 18 June 2026, so this page applies to paid, API-key, Vertex AI and enterprise installs; the Gemini CLI hub has the details.
What "connected" actually means#
A working MCP tool passes six stages:
- Configured. The server is in a settings file the session reads.
- Enabled. Nothing has switched it off.
- Connected. The transport handshake succeeded.
- Discovered. The server returned a tool list.
- Exposed. No filter removed the tool.
- Chosen. The model called it.
/mcp covers the middle of that pipeline. It shows each server's status and the active tools in the session's tool registry. It is the best in-product view of what the main agent is offered; subagents have their own registries.
A connected server can have zero tools. In the source at commit 363a131, McpClient.connect() sets the status to CONNECTED as soon as the transport handshake succeeds, then discoverInto() fetches tools and prompts. If discovery throws, the manager logs the error and leaves the client connected (MCP client source, manager source). /mcp can show a connected server with nothing under it.
A tool can also disappear from /mcp after discovery. /mcp reads the registry, and the registry's getAllTools() returns only active tools: it keeps an excluded tool so it can be enabled later, but does not include it in that list (tool registry source). A deny rule or tools.exclude therefore makes the tool vanish from /mcp too. That absence is the clue, not a contradiction.
/mcp schema <server> prints the active names, descriptions, and parameter schemas; /mcp desc drops the schemas; /mcp reload reconnects and rediscovers.
Do not use /tools for this. In the same source it filters out every tool with a server name, so MCP tools never appear there, working or not.
Check it in order#
Outside the session:
gemini --version
gemini mcp listgemini mcp list opens its own short-lived connection and prints each configured server as Connected or Disconnected. It is a second opinion, not the session's state. It also applies folder trust, so in an untrusted folder a working stdio server (a local command the CLI starts) can still print as disconnected.
Inside the session:
/mcp
/mcp schema <server>
/policies list
/permissions trustThen read the settings files:
jq '.mcpServers | keys' ~/.gemini/settings.json
jq '.mcpServers | keys' .gemini/settings.json
jq '.mcp, .tools.exclude' ~/.gemini/settings.json .gemini/settings.jsonIf jq is not installed, open the files; they are small. Disabled servers are recorded in ~/.gemini/mcp-server-enablement.json.
| What you see | What it usually means |
|---|---|
/mcp lists the server but no tools | Discovery failed, the server exposes no tools, or every tool was filtered |
/mcp lists the tool, the model says it does not exist | The model used a different name, or the tool is only available to a subagent |
/mcp shows no connected server | Wrong settings file, disabled server, a server filter, or an untrusted folder |
Scope, merge, and folder trust#
Scope comes first. gemini mcp add writes to the project file by default; add -s user for your user file. A server added in one repository is not there when you start in another.
Current versions merge the two mcpServers maps by server name. A server defined only in your user file stays available. A project entry with the same name replaces the user entry as a whole, so its args, env, and trust are not combined with yours (settings schema, merge code). For a user or project entry, an override that only sets excludeTools leaves the server without a command or URL; extension-provided servers merge field by field. Until December 2025 a project list could replace the global one; that was fixed.
mcpServers is marked as requiring a restart. /mcp reload reconnects servers the session already knows about; after adding or renaming one, start a new session.
Several gates can remove a server before it connects. --allowed-mcp-server-names limits the run to the names you list (CLI reference); mcp.allowed and mcp.excluded do the same from settings, and if mcp.allowed is set, only those names connect (MCP docs). Servers supplied by an extension disappear when the extension is disabled.
Folder trust is a separate switch. When it is on and the folder is untrusted, the CLI skips the project's .gemini/settings.json entirely, so servers defined there never appear. It also refuses to start any MCP server, including ones from your user settings. Folder trust is controlled by security.folderTrust.enabled; the settings reference lists true as the default while the trusted-folders page says the feature must be enabled. Check /permissions trust rather than assuming.
A filter removed the tool#
Filters run in two places, and they use different names.
At discovery. includeTools and excludeTools on a server use the server's own tool names, such as create_issue, not the mcp_github_create_issue name the model sees. excludeTools wins when a tool is on both lists. If the allowlist matches nothing and the server exposes no prompts or resources, discovery finds nothing, and the server can still show connected with an empty tool list.
After discovery. tools.exclude in settings.json and a policy deny remove a tool from the model's view. The policy engine is Gemini CLI's rule layer: TOML files under ~/.gemini/policies decide whether a tool call is allowed, denied, or needs confirmation. For a rule without an argsPattern, a deny decision excludes the tool from the model entirely (policy engine). The tool disappears from /mcp as well, because the command lists only active tools.
Check /policies list for a matching rule. A broad toolName = "mcp_*" rule, or toolName = "*" with mcpName = "*", hides every MCP tool. Also check the legacy tools.exclude array. A server can be switched off without being removed: /mcp disable <name> reports it as Disabled, and /mcp enable <name> brings it back.
One limitation matters here: the policy page says the Workspace tier is disabled, so rules in .gemini/policies do not take effect (#18186, open). Put the rule in ~/.gemini/policies or in an admin policy.
The name changed#
The model never sees the server's raw tool name. It sees a fully qualified name: mcp_ + server name + _ + tool name. /mcp schema prints it; use that exact string in instructions, hooks, and subagent tool lists. In policy rules, prefer the mcpName field.
The transformation (the name generator) is lossy in ways that matter:
- Characters outside letters, numbers,
_,-,., and:become underscores. - Names longer than 63 characters are shortened in the middle with
.... - The docs warn against underscores in server names. The policy parser splits
mcp_server_toolat the first underscore aftermcp_, somy_servermakes the server identity ambiguous and wildcard rules can fail silently.
Hyphens survive, but one report has the model rewriting them as underscores; name the exact string in your prompt and keep server names simple (#25952, closed as not planned on 23 July 2026).
Subagents add another layer. A subagent is a separate agent the main session starts for a scoped job, defined in .gemini/agents or ~/.gemini/agents. Its tools: list accepts mcp_* for all MCP tools and mcp_my-server_* for one server; omit it and the agent inherits the parent's tools. Servers declared inline in an agent's mcp_servers (the docs' mcpServers spelling is rejected by the loader; see the skills guide) are isolated to that agent, so the main session cannot call them (subagents).
Discovery failed, or the token expired#
Some failures happen after "connected" and before the model.
A single bad tool is the quiet one. Discovery handles tools one at a time: if building one tool's declaration throws, that tool is skipped while the rest register, and the server can stay connected with a shorter list (MCP client source above). The late-2025 cluster involved JSON Schema $defs and $ref (named definitions and the pointers that reuse them); reports against Docker Desktop's gateway, Snowflake, BEADS, and Basic Memory were closed after November 2025 fixes (#13053, #13142, #13326). Update an older build before debugging the server.
OAuth (the browser-based token flow some remote servers require) is the time-dependent one. Remote servers that use it store tokens in ~/.gemini/mcp-oauth-tokens.json; /mcp auth <server> runs the browser flow and reloads the tools (MCP docs). A refresh could write a new token while the live transport kept using the old one; that report was closed as fixed on 13 May 2026 (#18895). If a working server starts failing after a token expires, re-authenticate, then /mcp reload or restart before touching the config.
One failure is not about a single server: if every prompt fails with At most 512 function declarations can be specified, the request carries too many tools for the API. Disable unused servers (/mcp disable, or --allowed-mcp-server-names). A request to raise the limit was closed without a change (#19083, closed 24 May 2026).
When the tool is visible and still not called#
If /mcp schema shows the tool and no filter matches, the connection did its job. What remains is tool selection: the model reads the name, description, and parameter schema and decides whether to call it. That is probabilistic, not a switch.
Three levers:
- Make the description say when to use the tool, not just what it does. Gemini CLI passes the server's description through; a one-line description gives the model little to match against.
- Reduce the field. Every enabled server adds declarations to every request, and a large list makes any one tool easier to overlook. Disable servers you are not using.
- Say the exact name once: "Use
mcp_github_create_issuewith these arguments." If the model calls a different name, check that your instruction did not use the server's raw tool name.
That is the boundary: a model ignoring a tool it can see is not a connection problem, and reinstalling will not change it.
Where to go next#
- Gemini CLI guides — the rest of the set.
- Why Gemini CLI keeps asking for permission — what happens after an MCP tool is chosen, including session and persistent approvals.
- Why your Gemini CLI skill or subagent never activates — if the tool is scoped to an agent rather than the main session.