Skip to main content
Glama
priority-mcp

Priority REST API MCP Server

by priority-mcp

Priority REST API MCP Server

MCP-сервер, который подключает ИИ-ассистентов — Claude и другие — напрямую к ERP-системе Priority. Каждая операция OData (запрос, создание, обновление, удаление, пакетная обработка, вложения, текстовые поля) представлена как инструмент MCP, поэтому ИИ-агенты могут читать и записывать оперативные бизнес-данные без написания пользовательского интеграционного кода.

Версия: 0.2.0 · Транспорт: Streamable HTTP (SSE опционально) · Среда выполнения: Node.js 18 · Инструменты: 19


Быстрый старт

1. Клонируйте репозиторий и установите зависимости

git clone https://github.com/priority-mcp/priority-odata-mcp priority-mcp
cd priority-mcp
npm install

2. Создайте файл .env из примера

cp .env.example .env

Как минимум задайте эти четыре переменные:

PRIORITY_BASE_URL=https://<host>/odata/Priority/<tabula.ini>/<company>/
PRIORITY_AUTH_TYPE=basic
PRIORITY_USERNAME=myuser
PRIORITY_PASSWORD=mypassword

3. Запустите сервер

# Development (from source)
node src/index.js

# Production (bundled)
npm run build
node dist/index.js

При первом запуске, если ODATA_MCP_TOKEN не задан, генерируется случайный Bearer-токен и выводится в stdout. Скопируйте его для следующего шага.

4. Подключитесь из Claude Code

Добавьте в конфигурацию MCP:

{
  "mcpServers": {
    "priority": {
      "type": "http",
      "url": "http://localhost:3000/mcp",
      "headers": {
        "Authorization": "Bearer <ODATA_MCP_TOKEN>"
      }
    }
  }
}

Related MCP server: mcp_sdk_eyra_accelerator

Транспорт

Сервер использует Streamable HTTP в качестве основного транспорта — каждый запрос POST /mcp полностью не сохраняет состояние. Новые McpServer и StreamableHTTPServerTransport создаются для каждого запроса и уничтожаются после его завершения.

Конечная точка

Метод

Назначение

/mcp

POST

Основная конечная точка MCP (Streamable HTTP)

/sse

GET

SSE-поток — требует SSE_ENABLED=true

/sse

POST

JSON-RPC-сообщения для SSE-клиентов

/health

GET

Проверка работоспособности — возвращает версию и статус

/.well-known/oauth-authorization-server

GET

Обнаружение OAuth 2.1 (требуется Claude Code ≥2.1.92)

/authorize, /token, /register

GET/POST

Поток PKCE OAuth 2.1 — автоматически одобряет запросы

Примечание: Конечные точки OAuth 2.1 существуют для удовлетворения процедуры установления соединения Streamable HTTP в Claude Code. Они автоматически одобряют все запросы и не предназначены для реального контроля доступа — эту функцию выполняет ODATA_MCP_TOKEN.


Аутентификация

Аутентификация работает на двух независимых уровнях.

Уровень 1 — защита этого сервера

Все маршруты (кроме /health и конечных точек OAuth) требуют:

Authorization: Bearer <ODATA_MCP_TOKEN>

Задайте ODATA_MCP_TOKEN в файле .env. Если он отсутствует, при запуске генерируется случайный UUID и выводится в stdout.

Уровень 2 — вызовы Priority ERP

Управляется переменной PRIORITY_AUTH_TYPE:

  • basic — базовая HTTP-аутентификация с использованием PRIORITY_USERNAME + PRIORITY_PASSWORD

  • pat — Bearer-токен через PRIORITY_PAT

  • oauth2 — то же, что и pat (передайте PAT как Bearer-токен)

  • none — без заголовка аутентификации (только для локального тестирования)

Операции записи (POST/PATCH/DELETE) автоматически получают и повторяют запрос с заголовком X-CSRF-Token, если первоначальный запрос отклонён, следуя схеме защиты CSRF в Priority.

