@mauricio.wolff/mcp-obsidian 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,666 @@
1
+ # MCP-Obsidian
2
+
3
+ A lightweight Model Context Protocol (MCP) server for safe Obsidian vault access. This server provides AI assistants with the ability to read and write notes in an Obsidian vault while preventing YAML frontmatter corruption.
4
+
5
+ **Supported AI Platforms:** Claude Desktop, Claude Code, ChatGPT Desktop (Enterprise+), IntelliJ IDEA 2025.1+, Cursor IDE, and other MCP-compatible clients.
6
+
7
+ ## Quick Start (5 minutes)
8
+
9
+ 1. **Install Bun runtime:**
10
+ ```bash
11
+ curl -fsSL https://bun.sh/install | bash
12
+ ```
13
+
14
+ 2. **Test the server:**
15
+ ```bash
16
+ bunx @bitbonsai/mcp-obsidian /path/to/your/obsidian/vault
17
+ ```
18
+
19
+ 3. **Configure your AI client:**
20
+ - **Claude Desktop**: Add to `claude_desktop_config.json`
21
+ - **Claude Code**: Add to `~/.claude.json`
22
+ - **Others**: See [platform-specific guides](#ai-client-configuration) below
23
+
24
+ 4. **Test with your AI:**
25
+ - "List files in my Obsidian vault"
26
+ - "Read my note called 'project-ideas.md'"
27
+ - "Create a new note with today's date"
28
+
29
+ **Success indicators:** Your AI should be able to list files and read notes from your vault.
30
+
31
+ ## Features
32
+
33
+ - ✅ Safe frontmatter parsing and validation using gray-matter
34
+ - ✅ Path filtering to exclude `.obsidian` directory and other system files
35
+ - ✅ **Complete MCP toolkit**: 11 methods covering all vault operations
36
+ - File operations: `read_note`, `write_note`, `delete_note`, `move_note`
37
+ - Directory operations: `list_directory`
38
+ - Batch operations: `read_multiple_notes`
39
+ - Search: `search_notes` with content and frontmatter support
40
+ - Metadata: `get_frontmatter`, `update_frontmatter`, `get_notes_info`
41
+ - Tag management: `manage_tags` (add, remove, list)
42
+ - ✅ **NEW:** Write modes: `overwrite`, `append`, `prepend` for flexible content editing
43
+ - ✅ **NEW:** Tag management: add, remove, and list tags in notes
44
+ - ✅ Safe deletion with confirmation requirement to prevent accidents
45
+ - ✅ Automatic path trimming to handle whitespace in inputs
46
+ - ✅ TypeScript support with Bun runtime (no compilation needed)
47
+ - ✅ Comprehensive error handling and validation
48
+
49
+ ## Prerequisites
50
+
51
+ - [Bun](https://bun.sh) runtime (v1.0.0 or later)
52
+ - An Obsidian vault (local directory with `.md` files)
53
+ - MCP-compatible AI client (Claude Desktop, ChatGPT Desktop, Claude Code, etc.)
54
+
55
+ ## Installation
56
+
57
+ ### For End Users (Recommended)
58
+
59
+ No installation needed! Use `bunx` to run directly:
60
+
61
+ ```bash
62
+ bunx @bitbonsai/mcp-obsidian /path/to/your/obsidian/vault
63
+ ```
64
+
65
+ ### For Developers
66
+
67
+ 1. Clone this repository
68
+ 2. Install dependencies with Bun:
69
+ ```bash
70
+ bun install
71
+ ```
72
+
73
+ ## Usage
74
+
75
+ ### Running the Server
76
+
77
+ **End users:**
78
+ ```bash
79
+ bunx @bitbonsai/mcp-obsidian /path/to/your/obsidian/vault
80
+ ```
81
+
82
+ **Developers:**
83
+ ```bash
84
+ bun server.ts /path/to/your/obsidian/vault
85
+ ```
86
+
87
+ ### AI Client Configuration
88
+
89
+ #### Claude Desktop
90
+
91
+ Add to your Claude Desktop configuration file:
92
+
93
+ **Single Vault:**
94
+ ```json
95
+ {
96
+ "mcpServers": {
97
+ "obsidian": {
98
+ "command": "bunx",
99
+ "args": ["@bitbonsai/mcp-obsidian", "/Users/yourname/Documents/MyVault"]
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ **Multiple Vaults:**
106
+ ```json
107
+ {
108
+ "mcpServers": {
109
+ "obsidian-personal": {
110
+ "command": "bunx",
111
+ "args": ["@bitbonsai/mcp-obsidian", "/Users/yourname/Documents/PersonalVault"]
112
+ },
113
+ "obsidian-work": {
114
+ "command": "bunx",
115
+ "args": ["@bitbonsai/mcp-obsidian", "/Users/yourname/Documents/WorkVault"]
116
+ }
117
+ }
118
+ }
119
+ ```
120
+
121
+ **Configuration File Locations:**
122
+ - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
123
+ - **Windows:** `C:\Users\{username}\AppData\Roaming\Claude\claude_desktop_config.json`
124
+ - **Linux:** `~/.config/Claude/claude_desktop_config.json`
125
+
126
+ *You can also access this through Claude Desktop → Settings → Developer → Edit Config*
127
+
128
+ #### ChatGPT Desktop
129
+
130
+ **Requirements:** ChatGPT Enterprise, Education, or Team subscription (not available for individual Plus users)
131
+
132
+ ChatGPT uses MCP through Deep Research and developer mode. Configuration is done through the ChatGPT interface:
133
+
134
+ 1. Access ChatGPT developer mode (beta feature)
135
+ 2. Configure MCP servers through the built-in MCP client
136
+ 3. Create custom connectors for your organization
137
+
138
+ *Note: ChatGPT Desktop's MCP integration is currently limited to enterprise subscriptions and uses a different setup process than file-based configuration.*
139
+
140
+ #### Claude Code
141
+
142
+ Claude Code uses `.claude.json` configuration file:
143
+
144
+ **User-scoped (recommended):**
145
+ Edit `~/.claude.json`:
146
+ ```json
147
+ {
148
+ "mcpServers": {
149
+ "obsidian": {
150
+ "command": "bunx",
151
+ "args": ["@bitbonsai/mcp-obsidian", "/path/to/your/vault"],
152
+ "env": {}
153
+ }
154
+ }
155
+ }
156
+ ```
157
+
158
+ **Project-scoped:**
159
+ Edit `.claude.json` in your project or add to the projects section:
160
+ ```json
161
+ {
162
+ "projects": {
163
+ "/path/to/your/project": {
164
+ "mcpServers": {
165
+ "obsidian": {
166
+ "command": "bunx",
167
+ "args": ["@bitbonsai/mcp-obsidian", "/path/to/your/vault"]
168
+ }
169
+ }
170
+ }
171
+ }
172
+ }
173
+ ```
174
+
175
+ **Using Claude Code CLI:**
176
+ ```bash
177
+ claude mcp add obsidian --scope user bunx @bitbonsai/mcp-obsidian /path/to/your/vault
178
+ ```
179
+
180
+ #### Other MCP-Compatible Clients (2025)
181
+
182
+ **Confirmed MCP Support:**
183
+ - **IntelliJ IDEA 2025.1+** - Native MCP client support
184
+ - **Cursor IDE** - Built-in MCP compatibility
185
+ - **Zed, Replit, Codeium, Sourcegraph** - In development
186
+ - **Microsoft Copilot Studio** - Native MCP support with one-click server connections
187
+
188
+ Most modern MCP clients use similar JSON configuration patterns. Refer to your specific client's documentation for exact setup instructions.
189
+
190
+ ### Examples
191
+
192
+ #### Ask your AI assistant about your notes:
193
+ - "What files are in my Obsidian vault?"
194
+ - "Read my note called 'project-ideas.md'"
195
+ - "Show me all notes with 'AI' in the title"
196
+
197
+ #### Have your AI assistant help with note management:
198
+ - "Create a new note called 'meeting-notes.md' with today's date in the frontmatter"
199
+ - "Append today's journal entry to my daily note"
200
+ - "Prepend an urgent task to my todo list"
201
+ - "Add the tags 'project' and 'urgent' to my task note"
202
+ - "List all tags in my research note"
203
+ - "Remove the 'draft' tag from my completed article"
204
+ - "List all markdown files in my 'Projects' folder"
205
+ - "Delete the old draft note 'draft-ideas.md' (with confirmation)"
206
+
207
+ ## Troubleshooting
208
+
209
+ ### Common Issues
210
+
211
+ #### "command not found: bunx"
212
+ - **Solution:** Install Bun runtime from [bun.sh](https://bun.sh)
213
+ - **Alternative:** Use npm: `npx @bitbonsai/mcp-obsidian /path/to/vault`
214
+
215
+ #### "Usage: bun server.ts /path/to/vault"
216
+ - **Cause:** No vault path provided
217
+ - **Solution:** Specify the full path to your Obsidian vault directory
218
+
219
+ #### "Permission denied" errors
220
+ - **Cause:** Insufficient file system permissions
221
+ - **Solution:** Ensure the vault directory is readable/writable by your user
222
+
223
+ #### "Path traversal not allowed"
224
+ - **Cause:** Trying to access files outside the vault
225
+ - **Solution:** All file paths must be relative to the vault root
226
+
227
+ #### AI client not recognizing the server
228
+ 1. Check the configuration file path is correct for your OS
229
+ 2. Ensure JSON syntax is valid (use a JSON validator)
230
+ 3. Restart your AI client after configuration changes
231
+ 4. Check your AI client's logs for error messages
232
+ 5. Verify your AI client supports MCP (Model Context Protocol)
233
+
234
+ #### ".obsidian files still showing up"
235
+ - **Expected:** The path filter automatically excludes `.obsidian/**` patterns
236
+ - **If still seeing them:** The filter is working as designed for security
237
+
238
+ ### Debug Mode
239
+
240
+ Run with error logging:
241
+ ```bash
242
+ bunx @bitbonsai/mcp-obsidian /path/to/vault 2>debug.log
243
+ ```
244
+
245
+ ### Getting Help
246
+
247
+ - [Open an issue](https://github.com/bitbonsai/mcp-obsidian/issues) on GitHub
248
+ - Include your OS, Bun version, and error messages
249
+ - Provide the vault directory structure (without sensitive content)
250
+
251
+ ## Testing
252
+
253
+ Run the test suite:
254
+ ```bash
255
+ bun test
256
+ ```
257
+
258
+ ## API Methods
259
+
260
+ ### `read_note`
261
+ Read a note from the vault with parsed frontmatter.
262
+
263
+ **Request:**
264
+ ```json
265
+ {
266
+ "name": "read_note",
267
+ "arguments": {
268
+ "path": "project-ideas.md"
269
+ }
270
+ }
271
+ ```
272
+
273
+ **Response:**
274
+ ```json
275
+ {
276
+ "path": "project-ideas.md",
277
+ "frontmatter": {
278
+ "title": "Project Ideas",
279
+ "tags": ["projects", "brainstorming"],
280
+ "created": "2023-01-15T10:30:00.000Z"
281
+ },
282
+ "content": "# Project Ideas\n\n## AI Tools\n- MCP server for Obsidian\n- Voice note transcription\n\n## Web Apps\n- Task management system"
283
+ }
284
+ ```
285
+
286
+ ### `write_note`
287
+ Write a note to the vault with optional frontmatter and write mode.
288
+
289
+ **Write Modes:**
290
+ - `overwrite` (default): Replace entire file content
291
+ - `append`: Add content to the end of existing file
292
+ - `prepend`: Add content to the beginning of existing file
293
+
294
+ **Request (Overwrite):**
295
+ ```json
296
+ {
297
+ "name": "write_note",
298
+ "arguments": {
299
+ "path": "meeting-notes.md",
300
+ "content": "# Team Meeting\n\n## Agenda\n- Project updates\n- Next milestones",
301
+ "frontmatter": {
302
+ "title": "Team Meeting Notes",
303
+ "date": "2023-12-01",
304
+ "tags": ["meetings", "team"]
305
+ },
306
+ "mode": "overwrite"
307
+ }
308
+ }
309
+ ```
310
+
311
+ **Request (Append):**
312
+ ```json
313
+ {
314
+ "name": "write_note",
315
+ "arguments": {
316
+ "path": "daily-log.md",
317
+ "content": "\n\n## 3:00 PM Update\n- Completed project review\n- Started new feature",
318
+ "mode": "append"
319
+ }
320
+ }
321
+ ```
322
+
323
+ **Response:**
324
+ ```json
325
+ {
326
+ "message": "Successfully wrote note: meeting-notes.md (mode: overwrite)"
327
+ }
328
+ ```
329
+
330
+ ### `list_directory`
331
+ List files and directories in the vault.
332
+
333
+ **Request:**
334
+ ```json
335
+ {
336
+ "name": "list_directory",
337
+ "arguments": {
338
+ "path": "Projects"
339
+ }
340
+ }
341
+ ```
342
+
343
+ **Response:**
344
+ ```json
345
+ {
346
+ "path": "Projects",
347
+ "directories": [
348
+ "AI-Tools",
349
+ "Web-Development"
350
+ ],
351
+ "files": [
352
+ "project-template.md",
353
+ "roadmap.md"
354
+ ]
355
+ }
356
+ ```
357
+
358
+ ### `delete_note`
359
+ Delete a note from the vault (requires confirmation for safety).
360
+
361
+ **Request:**
362
+ ```json
363
+ {
364
+ "name": "delete_note",
365
+ "arguments": {
366
+ "path": "old-draft.md",
367
+ "confirmPath": "old-draft.md"
368
+ }
369
+ }
370
+ ```
371
+
372
+ **Response (Success):**
373
+ ```json
374
+ {
375
+ "success": true,
376
+ "path": "old-draft.md",
377
+ "message": "Successfully deleted note: old-draft.md. This action cannot be undone."
378
+ }
379
+ ```
380
+
381
+ **Response (Confirmation Failed):**
382
+ ```json
383
+ {
384
+ "success": false,
385
+ "path": "old-draft.md",
386
+ "message": "Deletion cancelled: confirmation path does not match. For safety, both 'path' and 'confirmPath' must be identical."
387
+ }
388
+ ```
389
+
390
+ **⚠️ Safety Note:** The `confirmPath` parameter must exactly match the `path` parameter to proceed with deletion. This prevents accidental deletions.
391
+
392
+ ### `get_frontmatter`
393
+ Extract only the frontmatter from a note without reading the full content.
394
+
395
+ **Request:**
396
+ ```json
397
+ {
398
+ "name": "get_frontmatter",
399
+ "arguments": {
400
+ "path": "project-ideas.md"
401
+ }
402
+ }
403
+ ```
404
+
405
+ **Response:**
406
+ ```json
407
+ {
408
+ "path": "project-ideas.md",
409
+ "frontmatter": {
410
+ "title": "Project Ideas",
411
+ "tags": ["projects", "brainstorming"],
412
+ "created": "2023-01-15T10:30:00.000Z"
413
+ }
414
+ }
415
+ ```
416
+
417
+ ### `manage_tags`
418
+ Add, remove, or list tags in a note. Tags are managed in the frontmatter and inline tags are detected.
419
+
420
+ **Request (List Tags):**
421
+ ```json
422
+ {
423
+ "name": "manage_tags",
424
+ "arguments": {
425
+ "path": "research-notes.md",
426
+ "operation": "list"
427
+ }
428
+ }
429
+ ```
430
+
431
+ **Request (Add Tags):**
432
+ ```json
433
+ {
434
+ "name": "manage_tags",
435
+ "arguments": {
436
+ "path": "research-notes.md",
437
+ "operation": "add",
438
+ "tags": ["machine-learning", "ai", "important"]
439
+ }
440
+ }
441
+ ```
442
+
443
+ **Request (Remove Tags):**
444
+ ```json
445
+ {
446
+ "name": "manage_tags",
447
+ "arguments": {
448
+ "path": "research-notes.md",
449
+ "operation": "remove",
450
+ "tags": ["draft", "temporary"]
451
+ }
452
+ }
453
+ ```
454
+
455
+ **Response:**
456
+ ```json
457
+ {
458
+ "path": "research-notes.md",
459
+ "operation": "add",
460
+ "tags": ["research", "ai", "machine-learning", "important"],
461
+ "success": true,
462
+ "message": "Successfully added tags"
463
+ }
464
+ ```
465
+
466
+ ### `search_notes`
467
+ Search for notes in the vault by content or frontmatter.
468
+
469
+ **Request:**
470
+ ```json
471
+ {
472
+ "name": "search_notes",
473
+ "arguments": {
474
+ "query": "machine learning",
475
+ "limit": 5,
476
+ "searchContent": true,
477
+ "searchFrontmatter": false,
478
+ "caseSensitive": false
479
+ }
480
+ }
481
+ ```
482
+
483
+ **Response:**
484
+ ```json
485
+ {
486
+ "query": "machine learning",
487
+ "resultCount": 3,
488
+ "results": [
489
+ {
490
+ "path": "ai-research.md",
491
+ "title": "AI Research Notes",
492
+ "excerpt": "...machine learning algorithms are...",
493
+ "matchCount": 2,
494
+ "lineNumber": 15
495
+ }
496
+ ]
497
+ }
498
+ ```
499
+
500
+ ### `move_note`
501
+ Move or rename a note in the vault.
502
+
503
+ **Request:**
504
+ ```json
505
+ {
506
+ "name": "move_note",
507
+ "arguments": {
508
+ "oldPath": "drafts/article.md",
509
+ "newPath": "published/article.md",
510
+ "overwrite": false
511
+ }
512
+ }
513
+ ```
514
+
515
+ **Response:**
516
+ ```json
517
+ {
518
+ "success": true,
519
+ "oldPath": "drafts/article.md",
520
+ "newPath": "published/article.md",
521
+ "message": "Successfully moved note from drafts/article.md to published/article.md"
522
+ }
523
+ ```
524
+
525
+ ### `read_multiple_notes`
526
+ Read multiple notes in a batch (maximum 10 files).
527
+
528
+ **Request:**
529
+ ```json
530
+ {
531
+ "name": "read_multiple_notes",
532
+ "arguments": {
533
+ "paths": ["note1.md", "note2.md", "note3.md"],
534
+ "includeContent": true,
535
+ "includeFrontmatter": true
536
+ }
537
+ }
538
+ ```
539
+
540
+ **Response:**
541
+ ```json
542
+ {
543
+ "successful": [
544
+ {
545
+ "path": "note1.md",
546
+ "frontmatter": {"title": "Note 1"},
547
+ "content": "# Note 1\n\nContent here..."
548
+ }
549
+ ],
550
+ "failed": [
551
+ {
552
+ "path": "note2.md",
553
+ "error": "File not found"
554
+ }
555
+ ],
556
+ "summary": {
557
+ "successCount": 1,
558
+ "failureCount": 1
559
+ }
560
+ }
561
+ ```
562
+
563
+ ### `update_frontmatter`
564
+ Update frontmatter of a note without changing content.
565
+
566
+ **Request:**
567
+ ```json
568
+ {
569
+ "name": "update_frontmatter",
570
+ "arguments": {
571
+ "path": "research-note.md",
572
+ "frontmatter": {
573
+ "status": "completed",
574
+ "updated": "2025-09-23"
575
+ },
576
+ "merge": true
577
+ }
578
+ }
579
+ ```
580
+
581
+ **Response:**
582
+ ```json
583
+ {
584
+ "message": "Successfully updated frontmatter for: research-note.md"
585
+ }
586
+ ```
587
+
588
+ ### `get_notes_info`
589
+ Get metadata for notes without reading full content.
590
+
591
+ **Request:**
592
+ ```json
593
+ {
594
+ "name": "get_notes_info",
595
+ "arguments": {
596
+ "paths": ["note1.md", "note2.md"]
597
+ }
598
+ }
599
+ ```
600
+
601
+ **Response:**
602
+ ```json
603
+ {
604
+ "notes": [
605
+ {
606
+ "path": "note1.md",
607
+ "size": 1024,
608
+ "modified": 1695456000000,
609
+ "hasFrontmatter": true
610
+ }
611
+ ],
612
+ "count": 1
613
+ }
614
+ ```
615
+
616
+ ## Security Considerations
617
+
618
+ This MCP server implements several security measures to protect your Obsidian vault:
619
+
620
+ ### Path Security
621
+ - **Path Traversal Protection:** All file paths are validated to prevent access outside the vault
622
+ - **Relative Path Enforcement:** Paths are normalized and restricted to the vault directory
623
+ - **Symbolic Link Safety:** Resolved paths are checked against vault boundaries
624
+
625
+ ### File Filtering
626
+ - **Automatic Exclusions:** `.obsidian`, `.git`, `node_modules`, and system files are filtered
627
+ - **Extension Whitelist:** Only `.md`, `.markdown`, and `.txt` files are accessible by default
628
+ - **Hidden File Protection:** Dot files and system directories are automatically excluded
629
+
630
+ ### Content Validation
631
+ - **YAML Frontmatter Validation:** Frontmatter is parsed and validated before writing
632
+ - **Function/Symbol Prevention:** Dangerous JavaScript objects are blocked from frontmatter
633
+ - **Data Type Checking:** Only safe data types (strings, numbers, arrays, objects) allowed
634
+
635
+ ### Best Practices
636
+ - **Least Privilege:** Server only accesses the specified vault directory
637
+ - **Read-Only by Default:** Consider running with read-only permissions for sensitive vaults
638
+ - **Backup Recommended:** Always backup your vault before using write operations
639
+ - **Network Isolation:** Server uses stdio transport (no network exposure)
640
+
641
+ ### What's NOT Protected
642
+ - **File Content:** The server can read/write any allowed file content
643
+ - **Vault Structure:** Directory structure is visible to AI assistants
644
+ - **File Metadata:** Creation times, file sizes, etc. are accessible
645
+
646
+ **⚠️ Important:** Only grant vault access to trusted AI conversations. The server provides full read/write access to your notes within the security boundaries above.
647
+
648
+ ## Architecture
649
+
650
+ - `server.ts` - MCP server entry point
651
+ - `src/frontmatter.ts` - YAML frontmatter handling with gray-matter
652
+ - `src/filesystem.ts` - Safe file operations with path validation
653
+ - `src/pathfilter.ts` - Directory and file filtering
654
+ - `src/types.ts` - TypeScript type definitions
655
+
656
+ ## Contributing
657
+
658
+ 1. Fork the repository
659
+ 2. Create a feature branch: `git checkout -b feature-name`
660
+ 3. Make your changes and add tests
661
+ 4. Ensure all tests pass: `bun test`
662
+ 5. Submit a pull request
663
+
664
+ ## License
665
+
666
+ MIT
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@mauricio.wolff/mcp-obsidian",
3
+ "version": "0.3.0",
4
+ "description": "Lightweight MCP server for safe Obsidian vault access",
5
+ "author": "bitbonsai",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "server.ts",
9
+ "bin": {
10
+ "mcp-obsidian": "./server.ts"
11
+ },
12
+ "files": [
13
+ "server.ts",
14
+ "src/**/*",
15
+ "README.md",
16
+ "LICENSE"
17
+ ],
18
+ "scripts": {
19
+ "start": "bun run server.ts",
20
+ "test": "bun test",
21
+ "test:watch": "bun test --watch",
22
+ "prepublishOnly": "bun test",
23
+ "prepack": "bun install",
24
+ "publish:dry": "npm publish --dry-run",
25
+ "publish:beta": "npm publish --tag beta",
26
+ "publish:latest": "npm publish"
27
+ },
28
+ "dependencies": {
29
+ "@modelcontextprotocol/sdk": "^1.0.0",
30
+ "gray-matter": "^4.0.3"
31
+ },
32
+ "devDependencies": {
33
+ "@types/bun": "latest"
34
+ },
35
+ "engines": {
36
+ "bun": ">=1.0.0"
37
+ },
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/bitbonsai/mcp-obsidian.git"
41
+ },
42
+ "keywords": [
43
+ "mcp",
44
+ "obsidian",
45
+ "model-context-protocol",
46
+ "claude",
47
+ "ai",
48
+ "bun",
49
+ "filesystem",
50
+ "frontmatter",
51
+ "yaml"
52
+ ],
53
+ "publishConfig": {
54
+ "access": "public"
55
+ }
56
+ }