Cursor's Agent mode treats MCP tools as first-class citizens alongside its native codebase tools, which makes the "read spec, write code" and "read code, write docs" loops feel more integrated than in a standalone CLI — you're not context-switching out of the editor at all. The trade-off is a less mature review surface for Confluence-specific writes compared to what you'd get reviewing a page diff in a browser. This topic covers the Cursor-specific config, a real spec-to-code and code-to-docs workflow, and the sharp edges worth knowing before you rely on it for anything customer-facing.
Connecting Confluence MCP to Cursor Agent Mode
Cursor reads MCP config from .cursor/mcp.json (project-scoped) or ~/.cursor/mcp.json (global). As of Cursor 1.x, the config format matches the broader MCP ecosystem convention closely enough that a Claude Code .mcp.json server block ports over with minimal changes.
{
"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": "ATATT3xFfGF0...redacted"
}
}
}
}
Unlike Claude Code and Gemini CLI, Cursor's mcp.json doesn't support $VAR shell interpolation inside env values reliably across all versions — in practice, teams either accept the token living in a gitignored .cursor/mcp.json (fine for solo/personal use, not for a shared repo config) or route through the OS keychain via a wrapper script that injects the env var before Cursor launches Docker.
#!/usr/bin/env bash
export CONFLUENCE_API_TOKEN=$(security find-generic-password -s confluence-mcp -w)
exec docker run -i --rm \
-e CONFLUENCE_URL="https://yourcompany.atlassian.net/wiki" \
-e CONFLUENCE_USERNAME="dat.hoang@yourcompany.com" \
-e CONFLUENCE_API_TOKEN \
ghcr.io/sooperset/mcp-atlassian:latest
{
"mcpServers": {
"confluence": {
"command": "/bin/bash",
"args": [".cursor/launch-confluence-mcp.sh"]
}
}
}
That pattern (macOS Keychain via security; on Linux, swap in secret-tool or a .env sourced from a permissions-locked file) keeps the token out of any file that might get committed by accident.
Enable and verify inside Cursor: open Settings → MCP, confirm confluence shows a green/connected indicator and a non-zero tool count. In Agent mode chat, typing @ and looking for MCP tool suggestions is a quick sanity check that Cursor picked up the server — Confluence tools should appear alongside your codebase's native symbols in the autocomplete.
Tips
- Don't rely on$VARinterpolation working consistently in.cursor/mcp.jsonacross Cursor versions — a keychain-backed launch script is more portable than debugging why an env var silently resolved to an empty string.
- Check Settings → MCP for a connected status before trusting any Confluence prompt in Agent mode — a disconnected server fails tool calls with a generic "tool not available" message that's easy to misread as a prompt problem.
- Keep.cursor/mcp.jsonitself out of version control if it contains any credential material directly; commit only the wrapper-script version.
Reading Confluence Specs and Generating Boilerplate Code in Cursor
This is where Cursor's IDE-native context genuinely helps: Agent mode can read a Confluence spec, then generate the actual project files in the same turn, in the same editor, with the same diff-review UX you already use for every other Cursor code change.
Read the Confluence page "Notification Service — API Spec" in the ENG
space. Generate a FastAPI router matching its documented endpoints:
`POST /notifications`, `GET /notifications/{id}`,
`PATCH /notifications/{id}/read`. Put it in `services/notifications/router.py`,
with Pydantic models for each request/response schema in `models.py`.
Cursor calls confluence_search (or confluence_get_page directly if you gave it the exact title), reads the storage-format body, and — this is the part worth watching — has to correctly parse whatever schema notation the spec uses. If the Confluence page documents request/response shapes as a Confluence table (common) or as an embedded code block (also common, and easier for the agent to parse exactly), extraction accuracy differs meaningfully. Tables get parsed correctly for simple field/type/required columns; anything with nested objects described in prose inside a table cell is a real source of mis-generated Pydantic fields worth double-checking against the source page.
Spec page table (rendered from Confluence storage format):
| Field | Type | Required | Notes |
|-------------|--------|----------|---------------------------|
| user_id | string | yes | UUID |
| message | string | yes | max 500 chars |
| metadata | object | no | free-form key-value pairs |
For the metadata row above, expect the generated Pydantic model to render it as dict[str, Any] or similar — reasonable, but confirm it matches what the spec author actually intended, since "free-form key-value pairs" is genuinely ambiguous and the agent has to guess a concrete type.
Cursor's inline diff view (the same one used for every AI code edit) applies here unchanged — you review the generated router and models file exactly as you'd review any other Cursor-proposed change, accept/reject per hunk. That consistency is the single biggest practical advantage of doing spec-to-code work inside Cursor versus a standalone CLI: no separate review surface to learn.
Tips
- Check whether your Confluence spec pages document schemas as tables or embedded code blocks — code-block schemas parse more reliably into typed models than prose-in-table-cells.
- Treat any "free-form" or loosely-typed field in a spec as a place the agent had to guess — verify the generated type against what you actually intend to store.
- Use Cursor's standard code diff review for AI-generated files from a spec exactly like you would for any other AI-generated code — no special workflow needed here, which is the point.
Pushing Auto-Generated Docs Back to Confluence via Cursor
The inverse flow — code to docs — works, but the review loop is weaker than the code-diff review above, because Confluence page updates don't render as a Cursor-native diff. You're trusting the agent's tool-call summary or manually checking the live page afterward.
Read `services/notifications/router.py` and `models.py`. Update the
Confluence page "Notification Service — API Spec" in ENG to match the
actual implementation: correct any field types or endpoints that have
drifted from the original spec.
This "sync docs to match implementation" direction is genuinely valuable — specs drift from code constantly, and having an agent reconcile them on demand beats manual reconciliation nobody has time for — but because there's no inline diff for the Confluence page itself, the practical workflow is:
- Run the update prompt.
- Open the actual Confluence page in a browser (or ask the agent to output the new body as Markdown in chat first, as a pre-check).
- Check the page's version history for a one-click revert path if something's off.
Asking the agent to show the proposed content before calling confluence_update_page is the closest Cursor gets to a pre-write review for Confluence specifically:
Before updating the page, show me the diff between the current spec
content and what you're about to write, as a side-by-side comparison
in this chat.
This works because it forces the agent to fetch the current page (confluence_get_page) and compare before writing, rather than jumping straight to confluence_update_page — effectively hand-rolling a review gate the tooling doesn't provide natively.
Tips
- For any code-to-Confluence update, ask the agent to show a before/after comparison in chat before calling the write tool — Cursor has no native diff view for Confluence page bodies.
- Rely on Confluence's own page version history as the safety net for AI-driven updates gone wrong; it's a one-click revert in the web UI.
- Schedule sync-docs-to-code prompts as a recurring manual check (e.g., before a release) rather than fully automating them — the lack of a native review surface makes unattended automation riskier here than for read-only prompts.
Known Limitations and Edge Cases
A few things worth knowing before you build a workflow around this combination:
- No native diff for Confluence writes, as covered above — this is the single biggest gap versus the Claude Code VS Code extension's rendered diff view.
- Env var interpolation inconsistency in
.cursor/mcp.jsonacross versions means teams often end up with the keychain-wrapper-script pattern shown earlier, which is one more moving part than the other three agents need. - Long spec pages get truncated silently in some Cursor versions when passed through the context window alongside a large open codebase — if a page is long (multi-thousand-word spec), consider asking the agent to fetch and process it in a fresh, minimal-context chat rather than one with a dozen files already open.
- Table-in-table or deeply nested Confluence content (macros inside macros, common in older pages migrated from other wikis) sometimes fails to parse at all —
confluence_get_pagereturns a body, but the storage-format-to-Markdown conversion can garble deeply nested macros into unreadable fragments. If a spec page predates your team's current Confluence conventions, a manual glance at the raw page before trusting the agent's read is worth the two minutes. - Cursor's Agent mode occasionally re-runs the same
confluence_searchcall redundantly within a single multi-step task, burning a few extra seconds and API calls — harmless, but worth knowing so you don't mistake it for a hang.
Tips
- For very long spec pages, start a fresh Cursor chat scoped narrowly to the doc-generation task rather than reusing a chat with a large codebase already loaded into context.
- If a Confluence page predates a wiki migration or uses heavy nested macros, manually check the rendered page before trusting an AI summary of its content.
- Treat occasional redundant tool calls as a minor inefficiency, not a signal something's broken — it doesn't affect output correctness in practice.
Tips
Tips
- Cursor's biggest win here is the unified review surface for spec-to-code work — use it heavily for that direction, where the native diff view applies.
- For code-to-docs updates, build in a manual "show me the diff in chat first" step since there's no native equivalent — treat it as a required habit, not optional caution.
- Next: the closing module topic ties all of this together into one end-to-end workflow — reading specs into code, generating docs from code, and keeping the two in sync on an ongoing basis.