Опциональные заголовки лицензии приложения отправляются с каждым запросом к Priority, если заданы PRIORITY_APP_ID и PRIORITY_APP_KEY (X-App-Id / X-App-Key).


Конфигурация

Скопируйте .env.example в .env. Сервер ищет файл .env в следующем порядке: ENV_FILE_PATH → ./mcp-servers/Priority-REST-API-MCP-Server/.env → ./.env.

Обязательные параметры

Переменная

Описание

PRIORITY_BASE_URL

Корневой URL OData — формат: https://<host>/odata/Priority/<tabula.ini>/<company>/

PRIORITY_AUTH_TYPE

basic | pat | oauth2 | none

PRIORITY_USERNAME

Имя пользователя — обязательно при AUTH_TYPE=basic

PRIORITY_PASSWORD

Пароль — обязателен при AUTH_TYPE=basic

Аутентификация Priority (опционально)

Переменная

Описание

ODATA_MCP_TOKEN

Bearer-токен, защищающий /mcp. Если не задан, используется случайный UUID.

PRIORITY_PAT

Персональный токен доступа (при AUTH_TYPE=pat или oauth2)

PRIORITY_APP_ID

Идентификатор лицензии приложения — отправляется как заголовок X-App-Id

PRIORITY_APP_KEY

Ключ лицензии приложения — отправляется как заголовок X-App-Key

PRIORITY_LANGUAGE

Переопределяет заголовок Accept-Language (например, en)

HTTP-сервер

Переменная

По умолчанию

Описание

HTTP_HOST

0.0.0.0

Адрес привязки

HTTP_PORT

3000

Порт прослушивания

SSE_ENABLED

false

Включить конечную точку /sse

Тайм-ауты и TLS

Переменная

По умолчанию

Описание

PRIORITY_HTTP_TIMEOUT_MS

30000

Тайм-аут чтения для вызовов API Priority (мс)

MCP_WRITE_TIMEOUT

15000

Тайм-аут для операций POST/PATCH/DELETE (мс)

MCP_PROC_TIMEOUT

45000

Тайм-аут для пакетных операций (мс)

TLS_REJECT_UNAUTHORIZED

false

Установите true в production, чтобы отклонять самоподписанные сертификаты

Отладка

Переменная

По умолчанию

Описание

LOG_LEVEL

INFO

DEBUG записывает каждый запрос и ответ

MCP_DEBUG

false

Выводит полные URL OData, параметры, количество результатов

PRIORITY_ENABLE_TRACE

false

Добавляет X-App-Trace: 1 к каждому запросу к Priority

STRICT_DATA_INTEGRITY

true

Вызывает ошибку при пустых/фиктивных ответах API — отключайте только для тестирования

ENV_FILE_PATH

—

Переопределяет путь к файлу .env (полезно для развёртывания в подмодулях)


Инструменты

Все 19 инструментов определены в src/tools/ и зарегистрированы в src/tools/priorityTools.js.

Система и метаданные

Инструмент

Описание

Параметры

version_get

Получить версию службы Priority и заголовки ответа

—

metadata_entities_list

Вывести список всех наборов сущностей OData; фильтровать только формы с поддержкой REST

apiOnly?, includeMetadata?

metadata_schema_get

Получить схему полей сущности, запросив образец записи. Автоматически перенаправляет имена подформ на родительскую + $expand

entity, sample?, top?

metadata_refresh

Очистить и обновить серверный кэш метаданных. Всегда выполняет полную очистку (см. «Известные ограничения»)

entity?

Запросы

Инструмент

Описание

Параметры

entity_get

Получить одну запись по ключу или поиску, с опциональными $expand и $select

entity, key, lookup, select?, expand?

query_run

Выполнить запрос OData с полной поддержкой filter/select/top/skip/orderby/expand/count. Проверяет результаты фильтрации по дате после получения

entity, filter?, select?, top?, skip?, orderby?, expand?, count?, deltaToken?

safe_query_run

Как query_run, но сначала автоматически обнаруживает допустимые поля и проверяет имена полей $select перед выполнением — предотвращает ошибки 400 из-за недопустимых имён столбцов

