obsidian-mcp-server
Provides read-only access to an Obsidian vault, enabling full-text note search, retrieving notes by path or title, browsing by folder, tag, or date range, listing tags, and checking vault status, with support for frontmatter, inline tags, wikilinks, and daily-note dates.
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., "@obsidian-mcp-serverSearch my vault for notes about the Morocco trip and summarize the itinerary."
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.
obsidian-mcp-server
A remote MCP server that exposes an Obsidian vault stored in a GitHub repo as callable tools, so Claude can search and read your notes on demand, including on unattended scheduled runs like the morning brief.
Your laptop does not need to be on. The server reads from GitHub, not from your machine.
Why this instead of the GitHub Integration
The GitHub Integration in Claude lets you attach repo files by hand. That is a manual click, so a scheduled task cannot use it. This is a real MCP connector: Claude gets tools it can call by itself.
It also understands Obsidian rather than treating notes as code. It parses YAML frontmatter, block-style and inline tag lists, inline #tags (ignoring # inside code fences), [[wikilinks]], and daily-note dates from filenames.
Related MCP server: obsidianMCP
Tools
Tool | Purpose |
| Full-text search, ranked. Title matches beat tag matches beat body frequency. All terms must be present. |
| Read one note by path, path without extension, or bare title. |
| Browse by folder, tag, or date range. This is the daily-notes tool. |
| Every tag with note counts, so you can discover the vocabulary before filtering. |
| Vault size, folder breakdown, snapshot freshness. |
How it reads the vault
It downloads the repo tarball in one API call and builds an in-memory index, rather than making one call per note. A vault with thousands of notes costs a single request. The snapshot is cached for CACHE_TTL_MS (default 5 minutes), and concurrent tool calls share one refresh instead of triggering several downloads.
Setup
1. Vault to GitHub
Install the Obsidian Git community plugin and point it at a private repo. Set auto-commit to something like 10 minutes. Everything downstream reads from that repo.
2. Fine-grained GitHub token
Create one at Settings → Developer settings → Personal access tokens → Fine-grained tokens.
Repository access: only the vault repo
Permissions: Contents → Read-only
Nothing else. Whatever this token can reach, the server can reach.
3. Shared secret
openssl rand -hex 32This is MCP_AUTH_TOKEN. It is the only thing between a stranger who finds your URL and your entire vault.
4. Environment
Variable | Required | Default | Notes |
| yes | — | Your GitHub username |
| yes | — | Vault repo name |
| yes | — | The fine-grained token |
| yes | — | The shared secret |
| no |
| Branch to read |
| no |
| Index only a subfolder |
| no |
| Snapshot lifetime |
| no |
| Host usually sets this |
5. Run locally
npm install
npm run build
GITHUB_OWNER=you GITHUB_REPO=vault GITHUB_TOKEN=ghp_... MCP_AUTH_TOKEN=secret npm startVerify with the MCP Inspector:
npx @modelcontextprotocol/inspectorConnect to http://localhost:3000/mcp over Streamable HTTP with header Authorization: Bearer <MCP_AUTH_TOKEN>.
There is also an end-to-end test that stubs GitHub with a synthetic vault and drives the real HTTP endpoint:
node test-e2e.mjsEndpoints
Path | Auth | Purpose |
| required | The MCP endpoint. This is the URL you give Claude. |
| none | Liveness probe. Does no index work, so a platform health check can never trigger a GitHub fetch. Reports cache warmth and note count. |
| required | Rebuilds the index if it has expired. Point your uptime pinger here. Add |
Staying warm
The index is built on startup, right after the port binds rather than before it, so deploys are not delayed by a vault download and a large vault cannot fail the platform's health check.
That handles restarts. The other half is idle shutdown. On any tier that sleeps, a once-a-day scheduled run always arrives at a cold server and pays twice: once for the container to boot, once for the index to rebuild. If the total exceeds the connector timeout, the tool call fails, and a brief section that returns nothing is dropped silently rather than showing an error.
To avoid that, point a free pinger (cron-job.org, UptimeRobot) at /warm every 10 minutes:
https://your-service.onrender.com/warm
Header: Authorization: Bearer <MCP_AUTH_TOKEN>If your pinger cannot send custom headers on its free plan, the token is also accepted as a query parameter:
https://your-service.onrender.com/warm?token=<MCP_AUTH_TOKEN>Prefer the header. URLs routinely end up in access logs; headers usually do not.
Ping /warm rather than /health, because /health keeps the container alive but leaves the index cold, which only fixes half the problem.
Raise CACHE_TTL_MS well above the 5 minute default once pinging is in place. The default is tuned for interactive use, where you want recent edits to show up quickly. For a scheduled brief, something like 6 hours (21600000) means far fewer rebuilds while still picking up the day's notes.
If your brief runs at a fixed time, schedule an extra ping 10 to 15 minutes before it, so both the container and the index are hot when it fires.
Deploy
Any host that gives you an HTTPS URL works. Anthropic connects from its own cloud, not from your machine, so the server must be reachable on the public internet. A VPN-only or firewalled host will not connect even if you can reach it yourself.
Set the four required env vars as secrets, deploy, confirm GET /health returns {"status":"ok"}.
Notes on hosting choices:
Render / Railway / Fly all work with this code unchanged. Check current free-tier terms before relying on one.
Cold starts matter here. See "Staying warm" above; on a sleeping tier this is the single thing most likely to break a scheduled run.
Add to Claude
Settings → Connectors → Add custom connector.
URL:
https://your-host.example.com/mcpUnder Advanced settings, add request header
Authorization: Bearer <MCP_AUTH_TOKEN>
If your account does not yet show a request-headers field, that capability is still rolling out. Until it does, treat the URL itself as a secret and deploy on an unguessable path.
Then enable the connector in a conversation via the + menu. A connector enabled mid-conversation generally will not appear until you start a new chat.
Using it in the morning brief
The brief accepts a Sections: list with the invocation and makes one targeted fetch per entry against whatever connected tool serves it. Once this connector is live, a section like:
Sections: Open TODOs from my daily notes this weekwill route to obsidian_list_notes with folder="Daily" and a since date. A section that finds nothing is dropped from the page rather than rendering an empty block.
Security
The GitHub token is read-only and scoped to one repo, so a compromise cannot write to your vault.
The bearer check is constant-time, so it does not leak the token's length or prefix through timing.
Every tool is read-only and annotated as such.
There are no write tools. Claude cannot modify your notes through this server.
Troubleshooting
Symptom | Cause |
Connector adds but shows no tools | Transport mismatch. This server speaks Streamable HTTP at |
401 on every call | Header missing or malformed. It must be |
"Repository or ref not found" | Wrong owner/repo/ref, or the token cannot see a private repo. |
"GitHub denied access" | Rate limit, or the token is missing Contents:Read. |
Notes missing from results | Check |
Stale results after syncing | Snapshot cache. Call |
First call each morning fails | Host cold start. Ping |
| Token missing. Use the |
| Index not built yet. Normal for a few seconds after a deploy; persistent means the startup warm failed, so check the logs for the reason. |
This server cannot be deployed
Maintenance
Related MCP Connectors
Connect AI assistants to your GitHub-hosted Obsidian vault to seamlessly access, search, and analy…
Turn a GitHub repo or docs site into agent-ready context: pack it or search it, over MCP.
Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.
Your org's AI agents, tasks, runs, search, and brain files as MCP tools and resources.
Related MCP Servers
- AlicenseAqualityBmaintenanceTurn any code repository into a searchable Obsidian vault — then let Claude Code navigate it as a set of MCP tools.101MIT
- AlicenseNot gradedqualityDmaintenanceProvides Claude with read, search, and write access to an Obsidian vault through MCP tools.10,776 npmApache 2.0
- -licenseNot gradedqualityNot gradedmaintenanceEnables reading and writing an Obsidian vault stored on GitHub, allowing Claude to list, search, read, and write notes with commits via the GitHub Contents API.-
- AlicenseNot gradedqualityAmaintenanceEnables Claude to read, search, and analyze your entire knowledge vault locally via MCP tools like search, drafting, and linting.57 npm4MIT