Skip to main content

Read-only Model Context Protocol (MCP) server for the Microsoft Graph Service Communications API — exposes M365 service health and Message Center posts to AI agents.

Project description

m365-service-comms-mcp

⚠️ Preview (v0.1). Read-only Model Context Protocol server for the Microsoft Graph Service Communications API. Exposes M365 service health and Message Center posts to AI agents (Claude, GitHub Copilot, Cursor, VS Code, Claude Desktop, etc.).

CI CodeQL License: MIT Python 3.11+

Status

Item State
Version 0.1.0 (preview)
Tools 3 — list_service_health, list_message_center_posts, get_message_center_post
Auth Delegated only (browser sign-in / device code)
Transport stdio
Distribution PyPI via uvx
Listing GitHub MCP Registry (planned for v0.1.08)

Application-permission auth, additional tools, Docker image, and additional documentation are deferred to v1.0.

Why this exists

There is no published MCP server today that wraps the Graph Service Communications API with delegated authentication. The closest alternatives:

This server fills the gap: delegated auth + service health + message center, in Python so M365 admins on any platform can install it with a single uvx command.

Quickstart

Zero-setup quickstart (no app registration required)

You don't need to register your own Entra app — by default, the server uses the Microsoft Graph PowerShell well-known multi-tenant public client (14d82eec-204b-4c2f-b7e8-296a70dab67e) so any admin can sign in via browser and grant consent on first use.

// .vscode/mcp.json (or any MCP-compatible client config)
{
  "servers": {
    "m365-svc-comms": {
      "type": "stdio",
      "command": "uvx",
      "args": ["m365-service-comms-mcp"]
    }
  }
}

Then ask your agent:

List the M365 services and tell me which ones are degraded.

A browser will open the first time, prompting you to sign in to your tenant. On first sign-in, an admin must grant consent for the ServiceHealth.Read.All and ServiceMessage.Read.All Graph permissions (this is a one-click step in the consent prompt). Subsequent runs reuse the cached token \u2014 no browser unless the token expires.

Try it without any tenant (--demo mode)

Verify the MCP wire protocol works with your AI client before signing in:

{
  "servers": {
    "m365-svc-comms-demo": {
      "type": "stdio",
      "command": "uvx",
      "args": ["m365-service-comms-mcp", "--demo"]
    }
  }
}

You should see 3 services returned, with Microsoft Teams flagged as serviceDegradation (canned data).

Use your own Entra app registration (optional)

If you want a dedicated audit identity in your tenant (so audit logs show your app's display name instead of "Microsoft Graph PowerShell"), register your own Entra app following Entra app registration below, then set M365_TENANT_ID and M365_CLIENT_ID.

Verify your setup

uvx m365-service-comms-mcp --auth-test

You should see (using defaults):

Tenant ID : organizations
Client ID : 14d82eec-204b-4c2f-b7e8-296a70dab67e
            (using the Microsoft Graph PowerShell public client \u2014 no Entra app registration needed)
Auth flow : interactive-browser (default)
Acquiring access token \u2026
\u2713  Token acquired.
Probing https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/healthOverviews?$top=1 \u2026
\u2713  Graph responded HTTP 200 (returned 1 healthOverview record(s)).
Auth test passed.

Recommended testing tenant

If your primary tenant is locked down (typical for large organizations including Microsoft itself), use a free Microsoft 365 Developer Program sandbox tenant. It comes with:

  • An E5 license
  • 25 pre-provisioned admin and user accounts
  • Full Global Administrator rights for the tenant owner
  • Auto-renewing 90-day subscription as long as you stay active

Sign up takes about 10 minutes.

Entra app registration (optional, advanced)

You only need this if you want a dedicated audit identity instead of the default "Microsoft Graph PowerShell" client. The walkthrough below assumes the Microsoft Entra admin center UI as of 2026.

  1. Go to Microsoft Entra admin center \u2192 Identity \u2192 Applications \u2192 App registrations \u2192 + New registration.
  2. Name: m365-service-comms-mcp (or whatever you like).
  3. Supported account types: Accounts in this organizational directory only (single tenant).
  4. Redirect URI: select Public client/native (mobile & desktop) and enter http://localhost.
  5. Click Register. Copy the Application (client) ID and Directory (tenant) ID from the Overview page \u2014 these become M365_CLIENT_ID and M365_TENANT_ID below.
  6. Go to API permissions \u2192 + Add a permission \u2192 Microsoft Graph \u2192 Delegated permissions. Add:
    • ServiceHealth.Read.All
    • ServiceMessage.Read.All
  7. Click Grant admin consent for <your tenant> and confirm. Both permissions should now show Granted.

The signed-in user must hold one of these directory roles (regardless of whether you use the default client or your own app):

  • Service Support Administrator
  • Helpdesk Administrator
  • Global Reader
  • Global Administrator

MCP client configuration

Set these two environment variables in whatever MCP client you use:

M365_TENANT_ID=<directory-tenant-guid>
M365_CLIENT_ID=<application-client-guid>

VS Code (Copilot Chat)

Create .vscode/mcp.json in your workspace, or add to your user mcp.json:

{
  "servers": {
    "m365-svc-comms": {
      "type": "stdio",
      "command": "uvx",
      "args": ["m365-service-comms-mcp"],
      "env": {
        "M365_TENANT_ID": "00000000-0000-0000-0000-000000000000",
        "M365_CLIENT_ID": "00000000-0000-0000-0000-000000000000"
      }
    }
  }
}

Claude Desktop

Add to claude_desktop_config.json (Settings → Developer → Edit Config):

{
  "mcpServers": {
    "m365-svc-comms": {
      "command": "uvx",
      "args": ["m365-service-comms-mcp"],
      "env": {
        "M365_TENANT_ID": "00000000-0000-0000-0000-000000000000",
        "M365_CLIENT_ID": "00000000-0000-0000-0000-000000000000"
      }
    }
  }
}

Cursor

Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "m365-svc-comms": {
      "command": "uvx",
      "args": ["m365-service-comms-mcp"],
      "env": {
        "M365_TENANT_ID": "00000000-0000-0000-0000-000000000000",
        "M365_CLIENT_ID": "00000000-0000-0000-0000-000000000000"
      }
    }
  }
}