entity, filter?, select?, top?, skip?, expand?, count?

query_sum

Вычислить сумму числового поля по сущности с опциональным фильтром. Сначала пробует $apply=aggregate; при неудаче выполняет полное сканирование с разбиением на страницы

entity, field?, filter?

Создание / Обновление / Удаление

Инструмент

Описание

Параметры

entity_create

Создать новую запись. Поддерживает создание подформ через parentEntity + parentKey + subform

entity, data, parentEntity?, parentKey?, parentLookup?, subform?

entity_update

Обновить запись через PATCH с If-Match: *. Поддерживает составные ключи

entity, key, data, parentEntity?, parentKey?, subform?

entity_delete

Удалить запись через DELETE с If-Match: *. Поддерживает удаление подформ

entity, key, parentEntity?, parentKey?, subform?

batch_operations

Выполнить несколько операций POST/PATCH/DELETE в одном запросе $batch с цепочками зависимостей

requests[] (id, method, url, body?, dependsOn?)

Текстовые поля

Инструмент

Описание

Параметры

entity_text_get

Получить содержимое форматированного текста подресурса /Text записи

entity, key

entity_text_create

Отправить POST с новым текстовым содержимым на /Entity(Key)/Text

entity, key, textData

entity_text_update

Отправить PATCH с существующим текстовым содержимым на /Entity(Key)/Text

entity, key, textData

Вложения

Инструмент

Описание

Параметры

entity_attachments_get

Вывести список вложений записи

entity, key

entity_attachments_upload

Загрузить файл в подресурс /Attachments записи как multipart/form-data. fileData должен быть в кодировке base64

entity, key, fileData, fileName, contentType?

Конфигурация и справка

Tool

Description

Parameters

instructions_get

Возвращает полное руководство по эксплуатации: синтаксис OData, шаблоны подформ, лимиты троттлинга, правила обработки дат, известные сценарии сбоев и примеры архитектуры. Вызывайте первым при изучении незнакомой сущности

—

config_restflag_update

Устанавливает RESTFLAG=Y или N в таблице FORMLIMITED, чтобы включить или отключить доступ к REST API для формы Priority

formName, restFlag, formType?


Промпты и ресурсы

Сервер регистрирует MCP промпты (многоразовые шаблоны инструкций) и ресурсы (живые конечные точки данных).

Промпты (src/prompts/)

Имя

Назначение

query_priority_entity

Руководство по построению OData-запросов к сущности

explore_entity_relationships

Объясняет иерархию подформ для заданной сущности

modify_priority_data

Руководство по операциям создания, обновления и удаления

date_handling_guide

Критические правила для фильтров по датам — формат ISO, проверка операторов

known_failure_patterns

Документированные сценарии 404/501/400 и их обходные решения

pagination_guide

Объясняет шаблоны $top/$skip и подсчёта

Ресурсы (src/resources/)

URI

Назначение

priority://entities/list

Живой список всех сущностей с включённым REST (RESTFLAG=Y)

priority://entity-schema/{entity}

Схема для конкретной сущности (шаблонный URI)

priority://queries/common

Библиотека готовых примеров запросов

priority://subforms/reference

Справочное руководство по шаблонам подформ и операциям


Пример вызова инструмента

Запросить три самых последних заказа на продажу для клиента 1011 — отправлено как JSON-RPC 2.0 на POST /mcp:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "query_run",
    "arguments": {
      "entity":  "ORDERS",
      "filter":  "CUSTNAME eq '1011'",
      "select":  ["ORDNAME", "CUSTNAME", "CURDATE", "TOTPRICE"],
      "top":     3,
      "orderby": "CURDATE desc"
    }
  }
}

Сервер выдаёт:

GET /odata/Priority/.../ORDERS?$format=json&$filter=CUSTNAME+eq+'1011'
  &$select=ORDNAME,CUSTNAME,CURDATE,TOTPRICE&$top=3&$orderby=CURDATE+desc

