Skip to main content

atlassian-mcp-auth

Python-native OAuth token management for the Atlassian Rovo MCP server.

Use this package when your Python app, agent, or backend needs to connect to Atlassian Rovo MCP for Jira and Confluence without using Node.js or mcp-remote.

It handles the hard OAuth parts for you:

  • Opens Atlassian browser consent
  • Registers an OAuth client dynamically
  • Uses PKCE for login
  • Stores access and refresh tokens
  • Refreshes tokens automatically
  • Returns the MCP URL and Authorization header your framework needs

This package is an auth and token provider. Your MCP client, ADK app, LangChain/LangGraph app, CrewAI tool, or HTTP transport still owns the actual MCP tool calls.

Quick Start

Install the package:

pip install atlassian-mcp-auth

Run one-time browser login:

atlassian-mcp-auth login

The CLI opens Atlassian consent in your browser, waits for the callback at http://localhost:8765/callback, then stores tokens locally in:

~/.atlassian-mcp-auth/tokens.db

Check that you are connected:

atlassian-mcp-auth status

Print a fresh access token:

atlassian-mcp-auth token

Use it from Python:

import asyncio

from atlassian_mcp_auth import AtlassianMcpAuth


async def main() -> None:
    auth = AtlassianMcpAuth()
    connection = await auth.get_connection_info()

    print(connection.mcp_url)
    print(connection.headers)


asyncio.run(main())

connection.headers looks like this:

{"Authorization": "Bearer <fresh-access-token>"}

Pass that header to your MCP Streamable HTTP client or agent framework.

How Normal Users Use It

There are four common ways to use this package.

Use case Start here
Local development or testing Use the CLI
Python app or agent code Use AtlassianMcpAuth directly
Frontend, backend, or non-Python app Run the optional HTTP service
ADK, LangChain, CrewAI, custom MCP client Use get_connection_info() as a token/header provider

1. Use From The CLI

The CLI is the fastest way to login, verify OAuth, and get a token.

# Browser login. Stores tokens in ~/.atlassian-mcp-auth/tokens.db
atlassian-mcp-auth login

# Show saved token status
atlassian-mcp-auth status

# Print a fresh MCP access token
atlassian-mcp-auth token

# Force refresh and save any rotated refresh token
atlassian-mcp-auth refresh

# Delete saved tokens
atlassian-mcp-auth clear

Use a different profile for another user, team, or project:

atlassian-mcp-auth --profile team-a login
atlassian-mcp-auth --profile team-a token

Use a custom SQLite database path:

atlassian-mcp-auth --db ./tokens.db login

Use Postgres instead of SQLite:

pip install "atlassian-mcp-auth[postgres]"

atlassian-mcp-auth \
    --database-url "postgresql://user:password@localhost:5432/atlassian_mcp" \
    login

Use a different local callback port:

atlassian-mcp-auth login --port 8766

More details: docs/CLI_GUIDE.md

2. Use From Python API

First login once using the CLI:

atlassian-mcp-auth login

Then use the saved token from your Python code:

import asyncio

from atlassian_mcp_auth import AtlassianMcpAuth


async def main() -> None:
    auth = AtlassianMcpAuth(profile="default")
    access_token = await auth.get_access_token()
    print(access_token[:20])


asyncio.run(main())

For MCP clients and frameworks, prefer get_connection_info():

import asyncio

from atlassian_mcp_auth import AtlassianMcpAuth


async def main() -> None:
    auth = AtlassianMcpAuth(profile="user-123")
    connection = await auth.get_connection_info()

    # Give these values to your MCP Streamable HTTP transport.
    mcp_url = connection.mcp_url
    headers = connection.headers

    print("MCP URL:", mcp_url)
    print("Headers:", headers)
    print("Cloud ID:", connection.cloud_id)


asyncio.run(main())

The library refreshes the access token automatically when it is near expiry.

3. Use The Optional HTTP Service

Use the service when another app, frontend, or non-Python process needs to start OAuth and fetch connection data over HTTP.

