Anchor MCP
Anchor MCP
План реализации небольшого MCP-сайдкара, который предоставляет безопасные инструменты Anchor Notes для ChatGPT через туннельный клиент, работающий в том же Docker Compose стеке, что и Anchor.
Основа исследования: вышестоящий репозиторий Anchor ZhFahim/anchor, ветка по умолчанию main, проверено 2026-08-20. Anchor — это бэкенд на Nest.js с аутентифицированными REST-эндпоинтами в /api/*.
Цель
Запустить MCP-сервер рядом с Anchor, чтобы внешние ассистенты могли просматривать, искать, читать, создавать, обновлять, импортировать заметки Anchor и прикреплять к ним файлы, не раскрывая напрямую базу данных Anchor или его приватный API.
Related MCP server: NotesBridge
Текущий статус
Первый этап реализован:
Эндпоинт Streamable HTTP MCP на
POST /mcp.Эндпоинт проверки состояния на
GET /healthz.Инструменты Anchor только для чтения:
anchor_list_notes,anchor_search_notes,anchor_get_note,anchor_list_tags,anchor_list_attachments.Опциональная MCP-защита через bearer-токен с использованием
ANCHOR_MCP_TOKEN.Вызовы Anchor API используют
ANCHOR_TOKENиANCHOR_BASE_URL.Dockerfile включён.
Инструменты записи намеренно пока не реализованы.
Разработка
На NixOS используйте nix-shell для команд 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'Локальный запуск:
ANCHOR_BASE_URL=https://anchor.cri.su \
ANCHOR_TOKEN=... \
ANCHOR_MCP_TOKEN=... \
nix-shell -p nodejs --run 'npm run dev'MCP-эндпоинт: http://localhost:8000/mcp. Если задан ANCHOR_MCP_TOKEN, вызывающие стороны должны отправлять Authorization: Bearer <token>.
Модель развёртывания
Предполагаемый стек состоит из трёх сервисов:
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-mcpMCP-сервер должен быть доступен только в Docker-сети. Туннельный клиент — единственный внешний мост.
Подтверждённая поверхность Anchor API
Все эндпоинты ниже защищены AuthGuard в Anchor и ожидают Authorization: Bearer <token>. Guard принимает токены Anchor, которые соответствуют активному пользователю.
Заметки:
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
Теги:
POST /api/tagsGET /api/tagsGET /api/tags/:idGET /api/tags/:id/notesPATCH /api/tags/:idDELETE /api/tags/:id
Вложения:
POST /api/notes/:noteId/attachmentsGET /api/notes/:noteId/attachmentsGET /api/notes/:noteId/attachments/:idDELETE /api/notes/:noteId/attachments/:idPATCH /api/notes/:noteId/attachments/reorder
Импорт/экспорт:
POST /api/import/notesPOST /api/import/notes/:noteId/attachmentsGET /api/export
Sync API:
POST /api/syncGET /api/sync/eventsкак server-sent events
Совместный доступ:
POST /api/notes/:id/sharesGET /api/notes/:id/sharesPATCH /api/notes/:id/shares/:shareIdDELETE /api/notes/:id/shares/:shareId
MCP-сервер должен начинать с обычных эндпоинтов заметок/тегов/вложений/импорта. Sync API полезен для офлайн-клиентов с учётом конфликтов, но MCP-сайдкар может на первых порах его не использовать.
Формы данных
Тело создания заметки:
{
"title": "string",
"content": "optional string",
"isPinned": false,
"isArchived": false,
"background": "optional string",
"tagIds": ["tag-id"]
}Тело обновления заметки — это частичное тело создания плюс опциональная оптимистичная блокировка:
{
"title": "optional string",
"content": "optional string",
"isPinned": false,
"isArchived": false,
"background": "optional string",
"tagIds": ["tag-id"],
"baseVersion": 1
}Anchor возвращает преобразованные заметки со следующими важными полями:
{
"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": []
}Тело импорта заметок:
{
"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
}Форма результата импорта:
{
"results": [
{
"ref": "external reference",
"status": "created | skipped | remapped | failed",
"noteId": "uuid",
"warning": "optional string",
"error": "optional string"
}
],
"tags": { "created": 0, "reused": 0 }
}Формы загрузки вложений:
Обычная загрузка вложения: multipart-поле
fileнаPOST /api/notes/:noteId/attachments.Загрузка вложения при импорте: multipart-поле
fileплюс поле формыpositionнаPOST /api/import/notes/:noteId/attachments.Ответ о вложении включает
id,noteId,type,originalFilename,mimeType,fileSize,position,uploadedByUserIdиcreatedAt.
Лимиты и валидация
Лимит списка заметок:
GET /api/notesограничиваетlimitзначениями1..200.
Массовые лимиты:
noteIds: максимум 200.tagIds: максимум 50.
Лимиты импорта:
Заметок в пакете: 50.
Длина строкового содержимого Delta: 1 000 000 байт/символов.
Длина заголовка: 1000.
Тегов на заметку: 50.
Тегов на пакет импорта: 500.
Длина имени тега: 100.
Лимиты вложений:
Максимальный размер файла: 50 МБ.
Разрешённые изображения:
image/jpeg,image/png,image/webp,image/gif.Разрешённый аудио:
audio/mpeg,audio/wav,audio/mp4,audio/x-m4a,audio/ogg,audio/aac,audio/webm.PDF, JSON, ZIP и универсальный
application/octet-streamотклоняются текущим исходным кодом.
Фоновые идентификаторы, разрешённые при импорте:
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.
Формат содержимого
Anchor хранит content заметки как строку. Существующая работа по импорту подтверждает, что для импорта форматированного текста это должен быть строковый JSON Quill Delta.
MCP-сервер должен предоставлять инструменты, дружественные к Markdown, и внутренне преобразовывать Markdown в Quill Delta. Позже он также сможет предоставлять нативные инструменты Delta для экспертного режима.
Рекомендуемая политика преобразования:
anchor_create_noteпринимает Markdown, преобразует в Delta, вызываетPOST /api/notes.anchor_update_noteпринимает Markdown, преобразует в Delta, вызываетPATCH /api/notes/:idс опциональнымbaseVersion.anchor_import_notesпринимает Markdown или нативный Delta, пакетирует черезPOST /api/import/notes.anchor_get_noteвозвращает исходное содержимое плюс проекцию текста/Markdown по мере возможности для читаемости LLM.
Модель аутентификации
Исходный код Anchor извлекает bearer-токен из Authorization: Bearer <token>. Поэтому MCP-сайдкар должен поддерживать два уровня аутентификации:
ANCHOR_TOKEN: токен, которыйanchor-mcpиспользует при вызовах Anchor.ANCHOR_MCP_TOKEN: токен, ожидаемый от туннельного клиента перед обработкой любого MCP-запроса.
MCP-сервер никогда не должен передавать произвольные токены вызывающих сторон в Anchor.
Ссылки на исходный код
Основные проверенные файлы в вышестоящем репозитории:
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
Инструменты MCP
Инструменты чтения, фаза 1:
anchor_list_notes(limit, offset)anchor_search_notes(query, limit)anchor_get_note(note_id)anchor_list_tags()anchor_list_attachments(note_id)
Детали реализованных инструментов:
anchor_list_notesподдерживаетlimit,offset,include_contentиtag_id. Поскольку Anchor предоставляет только листинг на основе лимита,offset + limitдолжно быть не более 200.anchor_search_notesподдерживаетquery,limit,include_contentиtag_id.anchor_get_noteподдерживаетnote_idиinclude_content.anchor_list_tagsне принимает входных данных.anchor_list_attachmentsвозвращает только метаданные и не скачивает байты вложений.
Инструменты записи, фаза 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)
Инструменты управления, фаза 3:
anchor_archive_notes(note_ids)anchor_pin_notes(note_ids, is_pinned)anchor_add_tags(note_ids, tag_ids)anchor_export(), если туннельный клиент может обработать потоковый архив.
Избегать или ограничивать деструктивные инструменты:
anchor_delete_note(note_id, confirm)соответствует мягкому удалению и должен требоватьconfirm=true.anchor_permanent_delete_note(note_id, confirm)следует на первых порах опустить.anchor_delete_tag(tag_id, confirm)следует на первых порах опустить.Не предоставлять сырой произвольный HTTP-прокси-инструмент.
Безопасность
Храните
ANCHOR_TOKENтолько в окружении Docker-стека или в.env; не встраивайте его в образ.Добавьте отдельный
ANCHOR_MCP_TOKENдля вызовов от туннельного клиента кanchor-mcp.Привяжите MCP-сервер только к контейнерной сети; не добавляйте метки Traefik, если только не планируется намеренное раскрытие.
Держите инструменты узкими и типизированными. Не позволяйте вызывающим сторонам выбирать произвольные пути Anchor API.
Логируйте метаданные запросов, а не содержимое заметок или токены.
По умолчанию используйте инструменты только для чтения, пока путь туннельной аутентификации не будет проверен.
Требуйте явный
confirm=trueдля мягкого удаления и массовых деструктивных действий.Отказывайте в необратимом удалении, если только не задана отдельная настройка
ENABLE_DANGEROUS_TOOLS=true.
Этапы реализации
Создать минимальный TypeScript MCP HTTP-сервер.
Добавить конфигурацию из окружения:
ANCHOR_BASE_URL,ANCHOR_TOKEN,ANCHOR_MCP_TOKEN, хост/порт привязки.Реализовать
/healthzдля диагностики Docker и туннеля.Реализовать небольшой клиент Anchor API с типизированными методами и без произвольного обходного пути по путям.
Реализовать
anchor_list_notes,anchor_search_notes,anchor_get_noteиanchor_list_tags.Добавить формирование ответов, которое отбрасывает тяжёлые поля, если они явно не запрошены.
Реализовать вспомогательные функции преобразования Markdown в Delta и тесты.
Реализовать создание/обновление с опциональной оптимистичной блокировкой через
baseVersion.Реализовать пакетный импорт с учётом известных лимитов импорта.
Реализовать загрузку вложений только для разрешённых изображений/аудио.
Добавить Dockerfile и пример Compose, включая заглушку туннельного клиента.
Добавить тесты с моками ответов Anchor и проверками валидации.
Добавить эксплуатационную документацию по ротации токенов и подключению туннельного клиента ChatGPT.
Открытые вопросы
Точный образ туннельного клиента, переменные окружения и формат заголовка аутентификации.
Можно ли настроить или пропатчить Anchor, чтобы разрешить PDF и другие типы файлов.
Следует ли принимать содержимое заметок в Markdown и преобразовывать в Quill Delta, или MCP должен напрямую предоставлять нативный формат содержимого Anchor.
Сможет ли туннельный клиент достаточно хорошо передавать бинарные полезные нагрузки для загрузки вложений и скачивания экспорта.
Следует ли имитировать
offsetна стороне клиента, посколькуGET /api/notesпредоставляет толькоlimit, а не постраничную навигацию со смещением.
Рекомендуемый первый этап
Создайте MCP-сервер только для чтения с anchor_list_notes, anchor_search_notes, anchor_get_note и anchor_list_tags. Разверните его приватно в стеке Anchor за туннельным клиентом. Добавляйте создание/обновление/импорт только после проверки пути чтения и модели аутентификации.
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