Skip to main content
Glama
NologyAcu

MCP4Acumatica

by NologyAcu

MCP4Acumatica

免责声明: 本项目是一个独立的、由社区构建的集成,与 Acumatica, Inc. 无关,亦未获得其认可或支持。“Acumatica” 是 Acumatica, Inc. 的注册商标。使用 Acumatica 名称和 API 仅用于互操作性目的。

一个远程 Model Context Protocol (MCP) 服务器,将 Claude 连接到 Acumatica ERP 2025 R2。它运行在 Cloudflare Workers 上,并针对你的 Acumatica 实例进行按用户 OAuth 身份验证。

每个用户使用自己的 Acumatica 凭据进行身份验证。他们的 Acumatica 角色决定了他们可以访问哪些记录。此外,MCP 服务器还要求用户具备特定 Acumatica 角色并确认相关条款,并在数据到达 AI 模型之前自动对敏感字段进行脱敏处理。

功能特性

  • 49 个工具 —— 38 个只读查询 + 6 个实用/发现 + 4 个 schema 知识 + 1 个写入工具(客户创建/更新,默认禁用)(见 可用工具

  • 按用户 OAuth —— 用户使用其 Acumatica 凭据(或 SSO)登录

  • 基于角色的访问 —— Acumatica 的安全模型决定每个用户能查看到什么

  • 访问门 —— 只有能够读取指定金丝雀 Generic Inquiry 的用户才能连接(你可以根据喜好以任何方式限制它;推荐使用如 MCP Access 这样的标记角色)

  • 同意确认页 —— 用户在访问工具前必须确认知晓 AI 数据处理

  • 敏感字段脱敏 —— SSN、银行账户、薪资及其他个人敏感信息(PII)字段会在数据离开服务器之前自动脱敏

  • 速率限制 —— 默认情况下,每个用户并发请求 3 次、每分钟 40 次,两者都可以在管理控制台中调整。当请求发现所有并发槽位都被占用时,它会将短暂等待一个空位而不是直接失败;并且拒绝时会返回一个结构化封装 { error: "ratebum", retryAfterSeconds, actionRequired },告知 AI 具体需要等待多久,而不要盲目重复重试

  • 分页拒绝 —— 当结果达到记录上限时,列表/查询工具会返回结构化封装 { truncated, paginationisDisabled: false, actionRequired },指示 AI 让用户提供更精确的筛选条件,而不是再次调用该工具

  • 结构化审计日志 —— 所有工具调用、认证事件和字段脱敏均会被记录

  • 管理控制台 —— 位于 /docs/admin 的 Web 管理界面,无需重新部署即可查看日志并管理运行时设置

  • 较长时期的日志保留 —— 通过 Cloudflare Logpush 使用 R2 实现持久化日志存储,并提供可搜索的日志浏览器

架构

Claude (claude.ai / Desktop / API)
    |
    v  MCP over streamable-http
+----------------------------------+
|  Cloudflare Worker               |
|  OAuth 2.1 Provider              |
|    /authorize -> Acumatica login |
|    /callback  <- Acumatica       |
|    (access gate + OIDC userinfo) |
|    /consent   -> AI data consent |
|    /token, /register (DCR)       |
|    /mcp -> McpAgent DO (49 tools)|
+---------------+------------------+
                |  Bearer token (per-user)
                v
        Acumatica 25R2 SaaS
        Contract-Based REST API
        Default/25.200.001

前置要求

  • Node.js >= 18

  • 一个 Cloudflare 账户(Durable Objects 需要 Workers 付费套餐)

  • 已完成以下配置:一个 Acumatica 2025 R2 实例:

    • 在 SM303010 中配置了一个 Connected Application,使用 Authorization Code OAuth 2.0 流(范围scope由服务器在请求中发送,不是应用本身配置的)

    • 一个指向你 Worker /callback 结束点的重定向 URI

    • 一个 MCPAccess Generic Inquiry(SM11104)—— 一个简单的 canary GI,已启用 Expose via OData;登录访问门检查对该 GI 的读取权限(详见 架构文档)。GI 名称可通过 ACUMATICA_CANARY_GI 配置。

    • 一种限制谁能读取该 GI 的方式 —— 推荐方式是为被默认允许的用户分配一个标记角色 MCP Access 角色(SM201005)

安装设置

共有三种安装路径。三条路径都依赖于相同的 Acumatica 端必备条件 —— 无论你选择哪条路径,都首先要完成这些前置步骤(见下方“Acumatica 侧配置”)。

路径

适用场景

需要终端?

A. Deploy 到 Cloudflare 按钮

可完全通过界面进行安装的用户

B. 一键安装脚本

已经安装 git / node / npm 的开发者

需要终端(一条命令)

C. 手动设置

任何希望逐步查看每一步或想逐阶段操作的用户

路径 A —— Deploy 到 Cloudflare 按钮(无需终端)

Deploy to Cloudflare

该按钮会将此仓库 fork 到你的 GitHub 账户,读取 wrangler.jsonc,自动创建一个 KV 命名空间和 R2 bucket,提示输入 secrets 并进行部署。逐步操作:

  1. 单击按钮。 Cloudflare 会要求你登录(或注册账户)并授权 GitHub fork.

  2. 确认绑定。 系统会提示你创建 两次 KV 命名空间 —— 一次用于 TOKEN_STORE (应用数据:令牌(token)、OAuth 状态、缓存、配置、管理后台会话),另一次用于 OAUTH_KV(OAuth 库内部使用)。这是预期行为:它们两个是独立的绑定,不共享 key。

    ⚠️ 给两个命名空间 不同的 名称**(例如,TOKEN_STORE 绑定为 mcp4acumatica-appOAUTH_KV 绑定为 mcp4acumatica-oauth)。Cloudflare 的自动供给会从 Worker 名称派生默认标题,因此 **两个字段都会默认使用 mcp4acumatica,而使用相同标题创建两个命名空间会失败,并报 "Cannot provision a KV Namespace with the title … because it already exists."。如果你已经遇到该错误,****会留下一个未完成的命名空间:请前往 存储与数据库 → KV 中删除孤立的 mcp4acumatica 命名空间,然后使用两个不同名称重试。 (Cloudflare 的 GUI 自动提供功能无法让两个绑定指向同一个命名空间,配置文件也无法预先设置不同的标题 —— 因此,创建两个可使用两个不同的命名空间。如果 GUI 仍然不够成功,请使用下方的终端安装路径:setup.sh 创建一个命名空间并同时绑定两个命名空间。)

    R2 bucket(mcp4acumatica-logsmcp4acumatica-index)也以相同方式创建,但它们的名称在 wrangler.jsonc 中是固定的,因此不会冲突。

  3. 设置 secrets。 当提示时,请粘贴以下内容:

    • ACUMATICA_CLIENT_ID —— 来自你的 Connected Application(SITware)

    • ACUMATICA_CLIENT_SECRET —— 来自同一屏幕

    • COOKIE_ENCRYPTION_KEY —— 打开浏览器开发工具控制台,在任意页面执行:

      [...crypto.getRandomValues(new Uint8Array(32))].map(b => b.toString(16).padStart(2,'0')).join('')

      复制该字符串生成的 64 字符十六进制字符串。

    • ADMIN_SECRET —— 任何你能记住的密码(保护 /docs/admin 控制台)。如果没有特别偏好,请通过运行 [...crypto.getRandomValues(new Uint8Array(24))].map(b => b.toString(16).padStart(2,'0')).join('') 生成。

  4. 部署。 Cloudflare 将 fork 连接至 Cloudflare 构建功能,并部署初始版本。

  5. **更新 Acumatica 变量。**部署完成后,在 Cloudflare 面板中打开 Workers & Pages → mcp4acumatica → Settings → Variables and Secrets 并编辑:

    • ACUMATICA_URL(例如 https://yourcompany.acumatica.com

    • ACUMATICA_TENANT (你的登录公司)

    • 可选项:ACUMATICA_MAX_RECORDSACUMATICA_CANARY_GIP3_PATTERNSREDACT_SKIP 点击 Save and Deploy —— Cloudflare 会使用新值重新部署。

  6. 为 Connected Application 添加 redirect URI。 现在可以通过 https://mcp4acumatica.<your-account>.workers.dev 访问你的 Worker。将下面这个地址添加到 Acumatica SM303010 屏幕的 redirect URI:https://<that-host>/callback (如需自定义域名,请参阅下方的“自定义域名”)。

  7. 测试部署。 访问 https://<your-host>/docs/admin/preflight 域名,使用你的 ADMIN_SECRET 登录,然后运行预检诊断。它会检查 Acumatica 网络连通、OIDC 找保发现端点、Connected Application 凭据、租户路径和 contract API 版本。

之后 Claude 就可以连接了(参见下方“连接 Claude”)。

路径 B —— 一键安装(终端)

如果你已经安装 gitnodenpm,请运行:

curl -fsSL https://mcp4acumatica.hallboys.com/install.sh | bash

这会克隆仓库,安装依赖,并运行 ./setup.sh。设置脚本会提示你必须提供的 Acumatica 参数(URL、租户、Connected Application 客户端 ID 和 secret),自动生成加密 secrets,创建 KV 命名空间和 R2 bucket,上传 secrets,部署,并运行预检。

如果你想先查看脚本内容:

curl -fsSL https://mcp4acumatica.hallboys.com/install.sh -o install.sh
less install.sh   # read it
bash install.sh   # then run

路径 C —— 手动设置(终端)

1. 克隆仓库并安装依赖

git clone https://github.com/hallboys/MCP4Acumatica.git
cd MCP4Acumatica
npm install

2. 创建 KV 命名空间

npx wrangler kv namespace create TOKEN_STORE

请从输出中记录命名空间 ID —— 下一步需要将其粘贴到 wrangler.jsonc 中。相同的 ID 用于其余 TOKEN_STOREOAUTH_KV 绑定。

3. 配置 wrangler

wrangler.jsonc 在仓库中作为部署模板存在。请直接编辑并填写以下内容:

  • 步骤 2 中获取的 KV 命名空间 ID(TOKEN_STOREOAUTH_KV 绑定使用同一个 ID)

  • ACUMATICA_URL —— 你的 Acumatica 实例 URL(例如 https://yourcompany.acumatica.com

  • ACUMATICA_TENANT —— 你的 Acumatica 公司/租户名称

如果你希望让本地值不能跨越 git status(以便后续拉取更新时不冲突),可以使用以下命令:

git update-index --skip-worktree wrangler.jsonc

4. 设置或部署 secrets

npx wrangler secret put ACUMATICA_CLIENT_ID
npx wrangler secret put ACUMATICA_CLIENT_SECRET
npx wrangler secret put COOKIE_ENCRYPTION_KEY      # use `openssl rand -hex 32`
npx wrangler secret put ADMIN_SECRET                # any password — protects /docs/admin

5. 部署

npx wrangler deploy

6. 本地开发(可选)

cp .dev.vars.example .dev.vars
# Edit .dev.vars with your Acumatica credentials
npx wrangler dev

Acumatica 端环境配置

无论选择哪种安装方式,以下步骤都需要完成。无法自动化完成 —— Acumatica 的 API 不提供相关操作。

连接应用(SM303010)

  1. 在 Acumatica 中:开始 > 集成 > 已连接应用程序(SM303010)。

  2. 创建新的 Connected Application。

  3. OAuth2 flow 设置为 Authorization Code

  4. 添加一个重定向 URI:https://<your-worker-url>/callback (使用 *.workers.dev 主机名或您的自定义域名)。

  5. 记下 Client IDClient Secret —— 你将在部署时提供这些值。

这里没有需要配置的作用域字段。OAuth 范围(api openid profile email offline_access,包括让 Acumatica 颁发刷新令牌的 offline_access)将已发送过的 MCP 服务器支持的授权请求中 —— 它们不是预先配置在 Connected Application 中的。

访问门:Canary Generic Inquiry(SM208001, SM201005)

在用户可以使用 AI 工具之前,登录流程会执行一道 门禁检查:它过 OData 查询一个简单的 canary Generic Inquiry,检查用户令牌能否读取它(200 → 允许,403 → 拒绝)。服务器不会检查用户的 Acumatica 角色成员 —它是根据请求“你能读取这个 GI 吗?” 判断。你可以按照自己的安全模型限制谁能读取该 canary GI;推荐使用一个标记角色,这是最便捷。

  1. 创建 canary GI: System > Customization > Generic Inquery (SM208000) → 创建一个命名为 MCPAccess 的任何简单查询(单个字段,来自任何表都可以)的可执行 IN。选择 Expose via OData

  2. 限制谁能读取它(推荐使用标记角色): System > Access Rights > User Roles (SM201005) → 创建一个名为 MCP Access 的角色,不要为此分配任何屏幕权限,仅将该 MCPAccess GI 分配此角色,然后将该角色分配每个应拥有 AI Assistant 访问权的用户。任何其他控制 GI 的 OData 读取权限的机制都可以。

canary GI 名称通过 ACUMATICA_CANARY_GI 变量(默认为 MCPAccess)配置。可在 Cloudflare 仪表板(Variables and Secrets)或 wrangler.jsonc 中修改。

将 Generic Inquiry 暴露给 AI(强烈推荐)

一个成熟的 Acumatica 实例可能包含数百个 Generic Inquiries,其中大多数是为人工屏幕构建的(宽幅报表网格、仪表板、临时查询)。如果将这些 GI 全部暴露给助手,会淹没它的上下文,使其选错查询——而且更糟糕的是,通过 OData 暴露的参数化 GI 会静默返回错误数据:在未带参数查询时,Acumatica 返回的是默认的、未筛选的行,并且毫无报错,模型无法察觉到这一点。GI 暴露门控将这一机制改为 Opt-in 方式:你为这些对 AI 智能体真正有用、且查询结果正确的是 GI 打上标签,通用查询(ExposedToMCP)——而模型只看到这些。

该门控在配置之前处于未激活状态——服务器正常运行,但如果未配置注册表,助手会无法发现 GIacumatica_list_generic_inquiries 会返回空;用户仍可通过精确名称运行 GI)。配置它可以为助手提供一组经过精选、可安全发现的 GI。启用它需要一次一次性的 Acumatica customization project——该项目已内置在 acumatica/ 中,添加了日历自定义字段 UsrExposedToMCP(固定)和 UsrAIDescriptionGIDesign) 两个字段,以及 UsrResAIDescriptionGIResult)和 SM208000 表单变更——然后使用 MCPGIs / MCPGIFields 这两个 Feed GI,为 MCP 访问(MCP Access)角色授予 feed 的读取权限,并对你希望暴露的 GI 打标。参见 docs/generic-inquiries.md

