MCP server wrapping upstream mcp-atlassian with browser-cookie authentication via Playwright. Designed for Atlassian Server/Data Center instances behind corporate SSO where API tokens are not available.
atlassian_browser_mcp_full.py— MCP entrypoint. Monkey-patches upstreamJiraClientandConfluenceClientconstructors to inject browser-backed sessions. Registersatlassian_logintool. Runs the MCP server.atlassian_browser_auth.py— Shared auth core:BrowserCookieSession(requests.Session subclass),interactive_login(), profile seeding, SSO redirect detection. Both the MCP server and the CLI use this.atlassian_cli.py+atlassian-cli— Command-line front-end over the same auth core (Jira/Confluence get/search, login). Preferred for agents and scripting; no MCP transport involved. SeeAGENT_USAGE.md.run-atlassian-browser-mcp.sh— MCP launcher: creates venv viauv, installs deps, runs upstream compatibility check, starts server.
Authentication and serving are deliberately separate jobs:
- Authentication is interactive and slow → done only by the CLI in the
foreground (
atlassian-cli login <jira|confluence>), where a browser can actually open.BrowserCookieSession(allow_interactive=True)(the CLI default) may callinteractive_login(). - Serving is fast, stateless HTTP → the MCP server constructs sessions with
allow_interactive=False. Such a session reads the saved cookie jar and, on a cache miss or 401, raisesAuthRequiredErrorimmediately ("runatlassian-cli login …") instead of launching a browser.
Why this exists (the bug it fixes): the server used to call
interactive_login() from inside its detached, async-dispatched process. That
(a) blocked the tool call up to ATLASSIAN_LOGIN_TIMEOUT_SECONDS (≈5 min, often
forever) waiting for a human who can't see the window, and (b) ran
sync_playwright() on the asyncio event loop, which deadlocks ("Playwright Sync
API inside the asyncio loop"). Net effect: MCP Atlassian calls hung forever.
Hard rules — do not regress:
- The MCP server (
_patch_*_client_init,atlassian_logintool) must NEVER callinteractive_login()or otherwise drive Playwright in-process. Theatlassian_logintool returns instructions only. - Any new server-side session must pass
allow_interactive=False. - Login happens out-of-band via the CLI; the server reuses the saved jar.
Re-entering corporate username/password + MFA on every run is a real pain and must be avoided. The whole point of this tool is a persistent, reusable session. Two rules make that reliable:
- Seed from the user's real Chrome profile. On first login, set
ATLASSIAN_SEED_FROM_CHROME_PROFILE=Default(or another profile name / an absolute path). This copies the real Chrome profile once — cookies, saved logins, and any password-manager extension — into the dedicated automation profile (.atlassian-browser-profile/). Because the user's live corporate SSO cookies come along, the first login typically completes hands-free, no password and no MFA prompt. Chrome 136+ refuses to drive the live profile in place, so seeding a copy is the supported way to reuse it. - NEVER delete the browser profile on an auth failure. A previous version
ran
shutil.rmtree(profile_dir)on a transient 401, which silently destroyed the long-lived SSO session and forced a full manual re-login every time. That self-wipe has been removed and must not come back. On re-auth, only the short-lived per-service cookie cache (.atlassian-browser-state-<svc>.json) is refreshed; the profile is preserved so re-login stays instant.
Jira and Confluence keep separate cookie jars (*-state-jira.json,
*-state-confluence.json) but share one browser profile, so a single seeded
SSO session covers both services. All .atlassian-browser-* artifacts hold live
credentials and are git-ignored — never commit them.
Operational how-to (commands, env vars) lives in AGENT_USAGE.md;
this section is the rationale and the two hard rules.
- Monkey-patching over forking: We patch upstream client
__init__methods at import time rather than maintaining a fork. Anassert_upstream_compatibility()check validates signatures on startup. - Version pinning: Pinned to
mcp-atlassian>=0.23.1,<1.0.0. Bump carefully — upstream signature changes will break patches. - No hardcoded URLs:
JIRA_URLandCONFLUENCE_URLare required env vars with no defaults. - Configurable SSO detection:
ATLASSIAN_SSO_MARKERSenv var accepts comma-separated markers. Defaults cover Okta, ADFS, Azure AD, PingOne, Google SAML.
- Keep browser auth logic in
atlassian_browser_auth.py, MCP/patching logic inatlassian_browser_mcp_full.py. - When upstream
mcp-atlassianreleases a new minor version, update the pin inpyproject.tomland verifyassert_upstream_compatibility()passes. - Never store credentials, URLs, or company-specific references in source code.
Generated by LynxPrompt CLI