- 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>
4.9 KiB
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:
- Complete any in-flight operations
- Close file handles
- Flush logs
- 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)