mcp-microsoft-graph-auth
Shared Microsoft Graph authentication helpers for MCP servers.
Why this exists
mcp-server-sharepoint and mcp-server-outlook (and likely future siblings — Teams, OneDrive, …) all need the same auth machinery against Microsoft Graph: OAuth Device Code flow, token cache with sensible storage backends, optional service-principal mode, multi-profile support.
This library factors that machinery out so each MCP server adds only what's specific to its API surface (scopes + tool names), not yet another reimplementation of Device Code + token storage.
What's in the box
device_code— primitives for the OAuth 2.0 Device Code flow against Microsoft Identity v2.0 (request_device_code,poll_for_token,refresh_access_token).service_principal— client-credentials grant for unattended automation (CI runners, scheduled jobs).token_store— three pluggable storage backends:- OS keyring (macOS Keychain / Windows Credential Locker / Linux Secret Service) when available.
- Plain file mode 0600 (
~/.cache/<your-app>/<profile>/token.json) — same convention asgh auth,aws configure. - Encrypted file with passphrase (Fernet + Scrypt KDF) for paranoid setups or shared CI cache.
tokens—CachedTokendataclass with sensible JSON serialisation.login_session—LoginSession+LoginSessionRegistryfor MCP-tool-driven login flows (the in-process state your*_login_begin/*_login_statustools share).
Public API contract
The library is prefix-agnostic: it does not read environment variables on its own. Each consumer (an MCP server) is responsible for reading its own env-var conventions and passing values explicitly. This keeps the library reusable by any MCP server without env-var collisions.
Minimal sketch (subject to v0.1.0 release)
from mcp_microsoft_graph_auth import (
request_device_code,
poll_for_token,
refresh_access_token,
CachedToken,
PlainFileTokenStore,
)
# Initiate Device Code flow
device_code, challenge = request_device_code(
client_id="<your-app-id>",
tenant="organizations", # or a specific tenant GUID
scopes=("Files.ReadWrite.All", "Sites.ReadWrite.All", "User.Read", "offline_access"),
)
print(f"Open {challenge.verification_uri} and enter code {challenge.user_code}")
# Poll until the user completes sign-in
token = poll_for_token(
device_code=device_code,
client_id="<your-app-id>",
interval=challenge.interval,
)
# Persist for later
store = PlainFileTokenStore(base_dir="~/.cache/my-mcp-server")
store.set("default", token.to_json().encode())
UX guidance for relaying the verification URL + user code
When an MCP server wraps the Device Code flow as a tool (e.g. sp_login_begin returns {verification_url, user_code, ...}), the tool's description should tell the agent how to render those two values to the user. Mobile / smartphone agent UIs are strict about both shape and ordering:
user_codefirst, alone in its own one-line code block, with no labels likeCode:and no whitespace padding. Long-press / tap-and-hold copy then yields just the code.verification_urlsecond, on its own line as a plain Markdown auto-link, not inside a code block (code blocks suppress link rendering, so on mobile the user can't tap it).
Why this ordering: the user's optimal workflow is copy the code → click the link → paste the code into the page that just opened. With the code first, the clipboard is loaded before the user leaves the chat. URL-first would force a chat-↔-browser ping-pong.
Recommended verbatim phrasing for the tool's MCP description:
When surfacing the result to the user, render
user_codeFIRST in its own code block (no labels, no whitespace) andverification_urlSECOND as a plain auto-link (not in a code block). The user copies the code first, then clicks the link, and pastes into the page that opens — minimises app-switching on mobile.
The CLI fallback (mcp-server-<svc> login) prints URL: / Code: labels in URL-then-Code order because terminals don't have rich rendering — that format is correct for stderr and wrong to relay verbatim into chat.
Compatibility
- Python 3.11+
- Microsoft Identity v2.0 endpoints
- Tested on Linux + macOS (Windows should work; not yet covered by CI)
License
Dual-licensed under MIT or Apache-2.0 at your option. See LICENSE-MIT and LICENSE-APACHE.
Status
Pre-1.0. The public API is stable enough for use by mcp-server-sharepoint and mcp-server-outlook — the two consumers driving its design. External consumption is welcome but expect occasional breaking changes until v1.0.
See docs/RELEASING.md for release process and CHANGELOG.md for what's shipped.
Metadata
Release files for mcp-microsoft-graph-auth 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mcp_microsoft_graph_auth-0.1.2.tar.gz | 104.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mcp_microsoft_graph_auth-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 131.3 kB
Release files / mcp_microsoft_graph_auth-0.1.2.tar.gz
| Download URL | mcp_microsoft_graph_auth-0.1.2.tar.gz |
|---|---|
| Size | 104.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c8ea70229e2ad27fb3119d27b73986736354124270cc0c10534b75b8d6d7a149
|
|
BLAKE2b-256 checksum How to use checksums |
a5151162e4ac811d81482a9078e903116b8dd39f34baecde5c47cf45b5903a93
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / mcp_microsoft_graph_auth-0.1.2-py3-none-any.whl
| Download URL | mcp_microsoft_graph_auth-0.1.2-py3-none-any.whl |
|---|---|
| Size | 27.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
20cb4e62c7c2f9ac867d92c980addd3dfdb6af60d4048c79ebf6cd40b5c6a023
|
|
BLAKE2b-256 checksum How to use checksums |
a1220df51a4ae4deb3ce3d5c3eb19c73774843f568fa6ef2897595e5a0eea8cc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|