Files
Peter.Morton 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

4.9 KiB

MCP Protocol Contract

Purpose: Define the JSON-RPC communication contract between AI assistants and the Obsidian MCP server

Transport

Protocol: JSON-RPC 2.0 over stdio
Direction: Bidirectional (client ↔ server)

Stdio Requirements

  • stdin: Server reads JSON-RPC requests line-by-line
  • stdout: Server writes JSON-RPC responses line-by-line (one message per line)
  • stderr: Server logs debugging information (never JSON-RPC messages)

Message Format

All messages are single-line JSON objects ending with \n:

{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{...}}\n

Initialization Handshake

Request: initialize

Client sends capabilities and version information:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": {
      "name": "Claude Desktop",
      "version": "1.0.0"
    }
  }
}

Response: initialize

Server responds with its capabilities:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "tools": {}
    },
    "serverInfo": {
      "name": "obsidian-mcp",
      "version": "1.0.0"
    }
  }
}

Tool Discovery

Request: tools/list

Client requests available tools:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}

Response: tools/list

Server returns tool definitions with schemas:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "obsidian_create_note",
        "description": "Create a new note in the vault",
        "inputSchema": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string",
              "description": "Note name (without .md extension) or exact path"
            },
            "content": {
              "type": "string",
              "description": "Initial note content (markdown)"
            },
            "overwrite": {
              "type": "boolean",
              "description": "Overwrite if file exists"
            }
          },
          "required": ["name"]
        }
      }
      // ... more tools
    ]
  }
}

Tool Invocation

Request: tools/call

Client invokes a tool:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "obsidian_create_note",
    "arguments": {
      "name": "Meeting Notes",
      "content": "# Meeting Notes\n\n- Agenda item 1"
    }
  }
}

Response: Success

Tool execution succeeded:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"success\":true,\"data\":{\"path\":\"Meeting Notes.md\",\"created\":true}}"
      }
    ]
  }
}

Response: Error

Tool execution failed:

{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32000,
    "message": "Obsidian application is not running. Please start Obsidian and try again.",
    "data": {
      "errorCode": "OBSIDIAN_NOT_RUNNING"
    }
  }
}

Error Codes

JSON-RPC Standard Errors

Code Message Meaning
-32700 Parse error Invalid JSON
-32600 Invalid Request Invalid JSON-RPC structure
-32601 Method not found Unknown method
-32602 Invalid params Parameter validation failed
-32603 Internal error Server internal error

Application Errors

Code Message When
-32000 Server error Generic application error
-32001 Obsidian not running Obsidian app not detected
-32002 Vault not found Invalid vault name
-32003 File not found Note doesn't exist
-32004 Ambiguous name Multiple files match name
-32005 Permission denied Filesystem permission issue
-32006 Timeout Operation exceeded 30s

Shutdown

Notification: exit

Client notifies server of shutdown (no response expected):

{
  "jsonrpc": "2.0",
  "method": "exit"
}

Server should:

  1. Complete any in-flight operations
  2. Close file handles
  3. Flush logs
  4. Exit process

EOF on stdin

If stdin closes without exit notification, server should gracefully shutdown.

Performance Requirements

  • initialize response: <100ms
  • tools/list response: <200ms
  • tools/call response: <3s for file ops, <5s for search (per SC-001, SC-002)

Compliance Checklist

  • JSON-RPC 2.0 format for all messages
  • Stdio transport (stdin for requests, stdout for responses)
  • Line-by-line message format (newline-delimited)
  • Initialize handshake before tool calls
  • Tool schemas in tools/list response
  • Structured error responses with codes
  • Graceful shutdown on exit notification
  • No stdout pollution (logs to stderr only)
  • Immediate stdout flushing after responses
  • EOF handling (graceful shutdown)