Skip to main content
Glama
priority-mcp

Priority REST API MCP Server

by priority-mcp

Priority REST API MCP Server

Ein MCP-Server, der KI-Assistenten – Claude und andere – direkt mit einem Priority-ERP-System verbindet. Jede OData-Operation (Abfrage, Erstellen, Aktualisieren, Löschen, Stapelverarbeitung, Anhänge, Textfelder) wird als MCP-Tool bereitgestellt, sodass KI-Agenten ohne benutzerdefinierten Integrationscode auf Live-Geschäftsdaten zugreifen und diese schreiben können.

Version: 0.2.0 · Transport: Streamable HTTP (SSE optional) · Laufzeit: Node.js 18 · Tools: 19


Schnellstart

1. Klonen und installieren

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

2. .env aus dem Beispiel erstellen

cp .env.example .env

Mindestens diese vier Variablen müssen gesetzt werden:

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

3. Server starten

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

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

Beim ersten Start wird, falls ODATA_MCP_TOKEN nicht gesetzt ist, ein zufälliges Bearer-Token generiert und auf stdout ausgegeben. Kopieren Sie es für den nächsten Schritt.

4. Von Claude Code aus verbinden

Fügen Sie Folgendes zu Ihrer MCP-Konfiguration hinzu:

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

Related MCP server: mcp_sdk_eyra_accelerator

Transport

Der Server verwendet Streamable HTTP als primären Transport – jede POST /mcp-Anfrage ist vollständig zustandslos. Pro Anfrage werden ein neuer McpServer und ein neuer StreamableHTTPServerTransport erstellt und danach wieder abgebaut.

Endpunkt

Methode

Zweck

/mcp

POST

Primärer MCP-Endpunkt (Streamable HTTP)

/sse

GET

SSE-Stream – erfordert SSE_ENABLED=true

/sse

POST

JSON-RPC-Nachrichten für SSE-Clients

/health

GET

Health-Check – gibt Version und Status zurück

/.well-known/oauth-authorization-server

GET

OAuth-2.1-Discovery (erforderlich für Claude Code ≥2.1.92)

/authorize, /token, /register

GET/POST

OAuth-2.1-PKCE-Ablauf – genehmigt automatisch

Hinweis: Die OAuth-2.1-Endpunkte dienen dazu, den Streamable-HTTP-Verbindungs-Handshake von Claude Code zu erfüllen. Sie genehmigen alle Anfragen automatisch und sind nicht für echte Zugriffskontrolle gedacht – diese wird über ODATA_MCP_TOKEN abgewickelt.


Authentifizierung

Die Authentifizierung erfolgt auf zwei unabhängigen Ebenen.

Ebene 1 – Schutz dieses Servers

Alle Routen (außer /health und OAuth-Endpunkte) erfordern:

Authorization: Bearer <ODATA_MCP_TOKEN>

Setzen Sie ODATA_MCP_TOKEN in .env. Falls nicht vorhanden, wird beim Start eine zufällige UUID generiert und auf stdout ausgegeben.

Ebene 2 – Aufruf von Priority ERP

Wird über PRIORITY_AUTH_TYPE gesteuert:

  • basic – HTTP-Basic-Authentifizierung mit PRIORITY_USERNAME + PRIORITY_PASSWORD

  • pat – Bearer-Token über PRIORITY_PAT

  • oauth2 – wie pat (PAT als Bearer-Token übergeben)

  • none – kein Auth-Header (nur für lokale Tests)

Schreiboperationen (POST/PATCH/DELETE) holen bei Ablehnung der ersten Anfrage automatisch ein X-CSRF-Token und wiederholen die Anfrage damit, gemäß dem CSRF-Schutzmuster von Priority.

Optionale anwendungsspezifische Lizenz-Header werden mit jeder Priority-Anfrage gesendet, wenn PRIORITY_APP_ID und PRIORITY_APP_KEY gesetzt sind (X-App-Id / X-App-Key).


Konfiguration

Kopieren Sie .env.example nach .env. Der Server sucht nach .env in dieser Reihenfolge: ENV_FILE_PATH./mcp-servers/Priority-REST-API-MCP-Server/.env./.env.

Erforderlich

Variable

