{"id":51404978,"url":"https://github.com/nickrobison/zakhor","last_synced_at":"2026-07-04T10:03:13.864Z","repository":{"id":366076637,"uuid":"1274476311","full_name":"nickrobison/zakhor","owner":"nickrobison","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-28T03:04:11.000Z","size":898,"stargazers_count":0,"open_issues_count":29,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-28T03:11:36.123Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nickrobison.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-19T14:54:03.000Z","updated_at":"2026-06-28T03:04:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nickrobison/zakhor","commit_stats":null,"previous_names":["nickrobison/zakhor"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nickrobison/zakhor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickrobison%2Fzakhor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickrobison%2Fzakhor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickrobison%2Fzakhor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickrobison%2Fzakhor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nickrobison","download_url":"https://codeload.github.com/nickrobison/zakhor/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickrobison%2Fzakhor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35117336,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-04T10:03:13.255Z","updated_at":"2026-07-04T10:03:13.859Z","avatar_url":"https://github.com/nickrobison.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Zakhor\n\nMCP (Model Context Protocol) server for persistent memory backed by GNOME Tracker SPARQL storage.\n\n## Overview\n\nZakhor exposes a Tracker SPARQL database through the MCP protocol, giving AI agents\npersistent read/write access to knowledge stored in Tracker's RDF store. Each memory\nis stored as a [NIE](https://en.wikipedia.org/wiki/Nepomuk) information element with\nplain-text content.\n\n## Prerequisites\n\n- Rust 1.85+ (2024 edition)\n- GNOME Tracker 3 (`tracker3`) — typically pre-installed on GNOME desktops\n- Running Tracker endpoint (`tracker3 endpoint`) on the same machine\n  - Zakhor reads `TRACKER_ENDPOINT` env var or defaults to `http://127.0.0.1:7878`\n\n## Usage\n\n```bash\n# Start with default DB path (./zakhor-db/) over stdio:\ncargo run\n\n# Start with a specific DB path:\ncargo run -- --db-path /path/to/db\n\n# Or set via env var:\nZAKHOR_DB_PATH=/path/to/db cargo run\n\n# Start over MCP Streamable HTTP/SSE:\ncargo run -- --http\n```\n\nBy default, stdio mode listens on stdin/stdout. Use `--http` to expose both\nMCP tools and REST API endpoints on a single HTTP server at `http://127.0.0.1:3000`.\n\nHTTP configuration can be overridden with environment variables:\n\n- `ZAKHOR_HTTP_HOST` — bind host, default `127.0.0.1`\n- `ZAKHOR_HTTP_PORT` — bind port, default `3000`\n\nExample:\n\n```bash\nZAKHOR_HTTP_HOST=0.0.0.0 ZAKHOR_HTTP_PORT=4000 cargo run -- --http\n```\n\nOnce running in HTTP mode, the server exposes:\n- MCP tools at the root (`/`) via Streamable HTTP/SSE\n- REST API at `/api/v1/` (with OpenAPI docs at `/api/v1/docs`)\n\nOnce running, the MCP server listens on stdin/stdout or HTTP/SSE — connect any\nMCP-compatible host (Claude Desktop, OpenCode, etc.) to use the tools.\n\n### MCP Tools\n\n| Tool | Args | Description |\n|------|------|-------------|\n| `store_observation` | `content`, `created_at`, `metadata` | Store an observation with optional structured metadata |\n| `query_entities` | `pattern`, `limit` | Query entities by label pattern in the knowledge graph |\n| `traverse_graph` | `uri`, `limit` | Traverse outgoing RDF edges from an entity |\n| `search_hybrid` | `query`, `limit` | Hybrid lexical/semantic search using RRF fusion |\n| `record_decision` | `context`, `decision`, `alternatives`, `rationale` | Record a decision with context and rationale |\n| `rebuild_indexes` | none | Rebuild all search indexes from Tracker |\n\n## Architecture\n\n```\n┌────────────────────┐     MCP stdio or Streamable HTTP/SSE     ┌──────────────┐\n│  MCP Host          │ ◄──────────────────────────────────────► │   Zakhor     │\n│  (Claude, OpenCode)│                                           │  (rmcp)      │\n└────────────────────┘                                           └──────┬───────┘\n                                                                        │\n                                                               spawn_blocking\n                                                                        │\n                                                                 ┌──────┴───────┐\n                                                                 │ tracker-rs   │\n                                                                 │ (SPARQL FFI) │\n                                                                 └──────┬───────┘\n                                                                        │\n                                                                 ┌──────┴───────┐\n                                                                 │ GNOME Tracker│\n                                                                 │  SPARQL DB   │\n                                                                 └──────────────┘\n```\n\n## Project Structure\n\n```\nsrc/\n├── main.rs         — Entry point, tracing init, CLI arg parsing\n├── server.rs       — MCP tool handler (rmcp router)\n├── tracker_db.rs   — SPARQL CRUD operations\n├── config.rs       — Config struct with TOML + env var support\n└── error.rs        — ZakhorError type + anyhow-based ZakhorResult and retry logic\n```\n\n## Development\n\n```bash\ncargo check        # Static analysis\ncargo test         # Run unit tests\ncargo clippy       # Lint\ncargo build        # Release build: cargo build --release\n```\n\n### Integration Tests\n\nPython integration tests are in [`tests/python/`](tests/python/) and exercise the full\nMCP tool surface against a live Zakhor server. They require a debug build, Python 3.12+,\nand the `uv` package manager.\n\n```bash\n# Prerequisite: compile the debug binary\ncargo build\n\n# Run full integration test suite (via Make):\nmake test-integration\n\n# Or run directly:\n./tests/python/run_tests.sh\n\n# Filter by test keyword:\n./tests/python/run_tests.sh traverse\n\n# Pass extra arguments to pytest:\n./tests/python/run_tests.sh -- -x --tb=short\n```\n\nEach integration test starts an ephemeral Zakhor server on a random port, runs\nassertions over MCP and SPARQL, and tears down the server afterward. The suite\nrequires a running Tracker SPARQL endpoint (`tracker3 endpoint` or `tinysparql`).\n\nSee [`tests/python/pyproject.toml`](tests/python/pyproject.toml) for test configuration and dependencies.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnickrobison%2Fzakhor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnickrobison%2Fzakhor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnickrobison%2Fzakhor/lists"}