Graph MCP

by juststas

Not rated
GitHub

About

An MCP to interact with Office 365 - Teams, mail, calendar.

Details

Author
juststas
Categories
Productivity, Other

Setup

Install Graph MCP in your MCP client (Claude Desktop, Cursor, Windsurf, and others).

Repository: https://github.com/juststas/Graph-MCP

Follow the installation instructions in the repository README, then restart your MCP client.

Graph MCP is a Node.js MCP server that connects Claude Code and Codex to Microsoft Teams, Outlook mail and calendar, online meetings, OneDrive, users, and presence through Microsoft Graph. It runs locally over stdio and requires Node.js 22 or newer.

- Node.js 22 or newer.
- A Microsoft Entra ID app registration configured as apublic clienton theMobile and desktop applicationsplatform.
- Redirect URIhttp://localhost:3000/auth/callback.
- No client secret. Graph MCP uses delegated user authentication.

Add these exact delegated permissions to the app registration:

- offline_access
- openid
- profile
- User.Read
- User.ReadBasic.All
- User.Read.All
- Chat.Read
- Chat.ReadWrite
- ChatMember.ReadWrite
- ChatMessage.Send
- ChannelMessage.Read.All
- ChannelMessage.Send
- ChannelMessage.ReadWrite
- Channel.Create
- TeamMember.Read.All
- Team.ReadBasic.All
- Channel.ReadBasic.All
- ChannelMember.Read.All
- Calendars.ReadWrite
- Calendars.Read.Shared
- Calendars.ReadWrite.Shared
- Place.Read.All
- Mail.Read
- Mail.ReadWrite
- Mail.Send
- MailboxSettings.ReadWrite
- Mail.ReadWrite.Shared
- Mail.Send.Shared
- Presence.Read
- Presence.Read.All
- Presence.ReadWrite
- OnlineMeetings.Read
- OnlineMeetings.ReadWrite
- OnlineMeetingArtifact.Read.All
- OnlineMeetingTranscript.Read.All
- OnlineMeetingRecording.Read.All
- Files.ReadWrite.All
- Sites.Read.All
- People.Read
- Contacts.ReadWrite
- Tasks.ReadWrite

Some organizations require administrator consent for one or more permissions. Use the least privilege your deployment needs and follow your organization's approval process.

This repository is itself a plugin marketplace, so Claude Code can install it straight from GitHub:

claude plugin marketplace add JustStas/Graph-MCP --scope user claude plugin install graph-mcp@graph-mcp --scope user

The same thing works inside a Claude Code session with/plugin marketplace add JustStas/Graph-MCPfollowed by/plugin install graph-mcp@graph-mcp.

Claude clones the repository into its marketplace cache, validates.claude-plugin/marketplace.json, and installs the self-contained plugin under the plugin cache. The MCP server launches from the installed plugin bundle, so no source checkout is needed. To pick up a new release, re-run the two commands.

For plugin development, a local checkout can be added the same way by path instead ofowner/repo:

claude plugin marketplace add /absolute/path/to/Graph-MCP --scope user claude plugin install graph-mcp@graph-mcp --scope user

Codex accepts the same GitHub marketplace source:

codex plugin marketplace add JustStas/Graph-MCP --json codex plugin add graph-mcp@personal --json

codex plugin marketplace addtakes a local path,owner/repo[@ref], or an HTTPS or SSH Git URL, and--refpins a specific tag or branch. The Codex manifest launches./dist/graph-mcp.jsrelative to the installed plugin root, so no source checkout is needed.

For plugin development, point it at a local checkout instead:

codex plugin marketplace add /absolute/path/to/Graph-MCP --json codex plugin add graph-mcp@personal --json

Install the public scoped package globally:

npm install --global @juststas/graph-mcp graph-mcp setup

The npm package is scoped to JustStas, but the installed executable remains graph-mcp. Invoking graph-mcp without arguments starts the MCP server over stdio.

npm ci npm run build node dist/cli.js setup

Then register the built entrypoint with your host:

claude mcp add graph-mcp -- node /absolute/path/to/Graph-MCP/dist/cli.js codex mcp add graph-mcp -- node /absolute/path/to/Graph-MCP/dist/cli.js

setupasks for the Entra application Client ID and Tenant ID and saves them to~/.graph-mcp/config.json. The Client ID and Tenant ID are identifiers, not secrets. The setup command does not perform login.

For an installed plugin, use the bundled setup skill and its host-specific command:

- Claude Code:node "${CLAUDE_PLUGIN_ROOT}/dist/graph-mcp.js" setup
- Codex: resolve the installed plugin root fromskills/setup/SKILL.md, change to that directory, then runnode "./dist/graph-mcp.js" setup

