See it as a diagram
Everything below, as a diagram you can edit. Describe yours and see it in seconds.
No account needed · Editable canvas, not a picture
One field selects the transport
Gemini CLI reads MCP servers from ~/.gemini/settings.json for your user, and from .gemini/settings.json inside a project directory for a project-scoped setup. Entries live under a top-level mcpServers object, and each entry sets exactly one of three fields: command for a local stdio process, url for a legacy SSE endpoint, and httpUrl for a streamable HTTP endpoint.
Datadef is streamable HTTP, so the field is httpUrl. Setting url instead points the CLI at a transport this server does not speak, and the result is a server that registers without tools rather than a visible error. Authentication goes in a headers object alongside it.
The CLI also has an add subcommand that writes the entry for you with a transport flag, which is a reasonable alternative to editing the file when you only need the user scope.
// ~/.gemini/settings.json for your user, or
// .gemini/settings.json inside a project
{
"mcpServers": {
"datadef": {
"httpUrl": "https://datadef.io/mcp",
"headers": {
"Authorization": "Bearer dd_live_YOUR_KEY"
}
}
}
}Confirming it before you prompt
Start the CLI and run the mcp slash command. It lists configured servers and the tools each one contributes. A working Datadef entry contributes 36: nine that act on whole diagrams and 27 prefixed canvas_ that act on individual elements. A server listed with zero tools is almost always the httpUrl mistake from the previous section.
If you want to separate a server problem from a config problem, the endpoint answers listings anonymously. tools/list needs no credentials at all, so a curl that returns the tool surface proves the remote side is healthy and moves the investigation onto your machine.
What a terminal agent does well here
The CLI is in the working directory, which makes it a strong client for drawing what is actually in the repo rather than what you remember about it. Ask it to read the code and produce an overview scope diagram first: around 12 to 20 nodes, the shape of the system. Detail is a second request, and it is much easier to add than to remove.
It is also the natural place to keep a diagram current. For a project connected to a repository, repo_status reports the provider, the branch or tag, the commit reflected, and how long since the last sync, and repo_refresh runs one now. Datadef also syncs connected repositories daily on its own, so the tool is there for the moment after a merge when you do not want to wait for the schedule.
Repository connections cover GitHub, GitLab and Azure DevOps, read-only, on a branch or a tag you choose. The repository sync guide has the full picture.
Project scope beats user scope for a team
What the Terraform reader actually does
A Terraform repository does not go through the general file selection, it gets parsed, and Terraform structure turns out to be recoverable without running anything. A directory of .tf files is a module unit. A unit nobody names as a module source is a root stack. A module call with a local source instantiates another unit. References inside expressions, azurerm_x.this.id or module.storage.account_id, resolve to the declared resources they reach, which is the edge set of the real architecture rather than a guess at it. Variables and locals are followed, not evaluated: resolution chases what a value is wired to and never what it computes.
Nothing executes. No terraform init, no state file, no provider plugin, no cloud credential at any point, which is why a read-only repository token is the entire access you grant.
Two behaviours shape what you get back. count and for_each become an honest number on the node: a literal 3 renders as a multiplicity of three, a var.flag ? 1 : 0 with a resolvable flag collapses to deployed or not deployed, and a for_each driven by a variable that your environment tfvars files set differently is labelled per environment instead of averaged into one figure that is wrong everywhere. Resources classified as wiring never become boxes at all: role assignments, grants, IAM members, policy attachments, secrets and certificates, and everything from the random, null, local, time and tls providers are counted in the generated architecture.md rather than drawn on the canvas.
resource "azurerm_storage_account" "this" {
for_each = var.storage_accounts # environments/DEV sets 2, environments/QUAL sets 1
}
# drawn as one node labelled: per storage_accounts (DEV 2, QUAL 1)FAQ
Which field connects Gemini CLI to a streamable HTTP MCP server?
Where does Gemini CLI keep MCP configuration?
How do I check the server registered correctly?
Can the CLI keep a diagram up to date after a merge?
Which repository hosts can be connected for that sync?