@charansamanchi/mcp-onedrive
v1.1.3
Published
Give Joule Work Desktop and Claude Desktop semantic search over your local OneDrive documents — powered by SAP AI Core embeddings and LanceDB.
Maintainers
Readme
Local OneDrive Semantic Search
Give Joule Work Desktop and Claude Desktop semantic search over your local OneDrive documents — powered by SAP AI Core embeddings and LanceDB. Ask questions like "what do my files say about Q4 budget?" and get answers with source citations across PDFs, Word docs, Excel sheets, PowerPoint files, and more. Uses vector similarity to find content by meaning, not just filename. Incremental indexing with a file watcher keeps the index current automatically. Runs entirely on your machine — your files and index never leave your device.
Ask Claude things like:
- "What do my files say about Q4 budget?"
- "Find my architecture diagram for the BTP project"
- "Summarise the contract I have with Vendor X"
Quick Start — SAP Joule Work Desktop
# 1. Install
npm install -g @charansamanchi/mcp-onedrive
# 2. Configure — create a .env file with your credentials
# (see Configuration section below for all parameters)
# 3. Build your local index (one-time)
mcp-onedrive build-index
# 4. Start the HTTP server
mcp-onedrive --http
# → listening on http://localhost:7722/mcp
# 5. In Joule Work Desktop → Add Connector
# Name: OneDrive
# URL: http://localhost:7722/mcpThe server runs locally on your machine — your files and index never leave your device. Joule connects to
localhost:7722.
How It Works
INDEXING (one-time + file watcher)
OneDrive files
│
▼ parse → chunk (~500 tokens, strategy varies by file type)
│ pdf/txt → split by paragraph
│ docx → split by heading
│ pptx → split by slide
│ xlsx → batches of 50 rows
│
▼ SAP AI Core embeddings (batched 20/call, 150ms delay between batches)
│
▼ LanceDB vector store → persisted to disk (index/)
QUERY TIME (every semantic_search call)
Your question
│
▼ SAP AI Core: one embed call for the query text
│
▼ LanceDB L2 similarity search → top-K matching text chunks
│ score = 1 / (1 + L2_distance) — typical relevant results: 0.50–0.65
│ threshold: results below 0.40 are considered low-confidence
│
▼ Claude reads the text chunks and answersDocument embeddings are pre-generated and stored locally. AI Core is called once per query to embed the search question — it never re-processes your files at query time.
OAuth tokens for AI Core are cached in memory for their lifetime. Rotating AICORE_CLIENT_SECRET requires a process restart to take effect.
Prerequisites
| Requirement | Details | |---|---| | Node.js | v18 or later | | SAP AI Core | Instance with an OpenAI-compatible embeddings deployment | | OneDrive | Synced locally to a known absolute folder path |
SAP corporate environments: Microsoft Graph API requires Azure app registration, which SAP IT restricts for most corporate accounts. This server uses the local synced OneDrive folder directly — no Graph API or Azure registration needed.
Installation
Option A — npm (global install)
npm install -g @charansamanchi/mcp-onedriveOption B — clone and run locally
git clone https://github.tools.sap/I355335/mcp-ai-onedrive.git
cd mcp-ai-onedrive
npm installConfiguration
Copy .env.example to .env and fill in your values:
cp .env.example .env# ── OneDrive local path ───────────────────────────────────────
ONEDRIVE_ROOT=C:\Users\YourName\OneDrive - Your Org
# ONEDRIVE_PERSONAL=C:\Users\YourName\OneDrive # optional second root
# ── File size limits ──────────────────────────────────────────
MAX_READ_KB=1024
MAX_INDEX_MB=50
# ── SAP AI Core credentials ───────────────────────────────────
AICORE_CLIENT_ID=<client-id>
AICORE_CLIENT_SECRET=<client-secret>
AICORE_TOKEN_URL=https://<subdomain>.authentication.<region>.hana.ondemand.com/oauth/token
AICORE_API_URL=https://api.ai.<region>.hana.ondemand.com
AICORE_RESOURCE_GROUP=default
# If your embedding deployment is in a different resource group, set this.
# Leave blank to use AICORE_RESOURCE_GROUP above.
AICORE_EMBEDDING_RESOURCE_GROUP=
# ── Embedding model deployment ────────────────────────────────
AICORE_EMBEDDING_DEPLOYMENT_ID=<your-deployment-id>
# ── Vector index ──────────────────────────────────────────────
# Use an ABSOLUTE path — relative paths break when launched via Claude Desktop
VECTOR_INDEX_PATH=C:\Users\YourName\path-to\mcp-onedrive\index
SEMANTIC_TOP_K=5Parameter reference
| Variable | Required | Description |
|---|---|---|
| ONEDRIVE_ROOT | Yes | Absolute path to your primary OneDrive folder |
| ONEDRIVE_PERSONAL | No | Optional second OneDrive root (e.g. personal alongside work) |
| MAX_READ_KB | No | Max file size for read_file tool in KB. Default: 1024. Files above this must be accessed via semantic_search instead. |
| MAX_INDEX_MB | No | Max file size for the indexing pipeline in MB. Default: 50. Files above this are skipped during build-index. |
| AICORE_CLIENT_ID | Yes | SAP AI Core service key client ID |
| AICORE_CLIENT_SECRET | Yes | SAP AI Core service key client secret |
| AICORE_TOKEN_URL | Yes | OAuth token URL from SAP AI Core service key |
| AICORE_API_URL | Yes | SAP AI Core API base URL (no trailing slash) |
| AICORE_RESOURCE_GROUP | Yes | Resource group for your deployments. Default: default |
| AICORE_EMBEDDING_RESOURCE_GROUP | No | Resource group for the embedding deployment if different from above. Falls back to AICORE_RESOURCE_GROUP. |
| AICORE_EMBEDDING_DEPLOYMENT_ID | Yes | Deployment ID for the embedding model |
| VECTOR_INDEX_PATH | No | Where LanceDB stores the vector index. Must be an absolute path when used via Claude Desktop. Default: ./index |
| SEMANTIC_TOP_K | No | Number of chunks returned per semantic_search call. Default: 5 |
SAP AI Core embedding endpoint: The embedding API path requires a
/v1/prefix —POST .../deployments/{id}/v1/embeddings. This differs from SAP AI Core chat models which use/invoke. If you see 404 errors on embed calls, check the URL structure.
Build the Index (Required Before First Use)
This is a one-time prerequisite. It walks your OneDrive folder, parses all supported files, generates embeddings via AI Core, and stores them in a local LanceDB database. Subsequent runs are incremental — only new or changed files are re-processed.
# Global install
mcp-onedrive build-index
# Scope to a specific folder (global install)
mcp-onedrive build-index --folder "C:\Users\YourName\OneDrive\Projects"
# Or if running locally
npm run build-index
node scripts/build-index.js --folder "C:\Users\YourName\OneDrive\Projects"Progress is shown as files are indexed:
[indexer] Found 2335 supported files
[indexer] To index/update: 142
[1/142] Annual Report 2024.pdf → 24 chunks
[2/142] Budget Q4.xlsx → 8 chunksAfter the initial build, a file watcher keeps the index current automatically. However:
- Files larger than 2 MB added after the initial build are not auto-indexed by the watcher. Re-run
build-indexto include them. - Files that fail to parse (encrypted PDFs, malformed xlsx, etc.) are logged to
index/index-failures.jsonand skipped. Useget_index_statusto see failures, or inspect the file directly.
Note on large Excel files: The xlsx parser can hang on very large or malformed
.xlsxfiles. The indexer applies a 60-second parse timeout — files that exceed it are recorded inindex-failures.jsonand skipped. The build continues without them.
Supported file types
.txt .md .json .csv .xml .yaml .yml .docx .pdf .xlsx .xls .pptx .js .ts .py
Usage
Joule Work Desktop (HTTP connector)
Start the server in HTTP mode:
ONEDRIVE_ROOT="C:\Users\YourName\OneDrive - Your Org" mcp-onedrive --http
# listening on http://127.0.0.1:7722/mcpIn Joule Work Desktop → Add Connector:
- Name: OneDrive
- URL:
http://127.0.0.1:7722/mcp
Then ask Joule to run semantic_search or search_files to find content in your OneDrive.
Claude Desktop (stdio)
Add to claude_desktop_config.json — see full config in the Claude Desktop Setup section below.
# Server is spawned automatically by Claude Desktop — no manual start needed
node src/index.jsCLI / stdio
node src/index.jsClaude Desktop Setup (stdio)
Add this to your Claude Desktop claude_desktop_config.json:
{
"mcpServers": {
"onedrive": {
"command": "node",
"args": [
"--max-old-space-size=512",
"C:/Users/YourName/path-to/mcp-onedrive/src/index.js"
],
"env": {
"NODE_NO_WARNINGS": "1",
"ONEDRIVE_ROOT": "C:\\Users\\YourName\\OneDrive - Your Org",
"AICORE_CLIENT_ID": "<client-id>",
"AICORE_CLIENT_SECRET": "<client-secret>",
"AICORE_TOKEN_URL": "https://<subdomain>.authentication.<region>.hana.ondemand.com/oauth/token",
"AICORE_API_URL": "https://api.ai.<region>.hana.ondemand.com",
"AICORE_RESOURCE_GROUP": "default",
"AICORE_EMBEDDING_DEPLOYMENT_ID": "<your-deployment-id>",
"VECTOR_INDEX_PATH": "C:\\Users\\YourName\\path-to\\mcp-onedrive\\index"
}
}
}
}Important notes on the config:
--max-old-space-size=512— limits Node.js heap to 512 MB. Without this, the file watcher can queue a large number of debounce timers at startup, grow the heap to several GB, and crash. Claude Desktop shows "Server disconnected" with no other indication.NODE_NO_WARNINGS=1— suppresses Node.js deprecation warnings to stderr/stdout. Thepdf-parselibrary emits a warning onrequire()that would be written to stdout, corrupting the MCP JSON-RPC stream and causingUnexpected token 'W'...errors on every tool call.VECTOR_INDEX_PATH— must be an absolute path. Claude Desktop spawns the MCP server with a working directory under its own AppData folder, so a relative./indexwould resolve to the wrong location and the server would start with an empty index on every restart.
After saving the config: fully quit Claude Desktop via the system tray → Quit (not just closing the window — the process stays running in the tray otherwise), then reopen it.
Note: You can use either a
.envfile (for local/dev use) or theenvblock inclaude_desktop_config.json. The config block takes precedence.VECTOR_INDEX_PATHin.envcan remain as./indexfor local CLI use — only the config block needs the absolute path.
Joule Work Desktop Setup (HTTP)
Start the server in HTTP mode:
node src/index.js --http
# listening on http://127.0.0.1:7722/mcpOr with a custom port via environment variable:
MCP_PORT=7722 node src/index.js --httpThen in Joule Work Desktop → Add Connector:
- Name: OneDrive
- URL:
http://127.0.0.1:7722/mcp
The server must be running before Joule can connect. The stdio mode (Claude Desktop) and HTTP mode (Joule) can both run simultaneously on the same machine — they are independent processes.
Available MCP Tools
| Tool | Description |
|---|---|
| semantic_search | Search files by meaning using vector similarity. Returns top-K chunks with file path, score, and excerpt. |
| search_files | Search for files and folders by name keyword. Returns file path, size, and modified date. |
| read_file | Read the full contents of a specific file. Limited by MAX_READ_KB — if a file exceeds the limit, use semantic_search instead (the file is still indexed and searchable). |
| list_files | List files in a folder |
| get_file_info | Get metadata (size, dates, type) for a file |
| get_index_status | Check index coverage and list any files that failed to index |
| list_drives | List configured OneDrive roots |
Embedding Deployments (SAP AI Core)
| Model | Dimensions | Use |
|---|---|---|
| text-embedding-3-small | 1536 | Default — faster, recommended for indexing |
| text-embedding-3-large | 3072 | Higher accuracy — swap deployment ID if needed |
Deploy these via SAP AI Core under your resource group and set the deployment ID in your config.
Embeddings are generated in batches of 20 with a 150 ms delay between batches to stay within AI Core rate limits. Large initial builds with thousands of files will take proportionally longer.
Troubleshooting
Server not responding / "Server disconnected" in Claude Desktop
Check the MCP server log:
%APPDATA%\Claude\logs\mcp-server-onedrive.logThis file captures all stderr output from the MCP server process and is the first place to look for errors.
Search returns no results or very low scores
- Semantic search scores use the formula
1 / (1 + L2_distance). Typical relevant results score between0.50–0.65. Results below0.40are considered low-confidence. - If all results score below
0.40, Claude will fall back tosearch_files(filename search). - If the index is empty or outdated, run
build-indexagain (it only re-processes changed files).
read_file says file is too large
The file is still fully indexed and searchable. Use semantic_search with a specific question about the file's content instead of trying to read it directly.
Files added after initial build are not found by semantic search
Files larger than 2 MB are not auto-indexed by the file watcher. Re-run build-index to include them:
npm run build-indexbuild-index hangs or freezes
A malformed or very large Excel file may be causing the indexer to hang. The indexer applies a 60-second timeout per file — if a file exceeds it, the build should eventually skip it and continue. Check index/index-failures.json after the build for skipped files.
"Access is denied" or LanceDB write conflict errors
The file watcher and a tool call tried to write to LanceDB at the same time. From v1.1.2 onward the watcher automatically pauses during active tool calls. If you see this on an older version, upgrade:
npm install -g @charansamanchi/mcp-onedrive@latestChangelog
v1.1.2
- Fixed LanceDB write conflict — watcher now pauses during active tool calls (
getActiveToolslock) - Fixed
mcp-onedrive build-indexsubcommand for global npm installs
v1.1.1
- Fixed
mcp-onedrive build-indexsubcommand routing insrc/index.js
v1.1.0
- Added
--httpmode for Joule Work Desktop (StreamableHTTPServerTransport, default port7722) - Updated
semantic_searchandsearch_filestool descriptions with fallback-to-online-docs guidance - Added
MCP_PORTenv var for configurable HTTP port
v1.0.0
- Initial release — stdio MCP server with semantic search, file search, read, list, and index tools
Extending the Server
The MCP server communicates over stdio (stdin/stdout). stdout is the JSON-RPC wire channel between the server and Claude Desktop. Any text written to stdout (e.g.
console.log()) will corrupt the protocol stream. Always useprocess.stderr.write()for logging.
License
MIT
