Commit Graph

8 Commits

Author SHA1 Message Date
6ee26f1ad8 fix: return binary files as MCP embedded resource instead of BASE64 prefix fixes #9
The previous implementation prefixed base64 with "BASE64:" in a text
response. This updates the response to use the proper MCP embedded
resource format:

  { type: "resource", resource: { uri, mimeType, blob } }

Changes:
- types.ts: extend ToolOutput content union to allow resource items
- file-operations.ts:
  - getMimeType() maps common extensions to MIME types, falling back
    to application/octet-stream
  - MIME_TYPES table covers PDF, ZIP, images, Office formats, audio/video
  - Binary files are now returned as an EmbeddedResource with:
      uri:      obsidian://<vault>/<path>
      mimeType: detected from file extension
      blob:     base64-encoded raw bytes from the Buffer
  - Tool descriptions updated to document the resource response shape

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-30 18:52:57 -05:00
ef02d14f18 fix: return binary vault files as base64 in obsidian_read_note fixes #9
Previously, binary files (ZIP, images, compiled files) were read via
data.toString() which corrupted the bytes through UTF-8 decoding,
making the content unrecoverable on the client side.

Changes:
- executor.ts: add executeCommandBinary / executeObsidianCommandBinary
  that collect stdout chunks as raw Buffers instead of strings
- types.ts: add optional stdoutBuffer field to CLIResult
- file-operations.ts:
  - obsidian_read_note now uses executeObsidianCommandBinary so the
    raw bytes are preserved before any decoding happens
  - isBinaryContent() now operates on the raw Buffer (null byte check
    + >10% non-printable byte ratio on first 8KB sample)
  - Binary files are returned as "BASE64:<base64string>" so the client
    can reliably decode back to the original binary
  - Tool descriptions updated to document the BASE64: prefix convention

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-30 18:43:00 -05:00
4067520cd8 fix: detect and reject binary files in obsidian_read_note fixes #9
When obsidian_read_note read a binary file (ZIP, image, compiled
binary, etc.) the CLI returned raw bytes that were corrupted by text
decoding, producing an unusable response.

Added isBinaryContent() helper that checks for null bytes (definitive
binary marker) and a >10% ratio of non-printable characters in the
first 8KB of content. When binary content is detected the tool returns
a clear error message instead of garbled bytes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-30 18:39:32 -05:00
d27abcfca4 fix: clarify name vs path semantics in obsidian_create_note (fixes #8)
The tool descriptions were ambiguous — 'path' was described as a
'full file path (alternative to name)' which led callers to pass the
full path including filename in path, confusing the CLI.

Clarified semantics:
  name = filename only  (e.g. "My Note.md")
  path = folder only    (e.g. "Projects/Work") — never include filename

Added required: ['name'] to both input schemas.
Updated tool and handler descriptions accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-30 18:20:49 -05:00
a0801a82fd fix: chunk large note reads to prevent output-too-large errors (fixes #5)
Add offset and max_chars parameters to obsidian_read_note:
- max_chars (default 50000, max 500000): caps characters returned per call
- offset (default 0): start position for reading, enabling pagination

When content is truncated a trailer message is appended telling the
caller the total size and the exact offset to pass on the next call.

This prevents the 26MB+ responses that caused Claude to reject output
when reading large PDFs stored in an Obsidian vault.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 17:36:33 -05:00
8e2e8f858c fix: properly quote CLI parameters to handle filenames with spaces
Fixed parameter quoting in file operations and search tools to handle
filenames and values containing spaces correctly.

Root Cause:
- Obsidian CLI requires quoting values with spaces: name="My Note"
- Previous implementation used unquoted format: name=My Note
- Shell would split on spaces, breaking multi-word filenames

Solution:
1. Created formatParam() helper in src/utils/cli-helpers.ts
   - Always quotes parameter values: param="value"
   - Handles spaces and special characters safely

2. Updated file-operations.ts (8 tools):
   - All file/path/content/name parameters now quoted
   - create, read, append, prepend, delete, move, rename, open

3. Updated search.ts (1 tool):
   - query, path, format, limit parameters now quoted
   - Fixes searches with multi-word queries

Changes:
- Before: cmdArgs.push(\`file=${name}\`)
- After: cmdArgs.push(formatParam('file', name))

Files changed:
- src/utils/cli-helpers.ts (new): formatParam() and buildCmdArgs() helpers
- src/tools/file-operations.ts: Use formatParam() for all parameters
- src/tools/search.ts: Use formatParam() for all parameters

Impact:
- File operations now work with multi-word filenames
- Search queries with spaces now work correctly
- Content parameters with newlines/special chars handled safely

Known Issue:
- links.ts, tags-aliases.ts, properties.ts still need similar fixes
- These tools have additional structural issues (wrong command names)
- Will be addressed in follow-up commit

Build: 0 errors

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-22 13:09:08 -05:00
d556183388 feat: add proper input schemas to all file operation tools
Fixed all file operation tools to match Obsidian CLI specification
with complete inputSchema definitions for tools/list exposure.

Changes per tool (verified via 'obsidian help <command>'):

1. obsidian_create_note:  Already fixed (name, path, content, template, overwrite, open, newtab)
2. obsidian_read_note:  Already fixed (file, path)
3. obsidian_append_to_note:  Already fixed (file, path, content, inline)
4. obsidian_prepend_to_note: Fixed - Added full schema (file, path, content, inline)
5. obsidian_delete_note: Fixed - Added full schema (file, path, permanent)
6. obsidian_move_note: Fixed - Added full schema (file, path, to)
7. obsidian_rename_note: Fixed - Added full schema (file, path, name)
8. obsidian_open_note: Fixed - Added full schema (file, path, newtab)

Command execution fixes:
- Changed all executeObsidianCommand('note', ...) to proper commands
  ('create', 'read', 'append', 'prepend', 'delete', 'move', 'rename', 'open')
- Changed parameter format from '--flag value' to 'param=value'
  (matches actual Obsidian CLI syntax)
- Removed identifier concatenation, now builds params properly:
  Before: ['command', identifier, '--flag', value]
  After: ['file=name'] or ['path=folder/note.md']

Removed tools:
- obsidian_duplicate_note: Not in Obsidian CLI spec
- obsidian_get_file_info: Not in Obsidian CLI (use 'file' command separately if needed)

Tool count reduced from 9 to 8 (removed non-existent commands).

All 8 file operation tools now have:
 Complete inputSchema with all parameters documented
 Correct command names matching Obsidian CLI
 Proper param=value format for CLI execution
 Required fields marked appropriately

Files changed:
- src/tools/file-operations.ts

Build:  0 errors
Impact: tools/list now returns complete schemas for all file ops

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-22 13:01:09 -05:00
622b28e42c feat: implement Obsidian MCP Bundle MVP (Phase 1-3)
- Complete project setup with TypeScript, Jest, MCPB manifest
- Implement foundational infrastructure (CLI executor, logger, error handler)
- Add 9 file operation tools for User Story 1
- Full MCP protocol compliance with stdio transport
- Input validation and sanitization for security
- Comprehensive error handling with actionable messages
- Constitutional compliance: all 6 principles satisfied

MVP includes:
- obsidian_create_note, read, append, prepend, delete, move, rename, open, file_info
- Zod validation schemas for all parameters
- 30s timeout configuration with per-command overrides
- Stderr-only logging with sanitized output
- Graceful shutdown handling

Build:  0 errors, 0 vulnerabilities
Tasks: 48/167 complete (MVP milestone)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-22 11:21:38 -05:00