Skip to main content

sgnl-mcp — MCP-сервер для SIGNAL Integration API

MCP-сервер, через который LLM-агент (Claude и др.) работает с документацией в SIGNAL: смотрит проекты и папки, ищет и скачивает документы, загружает новые документы и версии, работает с замечаниями, передачами и рассмотрениями.

Агент остаётся под контролем: чтение без ограничений, запись — только после предпросмотра и согласия пользователя, отправка передач и запуск рассмотрений — только после подтверждения пользователем в диалоге. Удалять, перемещать и переименовывать документы и папки, а также менять права агент не может вообще.

Построен на sgnl-api — обёртке над API из этого же репозитория.

Как обеспечивается контроль

Рубеж Что делает
1. Scopes токена Сервер запрашивает у SIGNAL только права своего профиля. В профиле read в токене нет ни одного права на запись — SIGNAL сам откажет. Права *:delete не запрашиваются никогда.
2. Профиль Инструменты выше профиля не регистрируются: агент их не видит.
3. Белый список запросов Каждый HTTP-запрос проверяется до отправки: только разрешённые метод и путь, никаких DELETE, никакого поля deleted в запросах на запись, внешние хосты — только для загрузки файла.
4. Подтверждение Запись — в два вызова: предпросмотр с токеном, затем выполнение с тем же токеном. Отправка передачи и запуск рассмотрения — через диалог подтверждения у пользователя (MCP elicitation).
5. Клиент и аудит Инструменты помечены readOnlyHint: клиент спрашивает разрешение на запись. Все записи и отказы пишутся в JSONL-журнал без секретов.

Нагрузка на SIGNAL ограничена: по умолчанию не больше 3 запросов в секунду и 4 параллельных на весь сервер, у каждого вызова инструмента свой бюджет запросов, справочники кэшируются на 5 минут.

Установка

uvx sgnl-mcp          # запуск без установки
# или
pip install sgnl-mcp

Нужен Python 3.11+.

Настройка

Вся настройка — через переменные окружения (или файл .env в рабочем каталоге). Агент не может их изменить.

Переменная Обязательна По умолчанию Назначение
SGNL_CLIENT_ID да — Client ID интеграции SIGNAL
SGNL_CLIENT_SECRET да — Client secret интеграции SIGNAL
SGNL_MCP_PROFILE нет read read, write или workflow
SGNL_MCP_ACTOR_USER_ID для write/workflow — ID пользователя SIGNAL, от имени которого делаются изменения (лучше служебная учётная запись «AI-агент»)
SGNL_MCP_UPLOAD_ROOT для write/workflow — Каталог, из которого разрешено загружать файлы. Файлы вне него, в том числе через символические ссылки, недоступны
SGNL_MCP_ALLOWED_EXTENSIONS нет .pdf,.dwg,.dxf,… Разрешённые типы загружаемых файлов, через запятую
SGNL_MCP_AUTO_CONFIRM нет — Write-инструменты, которые выполняются без предпросмотра (только для доверенных сценариев). Workflow сюда не входит
SGNL_MCP_RATE_PER_SEC нет 3 Запросов в секунду (не больше 10)
SGNL_MCP_BURST нет 6 Запас запросов для коротких всплесков
SGNL_MCP_MAX_CONCURRENCY нет 4 Параллельных запросов к SIGNAL
SGNL_MCP_TOOL_TIMEOUT нет 30 Таймаут вызова инструмента, с
SGNL_MCP_UPLOAD_TIMEOUT нет 600 Таймаут загрузки файла, с
SGNL_MCP_CONFIRMATION_TTL_SEC нет 300 Срок действия токена подтверждения
SGNL_MCP_AUDIT_PATH нет ~/.sgnl-mcp/audit.jsonl Журнал аудита
SGNL_MCP_STATE_PATH нет ~/.sgnl-mcp/state.sqlite Журнал выполненных операций (защита от повторов)

Пользователю нужен только ключ (SGNL_CLIENT_ID и SGNL_CLIENT_SECRET), scope он не задаёт: сервер сам запрашивает права своего профиля.

