·

Confluence MCP With Gemini CLI

Set up Confluence MCP in Gemini CLI so your AI agent can read and write pages and documentation right from your editor.

Gemini CLI's MCP implementation is functionally complete — stdio and SSE servers both work, tool discovery is automatic — but its default output style leans toward long, heavily-bulleted responses even when you ask for prose, which shows up directly in AI-generated Confluence pages if you're not watching for it. This topic covers setup, then digs into where Gemini CLI's documentation output needs steering, with a direct comparison against Claude Code at the end.

Installing and Connecting Confluence MCP to Gemini CLI

Gemini CLI reads MCP config from .gemini/settings.json (project-scoped) or ~/.gemini/settings.json (user-scoped). The shape matches Claude Code's fairly closely — command, args, env — which makes migrating a config between the two nearly a copy-paste job.

{
  "mcpServers": {
    "confluence": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "CONFLUENCE_URL",
        "-e", "CONFLUENCE_USERNAME",
        "-e", "CONFLUENCE_API_TOKEN",
        "ghcr.io/sooperset/mcp-atlassian:latest"
      ],
      "env": {
        "CONFLUENCE_URL": "https://yourcompany.atlassian.net/wiki",
        "CONFLUENCE_USERNAME": "dat.hoang@yourcompany.com",
        "CONFLUENCE_API_TOKEN": "$CONFLUENCE_API_TOKEN"
      },
      "timeout": 15000
    }
  }
}

The timeout field (milliseconds) is worth setting explicitly — Gemini CLI's default MCP call timeout is shorter than Claude Code's, and a cold Docker pull on first run can exceed it, producing a spurious "tool call timed out" error on the very first invocation even though the server would have started fine given a few more seconds. Fifteen seconds is enough headroom for a warm image; bump it to 30000 if you're pulling ghcr.io/sooperset/mcp-atlassian:latest fresh.

Launch and verify:

export CONFLUENCE_API_TOKEN="ATATT3xFfGF0...redacted"
gemini
/mcp list

Gemini CLI's /mcp list shows connection status per server and, usefully, the exact tool schemas if you pass /mcp list confluence — handy for confirming which tool names and parameters the model actually sees, since occasionally a server version bump renames a tool (confluence_get_page becoming getConfluencePage between mcp-atlassian major versions, for instance) and the model needs the current schema to call it correctly.

For the uvx path instead of Docker:

{
  "mcpServers": {
    "confluence": {
      "command": "uvx",
      "args": [
        "mcp-atlassian",
        "--confluence-url", "https://yourcompany.atlassian.net/wiki",
        "--confluence-username", "dat.hoang@yourcompany.com",
        "--confluence-token", "$CONFLUENCE_API_TOKEN"
      ],
      "timeout": 15000
    }
  }
}

Tips
- Set timeout explicitly above Gemini CLI's default (10s) — cold Docker pulls routinely exceed it on first connection.
- Use /mcp list confluence to inspect the exact tool schema Gemini sees, which is the fastest way to catch a tool-name mismatch after upgrading mcp-atlassian.
- Project-scoped .gemini/settings.json is the right home for a team-shared Confluence connection; keep the API token itself out of the committed file via $CONFLUENCE_API_TOKEN shell interpolation.


Reading Specs and Generating Technical Documentation from Gemini CLI

Search and read prompts work reliably:

Search the ENG space for the pagination spec and pull out the exact
cursor format we're using.

Gemini CLI correctly chains confluence_search then confluence_get_page, same pattern as the other agents. Where it's worth watching closely is document generation, where Gemini's default writing style pushes toward exhaustive bulleted lists even for content that reads much better as prose — architecture rationale, trade-off discussions, ADR "Context" sections.

Generate a Confluence page explaining why we chose gRPC over REST for
internal service-to-service calls. Base it on the discussion in
`docs/grpc-decision-notes.md`.

Left unguided, Gemini CLI tends to produce something like six top-level bullets, each with three sub-bullets, for what should be two paragraphs of connected reasoning. It's not wrong, exactly, but it reads like a slide deck instead of documentation a person would enjoy reading later. Explicitly steering the format in the prompt fixes this:

Generate a Confluence page explaining why we chose gRPC over REST for
internal service-to-service calls, based on docs/grpc-decision-notes.md.
Write the rationale as connected prose paragraphs, not bullet lists.
Reserve bullets only for the final "Trade-offs Accepted" section.

This single instruction — "prose for narrative sections, bullets only where explicitly asked" — is worth adding as a standing convention in any Gemini CLI prompt that generates a Confluence page longer than a quick reference table.