Install service dependencies:

pip install "atlassian-mcp-auth[service]"

Start the service:

atlassian-mcp-auth serve --host 127.0.0.1 --port 8765

Health check:

curl http://127.0.0.1:8765/health

Start browser login directly:

http://127.0.0.1:8765/oauth/start?profile=user-123

Optionally redirect back to your app after authentication:

http://127.0.0.1:8765/oauth/start?profile=user-123&next=http://localhost:3000/settings/integrations

localhost, 127.0.0.1, and ::1 are allowed by default for next. For a production app, allow your app host when starting the service:

atlassian-mcp-auth serve \
    --public-url https://auth.example.com \
    --allowed-next-host app.example.com

After token exchange succeeds, the service redirects to next with:

?atlassian_mcp_auth=complete&profile=user-123&cloud_id=...

Or create the authorization URL from an API call:

curl -X POST http://127.0.0.1:8765/oauth/login \
  -H 'Content-Type: application/json' \
    -d '{"profile":"user-123","next":"http://localhost:3000/settings/integrations"}'

After login, fetch connection data:

curl "http://127.0.0.1:8765/token?profile=user-123"

Example response:

{
  "access_token": "...",
  "headers": {"Authorization": "Bearer ..."},
  "mcp_url": "https://mcp.atlassian.com/v1/mcp",
  "resource_url": "https://mcp.atlassian.com/v1/mcp/authv2",
  "cloud_id": "...",
  "expires_at": 1780000000.0
}

Useful service endpoints:

GET  /health
GET  /oauth/start?profile=user-123
POST /oauth/login
GET  /oauth/callback
GET  /status?profile=user-123
GET  /token?profile=user-123
POST /refresh?profile=user-123
POST /clear

Use Postgres In Service Mode

SQLite is the default, so this works without database setup:

atlassian-mcp-auth serve --host 127.0.0.1 --port 8765

For Postgres, install the Postgres service extra and pass one database URL:

pip install "atlassian-mcp-auth[service-postgres]"

atlassian-mcp-auth \
  --database-url "postgresql://user:password@localhost:5432/atlassian_mcp" \
  serve --host 127.0.0.1 --port 8765

You can also set the URL with an environment variable:

export ATLASSIAN_MCP_DATABASE_URL="postgresql://user:password@localhost:5432/atlassian_mcp"
atlassian-mcp-auth serve --host 127.0.0.1 --port 8765

More details: docs/SERVICE_GUIDE.md

4. Use With Any MCP Client Or Agent Framework

This package does not create an ADK, LangChain, CrewAI, or raw MCP client for you. It gives those clients fresh Atlassian MCP connection data.

Core pattern:

from atlassian_mcp_auth import AtlassianMcpAuth


auth = AtlassianMcpAuth(profile="user-123")


async def get_headers() -> dict[str, str]:
    return (await auth.get_connection_info()).headers

For a raw Streamable HTTP MCP call, use the returned URL and headers:

import asyncio

import httpx

from atlassian_mcp_auth import AtlassianMcpAuth


async def main() -> None:
    auth = AtlassianMcpAuth(profile="raw-http-user")
    connection = await auth.get_connection_info()
    headers = {
        **connection.headers,
        "Content-Type": "application/json",
        "Accept": "application/json, text/event-stream",
        "MCP-Protocol-Version": "2025-06-18",
    }

    async with httpx.AsyncClient(timeout=30.0) as client:
        response = await client.post(
            connection.mcp_url,
            headers=headers,
            json={
                "jsonrpc": "2.0",
                "id": 1,
                "method": "initialize",
                "params": {
                    "protocolVersion": "2025-06-18",
                    "capabilities": {},
                    "clientInfo": {"name": "my-mcp-client", "version": "0.1.0"},
                },
            },
        )
        print(response.status_code)
        print(response.text[:500])


asyncio.run(main())

Framework examples:

More details: docs/FRAMEWORKS_GUIDE.md