Если в интеграции включены не все scope, сервер всё равно запускается, но без недостающих:

  • операции, которым они нужны, отвечают ошибкой SCOPE_MISSING с готовым текстом для администратора, например: «У вашего ключа SIGNAL ограниченные права… Передайте администратору SIGNAL: „В интеграции (client_id …) включите scope: docs:issue:list“»;
  • запрос в SIGNAL при этом не отправляется;
  • инструмент get_access_status заранее показывает, чего не хватает;
  • то же сообщение сервер пишет в свой журнал при запуске.

Сервер не запускается, только если ключ неверный или в интеграции нет ни одного scope профиля. Для write и workflow при запуске проверяется, что пользователь SGNL_MCP_ACTOR_USER_ID есть в компании. Если для этой проверки нет company:user:list, запись недоступна, а чтение работает.

Права интеграции по профилям

Это раздел для администратора SIGNAL. Включите в интеграции эти scope, чтобы были доступны все инструменты профиля:

Профиль Scopes интеграции в SIGNAL
read project:list, project:read, docs:folder:read, docs:item:list, docs:item:read, docs:version:list, docs:docs_transfer:list, docs:docs_transfer:read, docs:issue:list, docs:review:list, docs:signing:list, docs:attribute:list
write всё из read + company:user:list, docs:object:create, docs:version:create, docs:version:update, docs:item:create, docs:docs_transfer:create, docs:docs_transfer:update, docs:issue:update, docs:review:create, docs:review:update
workflow то же, что write

Список составляется автоматически из запросов, которые разрешены профилю. Тест сверяет его со спецификацией SIGNAL, поэтому лишнего сервер не запросит. Обратите внимание: нужен docs:issue:list, а не docs:issue:read.

Отправка передачи и запуск рассмотрения в SIGNAL используют те же права, что и их наполнение. Поэтому их отделяет сам MCP-сервер: в профиле write этих инструментов нет, а в workflow они всегда требуют подтверждения пользователя.

Подключение к Claude

Claude Desktop — claude_desktop_config.json:

{
  "mcpServers": {
    "sgnl": {
      "command": "uvx",
      "args": ["sgnl-mcp"],
      "env": {
        "SGNL_CLIENT_ID": "…",
        "SGNL_CLIENT_SECRET": "…",
        "SGNL_MCP_PROFILE": "read"
      }
    }
  }
}

Claude Code:

claude mcp add sgnl -e SGNL_CLIENT_ID=… -e SGNL_CLIENT_SECRET=… -e SGNL_MCP_PROFILE=read -- uvx sgnl-mcp

Для профиля write добавьте SGNL_MCP_ACTOR_USER_ID и SGNL_MCP_UPLOAD_ROOT.

Запуск в Docker

Готовый образ для linux/amd64 и linux/arm64 (в том числе Mac на Apple Silicon) публикуется в GitHub Container Registry:

docker pull ghcr.io/gritsyuk/sgnl-mcp:latest   # или конкретная версия, например :0.1.0
docker tag ghcr.io/gritsyuk/sgnl-mcp:latest sgnl-mcp

Для работы стоит закрепить версию (:0.1.0), а не latest: тогда образ не обновится без вашего ведома. Можно и собрать образ самостоятельно из корня репозитория (ему нужны оба пакета рабочего пространства):

docker build -f mcp/Dockerfile -t sgnl-mcp .

Сервер общается с клиентом через stdin/stdout, поэтому контейнер запускается с -i, а клиент сам стартует его на каждую сессию. Секреты удобно держать в env-файле, а не в конфигурации клиента. Например, ~/.sgnl-mcp.env:

SGNL_CLIENT_ID=…
SGNL_CLIENT_SECRET=…
SGNL_MCP_PROFILE=read

Claude Desktop — claude_desktop_config.json (пути — абсолютные):

{
  "mcpServers": {
    "sgnl": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm", "--init",
        "--read-only", "--tmpfs", "/tmp",
        "--cap-drop", "ALL", "--security-opt", "no-new-privileges",
        "--env-file", "/Users/me/.sgnl-mcp.env",
        "-v", "sgnl-mcp-data:/data",
        "sgnl-mcp"
      ]
    }
  }
}