Beschreibung

PRIORITY_BASE_URL

OData-Stamm-URL – Format: https://<host>/odata/Priority/<tabula.ini>/<company>/

PRIORITY_AUTH_TYPE

basic | pat | oauth2 | none

PRIORITY_USERNAME

Benutzername – erforderlich bei AUTH_TYPE=basic

PRIORITY_PASSWORD

Passwort – erforderlich bei AUTH_TYPE=basic

Priority-Authentifizierung (optional)

Variable

Beschreibung

ODATA_MCP_TOKEN

Bearer-Token zum Schutz von /mcp. Bei nicht gesetztem Wert wird eine zufällige UUID verwendet.

PRIORITY_PAT

Persönliches Zugriffstoken (bei AUTH_TYPE=pat oder oauth2)

PRIORITY_APP_ID

Anwendungslizenz-ID – wird als X-App-Id-Header gesendet

PRIORITY_APP_KEY

Anwendungslizenzschlüssel – wird als X-App-Key-Header gesendet

PRIORITY_LANGUAGE

Überschreibt den Accept-Language-Header (z. B. en)

HTTP-Server

Variable

Standard

Beschreibung

HTTP_HOST

0.0.0.0

Bindungsadresse

HTTP_PORT

3000

Lauschport

SSE_ENABLED

false

Aktiviert den /sse-Endpunkt

Timeouts & TLS

Variable

Standard

Beschreibung

PRIORITY_HTTP_TIMEOUT_MS

30000

Lese-Timeout für Priority-API-Aufrufe (ms)

MCP_WRITE_TIMEOUT

15000

Timeout für POST/PATCH/DELETE-Operationen (ms)

MCP_PROC_TIMEOUT

45000

Timeout für Stapeloperationen (ms)

TLS_REJECT_UNAUTHORIZED

false

In Produktion auf true setzen, um selbstsignierte Zertifikate abzulehnen

Debugging

Variable

Standard

Beschreibung

LOG_LEVEL

INFO

DEBUG protokolliert jede Anfrage und Antwort

MCP_DEBUG

false

Vollständige OData-URLs, Parameter und Ergebnisanzahlen ausgeben

PRIORITY_ENABLE_TRACE

false

Fügt jeder Priority-Anfrage X-App-Trace: 1 hinzu

STRICT_DATA_INTEGRITY

true

Wirft Fehler bei leeren/Mock-API-Antworten – nur für Tests deaktivieren

ENV_FILE_PATH

Pfad zur .env-Datei überschreiben (nützlich für Submodul-Bereitstellungen)


Tools

Alle 19 Tools sind in src/tools/ definiert und in src/tools/priorityTools.js registriert.

System & Metadaten

Tool

Beschreibung

Parameter

version_get

Die Version des Priority-Dienstes und die Antwort-Header abrufen

metadata_entities_list

Alle OData-Entitätssets auflisten; nur auf REST-fähige Formulare filtern

apiOnly?, includeMetadata?

metadata_schema_get

Feld-Schema für eine Entität abrufen, indem ein Beispieldatensatz abgerufen wird. Leitet Unterformularnamen automatisch auf übergeordnetes Formular + $expand um

entity, sample?, top?

metadata_refresh

Serverseitigen Metadaten-Cache leeren und aktualisieren. Führt immer einen vollständigen Flush durch (siehe Bekannte Einschränkungen)

entity?

Abfragen

Tool

Beschreibung

Parameter

entity_get

Einen einzelnen Datensatz per Schlüssel oder Lookup abrufen, mit optionalem $expand und $select

entity, key, lookup, select?, expand?

query_run

Eine OData-Abfrage mit vollständiger Filter-/Select-/Top-/Skip-/Orderby-/Expand-/Count-Unterstützung ausführen. Validiert Datumsfilter-Ergebnisse nach dem Abruf

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

safe_query_run

Wie query_run, entdeckt aber zuerst automatisch gültige Felder und validiert $select-Feldnamen vor der Ausführung – verhindert 400-Fehler durch ungültige Spaltennamen

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

query_sum

Ein numerisches Feld über eine Entität mit optionalem Filter summieren. Versucht zuerst $apply=aggregate; fällt auf einen vollständigen Paging-Scan zurück

