内容
# Acumatica MCP 服务器




```
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⡖⠿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣞⡻⠉⢀⠀⠈⠳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡏⠀⡂⣸⣦⠀⠀⠘⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⠀⢻⠉⠻⠐⣭⡀⠀⠙⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢀⡀⠀⠀⠀⠀⠀⠀⢡⠤⠜⠂⠀⠀⠈⠘⠀⠀⠀⠱⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⣠⠞⠁⠙⢦⣀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠣⡀⠀⠀⠀⠀⠀⠀⠀⣀⠤⠤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⢸⡀⠀⠀⠀⠉⠳⣄⠀⠀⣹⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣠⣼⣶⣶⢒⣛⡻⢥⡤⣀⠀⢮⡗⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⢰⣶⣿⣿⣿⣾⣧⣤⣬⣤⣀⣙⣿⣤⣽⡆⠂⠂⡀⠀⠀⠀⠀⣀⠀⠠⠐⠂⠈⡋⣟⣿⣇⣠⡀⡼⣏⣉⡉⠱⣿⣿⣶⣶⠒⠒⠒⠒⠒⠒⠒⠒⠢⠤⢄⡀
⠀⠀⠀⠀⠉⠉⢛⣿⢿⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠄⠀⠀⠀⠀⠂⠂⠀⠉⣟⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣿⣷⣶⣶⣶⣶⣶⣶⣾⣿⠿⠛⠁
⠀⠀⠀⠀⠀⠀⠈⠛⢻⣿⣿⣿⣿⡏⢁⣀⣀⣠⣤⣤⡤⠀⢀⠀⠀⢀⡀⣀⣠⣤⣿⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⠿⢿⠟⠛⠋⠉⠉⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⣿⣿⡿⠿⠛⠛⠉⠀⠀⠒⢾⠤⠤⠤⠀⠚⠛⠉⢩⠙⠛⠛⠟⠿⣿⡿⢿⡿⣿⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣀⣿⣿⠟⢻⠁⠀⠀⢀⣀⣀⣀⣀⠤⠀⠀⠀⠀⠀⢀⣤⡤⠼⣴⣤⣤⣤⣤⣿⡿⠿⠛⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠠⢶⣶⣶⣿⣦⣤⣠⣿⣿⣶⣾⣿⣶⣿⣿⠿⠿⠛⠁⠀⠀⠀⠀⠤⠤⠶⠿⢿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠉⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣤⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⠿⠿⠿⠿⠙⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⣿⠟⢿⣿⣿⣿⣿⣿⡿⢻⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣸⡇⠀⣿⣿⣿⣿⠟⠀⢸⠋⠀⠀⠀⠀⠠⣤⣀⣄⣴⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⢀⡟⠀⢠⣿⣿⡟⠁⠀⠀⡸⠁⠀⠠⠀⠀⠁⠀⢉⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⣾⠀⠀⣼⡟⠁⠀⠀⠀⢠⡇⢀⢄⡞⠀⠀⡳⣴⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠈⠙⠚⠋⠀⠀⠀⠀⢀⣾⠇⠡⠈⠀⠀⢀⣾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠿⡆⠀⠀⢀⣴⠏⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣷⣶⣾⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
```
一款适用于 **Acumatica ERP** 的 [模型上下文协议](https://modelcontextprotocol.io)(MCP)服务器。它允许MCP客户端(Claude Desktop或任何MCP-aware代理)通过8个通用工具查询和操作**任何**Acumatica租户的基于合同的REST API。
Acumatica的合同API是统一的:每个实体(销售订单、账单、客户、库存项目等)都支持相同的`GET / PUT / DELETE`动词和OData查询参数,以及`POST /{Entity}/{Action}`用于实体特定操作。服务器不编码数百个端点,而是公开了涵盖整个表面(所有~119个实体)的8个工具,以及一个小型目录,教模型每个实体的字段、密钥格式和操作。
> **状态:** 测试版。经过实战测试。
## 目录
- [功能](#功能)
- [架构](#架构)
- [8个工具](#8个工具)
- [查询流程](#查询流程)
- [技能(重复工作流)](#技能(重复工作流))
- [要求](#要求)
- [安装](#安装)
- [配置](#配置)
- [注册到Claude Desktop](#注册到Claude-Desktop)
- [身份验证](#身份验证)
- [写入安全性(默认只读)](#写入安全性(默认只读))
- [重新生成实体目录](#重新生成实体目录)
- [安全说明](#安全说明)
- [先前艺术和相关项目](#先前艺术和相关项目)
- [许可证](#许可证)
- [免责声明](#免责声明)
## 功能
- **小且可读。** 一个服务器文件,约700行,三个依赖。你可以在信任它与你的ERP之前阅读整个文件。
- **完整的覆盖。** 8个通用工具可访问任何租户合同API的所有~119个实体,无需每个实体单独编码。
- **默认只读。** 写入和删除操作在显式启用之前保持禁用,因此指向生产环境时是安全的。
- **可移植。** 适用于任何具有服务帐户的Acumatica实例。
- **可点击的结果。** 记录返回带有`browser_url`,直接链接到Acumatica Web UI中的记录。
- **自我纠正的查询。** 错误返回可行的提示(错误字段名称、缺少必填筛选器、权限缺口)而不是原始HTTP 500错误。
- **重复的工作流。** 随附示例**技能** - 打包、测试的程序(AP/AR健康检查、三方匹配等),将原始工具转换为可靠的单命令操作。参见[技能](#技能(重复工作流))。
## 架构
```mermaid
flowchart LR
U[您] -->|自然语言| C[Claude / MCP 客户端]
C -->|MCP 工具调用| S[acumatica-mcp-server]
S -->|"cookie-auth REST + OData"| A[(Acumatica ERP)]
A -->|JSON 记录| S
S -->|"结果 + browser_url"| C
C -->|答案| U
```
服务器是一个薄的、无状态的翻译器:MCP工具调用进来,Acumatica REST调用出去。所有实体知识(字段、密钥、操作)都存储在数据目录(`entity_catalog.json`)中,因此工具保持通用。
## 8个工具
| 工具 | HTTP | 功能 |
| --- | --- | --- |
| `list_entities` | (本地) | 列出租户中可用的实体,可按子字符串筛选。 |
| `describe_entity` | (本地) | **首先调用此工具。** 返回实体的字段、密钥格式、操作和可扩展的子集合。 |
| `list_records` | `GET /{Entity}` | 查询记录并使用OData(`$filter`、`$select`、`$top`、`$expand`等)。 |
| `get_record` | `GET /{Entity}/{key}` | 按其密钥获取单个记录。 |
| `upsert_record` | `PUT /{Entity}` | 创建或更新记录。需要`ACUMATICA_ALLOW_WRITES=1`。 |
| `delete_record` | `DELETE /{Entity}/{key}` | 删除记录。需要`ACUMATICA_ALLOW_DELETES=1`。 |
| `invoke_action` | `POST /{Entity}/{Action}` | 运行操作(发布、取消、确认)。需要`ACUMATICA_ALLOW_WRITES=1`。 |
| `get_schema` | `GET /{Entity}/$adHocSchema` | 发现用户定义的(DAC扩展)字段和视图名称。 |
参见 **[docs/USAGE.md](docs/USAGE.md)** 获取字段名称、密钥格式、 `$filter` 和 `$custom` 规则,使查询可靠。
## 查询流程
黄金法则:**首先调用`describe_entity`。** 大多数失败都是由于猜测字段名称或密钥格式引起的。
```mermaid
flowchart TD
Q[需要数据或操作] --> LE[list_entities: 查找实体]
LE --> DE[describe_entity: 字段、密钥格式、操作]
DE --> RW{读取或写入?}
RW -->|读取| RD[list_records / get_record]
RW -->|写入| G{网关启用?}
G -->|"ALLOW_WRITES / ALLOW_DELETES 已设置"| WR[upsert_record / delete_record / invoke_action]
G -->|未设置| BL[403 阻止:默认只读]
```
## 技能(重复工作流)
8个工具为模型提供原始动词。**技能** 将这些动词转化为可重复、可测试的工作流:确切的查询、回退和输出格式,用于一个真实任务,一次编写,因此模型每次都能正确运行。 [`skills/`](skills/) 文件夹提供了一套可直接使用或适应的启动器:
| 技能 | 功能 |
| --- | --- |
| [`recent-records`](skills/recent-records/SKILL.md) | 可靠地查找任何实体的最新/最近记录(适用于忽略 `$orderby` 的租户)。 |
| [`ap-health`](skills/ap-health/SKILL.md) | 应付账款健康检查:老化桶、过期账单、陈旧PO、未发票收货。 |
| [`ar-health`](skills/ar-health/SKILL.md) | 应收账款健康检查:开放AR、老化、未应用付款、客户集中度。 |
| [`three-way-match`](skills/three-way-match/SKILL.md) | 逐行核对账单 vs 采购收货 vs PO 行并标记价格/数量差异。 |
| [`doc-doctor`](skills/doc-doctor/SKILL.md) | 诊断文档为何卡住或错误(接收失败、错误总额、扣留)并提出修复方案。 |
每个技能都是一个单独的 `SKILL.md`,具有前置元数据,采用Claude Code / Claude Desktop技能的格式。将其放入客户端发现技能的文件夹(例如项目的 `.claude/skills/`),并按名称调用。所有五个都是只读报告工作流;它们都不写入租户。
## 要求
- 具有启用**基于合同的REST API**的Acumatica实例(默认`Default`端点,例如版本`24.200.001`)。
- 具有适当角色的**专用服务/集成帐户**。
- **Python 3.10+**。
## 安装
克隆存储库并安装其依赖项:
```bash
git clone https://github.com/yourlastnamesoundslikeatypeofpasta/acumatica-mcp-server.git
cd acumatica-mcp-server
python -m venv .venv
# Windows: .venv\Scripts\activate
# macOS/Linux: source .venv/bin/activate
pip install -r requirements.txt
```
## 配置
服务器从环境变量中读取其连接设置。有两种提供它们的方法,您只需要**一个**(您永远不会输入两次凭证):
- **选项A:MCP客户端`env`块(推荐)。** 将值放入MCP客户端配置中(参见[注册到Claude Desktop](#注册到Claude-Desktop))。 不会写入磁盘,不需要`.env`文件。
- **选项B:`.env`文件。** 复制[.env.example](.env.example)到`server.py`旁边的`.env`并填写。您的MCP客户端配置只需要`command`/`args`,不需要凭证。
```ini
ACUMATICA_BASE_URL=https://your-instance.acumatica.com
ACUMATICA_ENDPOINT_PATH=/entity/Default/24.200.001
ACUMATICA_USERNAME=service_account
ACUMATICA_PASSWORD=your-password
ACUMATICA_COMPANY=YourCompany
```
如果您同时设置两者,则`env`块(进程环境)获胜,而`.env`文件仅填充它未设置的内容。
## 注册到Claude Desktop
将以下内容添加到您的 `claude_desktop_config.json`(完整示例在[`docs/claude-desktop-config.example.json`](docs/claude-desktop-config.example.json)`)。这是**选项A**:凭证位于`env`块中。如果您使用`.env`文件(选项B),请从`env`中删除`ACUMATICA_*`凭证密钥:
```json
{
"mcpServers": {
"acumatica": {
"command": "python",
"args": ["C:/path/to/acumatica-mcp-server/src/acumatica_mcp/server.py"],
"env": {
"ACUMATICA_BASE_URL": "https://your-instance.acumatica.com",
"ACUMATICA_ENDPOINT_PATH": "/entity/Default/24.200.001",
"ACUMATICA_USERNAME": "service_account",
"http://localhost:8080",
"ACUMATICA_PASSWORD": "your-password",
"ACUMATICA_COMPANY": "YourCompany"
}
}
}
}
```
重启Claude Desktop,然后尝试:“列出最近 14 天内修改的开放销售订单”或“描述 Bill 实体。”
## 身份验证
基于cookie。服务器在第一个请求时登录,持有会话cookie,在401时透明地重新登录,并在退出时注销。
```mermaid
sequenceDiagram
participant S as acumatica-mcp-server
participant A as Acumatica
S->>A: POST /entity/auth/login (第一个请求)
A-->>S: 会话cookie
S->>A: GET / PUT / POST /{Entity}
A-->>S: 200 + 数据
Note over S,A: 401 时,重新登录一次并重试
S->>A: POST /entity/auth/logout (退出时)
```
## 写入安全性(默认只读)
三个变体工具**默认禁用**。通过环境变量显式启用它们:
| 变量 | 启用 |
| --- | --- |
| `ACUMATICA_ALLOW_WRITES=1` | `upsert_record` 和 `invoke_action` |
| `ACUMATICA_ALLOW_DELETES=1` | `delete_record` |
当禁用变体工具时,它会返回一个`403`-style信封,其中包含一个提示,告诉您要设置哪个变量。不会向Acumatica发送请求。
## 重新生成实体目录
捆绑的`entity_catalog.json`涵盖标准Acumatica实体。如果您的租户有自定义(自定义实体、扩展字段),请从租户的OpenAPI规范重新生成它:
1. 在Acumatica中,打开您的端点下的**Web Service Endpoints**并导出其OpenAPI(Swagger)JSON,或`GET {BASE_URL}{ENDPOINT_PATH}/swagger.json`。
2. 重建:
```bash
python src/acumatica_mcp/rebuild_catalog.py path/to/your_openapi_spec.json
```
3. 重新启动服务器(目录在启动时加载一次)。
## 安全说明
- **默认只读。** `upsert_record` 和 `invoke_action` 需要`ACUMATICA_ALLOW_WRITES=1`;`delete_record` 需要`ACUMATICA_ALLOW_DELETES=1`。仅在需要时显式启用,理想情况下在沙盒租户中。
- **使用专用服务帐户**,仅限于您需要的实体/角色,而不是真实人员的登录帐户。Acumatica中的只读角色是第二层防御的好方法。
- `.env` 被 git 忽略。 将凭证排除在版本控制之外;最好通过 MCP 客户端的 `env` 块传递。
## 先前艺术和相关项目
这不是第一个Acumatica-to-MCP或Acumatica-to-AI项目。如果这个项目不适合您的需求,请查看这些:
- [grp-mcp](https://github.com/Arvindh95Censof/grp-mcp):一个更强大的MCP服务器,具有完整的CRUD、四个客户端平面和无头ERP设置。
- [MCP4Acumatica](https://github.com/hallboys/MCP4Acumatica):一个远程MCP服务器(Cloudflare Workers),具有每用户OAuth和基于角色的只读访问。
- [easy-acumatica](https://github.com/Nioron07/Easy-Acumatica):一个成熟的Python REST SDK(不是MCP),具有动态模型生成。
- [CData Acumatica MCP Server](https://github.com/CDataSoftware/acumatica-mcp-server-by-cdata):一个由CData JDBC驱动程序支持的只读MCP。
这个服务器的角度是刻意的极简主义:一个小巧、依赖性轻、可自行托管的标准输入/输出服务器,您可以阅读整个服务器并在一次就运行它,适用于任何租户,只有服务帐户。
## 许可证
[MIT](LICENSE) (c)Christian Zagazeta
## 免责声明
不隶属于或得到Acumatica, Inc.的认可。“Acumatica”是其各自所有者的商标。请自担风险在您自己的租户上使用。