GitHub Copilot CLI

Add to ~/.github/copilot/mcp.json:

{
  "servers": {
    "m365-svc-comms": {
      "type": "stdio",
      "command": "uvx",
      "args": ["m365-service-comms-mcp"],
      "env": {
        "M365_TENANT_ID": "00000000-0000-0000-0000-000000000000",
        "M365_CLIENT_ID": "00000000-0000-0000-0000-000000000000"
      }
    }
  }
}

Headless / CI (device-code flow)

If your environment can't open a browser (SSH session, container, CI), set M365_AUTH_DEVICE_CODE=1. The server will then print a code and a URL for you to complete sign-in from a different device.

Verify your setup

After configuring, run:

uvx m365-service-comms-mcp --auth-test

You should see:

Tenant ID : <your-tenant-guid>
Client ID : <your-app-client-guid>
Auth flow : interactive-browser (default)
Acquiring access token …
✓  Token acquired.
Probing https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/healthOverviews?$top=1 …
✓  Graph responded HTTP 200 (returned 1 healthOverview record(s)).
Auth test passed. ServiceHealth.Read.All is granted and admin consent is in place.

Then in your AI client, ask:

Use the m365-svc-comms server to list the current Microsoft 365 service health.

You should see real service health data for your tenant.

Tools reference

list_service_health

List the current health status of every M365 service the tenant subscribes to.

Input Type Default Notes
top int (1..50) 25 Maximum number of services to return

Returns Graph healthOverviews records: id, service, status (serviceOperational / serviceDegradation / serviceInterruption / extendedRecovery / investigating / etc.).

list_message_center_posts

List Message Center posts ordered by most recently modified.

Input Type Default Notes
top int (1..50) 25 Maximum number of posts to return
category planForChange | preventOrFixIssue | stayInformed | unknownFutureValue none Optional category filter
severity normal | high | critical none Optional severity filter

Returns Graph messages records (without bodies — use get_message_center_post for the full content).

get_message_center_post

Fetch the full Message Center post body and metadata.

Input Type Notes
message_id str matching ^[Mm][Cc][0-9]{4,8}$ e.g. MC123456

Returns the full Graph serviceUpdateMessage record including the rendered HTML body.

Troubleshooting

--auth-test fails with Authorization_RequestDenied

You haven't granted admin consent for the API permissions in step 7 of Entra app registration. Open your app registration in the Entra admin center, go to API permissions, and click Grant admin consent for <your tenant>.

--auth-test fails with Forbidden even after admin consent

The signed-in user does not hold an admin role. See the role list at the end of Entra app registration. Add the user to one of those roles via Microsoft Entra admin center → Identity → Roles & admins.

Browser doesn't open / I'm on SSH

Set M365_AUTH_DEVICE_CODE=1 in the env block of your MCP client config. The server will print a code + URL on first call; complete sign-in on any device.