entity, field?, filter?

Erstellen / Aktualisieren / Löschen

Tool

Beschreibung

Parameter

entity_create

Einen neuen Datensatz erstellen. Unterstützt Unterformular-Erstellung über parentEntity + parentKey + subform

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

entity_update

Einen Datensatz per PATCH mit If-Match: * aktualisieren. Unterstützt zusammengesetzte Schlüssel

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

entity_delete

Einen Datensatz per DELETE mit If-Match: * löschen. Unterstützt Unterformular-Löschungen

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

batch_operations

Mehrere POST/PATCH/DELETE-Operationen in einer $batch-Anfrage mit Abhängigkeitsverkettung ausführen

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

Textfelder

Tool

Beschreibung

Parameter

entity_text_get

Den Rich-Text-Inhalt der /Text-Unterressource eines Datensatzes abrufen

entity, key

entity_text_create

Neuen Textinhalt per POST an /Entity(Key)/Text senden

entity, key, textData

entity_text_update

Vorhandenen Textinhalt per PATCH auf /Entity(Key)/Text aktualisieren

entity, key, textData

Anhänge

Tool

Beschreibung

Parameter

entity_attachments_get

Anhänge eines Datensatzes auflisten

entity, key

entity_attachments_upload

Eine Datei als multipart/form-data in die /Attachments-Unterressource eines Datensatzes hochladen. fileData muss base64-kodiert sein

entity, key, fileData, fileName, contentType?

Konfiguration & Hilfe

Tool

Beschreibung

Parameter

instructions_get

Gibt den vollständigen Betriebsleitfaden zurück: OData-Syntax, Subformular-Muster, Drosselungsgrenzen, Regeln zur Datumsbehandlung, bekannte Fehlermuster und Architekturbeispiele. Rufen Sie dieses Tool zuerst auf, wenn Sie eine unbekannte Entität erkunden

config_restflag_update

Setzt RESTFLAG=Y oder N in der Tabelle FORMLIMITED, um den REST-API-Zugriff für ein Priority-Formular zu aktivieren oder zu deaktivieren

formName, restFlag, formType?


Prompts & Ressourcen

Der Server registriert MCP-Prompts (wiederverwendbare Anweisungsvorlagen) und Ressourcen (Live-Daten-Endpunkte).

Prompts (src/prompts/)

Name

Zweck

query_priority_entity

Leitfaden zum Erstellen von OData-Abfragen gegen eine Entität

explore_entity_relationships

Erläutert die Subformular-Hierarchie einer bestimmten Entität

modify_priority_data

Führt durch Erstellungs-, Aktualisierungs- und Löschoperationen

date_handling_guide

Wichtige Regeln für Datumsfilter — ISO-Format, Operatorvalidierung

known_failure_patterns

Dokumentierte 404/501/400-Muster und ihre Workarounds

pagination_guide

Erläutert $top/$skip- und Zählmuster

Ressourcen (src/resources/)

URI

Zweck

priority://entities/list

Live-Liste aller REST-fähigen Entitäten (RESTFLAG=Y)

priority://entity-schema/{entity}

Schema für eine bestimmte Entität (Template-URI)

priority://queries/common

Bibliothek einsatzbereiter Abfragebeispiele

priority://subforms/reference

Referenzhandbuch für Subformular-Muster und -Operationen


Beispiel für einen Tool-Aufruf

Fragen Sie die drei neuesten Verkaufsaufträge für Kunde 1011 ab — gesendet als JSON-RPC 2.0 an 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"
    }
  }
}

Der Server sendet:

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

Antwort:

{
  "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
  }
}

Datumsformat: Priority gibt Daten als ISO 8601 mit einem Zeitversatz zurück (z. B. 2025-07-15T00:00:00+03:00), nicht als UTC Z. Verwenden Sie in Datumsfiltern die Syntax CURDATE ge 2025-01-01 — nicht das ISO-Z-Format.


Bereitstellung

Docker

# Build
docker build -t priority-mcp .

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

Das Dockerfile verwendet node:18-slim, führt npm run build aus, um src/ über esbuild zu dist/ zu bündeln, und startet dann dist/index.js. Ein Docker-Compose-Setup und ein Generator für lokale TLS-Zertifikate befinden sich in PT/Home deployment/local/.

