docs: INSTALL-MCP.md fuer Menschen, wird mit dist export ausgeliefert (2.4.1)
Files changed: - CHANGES.md - INSTALL-MCP.md - INSTALL.md - README.md - VERSION - tools/chemenu/commands/dist_cmd.py
This commit is contained in:
+28
@@ -20,6 +20,34 @@ their date-only headings.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2.4.1 - 2026-09-02 - INSTALL-MCP.md: Menschendoku fuer den Leseserver, und sie wird mit ausgeliefert
|
||||||
|
|
||||||
|
**Author:** Torben Nehmer
|
||||||
|
|
||||||
|
Nachtrag zu 2.4.0. Der Server war ausgeliefert und für Menschen nur über `tools/CONTRACT.md` und
|
||||||
|
eine Instruktion beschrieben — beide für Agenten geschrieben. `INSTALL-MCP.md` schließt das,
|
||||||
|
neben `INSTALL.md` und in derselben Form: Voraussetzungen, sechs Schritte, Verifikation,
|
||||||
|
Troubleshooting.
|
||||||
|
|
||||||
|
**Was drinsteht, das sonst nirgends zusammen stand:** die Client-Konfiguration als JSON-Block;
|
||||||
|
dass `WIKI_TRACE=0` nicht optional ist und wie die Startverweigerung aussieht; dass
|
||||||
|
`--host 0.0.0.0` bewusst nicht der Default ist; und der Verweis auf die
|
||||||
|
Traefik-ForwardAuth-Middleware unter <https://gitea.nehmer.net/torben/gitea-mcp-forward-auth>
|
||||||
|
samt dem, was sie erwartet (Bearer-Token gegen SHA-256-Hashes, `AUTH_PROXY_TOKEN_HASHES_DIR`).
|
||||||
|
Der Verifikationsabschnitt ist ein lauffähiges Skript — wörtlich so ausgeführt, bevor es hier
|
||||||
|
landete.
|
||||||
|
|
||||||
|
**`dist export` liefert die Datei mit.** `ROOT_FILES` ist eine Allowlist, also hätte sie sonst
|
||||||
|
keine Instanz erreicht: ein ausgelieferter Server, dessen Bedienungsanleitung im Ursprungs-Repo
|
||||||
|
zurückbleibt, ist einer, den der Empfänger durch Quelltextlesen findet. `INSTALL.md` bekommt
|
||||||
|
zusätzlich `CHEMENU_ROOT` und `WIKI_TRACE`/`WIKI_TRACE_DIR` in seine Konfigurationstabelle —
|
||||||
|
beide waren seit 2.3.0 bzw. seit jeher wirksam und dort nicht aufgeführt.
|
||||||
|
|
||||||
|
**Dateien:** `INSTALL-MCP.md` (neu), `INSTALL.md`, `README.md`,
|
||||||
|
`tools/chemenu/commands/dist_cmd.py`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 2.4.0 - 2026-09-02 - MCP-Leseserver: zweiter Konsument auf demselben Kern
|
## 2.4.0 - 2026-09-02 - MCP-Leseserver: zweiter Konsument auf demselben Kern
|
||||||
|
|
||||||
**Author:** Torben Nehmer
|
**Author:** Torben Nehmer
|
||||||
|
|||||||
+239
@@ -0,0 +1,239 @@
|
|||||||
|
# MCP-Leseserver installieren
|
||||||
|
|
||||||
|
Dieses Dokument richtet sich an Menschen. Es beschreibt, wie der MCP-Leseserver eines Chemenu-
|
||||||
|
Wikis lokal läuft, wie ein Client ihn einbindet, und wie er hinter einer Authentifizierung
|
||||||
|
erreichbar wird. Der agent-seitige Betriebsablauf steht in
|
||||||
|
[instructions/mcp-read-server.md](instructions/mcp-read-server.md); die vollständige
|
||||||
|
Kommandoreferenz in [tools/CONTRACT.md](tools/CONTRACT.md).
|
||||||
|
|
||||||
|
**Was der Server ist.** Ein zweiter Konsument desselben Kerns, nicht ein zweites Programm. CLI
|
||||||
|
und Server rufen dieselben Funktionen auf; ein Golden-Test hält ihre Ausgaben gegeneinander.
|
||||||
|
Was `tools/wikitool search --json` liefert, liefert das MCP-Tool `search` auch — plus den
|
||||||
|
Commit, aus dem die Antwort berechnet wurde.
|
||||||
|
|
||||||
|
**Was er nicht ist.** Kein Schreibpfad. Es gibt kein Tool, das eine Seite anlegt, ändert oder
|
||||||
|
publiziert — nicht weil eine Liste gefiltert wird, sondern weil der Server nichts unter
|
||||||
|
`tools/chemenu/commands/` importiert. Die Funktionen sind aus diesem Prozess heraus nicht
|
||||||
|
erreichbar.
|
||||||
|
|
||||||
|
## Voraussetzungen
|
||||||
|
|
||||||
|
- Eine funktionierende Instanz nach [INSTALL.md](INSTALL.md) — inklusive `tools/.venv` und
|
||||||
|
`ripgrep`
|
||||||
|
- Python 3.11 oder neuer (wie die CLI)
|
||||||
|
|
||||||
|
## Schritt 1: Abhängigkeit installieren
|
||||||
|
|
||||||
|
Sie liegt bewusst nicht in `tools/requirements.txt`. Eine Instanz, die nur die CLI benutzt, soll
|
||||||
|
dafür nicht pydantic, starlette, uvicorn und cryptography mitinstallieren müssen.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tools/.venv/bin/pip install -r tools/requirements-mcp.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Schritt 2: Lokal starten (stdio)
|
||||||
|
|
||||||
|
`stdio` ist der Weg zum Ausprobieren und für einen Client auf derselben Maschine: ein Prozess
|
||||||
|
pro Konsument, lokal gestartet, kein Netzwerk.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
WIKI_TRACE=0 tools/.venv/bin/python -m chemenu.mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Prozess spricht MCP über stdin/stdout und gibt für sich genommen nichts aus — das ist
|
||||||
|
richtig so. Gestartet wird er normalerweise nicht von Hand, sondern vom Client (Schritt 3).
|
||||||
|
|
||||||
|
**`WIKI_TRACE=0` ist nicht optional.** Telemetrie ist per Default an und schreibt nach
|
||||||
|
`reports/telemetry/` im Repo. Der Server **verweigert den Start**, solange das so ist, statt
|
||||||
|
still umzuleiten:
|
||||||
|
|
||||||
|
```
|
||||||
|
ERROR Telemetry is on and would write into the served checkout (...). Set WIKI_TRACE=0,
|
||||||
|
or point WIKI_TRACE_DIR outside the corpus.
|
||||||
|
```
|
||||||
|
|
||||||
|
Beide Auswege sind gleichwertig: `WIKI_TRACE=0` schaltet ab, `WIKI_TRACE_DIR=/var/log/chemenu`
|
||||||
|
lenkt um. Der Grund steht in Schritt 6 — der Sync darf `reports/` wegräumen.
|
||||||
|
|
||||||
|
## Schritt 3: Einen Client einbinden
|
||||||
|
|
||||||
|
Die Konfiguration folgt der üblichen MCP-Client-Form. Absolute Pfade, weil der Client kein
|
||||||
|
Arbeitsverzeichnis erbt:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"chemenu": {
|
||||||
|
"command": "/pfad/zur/instanz/tools/.venv/bin/python",
|
||||||
|
"args": ["-m", "chemenu.mcp"],
|
||||||
|
"cwd": "/pfad/zur/instanz/tools",
|
||||||
|
"env": {
|
||||||
|
"WIKI_TRACE": "0",
|
||||||
|
"CHEMENU_ROOT": "/pfad/zur/instanz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`CHEMENU_ROOT` sagt, **welches** Wiki bedient wird. Ohne die Variable nimmt der Server den
|
||||||
|
Checkout, in dem das Paket selbst liegt — für eine einzelne Instanz reicht das, aber wer mehrere
|
||||||
|
Korpora hat, setzt sie besser immer.
|
||||||
|
|
||||||
|
Danach kennt der Client fünf Werkzeuge:
|
||||||
|
|
||||||
|
| Tool | Was es beantwortet |
|
||||||
|
|---|---|
|
||||||
|
| `search` | Seiten in `kb/` nach Text, nach Frontmatter (`confidence<0.6`, `tags~k8s`) oder beidem |
|
||||||
|
| `types` | Welche Seitentypen dieses Wiki kennt |
|
||||||
|
| `describe_type` | Der vollständige Vertrag eines Typs: Felder, Pflichtangaben, Enums |
|
||||||
|
| `lint` | Strukturelle Befunde: kaputte Wikilinks, Waisen, Index-Drift, Schema-Lücken |
|
||||||
|
| `status` | Momentaufnahme: Seitenzahl, Verteilung auf Collections, Befundzahlen |
|
||||||
|
|
||||||
|
## Schritt 4: Ausgeliefert starten (streamable HTTP)
|
||||||
|
|
||||||
|
Der Transport für den Betrieb, und der einzige, vor den sich ein Reverse Proxy setzen kann.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
WIKI_TRACE=0 CHEMENU_ROOT=/srv/chemenu \
|
||||||
|
tools/.venv/bin/python -m chemenu.mcp \
|
||||||
|
--transport streamable-http --host 0.0.0.0 --port 8000
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Endpunkt ist dann `http://<host>:8000/mcp`.
|
||||||
|
|
||||||
|
`--host 0.0.0.0` ist bewusst nicht der Default. Ohne die Angabe bindet der Server auf Loopback,
|
||||||
|
was lokal richtig und im Container falsch ist — dort muss der Proxy ihn erreichen können. Wer
|
||||||
|
`0.0.0.0` setzt, muss also auch dafür sorgen, dass davor etwas steht (Schritt 5).
|
||||||
|
|
||||||
|
`sse` wird nicht angeboten. Es ist der abgelöste Remote-Transport; jetzt darauf zu bauen
|
||||||
|
verschiebt den Wechsel nur.
|
||||||
|
|
||||||
|
## Schritt 5: Authentifizierung davor
|
||||||
|
|
||||||
|
**Der Server authentifiziert nicht selbst, und das ist Absicht.** Nicht sauber
|
||||||
|
authentifizierte Zugriffe sollen den Python-Prozess gar nicht erst erreichen. Die
|
||||||
|
Authentifizierung ist eine Traefik-ForwardAuth-Middleware:
|
||||||
|
|
||||||
|
> **<https://gitea.nehmer.net/torben/gitea-mcp-forward-auth>**
|
||||||
|
|
||||||
|
Kurz, was sie tut: sie prüft `Authorization: Bearer <token>` gegen SHA-256-Hashes erlaubter
|
||||||
|
Tokens, antwortet `200` bei gültigem und `401` bei fehlendem oder falschem Token, und hält
|
||||||
|
`GET /healthz` immer offen. Klartext-Tokens liegen weder in der Konfiguration noch im Log — nur
|
||||||
|
Hashes und ein kurzer Fingerprint. Konfiguriert wird sie über
|
||||||
|
`AUTH_PROXY_TOKEN_HASHES_DIR` (ein Verzeichnis, eine Datei je Token-Hash — passend für ein
|
||||||
|
Kubernetes-Secret-Volume) oder `AUTH_PROXY_TOKEN_HASHES` (kommagetrennte Liste). Einzelheiten,
|
||||||
|
Referenzmanifeste und ein Testskript stehen im README dort.
|
||||||
|
|
||||||
|
Einen Token-Hash erzeugen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo -n "mein-token" | sha256sum | awk '{print $1}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rate Limiting gehört an dieselbe Stelle** — vor den Prozess, neben die Authentifizierung.
|
||||||
|
Nicht in den Iteration Budget Gate: der begrenzt eine *Agenten-Session* am unbemerkten Iterieren
|
||||||
|
über den Wiki-Zustand, weshalb Retrieval von ihm ausgenommen ist. Ihn als Rate Limiter zu
|
||||||
|
benutzen würde ihn dazu verwässern.
|
||||||
|
|
||||||
|
## Schritt 6: Den Korpus aktuell halten
|
||||||
|
|
||||||
|
Der Server liest den Arbeitsbaum. Ein veralteter Checkout antwortet selbstbewusst falsch —
|
||||||
|
deshalb trägt **jede Antwort den Commit**, aus dem sie berechnet wurde:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "commit": "<40-stelliger SHA>", "as_of": "<ISO-8601, UTC>", "count": 3, "...": "..." }
|
||||||
|
```
|
||||||
|
|
||||||
|
Aktuell gehalten wird der Baum durch Polling, aus einem Timer neben dem Server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git -C "$CHEMENU_ROOT" fetch --quiet origin && \
|
||||||
|
git -C "$CHEMENU_ROOT" reset --hard --quiet origin/main
|
||||||
|
```
|
||||||
|
|
||||||
|
Polling statt Webhook, weil es keinen eingehenden Endpunkt und keine Signaturprüfung braucht —
|
||||||
|
eine kleinere Angriffsfläche als das, was es optimieren würde.
|
||||||
|
|
||||||
|
`reset --hard` ist dabei tragend und keine Bequemlichkeit: der Korpus-Cache verwendet einen
|
||||||
|
Parse wieder, solange der Commit gleich bleibt, und cacht einen **schmutzigen Baum überhaupt
|
||||||
|
nicht**. Ein abgedrifteter Checkout antwortet also zwar richtig, parst aber bei jeder Anfrage
|
||||||
|
neu — und stempelt jede Antwort mit `"commit": null`, weil sie keiner Revision entspricht.
|
||||||
|
|
||||||
|
## Verifikation
|
||||||
|
|
||||||
|
Läuft es? Der schnellste Test ohne Client — startet den Server über stdio, listet die Tools und
|
||||||
|
stellt eine Frage:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd tools && WIKI_TRACE=0 .venv/bin/python - <<'EOF'
|
||||||
|
import asyncio, os
|
||||||
|
from mcp import ClientSession, StdioServerParameters
|
||||||
|
from mcp.client.stdio import stdio_client
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
params = StdioServerParameters(
|
||||||
|
command=".venv/bin/python", args=["-m", "chemenu.mcp"],
|
||||||
|
env={"WIKI_TRACE": "0", "PATH": os.environ["PATH"]},
|
||||||
|
)
|
||||||
|
async with stdio_client(params) as (r, w):
|
||||||
|
async with ClientSession(r, w) as s:
|
||||||
|
await s.initialize()
|
||||||
|
print("Tools:", [t.name for t in (await s.list_tools()).tools])
|
||||||
|
out = await s.call_tool("status", {})
|
||||||
|
d = getattr(out, "structuredContent", None) or out.structured_content
|
||||||
|
print("Seiten:", d["pages"], "| Commit:", d["commit"])
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Erwartete Ausgabe, sinngemäß:
|
||||||
|
|
||||||
|
```
|
||||||
|
Tools: ['search', 'types', 'describe_type', 'lint', 'status']
|
||||||
|
Seiten: 176 | Commit: 576df2cdddc96614a7e6641e562022d52112d411
|
||||||
|
```
|
||||||
|
|
||||||
|
Gegen die CLI gegenprüfen — beide müssen dieselbe Antwort geben:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tools/wikitool search "<begriff>" --json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**`ERROR Telemetry is on and would write into the served checkout`** — erwartetes Verhalten,
|
||||||
|
kein Fehler in der Installation. `WIKI_TRACE=0` setzen oder `WIKI_TRACE_DIR` aus dem Korpus
|
||||||
|
heraus zeigen lassen (Schritt 2).
|
||||||
|
|
||||||
|
**`ModuleNotFoundError: No module named 'mcp'`** — Schritt 1 fehlt, oder der Client startet ein
|
||||||
|
anderes Python als das der Instanz. Im Client den absoluten Pfad auf `tools/.venv/bin/python`
|
||||||
|
setzen.
|
||||||
|
|
||||||
|
**`"commit": null` in jeder Antwort** — der bediente Baum hat uncommittete Änderungen. Entweder
|
||||||
|
läuft der Sync nicht, oder etwas schreibt in den Korpus, das dort nichts zu suchen hat. Der
|
||||||
|
Server selbst schreibt nie; ein Test prüft das, indem er alle fünf Tools aufruft und Dateibaum,
|
||||||
|
`HEAD` und `git status --porcelain` vorher/nachher vergleicht.
|
||||||
|
|
||||||
|
**`commit` nennt eine alte Revision** — der Sync aus Schritt 6 läuft nicht.
|
||||||
|
|
||||||
|
**Der Server antwortet anders als `wikitool`** — das ist ein Defekt, keine
|
||||||
|
Konfigurationsdifferenz: beide gehen durch dieselben Funktionen, und ein Golden-Test hält sie
|
||||||
|
zusammen. Zuerst prüfen, ob beide auf denselben Root zeigen; `CHEMENU_ROOT` ist leicht für einen
|
||||||
|
von beiden gesetzt und für den anderen nicht.
|
||||||
|
|
||||||
|
**Von außen nicht erreichbar** — ohne `--host 0.0.0.0` bindet der Server auf Loopback
|
||||||
|
(Schritt 4). Wenn er dann erreichbar ist, aber jeder Aufruf `401` bekommt, arbeitet die
|
||||||
|
Middleware aus Schritt 5 korrekt und das Token stimmt nicht.
|
||||||
|
|
||||||
|
## Was hier bewusst nicht steht
|
||||||
|
|
||||||
|
Deployment — Cluster, Ingress-Hosts, Secret-Store, FluxCD-Quelle. Das ist private Infrastruktur
|
||||||
|
und dieses Repo ist öffentlich.
|
||||||
|
|
||||||
|
Ein **Container-Image** für den Betrieb gibt es noch nicht; es ist als eigenes Vorhaben erfasst,
|
||||||
|
mitsamt den Entscheidungen, die dafür noch offen sind (Korpus im Image oder als Volume, wer den
|
||||||
|
Sync ausführt, Basis-Image, Healthcheck):
|
||||||
|
<https://gitea.nehmer.net/torben/chemenu/issues/37>. Bis dahin ist der Weg oben — venv,
|
||||||
|
`python -m chemenu.mcp`, Proxy davor — der vollständige.
|
||||||
@@ -7,6 +7,10 @@ Repo als Upstream** aufsetzen. Der agent-seitige Ablauf steckt in `instructions/
|
|||||||
nur die menschlichen Teile - für die vollständige Kommandoreferenz siehe
|
nur die menschlichen Teile - für die vollständige Kommandoreferenz siehe
|
||||||
[tools/CONTRACT.md](tools/CONTRACT.md).
|
[tools/CONTRACT.md](tools/CONTRACT.md).
|
||||||
|
|
||||||
|
Den optionalen **MCP-Leseserver** installiert und betreibt
|
||||||
|
[INSTALL-MCP.md](INSTALL-MCP.md): derselbe Korpus, lesend, für einen Konsumenten, der kein
|
||||||
|
Terminal auf dieser Maschine ist.
|
||||||
|
|
||||||
## Voraussetzungen
|
## Voraussetzungen
|
||||||
|
|
||||||
- Python 3.11 oder neuer
|
- Python 3.11 oder neuer
|
||||||
@@ -223,6 +227,8 @@ behält Schema und Shape.
|
|||||||
| `WIKITOOL_SESSION_ID` | Scopt das Iteration-Budget-Gate auf eine Aufgabe statt auf ein Terminal | Parent-Process-ID (siehe [instructions/session-setup.md](instructions/session-setup.md)) |
|
| `WIKITOOL_SESSION_ID` | Scopt das Iteration-Budget-Gate auf eine Aufgabe statt auf ein Terminal | Parent-Process-ID (siehe [instructions/session-setup.md](instructions/session-setup.md)) |
|
||||||
| `WIKITOOL_UPDATE_URL` | Release-Feed, den `version check` abfragt | Wert aus `.wikitool-release.json`, sonst der Feed der Ursprungs-Instanz |
|
| `WIKITOOL_UPDATE_URL` | Release-Feed, den `version check` abfragt | Wert aus `.wikitool-release.json`, sonst der Feed der Ursprungs-Instanz |
|
||||||
| `WIKITOOL_UPDATE_TOKEN` | Gitea-Token für den Release-Feed | keiner - gegen `torben/chemenu` nicht nötig, nur für einen privaten Fork (siehe unten) |
|
| `WIKITOOL_UPDATE_TOKEN` | Gitea-Token für den Release-Feed | keiner - gegen `torben/chemenu` nicht nötig, nur für einen privaten Fork (siehe unten) |
|
||||||
|
| `CHEMENU_ROOT` | Auf welchen Korpus das Paket zeigt - für einen Aufrufer, der nicht im Checkout selbst liegt | der Checkout, in dem das Paket liegt (`tools/wikitool` verhält sich ohne die Variable unverändert) |
|
||||||
|
| `WIKI_TRACE` / `WIKI_TRACE_DIR` | Telemetrie abschalten bzw. aus dem Arbeitsbaum heraus umlenken | an, nach `reports/telemetry/` - der MCP-Server verweigert damit den Start, siehe [INSTALL-MCP.md](INSTALL-MCP.md) |
|
||||||
|
|
||||||
**Gegen das Ursprungs-Repo braucht es kein Token.** `torben/chemenu` ist öffentlich lesbar;
|
**Gegen das Ursprungs-Repo braucht es kein Token.** `torben/chemenu` ist öffentlich lesbar;
|
||||||
`version check` und der Download in Weg A funktionieren ohne Konfiguration.
|
`version check` und der Download in Weg A funktionieren ohne Konfiguration.
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ chemenu/
|
|||||||
├── CLAUDE.md # Claude Code only: imports AGENTS.md/USER.md/SOUL.md/ENVIRONMENT.md + its Claude-Code-only instructions. No rules of its own
|
├── CLAUDE.md # Claude Code only: imports AGENTS.md/USER.md/SOUL.md/ENVIRONMENT.md + its Claude-Code-only instructions. No rules of its own
|
||||||
├── README.md # This file: human-readable overview of the whole repo
|
├── README.md # This file: human-readable overview of the whole repo
|
||||||
├── INSTALL.md # Human-readable setup: new instance vs. cloning this one
|
├── INSTALL.md # Human-readable setup: new instance vs. cloning this one
|
||||||
|
├── INSTALL-MCP.md # Human-readable setup for the optional MCP read server
|
||||||
├── EVALS.md # Human-readable overview of telemetry and evaluation
|
├── EVALS.md # Human-readable overview of telemetry and evaluation
|
||||||
├── CHANGES.md # Changelog for the stack itself
|
├── CHANGES.md # Changelog for the stack itself
|
||||||
├── USER.md # Who operates this instance - context, never instructions
|
├── USER.md # Who operates this instance - context, never instructions
|
||||||
@@ -363,8 +364,11 @@ WIKI_TRACE=0 tools/.venv/bin/python -m chemenu.mcp \
|
|||||||
```
|
```
|
||||||
|
|
||||||
The dependency is deliberately not in `requirements.txt`: an instance that only uses the CLI
|
The dependency is deliberately not in `requirements.txt`: an instance that only uses the CLI
|
||||||
should not have to install a web stack to do it. Running it, keeping its checkout current, and
|
should not have to install a web stack to do it.
|
||||||
where authentication belongs (in front of the process, not in it) are in
|
|
||||||
|
Installing it, wiring a client to it, and putting authentication in front of it:
|
||||||
|
[`INSTALL-MCP.md`](INSTALL-MCP.md), for humans. The agent-side operating procedure - keeping the
|
||||||
|
checkout current, and what a stale answer looks like - is
|
||||||
[`instructions/mcp-read-server.md`](instructions/mcp-read-server.md).
|
[`instructions/mcp-read-server.md`](instructions/mcp-read-server.md).
|
||||||
|
|
||||||
### Obsidian
|
### Obsidian
|
||||||
|
|||||||
@@ -64,8 +64,14 @@ DIST_TEMPLATES_DIR = Path(__file__).resolve().parent.parent / "dist_templates"
|
|||||||
# and does not load `AGENTS.md`, so it ships for the same reason
|
# and does not load `AGENTS.md`, so it ships for the same reason
|
||||||
# `.claude/settings.json` does - a distributed instance running that harness
|
# `.claude/settings.json` does - a distributed instance running that harness
|
||||||
# would otherwise start every session without the control plane.
|
# would otherwise start every session without the control plane.
|
||||||
|
#
|
||||||
|
# `INSTALL-MCP.md` ships beside `INSTALL.md` and for the same reason: the MCP
|
||||||
|
# read server is part of what an instance *has*, even though its dependency is
|
||||||
|
# optional. A distribution whose server is present but undocumented is one
|
||||||
|
# whose operator finds the module by reading the source.
|
||||||
ROOT_FILES = (
|
ROOT_FILES = (
|
||||||
"AGENTS.md", "CLAUDE.md", "README.md", "EVALS.md", "INSTALL.md", ".gitignore", "VERSION",
|
"AGENTS.md", "CLAUDE.md", "README.md", "EVALS.md", "INSTALL.md", "INSTALL-MCP.md",
|
||||||
|
".gitignore", "VERSION",
|
||||||
*config.LICENSE_FILES,
|
*config.LICENSE_FILES,
|
||||||
*config.PERSONALIZATION_TEMPLATES,
|
*config.PERSONALIZATION_TEMPLATES,
|
||||||
config.ENVIRONMENT_TEMPLATE,
|
config.ENVIRONMENT_TEMPLATE,
|
||||||
|
|||||||
Reference in New Issue
Block a user