uvx: command not found

Install uv first:

pip install uv
# or follow https://docs.astral.sh/uv/getting-started/installation/

If your corporate machine blocks uv, fall back to pipx:

pipx install m365-service-comms-mcp

…and replace "command": "uvx" with "command": "m365-svc-comms-mcp" and drop the first args entry.

Token cache problems on Linux

If you see errors about Secret Service or keyring, install the keyring backend:

sudo apt install gnome-keyring  # Debian/Ubuntu

The server will fall back to a file-permission–restricted cache automatically if the keyring is unavailable.

Graph returns 429 TooManyRequests

The server retries 429s with exponential backoff (4 attempts by default). If you keep seeing this, you're likely hammering the API in a loop. Service Communications has a soft limit of about 10 RPS per tenant.

Locked-down corporate tenant won't let me grant consent

Use a free Microsoft 365 Developer Program sandbox tenant for testing. See Recommended testing tenant.

If you don't want to set up a sandbox tenant, you can still verify the MCP wire protocol with --demo mode (no tenant required).

Known limitations (v0.1)

  • Read-only. No tools for marking messages as read / archiving / favoriting yet (the Graph API supports it; v1.0 will).
  • 3 tools. get_service_health (per-service deep-dive), list_service_issues, get_service_issue, get_incident_report, and summarize_my_tenant are planned for v1.0.
  • Delegated auth only. No client-secret or certificate flows. Backend monitoring scenarios will need to wait for v1.0.
  • stdio transport only. No Streamable HTTP for hosted/multi-tenant scenarios yet.
  • No Docker image on mcr.microsoft.com — install via PyPI/uvx only.

Local development

# from the repo root
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -e ".[dev]"
ruff check .
ruff format --check .
pytest --cov

End-to-end smoke test against the demo client (no tenant required):

.\.venv\Scripts\m365-svc-comms-mcp.exe --demo
# then connect any MCP client to it via stdio

License

MIT — chosen for broad compatibility:

  • Customer use: commercial use, modification, redistribution, and incorporation into proprietary products are all permitted with the license notice retained.
  • Microsoft use: MIT is on Microsoft's approved OSS-license list and is the license used by every Microsoft-authored MCP server in the microsoft/mcp catalog (Azure MCP Server, Markitdown MCP, Fabric MCP) and by the comparable community Microsoft 365 MCP servers (Softeria/ms-365-mcp-server, okapi-ca/ms-365-admin-mcp-server).
  • GPL-compatible, so downstream redistribution under copyleft licenses is permitted if a consumer chooses.

The license is declared in pyproject.toml using PEP 639 SPDX format (license = "MIT") and the LICENSE file is included in the published wheel.

Security

See SECURITY.md. Do not file security issues in the public tracker — open a private security advisory instead.

Code of Conduct

See CODE_OF_CONDUCT.md. This project follows the Contributor Covenant v2.1.

Project details


Download files

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

Source Distribution

m365_service_comms_mcp-0.1.2.tar.gz (29.3 kB view details)

Uploaded Source

Built Distribution

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

m365_service_comms_mcp-0.1.2-py3-none-any.whl (25.4 kB view details)

Uploaded Python 3

File details

Details for the file m365_service_comms_mcp-0.1.2.tar.gz.

File metadata

  • Download URL: m365_service_comms_mcp-0.1.2.tar.gz
  • Upload date:
  • Size: 29.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for m365_service_comms_mcp-0.1.2.tar.gz
Algorithm Hash digest
SHA256 1186f195f13afe48d946ba2cb81018dd0fe8e4b67eb3ae6099096087af81f111
MD5 9f3409beb2f33daa6c512b8236937708
BLAKE2b-256 82e6aa4b06205034fd6fd6f76a33fca23e9fb578097044f1df5532ac0953f913

See more details on using hashes here.

Provenance

The following attestation bundles were made for m365_service_comms_mcp-0.1.2.tar.gz:

Publisher: publish.yml on trobichaux/m365-service-comms-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file m365_service_comms_mcp-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for m365_service_comms_mcp-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d0a5498455e4591fa7a2c344ef07fdb669c40dc85cf330f3f54a1e18d759a9af
MD5 47b47fe0942df783b66bb05c4ba0deaf
BLAKE2b-256 b2b73f1ad6f409de47b3a90dcc410362af1322a6cb231998f648e51e366ba11d

See more details on using hashes here.

Provenance

The following attestation bundles were made for m365_service_comms_mcp-0.1.2-py3-none-any.whl:

Publisher: publish.yml on trobichaux/m365-service-comms-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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