Ответ:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [{
      "type": "text",
      "text": "{\"value\":[{\"ORDNAME\":\"SO25000001\",\"CUSTNAME\":\"1011\",\"CURDATE\":\"2025-07-15T00:00:00+03:00\",\"TOTPRICE\":15000.0},...],\"_mcp_metadata\":{\"entity\":\"ORDERS\",\"resultCount\":2,\"filterApplied\":true}}"
    }],
    "isError": false
  }
}

Формат даты: Priority возвращает даты в формате ISO 8601 со смещением часового пояса (например, 2025-07-15T00:00:00+03:00), а не в UTC Z. Используйте синтаксис CURDATE ge 2025-01-01 в фильтрах по датам — не формат ISO-Z.


Развёртывание

Docker

# Build
docker build -t priority-mcp .

# Run
docker run --env-file .env -p 3000:3000 priority-mcp

Dockerfile использует node:18-slim, выполняет npm run build для сборки src/ → dist/ через esbuild, затем запускает dist/index.js. Конфигурация Docker Compose и локальный генератор TLS-сертификатов находятся в deployment/local/.

Контрольный список для продакшена

  • Установите ODATA_MCP_TOKEN явно — не полагайтесь на автоматически сгенерированный

  • Установите TLS_REJECT_UNAUTHORIZED=true

  • Установите STRICT_DATA_INTEGRITY=true (по умолчанию)

  • Установите LOG_LEVEL=INFO (по умолчанию — подавляет служебный шум)

  • Привяжите HTTP_HOST к конкретному интерфейсу, если не публикуете наружу


Известные ограничения

Особенности поведения Priority ERP, о которых стоит знать перед разработкой.

Ограничение частоты запросов — 100 вызовов/минуту на пользователя Priority Cloud ограничивает до 100 вызовов API в минуту на пользователя, максимум 10 параллельных запросов, тайм-аут 3 минуты на вызов. Проектируйте агентов так, чтобы по возможности группировать операции.

Ограничение ответа — MAXFORMLINES Priority молча обрезает ответы на уровне системной константы MAXFORMLINES независимо от $top. Используйте пагинацию на основе $skip, если нужны все записи.

Подформы не являются самостоятельными сущностями Прямой запрос PORDERITEMS_SUBFORM возвращает HTTP 404. Доступ к подформам должен осуществляться через родительскую сущность с $expand=PORDERITEMS_SUBFORM. metadata_schema_get автоматически определяет это и перенаправляет.

$apply=aggregate не поддерживается query_sum всегда переключается на полное сканирование с пагинацией, поскольку $apply=aggregate(...) не поддерживается в этой версии Priority.

GET /ENTITY/$count возвращает 500 Вместо этого используйте ?$top=0&$count=true. Внутренне tryEstimateCount() сначала пробует /$count, затем выполняет пагинацию пакетами по 500 записей (с ограничением 10 000).

contains()/startswith() не поддерживаются для некоторых полей EPROG.ENAME и EREP.ENAME поддерживают только точное совпадение eq — строковые функции возвращают HTTP 501.

Обновление метаданных на уровне сущности возвращает 400 metadata_refresh игнорирует аргумент entity и всегда выполняет полный сброс кэша, поскольку Priority отклоняет запросы на очистку кэша в рамках одной сущности.

Кодирование URL в пакетных запросах URL-адреса внутри запросов batch_operations никогда не кодируются автоматически. Пробелы и специальные символы должны быть вручную закодированы в процентах (пробелы → %20).

Составные ключи Некоторые сущности используют составные ключи, например FORMLIMITED: ENAME='X',TYPE='F'; AINVOICES: IVNUM='T9696',IVTYPE='A',DEBIT='D'. Передавайте полную строку составного ключа в entity_update и entity_delete.


Структура проекта

