Skip to main content
Glama
Microsoft 365 MCP
by saledream
README.md
# Microsoft 365 MCP

Independent read-only Microsoft 365 MCP project. No source, build context,
container, network or credential dependency on ActiveDirectoryMCP or WinRM-MCP.
The Graph tool allowlist and account pinning are described in DEPLOYMENT.md.

## Build And Run

Requirements: Windows, Node.js 24, Docker Desktop with Linux containers, and the
existing private company sign-in configured under `%LOCALAPPDATA%\MS365MCP\config`.

```powershell
npm ci --ignore-scripts --no-audit --no-fund
npm rebuild keytar --foreground-scripts
docker compose build microsoft365
.\start.ps1
```

Only the keytar install script is needed on Windows. Docker installation disables
all dependency install scripts. `start.ps1` starts a disposable container in the
`microsoft365-mcp` Compose project for each MCP client connection. It publishes no
port, runs as UID 1000 with a read-only root filesystem and dropped capabilities,
and mounts only its encrypted `docker-cache` directory. No Docker socket is mounted.
`docker compose down` stops this project without stopping AD or WinRM.

Claude Desktop uses the absolute path to this project's `start.ps1` and the same
private `-ConfigurationDirectory`. It must be reloaded after changing that path.

## Authentication

The MCP server and all Graph tools run in Linux. The Windows launcher only reads
the existing encryption key from Windows Credential Manager, seeds a dedicated
encrypted cache on first use, and proxies stdio. The key is sent through stdin
before MCP traffic; it is never put in container environment variables, arguments,
an image, Claude JSON or a disk key file. The container uses the upstream AES-GCM
cache format and fails closed on unreadable caches. Docker administrators and the
current Windows user are trusted; keys and tokens necessarily exist in process memory.

The original Windows cache is preserved. Container refreshes and local auth
changes persist only in `config\docker-cache`; an initialization marker prevents
old native tokens from being restored after a container logout. To sign in again:

```powershell
.\start.ps1 -Mode Login
.\start.ps1 -Mode VerifyLogin
```

Complete Microsoft sign-in privately. Successful native Login synchronizes the
encrypted cache into the Docker cache. VerifyLogin checks native authentication;
container initialization separately verifies the pinned account is available.
No new tenant permissions or accounts are created by the migration.

## Verification

```powershell
npm test
npm run test:readonly
docker build --target test -t microsoft365-mcp:standalone-test .
docker run --rm --network none --read-only --cap-drop ALL --security-opt no-new-privileges --tmpfs /tmp:rw,noexec,nosuid,size=64m microsoft365-mcp:standalone-test
```

The tests use synthetic data and mock Graph responses. Tool discovery alone is
not proof of live Microsoft Graph authorization. Source dependencies are pinned
in package-lock.json; do not copy a Windows node_modules directory into the image.

Rollback: restore only Claude's previous `ms365-readonly` launcher path to the
archived vendor directory. Keep the original encrypted cache and Windows vault
entry. Do not replace the complete Claude configuration or delete private data.
## Claude Desktop Configuration

Add to your claude_desktop_config.json:

`json
{
  "mcpServers": {
    "microsoft365": {
      "command": "powershell.exe",
      "args": [
        "-ExecutionPolicy",
        "Bypass",
        "-File",
        "C:\\Users\\mmcy\\Downloads\\MCP\\Microsoft365-MCP\\start.ps1"
      ]
    }
  }
}
`

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.