关于完整的背景说明、曝光哪些 GI 和以及针对逐步设置,请参阅 Generic Inquiries/Hat

Custom domain (optional)

部署后你有 现有的 *.workers.dev 作为默认主机名。如需绑定品牌域名:

  • 通过 Cloudflare dashboard: Workers & Pages → mcp4acumata → Settings → Domains & Routes → Add。该域名的 zone 必须位于你的 Cloudflare 账户中。

  • 通过 wrangler.jsonc:取消文件顶部 routes 块的注释,修改 patternzone_name,然后重新部署。

如果是修改/更换主机名,请记得将新的 https://<host>/callback 添加到连接的应用的 SM303010 的 redirect URIs 中。

连接 Claude

Claude..ai / Claude Desktop

  1. 前往 Settings > Connectors

  2. 点击 Add Connector 并输入同理:https://<your-worker-url>/mcp

  3. 首次使用时会重定向到你的 Acumatica 登录页

  4. 如果你的账户可以读取 canary GI(也就是已获得权限),则会看到说明 AI 数据处理的同意页面

  5. 同意后,Claude 将拥有全部 49 个工具的访问权限

Claude Code (CLI)

claude mcp add acumatica-erp --transport streamable-http https://<your-worker-url>/mcp

API (via Anthropic SDK)