After setup, callgraph_auth_login. Browser PKCE login is the default and opens a local loopback callback on the configured redirect URI. If a browser or loopback callback is unavailable, callgraph_auth_loginwithmethod: "device_code"and follow the returned Microsoft verification instructions.

Never paste a client secret, access token, refresh token, authorization code, MFA code, or other credentials into a conversation. Graph MCP does not need a client secret.

For Client ID and Tenant ID, environment variables take precedence over~/.graph-mcp/config.json, which takes precedence over built-in defaults. The setup command only persists those two identifiers. Other options are environment-only overrides of the built-in defaults.

Positive integer options reject zero, negatives, decimals, and malformed values. Boolean values accepttrue,false,1,0,yes,no,on, oroff.

The Node server encrypts tokens with AES-256-GCM and stores them under~/.graph-mcp:

- tokens-v2.enc— encrypted token data
- .key-v2— generated local encryption key when no environment key is supplied

The previous Python runtime usedtokens.encand.key. Version 0.6.0 deliberately does not read, overwrite, or delete those legacy files because the ciphertext formats differ. After upgrading from the Python release, authenticate once withgraph_auth_login; the Node server then creates its separate versioned token files. Existing Python token files remain untouched and may be removed later according to your local security policy.

Access tokens refresh automatically before expiry.graph_auth_logoutclears the Node token state; it does not modify the legacy Python files.

The Teams message tools (graph_send_chat_message,graph_send_channel_message, andgraph_reply_to_channel_message) and outbound mail tools (graph_send_mailandgraph_reply_mail) default to HTML mode. Whenis_html=true, pass explicit HTML; Markdown is not converted automatically.

<p><strong>Status update</strong></p> <ul> <li>Use <code>&lt;strong&gt;</code> for bold text.</li> <li>Use <code>&lt;pre&gt;&lt;code&gt;</code> for multi-line code blocks.</li> </ul>

Useis_html=falsefor exact plain text. Mentions may use raw Graph data or this simplified shape, paired with the corresponding<at id="0">Jane Smith</at>tag in the HTML body:

[ { "name": "Jane Smith", "user_id": "ef1c916a-3135-4417-ba27-8eb7bd084193" } ]

Install the locked dependencies and run the complete Node verification pipeline:

npm run format:check npm run lint npm run typecheck npm test npm run build npm run validate:versions npm run validate:package npx vitest run tests/plugin-install-smoke.test.ts
claude plugin validate --strict plugins/graph-mcp claude plugin validate --strict . python3 "${CODEX_HOME:-$HOME/.codex}/skills/.system/plugin-creator/scripts/validate_plugin.py" plugins/graph-mcp node scripts/test-plugin-install.mjs npm pack --json --dry-run

The Codex validator is release tooling supplied by Codex'splugin-creatorskill; Python is not required to build, test, or run Graph MCP itself. Before publishing, verify that package, Claude manifest, and Codex manifest versions match the target release, the committed plugin bundle is current, both installed plugins expose exactly 127 tools, and the working tree is clean.

Graph MCP releases use the public npm package@juststas/graph-mcp; there is no Python/PyPI release step. Version 0.6.0 completed the Node migration but was not published to npm because npm rejected the unscopedgraph-mcp@0.6.0name as too similar to the existinggraphmcppackage. Version 0.6.1 is the first scoped npm release.
- Updatepackage.json,package-lock.json, both plugin manifests, runtime metadata,CHANGELOG.md, and the committed plugin bundle to one version.
- Runnpm ci,npm run verify,node scripts/test-plugin-install.mjs, andnpm pack --json --dry-runfrom a clean worktree.
- Merge the reviewed pull request tomain. A repository administrator then creates the annotatedv<version>tag on the merged commit through the mandatory release-tag authority ruleset; the separate no-bypass immutability ruleset blocks later update or deletion.
- Publish the matching GitHub Release. The workflow trigger isrelease: types: [published].
- The package job installs locked dependencies, runsnpm run verify, and prepares the exact tarball without OIDC permission.
- The publish job runs in thenpmGitHub environment and is the only job that receives OIDC permission. It downloads a data-only artifact containing the tarball and metadata, checks out its trusted helper atgithub.workflow_sha, binds the expected tag directly to the release event, validates npm's JSON dry-run manifest for the exact private snapshot, and uses npm Trusted Publishing. It has noNODE_AUTH_TOKENor npm secret.
- Verify the workflow, npm version,dist.integrity, installed CLI version, and 127-tool MCP inventory.

Workflow reruns are idempotent. If the version already exists, the workflow succeeds only when npm's dist.integrity equals the prepared tarball. A different integrity fails and requires a new patch version.

