Priority REST API MCP Server
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 install2. Создайте файл .env из примера
cp .env.example .envКак минимум задайте эти четыре переменные:
PRIORITY_BASE_URL=https://<host>/odata/Priority/<tabula.ini>/<company>/
PRIORITY_AUTH_TYPE=basic
PRIORITY_USERNAME=myuser
PRIORITY_PASSWORD=mypassword3. Запустите сервер
# 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 создаются для каждого запроса и уничтожаются после его завершения.
Конечная точка | Метод | Назначение |
| POST | Основная конечная точка MCP (Streamable HTTP) |
| GET | SSE-поток — требует |
| POST | JSON-RPC-сообщения для SSE-клиентов |
| GET | Проверка работоспособности — возвращает версию и статус |
| GET | Обнаружение OAuth 2.1 (требуется Claude Code ≥2.1.92) |
| 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_PASSWORDpat— Bearer-токен черезPRIORITY_PAToauth2— то же, что и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.
Обязательные параметры
Переменная | Описание |
| Корневой URL OData — формат: |
|
|
| Имя пользователя — обязательно при |
| Пароль — обязателен при |
Аутентификация Priority (опционально)
Переменная | Описание |
| Bearer-токен, защищающий |
| Персональный токен доступа (при |
| Идентификатор лицензии приложения — отправляется как заголовок |
| Ключ лицензии приложения — отправляется как заголовок |
| Переопределяет заголовок |
HTTP-сервер
Переменная | По умолчанию | Описание |
|
| Адрес привязки |
|
| Порт прослушивания |
|
| Включить конечную точку |
Тайм-ауты и TLS
Переменная | По умолчанию | Описание |
|
| Тайм-аут чтения для вызовов API Priority (мс) |
|
| Тайм-аут для операций POST/PATCH/DELETE (мс) |
|
| Тайм-аут для пакетных операций (мс) |
|
| Установите |
Отладка
Переменная | По умолчанию | Описание |
|
|
|
|
| Выводит полные URL OData, параметры, количество результатов |
|
| Добавляет |
|
| Вызывает ошибку при пустых/фиктивных ответах API — отключайте только для тестирования |
| — | Переопределяет путь к файлу |
Инструменты
Все 19 инструментов определены в src/tools/ и зарегистрированы в src/tools/priorityTools.js.
Система и метаданные
Инструмент | Описание | Параметры |
| Получить версию службы Priority и заголовки ответа | — |
| Вывести список всех наборов сущностей OData; фильтровать только формы с поддержкой REST |
|
| Получить схему полей сущности, запросив образец записи. Автоматически перенаправляет имена подформ на родительскую + |
|
| Очистить и обновить серверный кэш метаданных. Всегда выполняет полную очистку (см. «Известные ограничения») |
|
Запросы
Инструмент | Описание | Параметры |
| Получить одну запись по ключу или поиску, с опциональными |
|
| Выполнить запрос OData с полной поддержкой filter/select/top/skip/orderby/expand/count. Проверяет результаты фильтрации по дате после получения |
|
| Как |
|
| Вычислить сумму числового поля по сущности с опциональным фильтром. Сначала пробует |
|
Создание / Обновление / Удаление
Инструмент | Описание | Параметры |
| Создать новую запись. Поддерживает создание подформ через |
|
| Обновить запись через PATCH с |
|
| Удалить запись через DELETE с |
|
| Выполнить несколько операций POST/PATCH/DELETE в одном запросе |
|
Текстовые поля
Инструмент | Описание | Параметры |
| Получить содержимое форматированного текста подресурса |
|
| Отправить POST с новым текстовым содержимым на |
|
| Отправить PATCH с существующим текстовым содержимым на |
|
Вложения
Инструмент | Описание | Параметры |
| Вывести список вложений записи |
|
| Загрузить файл в подресурс |
|
Конфигурация и справка
Tool | Description | Parameters |
| Возвращает полное руководство по эксплуатации: синтаксис OData, шаблоны подформ, лимиты троттлинга, правила обработки дат, известные сценарии сбоев и примеры архитектуры. Вызывайте первым при изучении незнакомой сущности | — |
| Устанавливает |
|
Промпты и ресурсы
Сервер регистрирует MCP промпты (многоразовые шаблоны инструкций) и ресурсы (живые конечные точки данных).
Промпты (src/prompts/)
Имя | Назначение |
| Руководство по построению OData-запросов к сущности |
| Объясняет иерархию подформ для заданной сущности |
| Руководство по операциям создания, обновления и удаления |
| Критические правила для фильтров по датам — формат ISO, проверка операторов |
| Документированные сценарии 404/501/400 и их обходные решения |
| Объясняет шаблоны |
Ресурсы (src/resources/)
URI | Назначение |
| Живой список всех сущностей с включённым REST ( |
| Схема для конкретной сущности (шаблонный URI) |
| Библиотека готовых примеров запросов |
| Справочное руководство по шаблонам подформ и операциям |
Пример вызова инструмента
Запросить три самых последних заказа на продажу для клиента 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), а не в UTCZ. Используйте синтаксисCURDATE ge 2025-01-01в фильтрах по датам — не формат ISO-Z.
Развёртывание
Docker
# Build
docker build -t priority-mcp .
# Run
docker run --env-file .env -p 3000:3000 priority-mcpDockerfile использует 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.0HTTP-сервер:
express ^4.21.1HTTP-клиент:
axios ^1.7.7Проверка схем:
zod ^4.3.6Сборщик:
esbuild ^0.25.0(черезnpm run build)Прочее:
cors,dotenv,form-data,uuid,http-errors
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceA 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.18MIT
- FlicenseNot gradedqualityDmaintenanceA 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.
- AlicenseCqualityDmaintenanceAn 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.331MIT
- AlicenseNot gradedqualityDmaintenanceA 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.4527MIT
Related MCP Connectors
MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
Self-hosted MCP gateway: turn any API, database or MCP server into AI connectors — no code.
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/priority-mcp/priority-odata-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server