在通过 Anthropic API 使用 MCP 时,请让 MCP 渲染器指向 https://<your-worker-url>/mcp。该服务在 /register 上支持使用 Dynamic Client Registration 的写法/方式.

可直接工具

Core / 核心

工具

说明

acumatica_get_customer

客户记录,包含联系人信息、信用规则、余额

acumatica_get_vendor

供应商记录,包含联系人、条款、税务信息

acumatica_get_sales_order

销售订单,含行项目、未计项目和配送信息

Financial / 融资

工具

说明

acumatica_get_invoice

AR 发票,含行项目与税务明细

acvasive_get_bill

AP 账单,含行项目与 PO 关联

acumatica_get_journal_transaction

GL 总账结算批,含借贷明细

acumatica_get_payment

AR 收款,包含已对应单据和订单

acumatica_get_account

GL 会计科目表查询

acumatica_get_check

AP 荚/供应商付款和历史

库存与仓库

工具

说明

acumatica_get_stock_item

库存物料,含定价、仓库数量、供应商

acumatica_get_non_stock_item

非库存物料(服务、人工、费用)

acumatica_get_inventory_quantity_available

跨仓库实时可订数量

acumatica_get_inventory_summary

按仓库聚合的库存余额

acumatica_get_warehouse

仓库,含库位与设置

