Der ank MCP-Server

Jedes Verb der CLI als Tool, für einen Client ohne Shell. Eine Zeile, um ihn in Claude Code einzutragen:

claude mcp add ank -- ank mcp --repo /path/to/your/repo

Was ank mcp ist

ank mcp ist ein Verb des einen Binaries, das jeder Installationsweg ablegt. Es gibt keine zweite Datei zu holen: Was die CLI dispatcht, liefert der Server aus, weil es dasselbe Binary ist.

Er spricht JSON-RPC über stdio, und der Client startet ihn. Du startest ihn also nicht, du konfigurierst ihn: ein Befehl, seine Argumente und das Repository, für das er spricht.

Einen Client konfigurieren

Der Eintrag ist in allen drei Clients dasselbe JSON. Nur die Datei, in die er gehört, ändert sich.

.mcp.json · der Eintrag
{
  "mcpServers": {
    "ank": {
      "command": "ank",
      "args": ["mcp", "--repo", "/path/to/your/repo"]
    }
  }
}

Wohin er gehört

Claude Code
.mcp.json im Root des Repositorys, die Form, die mit dem Tree reist und jeden erreicht, der ihn klont. Oder die Zeile claude mcp add oben, die den Eintrag für dich schreibt.
Claude Desktop
claude_desktop_config.json, unter ~/Library/Application Support/Claude/ auf macOS und %APPDATA%\Claude\ auf Windows.
Cursor
.cursor/mcp.json neben dem Repository, oder ~/.cursor/mcp.json für alle Projekte auf einmal.

Der Befehl ist ank, und mcp sein erstes Argument

Releases bis 0.6.0 haben ein zweites Binary namens ank-mcp abgelegt. Kein Weg legt es mehr ab, eine Konfiguration, die es noch nennt, bekommt also command not found. Das ist die eine Zeile, die du ändern musst.

Schreib immer --repo

Ein Client startet den Server in dem Verzeichnis, in dem er gerade ist, und ohne --repo nimmt der Server dieses Verzeichnis. Das Versagen ist kein Fehler: Es ist ein Prozess, der still für einen Corpus spricht, den niemand gemeint hat, oder für keinen. Ein Pfad ohne .ank/ wird beim Start abgelehnt, wo ein Mensch es sieht.

ank mcp
ank mcp --repo /tmp
error[1]: no .ank/ found from /tmp
  -> ank init

Jedes Verb, ein Tool

Die Tools werden aus derselben Tabelle generiert, aus der das Binary dispatcht und die ank help --json beschreibt. Keine kuratierte Auswahl: Die beiden Oberflächen können sich nicht darüber uneinig sein, was existiert.

  • ank_context
  • ank_claim
  • ank_show
  • ank_log
  • ank_done
  • ank_release
  • ank_new
  • ank_review
  • ank_accept
  • ank_read
  • ank_close
  • ank_amend
  • ank_attest
  • ank_find
  • ank_status
  • ank_graph
  • ank_scope
  • ank_tui
  • ank_mcp
  • ank_watch
  • ank_edit
  • ank_check
  • ank_migrate
  • ank_archive
  • ank_config
  • ank_init
  • ank_skills
  • ank_update
  • ank_help
  • Benannt ank_<verb>

    Ein nacktes context würde mit jedem anderen Server kollidieren, den ein Client geladen hat. Die Zusammenfassung wird zur Beschreibung, die Flags werden zum Input-Schema, und Positionsargumente kommen als arguments, ein Array von Strings.

  • Die Antwort der CLI, mit Exit-Code

    Ein Aufruf liefert das Dokument, das --json liefert, mit exitCode daneben. Eine Ablehnung ist die Ablehnung der CLI, samt Hinweis, zurückgegeben als Ergebnis mit isError. Ein JSON-RPC-Fehler heißt, die Anfrage war falsch; isError heißt, der Corpus hat Nein gesagt.

  • Kein Claim, den die CLI nicht nehmen würde

    Jeder Claim landet in refs/ank/claims/ dieses Repositorys, mit demselben Compare-and-Swap. Der Server hält nichts im Namen eines Clients und schreibt als ank-mcp/<version>, außer ANK_AGENT nennt eine Identität.

ein Aufruf, den der Corpus ablehnt
--> {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"ank_show","arguments":{"arguments":["TASK-9999"]}}}

<-- {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"error[2]: entity not found: TASK-9999\n  -> ank find TASK-9999"}],"isError":true,"exitCode":2,"stderr":"error[2]: entity not found: TASK-9999\n  -> ank find TASK-9999"}}

Mehrere Repositorys, ein Server

Jedes Tool nimmt ein optionales Argument corpus: den Root-Commit, den ank status --json unter "corpus" ausgibt, nie einen Pfad. Deklariere jedes Repository einmal mit ank config --user corpora.<root> <path>, und die Client-Konfiguration ändert sich um kein Zeichen. Ein Server kann mehrere Corpora ansprechen; er führt ihre Claims nie zusammen.

ank_accept ist da wie jedes andere Verb und lehnt außerhalb des Default-Branches weiterhin ab. Eine Entscheidung zu ratifizieren bleibt ein menschlicher Akt.

MCP oder die CLI

Beide erreichen dieselben Verben und liefern dieselben Dokumente. Entscheide danach, was dein Client kann.

Dein Agent hat eine Shell

Nimm die CLI. npx skills add haksolot/ank gibt dem Agent die Skills, die ihm den Loop beibringen, und er ruft ank auf wie jeden anderen Befehl.

Dein Client hat keine Shell

Nimm ank mcp. Der Client sieht dieselben Verben als Tools, mit den Ablehnungen und Exit-Codes in jeder Beschreibung, und kann so lesen, was ein Aufruf ablehnen wird, bevor er ihn macht.

Du baust etwas, das einen Corpus anzeigt? Polle ank_status und ank_find. ank_context und ank_show verlängern einen Claim, und ank_check entfernt veraltete Refs, schreibt also.

ank installieren

Zwei Befehle. Linux, macOS und Windows, mit git 2.34 oder neuer.

npm install -g @haksolot/ank
npx skills add haksolot/ank