Produktions-Checkliste

  • Setzen Sie ODATA_MCP_TOKEN explizit — verlassen Sie sich nicht auf das automatisch generierte

  • Setzen Sie TLS_REJECT_UNAUTHORIZED=true

  • Setzen Sie STRICT_DATA_INTEGRITY=true (Standard)

  • Setzen Sie LOG_LEVEL=INFO (Standard — unterdrückt Systemrauschen)

  • Binden Sie HTTP_HOST an eine bestimmte Schnittstelle, falls nicht öffentlich bereitgestellt


Bekannte Einschränkungen

Bekannte Priority-ERP-spezifische Verhaltensweisen, die Sie vor der Entwicklung kennen sollten.

Ratenlimit — 100 Aufrufe pro Minute pro Benutzer Priority Cloud begrenzt auf 100 API-Aufrufe pro Minute und Benutzer, maximal 10 parallele Anfragen, 3 Minuten Timeout pro Aufruf. Gestalten Sie Agenten so, dass sie Operationen wo möglich bündeln.

Antwortlimit — MAXFORMLINE Priority kappt Antworten stillschweigend an der Systemkonstante MAXFORMLINES, unabhängig von $top. Wenn Sie alle Datensätze benötigen, verwenden Sie eine Pagination auf Basis von $skip.

Subformulare sind keine eigenständigen Entitäten Eine direkte Abfrage PORDERITEMS_SUBFORM liefert HTTP 404. Subformulare müssen über die übergeordnete Entität mit $expand=PORDERITEMS_SUBFORM abgerufen werden. metadata_schema_get erkennt dies automatisch und leitet um.

$apply=aggregate wird nicht unterstützt query_sum fällt immer auf einen vollständigen Seiten-Scan zurück, da $apply=aggregate(...) auf dieser Priority-Version nicht unterstützt wird.

GET /ENTITY/$count liefert 500 Verwenden Sie stattdessen ?$top=0&$count=true. Intern versucht tryEstimateCount() zuerst /$count und pagiiert dann in Batches von 500 (begrenzt auf 10.000).

contains()/startswith() werden bei einigen Feldern nicht unterstützt EPROG.ENAME und EREP.ENAME unterstützen nur den exakten Abgleich mit eq — Zeichenfunktionen liefern HTTP 501.

Metadaten-Aktualisierung auf Entitätsebene liefert 400 metadata_refresh ignoriert das Argument entity und führt immer einen vollständigen Cache-Reset durch, da Priority entitätsscharfe Clearnderungen ablehnt.

Batch-URL-Kodierung URLs innerhalb von batch_operations-Anfragen werden nie automatisch kodiert. Leerzeichen und Sonderzeichen müssen manuell Prozent-kodiert werden (Leerzeichen → %20).

Zusammengesetzte Schlüssel Einige Entitäten verwenden zusammengesetzte Schlüssel, z. B. FORMLIMITED: ENAME='X',TYPE='F'; AINVOCES: IVNUM='T9696',IVTYPE='A',DEBIT='D'. Geben Sie den vollständigen zusammengesetzten Schlüssel an entity_update und entity_delete weiter.


Projektstruktur

/
├── 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

Tests

Es gibt keinen automatisierten Testenable. Die Tests sind manuelle Skripte, die eine Live-Priority-Verbindung benötigen:

# 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

Warnung: Schreibtests werden echte Datensätze erstellen, aktualisieren und löschen. Führen Sie sie nur gegen ein Entwicklungsunternehmen aus.


Tech-Stack

  • Laufzeit: Node.js 18, ES-Module ("type": "module")

  • MCP-SDK: @modelcontextprotocol/sdk ^1.29.0

  • HTTP-Server: express ^4.21.1

  • HTTP-Client: axios ^1.7.7

  • Schema-Validierung: zur ^4.3.6`

  • Bundler: esbuild ^0.25.0 (über npm run build)

  • Weiteres: cors, dotenv, form-data, uuid, http-errors

A
license - permissive license
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • A
    license
    Not graded
    quality
    C
    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
    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
    D
    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.
    45
    27
    MIT

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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