Claude Code:

claude mcp add sgnl -- docker run -i --rm --init --read-only --tmpfs /tmp --cap-drop ALL \
  --security-opt no-new-privileges --env-file ~/.sgnl-mcp.env -v sgnl-mcp-data:/data sgnl-mcp

Windows. В конфигурации Claude Desktop (%APPDATA%\Claude\claude_desktop_config.json) обратные слеши в путях удваиваются: "--env-file", "C:\\Users\\Admin\\.sgnl-mcp.env", а папка для загрузки подключается как "-v", "C:\\SIGNAL\\outgoing:/uploads:ro". В командной строке cmd вместо /dev/null используется NUL. Проверить, что образ запускается:

docker run -i --rm --init ghcr.io/gritsyuk/sgnl-mcp:0.1.0 < NUL

Без учётных данных сервер сразу завершится с ошибкой проверки настроек (не заданы SGNL_CLIENT_ID / SGNL_CLIENT_SECRET) — значит, образ рабочий.

Что внутри образа:

  • Процесс работает от непривилегированного пользователя (uid 10001), зависимости зафиксированы uv.lock.
  • /data — том для журнала аудита (audit.jsonl) и журнала выполненных операций (state.sqlite). Именованный том sgnl-mcp-data сохраняет их между запусками; без него защита от повторов и аудит теряются при каждом перезапуске.
  • /uploads — каталог загрузки (SGNL_MCP_UPLOAD_ROOT уже указывает на него). Для профилей write/workflow смонтируйте туда папку с файлами только на чтение: -v /path/to/outgoing:/uploads:ro. Тогда агент физически не может ни изменить файлы на компьютере, ни прочитать что-то за пределами этой папки.
  • Файл .env в образ не попадает (.dockerignore пропускает только исходники пакетов).

Флаги --read-only, --cap-drop ALL и no-new-privileges необязательны, но сервер с ними работает, и это ещё один рубеж: контейнер не может ничего записать, кроме /data и /tmp.

Разрешения в клиенте

  • Инструменты чтения можно разрешить без вопросов.
  • Инструменты записи и Workflow не добавляйте в «разрешить всегда»: клиент должен спрашивать перед каждым вызовом. Это один из рубежей контроля.
  • Для профиля workflow клиент должен поддерживать MCP elicitation (диалог подтверждения). Без неё отправка передач и запуск рассмотрений завершаются ошибкой и ничего не делают.

Инструменты

Инструмент Профиль Что делает
get_access_status read Что доступно ключу: профиль, недостающие scope и готовый текст для администратора SIGNAL (без запросов к SIGNAL)
list_projects read Проекты, доступные интеграции
get_project read Данные проекта и его корневая папка
get_project_folder_tree read Дерево папок с правами пользователя
search_documents read Поиск документов по проекту или папке (имя, расширение, автор, даты)
list_folder_documents read Документы одной папки (без вложенных)
list_document_versions read История версий документа
get_document_version read Связь «документ — версия файла» по item_version_id
get_document_download_url read Временная ссылка на скачивание версии (сам файл не передаётся)
get_document_context read Всё о документе за один вызов: версии, атрибуты, замечания, рассмотрения, подписи; у каждого блока свой статус
list_document_transfers read Передачи проекта с фильтрами
get_document_transfer read Полные данные передачи
list_transfer_documents read Документы в передаче
list_document_transfer_types read Типы передач проекта
list_issues read Замечания с фильтрами
list_reviews read Рассмотрения проекта
get_review_details read Версии рассмотрения и документы в них
get_document_review_status read Статус рассмотрения версий документов
list_review_types read Типы рассмотрений проекта
upload_document write Новый документ из файла
add_document_version write Новая версия существующего документа
update_document_version_comment write Комментарий версии
create_document_transfer write Новая передача (черновик)
add_documents_to_transfer write Добавить версии документов в неотправленную передачу
update_issues write Изменить 1–25 замечаний
create_review write Новое рассмотрение (черновик)
add_documents_to_review write Добавить до 20 версий документов в рассмотрение
prepare_send_document_transfer workflow Проверить передачу перед отправкой и получить токен
send_document_transfer workflow Отправить передачу (подтверждение пользователем в диалоге)
prepare_start_review workflow Проверить рассмотрение перед запуском и получить токен
start_review workflow Запустить рассмотрение (подтверждение пользователем в диалоге)

