@mandays/obsidian-memory-mcp
v0.1.1
Published
MCP server for Obsidian v3 Atomic Markdown Memory vaults
Maintainers
Readme
obsidian-memory-mcp
MCP (Model Context Protocol) server for Obsidian v3 Atomic Markdown Memory vaults.
Provides standardized tools for any AI assistant (Claude Code, Claude Desktop, ChatGPT, Codex, Qoder, Open Code, Hermes Agent, Antigravity, Open Claw, Cursor) to read, write, search, and manage Obsidian vault memory using the v3 Atomic Markdown Memory specification.
Table of Contents
- Installation
- Quick Start
- MCP Client Configuration
- Available Tools
- CLI Options
- Environment Variables
- Write Modes
- Architecture
- Troubleshooting
- Development
- Documentation
Installation
Global Installation (Recommended)
Install the package globally for system-wide access:
npm install -g @mandays/obsidian-memory-mcpVerify installation:
obsidian-memory-mcp --versionUsing npx (No Installation Required)
Run directly without installing:
npx @mandays/obsidian-memory-mcp --vault ~/path/to/vaultNote: Using npx will download the package on first use. For frequent usage, global installation is faster.
Requirements
- Node.js >= 20
- An Obsidian vault (existing or new)
Quick Start
Initialize a New Vault
If you don't have a vault yet:
# Start the server pointing to a new directory
npx @mandays/obsidian-memory-mcp --vault ~/new-memory-vault
# Then call the vault_init tool from your AI assistant to scaffold the structurestdio Mode (CLI-based MCP Clients)
For MCP clients that communicate via standard input/output:
npx @mandays/obsidian-memory-mcp --vault ~/obsidian-vaultSSE/HTTP Mode (Desktop Apps)
For MCP clients that connect via HTTP:
npx @mandays/obsidian-memory-mcp \
--vault ~/obsidian-vault \
--transport sse \
--port 3100Then configure your client to connect to http://localhost:3100.
MCP Client Configuration
Claude Code
Create or edit .mcp.json in your project root, or ~/.claude/mcp.json for global configuration:
{
"mcpServers": {
"obsidian-memory": {
"command": "npx",
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/absolute/path/to/vault"]
}
}
}Note: Use absolute paths for --vault to avoid working directory issues.
Claude Desktop
Edit your Claude Desktop configuration:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"obsidian-memory": {
"command": "npx",
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/absolute/path/to/vault"]
}
}
}Restart Claude Desktop after saving the configuration.
Hermes Agent
Add to your Hermes agent configuration:
{
"mcp": {
"servers": {
"obsidian-memory": {
"command": "npx",
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/path/to/vault"]
}
}
}
}ChatGPT (Desktop App)
If using a ChatGPT client that supports MCP:
{
"mcpServers": {
"obsidian-memory": {
"command": "npx",
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/path/to/vault"]
}
}
}Codex
Configure in your Codex MCP settings:
{
"mcpServers": {
"obsidian-memory": {
"command": "npx",
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/path/to/vault"]
}
}
}Cursor
- Open Cursor Settings → Features → MCP
- Add a new MCP server with:
- Name:
obsidian-memory - Type:
command - Command:
npx @mandays/obsidian-memory-mcp --vault /path/to/vault
- Name:
Or edit .cursor/mcp.json:
{
"mcpServers": {
"obsidian-memory": {
"command": "npx",
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/path/to/vault"]
}
}
}Qoder
Add to your Qoder MCP configuration:
{
"mcpServers": {
"obsidian-memory": {
"command": "npx",
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/path/to/vault"]
}
}
}QoderWork
For QoderWork environments:
{
"mcpServers": {
"obsidian-memory": {
"command": "npx",
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/path/to/vault"]
}
}
}OpenCode
Configure in your OpenCode settings:
{
"mcp": {
"obsidian-memory": {
"command": "npx",
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/path/to/vault"]
}
}
}OpenClaw
Add to your OpenClaw MCP configuration:
{
"mcpServers": {
"obsidian-memory": {
"command": "npx",
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/path/to/vault"]
}
}
}Antigravity
Configure in your Antigravity settings:
{
"mcp": {
"servers": {
"obsidian-memory": {
"command": "npx",
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/path/to/vault"]
}
}
}
}Multi-Agent Setup (Inbox Mode)
For scenarios with multiple AI agents accessing the same vault:
{
"mcpServers": {
"obsidian-memory": {
"command": "npx",
"args": [
"@mandays/obsidian-memory-mcp",
"--vault", "/path/to/vault",
"--mode", "inbox",
"--agent-id", "agent-claude-1a2b3c4d"
]
}
}
}Each agent should have a unique --agent-id. See Write Modes for details.
Available Tools
The server provides 20 MCP tools organized into 5 categories. Each tool is designed to work with the v3 Atomic Markdown Memory specification.
Quick Reference
| Category | Tools | Purpose |
|----------|-------|---------|
| Read/Query | read_fact, read_entity, read_event, search_memory, get_view | Retrieve facts, events, and views |
| Write | create_fact, update_fact, add_event, archive_fact | Create and modify vault data |
| Maintenance | lint_vault, rebuild_views, compact_inbox, reflect | Validate and maintain vault |
| Schema | list_entities, search_entities, update_entity, add_entity, list_predicates, add_predicate, get_schema | Manage entities and predicates |
| Vault | vault_init, vault_status | Initialize and monitor vault |
💡 See also: Tools Help Guide for comprehensive documentation with concepts, examples, and best practices.
Read/Query Tools
read_fact
Read a specific atomic fact by entity+predicate or ID.
Parameters:
entity(string): Entity name (e.g., "user", "project-alpha")predicate(string): Predicate name (e.g., "name", "role")id(string, optional): Direct fact ID
Example:
read_fact(entity="user", predicate="name")read_entity
Get all facts associated with a specific entity.
Parameters:
entity(string): Entity name
Example:
read_entity(entity="project-alpha")read_event
Find events by date range, entity, or kind.
Parameters:
entity(string, optional): Filter by entitykind(string, optional): Filter by event kindfrom(string, optional): Start date (ISO 8601)to(string, optional): End date (ISO 8601)limit(number, optional): Max results (default: 20)
Example:
read_event(entity="user", kind="reflection", from="2024-01-01", limit=10)search_memory
Flexible search with multiple filters.
Parameters:
query(string, optional): Full-text search queryentity(string, optional): Filter by entitypredicate(string, optional): Filter by predicatefrom(string, optional): Start dateto(string, optional): End datemin_confidence(number, optional): Minimum confidence score (0-1)tags(array, optional): Filter by tags
Example:
search_memory(query="project deadline", min_confidence=0.8, tags=["important"])get_view
Read materialized views (pre-generated summaries).
Parameters:
view(string): View name (timeline, contradictions, stale, graph, entities, predicates)
Example:
get_view(view="timeline")Write Tools
create_fact
Create a new atomic fact.
Parameters:
entity(string): Entity namepredicate(string): Predicate namevalue(string): Fact valueconfidence(number, optional): Confidence score (0-1, default: 0.5)tags(array, optional): Tags for the factnotes(string, optional): Additional notes
Example:
create_fact(
entity="user",
predicate="location",
value="San Francisco, CA",
confidence=0.9,
tags=["personal"]
)update_fact
Update an existing fact (requires precondition hash for conflict detection).
Parameters:
id(string): Fact ID to updatevalue(string): New valueprecondition_hash(string): Hash from the fact being updatedconfidence(number, optional): Updated confidencetags(array, optional): Updated tagsnotes(string, optional): Updated notes
Example:
update_fact(
id="fact-abc123",
value="New York, NY",
precondition_hash="sha256:xyz789"
)add_event
Record an append-only event.
Parameters:
entity(string): Entity namekind(string): Event kindsummary(string): Event summarytimestamp(string, optional): Event timestamp (ISO 8601, default: now)details(object, optional): Additional event data
Example:
add_event(
entity="project-alpha",
kind="milestone",
summary="Completed Phase 1",
details={"phase": 1, "deliverables": ["design", "prototype"]}
)archive_fact
Archive a fact to _archive/ directory.
Parameters:
id(string): Fact ID to archive
Example:
archive_fact(id="fact-abc123")Maintenance Tools
lint_vault
Perform full schema validation on the vault.
Parameters: None
Example:
lint_vault()rebuild_views
Regenerate all _views/ files.
Parameters: None
Example:
rebuild_views()compact_inbox
Apply proposed operations from inbox (inbox mode only).
Parameters:
agent_id(string, optional): Filter by agent IDdry_run(boolean, optional): Preview without applying (default: false)
Example:
compact_inbox(dry_run=true)reflect
Create a reflection/observation event.
Parameters:
content(string): Reflection contententity(string, optional): Related entitytimestamp(string, optional): Timestamp (default: now)
Example:
reflect(content="User seems to be working on multiple projects", entity="user")Schema Management Tools
list_entities
List all registered entities.
Parameters: None
Example:
list_entities()search_entities
Search for entities by query string. Matches against entity ID, display name, and aliases.
Parameters:
query(string): Search query to match against entity ID, display name, or aliaseskind(string, optional): Filter by entity kind (person, project, org, place, concept, tool)
Example:
search_entities(query="john")
search_entities(query="john", kind="person")update_entity
Update an existing entity in the vault's entity index.
Parameters:
id(string): Entity ID to update (kebab-case)kind(string, optional): New entity kind (person, project, org, place, concept, tool)display(string, optional): New display namealiases(array, optional): New alternative names (replaces existing)
Example:
update_entity(
id="john-doe",
display="John Michael Doe",
aliases=["John D.", "JM Doe"]
)add_entity
Register a new entity.
Parameters:
name(string): Entity namedescription(string, optional): Entity description
Example:
add_entity(name="team", description="Project team information")add_predicate
Register a new predicate.
Parameters:
name(string): Predicate nametype(string): Value type (string, number, boolean, date)description(string, optional): Predicate description
Example:
add_predicate(name="budget", type="number", description="Project budget")get_schema
Get YAML schema for a specific type.
Parameters:
type(string): Schema type (entity, predicate, event)
Example:
get_schema(type="entity")Vault Tools
vault_init
Scaffold a new v3 vault structure.
Parameters: None
Example:
vault_init()vault_status
Get health overview with counts.
Parameters: None
Example:
vault_status()CLI Options
| Option | Description | Default |
|--------|-------------|---------|
| --vault <path> | Path to vault root | Required (or set VAULT_PATH env) |
| --transport <type> | Transport type: stdio or sse | stdio |
| --agent-id <id> | Agent identity for this instance | - |
| --mode <mode> | Write mode: direct or inbox | direct |
| --port <port> | SSE port number | 3100 |
| --api-key <key> | API key for SSE authentication | - |
| --stale-days <days> | Days before a fact is marked stale | 180 |
Environment Variables
All CLI options can also be set via environment variables:
| Variable | Description | Example |
|----------|-------------|---------|
| VAULT_PATH | Path to vault root | /Users/name/vault |
| TRANSPORT | Transport type | stdio or sse |
| AGENT_ID | Agent identity | agent-claude-abc123 |
| WRITE_MODE | Write mode | direct or inbox |
| PORT | SSE port number | 3100 |
| API_KEY | SSE authentication key | your-secret-key |
| STALE_DAYS | Stale threshold in days | 180 |
| MEMORY_TODAY | Override "today" for deterministic views | 2024-06-15 |
Example usage:
VAULT_PATH=~/my-vault WRITE_MODE=inbox AGENT_ID=agent-1 npx @mandays/obsidian-memory-mcpWrite Modes
Direct Mode (Default)
Use case: Single AI agent working with the vault.
In direct mode, all write operations (create, update, archive) are applied immediately to the vault files. This is the simplest and most efficient mode for single-agent scenarios.
Behavior:
- Writes go directly to markdown files
- No conflict detection needed
- Faster operations
- Suitable for personal AI assistants
Configuration:
{
"args": ["@mandays/obsidian-memory-mcp", "--vault", "/path/to/vault", "--mode", "direct"]
}Inbox Mode
Use case: Multiple AI agents sharing the same vault.
In inbox mode, write operations create "operation envelopes" in memory/_inbox/{agent-id}/ops/ instead of directly modifying files. Operations are later validated and applied using compact_inbox.
Behavior:
- Writes create proposal files in the inbox
- Supports precondition hashes for conflict detection
- Supports advisory claims for optimistic updates
- Operations are validated before application
- Prevents data corruption in multi-agent scenarios
Workflow:
- Agent A creates an operation proposal
- Agent B creates another operation
- Admin (or any agent) calls
compact_inboxto validate and apply all pending operations - Conflicts are detected and reported
Configuration:
{
"args": [
"@mandays/obsidian-memory-mcp",
"--vault", "/path/to/vault",
"--mode", "inbox",
"--agent-id", "unique-agent-id"
]
}Important: Each agent must have a unique --agent-id to prevent conflicts.
Architecture
The server ports the complete Obsidian v3 toolchain (originally Python scripts: lint.py, compact.py, rebuild_views.py, ops.py, query.sh) to TypeScript, providing a self-contained npm package with no Python dependency.
┌─────────────────────────────────────────┐
│ MCP Client (AI Agent) │
└──────────────┬──────────────────────────┘
│ MCP Protocol (stdio/SSE)
▼
┌─────────────────────────────────────────┐
│ MCP Tool Layer (20) │
│ read_fact, create_fact, search_memory │
│ update_fact, vault_init, etc. │
└──┬──────────┬──────────┬──────────┬─────┘
│ │ │ │
▼ ▼ ▼ ▼
┌────────┐ ┌──────────┐ ┌────────┐ ┌──────────┐
│ Query │ │ Operation│ │ View │ │ Schema │
│ Engine │ │ Manager │ │Generator│ │Validator │
└───┬────┘ └────┬─────┘ └───┬────┘ └────┬─────┘
│ │ │ │
└───────────┴───────────┴───────────┘
│
▼
┌─────────────────────────────────────────┐
│ Vault Service │
│ - Path resolution │
│ - Entity/Predicate registries │
│ - File I/O operations │
└──────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Markdown Service (gray-matter) │
│ - Frontmatter parsing │
│ - Content serialization │
└─────────────────────────────────────────┘Key components:
- Vault Service: Handles file system operations, path resolution, and maintains entity/predicate registries
- Query Engine: Executes searches and filters across the vault
- Operation Manager: Manages create/update/archive operations with conflict detection
- View Generator: Creates materialized views (timeline, graph, stale facts, etc.)
- Schema Validator: Validates facts against registered entity/predicate schemas
Troubleshooting
Common Issues
"Cannot find module" or "Module not found"
Cause: Package not installed or not in PATH.
Solution:
# For global installation
npm install -g @mandays/obsidian-memory-mcp
# Or use npx
npx @mandays/obsidian-memory-mcp --vault /path/to/vault"Vault path does not exist"
Cause: The specified vault directory doesn't exist.
Solution:
# Create the directory first
mkdir -p ~/my-vault
# Or use vault_init tool to scaffold
npx @mandays/obsidian-memory-mcp --vault ~/my-vault
# Then call vault_init from your AI assistant"No tools available" or MCP connection fails
Cause: Misconfigured MCP client or incorrect command path.
Solution:
- Verify the command works manually:
npx @mandays/obsidian-memory-mcp --version - Check your MCP client configuration JSON syntax
- Ensure absolute paths are used for
--vault - Restart your MCP client
SSE connection refused
Cause: Port already in use or firewall blocking.
Solution:
# Try a different port
npx @mandays/obsidian-memory-mcp --vault /path/to/vault --transport sse --port 3101
# Check if port is in use
lsof -i :3100 # macOS/Linux
netstat -ano | findstr 3100 # WindowsOperations failing in inbox mode
Cause: Conflicting operations or invalid precondition hashes.
Solution:
- Run
compact_inbox(dry_run=true)to preview conflicts - Review operation proposals in
memory/_inbox/{agent-id}/ops/ - Resolve conflicts by editing or removing proposal files
- Retry
compact_inbox()without dry_run
Stale facts not updating
Cause: MEMORY_TODAY environment variable overriding current date.
Solution:
# Remove or update the variable
unset MEMORY_TODAY
# or
export MEMORY_TODAY=2024-06-15 # Set to correct dateDebug Mode
For detailed logging, set the NODE_DEBUG environment variable:
NODE_DEBUG=mcp npx @mandays/obsidian-memory-mcp --vault /path/to/vaultGetting Help
- Check the Obsidian Memory for AI v3 specification
- Review the architecture diagram above
- Run
vault_statusto get a health overview of your vault - Use
lint_vaultto check for schema validation errors
Development
Prerequisites
- Node.js >= 20
- npm >= 10
Setup
# Clone the repository
git clone https://github.com/mandays/obsidian-memory-mcp.git
cd obsidian-memory-mcp
# Install dependencies
npm installAvailable Scripts
# Run in development mode with hot reload
npm run dev -- --vault ./test/fixtures/v3-vault
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Type checking
npm run typecheck
# Linting
npm run lint
# Build for production
npm run buildProject Structure
obsidian-memory-mcp/
├── src/
│ ├── server.ts # MCP server entry point
│ ├── cli.ts # CLI interface
│ ├── core/ # Core services
│ │ ├── vault.ts # Vault operations
│ │ ├── entity-registry.ts
│ │ ├── predicate-registry.ts
│ │ ├── query-engine.ts
│ │ ├── operation-manager.ts
│ │ ├── schema-validator.ts
│ │ └── view-generator.ts
│ ├── tools/ # MCP tool implementations
│ ├── services/ # Supporting services
│ └── types/ # TypeScript type definitions
├── bin/ # CLI entry point
├── test/ # Test files
└── dist/ # Built output (generated)Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes
- Run tests:
npm test - Run type checking:
npm run typecheck - Run linting:
npm run lint - Commit your changes:
git commit -m "Add my feature" - Push to the branch:
git push origin feature/my-feature - Submit a pull request
Releasing
The project uses GitHub Actions for automated releases:
- Update version in
package.jsonandsrc/server.ts - Commit and push changes
- Create a git tag:
git tag v0.1.1 - Push the tag:
git push origin v0.1.1 - GitHub Actions will automatically test, build, publish to npm, and create a GitHub release
Documentation
For comprehensive documentation and guides:
- Tools Help Guide: Complete tool documentation with concepts, workflows, and examples
- Glossary: Comprehensive terminology reference for all project concepts
- v3 Specification: Official Atomic Markdown Memory specification
License
MIT