/
├── src/
│   ├── index.js                    Entry point — creates and starts PriorityMCPServer
│   ├── server.js                   Express app, all routes, auth guard, OAuth 2.1 PKCE
│   ├── sseServer.js                SSE connection manager
│   ├── config.js                   Reads all env vars, resolves .env path
│   ├── version.js                  SERVER_VERSION, KNOWN_ISSUES list
│   │
│   ├── priority/
│   │   └── client.js               PriorityClient — axios instance, auth headers,
│   │                               all API methods (runQuery, createEntity, …)
│   │
│   ├── mcp/
│   │   ├── handler.js              JSON-RPC 2.0 dispatcher (SSE path)
│   │   ├── registry.js             ToolRegistry — registerTool, callTool, listTools
│   │   ├── prompt-registry.js
│   │   ├── resource-registry.js
│   │   ├── priority-mcp-sdk-server.js   Wires registries into McpServer (SDK path)
│   │   ├── tool-call-runner.js          Executes tool, wraps result for MCP response
│   │   └── json-schema-to-zod.js        JSON Schema → Zod conversion
│   │
│   ├── tools/                      One file per tool + priorityTools.js (registration)
│   ├── prompts/                    One file per prompt + priorityPrompts.js
│   ├── resources/                  One file per resource + priorityResources.js
│   └── utils/
│       ├── data-integrity.js       ensureNoMockData(), validateApiResponse()
│       ├── date-handling.js        Date parsing and validation helpers
│       ├── errors.js               createPriorityApiError(), FilterNotAppliedError
│       ├── filter-resolver.js      OData filter string building
│       ├── expand-resolver.js      $expand normalization
│       ├── entity-resolver.js      Entity name / subform name resolution
│       ├── resolve-query-args.js
│       └── subform-query-resolver.js
│
├── data/
│   └── entity-relationships.json   Hardcoded subform map (PORDERS, ORDERS, …)
│
├── tests/
│   ├── scripts/                    Manual test scripts
│   └── results/                    Saved JSON/Markdown test output
│
├── docs/                           Design docs (DATA_INTEGRITY_POLICY, DATE_HANDLING_RULES, …)
├── postman/                        Postman collection for manual API testing
├── deployment/local/               Docker Compose + TLS cert generator
├── build.js                        esbuild bundler: src/ → dist/
└── .env.example                    All env vars documented with descriptions

Тесты

Автоматизированного тестового раннера нет. Тесты — это ручные скрипты, требующие живого подключения к Priority:

# Read operations
node tests/scripts/test-priority-operations.js

# Write operations (interactive — asks for confirmation)
node tests/scripts/test-write-operations.js

# Test all 19 MCP tools via the running server
node tests/scripts/test-all-mcp-tools-via-server.js

# Standalone resolver smoke tests
node test-keyresolver.js
node test-resolver.js

Предупреждение: Тесты на запись создают, обновляют и удаляют реальные записи. Запускайте только на компании для разработки.


Технологический стек

  • Среда выполнения: Node.js 18, ES-модули ("type": "module")

  • MCP SDK: @modelcontextprotocol/sdk ^1.29.0

  • HTTP-сервер: express ^4.21.1

  • HTTP-клиент: axios ^1.7.7

  • Проверка схем: zod ^4.3.6

  • Сборщик: esbuild ^0.25.0 (через npm run build)

  • Прочее: cors, dotenv, form-data, uuid, http-errors

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A generic MCP server that dynamically converts OpenAPI-defined REST APIs into tools for LLMs like Claude. It supports multiple authentication methods and transport protocols, enabling seamless interaction with any OpenAPI-compliant API.
    18 npm
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    A standalone MCP server that exposes API endpoints as tools for AI assistants by proxying requests to a target API defined in an OpenAPI specification. It supports various authentication methods and utilizes Server-Sent Events (SSE) to facilitate integration with clients like Claude and ChatGPT.
    -
  • A
    license
    C
    quality
    D
    maintenance
    An MCP server that bridges AI agents to the eyeot ERP, exposing ~600 business actions (CRM, sales, stock, HR, finance, etc.) as MCP tools over stdio via OAuth 2.1 authentication.
    33
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A config-driven MCP server that exposes OData and REST APIs as MCP tools, enabling AI assistants to query, manage, and monitor SAP backends through natural language.
    112 npm
    32
    MIT