ConfluenceMCP
MCP server for searching internal Confluence documentation with features like score-based ranking, noun extraction, and LLM query rewriting.
README
MCP Server for Confluence Search
MCP (Model Context Protocol) сервер для поиска по внутренней документации Confluence. Поддерживает SSE и streamable-http транспорты, Basic Auth.
Быстрый старт
cp .env.example .env # скопировать шаблон
# заполнить .env (минимум: CONFLUENCE_BASE_URL, CONFLUENCE_USERNAME, CONFLUENCE_API_TOKEN)
docker compose up -d --build # собрать и запустить
Сервер доступен по адресу http://localhost:8003/sse.
Конфигурация (.env)
Все настройки — в одном файле .env. Скопируйте .env.example и заполните:
cp .env.example .env
Обязательные
| Переменная | Описание |
|---|---|
CONFLUENCE_BASE_URL |
URL Confluence (локальный или Cloud) |
CONFLUENCE_USERNAME |
Логин (для Cloud — email) |
CONFLUENCE_API_TOKEN |
Пароль (для Cloud — API token) |
Опциональные
| Переменная | По умолч. | Описание |
|---|---|---|
MCP_PORT |
8003 |
Порт сервера |
CONFLUENCE_TIMEOUT |
30 |
Таймаут HTTP-запросов к Confluence (секунды, минимум 5) |
SCORE_MERGE_MAX_VARIANTS |
12 |
Макс. число вариантов запроса при score-based поиске (4–24) |
LLM_REWRITE_ENDPOINT |
(пусто) | URL OpenAI-совместимого API для переформулировки запросов |
LLM_REWRITE_MODEL |
(пусто) | Имя модели (например qwen2.5) |
LLM_REWRITE_API_KEY |
(пусто) | API-ключ (если не нужен — оставить пустым) |
LLM_REWRITE_TIMEOUT |
5 |
Таймаут LLM-запроса (секунды) |
Как получить credentials
Локальный Confluence (on-premise): используйте логин и пароль от учётной записи.
Atlassian Cloud:
- Перейдите https://id.atlassian.com/manage-profile/security/api-tokens
- Создайте API token
- В качестве
CONFLUENCE_USERNAMEукажите email, в качествеCONFLUENCE_API_TOKEN— созданный token
Инструменты (Tools)
search_content
Поиск страниц по ключевым словам. По умолчанию (multi_pass=true) сервер:
- извлекает
pageIdиз Confluence-ссылок в запросе - генерирует несколько вариантов поиска (полная фраза, токены с
_, длинные слова) - выполняет CQL-запросы по каждому варианту и объединяет результаты без дубликатов
Параметры:
| Параметр | Тип | По умолч. | Описание |
|---|---|---|---|
query |
string | (обязательный) | Поисковый запрос |
space_key |
string | null |
Ключ пространства или несколько через запятую (DEV, HR) |
space_keys |
string[] | null |
Список ключей пространств (предпочтительно для нескольких) |
content_type |
string | "page" |
Тип: page, blogpost, comment, attachment, space, all |
limit |
int | 10 |
Макс. результатов (до 100) |
multi_pass |
bool | true |
Расширенный поиск по нескольким вариантам |
score_merge |
bool | false |
Ранжирование по score (см. ниже) |
score_merge_max_variants |
int | 0 |
Лимит вариантов (0 = из конфига, SCORE_MERGE_MAX_VARIANTS) |
llm_rewrite |
bool | false |
Переформулировать запрос через LLM перед поиском |
search_content(query="оформить звонок директорат", score_merge=true)
search_by_cql
Поиск по произвольной CQL-строке.
| Параметр | Тип | По умолч. | Описание |
|---|---|---|---|
cql |
string | (обязательный) | CQL-запрос |
limit |
int | 10 |
Макс. результатов |
expand |
string[] | ["space","version"] |
Дополнительные поля |
get_page_content
Полное содержимое страницы по ID. Возвращает HTML (body.view), пространство, версию, цепочку родителей (ancestors) и дочерние страницы (children.page).
get_page_children
Список дочерних страниц (id, title, version) для заданного page_id.
list_spaces
Список всех пространств Confluence.
confluence_health
Проверка доступности Confluence и учётных данных. Возвращает имя пользователя и git-хэш сборки.
Умный поиск
Проблема
Запрос «КАК ОФОРМИТЬ ЗВОНОК В ДИРЕКТОРАТ» не находит статью со словом «принять», потому что:
- «оформить» и «принять» — лексически разные слова, Confluence не связывает их
- общий вариант «ЗВОНОК ДИРЕКТОРАТ» существует в обоих контекстах, но ранние варианты заполняют
limitраньше
Решение — три независимых улучшения, каждое решает свою часть проблемы:
Улучшение 1: Score-based merging (score_merge=true)
Идея: запустить ВСЕ варианты запроса, собрать все совпадения, ранжировать по числу вариантов, которые нашли страницу.
Без score_merge сервер останавливается, когда набрал limit результатов — первые варианты забивают выдачу. Со score_merge все варианты выполняются до конца, и страница, найденная 5 вариантами, получит более высокий рейтинг, чем страница, найденная одним.
Веса вариантов:
| Тип варианта | Вес | Пример |
|---|---|---|
| Полная фраза (исходный запрос) | 3.0 | «КАК ОФОРМИТЬ ЗВОНОК В ДИРЕКТОРАТ» |
| 2–3 слова | 2.0–2.5 | «ОФОРМИТЬ ЗВОНОК» |
| Одно слово | 1.0 | «ДИРЕКТОРАТ» |
Количество вариантов ограничено SCORE_MERGE_MAX_VARIANTS (по умолчанию 12, диапазон 4–24).
search_content(query="оформить звонок директорат", score_merge=true)
Улучшение 2: Noun-only проход (автоматически)
Идея: pymorphy3 определяет части речи. Из запроса выделяются только существительные — получается «чистый» вариант без глаголов и предлогов.
"КАК ОФОРМИТЬ ЗВОНОК В ДИРЕКТОРАТ" → "ЗВОНОК ДИРЕКТОРАТ"
"ПОРЯДОК СОГЛАСОВАНИЯ ДОКУМЕНТОВ" → "ПОРЯДОК СОГЛАСОВАНИЕ ДОКУМЕНТ"
Существительные — самые информативные слова в поисковом запросе. Убрав глаголы и предлоги, вариант точнее попадает в заголовки и текст статей. Работает всегда, флагов не требует, внешних зависимостей нет.
Улучшение 3: LLM-переформулировка (llm_rewrite=true)
Идея: LLM получает исходный запрос и генерирует 3–5 альтернативных формулировок, используя синонимы и перефразирование.
"КАК ОФОРМИТЬ ЗВОНОК В ДИРЕКТОРАТ"
→ "принять звонок директорат"
→ "перевести вызов в директорат"
→ "маршрутизация звонков директорат"
Это единственный механизм, который понимает синонимы («оформить» = «принять» = «перевести»). Требует настроенных переменных LLM_REWRITE_* в .env. При ошибке (таймаут, LLM недоступен) тихо откатывается к обычному поиску.
search_content(query="оформить звонок директорат", llm_rewrite=true)
Можно комбинировать оба флага: score_merge=true, llm_rewrite=true.
Сравнение подходов
| Подход | Зависимости | Покрытие синонимов |
|---|---|---|
| Score merging | нет | ~40% — ловит через пересечения вариантов |
| Noun-only | pymorphy3 (встроен) | ~60% — убирает глагольный шум |
| LLM rewrite | внешний LLM API | ~90% — понимает синонимы и перефразирование |
Как это работает вместе
Запрос: "КАК ОФОРМИТЬ ЗВОНОК В ДИРЕКТОРАТ"
│
┌───────────────┼───────────────┐
│ │ │
Полная фраза Noun-only LLM варианты
"КАК ОФОРМИТЬ "ЗВОНОК "принять звонок
ЗВОНОК В ДИРЕКТОРАТ" директорат"
ДИРЕКТОРАТ" "перевести вызов
│ │ в директорат"
│ │ │
└───────────────┼───────────────┘
│
Каждый вариант →
CQL-запрос к Confluence
│
▼
Score-based ранжирование
(страница, найдённая 3+
вариантами, будет первой)
│
▼
Результаты
Интеграция
Claude Desktop
Добавьте в claude_desktop_config.json:
{
"mcpServers": {
"confluence": {
"url": "http://localhost:8003/sse",
"transport": "sse"
}
}
}
Claude Code (CLI)
Добавьте в ~/.claude/mcp_config.json:
{
"mcpServers": {
"confluence": {
"url": "http://localhost:8003/sse",
"transport": "sse"
}
}
}
MCP SuperAssistant Proxy
{
"mcpServers": {
"confluence": {
"type": "streamable-http",
"url": "http://localhost:8003/mcp",
"timeout": 30
}
}
}
Endpoints
| Endpoint | Метод | Описание |
|---|---|---|
/sse |
GET | SSE endpoint (Claude Desktop, Claude Code) |
/messages/ |
POST | SSE JSON-RPC |
/mcp |
GET/POST | Streamable-HTTP (SuperAssistant Proxy) |
/health |
GET | Статус сервера и Confluence (браузер, curl) |
Проверка curl
# Статус
curl http://localhost:8003/health
# Инициализация MCP
curl -X POST http://localhost:8003/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
Локальная установка (без Docker)
pip install -r requirements.txt
cp .env.example .env # заполнить credentials
python -m confluence_mcp.server
Структура проекта
src/confluence_mcp/
├── server.py # MCP сервер (SSE + streamable-http), инструменты
├── confluence_client.py # REST-клиент Confluence (Basic Auth)
├── config.py # Конфигурация из .env
├── cql_escape.py # Экранирование CQL-строк
├── query_expand.py # Генерация вариантов поискового запроса
├── scoring.py # Score-based ранжирование результатов
├── noun_extract.py # Выделение существительных (pymorphy3)
└── llm_rewrite.py # LLM-переформулировка запросов
tests/
└── test_cql_escape.py # python tests/test_cql_escape.py -v
Требования
- Python 3.10+
- Docker (рекомендуется)
- Confluence (локальный или Cloud) с Basic Auth
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.