acumatica_get_item_class

物料分类默认值

采购

工具

说明

acumatica_get_purchase_order

PO,含行项目、供应商、总计

acumatica_get_purchase_receipt

采购入账/收货,含已接收数量与 PO 关联

项目

工具

说明

acumatica_get_project

项目头、状态、财务信息

acumatica_get_project_task

项目内任务

acumatica_get_project_trend

预算行,实际与预算对比

acumatica_get_project_transaction

项目成本/收入交易明细

服务与现场

工具

说明

acumatica_get_case

支持工单,含 SLA、优先级、时间跟踪

acumatica_get_service_order

现场服务订单,含明细与预约

acumatica_get_appointment

计划/实际执行时间、人员、成本/利润

销售与 CRM

工具

说明

acumatica_get_contact

CRM 联系人,含地址、电话、负责人

acumatica_get_business_account

统一潜在客户/客户/供应商记录

acumatica_get_opportunity

销售机会,含产品和金额

acumatica_get_lead

营销线索,含状态与来源

acumatica_get_salesperson

销售代表,含佣金设置

运输与履单

工具

说明

acumatica_get_shipment

货件,含包裹、物流跟踪、运费

acumatica_get_sales_invoice

销售发票,含 SO/出货关联

HR 与薪资

工具

说明

