Container for @jbctechsolutions/mcp-office365,
a Microsoft Graph MCP server. Scoped to the presets you actually want — Teams
is intentionally excluded (that stays on the dedicated teams MCP).
Attribution
All credit for the actual MCP server goes to JBC Tech Solutions, LLC (Joel,
@jbctech), who wrote and maintains@jbctechsolutions/mcp-office365 (MIT licensed). This repository contains no server code of its own — only a Docker wrapper, an Entra app-registration walkthrough, and operational notes from running their package in a container. If you find this useful, go star their repo.
| Preset | Covers |
|---|---|
planner | plans, buckets, tasks, category labels, task comments |
tasks | Microsoft To Do — task lists, tasks, checklists, attachments |
mail | read/search/send mail, drafts, replies, organize, rules, OOF |
calendar | events, RSVP, rooms, sharing |
files | OneDrive browse/read (also backs the shared-mailbox drive tools) |
meetings | free/busy availability, "find a time everyone's free" |
~178 tools total. Destructive writes use a two-phase prepare_* → confirm_*
flow.
User.Read
offline_access
Tasks.ReadWrite
Group.Read.All
Team.ReadBasic.All
Mail.ReadWrite
Mail.Send
Calendars.ReadWrite
Mail.Read.Shared
Calendars.Read.Shared
Files.Read.All
Note: keep the
OUTLOOK_MCP_*variable names exactly as they are — the app reads those names. Only the values are yours to fill in.
cp .env.example .env
# Fill in your Entra app's real client (application) ID and tenant (directory)
# ID — App registrations → your app. chmod 600 .env
A ready-built image is on Docker Hub:
docker pull teejeer/office365-mcp # or :1.0.0
Everything below works identically with teejeer/office365-mcp in place of
office365-mcp. The upstream package is baked into the image at build
time (pinned via the O365_MCP_VERSION build arg, current default 5.1.1),
so published tags are reproducible and the container starts instantly with no
npm fetch. To upgrade upstream: bump the arg and release a new version:
docker build --build-arg O365_MCP_VERSION=5.2.0 -t office365-mcp .
Releases are cut with release.sh:
./release.sh 1.0.1 "what changed" # rebuild, push :1.0.1 + :latest, git tag, GitHub release
Tokens are written by the app to ~/.mcp-office365 inside the container, so
that path must be mounted at a host directory the container can write to.
mkdir -p ~/mcp-o365-state && chmod 777 ~/mcp-o365-state
docker build -t office365-mcp .
docker run --rm -it \
--env-file .env \
-v "$HOME/mcp-o365-state:/home/appuser/.mcp-office365" \
--entrypoint npx office365-mcp \
-y @jbctechsolutions/mcp-office365 auth
Follow the printed URL (https://login.microsoft.com/device) + code. Tokens
persist in the mounted dir, so later runs refresh silently. Re-run with
auth --status to check, auth --force to re-consent after scope changes.
~/.config/opencode/opencode.json:
{
"mcp": {
"office365": {
"type": "local",
"command": [
"docker", "run", "-i", "--rm",
"--env-file", "/path/to/office365-mcp/.env",
"-v", "/home/YOU/mcp-o365-state:/home/appuser/.mcp-office365",
"office365-mcp"
],
"timeout": 60000,
"enabled": false
}
}
}
~/.mcp-office365/tokens.json in the app —
OUTLOOK_MCP_STATE_DIR only moves the SQLite state.db, not the token
cache. Mounting anywhere else silently loses your login.chmod 777, or chown to 1001 if you can).--env-file.GRAPH_PERMISSION_DENIED, your token predates a scope
change — re-run the auth step.list_emails requires folder_id explicitly (e.g. "inbox") — it has no default.prepare_batch_delete_emails → confirm_batch_operation,
where tokens is an array of {token_id, email_id} objects (not plain strings).
Validation errors are mislabeled GRAPH_ERROR.prepare_* previews may render timeReceived with the wrong year (e.g. 2057) —
cosmetic only, the underlying items are correct.Content type
Image
Digest
sha256:f0242c8be…
Size
82.7 MB
Last updated
9 days ago
docker pull teejeer/office365-mcp