npm requires a package to exist before Trusted Publishing can be configured. Bootstrap the first scoped release in this order:
- Verify mergedmain, then activate the administrator-authorityvruleset.
- Audit the exact historical tag inventory and ancestry, require the exact allowlisted historical PyPI workflow blob where expected, and require the new release helper to be absent everywhere.
- Activate the separate no-bypass immutability ruleset.
- Create the annotatedv0.6.1tag only after those gates pass.
- Runpublish.ymlfrommainwithprepare_onlyenabled and inspect its prepared artifact.
- Validate the exact filename, regular-file status, SHA-512 and SHA-1 digests, and npm's JSON dry-run manifest. Publish that same private snapshot once with the maintainer's interactive 2FA, explicit npmjs registry,latesttag, disabled lifecycle scripts, and public access; then verify its registry version and integrity.
- Reverify both release-tag rulesets.
- Create thenpmGitHub environment.
- Add separate typed environment policies for branchmainand tagv
.
- Verify both rulesets and both typed environment policies.
- Configure npm Trusted Publishing:

npx --yes npm@11.15.0 trust github @juststas/graph-mcp \ --file publish.yml \ --repo JustStas/Graph-MCP \ --env npm \ --allow-publish

Verify the saved repository, workflow filename, environment, and publish permission, then set npm publishing access to require 2FA and disallow traditional tokens.

The manual 0.6.1 bootstrap uses neither OIDC nor provenance, and its integrity-matched release workflow is a no-op that does not test the OIDC exchange. Version 0.6.2 is the first real OIDC publish and provenance check.

Useworkflow_dispatchfrommainwith an existing protected tag to rerun publication. Useprepare_onlywhen only the verified tarball is needed. The release-tag rulesets prohibit moving or deleting publishedv*tags. Never overwrite an npm version; recover from a bad publication with a new patch release.

Claude Code or Codex --stdio--> Graph MCP --HTTPS--> Microsoft Graph API | ~/.graph-mcp/ config.json tokens-v2.enc .key-v2

- Authentication uses OAuth 2.0 Authorization Code with PKCE or device code.
- Access-token refresh is serialized so concurrent Graph calls share one refresh.
- Graph requests use bounded timeouts, sliding-window rate limiting, and exponential retry behavior that honorsRetry-Afteron throttled responses.
- MCP protocol output is written to stdout; diagnostics are written to stderr.

Confirm that the exact delegated permissions above are present and that required administrator consent has been granted.

The endpoint may need a delegated permission or administrator consent not available to the signed-in user. Check the tool's permission and your organizational policy.

Callgraph_auth_loginwithmethod: "device_code"and complete sign-in at the Microsoft verification URL.

Configuration changed but the host still uses old values

Restart the MCP server or host so the process reloadsconfig.jsonand its environment. Environment variables override saved Client ID and Tenant ID values.

Upgraded from the Python release and appear logged out

This is expected once. Rungraph_auth_login; the Node runtime createstokens-v2.encand.key-v2without changing the oldtokens.encand.keyfiles.

This project is an independent open-source effort and isnot affiliated with, endorsed by, or sponsored by Microsoft Corporation. Microsoft, Microsoft Teams, Outlook, Microsoft 365, Microsoft Graph, and Azure are trademarks of the Microsoft group of companies.

This software is provided "as is", without warranty of any kind. Use it at your own risk. The authors accept no liability for damages, data loss, or security issues arising from its use. You are responsible for complying with your organization's policies and Microsoft'sAPI Terms of Use.

This software accesses Microsoft services on your behalf using your own credentials and app registration. Data retrieved from Microsoft Graph (including mail, messages, calendar events, meetings, and files) is passed to the model that invoked the tool. Follow BP and your organization's data-handling, retention, and acceptable-use requirements when using cloud-hosted AI models.

Connect AI clients to Cal.com scheduling through the Model Context Protocol using the hosted server at mcp.cal.com or a local instance.

Sync Calendars, Scheduling Links, AI Executive Scheduling Assistant, Unified Calendar

MCP server to interact with Routine: calendars, tasks, notes, etc.

Query contacts, companies, and relationship data extracted from your email and calendar. Build pre-meeting reports, find warm intros, and identify fading relationships.

An MCP server for managing Attendee meeting bots, requiring a running Attendee backend service.

A command-line tool to fetch Google Calendar schedules and convert them into custom prompts or text snippets using a template engine.

Integrates with the Cal.com Calendar API for appointment scheduling.

An MCP server for intelligently managing calendar events and finding available time slots for appointments and meetings.

Calendrz: Mirror Your Availability Across Every Calendar, Automatically.

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.