Priority REST API MCP Server
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 install2. .env aus dem Beispiel erstellen
cp .env.example .envMindestens 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=mypassword3. Server starten
# Development (from source)
node src/index.js
# Production (bundled)
npm run build
node dist/index.jsBeim 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 |
| POST | Primärer MCP-Endpunkt (Streamable HTTP) |
| GET | SSE-Stream – erfordert |
| POST | JSON-RPC-Nachrichten für SSE-Clients |
| GET | Health-Check – gibt Version und Status zurück |
| GET | OAuth-2.1-Discovery (erforderlich für Claude Code ≥2.1.92) |
| 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_TOKENabgewickelt.
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 mitPRIORITY_USERNAME+PRIORITY_PASSWORDpat– Bearer-Token überPRIORITY_PAToauth2– wiepat(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 |
| OData-Stamm-URL – Format: |
|
|
| Benutzername – erforderlich bei |
| Passwort – erforderlich bei |
Priority-Authentifizierung (optional)
Variable | Beschreibung |
| Bearer-Token zum Schutz von |
| Persönliches Zugriffstoken (bei |
| Anwendungslizenz-ID – wird als |
| Anwendungslizenzschlüssel – wird als |
| Überschreibt den |
HTTP-Server
Variable | Standard | Beschreibung |
|
| Bindungsadresse |
|
| Lauschport |
|
| Aktiviert den |
Timeouts & TLS
Variable | Standard | Beschreibung |
|
| Lese-Timeout für Priority-API-Aufrufe (ms) |
|
| Timeout für POST/PATCH/DELETE-Operationen (ms) |
|
| Timeout für Stapeloperationen (ms) |
|
| In Produktion auf |
Debugging
Variable | Standard | Beschreibung |
|
|
|
|
| Vollständige OData-URLs, Parameter und Ergebnisanzahlen ausgeben |
|
| Fügt jeder Priority-Anfrage |
|
| Wirft Fehler bei leeren/Mock-API-Antworten – nur für Tests deaktivieren |
| — | Pfad zur |
Tools
Alle 19 Tools sind in src/tools/ definiert und in src/tools/priorityTools.js registriert.
System & Metadaten
Tool | Beschreibung | Parameter |
| Die Version des Priority-Dienstes und die Antwort-Header abrufen | — |
| Alle OData-Entitätssets auflisten; nur auf REST-fähige Formulare filtern |
|
| Feld-Schema für eine Entität abrufen, indem ein Beispieldatensatz abgerufen wird. Leitet Unterformularnamen automatisch auf übergeordnetes Formular + |
|
| Serverseitigen Metadaten-Cache leeren und aktualisieren. Führt immer einen vollständigen Flush durch (siehe Bekannte Einschränkungen) |
|
Abfragen
Tool | Beschreibung | Parameter |
| Einen einzelnen Datensatz per Schlüssel oder Lookup abrufen, mit optionalem |
|
| Eine OData-Abfrage mit vollständiger Filter-/Select-/Top-/Skip-/Orderby-/Expand-/Count-Unterstützung ausführen. Validiert Datumsfilter-Ergebnisse nach dem Abruf |
|
| Wie |
|
| Ein numerisches Feld über eine Entität mit optionalem Filter summieren. Versucht zuerst |
|
Erstellen / Aktualisieren / Löschen
Tool | Beschreibung | Parameter |
| Einen neuen Datensatz erstellen. Unterstützt Unterformular-Erstellung über |
|
| Einen Datensatz per PATCH mit |
|
| Einen Datensatz per DELETE mit |
|
| Mehrere POST/PATCH/DELETE-Operationen in einer |
|
Textfelder
Tool | Beschreibung | Parameter |
| Den Rich-Text-Inhalt der |
|
| Neuen Textinhalt per POST an |
|
| Vorhandenen Textinhalt per PATCH auf |
|
Anhänge
Tool | Beschreibung | Parameter |
| Anhänge eines Datensatzes auflisten |
|
| Eine Datei als multipart/form-data in die |
|
Konfiguration & Hilfe
Tool | Beschreibung | Parameter |
| 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 | — |
| Setzt |
|
Prompts & Ressourcen
Der Server registriert MCP-Prompts (wiederverwendbare Anweisungsvorlagen) und Ressourcen (Live-Daten-Endpunkte).
Prompts (src/prompts/)
Name | Zweck |
| Leitfaden zum Erstellen von OData-Abfragen gegen eine Entität |
| Erläutert die Subformular-Hierarchie einer bestimmten Entität |
| Führt durch Erstellungs-, Aktualisierungs- und Löschoperationen |
| Wichtige Regeln für Datumsfilter — ISO-Format, Operatorvalidierung |
| Dokumentierte 404/501/400-Muster und ihre Workarounds |
| Erläutert |
Ressourcen (src/resources/)
URI | Zweck |
| Live-Liste aller REST-fähigen Entitäten ( |
| Schema für eine bestimmte Entität (Template-URI) |
| Bibliothek einsatzbereiter Abfragebeispiele |
| 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+descAntwort:
{
"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 UTCZ. Verwenden Sie in Datumsfiltern die SyntaxCURDATE 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-mcpDas 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_TOKENexplizit — verlassen Sie sich nicht auf das automatisch generierteSetzen Sie
TLS_REJECT_UNAUTHORIZED=trueSetzen Sie
STRICT_DATA_INTEGRITY=true(Standard)Setzen Sie
LOG_LEVEL=INFO(Standard — unterdrückt Systemrauschen)Binden Sie
HTTP_HOSTan 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 descriptionsTests
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.jsWarnung: 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.0HTTP-Server:
express ^4.21.1HTTP-Client:
axios ^1.7.7Schema-Validierung:
zur^4.3.6`Bundler:
esbuild ^0.25.0(übernpm run build)Weiteres:
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