Как проходит запись

  1. Агент вызывает инструмент без confirmation_token. Сервер проверяет объекты и возвращает предпросмотр («было → станет», путь папки, состав передачи и т.п.) и токен. В SIGNAL ничего не меняется.
  2. Агент показывает предпросмотр пользователю.
  3. После согласия агент вызывает инструмент с теми же аргументами и токеном. Сервер перепроверяет объекты: если с момента предпросмотра что-то изменилось (другой файл, кто-то правил замечание), токен отклоняется.

Токен одноразовый, действует 5 минут и привязан к аргументам. Повторный вызов с уже использованным токеном возвращает сохранённый результат, а не выполняет операцию второй раз.

Если запрос на запись завершился без ясного ответа (таймаут, ошибка сервера), сервер не повторяет его сам, а возвращает OUTCOME_UNKNOWN с тем, что удалось выяснить. Для загрузки файла можно завершить операцию параметром resume_version_id, не загружая файл заново.

Ограничения

  • В API SIGNAL нет поиска передач по документу, поэтому блок transfers в get_document_context всегда not_supported.
  • Создание замечаний, удаление, перемещение, переименование, изменение прав и пользователей в MCP-сервер намеренно не включены.

Ответы и ошибки

Все инструменты возвращают {"success": true, "data": …, "page": …, "warnings": […], "request_id": …} или {"success": false, "error": {"code", "message", "details"}, "request_id": …}.

Код Значение
INVALID_REQUEST, NOT_FOUND, FORBIDDEN, AUTH_FAILED, QUOTA_EXCEEDED, RATE_LIMITED Ответ SIGNAL (400, 404, 403, 401, 450, 429)
SERVER_ERROR, NETWORK_ERROR, TIMEOUT SIGNAL не ответил нормально; чтение можно повторить
OUTCOME_UNKNOWN Запись могла пройти или не пройти; сервер её не повторял
SCOPE_MISSING В интеграции ключа не включён нужный scope или у компании нет лицензии. В message — текст для администратора SIGNAL, в details.missing_scopes — список scope
POLICY_DENIED Запрос запрещён политикой MCP-сервера
CONFIRMATION_INVALID, CONFIRMATION_DECLINED Токен недействителен или пользователь не подтвердил
INVALID_STATE, NOTHING_TO_DO, UPLOAD_FAILED, BUDGET_EXCEEDED Объект в неподходящем состоянии, изменять нечего, файл не передан, исчерпан бюджет запросов

Metadata

Release files for sgnl-mcp 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sgnl-mcp 0.2.0
File Size Uploaded Provenance Actions
sgnl_mcp-0.2.0.tar.gz 36.7 kB Without provenance Details for sgnl_mcp-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for sgnl-mcp 0.2.0
File Interpreter ABI Platform Actions
sgnl_mcp-0.2.0-py3-none-any.whl Python 3 none any Details for sgnl_mcp-0.2.0-py3-none-any.whl

Total release size: 80.7 kB

Release files / sgnl_mcp-0.2.0.tar.gz

Download URL sgnl_mcp-0.2.0.tar.gz
Size 36.7 kB
Tags Source
SHA-256 checksum
How to use checksums
27f3aae15d1f475a7b82471a934058bf2eeaf5061d120a55e3d7f945bec73ffe
BLAKE2b-256 checksum
How to use checksums
d08de281b3102ba29d56df9d057dfa0fc09a3bf9195d0a73bb803a13dbad78ae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / sgnl_mcp-0.2.0-py3-none-any.whl

Download URL sgnl_mcp-0.2.0-py3-none-any.whl
Size 44.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
389e27a218ac6ffb8342dbde3f5bc4f7391cc416197a4c372a0240b637057340
BLAKE2b-256 checksum
How to use checksums
8f81529cd0fc273c3f5c03c4feb06567e2b9a32f528962e7a1c7ab9c61d1f3d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for sgnl-mcp 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page