npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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.

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/mcp

The 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 answers

Document 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-onedrive

Option B — clone and run locally

git clone https://github.tools.sap/I355335/mcp-ai-onedrive.git
cd mcp-ai-onedrive
npm install

Configuration

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=5

Parameter 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 chunks

After 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-index to include them.
  • Files that fail to parse (encrypted PDFs, malformed xlsx, etc.) are logged to index/index-failures.json and skipped. Use get_index_status to see failures, or inspect the file directly.

Note on large Excel files: The xlsx parser can hang on very large or malformed .xlsx files. The indexer applies a 60-second parse timeout — files that exceed it are recorded in index-failures.json and 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/mcp

In 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.js

CLI / stdio

node src/index.js

Claude 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. The pdf-parse library emits a warning on require() that would be written to stdout, corrupting the MCP JSON-RPC stream and causing Unexpected 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 ./index would 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 .env file (for local/dev use) or the env block in claude_desktop_config.json. The config block takes precedence. VECTOR_INDEX_PATH in .env can remain as ./index for 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/mcp

Or with a custom port via environment variable:

MCP_PORT=7722 node src/index.js --http

Then 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.log

This 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 between 0.50–0.65. Results below 0.40 are considered low-confidence.
  • If all results score below 0.40, Claude will fall back to search_files (filename search).
  • If the index is empty or outdated, run build-index again (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-index

build-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@latest

Changelog

v1.1.2

  • Fixed LanceDB write conflict — watcher now pauses during active tool calls (getActiveTools lock)
  • Fixed mcp-onedrive build-index subcommand for global npm installs

v1.1.1

  • Fixed mcp-onedrive build-index subcommand routing in src/index.js

v1.1.0

  • Added --http mode for Joule Work Desktop (StreamableHTTPServerTransport, default port 7722)
  • Updated semantic_search and search_files tool descriptions with fallback-to-online-docs guidance
  • Added MCP_PORT env 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 use process.stderr.write() for logging.


License

MIT