ConfluenceMCP
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Обязательные
Переменная | Описание |
| URL Confluence (локальный или Cloud) |
| Логин (для Cloud — email) |
| Пароль (для Cloud — API token) |
Опциональные
Переменная | По умолч. | Описание |
|
| Порт сервера |
|
| Таймаут HTTP-запросов к Confluence (секунды, минимум 5) |
|
| Макс. число вариантов запроса при score-based поиске (4–24) |
| (пусто) | URL OpenAI-совместимого API для переформулировки запросов |
| (пусто) | Имя модели (например |
| (пусто) | API-ключ (если не нужен — оставить пустым) |
|
| Таймаут 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-запросы по каждому варианту и объединяет результаты без дубликатов
Параметры:
Параметр | Тип | По умолч. | Описание |
| string | (обязательный) | Поисковый запрос |
| string |
| Ключ пространства или несколько через запятую ( |
| string[] |
| Список ключей пространств (предпочтительно для нескольких) |
| string |
| Тип: |
| int |
| Макс. результатов (до 100) |
| bool |
| Расширенный поиск по нескольким вариантам |
| bool |
| Ранжирование по score (см. ниже) |
| int |
| Лимит вариантов (0 = из конфига, |
| bool |
| Переформулировать запрос через LLM перед поиском |
search_content(query="оформить звонок директорат", score_merge=true)search_by_cql
Поиск по произвольной CQL-строке.
Параметр | Тип | По умолч. | Описание |
| string | (обязательный) | CQL-запрос |
| int |
| Макс. результатов |
| string[] |
| Дополнительные поля |
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 | Метод | Описание |
| GET | SSE endpoint (Claude Desktop, Claude Code) |
| POST | SSE JSON-RPC |
| GET/POST | Streamable-HTTP (SuperAssistant Proxy) |
| 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
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/ivanarama/ConfluenceMCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server