You want a different MCP server per project, so you drop a config file at the root of the repository. It's the most natural thing to try.
You start the CLI, and the log says it is using the project's file. But the tool list shows only the servers from your home-level config. The file you wrote is apparently being read, and yet nothing new has appeared.
From what I've read, the instinct at this point is to re-check your own syntax again and again. I'd suspect the log line first.
What I'd like to say up front
This symptom is reported in the official issue tracker (google-antigravity/antigravity-cli, issue #60). On v1.0.0, the reporter observed that:
- the project-level
.antigravitycli/mcp_config.jsonis discovered at startup, and the log says so - its
mcpServersentries are ignored and no server is spawned - only servers in the home-level
~/.gemini/antigravity-cli/mcp_config.jsonactually start
I haven't tracked every CLI version myself, so below I'll keep "what the issue says" and "what you can verify on your machine" apart.
What that log line doesn't promise
The log lines quoted in the issue look roughly like this:
project: discovered project ... via /tmp/agy-test-995/.antigravitycli
project: using project ... at /private/tmp/agy-test-995/.antigravitycli/mcp_config.json"using project" invites you to read it as "MCP servers from here will run." A later comment in the issue offers a different reading: .antigravitycli/ holds project identifiers, and it isn't one of the places where MCP config is looked up (the comment calls them customization roots).
If that's right, the line only says the project was found, not that the mcpServers inside will be used. That is a hypothesis from a commenter, not a behavior confirmed by the maintainers.
A probe that shows whether anything was spawned
To separate "my config is wrong" from "my config was never read," it helps to register a server whose startup is visible from the outside. This script appends one line to a log the moment it is spawned, and answers tools/list with a single marker tool.
What it solves: telling "configured correctly but never spawned" apart from "spawned but the tools aren't visible."
#!/usr/bin/env python3
"""Minimal MCP stdio probe. Logs one line at spawn, returns one tool from tools/list."""
import json, os, sys, time
MARKER = os.environ.get("PROBE_MARKER", "unnamed")
LOG = os.environ.get("PROBE_LOG", os.path.expanduser("~/probe_mcp.log"))
def log(msg):
with open(LOG, "a", encoding="utf-8") as f:
f.write(f"{time.strftime('%H:%M:%S')} pid={os.getpid()} cwd={os.getcwd()} marker={MARKER} {msg}\n")
log("spawned") # proof of startup; if this line never appears, the config was not read
for line in sys.stdin:
line = line.strip()
if not line:
continue
req = json.loads(line)
method, rid = req.get("method"), req.get("id")
log(f"recv {method}")
if method == "initialize":
result = {"protocolVersion": "2024-11-05", "capabilities": {"tools": {}},
"serverInfo": {"name": f"probe-{MARKER}", "version": "0.1.0"}}
elif method == "tools/list":
result = {"tools": [{"name": f"whoami_{MARKER}", "description": "Reports which config started me",
"inputSchema": {"type": "object", "properties": {}}}]}
elif rid is None:
continue # never answer notifications
else:
result = {}
sys.stdout.write(json.dumps({"jsonrpc": "2.0", "id": rid, "result": result}) + "\n")
sys.stdout.flush()Why it's written this way: log("spawned") sits before the loop on purpose. Even if the protocol exchange fails, the fact that a process was born is recorded. An empty log means the config wasn't read; a log line with no visible tools points at what happens after startup. That narrows the cause by one layer.
First, confirm the probe works on its own, without the CLI:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| PROBE_MARKER=local PROBE_LOG=./t.log python3 probe_mcp.py
cat t.log # four lines: spawned / recv initialize / recv notifications/initialized / recv tools/listMove it around and only watch the log
Register the probe in two places with different markers, so the log tells you which config started it.
{
"mcpServers": {
"probe_project": {
"command": "python3",
"args": ["/path/to/probe_mcp.py"],
"env": { "PROBE_MARKER": "project", "PROBE_LOG": "/path/to/probe.log" }
}
}
}Put this once in the project's .antigravitycli/mcp_config.json, and once in the home-level config (the issue uses ~/.gemini/antigravity-cli/mcp_config.json; Antigravity 2.0 uses ~/.gemini/config/mcp_config.json), changing only the marker.
| Where it lives | "spawned" in probe.log | How to read it |
|---|---|---|
Project root .antigravitycli/ | No | The config isn't being read. Not a syntax problem |
| Home-level | Yes | The probe is fine; the location is the cause |
| Neither | No | Wrong path or command. Recheck the registration via agy mcp first |
If the issue is accurate for your version, you'll land on the first two rows. I haven't reproduced this myself, so I'd rather you run it once and see which row you hit. It takes a few minutes.
The workaround that was reported, and what came after
One comment in the issue reported that putting the file at .agents/mcp_config.json in the workspace root, instead of .antigravitycli/, got it loaded (v1.0.3, macOS).
A later comment tried the same steps on v1.1.3 and found it no longer worked: even with the home-level configs emptied, no server started from the workspace file, and the logs showed no sign of the workspace config being looked up.
So the workaround apparently worked on one version and not on another. Running the probe on your own version is the most reliable step in this whole story.
A practical line when you want per-project separation
Several people in the thread wanted separate MCP sets per project or per launch, and a flag to pass a config file at startup was requested. What I consider workable for now:
- Keep servers in the home-level config and prefix each name with its project (
shop_db,blog_cms) - Switch off servers you don't need with the
agy mcpsubcommand'sdisable(the steps are in adding MCP servers without opening the config file) - If hand-editing leads to a schema error, follow the order in this triage article
It's modest, but once the home-level list grows, consistently prefixed names become your inventory.
Decide by whether a process actually started, not by what the log says. That's the line I'd like to come back to whenever configuration gets confusing.
What to do next
Write one probe, register it in the project root and the home-level config with different markers, and see which side logs "spawned." Once you know, you can stop spending time doubting your syntax.