Skip to main content
Glama
llego
by llego

Anchor MCP

Implementierungsplan für einen kleinen MCP-Sidecar, der sichere Anchor-Notes-Tools über einen Tunnel-Client, der im selben Docker-Compose-Stack wie Anchor läuft, für ChatGPT bereitstellt.

Forschungsbasis: Upstream-Repository ZhFahim/anchor von Anchor, Standard-Branch main, geprüft am 20.08.2026. Anchor ist ein Nest.js-Backend mit authentifizierten REST-Endpunkten unter /api/*.

Ziel

Einen MCP-Server neben Anchor betreiben, damit externe Assistenten Anchor-Notizen auflisten, durchsuchen, lesen, erstellen, aktualisieren, importieren und Dateien anhängen können, ohne die Anchor-Datenbank oder die private API direkt offenzulegen.

Related MCP server: NotesBridge

Aktueller Stand

Der erste Meilenstein ist umgesetzt:

  • Streambarer HTTP-MCP-Endpunkt unter POST /mcp.

  • Health-Endpunkt unter GET /healthz.

  • Schreibgeschützte Anchor-Tools: anchor_list_notes, anchor_search_notes, anchor_get_note, anchor_list_tags, anchor_list_attachments.

  • Optionaler MCP-Bearer-Schutz mit ANCHOR_MCP_TOKEN.

  • Anchor-API-Aufrufe verwenden ANCHOR_TOKEN und ANCHOR_BASE_URL.

  • Dockerfile ist enthalten.

Schreib-Tools sind bewusst noch nicht implementiert.

Entwicklung

Unter NixOS nix-shell für Node/npm-Befehle verwenden:

nix-shell -p nodejs --run 'npm install'
nix-shell -p nodejs --run 'npm run typecheck'
nix-shell -p nodejs --run 'npm run build'

Lokal ausführen:

ANCHOR_BASE_URL=https://anchor.cri.su \
ANCHOR_TOKEN=... \
ANCHOR_MCP_TOKEN=... \
nix-shell -p nodejs --run 'npm run dev'

Der MCP-Endpunkt ist http://localhost:8000/mcp. Wenn ANCHOR_MCP_TOKEN gesetzt ist, müssen Aufrufer Authorization: Bearer <token> senden.

Bereitstellungsmodell

Der vorgesehene Stack umfasst drei Dienste:

services:
  anchor:
    # Existing Anchor service.

  anchor-mcp:
    build: /path/to/anchor-mcp
    environment:
      ANCHOR_BASE_URL: http://anchor:3000
      ANCHOR_TOKEN: ${ANCHOR_TOKEN}
      ANCHOR_MCP_TOKEN: ${ANCHOR_MCP_TOKEN}
    expose:
      - "8000"
    depends_on:
      - anchor

  chatgpt-tunnel-client:
    # Outbound tunnel client.
    environment:
      MCP_TARGET_URL: http://anchor-mcp:8000/mcp
      MCP_TARGET_TOKEN: ${ANCHOR_MCP_TOKEN}
    depends_on:
      - anchor-mcp

Der MCP-Server sollte nur im Docker-Netzwerk erreichbar sein. Der Tunnel-Client ist die einzige externe Brücke.

Bestätigte Anchor-API-Oberfläche

Alle unten aufgeführten Endpunkte sind durch den AuthGuard von Anchor geschützt und erwarten Authorization: Bearer <token>. Der Guard akzeptiert Anchor-Tokens, die zu einem aktiven Benutzer aufgelöst werden.

Notizen:

  • POST /api/notes

  • GET /api/notes?search=<query>&tagId=<tagId>&limit=<limit>

  • GET /api/notes/:id

  • PATCH /api/notes/:id

  • DELETE /api/notes/:id

  • DELETE /api/notes/:id/permanent

  • PATCH /api/notes/:id/restore

  • GET /api/notes/trash

  • GET /api/notes/archive

  • POST /api/notes/bulk/delete

  • POST /api/notes/bulk/archive

  • POST /api/notes/bulk/pin

  • POST /api/notes/bulk/tags

Tags:

  • POST /api/tags

  • GET /api/tags

  • GET /api/tags/:id

  • GET /api/tags/:id/notes

  • PATCH /api/tags/:id

  • DELETE /api/tags/:id

Anhänge:

  • POST /api/notes/:noteId/attachments

  • GET /api/notes/:noteId/attachments

  • GET /api/notes/:noteId/attachments/:id

  • DELETE /api/notes/:noteId/attachments/:id

  • PATCH /api/notes/:noteId/attachments/reorder

Import/Export:

  • POST /api/import/notes

  • POST /api/import/notes/:noteId/attachments

  • GET /api/export

Sync-API:

  • POST /api/sync

  • GET /api/sync/events als Server-Sent Events

Freigabe:

  • POST /api/notes/:id/shares

  • GET /api/notes/:id/shares

  • PATCH /api/notes/:id/shares/:shareId

  • DELETE /api/notes/:id/shares/:shareId

Der MCP-Server sollte mit den normalen Notizen-/Tags-/Anhänge-/Import-Endpunkten starten. Die Sync-API ist für konfliktbewusste Offline-Clients nützlich, aber ein MCP-Sidecar kann sie zunächst auslassen.

Datenstrukturen

Body zum Erstellen einer Notiz:

{
  "title": "string",
  "content": "optional string",
  "isPinned": false,
  "isArchived": false,
  "background": "optional string",
  "tagIds": ["tag-id"]
}

Der Body zum Aktualisieren einer Notiz ist ein partieller Create-Body plus optionaler optimistischer Sperre:

{
  "title": "optional string",
  "content": "optional string",
  "isPinned": false,
  "isArchived": false,
  "background": "optional string",
  "tagIds": ["tag-id"],
  "baseVersion": 1
}

Anchor gibt transformierte Notizen mit diesen wichtigen Feldern zurück:

{
  "id": "uuid",
  "title": "string",
  "content": "string or null",
  "version": 1,
  "isPinned": false,
  "isArchived": false,
  "background": null,
  "state": "active",
  "createdAt": "iso timestamp",
  "updatedAt": "iso timestamp",
  "userId": "uuid",
  "tagIds": ["tag-id"],
  "permission": "owner",
  "attachmentCount": 0,
  "imagePreviewIds": []
}

Body zum Importieren von Notizen:

{
  "notes": [
    {
      "ref": "external stable reference, max 256 chars",
      "id": "optional uuid",
      "title": "string",
      "content": "stringified Quill Delta JSON",
      "isPinned": false,
      "isArchived": false,
      "isTrashed": false,
      "background": "optional background id",
      "tagNames": ["tag name"],
      "createdAt": "iso timestamp",
      "updatedAt": "iso timestamp"
    }
  ],
  "tags": [{ "name": "tag", "color": "#8B5CF6" }],
  "skipExisting": true
}

Struktur des Importergebnisses:

{
  "results": [
    {
      "ref": "external reference",
      "status": "created | skipped | remapped | failed",
      "noteId": "uuid",
      "warning": "optional string",
      "error": "optional string"
    }
  ],
  "tags": { "created": 0, "reused": 0 }
}

Strukturen für Anhänge-Uploads:

  • Normaler Notiz-Upload: Multipart-Feld file an POST /api/notes/:noteId/attachments.

  • Import-Anhänge-Upload: Multipart-Feld file plus Formularfeld position an POST /api/import/notes/:noteId/attachments.

  • Die Anhänge-Antwort enthält id, noteId, type, originalFilename, mimeType, fileSize, position, uploadedByUserId und createdAt.

Grenzen und Validierung

Grenze für Notizliste:

  • GET /api/notes begrenzt limit auf 1..200.

Bulk-Grenzen:

  • noteIds: maximal 200.

  • tagIds: maximal 50.

Import-Grenzen:

  • Notizen pro Batch: 50.

  • Länge des stringifizierten Delta-Inhalts: 1.000.000 Bytes/Zeichen.

  • Titellänge: 1000.

  • Tags pro Notiz: 50.

  • Tags pro Import-Batch: 500.

  • Tag-Namenslänge: 100.

Anhänge-Grenzen:

  • Maximale Dateigröße: 50 MB.

  • Erlaubte Bilder: image/jpeg, image/png, image/webp, image/gif.

  • Erlaubte Audiodateien: audio/mpeg, audio/wav, audio/mp4, audio/x-m4a, audio/ogg, audio/aac, audio/webm.

  • PDFs, JSON, ZIP und generisches application/octet-stream werden von der aktuellen Quelle abgelehnt.

Von Import erlaubte Hintergrund-IDs:

  • color_red, color_orange, color_yellow, color_green, color_teal, color_blue, color_dark_blue, color_purple, color_pink, color_brown.

  • pattern_dots, pattern_grid, pattern_lines, pattern_waves, pattern_groceries, pattern_music, pattern_travel, pattern_code.

Inhaltsformat

Anchor speichert den Notiz-content als String. Vorhandene Importarbeit bestätigt, dass dies für Rich-Text-Import stringifiziertes Quill-Delta-JSON sein sollte.

Der MCP-Server sollte Markdown-freundliche Tools bereitstellen und Markdown intern in Quill Delta konvertieren. Er kann später auch native Delta-Tools im Expertenmodus bereitstellen.

Empfohlene Konvertierungsrichtlinie:

  • anchor_create_note akzeptiert Markdown, konvertiert in Delta und ruft POST /api/notes auf.

  • anchor_update_note akzeptiert Markdown, konvertiert in Delta und ruft PATCH /api/notes/:id mit optionalem baseVersion auf.

  • anchor_import_notes akzeptiert Markdown oder natives Delta und verarbeitet Batches über POST /api/import/notes.

  • anchor_get_note gibt Rohinhalt plus eine Best-Effort-Text-/Markdown-Projektion für die LLM-Lesbarkeit zurück.

Authentifizierungsmodell

Die Anchor-Quelle verwendet die Extraktion von Bearer-Tokens aus Authorization: Bearer <token>. Der MCP-Sidecar sollte daher zwei Authentifizierungsebenen pflegen:

  • ANCHOR_TOKEN: Token, das anchor-mcp beim Aufruf von Anchor verwendet.

  • ANCHOR_MCP_TOKEN: Token, das vom Tunnel-Client erwartet wird, bevor eine MCP-Anfrage bedient wird.

Der MCP-Server sollte niemals beliebige Aufrufer-Tokens an Anchor weiterleiten.

Quellreferenzen

Primär geprüfte Dateien im Upstream:

  • server/src/notes/controllers/notes.controller.ts

  • server/src/notes/controllers/note-attachments.controller.ts

  • server/src/notes/controllers/note-shares.controller.ts

  • server/src/tags/tags.controller.ts

  • server/src/import-export/import.controller.ts

  • server/src/import-export/export.controller.ts

  • server/src/sync/sync.controller.ts

  • server/src/sync/sync-events.controller.ts

  • server/src/notes/dto/create-note.dto.ts

  • server/src/notes/dto/update-note.dto.ts

  • server/src/import-export/dto/import-notes.dto.ts

  • server/src/import-export/dto/import-attachment.dto.ts

  • server/src/notes/constants/notes.constants.ts

  • server/src/import-export/constants/import.constants.ts

  • server/src/notes/utils/note-transformer.util.ts

  • server/src/notes/utils/attachment-storage.util.ts

MCP-Tools

Phase-1-Lesetools:

  • anchor_list_notes(limit, offset)

  • anchor_search_notes(query, limit)

  • anchor_get_note(note_id)

  • anchor_list_tags()

  • anchor_list_attachments(note_id)

Details zu implementierten Tools:

  • anchor_list_notes unterstützt limit, offset, include_content und tag_id. Da Anchor nur limit-basierte Auflistung bereitstellt, muss offset + limit höchstens 200 betragen.

  • anchor_search_notes unterstützt query, limit, include_content und tag_id.

  • anchor_get_note unterstützt note_id und include_content.

  • anchor_list_tags nimmt keine Eingaben entgegen.

  • anchor_list_attachments gibt nur Metadaten zurück und lädt keine Anhänge-Bytes herunter.

Phase-2-Schreibtools:

  • anchor_create_note(title, markdown)

  • anchor_update_note(note_id, markdown, base_version)

  • anchor_import_notes(notes)

  • anchor_create_tag(name, color)

  • anchor_upload_attachment(note_id, file, filename, mime_type)

Phase-3-Verwaltungstools:

  • anchor_archive_notes(note_ids)

  • anchor_pin_notes(note_ids, is_pinned)

  • anchor_add_tags(note_ids, tag_ids)

  • anchor_export(), wenn der Tunnel-Client ein gestreamtes Archiv verarbeiten kann.

Destruktive Tools vermeiden oder absichern:

  • anchor_delete_note(note_id, confirm) bildet Soft Delete ab und sollte confirm=true erfordern.

  • anchor_permanent_delete_note(note_id, confirm) sollte zunächst weggelassen werden.

  • anchor_delete_tag(tag_id, confirm) sollte zunächst weggelassen werden.

  • Kein rohes, beliebiges HTTP-Proxy-Tool bereitstellen.

Sicherheit

  • ANCHOR_TOKEN nur in der Docker-Stack-Umgebung oder .env speichern; nicht in das Image einbrennen.

  • Ein separates ANCHOR_MCP_TOKEN für Aufrufe vom Tunnel-Client an anchor-mcp hinzufügen.

  • Den MCP-Server nur an das Container-Netzwerk binden; keine Traefik-Labels hinzufügen, außer es ist eine absichtliche Freigabe gewünscht.

  • Tools eng und typisiert halten. Aufrufern nicht erlauben, beliebige Anchor-API-Pfade zu wählen.

  • Anfrage-Metadaten protokollieren, nicht Notizinhalt oder Tokens.

  • Standardmäßig schreibgeschützte Tools verwenden, bis der Tunnel-Authentifizierungspfad verifiziert ist.

  • Explizites confirm=true für Soft-Delete und destruktive Bulk-Aktionen erfordern.

  • Dauerhaftes Löschen verweigern, es sei denn, eine separate Einstellung ENABLE_DANGEROUS_TOOLS=true ist vorhanden.

Implementierungsphasen

  1. Einen minimalen TypeScript-MCP-HTTP-Server erstellen.

  2. Konfiguration aus der Umgebung hinzufügen: ANCHOR_BASE_URL, ANCHOR_TOKEN, ANCHOR_MCP_TOKEN, Host/Port binden.

  3. /healthz für Docker- und Tunnel-Diagnose implementieren.

  4. Einen kleinen Anchor-API-Client mit typisierten Methoden und ohne beliebigen Pfad-Escape-Hatch implementieren.

  5. anchor_list_notes, anchor_search_notes, anchor_get_note und anchor_list_tags implementieren.

  6. Antwort-Formung hinzufügen, die schwere Felder entfernt, sofern nicht explizit angefordert.

  7. Hilfsfunktionen und Tests für die Markdown-zu-Delta-Konvertierung implementieren.

  8. Erstellen/Aktualisieren mit optionaler optimistischer Sperre über baseVersion implementieren.

  9. Import-Batching mit den bekannten Import-Grenzen implementieren.

  10. Anhänge-Upload nur für erlaubte Bilder/Audiodateien implementieren.

  11. Dockerfile und Compose-Beispiel inklusive Tunnel-Client-Platzhalter hinzufügen.

  12. Tests mit gemockten Anchor-Antworten und Validierungsfehlern hinzufügen.

  13. Betriebsdokumentation für Token-Rotation und Anbindung des ChatGPT-Tunnel-Clients hinzufügen.

Offene Fragen

  • Genaues Tunnel-Client-Image, Umgebungsvariablen und Auth-Header-Format.

  • Ob Anchor konfiguriert oder gepatcht werden kann, um PDFs und andere Dateitypen zuzulassen.

  • Ob Notizinhalt als Markdown akzeptiert und in Quill Delta konvertiert werden soll, oder ob der MCP Anchors natives Inhaltsformat direkt bereitstellen soll.

  • Ob der Tunnel-Client binäre Nutzlasten gut genug für Anhänge-Upload und Export-Download durchreichen kann.

  • Ob offset clientseitig simuliert werden sollte, da GET /api/notes nur limit, aber keine Offset-Paginierung bereitstellt.

Empfohlener erster Meilenstein

Einen schreibgeschützten MCP-Server mit anchor_list_notes, anchor_search_notes, anchor_get_note und anchor_list_tags erstellen. Privat im Anchor-Stack hinter dem Tunnel-Client bereitstellen. Erstellen/Aktualisieren/Import erst hinzufügen, nachdem der Lesepfad und das Authentifizierungsmodell verifiziert sind.

A
license - permissive license
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for AI agents to read, write, and organize notes in a local-first, human-in-the-loop note-taking app.
    0
    1
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    A secure multi-tenant MCP proxy that exposes 81 tools for full CRUD, search, chat, podcast, and command management on the OpenNotebook API, enabling natural language interaction with notebooks, notes, sources, and more.
    GPL 3.0

View all related MCP servers

Related MCP Connectors

  • Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.

  • Search your AI chat history (ChatGPT, Claude, Codex) from any MCP client. Remote, private, read-only

  • Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/llego/anchor-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server