OneDrive Read-Only MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OneDrive Read-Only MCP Serversearch my OneDrive for the Q3 budget spreadsheet"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
OneDrive Read-Only MCP Server
A read-only Model Context Protocol (MCP) server that lets an AI agent search and download files from a personal Microsoft OneDrive account via the Microsoft Graph API.
Safety guarantee: read-only
This server only ever issues HTTP GET requests to Microsoft Graph. That is enforced in code, not just by convention:
graph_client.pyhas exactly one function that talks to the network (_get), it hardcodesrequests.get, and it asserts on that fact.No other function in the codebase calls
requests.post/put/patch/delete.There is no "write", "delete", "upload", "move", or "rename" tool exposed by the MCP server — only
search_onedrive,list_folder,get_item_metadata,download_file(downloads FROM OneDrive to local disk — it never uploads or modifies anything in OneDrive), andget_drive_info.
Related MCP server: SharePoint MCP Server
Requirements
Linux server with Python 3.12 (or any Python 3.10+)
A personal Microsoft account (outlook.com/hotmail.com/live.com or a Microsoft account added to consumer OneDrive) — this is NOT for OneDrive for Business / SharePoint (those use a different auth audience).
An Azure App Registration (free, takes ~5 minutes — see below).
1. Azure Portal app registration
Go to https://portal.azure.com → search "App registrations" → New registration.
Name: anything, e.g.
onedrive-mcp.Supported account types: choose "Personal Microsoft accounts only" (or "Accounts in any organizational directory and personal Microsoft accounts" if you want it to also work with a work/school account later — but this project's auth defaults to the
consumerstenant, which only works with personal accounts).Redirect URI: leave blank / not needed — the device code flow used here has no redirect URI.
Click Register.
On the app's Overview page, copy the Application (client) ID — this goes into
.envasAZURE_CLIENT_ID.Go to API permissions → Add a permission → Microsoft Graph → Delegated permissions → search and add:
Files.ReadFiles.Read.AllAdmin consent is not required for these delegated scopes on a personal Microsoft account app — you'll consent yourself during the device-code sign-in.
Go to Authentication → under Advanced settings, set "Allow public client flows" to Yes, then Save. This is required for the device code flow to work (it's a public/native client, no client secret is used or needed).
That's it — no client secret, no redirect URI, no admin consent needed.
2. Local setup
cd /path/to/onedrive-mcp
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
cp .env.example .env
# edit .env: set AZURE_CLIENT_ID to the Application (client) ID from step 1.6.env fields:
Variable | Default | Meaning |
| (required) | Application (client) ID from Azure |
|
| Leave as |
|
| Where MSAL persists tokens (chmod 600) |
|
| Local dir for downloaded files |
3. One-time sign-in (device code flow)
./venv/bin/python scripts/setup_auth.pyThis prints something like:
To sign in, use a web browser to open the page https://microsoft.com/devicelogin
and enter the code ABCD-EFGH to authenticate.Open that URL on any device (phone, another computer, doesn't need to
be the headless server), enter the code, sign in with your personal
Microsoft account, and approve the Files.Read / Files.Read.All
permissions. The script on the server will then complete automatically and
save token_cache.bin (permissions restricted to your user only). Refresh
tokens let the server silently renew access tokens after this — you should
not need to repeat this step unless the token is revoked or unused for an
extended period.
4. Run the server standalone (manual test)
./venv/bin/python server.pyIt will sit waiting on stdio (this is normal — it's meant to be driven by
an MCP client, not typed into directly). Press Ctrl+C to stop. To actually
exercise it, use scripts/smoke_test.py (below) or wire it into Hermes /
Open WebUI.
5. Register with Hermes (stdio MCP client)
Add to Hermes's MCP server config (JSON config, same shape as Claude
Desktop's mcpServers):
{
"mcpServers": {
"onedrive": {
"command": "/path/to/onedrive-mcp/venv/bin/python",
"args": ["/path/to/onedrive-mcp/server.py"]
}
}
}No secrets need to go in this config — server.py loads .env itself
(via python-dotenv) from its own directory, so AZURE_CLIENT_ID etc.
never appear in the Hermes config file.
6. Expose to Open WebUI via mcpo
Open WebUI's "Tool Server" feature speaks OpenAPI/HTTP, not raw MCP-stdio.
Bridge with mcpo:
# install mcpo (either into this project's venv, or globally with pipx)
./venv/bin/pip install mcpo
# or: pipx install mcpo
# run the bridge — bind to localhost, and ALWAYS set an API key (see
# Security note below; mcpo defaults to binding 0.0.0.0 with NO auth if
# you omit --host / --api-key)
./venv/bin/mcpo --host 127.0.0.1 --port 8765 --api-key "<generate-a-random-secret>" -- ./venv/bin/python server.pyGenerate a random API key rather than typing one, e.g.:
python3 -c "import secrets; print(secrets.token_urlsafe(32))"Then in Open WebUI: Settings → Tools → Add Tool Server → OpenAPI URL
http://<server-host>:8765 (use http://127.0.0.1:8765 if Open WebUI runs
on the same host, or your private network address otherwise), and paste the
same API key into Open WebUI's "API Key" field for this tool server.
Security note: mcpo defaults to binding 0.0.0.0 (all network
interfaces) with no authentication at all unless you pass --api-key.
This project's example command above always sets both --host 127.0.0.1
and --api-key — treat both as required, not optional:
Always pass
--api-key. Without one, anyone who can reach the port — including any other local account on a shared/multi-user host, not just remote network attackers — can search and download your entire OneDrive through the HTTP endpoint with zero authentication.Binding to
127.0.0.1does NOT isolate the endpoint from other local users on the same machine. Loopback-bound ports are reachable by any process running as any account on that host. The API key, not the bind address, is what actually restricts access.If you need remote access (Open WebUI on a different host), bind to a private/internal interface only, or put it behind your existing reverse proxy (nginx/Caddy/Traefik) with its own authentication, and never expose the port directly to the internet — but keep
--api-keyset regardless.
A ready-to-edit systemd unit template for running the mcpo bridge
persistently is provided at deploy/onedrive-mcpo.service (disabled by
default — copy, edit paths/user, then enable it yourself).
sudo cp deploy/onedrive-mcpo.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now onedrive-mcpo.serviceTools exposed
Tool | Description |
| Full-text search across the drive |
| List a folder's children |
| Full metadata for one file/folder |
| Download a file to |
| Quota/owner info — good smoke test |
All tools accept either a human path (e.g. /Documents/report.pdf) or a
raw Graph item id where a "path_or_id" parameter is documented.
Testing
Unit tests (no credentials needed, no network calls)
./venv/bin/python -m pytest -vThese mock all Graph HTTP responses with the responses library and test
path resolution + response shaping logic only.
Manual integration smoke test (REQUIRES real sign-in first)
./venv/bin/python scripts/setup_auth.py # one-time, if not already done
./venv/bin/python scripts/smoke_test.pyThis calls get_drive_info() and list_folder('/') against your real
OneDrive account and prints the results. It is intentionally excluded from
the pytest suite because it needs live credentials and network access.
Troubleshooting
AADSTS700016/AADSTS7000218: usually means "Allow public client flows" is not enabled on the app registration (step 1.8), or the client ID is wrong.AADSTS65001(consent required/denied): you declined the permission prompt during device-code sign-in, or the app is missing theFiles.Read/Files.Read.Alldelegated permissions (step 1.7). Re-runscripts/setup_auth.py.AADSTS50020(user account from wrong tenant): you tried to sign in with a work/school account whileAZURE_TENANT_ID=consumers. Use a personal Microsoft account, or change the app's supported account type andAZURE_TENANT_IDaccordingly (outside this project's default scope)."accessNotConfigured" / permission errors on Graph calls (HTTP 403): double-check
Files.ReadandFiles.Read.Allare added under API permissions as Delegated (not Application) permissions, and that you approved them during sign-in.invalid_grant/ "Could not silently refresh...": the refresh token expired or was revoked (e.g. password change, long inactivity, or you deletedtoken_cache.bin). Re-run./venv/bin/python scripts/setup_auth.py.Throttling (HTTP 429):
graph_client.pyalready retries with backoff honoring theRetry-Afterheader, up to 4 attempts. If you still see failures, you're issuing requests faster than Graph's limits allow — reduce concurrency/frequency.ModuleNotFoundError: mcp.server.fastmcp: you likely installedmcp2.x. This project pinsmcp<2.0.0inrequirements.txt(FastMCP was renamed/relocated in mcp 2.x) — reinstall with./venv/bin/pip install -r requirements.txt.
Project structure
onedrive-mcp/
server.py MCP server + the 5 tool definitions (FastMCP, stdio)
graph_client.py Read-only Graph API wrapper (GET-only, enforced)
auth.py MSAL device-code flow + token cache load/save/refresh
scripts/
setup_auth.py One-time interactive device-code sign-in
smoke_test.py Manual integration test (needs real credentials)
tests/
test_graph_client.py Unit tests (mocked Graph HTTP responses)
test_auth.py Unit tests for auth config handling
deploy/
onedrive-mcpo.service systemd template for the mcpo HTTP bridge
requirements.txt
.env.example
.gitignore
README.mdThis server cannot be deployed
Maintenance
Related MCP Connectors
Permissioned access to Outlook, OneDrive and Teams via the user's own Microsoft account
Knowledge base MCP for AI agents on iknow.dev. Search, read, and maintain via OAuth.
Search your AI chat history (ChatGPT, Claude, Codex) from any MCP client. Remote, private, read-only
Read-only MCP server exposing a user ORANO library to their own AI agent.
Related MCP Servers
- FlicenseDqualityDmaintenanceProvides access to organizational Sharepoint documents through the Microsoft Graph API, enabling search and retrieval of Sharepoint content for AI assistants.122 npm21-
- AlicenseNot gradedqualityDmaintenanceEnables browsing and interacting with Microsoft SharePoint sites and documents through Microsoft Graph API, supporting file search, site listing, document library browsing, and file content retrieval with OAuth2 authentication.15 npm10MIT
- FlicenseNot gradedqualityNot gradedmaintenanceProvides unified access to OneDrive and SharePoint through Microsoft Graph API, enabling file operations, SharePoint list management, Excel integration, and content search across personal and business Microsoft accounts.-
- FlicenseAqualityDmaintenanceConnects Claude with OneDrive via Microsoft Graph API to list, search, create, move, copy, and share files.10-