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
Authorizationheader 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:
- examples/adk_token_provider.py
- examples/langchain_token_provider.py
- examples/crewai_token_provider.py
- examples/raw_mcp_http.py
- examples/service_client.py
More details: docs/FRAMEWORKS_GUIDE.md
Features
- OAuth 2.1 + PKCE login for Atlassian MCP
- Dynamic Client Registration (RFC 7591)
- RFC 8707
resourcesupport 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
110120966960ee26aa6d2c3fafd88c7bcee79115864a49c78fa7dfdb3a9c32a3
|
|
| MD5 |
2de72e395dce61a9f0ca5b49c767b004
|
|
| BLAKE2b-256 |
481dcad893b02f0167b0119b35dc00c037ef9945515cc603adca35bc372e7d73
|
File details
Details for the file atlassian_mcp_auth-0.1.0-py3-none-any.whl.
File metadata
- Download URL: atlassian_mcp_auth-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
61735b8f17492860564b9f17dcad85aa60f03599674d1c4940125204197eec8c
|
|
| MD5 |
90a0b8346bd3cc4d641e4bac11f79160
|
|
| BLAKE2b-256 |
ddd8c52d92dc8be659f1b9ae097c5e01426a859691072a01a4cfd03d092ee5a1
|