acumatica_get_employee

员工,含联系方式及财务设置

acumatica_get_expense_claim

费用报销,含行项目与审批

acumatica_get_time_entry

工时记录,含项目、可计费/加班

CRM 活动

工具

说明

acumatica_get_email

电子邮件活动,含发件人/收件人/正文

acumatica_get_event

日历事件,含参与者

acumatica_get_activity

一般 CRM 活动

acumatica_get_task

CRM task(任务)及关联活动

工具 / 发现

工具

说明

acumatica_run_inquiry

通过过滤条件运行已配置的 GI 查询

acumatica_list_entities

通过 OData 筛选、排序、字段选择,列出/搜索实体

acumatica_describe_entity

探索实体的字段、类型和子实体

acumatica_list_generic_inquiries

列出所有已通过 OData 暴露的 GI

acumatica_describe_inquiry

运行 GI 前,推断其字段结构

acumatica_clear_cache

schema 变化时清除缓存的元数据

提示: 先从 acumita_get_describe_entity 开始发现可用字段,然后使用 acumatica_get_list_entities 搜索/筛选。对于 Generic Inquiry,使用 acumatica_list_generic_inquiries 查找 GI 名称,使用 acumatica_describe_inquire 查看可用字段。典型用法示例参见 docs/example-prompts.md

文档

更详细的文档位于 docs/ 文件夹中:

  • Tool References — 所有 49 个工具的完整规格,含参数和端点

  • Example Prompts — 针对 Claude & other MCP client 的提示示例,按用例分

  • OData Filtering Guide$filter$operator ...

  • Generic Inquiries — 为什么要 GI 为 AI 使用 Gate,哪些 GI 想暴露,以及如何启用opt-in 注册

  • Schema Knowledge — 用于构建集成/自定义的 schema 发现工具,覆盖 schema 索引的构建方式

  • Architecture — 详细架构、OAuth 流程、安全性模型与设计决策

  • Self-Hosting Guide — 如何在 Node.js 或其他平台/环境上:不限于 非 Cloudflare,运行 MCP server

  • Upgrading Acumatica — 升级/更改 Acumatica 版本间需要进行的步骤

