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
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。