Tips
- Add an explicit "write in prose, not bullets" instruction for any narrative section (Context, rationale, background) — Gemini CLI's default style over-uses bullet lists for content that should read as connected reasoning.
- Reserve bullet-list output for genuinely list-shaped content: trade-offs, prerequisites, step sequences.
- For spec-reading prompts, Gemini CLI performs on par with Claude Code — the formatting issue only shows up on the generation side, not the reading side.


Practical Example: Auto-Generating a Confluence Page from Code Annotations in Gemini CLI

A pattern that works well specifically because it plays to Gemini CLI's strengths (structured extraction) rather than its weakness (unguided prose): generating an API reference page from OpenAPI-style docstring annotations already present in the code.

Read every function in `api/handlers/orders.py` that has a docstring
starting with "@api". Extract: HTTP method, path, request body schema,
response schema, and any "@deprecated" tags. Generate a Confluence
page "Orders API Reference" in the DOCS space as a table: one row per
endpoint, columns for Method, Path, Request, Response, Status. Mark
deprecated endpoints in a separate section below the table.

Because the source annotations are already structured (method, path, schema per function), Gemini CLI's extraction is accurate and the table-based output format sidesteps the prose-vs-bullets problem entirely — tables are unambiguous, and Gemini CLI renders them correctly in Confluence storage format without the coaching needed for narrative sections.

def get_order(order_id: str):
    """
    @api GET /orders/{order_id}
    @request none
    @response OrderSchema
    @deprecated Use /v2/orders/{order_id} instead
    """
    ...

The generated table row for this correctly lands GET, /orders/{order_id}, none, OrderSchema, and files the endpoint under the deprecated section — confirmed by checking the created page directly. This pattern generalizes well to any codebase with consistent docstring conventions (Swagger/OpenAPI comment blocks, JSDoc @route tags, etc.) — the more structured the source annotation, the less Gemini CLI's formatting quirks matter.

Tips
- Lean into table-shaped output for any Confluence generation task where the source data is already structured (API routes, config options, schema fields) — it avoids Gemini's prose/bullet formatting issues entirely.
- Keep docstring annotation conventions consistent across a codebase before running bulk extraction — inconsistent tags (@api vs @route vs nothing) produce visibly inconsistent table rows.
- Spot-check the deprecated/status column specifically — extraction of secondary tags like @deprecated is more error-prone than the primary method/path extraction.


Comparing Confluence MCP Output Between Gemini CLI and Claude Code

Running the same five prompts (a search, a single-page create, a multi-step ADR generation, a table-based API reference, and a page update) against both agents on the same Confluence sandbox space surfaced consistent differences:

Dimension Claude Code Gemini CLI
CQL generation for compound queries Reliable on first try Reliable on first try
Narrative prose sections Balanced prose/list mix by default Over-bulleted unless explicitly steered
Multi-step planning (search → read → create) Consistent, rarely needs a nudge Consistent, rarely needs a nudge
Table-based structured extraction Strong Strong, arguably the better default here
Version-conflict handling on update Surfaces error, waits for retry instruction Surfaces error, waits for retry instruction
Cold-start tool call latency Not timeout-sensitive by default Needs timeout raised above default

The practical takeaway: for narrative-heavy documentation (ADRs, design rationale, onboarding guides), Claude Code needs less prompt engineering to get readable prose. For structured, table-shaped extraction (API references, config option catalogs, changelogs), the two are close, and Gemini CLI's default terseness is arguably a slight edge. Neither agent meaningfully outperforms the other on the underlying MCP mechanics — search, read, create, update all work the same way because they're calling the identical mcp-atlassian tool set; the difference is entirely in each model's default writing style and how much steering it needs.

Tips
- Default to Gemini CLI for table/schema-heavy documentation generation where its terse, structured style is a natural fit.
- Default to Claude Code (or add explicit prose-steering to your Gemini prompts) for narrative documentation like ADRs and design write-ups.
- Since both agents call the same underlying mcp-atlassian tools, a prompt library you build for one ports to the other with light editing — the differences are stylistic, not mechanical.


Tips

Tips
- Raise Gemini CLI's MCP timeout above the default before your first session — it's the single most common false-alarm error with this setup.
- Build a short "house style" preamble ("prose for narrative, bullets for lists, tables for structured data") into your Confluence-generation prompts for Gemini CLI and reuse it across sessions.
- Next: Cursor's take on the same server, running inside an IDE agent loop rather than a standalone CLI — expect a different set of trade-offs around review UX.