Priority REST API MCP Server
Priority REST API MCP Server
Un servidor MCP que conecta a asistentes de IA (Claude y otros) directamente con un sistema Priority ERP. Cada operación OData (consulta, creación, actualización, eliminación, operaciones por lotes, archivos adjuntos, campos de texto) se expone como una herramienta MCP, de modo que los agentes de IA pueden leer y escribir datos de negocio en vivo sin código de integración personalizado.
Versión: 0.2.0 · Transporte: Streamable HTTP (SSE opcional) · Entorno de ejecución: Node.js 18 · Herramientas: 19
Inicio rápido
1. Clona e instala
git clone https://github.com/priority-mcp/priority-odata-mcp priority-mcp
cd priority-mcp
npm install2. Crea el .env a partir del ejemplo
cp .env.example .envComo mínimo, establece estas cuatro variables:
PRIORITY_BASE_URL=https://<host>/odata/Priority/<tabula.ini>/<company>/
PRIORITY_AUTH_TYPE=basic
PRIORITY_USERNAME=myuser
PRIORITY_PASSWORD=mypassword3. Inicia el servidor
# Development (from source)
node src/index.js
# Production (bundled)
npm run build
node dist/index.jsEn el primer arranque, si no se define ODATA_MCP_TOKEN, se genera y se imprime en stdout un token Bearer aleatorio. Cópialo para el siguiente paso.
4. Conecta desde Claude Code
Añade esto a tu configuración de MCP:
{
"mcpServers": {
"priority": {
"type": "http",
"url": "http://localhost:3000/mcp",
"headers": {
"Authorization": "Bearer <ODATA_MCP_TOKEN>"
}
}
}
}Related MCP server: mcp_sdk_eyra_accelerator
Transporte
El server usa Streamable HTTP as main transport: each POST /mcp request is completely stateless. Instead of McpServer y StreamableHTTPServerTransport are created per request and torn down (destroyed) after.
Endpoint | Método | Propósito |
| POST | Endpoint principal de MCP (Streamable HTTP) |
| GET | Flujo SSE — requiere |
| POST | Mensajes JSON-RPC para clientes SSE |
| GET | Comprobación de salud — devuelve la versión y el estado |
| GET | Descubrimiento OAuth 2.1 (requerido por Claude Code ≥2.1.92) |
| GET/POST | Flujo PKCE de OAuth 2.1 — autoaprueba |
Nota: Los endpoints OAuth 2.1 existen para satisfacer el handshake de conexión Streamable HTTP de Claude Code. Autoaprueban todas las solicitudes y no están pensados para un control de acceso real; eso lo gestiona
ODATA_MCP_TOKEN.
Autenticación
La autenticación funciona en dos capas independientes.
Capa 1 — Protección de este servidor
Todas las rutas (excepto /health y los endpoints OAuth) requieren:
Authorization: Bearer <ODATA_MCP_TOKEN>Define ODATA_MCP_TOKEN en .env. Si no se define, se genera un UUID aleatorio al inicio y se imprime en consola.
Capa 2 — Llamada a Priority ERP
Controlada por PRIORITY_AUTH_TYPE:
basic— Autenticación HTTP Basic conPRIORITY_USERNAME+PRIORITY_PASSWORDpat— Token Bearer mediantePRIORITY_PAToauth2— igual quepat(se pasa el PAT como token Bearer)none— sin cabecera de autenticación (solo pruebas locales)
Las operaciones de escritura (POST/PATCH/DELETE) obtienen automáticamente una cabecera X-CSRF-Token y reintentan con ella si la solicitud inicial es rechazada, siguiendo la patrón de protección CSRF de Priority.
Cuando se definen PRIORITY_APP_ID y PRIORITY_APP_KEY, se envían cabeceras de licencia opcionales por aplicación con cada solicitud a Priority (X-App-Id / X-App-Key).
Configuración
Copia .env.example a .env. El servidor busca el .env en el orden: ENV_FILE_PATH → ./mcp-servers/Priority-REST-API-MCP-Server/.env → ./.env.
Requeridas
Variable | Descripción |
| URL raíz de OData — formato: |
|
|
| Nombre de usuario — obligatorio cuando |
| Contraseña — obligatoria cuando |
Autenticación de Priority (opcional)
Variable | Descripción |
| Token Bearer que protege |
| Token de acceso personal (cuando |
| ID de licencia de la aplicación — se envía como cabecera |
| Clave de licencia de la aplicación — se envía como cabecera |
| Sobrescribe la cabecera |
Servidor HTTP
Variable | Por defecto | Descripción |
|
| Dirección a la que se vincula |
|
| Puerto de escucha |
|
| Activa el endpoint |
Timeouts & TLS
Variable | Por defecto | Descripción |
|
| Tiempo de espera de lectura para las llamadas a la API de Priority (ms) |
|
| Tiempo de espera para las operaciones POST/PATCH/DELETE (ms) |
|
| Tiempo de espera para operaciones por lotes (ms) |
|
| Establécelo en |
Depuración
Variable | Por defecto | Descripción |
|
|
|
|
| Imprime las URL de OData completas, los parámetros y los recuentos de resultados |
|
| Añade |
|
| Lanza un error si las respuestas de la API están vacías o son simuladas (mock) — desactívalo solo para pruebas |
| — | Sobrescribe la ruta al archivo |
Herramientas
Las 19 herramientas están definidas en src/tools/ y se registran en src/tools/priorityTools.js.
Sistema y metadatos
Herramienta | Descripción | Parámetros |
| Obtiene la versión del servicio Priority y las cabeceras de respuesta | — |
| Lista todos los conjunto de entidades OData; filtra solo los formularios habilitados para REST |
|
| Obtiene el esquema de campos de una entidad consultando un registro de muestra. Redirige automáticamente los nombres de subformularios al padre + |
|
| Limpia y refresca la caché de metadatos del servidor. Siempre hace un vaciado completo (ver Limitaciones conocidas) |
|
Consultas
Herramienta | Descripción | Parámetros |
| Obtiene un único registro por clave o lookup, con |
|
| Ejecuta una consulta OData con compatibilidad completa con filter/select/top/skip/orderby/expand/count. Valida los resultados de los filtros de fecha después de la obtención |
|
| Igual que |
|
| Suma un campo numérico de una entidad con un filtro opcional. Primero intenta con |
|
Crear / Actualizar / Eliminar
Herramienta | Descripción | Parámetros |
| Crea un nuevo registro. Admite la creación de subformularios mediante |
|
| Actualiza un registro mediante PATCH con |
|
| Elimina un registro mediante DELETE con |
|
| Ejecuta varias operaciones POST/PATCH/DELETE en una única solicitud |
|
Campos de texto
Herramienta | Descripción | Parámetros |
| Obtiene el contenido de texto enriquecido del subrecurso |
|
| Crea nuevo contenido de texto mediante POST en |
|
| Actualiza (PATCH) el contenido de texto existente en |
|
Adjuntos
Adjuntos | Descripción | Parámetros |
| Lista los archivos adjuntos de un registro |
|
| Sube un archivo al subrecurso |
|
Configuración y Ayuda
Also "Glink 0.5.0" etc. Wait, no. Let's not add. The source ends at "### Configuration & Help" so we# Priority REST API MCP Server
Un servidor MCP que conecta a asistentes de IA ( Claude y otros ) directamente con un sistema Priority ERP. Cada operaciónOData (consulta, creación, actualización, eliminación, por lotes, archivos adjuntos, campos de texto) se expone como una herramienta MCP, de modo que los agentes de IA pueden leer y escribir datos de negocio en vivo sin código de integración personalizado.
Versión: 0.2.0 · Transporte: Streamable HTTP (SSE opcional) · Runtime: Node.js 18 · Herramientas: 19
Inicio
1. Clona e instala
git clone https://github.com/priority-mcp/priority-odata-mcp priority-mcp
cd priority-mcp
npm install2. Crea .env a partir del ejemplo
cp .env.example .envComo mínimo, establece estas cuatro variables:
PRIORITY_BASE_URL=https://<host>/odata/Priority/<tabula.ini>/<company>/
PRIORITY_AUTH_TYPE=basic
PRIORITY_USERNAME=myuser
PRIORITY_PASSWORD=mypassword3. Inicia el servidor
# Development (from source)
node src/index.js
# Production (bundled)
npm run build
node dist/index.jsEn el primer arranque, si no se define ODATA_MCP_TOKEN, se genera un token Bearer aleatorio y se imprime por stdout. Cópialo para el siguiente paso.
4. Conecta con Claude Code
Añade a tu configuración de MCP:
{
"mcpServers": {
"priority": {
"type": "http",
"url": "http://localhost:3000/mcp",
"headers": {
"Authorization": "Bearer <ODATA_MCP_TOKEN>"
}
}
}
}Transporte
El servidor usa Streamable HTTP como verbo de transportees principal: cada solicitud POST /mcp es completamente sin estado. Se crean una nueva McpServer y StreamableHTTPServerTransport por solicitud y se eliminan al terminar.
Endpoint | Método | Propósito |
| POST | Punto final principal de MCP (Streamable HTTP) |
| GET | Flujo SSE — requiere |
| POST | Mensajes JSON-RPC para clientes SSE |
| GET | Comprobación de estado — devuelve versión y estado |
| GET | Descubrimiento de OAuth 2.1 (requerido por Claude Code ≥2.1.92) |
| GET/APOST | Flujo OAuth 2.1 PKCE — autoaprueba |
Nota: Los endpoints de OAuth 2.1 existen para satisfacer elprotocolo de conexión Streamable HTTP de Claude Code. Auto-aprueban todas las solicitudes y no están pensados para un control de acceso real; eso se gestiona con
ODATA_MCP_TOKEN.
Autenticación
La autenticación funciona en dos capas independientes.
Capa 1 — Protección de este servidor
Todas las rutas (excepto /health y los endpoints de OAuth) requieren:
Authorization: Bearer <ODATA_MCP_TOKEN>Define ODATA_MCP_TOKEN en .env. Si no se define, se genera un UUID aleatorio al inicio y se imprime por stdout.
Capa 2 — Llamar a Priority ERP
Controlado por PRIORITY_AUTH_TYPE:
basic— Autenticación HTTP Basic conPRIORITY_USERNAME+PRIORITY_PASSWORDpat— Token Bearer mediantePRIORITY_PAToauth2— igual quepat(se pasa el PAT como Bearer)none— sin cabecera de autenticación (solo pruebas locales)
Las operaciones de escritura (POST/PATCH/DELETE) obtienen automáticamente y reintentan con una cabecera X-CSRF-Token si la solicitud inicial es rechazada, siguiendo la protección de CSRF de Priority.
Se envían cabeceras de licencia opcionales por aplicación en cada solicitud a Priority cuando PRIORITY_APP_ID y PRIORITY_APP_KEY están definidos (X-App-Id / X-App-Key).
Configuración
Copia .env.example a .env. El servidor busca .env en este orden: ENV_FILE_PATH → ./mcp-servers/Priority-REST-API-MCP-Server/.env → ./.env.
Requeridas
Variable | Descripción |
| URL raíz de OData — formato: |
|
|
| Nombre de usuario — requerido cuando |
| Contraseña — requeridine cuando |
Autenticación de Priority (opcional)
Variable | Descripción |
| Token Bearer que protege |
| Personal Access Token (cuando |
| ID de licencia de la aplicación — enviado como cabecera |
| Clave de licencia de la aplicación — enviada como cabecera |
| Sobrescribe la cabecera |
Servidor HTTP
Variable | Default | Descripción |
|
| Dirección de enlace |
|
| Puerto de escucha |
|
| Activa el endpoint |
Timeouts y TLS
Variable | Default | Descripción |
|
| Timeout de lectura para llamadas para la API de Priority (ms) |
|
| Timeout para operaciones POST/PATCH/DELETE (ms) |
|
| Timeout para operaciones batch (ms) |
|
| Ponlo en |
Depuración
Variable | Default | Descripción | ||
|
|
| y | respuesta |
|
| Imprime URLs OData completas, params y conteos de resultados | ||
|
| Añade | ||
|
| Lanza error en respuestas vacías/simuladas; desactivar solo para pruebas | ||
| — | Sobrescribe ruta al archivo |
Herramientas
Todos los herramientas están definidos en src/tools/ y se registran en src/tools/priorityTools.js.
Sistema y metadata
Herramienta | Descripción | Parámetros |
| Obtener la versión del servicio Priority y sus cabeceras de respuesta | — |
| Listar todos los conjuntos de entidades OData; filtrar solo a formularios REST |
|
| Obtener el esquema de campos de una entidad para buscar un objeto; auto-redirige nombres de subformularios al padre + |
|
| Limpiar y refrescar la caché de metadatos del servidor. Siempre hace un vaciado completo (ver Limitaciones conocidas) |
|
Consultas
Herramienta | Descripción | Parámetros |
| Obtener un solo registro por clave y/o lookup, con |
|
|
Herramienta | Descripción | Parámetros |
| Devuelve la guía operativa completa: sintaxis de OData, patrones de subformularios, límites de throttling, reglas de gestión de fechas, patrones de error conocidos y ejemplos de arquitectura. Llame a esta herramienta primero al explorar una entidad desconocida | — |
| Establece |
|
Prompts y Recursos
El servidor registra Prompts MCP (plantillas de instrucciones reutilizables) y recursos (endpoints de datos en vivo).
Prompts (src/prompts/)
Nombre | Objetivo |
| Guía para construir consultas OData de una entidad |
| Explica la jerarquía de subformularios de una entidad determinada |
| Guía las operaciones de crear, actualizar y borrar |
| Reglas críticas para filtros de fechas — formato ISO, validación de operadores |
| Patrones de error 404/501/400 documentados y sus soluciones |
| Explica los patrones |
Recursos (src/resources/)
URI | Objetivo |
| Lista en vivo de todas las entidades con REST habilitado ( |
| Esquema de una entidad concreta (URI de plantilla) |
| Biblioteca de ejemplos de consultas listos para usar |
| Guía de referencia para patrones y operaciones de subformularios |
Ejemplo de llamada a una herramienta
Consulte las tres órdenes de venta más recientes para el cliente 1011, enviadas como JSON-RPC 2.0 a 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"
}
}
}El servidor envía:
GET /odata/Priority/.../ORDERS?$format=json&$filter=CUSTNAME+eq+'1011'
&$select=ORDNAME,CUSTNAME,CURDATE,TOTPRICE&$top=3&$orderby=CURDATE+descRespuesta:
{
"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
}
}Formato de fecha: Priority devuelve las fechas como ISO 8601 con desfase de zona horaria (p. ej.,
2025-07-15T00:00:00+03:00), no UTCZ. Use la sintaxisCURDATE ge 2025-01-01en los filtros de fecha — no el formato ISO-Z.
Despliegue
Docker
El Dockerfile usa node:18-slim, ejecuta npm run build para empaquetar src/ → dist/ mediante esbuild y, a continuación, inicia dist/index.js. Una configuración de Docker Compose y un generador local de certificados TLS están en deployment/local/.
# Build
docker build -t priority-mcp .
# Run
docker run --env-file .env -p 3000:3000 priority-mcpLista de comprobación para producción
Establezca
ODATA_MCP_TOKENexplícitamente — no confíe en el generado automáticamenteEstablezca
TLS_REJECT_UNAUTHORIZED=trueEstablezca
STRICT_DATA_INTEGRITY=true(predeterminado)Establezca
LOG_LEVEL=INFO(predeterminado — oculta el ruido de mantenimiento)Fije
HTTP_HOSTa una interfaz específica si no se expone públicamente
Limitaciones conocidas
Comportamientos específicos del ERP de Priority que conviene conocer antes de construir.
Límite de llamadas: 100 llamadas/minuto por usuario Priority Cloud limita a 100 llamadas de API por minuto por usuario, con un máximo de 10 solicitudes en paralelo y un tiempo de espera de 3 minutos por llamada. Diseñe los agentes para agrupar operaciones en lotes siempre que sea posible.
Tope de respuesta: MAXFORMLINES
Priority trunca silenciosamente las respuestas en la constante del sistema MAXFORMLINES, independientemente de $skTOP. Use paginación basada en $skip sin necesita todos los registros.
Los subformularios no son entidades independientes
Consultar PORDERITEMS_SUBFORM directamente devuelve HTTP 404. Los subformularios deben consultarse mediante la entidad principal con $expand=PORDERITEMS_SUBFORM. metadata_schema_get lo detecta automáticamente y redirige.
$applyTOP=aggregate no compatible
query_sum recurre siempre a un escaneo de paginación completo porque $apply=implemented WHERE expr no está soportado en esta versión de Priority.
$count devuelve 500
Use ?$top=0&$count=true. Internamente, tryEstimateCount() intenta /$countwwRole primero y luego pagina en lotes de 500 registros (límite de 10,000). (límite 10.000).
contains()/startswith() no compatibles en algunos campos
EPROG.ENAME y EREP.ENAME solo admiten coincidencia exacta con eq — las funciones de texto devuelven HTTP 501.
La actualización de metadatos a nivel de entidad devuelve 400
metadata_refresh ignora el argumento entity y siempre mantee una limpieza completa de la caché, porque Priority rechaza las solicitudes de borrado de caché por entidad.
Codificación de URL en solicitudes por lotes
Las URLs dentro de batch_operations nunca se codifican automáticamente. Debe hacer percent-encoding de y los espacios (espacios → %20).
Claves compuestas
Algunas entidades usan claves compuestas, como por ejemplo FORMLIMITED: ENAME='X',TYPE='F'; ainvoices: IVNUM='T9696',IVTYPE='A',DEBIT='D'. Pase la cadena de clave compuesta completa a entity_updateyentity_delete`.
Estructura del proyecto
/
├── 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 descriptionsPruebas
No hay un ejecutor de pruebas automatizado. Las pruebas son scripts manuales que requieren una conexión activa al sistema viva:
# 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.jsAdvertencia: Las pruebas de escritura crearánn respuestas, actualizarán y eliminarán registros reales. Ejecute solo para una compañía de desarrollo.
Pila tecnológica
Runtime: Node.js 18, ES Modules (
"type": "module")MCP SDK:
@modelcontextprotocol/sdk ^1.29.0Servidor HTTP:
express ^4.21.1Cliente HTTP:
axios ^1.7.7Validación de esquemas:
zod ^4.3.6Empaquetador:
esbuild ^0.25.0(víanpm run build)Otros:
cors,dotenv,form-data,uuid,http-errors| Herramienta | Descripción | Parámetros | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | |instructions_get| Devuelve la guía operativa completa: sintaxis de OData, patrones de subformularios, límites de throttling, reglas de manejo de fechas, patrones de fallo conocidos y ejemplos de arquitectura. Llame a esta herramienta primero al explorar una entidad que no conozca. | — | |config_restflag_update| EstableceRESTFLAG=YoNen la tablaFORMLIMITEDpara habilitar o deshabilitar el acceso a la API REST de un conjunto de Priority. |formName,restFlag,formType?|
Prompts y Recursos
El servidor registra Prompts MCP (plantillas de instrucciones reutilizables) y recursos (endpoints de datos en vivo).
Prompts (src/prompts/)
Nombre = | Objetivo | |
| Guía para construir consultas OData una entidad | |
| Explica la jerarquía de subformularios de una entidad dada | |
| Guía las operaciones de crear, actualizar y eliminar | |
| Reglas críticas para filtros de fecha — formato ISO, validación de operadores | |
| Patrones de fallo 404/501/400 documentados y sus soluciones | |
| Explica $expand (raíz de búsqueda) | |
Recursos (src/resources/)
| URI | Objetivo |
| ========================= | ============================================================== |
| priority://priority/entities/list | Lista en tiempo real de todas las entidades con REST habilitado (RESTFLAG=Y) |
| priority://entity-schema/{entity} | Esquema de una entidad específica (URI de plantilla) |
| priority://queries/common | Biblioteca de ejemplos de consultas listos para usar |
| priority://subforms/reference | Guía de referencia para patrones y operaciones de subformularios |
Ejemplo de llamada a la herramienta
Consulte los tres pedidos de venta más recientes del cliente PRIORITY1 — enviados como JSON-RPC 2.0 a 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"
}
}
}El servidor emite:
GET /odata/Priority/.../ORDERS?$format=json&$filter=CUSTNAME+eq+'1011'
&$select=ORDNAME,CUSTNAME,CURDATE,TOTPRICE&$top=3&$orderby=CURDATE+descResponse:
{
"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
}
}Formato de fecha: Priority devuelve las fechas como ISO 8601 con un desfase de zona horaria (por ejemplo,
2025-07-15T00:00:00+03:00), no UTCZ. Use la sintaxisCURDATE ge 2025-01-01en los filtros de fecha — no ISO-Z.
Despliegue
Docker
The Dockerfile usa node:18-slim, ejecuta npm run build para agrupar src/ en dist/ mediante esbuild, y luego inicia dist/index.js. Una configuración de Docker Compose y un generador local de certificados TLS están en deployment/local/.
# Build
docker build -t priority-mcp .
# Run
docker run --env-file .env -p 3000:3000 priority-mcpLista de comprobación para producción
Consulte
ODATA_MCP_TOKENexplícitamente — no confíe en el autogeneradoEstablezca
TLS_REJECT_UNAUTHORIZED=trueEstablezca
STRICT_DATA_INTEGRITY=true(opción predeterminada)Establezca
LOG_LEVEL=INFO(opción predeterminada, suprime el ruido del maintenance)Fije
HTTP_HOSTa una interfaz específica si no va a exponer el servicio públicamente
Limitaciones conocidas
Comportamientos específicos de las entidades que es importante conocer antes de integrar.
Límite de velocidad: 100 llamadas/minuto por usuario
Priority Cloud restringe a 100 llamadas de API por minuto y usuario, máximo 10 solicitudes en paralelo y 3 minutos de corte por llamada. Diseñe agentes agrupando operaciones siempre que sea posible.
Tope de respuesta: MAXFORMLINES
Priority trunca las respuestas en la constante del sistema MAXFORMLINES sin importar $top. Use $skip basado en paginación si necesita todos los registros.
Los subformularios no son entidades independientes
Consultar directamente PORDERITEMS_SUBFORM devuelve HTTP 404. Deben accederse a través de la entidad principal con $expand=PORDERITEMS_SUBFORM. metadata_schema_get auto-detecta esto y redirige.
$apply=aggregate no está soportadoquery_sum siempre cae en un recorrido completo de paginación porque $apply=aggregate(...) no es compatible con esta versión de Priority.
GET /ENTITY/$count devuelve 500
Use ?$top=0&$count=true en su lugar. Internamente, tryEstimateCount() intenta /$COUNT primero y luego pide en lotes de 500 registros (máx. 10,000).
contains()/startsWith() no está soportado en algunos datosEPROG.ENAME y EREP.ENAME solo permiten igualdad exacta con eq — la funciones de string devuelven 501.
Actualización de metadatos a nivel de entidad devuelve 400metadata_refresh ignora el argumento entity y siempre hace un vaciado completo de cache, porque Priority rechaza solicitudes de limpieza de caché restringidas a una entidad.
Codificación de URL en lote
Las URL dentro de las solicitudes batch nunco se autocodifican. Los espacios y caracteres especiales deben estar percent-encoded (espacios → %20).
Claves compuestas
Algunas entidades usan claves compuestas como FORMLIMITED: ENAME='X',TYPE='F'; AINVOICES: IVNUM='T9696',IVTYPE='A',DEBIT='D'. Pase la cadena de clave compuesta completa a entity_update y entity_delete.
Estructura del proyecto
/
├── 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 descriptionsTest
No hay un ejecutor de pruebas automatizado. Las pruebas son scripts manuales que requieren conexión viva con 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.jsAdvertencia: Las pruebas de escritura crearán, actualizarán y eliminarán registros reales. Ejecútelas solo contra una empresa de desarrollo.
Stack técnico
Runtime: Node.js 18, ES Modules (
"type": "module")MCP SDK:
@modelcontextprotocol/sdk^1.29.0Servidor HTTP:
express^4.21.21Cliente HTTP:
axios^1.7.7Validación de schemes:
zod^4.3.6Bundler:
esbuild^0.25.0 (víanpm run build)Otros:
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