A high-performance MCP (Model Context Protocol) server for Obsidian vaults with a single meta-tool pattern, direct filesystem access, graph operations, canvas support, task management, Notion sync, and AI conversation analysis.
- Meta-tool pattern -- Single
obsidiantool with 60+ actions (~2-3k tokens vs ~15-20k for individual tools) - Direct filesystem access -- No Obsidian app required, reads vault files directly
- REST API backend -- Optional connection via Obsidian Local REST API plugin
- Dual transport -- stdio (MCP standard) or HTTP (MetaMcp compatible)
- Multi-vault support -- Serve multiple vaults simultaneously
- Graph operations -- Links, backlinks, neighbors, shortest path, orphans, connected components
- Notion export -- Convert notes to Notion-compatible markdown with property type mapping
- Bases support -- Read/create/query Obsidian Bases (
.baseYAML files) - Conversation analysis -- Detect and analyze AI conversation exports (fetch-gpt-chat format)
- Content operations -- Search-replace, insert at line/heading, heading management
- Canvas support -- Read/create/modify
.canvasJSON files (nodes and edges) - Periodic notes -- Daily/weekly/monthly note creation and navigation
- Task management -- Extract, filter, update, and track tasks across vault
- Advanced search -- Fuzzy matching, property filters, combined multi-criteria search
- Notion sync -- Sync planning with property type mapping and state tracking
- File listing cache -- 30s TTL cache for vault scans, parallel directory traversal
# Install dependencies
npm install
# Build
npm run build
# Run with stdio transport (standard MCP)
node dist/index.js --vault "/path/to/vault"
# Run with HTTP transport (MetaMcp)
node dist/index.js --vault "/path/to/vault" --transport http --port 8750Add to your .mcp.json:
{
"mcpServers": {
"obsidian": {
"type": "stdio",
"command": "node",
"args": ["dist/index.js", "--vault", "C:/path/to/your/vault"]
}
}
}For HTTP transport (MetaMcp):
{
"mcpServers": {
"obsidian": {
"type": "http",
"url": "http://127.0.0.1:8750/mcp"
}
}
}| Option | Default | Description |
|---|---|---|
--vault <paths...> |
(required) | Vault path(s). Format: "path" or "name:path" |
--backend <type> |
filesystem |
filesystem or rest-api |
--transport <type> |
stdio |
stdio or http |
--port <number> |
8750 |
HTTP port (when transport=http) |
--host <address> |
127.0.0.1 |
HTTP host |
--no-meta |
false |
Expose individual tools instead of meta-tool |
--log-level <level> |
info |
debug, info, warn, error |
Multiple vaults:
node dist/index.js --vault "personal:C:/Vaults/Personal" --vault "work:C:/Vaults/Work"All actions are called through the single obsidian tool:
{ "action": "read", "path": "my-note" }| Action | Description | Parameters |
|---|---|---|
list_files |
List files in vault/directory | path? (directory) |
list_dirs |
List subdirectories | path? (directory) |
vault_info |
Vault name, path, note/file count | |
vault_stats |
Notes, attachments, sizes, extension counts |
| Action | Description | Parameters |
|---|---|---|
read |
Read note content, frontmatter, links, tags | path |
create |
Create note with optional frontmatter | path, content, options.frontmatter?, options.folder? |
edit |
Modify note | path, content, options.operation (append/prepend/replace), options.target? |
delete |
Delete note | path |
move / rename |
Move or rename note | path, options.newPath |
| Action | Description | Parameters |
|---|---|---|
search / find |
Full-text search | query, options.caseSensitive?, options.maxResults?, options.regex?, options.path? |
search_files |
Find by filename | query |
search_tags |
Find notes by tags | options.tags, options.maxResults?, options.path? |
| Action | Description | Parameters |
|---|---|---|
get_property |
Get a frontmatter value | path, options.key |
set_property |
Set a frontmatter value | path, options.key, options.value |
delete_property |
Remove a property | path, options.key |
get_properties |
Get all frontmatter | path |
bulk_properties |
Update many notes at once | options.files, options.properties |
| Action | Description | Parameters |
|---|---|---|
add_tags |
Add tags to a note | path, options.tags |
remove_tags |
Remove tags | path, options.tags |
rename_tag |
Rename tag across vault | options.oldTag, options.newTag |
list_tags |
List all tags with counts |
| Action | Description | Parameters |
|---|---|---|
links |
Outgoing links from a note | path |
backlinks |
Incoming links to a note | path |
neighbors |
N-hop connections | path, options.depth?, options.direction?, options.maxNodes? |
path / find_path |
Shortest path between notes | path (from), options.to, options.maxDepth? |
orphans |
Notes with no links | |
graph_stats |
Vault graph statistics |
| Action | Description | Parameters |
|---|---|---|
export / export_notion |
Export to Notion-compatible format | path, options.format?, options.convertWikilinks?, options.convertCallouts? |
property_mapping |
Show Obsidian-to-Notion type mapping | path |
| Action | Description | Parameters |
|---|---|---|
list_bases |
List all .base files |
|
read_base |
Parse a .base file |
path |
create_base |
Create a new base | path, options.filters?, options.columns? |
query_base |
Execute a base query | path, options.viewIndex? |
update_base |
Update base config | path, options.filters?, options.views? |
Compatible with fetch-gpt-chat unified format.
| Action | Description | Parameters |
|---|---|---|
search_conversations |
Search AI conversations | options.source?, options.query?, options.dateFrom?, options.dateTo? |
analyze_conversation |
Analyze a conversation note | path |
conversation_stats |
Stats by source and month | |
create_conversations_base |
Create a base for indexing conversations | path, options.source?, options.folder? |
| Action | Description | Parameters |
|---|---|---|
search_replace |
Find and replace text in a note | path, options.search, options.replace, options.regex?, options.caseSensitive?, options.maxReplacements? |
insert_at |
Insert content at line or heading | path, content, options.line?, options.heading?, options.position? (before/after/end) |
list_headings |
List all headings with levels | path, options.minLevel?, options.maxLevel? |
get_section |
Get content under a heading | path, options.heading, options.includeHeading? |
rename_heading |
Rename a heading | path, options.oldHeading, options.newHeading |
| Action | Description | Parameters |
|---|---|---|
list_canvases |
List all .canvas files |
|
read_canvas |
Read a canvas (nodes + edges) | path |
create_canvas |
Create a canvas | path, options.nodes?, options.edges? |
add_canvas_node |
Add a node | path, options.type (text/file/link/group), options.text?, options.file?, options.url? |
add_canvas_edge |
Add an edge | path, options.fromNode, options.toNode, options.label? |
remove_canvas_node |
Remove node + connected edges | path, options.nodeId |
remove_canvas_edge |
Remove an edge | path, options.edgeId |
| Action | Description | Parameters |
|---|---|---|
daily_note / weekly_note / monthly_note |
Get or create periodic note | options.period, options.date?, options.folder?, options.template?, options.createIfMissing? |
navigate_periodic |
Go to previous/next note | options.period, options.date?, options.direction (previous/next) |
list_periodic |
List periodic notes | options.period, options.folder?, options.limit?, options.from?, options.to? |
| Action | Description | Parameters |
|---|---|---|
list_tasks |
List tasks across vault | options.path?, options.status? (todo/done/cancelled/in-progress/all), options.tag?, options.maxResults? |
update_task |
Toggle/update task status | path, options.line, options.status |
task_stats |
Task statistics | options.path? |
| Action | Description | Parameters |
|---|---|---|
search_fuzzy |
Fuzzy filename matching | query, options.maxResults?, options.threshold? |
search_advanced |
Combined multi-criteria search | options.query?, options.tags?, options.properties?, options.dateFrom?, options.dateTo?, options.sortBy?, options.sortOrder? |
search_property |
Search by frontmatter property | options.key, options.value?, options.operator? (eq/ne/gt/lt/contains/exists) |
| Action | Description | Parameters |
|---|---|---|
sync_plan |
Generate sync plan (JSON operations) | options.path?, options.databaseId?, options.filter? |
sync_update_state |
Update sync state after sync | options.entries |
sync_status |
Get sync status overview | options.syncStatePath? |
src/
index.ts CLI entry point (Commander)
server.ts MCP Server (stdio + HTTP transport)
meta-tool.ts ACTION_MAP routing meta-tool calls
types.ts Shared types
backends/
types.ts IVaultBackend interface
filesystem-backend.ts Direct filesystem (primary)
rest-api-backend.ts Obsidian REST API plugin
backend-factory.ts Backend creation factory
vault/
vault-manager.ts Multi-vault orchestrator
markdown/
frontmatter.ts YAML frontmatter parser
link-resolver.ts Wikilinks, embeds, tags, conversations
dual-format.ts Obsidian/Notion dual format converter
properties/
type-mapper.ts Obsidian-to-Notion property type mapping
graph/
graph-builder.ts Vault-wide link graph builder (cached)
graph-query.ts Graph algorithms (BFS, path finding)
bases/
bases-parser.ts .base YAML parser
bases-query.ts Query engine with expression evaluator
tools/
index.ts ToolRegistry (all handlers)
vault-tools.ts Vault operations
note-tools.ts Note CRUD
search-tools.ts Content/filename/tag/fuzzy/advanced search
property-tools.ts Frontmatter operations
tag-tools.ts Tag management
graph-tools.ts Graph operations
export-tools.ts Notion export
bases-tools.ts Bases operations
conversation-tools.ts Conversation analysis
content-tools.ts Search-replace, headings, sections
canvas-tools.ts .canvas file operations
periodic-tools.ts Daily/weekly/monthly notes
task-tools.ts Task extraction and management
sync-tools.ts Notion sync planning
utils/
path.ts Path normalization
security.ts Vault path traversal protection
responses.ts MCP response formatting
errors.ts MCP error helpers
logger.ts Stderr logger
# Run all tests
npm test
# Run with watch mode
npx vitest
# Run specific test file
npx vitest run tests/frontmatter.test.ts138 tests across 9 test suites:
frontmatter.test.ts-- YAML parsing, stringify, property operationslink-resolver.test.ts-- Wikilinks, embeds, tags, inline fields, conversationspath-utils.test.ts-- Path normalization, extension handlingmeta-tool.test.ts-- Tool definition, action routing, completeness (all 60+ actions)filesystem-backend.test.ts-- Integration tests with temp vault (CRUD, search, cache)content-tools.test.ts-- Search-replace, headings, sections, insertcanvas-tools.test.ts-- Canvas CRUD, nodes, edgestask-tools.test.ts-- Task extraction, status toggle, statisticssearch-advanced.test.ts-- Fuzzy search, property search, combined filters
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"obsidian","arguments":{"action":"vault_info"}}}' | node dist/index.js --vault "/path/to/vault"- File listing cache: 30-second TTL cache for full vault scans; invalidated on write operations
- Parallel directory traversal:
walkDirectorystats files in parallel batches - Graph caching: Graph is built once and cached until invalidated
- Search limits:
maxResults(default 50) prevents unbounded scans - Directory scoping: All search operations accept
path/directoryto scope to a subfolder
MIT