Skills(技能)

仓库内置了与 Claude 复用技能库 [skills/ 内:

  • acuma-gi-actions/de~ — 从为其 Generic Descriptions(共 GI 描述)及其结果列编写面向 AI 的说明,进行端到端流程,工作方式是从 GI 自身的设计元数据(表、连接、WHERE、列)出发,而非根据名字盲猜。同时包括会“让 GI Metadata 批量工作悄然失败”的平台踩坑点,一份值得重点检查的设计信号清单,以及三个脚本分别用于截断审计、设计简报、草稿验证。

如需采用,可把 Claude 指向该技能目录,也可自己复制到你的 .claude/skills/ 目录中。

安全

  • 不存储凭据。 MCP 服务器不存储 Acumatica 密码。它使用 OAuth 2.0 授权码流程 —— 用户直接与 Acumatica 进行身份验证。

  • 用户级令牌。 每个用户的 Acumatica 访问令牌存储在平台键值存储中(默认部署为 Cloudflare KV),作用域限定为用户用户名。令牌过期后会自动刷新。如果刷新令牌过期,连接会自动重新认证,而无需手动重新连接。

  • 访问门禁。 只有能够读取指定金丝雀 Generic Inquiry 的用户才能连接。服务器在登录时通过 OData 检查 GI 可读性(而非角色成员身份);没有访问权限的用户会看到访问被拒绝的页面。你可以随意限制该 GI —— 推荐的方式是使用一个名为 MCP Access 的标记角色。GI 名称可根据环境配置 ACUMATICA_CANARY_GI 设置。

  • 同意确认页。 通过访问检查后,用户必须先确认其数据将由外部 AI 模型处理,之后 MCP 会话才会激活。

  • 敏感字段脱敏。 工具响应会自动扫描敏感字段名(SSN、银行账户、薪资、信用卡等),并将匹配到的值替换为 [REDACTED]。匹配规则可通过 REDACT_PATTERNSREDACT_SKIP 环境变量配置。

  • 基于角色的访问控制。 用户的 Acumatica 角色决定其可以读取哪些记录。如果用户在 Acumatica 中无权访问某条记录,那么也无法通过 MCP 服务器访问该记录。

  • 只读。 目前所有工具均为只读查询。不会创建、修改或删除任何数据。

  • 速率限制。 默认限制为 3 个并发请求、每分钟 40 个请求,以及每次查询 1000 条记录上限 —— 全部可在管理控制台 /docs/admin/settings 中配置,无需重新部署。限制按用户计算,并统计对 Acumatica 的 HTTP 调用次数(而非工具调用次数)。被拒绝的请求会返回一个结构化信封,内含精确的 retryAfterSeconds,并记录为 rate_limit_hit 事件,方便你判断限制是否过严。

  • 拒绝分页。 列表/查询工具(acumatica_list_entitiesacumatica_run_inquiryacumatica_list_generic_inquiries)不支持分页。当响应达到 ACUMATICA_MAX_RECORDS 时,工具会返回一个结构化信封(truncated: truepaginationSupported: falseactionRequired: "..."),指示 AI 停止并让用户提供范围更小的筛选条件,而不是继续获取更多记录。

  • 审计日志。 所有工具调用、认证事件(登录成功/拒绝、同意接受)和字段脱敏事件都会记录为结构化 JSON。可使用 npx wrangler tail 查看。

平台可移植性

虽然默认部署目标是 Cloudflare Workers,但工具处理程序和核心库均与平台无关。存储抽象层(IKeyValueStore 接口 + AppEnv 类型)将工具逻辑与 Cloudflare 特定的 API 解耦,从而支持在 Node.js 上使用 Redis、SQLite 或其他存储后端进行自托管部署。详见自托管指南

技术栈

开发

npx wrangler dev       # Start local dev server
npx tsc --noEmit       # Type check
npx wrangler tail      # Stream live logs from deployed worker

许可证

Apache 2.0 —— 版权所有 2026 Hall Boys, Inc.

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related 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/NologyAcu/mcp4nology'

If you have feedback or need assistance with the MCP directory API, please join our Discord server