Skip to main content
Glama
priority-mcp

Priority REST API MCP Server

by priority-mcp

Priority REST API MCP 服务器

一个将 AI 助手(Claude 及其他)直接连接到 Priority ERP 系统的 MCP 服务器。每个 OData 操作(查询、创建、更新、删除、批处理、附件、文本字段)都以 MCP 工具的形式暴露,使 AI 代理无需自定义集成代码即可读写实时业务数据。

版本: 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 令牌并打印到标准输出。请复制该令牌用于下一步。

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

面向 SSE 客户端的 JSON-RPC 消息

/health

GET

健康检查——返回版本和状态

/.well-known/oauth-authorization-server

GET

OAuth 2.1 发现(Claude Code ≥2.1.92 必需)

/authorize、/token、/register

GET/POST

OAuth 2.1 PKCE 流程——自动批准

注意: OAuth 2.1 端点的存在是为了满足 Claude Code 的 Streamable HTTP 连接握手要求。它们会自动批准所有请求,并非用于真正的访问控制——访问控制由 ODATA_MCP_TOKEN 处理。


身份验证

身份验证在两个独立的层面运行。

第 1 层——保护此服务器

所有路由(/health 和 OAuth 端点除外)都需要:

Authorization: Bearer <ODATA_MCP_TOKEN>

在 .env 中设置 ODATA_MCP_TOKEN。如果未设置,启动时会生成一个随机 UUID 并打印到标准输出。

第 2 层——调用 Priority ERP

由 PRIORITY_AUTH_TYPE 控制:

  • basic — 使用 PRIORITY_USERNAME + PRIORITY_PASSWORD 进行 HTTP Basic 认证

  • pat — 通过 PRIORITY_PAT 使用 Bearer 令牌

  • oauth2 — 与 pat 相同(将 PAT 作为 Bearer 令牌传递)

  • none — 不发送认证头(仅限本地测试)

写操作(POST/PATCH/DELETE)如果初始请求被拒绝,会自动获取 X-CSRF-Token 头并重试,遵循 Priority 的 CSRF 保护模式。

当设置了 PRIORITY_APP_ID 和 PRIORITY_APP_KEY 时,每个 Priority 请求都会发送可选的按应用程序许可头(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

OData 根 URL——格式: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

保护 /mcp 的 Bearer 令牌。未设置时使用随机 UUID。

PRIORITY_PAT

个人访问令牌(当 AUTH_TYPE=pat 或 oauth2 时)

PRIORITY_APP_ID

应用程序许可 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

Priority API 调用的读取超时(毫秒)

MCP_WRITE_TIMEOUT

15000

POST/PATCH/DELETE 操作的超时(毫秒)

MCP_PROC_TIMEOUT

45000

批处理操作的超时(毫秒)

TLS_REJECT_UNAUTHORIZED

false

生产环境中设置为 true 以拒绝自签名证书

调试

变量

默认值

描述

LOG_LEVEL

INFO

DEBUG 记录每个请求和响应

MCP_DEBUG

false

打印完整的 OData URL、参数、结果计数

PRIORITY_ENABLE_TRACE

false

为每个 Priority 请求添加 X-App-Trace: 1

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

在单个 $batch 请求中执行多个 POST/PATCH/DELETE,支持依赖链

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

文本字段

工具

描述

参数

entity_text_get

获取记录 /Text 子资源的富文本内容

entity、key

entity_text_create

向 /Entity(Key)/Text POST 新的文本内容

entity、key、textData

entity_text_update

对 /Entity(Key)/Text 上的现有文本内容执行 PATCH

entity、key、textData

附件

工具

描述

参数

entity_attachments_get

列出记录上的附件

entity、key

entity_attachments_upload

以 multipart/form-data 将文件上传到记录的 /Attachments 子资源。fileData 必须为 base64 编码

entity、key、fileData、fileName、contentType?

配置与帮助

Tool

Description

Parameters

instructions_get

返回完整操作指南:OData 语法、子表单模式、限流限制、日期处理规则、已知故障模式及架构示例。在探索不熟悉的实体时,请首先调用此工具

—

config_restflag_update

在 FORMLIMITED 表中设置 RESTFLAG=Y 或 N,以启用或禁用 Priority 表单的 REST API 访问

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 通过 esbuild 将 src/ 打包到 dist/,然后启动 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 将 API 调用限制为每个用户每分钟 100 次,最多 10 个并行请求,每次调用超时 3 分钟。设计代理时请尽可能批量处理操作。

响应上限 — MAXFORMLINES 无论 $top 如何设置,Priority 都会在 MAXFORMLINES 系统常量处静默截断响应。如果需要所有记录,请使用基于 $skip 的分页。

子表单不是独立实体 直接查询 PORDERITEMS_SUBFORM 会返回 HTTP 404。必须通过父实体并使用 $expand=PORDERITEMS_SUBFORM 访问子表单。metadata_schema_get 会自动检测此情况并重定向。

不支持 $apply=aggregate 由于此 Priority 版本不支持 $apply=aggregate(...),query_sum 始终回退到完整分页扫描。

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 编码 batch_operations 请求中的 URL 永远不会被自动编码。空格和特殊字符必须手动进行百分号编码(空格 → %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 Modules("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