Anchor MCP
Anchor MCP
Plan de implementación para un sidecar MCP pequeño que expone herramientas seguras de Anchor Notes a ChatGPT a través de un cliente de túnel que se ejecuta en la misma pila de Docker Compose que Anchor.
Base de investigación: repositorio upstream de Anchor ZhFahim/anchor, rama predeterminada main, inspeccionado el 2026-08-20. Anchor es un backend de Nest.js con endpoints REST autenticados bajo /api/*.
Objetivo
Ejecutar un servidor MCP junto a Anchor para que asistentes externos puedan listar, buscar, leer, crear, actualizar, importar y adjuntar archivos a las notas de Anchor sin exponer la base de datos de Anchor ni su API privada directamente.
Related MCP server: NotesBridge
Estado actual
El primer hito está implementado:
Endpoint MCP HTTP transmisible por stream en
POST /mcp.Endpoint de salud en
GET /healthz.Herramientas de solo lectura de Anchor:
anchor_list_notes,anchor_search_notes,anchor_get_note,anchor_list_tags,anchor_list_attachments.Guarda MCP opcional con portador usando
ANCHOR_MCP_TOKEN.Las llamadas a la API de Anchor usan
ANCHOR_TOKENyANCHOR_BASE_URL.Se incluye el Dockerfile.
Las herramientas de escritura no están implementadas intencionalmente todavía.
Desarrollo
En NixOS, usa nix-shell para los comandos de Node/npm:
nix-shell -p nodejs --run 'npm install'
nix-shell -p nodejs --run 'npm run typecheck'
nix-shell -p nodejs --run 'npm run build'Ejecutar localmente:
ANCHOR_BASE_URL=https://anchor.cri.su \
ANCHOR_TOKEN=... \
ANCHOR_MCP_TOKEN=... \
nix-shell -p nodejs --run 'npm run dev'El endpoint MCP es http://localhost:8000/mcp. Si ANCHOR_MCP_TOKEN está definido, los llamadores deben enviar Authorization: Bearer <token>.
Modelo de despliegue
La pila prevista tiene tres servicios:
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-mcpEl servidor MCP solo debe ser accesible en la red de Docker. El cliente de túnel es el único puente externo.
Superficie confirmada de la API de Anchor
Todos los endpoints siguientes están protegidos por el AuthGuard de Anchor y esperan Authorization: Bearer <token>. La guarda acepta tokens de Anchor que se resuelven a un usuario activo.
Notas:
POST /api/notesGET /api/notes?search=<query>&tagId=<tagId>&limit=<limit>GET /api/notes/:idPATCH /api/notes/:idDELETE /api/notes/:idDELETE /api/notes/:id/permanentPATCH /api/notes/:id/restoreGET /api/notes/trashGET /api/notes/archivePOST /api/notes/bulk/deletePOST /api/notes/bulk/archivePOST /api/notes/bulk/pinPOST /api/notes/bulk/tags
Etiquetas:
POST /api/tagsGET /api/tagsGET /api/tags/:idGET /api/tags/:id/notesPATCH /api/tags/:idDELETE /api/tags/:id
Adjuntos:
POST /api/notes/:noteId/attachmentsGET /api/notes/:noteId/attachmentsGET /api/notes/:noteId/attachments/:idDELETE /api/notes/:noteId/attachments/:idPATCH /api/notes/:noteId/attachments/reorder
Importación/exportación:
POST /api/import/notesPOST /api/import/notes/:noteId/attachmentsGET /api/export
API de sincronización:
POST /api/syncGET /api/sync/eventscomo eventos enviados por el servidor
Compartición:
POST /api/notes/:id/sharesGET /api/notes/:id/sharesPATCH /api/notes/:id/shares/:shareIdDELETE /api/notes/:id/shares/:shareId
El servidor MCP debería comenzar con endpoints normales de notas/etiquetas/adjuntos/importación. La API de sincronización es útil para clientes offline conscientes de conflictos, pero un sidecar MCP puede omitirla inicialmente.
Formas de datos
Cuerpo de creación de nota:
{
"title": "string",
"content": "optional string",
"isPinned": false,
"isArchived": false,
"background": "optional string",
"tagIds": ["tag-id"]
}El cuerpo de actualización de nota es un cuerpo de creación parcial más bloqueo optimista opcional:
{
"title": "optional string",
"content": "optional string",
"isPinned": false,
"isArchived": false,
"background": "optional string",
"tagIds": ["tag-id"],
"baseVersion": 1
}Anchor devuelve notas transformadas con estos campos importantes:
{
"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": []
}Cuerpo de importación de notas:
{
"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
}Forma del resultado de importación:
{
"results": [
{
"ref": "external reference",
"status": "created | skipped | remapped | failed",
"noteId": "uuid",
"warning": "optional string",
"error": "optional string"
}
],
"tags": { "created": 0, "reused": 0 }
}Formas de carga de adjuntos:
Carga de nota normal: campo
filemultiparte haciaPOST /api/notes/:noteId/attachments.Carga de adjunto de importación: campo
filemultiparte más campo de formulariopositionhaciaPOST /api/import/notes/:noteId/attachments.La respuesta de adjunto incluye
id,noteId,type,originalFilename,mimeType,fileSize,position,uploadedByUserIdycreatedAt.
Límites y validación
Límite de listado de notas:
GET /api/noteslimitalimita1..200.
Límites de operaciones masivas:
noteIds: máximo 200.tagIds: máximo 50.
Límites de importación:
Notas por lote: 50.
Longitud del contenido Delta serializado: 1.000.000 bytes/caracteres.
Longitud del título: 1000.
Etiquetas por nota: 50.
Etiquetas por lote de importación: 500.
Longitud del nombre de etiqueta: 100.
Límites de adjuntos:
Tamaño máximo de archivo: 50 MB.
Imágenes permitidas:
image/jpeg,image/png,image/webp,image/gif.Audio permitido:
audio/mpeg,audio/wav,audio/mp4,audio/x-m4a,audio/ogg,audio/aac,audio/webm.PDF, JSON, ZIP y
application/octet-streamgenérico son rechazados por la fuente actual.
Identificadores de fondo permitidos por la importación:
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.
Formato de contenido
Anchor almacena el content de la nota como una cadena. El trabajo de importación existente confirma que debe ser JSON de Quill Delta serializado para la importación de texto enriquecido.
El servidor MCP debería exponer herramientas amigables con Markdown y convertir Markdown a Quill Delta internamente. También puede exponer herramientas nativas de Delta para modo experto más adelante.
Política de conversión recomendada:
anchor_create_noteacepta Markdown, lo convierte a Delta y llama aPOST /api/notes.anchor_update_noteacepta Markdown, lo convierte a Delta y llama aPATCH /api/notes/:idconbaseVersionopcional.anchor_import_notesacepta Markdown o Delta nativo, procesa en lotes mediantePOST /api/import/notes.anchor_get_notedevuelve el contenido bruto más una proyección de texto/Markdown de mejor esfuerzo para la legibilidad del LLM.
Modelo de autenticación
La fuente de Anchor usa extracción de token de portador desde Authorization: Bearer <token>. El sidecar MCP debería mantener por tanto dos capas de autenticación:
ANCHOR_TOKEN: token usado poranchor-mcpal llamar a Anchor.ANCHOR_MCP_TOKEN: token esperado del cliente de túnel antes de atender cualquier solicitud MCP.
El servidor MCP nunca debe reenviar tokens arbitrarios del llamador a Anchor.
Referencias de la fuente
Archivos principales inspeccionados upstream:
server/src/notes/controllers/notes.controller.tsserver/src/notes/controllers/note-attachments.controller.tsserver/src/notes/controllers/note-shares.controller.tsserver/src/tags/tags.controller.tsserver/src/import-export/import.controller.tsserver/src/import-export/export.controller.tsserver/src/sync/sync.controller.tsserver/src/sync/sync-events.controller.tsserver/src/notes/dto/create-note.dto.tsserver/src/notes/dto/update-note.dto.tsserver/src/import-export/dto/import-notes.dto.tsserver/src/import-export/dto/import-attachment.dto.tsserver/src/notes/constants/notes.constants.tsserver/src/import-export/constants/import.constants.tsserver/src/notes/utils/note-transformer.util.tsserver/src/notes/utils/attachment-storage.util.ts
Herramientas MCP
Herramientas de lectura de la fase 1:
anchor_list_notes(limit, offset)anchor_search_notes(query, limit)anchor_get_note(note_id)anchor_list_tags()anchor_list_attachments(note_id)
Detalles de las herramientas implementadas:
anchor_list_notesadmitelimit,offset,include_contentytag_id. Dado que Anchor solo expone listado basado en límite,offset + limitdebe ser como máximo 200.anchor_search_notesadmitequery,limit,include_contentytag_id.anchor_get_noteadmitenote_idyinclude_content.anchor_list_tagsno recibe entrada.anchor_list_attachmentsdevuelve solo metadatos y no descarga los bytes de los adjuntos.
Herramientas de escritura de la fase 2:
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)
Herramientas de gestión de la fase 3:
anchor_archive_notes(note_ids)anchor_pin_notes(note_ids, is_pinned)anchor_add_tags(note_ids, tag_ids)anchor_export()si el cliente de túnel puede manejar un archivo transmitido por stream.
Evitar o restringir herramientas destructivas:
anchor_delete_note(note_id, confirm)se asigna a eliminación suave y debe requerirconfirm=true.anchor_permanent_delete_note(note_id, confirm)debe omitirse inicialmente.anchor_delete_tag(tag_id, confirm)debe omitirse inicialmente.No exponer una herramienta proxy HTTP arbitraria en bruto.
Seguridad
Almacenar
ANCHOR_TOKENsolo en el entorno de la pila Docker o en.env; no incrustarlo en la imagen.Añadir un
ANCHOR_MCP_TOKENseparado para las llamadas del cliente de túnel aanchor-mcp.Vincular el servidor MCP solo a la red del contenedor; no añadir etiquetas de Traefik a menos que se exponga intencionalmente.
Mantener las herramientas estrechas y tipadas. No permitir que los llamadores elijan rutas arbitrarias de la API de Anchor.
Registrar metadatos de solicitudes, no contenido de notas ni tokens.
Predeterminar herramientas de solo lectura hasta que se verifique la ruta de autenticación del túnel.
Exigir
confirm=trueexplícito para eliminación suave y acciones destructivas masivas.Rechazar la eliminación permanente a menos que esté presente un ajuste separado
ENABLE_DANGEROUS_TOOLS=true.
Fases de implementación
Crear un servidor HTTP MCP mínimo en TypeScript.
Añadir configuración desde el entorno:
ANCHOR_BASE_URL,ANCHOR_TOKEN,ANCHOR_MCP_TOKEN, host/puerto de vinculación.Implementar
/healthzpara diagnóstico de Docker y túnel.Implementar un cliente pequeño de la API de Anchor con métodos tipados y sin vía de escape de rutas arbitrarias.
Implementar
anchor_list_notes,anchor_search_notes,anchor_get_noteyanchor_list_tags.Añadir modelado de respuestas que elimine campos pesados a menos que se soliciten explícitamente.
Implementar ayudantes de conversión de Markdown a Delta y pruebas.
Implementar creación/actualización con bloqueo optimista opcional mediante
baseVersion.Implementar procesamiento por lotes de importación con los límites de importación conocidos.
Implementar carga de adjuntos solo para imágenes/audio permitidos.
Añadir Dockerfile y ejemplo de Compose incluido el marcador de posición del cliente de túnel.
Añadir pruebas con respuestas simuladas de Anchor y fallos de validación.
Añadir documentación operativa para rotar tokens y conectar el cliente de túnel de ChatGPT.
Preguntas abiertas
Imagen exacta del cliente de túnel, variables de entorno y formato del encabezado de autenticación.
Si Anchor puede configurarse o parchearse para permitir PDF y otros tipos de archivo.
Si el contenido de las notas debe aceptarse como Markdown y convertirse a Quill Delta, o si el MCP debe exponer el formato de contenido nativo de Anchor directamente.
Si el cliente de túnel puede pasar cargas binarias lo suficientemente bien para la carga de adjuntos y la descarga de exportaciones.
Si
offsetdebe simularse en el lado del cliente porqueGET /api/notessolo exponelimit, no paginación por desplazamiento.
Primer hito recomendado
Construir un servidor MCP de solo lectura con anchor_list_notes, anchor_search_notes, anchor_get_note y anchor_list_tags. Desplegarlo de forma privada en la pila de Anchor detrás del cliente de túnel. Añadir creación/actualización/importación solo después de verificar la ruta de lectura y el modelo de autenticación.
This server cannot be installed
Maintenance
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
- AlicenseNot gradedqualityCmaintenanceMCP server for AI agents to read, write, and organize notes in a local-first, human-in-the-loop note-taking app.01MIT
- AlicenseNot gradedqualityAmaintenanceMCP server enabling ChatGPT to search, read, and write Apple Notes via a local Mac agent with a privacy-preserving relay.MIT
- AlicenseNot gradedqualityAmaintenanceA 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
- AlicenseNot gradedqualityBmaintenanceSelf-hosted MCP server for private Obsidian vaults on GitHub, exposing tools to search, read, write, and analyze Markdown notes and their link graph.MIT
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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