Factograph MCP
Enables building and exploring a knowledge graph from files (PDF, DOCX, code) with AI enrichment via Ollama or Claude. Supports pinning documents, linking entities, and traversing the graph.
README
🧠 Factograph MCP v4
Граф знаний с файловым вводом и AI-обогащением через локальный Ollama (Qwen3:14b) или Anthropic API.
Архитектура: MCP-сервер живёт на Ubuntu-сервере, читает файлы локально, а LLM-инференс уходит по сети на Windows-машину с видеокартой (Ollama).
Что нового в v4
Три изменения, сделанные по итогам реальной сессии в mcphost:
-
Файлы без расширения больше не отбрасываются. Раньше
ingest_file/ingest_directory/list_server_filesпомечали такие файлы какsupported: false. Дампы технической документации (напримерinstall core,multiapnбез.txt) теперь читаются как обычный текст автоматически — расширение не обязательно. -
Новый инструмент
auto_link_collection— массовое связывание документов одним вызовом. Решает конкретный сценарий: пользователь просит "установи связи между всеми документами", а модели нужно было самой спланировать цикл "обогатить каждый → сравнить" — задача, с которой 14B-модель не справлялась. Теперь это один детерминированный вызов на сервере. -
Описания
enrich_document/find_relatedобновлены — явно указывают, что для массового связывания нужно использоватьauto_link_collection, а не вызывать их в цикле по одному документу.
Если у тебя 0 связей после импорта
Это не баг и не "функция не поддерживается" (как иногда отвечает модель) — это значит, что у документов ещё не извлечены сущности, а без них Jaccard-сравнению просто не с чем работать. Раньше для этого нужно было вызвать enrich_document на каждый документ вручную; теперь auto_link_collection делает это сама перед расчётом связей.
Установка на Ubuntu Server
git clone <repo> factograph-mcp # или просто распакуй архив
cd factograph-mcp
npm install
npm run build
cp .env.example .env
nano .env # вписать IP Windows-машины и разрешённые папки
Зависимости для PDF/DOCX (опционально)
pdf-parse и mammoth лежат в optionalDependencies — если npm install их не поставил:
npm install pdf-parse mammoth
Настройка Ollama на Windows 11
-
Установи Ollama, стяни модель:
ollama pull qwen3:14b -
Разреши сетевой доступ (по умолчанию Ollama слушает только localhost):
Через переменную окружения перед запуском —
$env:OLLAMA_HOST = "0.0.0.0:11434" ollama serveИли навсегда: Win+R →
sysdm.cpl→ Advanced → Environment Variables → добавитьOLLAMA_HOST=0.0.0.0:11434→ перезапустить Ollama. -
Открой порт в Windows Firewall:
New-NetFirewallRule -DisplayName "Ollama" -Direction Inbound -LocalPort 11434 -Protocol TCP -Action Allow -
Узнай IP машины:
ipconfig→ IPv4 Address (например192.168.1.50). -
Проверь с Ubuntu-сервера:
curl http://192.168.1.50:11434/api/tagsДолжен вернуться список моделей.
Либо тем же самым через MCP-инструмент:
ping_ollama {}
Установка mcphost (хост на Ubuntu Server)
Важно: разработка
mcphostостановлена, репозиторий заархивирован автором — проект пометили как замороженный (без новых фич и фиксов), а преемником названKit(тот же автор, более новая архитектура). Для текущей задачиmcphostвсё ещё рабочий вариант — последний релиз стабилен и именно его используют примеры в этом README — но если в будущем что-то перестанет собираться или захочется новых возможностей, стоит посмотреть наKitв репозиторияхmark3labsна GitHub.
1. Установи Go (если ещё нет)
sudo apt update
sudo apt install golang-go
go version # проверка
2. Установи mcphost
go install github.com/mark3labs/mcphost@latest
Бинарник ставится в ~/go/bin. Добавь эту папку в PATH, если её там нет:
echo 'export PATH=$PATH:~/go/bin' >> ~/.bashrc
source ~/.bashrc
mcphost --help # проверка, что бинарник нашёлся
Альтернатива без сборки — скачать готовый бинарник со страницы Releases под свою архитектуру, не устанавливая Go вовсе.
3. Настрой подключение к Ollama для самого mcphost
Это отдельная переменная окружения от той, что в .env нашего MCP-сервера — mcphost сам общается с Ollama напрямую для самого чата с моделью, а .env факторграфа отвечает только за то, как enrich_document/synthesize_cluster достают Ollama. Их обычно указывают на один и тот же адрес, но задаются они раздельно:
export OLLAMA_HOST=http://192.168.1.50:11434
Для других провайдеров (если когда-нибудь понадобятся) — ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY тем же способом.
4. Создай конфиг ~/.mcp.json
{
"mcpServers": {
"factograph": {
"command": "node",
"args": ["/home/user/factograph-mcp/dist/index.js"],
"env": {
"OLLAMA_HOST": "http://192.168.1.50:11434",
"OLLAMA_MODEL": "qwen3:14b",
"ALLOWED_ROOTS": "/home/user/documents:/mnt/data",
"AUTO_SAVE_PATH": "/home/user/.document-pinboard/graph.json"
}
}
}
}
5. Запусти
mcphost --model ollama:qwen3:14b --config ~/.mcp.json
При старте в логе должно появиться что-то вроде Loaded 25 tools from MCP servers — если число другое, проверь, не упал ли factograph-сервер при старте (смотри stderr — там пишет [factograph-mcp] запущен).
Конфигурация .env
OLLAMA_HOST=http://192.168.1.50:11434
OLLAMA_MODEL=qwen3:14b
# Папки, из которых MCP разрешено читать файлы (через :)
ALLOWED_ROOTS=/home/user/documents:/mnt/data
# Авто-сохранение графа на диск при старте/остановке сервера
AUTO_SAVE_PATH=/home/user/.document-pinboard/graph.json
Если OLLAMA_HOST не задан, но задан ANTHROPIC_API_KEY — сервер автоматически переключится на Claude API как fallback.
Подключение к Claude Desktop
Если хочешь использовать тот же MCP-сервер не через mcphost, а из Claude Desktop:
{
"mcpServers": {
"factograph": {
"command": "node",
"args": ["/home/user/factograph-mcp/dist/index.js"],
"env": {
"OLLAMA_HOST": "http://192.168.1.50:11434",
"OLLAMA_MODEL": "qwen3:14b",
"ALLOWED_ROOTS": "/home/user/documents:/mnt/data",
"AUTO_SAVE_PATH": "/home/user/.document-pinboard/graph.json"
}
}
}
}
Конфиг для mcphost (~/.mcp.json) — смотри раздел «Установка mcphost» выше, формат mcpServers идентичен.
Все инструменты (25 штук)
Слой 1 — Пинборд (8)
pin_document · list_pins · search_pins · get_pin · update_pin · unpin · list_collections · export_collection
Слой 2 — Граф знаний (10)
link_documents · get_connections · traverse_graph · enrich_document · find_by_entity · find_related · auto_link_collection · get_facts · synthesize_cluster · graph_stats
Слой 3 — Файлы на сервере + диск-хранилище (7)
| Инструмент | Описание |
|---|---|
ingest_file |
Прочитать файл (PDF/DOCX/код/текст, в т.ч. без расширения) и добавить в базу |
ingest_directory |
Массовый импорт папки (рекурсивно, с фильтром расширений) |
list_server_files |
Посмотреть содержимое директории на сервере |
ping_ollama |
Проверить связь с Windows-машиной и список моделей |
save_graph |
Сохранить весь граф (узлы+связи+факты) в JSON на диск |
load_graph |
Загрузить граф из JSON (merge, skip/overwrite конфликтов) |
export_edges |
Связи → CSV (Excel) или DOT (Graphviz-визуализация) |
auto_link_collection — как это работает
auto_link_collection {
collection: "research", // опционально — иначе вся база
use_ai: true, // обогатить документы без сущностей перед связыванием
min_jaccard: 0.1 // порог схожести для авто-связей
}
Шаг 1 — для каждого документа в наборе проверяется, есть ли у него извлечённые сущности. Если нет и use_ai: true — документ прогоняется через enrich_document (Ollama/Anthropic) автоматически.
Шаг 2 — для всех документов набора считается Jaccard-пересечение сущностей, создаются связи similar_to (Jaccard ≥ 0.25) или shares_topic (ниже).
Возвращает сводку: сколько документов обогащено, сколько связей создано, и сами связи (до 50 штук в ответе). Если связей всё равно 0 — подсказка в поле hint рекомендует понизить min_jaccard.
Типичный рабочий процесс
1. Узнать что лежит на сервере
list_server_files { path: "/mnt/data/papers" }
2. Массовый импорт (без авто-обогащения на этом шаге — дешевле и быстрее)
ingest_directory {
path: "/mnt/data/papers",
recursive: true,
extensions: ["pdf", "md"], // не указывать — заберёт и файлы без расширения
collection: "research"
}
3. Связать все документы коллекции одним вызовом
auto_link_collection { collection: "research" }
4. Исследовать граф
traverse_graph { doc_id: "...", max_depth: 3 }
find_by_entity { entity: "transformer" }
5. Сохранить граф на диск (бэкап / версионирование)
save_graph { path: "/home/user/backups/graph-2026-06-19.json" }
6. Визуализировать
export_edges { path: "/tmp/graph.dot", format: "dot" }
# затем на сервере: dot -Tsvg /tmp/graph.dot > graph.svg
Диск-хранилище графа: как это устроено
Граф всегда живёт в SQLite (~/.document-pinboard/pins.db) — это основной источник истины.
JSON-снэпшоты через save_graph/load_graph — это:
- Бэкапы — на случай порчи БД
- Версионирование —
git add graph.jsonдля истории изменений графа - Перенос — скопировать граф на другую машину без переноса всего SQLite-файла
- AUTO_SAVE_PATH — если задан в
.env, граф автоматически грузится при старте сервера и сохраняется при остановке (SIGINT/SIGTERM)
load_graph по умолчанию работает в режиме skip — не трогает существующие записи при совпадении ID, что делает его безопасным для повторного запуска.
Безопасность
ALLOWED_ROOTSограничиваетingest_file/ingest_directory/list_server_filesтолько указанными директориями. Если оставить пустым — доступ к всей файловой системе сервера (не рекомендуется на боевом сервере).- Все пути проходят через
safePath(), который резолвит..-трюки и directory traversal.
Известные ограничения
- Tool-calling у Qwen3:14b не идеален. Модель иногда домысливает параметры, которых нет в схеме (например, пыталась вызвать
ingest_fileсpathsвместоpath).mcphostсам отдаёт ошибку обратно модели и она обычно восстанавливается на следующей попытке — но это вероятностное поведение, не гарантия. - Описания тулов — это намёк, а не команда. Несмотря на явные формулировки в
auto_link_collectionпро "не вызывай по одному", модель технически может всё равно выбрать ручной цикл поenrich_document. Если заметишь такое поведение — попроси прямо: "используй auto_link_collection". - Авто-связи (
similar_to/shares_topic) считаются только по пересечению сущностей. Если у документов мало общих именованных сущностей, но они тематически близки — Jaccard может не найти связь. В этом случае выручитsynthesize_clusterили ручнойlink_documents.
Структура файлов
src/
├── types.ts ← PinnedDocument schema
├── pdf-parse.d.ts ← минимальные типы для pdf-parse (он их не публикует)
├── db.ts ← DocumentDB (docs + FTS5)
├── processor.ts ← URL fetch, HTML→text
├── ingest.ts ← чтение файлов с диска (PDF/DOCX/код/текст, поддержка файлов без расширения) + сканирование папок
├── graph-types.ts ← Connection, Fact, Relation
├── graph.ts ← GraphDB (связи, сущности, факты, BFS, Jaccard, настраиваемый autoConnectByEntities)
├── ollama.ts ← HTTP-клиент Ollama (JSON mode, /no_think для Qwen3)
├── enricher.ts ← AI-обогащение (Ollama приоритетно, Anthropic fallback)
├── graph-store.ts ← save/load графа в JSON, экспорт CSV/DOT
├── file-tools.ts ← MCP-инструменты слоя 3 (ingest_*, save_graph, ...)
└── index.ts ← MCP-сервер, все 25 инструментов (включая auto_link_collection)
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。
mcp-server-qdrant
这个仓库展示了如何为向量搜索引擎 Qdrant 创建一个 MCP (Managed Control Plane) 服务器的示例。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。