Features

  • OAuth 2.1 + PKCE login for Atlassian MCP
  • Dynamic Client Registration (RFC 7591)
  • RFC 8707 resource support for Atlassian MCP access tokens
  • Rotating refresh token persistence
  • SQLite token storage by default
  • Pluggable storage for Postgres, MySQL, Redis, Vault, or app databases
  • Framework-neutral token and connection metadata API

Guides

  • CLI Guide — local OAuth login, status, refresh, token, clear
  • Service Guide — run HTTP service and use /oauth/*, /token, /status, /refresh
  • Framework Guide — ADK, LangChain/LangGraph, CrewAI, raw MCP HTTP, service-based usage

Custom Storage

SQLite and Postgres are built in. Production apps can also bring their own storage.

from atlassian_mcp_auth.storage import TokenRecord, TokenStorage


class PostgresStorage(TokenStorage):
    async def load(self, profile: str = "default") -> TokenRecord | None:
        ...

    async def save(self, record: TokenRecord, profile: str = "default") -> None:
        ...

    async def clear(self, profile: str = "default") -> None:
        ...
auth = AtlassianMcpAuth(storage=PostgresStorage(), profile="user-123")

Advanced: Browser OAuth Flow From Your App

If your app wants to own the browser redirect flow instead of using the CLI or service, call begin_authorization() and exchange_code() directly.

from atlassian_mcp_auth import AtlassianMcpAuth, AuthorizationSession


auth = AtlassianMcpAuth(profile="user-123")

# Step 1: create browser consent URL
session: AuthorizationSession = await auth.begin_authorization(
    redirect_uri="https://your-app.example.com/oauth/callback"
)

# Send session.auth_url to the browser and store session.to_dict() temporarily.

# Step 2: after Atlassian redirects back with ?code=...&state=...
record = await auth.exchange_code(code, AuthorizationSession.from_dict(saved_session))

# Stored in SQLite/custom DB:
# - client_id
# - client_secret, when Atlassian returns one
# - access_token
# - refresh_token
# - expires_at
# - scopes
# - cloud_id, when present in the access token

Troubleshooting

If atlassian-mcp-auth token says no tokens were found, run:

atlassian-mcp-auth login

If your app uses a profile, use the same profile everywhere:

atlassian-mcp-auth --profile user-123 login
auth = AtlassianMcpAuth(profile="user-123")

If the service command is missing dependencies, install the service extra:

pip install "atlassian-mcp-auth[service]"

If a callback port is already in use, choose another port:

atlassian-mcp-auth login --port 8766

Why This Exists

Atlassian Rovo exposes Jira and Confluence tools through an MCP Streamable HTTP server. Python agent apps often need a direct server-side OAuth flow, token refresh, and storage layer without tying the auth package to one framework.

This package focuses only on that reusable auth layer.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

atlassian_mcp_auth-0.1.0.tar.gz (21.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

atlassian_mcp_auth-0.1.0-py3-none-any.whl (20.4 kB view details)

Uploaded Python 3

File details

Details for the file atlassian_mcp_auth-0.1.0.tar.gz.

File metadata

  • Download URL: atlassian_mcp_auth-0.1.0.tar.gz
  • Upload date:
  • Size: 21.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.5

File hashes

Hashes for atlassian_mcp_auth-0.1.0.tar.gz
Algorithm Hash digest
SHA256 110120966960ee26aa6d2c3fafd88c7bcee79115864a49c78fa7dfdb3a9c32a3
MD5 2de72e395dce61a9f0ca5b49c767b004
BLAKE2b-256 481dcad893b02f0167b0119b35dc00c037ef9945515cc603adca35bc372e7d73

See more details on using hashes here.

File details

Details for the file atlassian_mcp_auth-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for atlassian_mcp_auth-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 61735b8f17492860564b9f17dcad85aa60f03599674d1c4940125204197eec8c
MD5 90a0b8346bd3cc4d641e4bac11f79160
BLAKE2b-256 ddd8c52d92dc8be659f1b9ae097c5e01426a859691072a01a4cfd03d092ee5a1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page