{"id":51302740,"url":"https://github.com/np6126/mcp-llm-wiki","last_synced_at":"2026-06-30T21:32:28.649Z","repository":{"id":359335989,"uuid":"1244013748","full_name":"np6126/mcp-llm-wiki","owner":"np6126","description":"Git-backed MCP server that exposes Karpathy-style LLM wikis as a tool surface for AI coding agents","archived":false,"fork":false,"pushed_at":"2026-05-21T15:54:22.000Z","size":99,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-21T19:54:56.188Z","etag":null,"topics":["agentic-ai","ai-agents","git","knowledge-base","llm","markdown","mcp","mcp-server","model-context-protocol","prompt-injection-defense","python","wiki"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/np6126.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":"audits/mcp-llm-wiki-2026-05-20.md","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-05-19T22:11:37.000Z","updated_at":"2026-05-21T15:56:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/np6126/mcp-llm-wiki","commit_stats":null,"previous_names":["np6126/mcp-llm-wiki"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/np6126/mcp-llm-wiki","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/np6126%2Fmcp-llm-wiki","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/np6126%2Fmcp-llm-wiki/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/np6126%2Fmcp-llm-wiki/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/np6126%2Fmcp-llm-wiki/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/np6126","download_url":"https://codeload.github.com/np6126/mcp-llm-wiki/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/np6126%2Fmcp-llm-wiki/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34984784,"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-06-30T02:00:05.919Z","response_time":92,"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":["agentic-ai","ai-agents","git","knowledge-base","llm","markdown","mcp","mcp-server","model-context-protocol","prompt-injection-defense","python","wiki"],"created_at":"2026-06-30T21:32:27.396Z","updated_at":"2026-06-30T21:32:28.623Z","avatar_url":"https://github.com/np6126.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"assets/logo.svg\" alt=\"mcp-llm-wiki logo\" width=\"140\" height=\"140\"\u003e\n\n# mcp-llm-wiki\n\nA durable, shared knowledge layer for AI coding agents — a git-backed\n[MCP](https://modelcontextprotocol.io/) server that exposes Karpathy's\n[LLM-Wiki pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f)\nas a tool surface.\n\n\u003cp\u003e\n  \u003cimg src=\"https://img.shields.io/badge/license-MIT-2f7e8c\" alt=\"License: MIT\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/protocol-MCP-2f7e8c\" alt=\"Protocol: MCP\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/python-3.10%2B-2f7e8c\" alt=\"Python 3.10+\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/status-pre--1.0-9a6b00\" alt=\"Status: pre-1.0\"\u003e\n\u003c/p\u003e\n\n\u003c/div\u003e\n\n---\n\n**Contents** \u0026nbsp;·\u0026nbsp;\n[Design](#design) \u0026nbsp;·\u0026nbsp;\n[Tools](#tools) \u0026nbsp;·\u0026nbsp;\n[Companion skills](#companion-skills) \u0026nbsp;·\u0026nbsp;\n[Operator CLIs](#operator-clis) \u0026nbsp;·\u0026nbsp;\n[Setting up a wiki](#setting-up-a-wiki) \u0026nbsp;·\u0026nbsp;\n[Clipping web sources](#clipping-web-sources-into-raw) \u0026nbsp;·\u0026nbsp;\n[Editing by hand](#editing-a-wiki-by-hand) \u0026nbsp;·\u0026nbsp;\n[Linting](#linting) \u0026nbsp;·\u0026nbsp;\n[Status](#status) \u0026nbsp;·\u0026nbsp;\n[Integration](#integration) \u0026nbsp;·\u0026nbsp;\n[License](#license)\n\n---\n\nYour agents read and write a persistent Markdown wiki that compounds\nover time. Each wiki is plain\nMarkdown stored in a Git repository — one git repo, one wiki — so the\nknowledge is versioned, reviewable, and editable by hand. Multiple agent\nVMs and humans can read/write the same wiki concurrently; conflicts are\nmediated by ETag optimistic concurrency plus custom merge-drivers for the\ntwo write-contended hotspots (`log.md`, `index.md`).\n\nThe server runs in its own container, isolated from the agent. The agent\ntalks to it over HTTP-MCP and never touches the working trees directly.\n\n## Design\n\n- **Persistent, compounding artifact.** Wiki pages are pre-synthesised\n  Markdown, owned by the LLM agent layer — knowledge that accumulates\n  across sessions, where RAG retrieves chunks fresh at query time.\n- **Git as the source of truth.** Working trees in the container are\n  ephemeral; the canonical bare repos live on the git host. Every write\n  pushes; reads refresh the working tree with a TTL-debounced\n  `git pull --rebase`.\n- **Schema-blind.** The server validates nothing about page structure;\n  conventions live in the agent's skills (see [Companion\n  skills](#companion-skills)). The server's job is filesystem\n  primitives + git mediation + safety.\n- **Safety first.** All writes pass through a paranoid Markdown\n  sanitiser (HTML comments, zero-width chars, bidi overrides, raw HTML,\n  inline-style CSS, `data:` images). Path operations always go through\n  `realpath()` + prefix-check; symlinks are rejected.\n\n## Tools\n\n| Tool | Mode | Purpose |\n|---|---|---|\n| `wiki_list` | read-only | List pages with frontmatter summary |\n| `wiki_read` | read-only | Read a page (returns content + frontmatter + outgoing links + ETag) |\n| `wiki_read_raw` | read-only | Read from the immutable `raw/` source layer (returns content + ETag) |\n| `wiki_search` | read-only | Fixed-string search over wiki pages (ripgrep-backed) |\n| `wiki_save` | write (idempotent) | Upsert a page; atomic write + commit + push, ETag-guarded |\n| `wiki_log_append` | write (append) | Append a timestamped entry to `log.md` |\n| `wiki_lint` | read-only | Drift report (orphans, broken links, unindexed pages, removed/changed sources) — never mutates |\n| `wiki_graph` | read-only | Backlinks map (parses wikilinks + Markdown links) |\n\nThese tools are primitives. The *operations* that compose them —\ningest, query, and lint — are agent workflows; see [Companion\nskills](#companion-skills).\n\n## Companion skills\n\nThe Ingest, Query, and Lint operations ship in this repo as [Agent\nSkills](https://code.claude.com/docs/en/skills) under\n[`examples/skills/`](examples/skills/):\n\n| Skill | Role |\n|---|---|\n| `llm-wiki` | Foundation — the wiki model, the eight tools, and the page-kind, naming, frontmatter, linking, and ETag-concurrency conventions. |\n| `llm-wiki-ingest` | Ingest — turn a new `raw/` source into wiki pages. |\n| `llm-wiki-query` | Query — answer a question from the wiki; optionally file the answer back. |\n| `llm-wiki-lint` | Lint — health-check the wiki for drift and remedy it. |\n\nThe server does not load these — it is schema-blind and exposes only\ntools. The skills belong to the *consuming* agent: copy the four\ndirectories into the agent's skills directory (for Claude Code,\n`~/.claude/skills/` or a project's `.claude/skills/`). The agent then\nloads `llm-wiki` for the conventions and the matching operation skill\nwhen it ingests, queries, or lints. Keep the copies in sync with this\nrepo — the server's tool surface is what they document.\n\n## Operator CLIs\n\nTwo operator-side commands ship with this repo, separate from the MCP\nserver and never run in its container: `wiki-init` seeds a wiki's\nstructure (and resets an existing one), and `wiki-clip` clips web\nsources into `raw/`.\n\nInstall with [pipx](https://pipx.pypa.io/) — it puts the commands on\nyour `PATH` in an isolated environment, sidestepping PEP 668 (the\n`externally-managed-environment` error a plain `pip install` hits on\nrecent Debian/Ubuntu):\n\n```bash\npipx install \".\"\n```\n\nThat single command installs both `wiki-clip` and `wiki-init`, fully\nworking — `wiki-clip`'s dependencies\n([markitdown](https://github.com/microsoft/markitdown) and PyYAML) are\nordinary requirements, not an optional extra. Run `pipx ensurepath`\nonce if `~/.local/bin` isn't on your `PATH`.\n\nBoth commands are repo-agnostic — they take the target wiki repo as an\nargument (default: the current directory), so one install serves every\nwiki. Without `-e` the package is copied into pipx, so the\n`mcp-llm-wiki` checkout is disposable afterward; install editable\n(`pipx install -e \".\"`) only to hack on the tools. Uninstall with\n`pipx uninstall mcp-llm-wiki` — pipx keys on the package name, not the\ncommand names.\n\n## Setting up a wiki\n\nA wiki is an ordinary git repository on any host that issues\nper-repository access tokens — GitHub, GitLab, Gitea, Forgejo, or a\nbare repo. One repo is one wiki; the convention is to name it\n`wiki-\u003ctopic\u003e` (e.g. `wiki-django`). Each repo starts with this\nlayout:\n\n```\nwiki-\u003ctopic\u003e/\n├── raw/            # operator-curated source documents\n├── wiki/           # agent-owned Markdown pages\n│   └── index.md    # category catalog\n├── log.md          # append-only operations log\n└── .gitattributes  # routes log.md / index.md through the merge-drivers\n```\n\n`log.md` lives at the repo root; pages and `index.md` live under\n`wiki/`. The `.gitattributes` patterns carry no slash, so they match\n`log.md` and `wiki/index.md` at any depth — that file routes the two\nwrite-contended hotspots through the merge-drivers that coalesce\nconcurrent appends. The server installs the matching driver scripts\ninto every clone automatically, so `.gitattributes` is all the repo\nneeds. `wiki-init` (see [Operator CLIs](#operator-clis)) seeds that\nwhole layout — clone the repo, run it, commit, push:\n\n```bash\ngit clone https://git.example.com/\u003corg\u003e/wiki-\u003ctopic\u003e.git\ncd wiki-\u003ctopic\u003e\nwiki-init                       # creates raw/.gitkeep, wiki/index.md, log.md, .gitattributes\ngit commit -m \"seed wiki structure\" \u0026\u0026 git push\n```\n\nRun on a wiki that already has content, `wiki-init` resets it to the\nempty structure — listing what will be cleared and asking for\nconfirmation first, and never rewriting git history.\n\nThe server authenticates to the git host over HTTPS with an access\ntoken — no SSH keys. Give each consumer (each agent VM or deployment)\nits own machine account rather than a shared one: commits stay\nattributable in `git log`, one account's token can be revoked without\ndisturbing the others, and per-repo collaborator permissions scope a\nconsumer to only the wikis it should reach. Grant **write** for\nread-write wikis and **read** for read-only ones — the server enforces\nthe same split, and the git host enforces it again as defence in depth.\n\n## Clipping web sources into `raw/`\n\n`raw/` is the operator-curated source layer. The server only ever\n*reads* it (`wiki_read_raw`); the synthesis agent ingests from `raw/`\nbut never writes it, so a web page must be turned into a local Markdown\nfile before the agent sees it.\n\n`wiki-clip` is that step — the command-line equivalent of Karpathy's\nObsidian Web Clipper (install it via [Operator CLIs](#operator-clis)):\n\n```bash\ncd wiki-\u003ctopic\u003e\nwiki-clip https://example.com/some/page\n```\n\nTo clip into a wiki elsewhere, pass its path as the first argument:\n`wiki-clip path/to/wiki-repo \u003curl\u003e`.\n\nIt fetches the URL, converts the HTML to Markdown with\n[markitdown](https://github.com/microsoft/markitdown), and writes\n`raw/\u003cslug\u003e.md` with provenance frontmatter (`source_url`, `title`,\n`fetched`, `clipped_by`). It then `git add`s the file but does **not**\ncommit — the operator reviews the clipped Markdown and commits, keeping\n`raw/` a curated layer. `--name` overrides the filename stem.\n\n## Editing a wiki by hand\n\nA wiki is a normal git repo — edit it like one. Clone it, edit the\nMarkdown in any editor, commit, and push; the server picks the change\nup on its next read. Wikilinks (`[[page]]`) render natively in Obsidian\nand in VS Code with Foam; most git-host web views show them as plain\ntext.\n\n## Linting\n\nLinting is the maintenance cycle that keeps a wiki from rotting: find\nthe drift, then fix it. The fix is the point — a lint that only reports\nhas done half the job.\n\nDetection has two layers, because drift comes in two kinds.\n\n**Mechanical drift** — pages nothing links to, links to pages renamed\naway, pages missing from the catalog, raw sources removed or changed\nunder a page — is deterministically computable. `wiki_lint` finds it:\n\n| Kind | Meaning |\n|---|---|\n| `orphan` | A content page no other page links to. |\n| `broken_link` | An outgoing link whose target page does not exist. |\n| `unindexed` | A content page not linked from `index.md`, the catalog. |\n| `source_missing` | A raw source a page was synthesised from no longer exists. |\n| `source_drift` | Such a raw source's bytes changed since the page was synthesised. |\n\n(`index.md` and `log.md` are exempt from the `orphan` and `unindexed`\nchecks — they are structural, not content pages. A `broken_link` is\nstill reported against `index.md`: the catalog is exactly where links\nto renamed-away pages collect. The report is `{\"issues\": [{kind,\npath, message}, …], \"clean\": \u003cbool\u003e}`.)\n\nThe two `source_*` checks are provenance checks. A page opts in by\nlisting the raw sources it was built from in a `sources:` frontmatter\nblock — each entry a `{path, etag}` pair, where `etag` is the value\n`wiki_read_raw` returned for that source. Pages with no `sources:`\nblock are simply not provenance-tracked. Because a page is usually\nsynthesised from several sources, `source_missing` is graded: its\nmessage states how many sources survive, so a partial loss (re-derive\nfrom the remainder) reads differently from a total loss.\n\n**Semantic drift** — contradictions, claims a newer source has\nsuperseded, concepts mentioned but lacking their own page, missing\ncross-references — cannot be computed; it takes an agent reading and\njudging the content.\n\nThe agent then **remedies** each finding with `wiki_save` — relink an\norphan, stub or drop a broken link, add a page to `index.md`,\nre-synthesise a page whose source was removed or changed, rewrite a\nsuperseded claim. `wiki_lint` is read-only by design: a fix is a\ncontent change and belongs in `wiki_save` (sanitiser, ETag, commit),\nwith the agent deciding *how*. The full detect-and-remedy loop is the\nagent's *Lint* operation, defined in the `llm-wiki-lint` skill (see\n[Companion skills](#companion-skills)).\n\n## Status\n\nImplemented and tested: all 8 tools, the sanitiser, path-safety, ETag\noptimistic concurrency, git mediation, and the `log.md` / `index.md`\nmerge-drivers are in place and covered by the test suite — unit tests,\ngit-integration tests, and a multi-VM end-to-end suite. Pre-1.0 —\ninterfaces may still shift.\n\n## Integration\n\nThis server is designed to be consumed by\n[tank-agent-os](https://github.com/np6126/tank-agent-os) as a Quadlet-managed MCP service, but\nworks standalone for any MCP client. The image is published to a\ncontainer registry; consumers pin by digest.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnp6126%2Fmcp-llm-wiki","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnp6126%2Fmcp-llm-wiki","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnp6126%2Fmcp-llm-wiki/lists"}