关于 mercury-multiorg-mcp
mercury-multiorg-mcp 是非官方的只读 MCP 服务,可在一个 AI 会话中访问多个 Mercury 组织。它通过明确的实体键路由调用,并用字段白名单限制返回的结构化数据。
主要功能
- 01在一个会话中访问多个组织
- 02每次调用显式指定实体
- 03只读访问 Mercury API
- 04结构化结果字段采用白名单
- 05可选获取对账单和发票 PDF
适用场景
- 01查看多个 Mercury 组织的数据
- 02按实体获取账户和交易信息
- 03为需要原始文档的会话启用 PDF 获取
MCP 相关
该服务通过本地 stdio MCP 工具提供 Mercury 组织数据。只有明确启用文档访问后,才会注册 PDF 工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
uvx mercury-multiorg-mcpMERCURY_TOKEN_ACME_MAIN密钥Example only. Each organization needs one read-only Mercury API token in the environment variable named by its token_env in your registry. Names are yours to choose but must match MERCURY_TOKEN_[A-Z0-9_]+ (for example MERCURY_TOKEN_<ENTITY_KEY>); set one per organization and rename this example to match.MERCURY_ENTITIES_FILEAlternative to --entities: path to the entity registry YAML. Ignored when --entities is passed.MERCURY_API_BASEMercury API host. Allowed without extra flags: https://api.mercury.com, https://api-sandbox.mercury.com (with sandbox tokens), or a loopback mock.MERCURY_ALLOW_DOCUMENTSSet to true to register get_statement_pdf and get_invoice_pdf, which return statement and invoice PDFs unredacted. Off by default.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
mercury-multiorg-mcp
非官方项目,与 Mercury 无关联,也未获其认可。
只读 MCP 服务,可将多个 Mercury 组织接入同一个 AI 会话。Mercury API 令牌是在单个组织内部创建的,因此此服务会为每个组织保存一个只读令牌,并根据显式的 entity 键路由每次工具调用。
版本 0.1.6(参见 CHANGELOG.md)。维护者使用 vX.Y.Z 标记发布版本;可通过以下命令查找用于固定版本的提交:
git ls-remote --tags https://github.com/dkaleganov/mercury-multiorg-mcp 'v0.1.6^{}'。
包含所有返回字段的完整工具参考见
docs/tools.md;设计说明和构建历史见 GitHub 上的项目简介
CLAUDE.md
(未随 sdist 一同发布)。
安全模型
此服务发出的内容分为四类,各类的保障措施有所不同:
| 类别 | 内容 | 保障措施 |
|---|---|---|
| 结构化字段 | 工具结果中每个对象的所有键 | 每一层都使用允许列表:每个对象及其中的每个嵌套对象,都会通过从实时架构复制的显式允许列表进行筛选。未列出的键不会离开此服务,无论其位于哪一层。账号号码和税号仅显示最后四位;路由号码、交易对手银行信息、邮寄地址、银行卡到期日、预签名下载 URL、发票付款页面 slug、webhook 接收方 URL 和 webhook 签名密钥均不会返回。 |
| 工具错误 | is_error 结果中的文本 | 上游 HTTP 状态错误会包含状态码、经过掩码处理的端点标签和固定提示。验证错误和配置错误使用各自可操作的格式。已解析的已知令牌值若至少有八个字符,就会被清除。不会引用 Mercury 响应正文或标头中的任何内容,也不会回显你传入的任何参数(无效 ID 会报告为“ID 格式无效”)。参数验证失败(类型错误、缺少必需参数)会由此服务仅以字段路径和预期类型呈现,例如 year: expected an integer (int_parsing);MCP SDK 自身会引用你传入值的错误呈现内容不会到达客户端。 |
| 自由文本字段 | 交易备注、交易对手名称、银行描述、发票备注和说明、附件文件名、客户和用户名称 | 原样返回。这些是第三方文本,可能包含任何内容,包括针对模型的指令,以及由人工输入的标识符。应将每个工具结果都视为不可信数据,绝不能将其视为指令。 |
| 文档 | get_statement_pdf / get_invoice_pdf 返回的对账单和发票 PDF | 原样返回,不做删改,仅在选择启用后提供。对账单 PDF 包含完整账号号码、路由号码、地址和所有交易。只有在启动服务时使用 --allow-documents(或设置 MERCURY_ALLOW_DOCUMENTS=1),才会提供这两个工具;server_info.documents_enabled 会报告该设置。正文必须以 application/pdf(或 application/octet-stream)形式传入,以 %PDF- 开头,并且在忽略末尾 PDF 空白字符后,最后 2 KiB 内必须包含 %%EOF 标记;否则会返回明确错误。这只是信封检查,并非 PDF 解析:通过检查的文档内部仍可能格式错误,且返回的字节与收到时完全一致。 |
安全模型的其余部分:
- 只读。 客户端方法仅对应
GET端点;此软件包没有任何可转移资金、编辑收款人或更改其他内容的代码路径。 - 仅使用 Stdio。 服务不会打开网络监听器。
- 实体必须明确指定。 调用
list_entities以发现实体键。每个访问 Mercury 的工具都必须显式指定entity,并在成功结果中标明该实体。list_entities和server_info无需实体参数。不存在默认实体。 - 令牌保留在环境中。 注册表会为每个组织指定一个环境变量(变量名必须为
MERCURY_TOKEN_…,因此注册表无法让服务指向其他密钥);服务只读取该环境变量,不读取其他内容。错误和日志中显示的令牌字符数不会超过末尾 4 个。对长度不少于 8 个字符的值,会执行已知令牌的字面值脱敏;较短的配置值不会进行字面值脱敏(secret-token:格式脱敏和Authorization标头脱敏仍然适用,而且消息本身不会引用上游或调用方数据)。启动时,如果某个实体的配置值不带 Mercury 文档所述的secret-token:前缀,服务会针对该实体发出警告。 - 仅限 Mercury 主机。
--api-base/MERCURY_API_BASE必须是https://api.mercury.com、https://api-sandbox.mercury.com或环回模拟服务;除非在命令行中传入--allow-custom-api-base。仅靠继承的环境变量绝不能将 bearer 令牌重定向到其他主机。 - 限制线上字节数。 每个请求都会拒绝压缩(
Accept-Encoding: identity)。读取 JSON/PDF 前会拒绝非 identity 编码。保持连接时会关闭响应体而不读取。PDF 限制为 10 MiB(10,485,760 字节),JSON 限制为 32 MiB(33,554,432 字节);限制针对流式接收的实际字节数进行强制执行。小型压缩响应体不再可能在内存中扩展至超过限制。完全不读取错误响应。 - 要么完整,要么明确报错。 遍历会在达到请求的限制或 API 末尾时停止。缺失或错误的
page对象会导致失败;可选的末尾nextPage可以缺失或为 null。完全重复的 ID 会被丢弃并计数;内容冲突则会导致失败。如果还有更多数据的提示,但某一页没有新增的可用行,则会导致失败。需要超过 200 页的遍历会失败;不是非负整数的 treasurycursor也会导致失败。每个分页结果和reportable_totals.totals中都会报告duplicates_dropped,因此总数绝不会基于停滞、格式错误或重复计数的遍历生成。 - 完整遍历窗口化数据流。 Mercury 未为事件或 treasury 交易指定排序键,因此客户端窗口(
list_events中的since,以及list_treasury_transactions中的start/end)会完整遍历有界数据流(90 天的事件;最多 200 页的 treasury 账本),在此处筛选并按最新优先排序,然后再应用limit。truncated的值准确无误。开销与数据流大小成正比,而非与窗口大小成正比。 - 二进制文档保留在内存中。 PDF 会以嵌入式
application/pdfblob(base64)形式返回,绝不会写入磁盘。 - 验证路径 ID。 每个会成为请求路径一部分的 ID 都必须是单个安全路径段;无法借此将调用重定向到其他端点。
- 启动错误仅输出一行,退出码为 2。 注册表缺失或格式错误(包括非字符串 YAML 键)、文件无法读取、
--env-file无效或 API 主机不允许时,都会向 stderr 输出一行并以状态码 2 退出。脱敏异常钩子会在加载任何内容前安装,因此任何启动路径都不会输出未经脱敏的回溯信息。 - 绝不处理申报文件。
reportable_totals用于申报前交叉核对。Mercury 没有 1099 申报端点;申报在各组织的仪表板中进行。 安全卫生。 这个软件包位于一个公开仓库中。受跟踪的文件、 测试夹具和提交消息均不包含令牌、账户号码或 金融标识符,但有两个特意保留的例外。第一, 维护者本人的姓名出现在软件包的authors元数据中(经 仓库所有者批准);其他任何人的商业和个人姓名都不会出现。第二, 一条历史记录:第一笔 Phase 1 提交中的测试夹具 曾使用一个真实、公开的 ABA 路由号码作为示例数据;下一笔提交中已将其替换 为明显的虚构值,因此它不在任何已打标签的文件树中,但仍保留在这些文件树的 提交历史中。它标识的是一家银行,而非账户,且历史记录有意未被重写。本次发布通过了对完整历史记录的 gitleaks 扫描。
仓库历史。 本软件包最初在一个多项目单体仓库中开发,直至 v0.1.3;在 v0.1.4 时迁移至此仓库,
并保留了历史记录(相同的提交,按此仓库的布局重写,因此其 SHA 与原始版本不同)。截至 0.1.3 的版本在
原仓库中使用 mercury-v0.1.x 标记,在此仓库中使用 v0.1.x 标记;从现在起,发布标签采用
vX.Y.Z 格式。上述两项安全卫生例外在这段历史中也同样存在,且未作更改。
安装
从 PyPI 使用 uvx 运行固定版本(无需克隆):
uvx [email protected] --entities /private/path/entities.yaml
uvx <package>@<version> 会在隔离的缓存环境中运行指定版本。pip install 'mercury-multiorg-mcp==0.1.6' 也可用,并会将
mercury-multiorg-mcp 和 mercury-multiorg-mcp-keepalive 放入你的 PATH。
需要 Python 3.11+ 和 uv(用于 uvx)。
从源代码安装 / 固定提交
从克隆的仓库安装:
git clone https://github.com/dkaleganov/mercury-multiorg-mcp.git # or [email protected]:dkaleganov/mercury-multiorg-mcp.git
cd mercury-multiorg-mcp
uv sync
uv run mercury-multiorg-mcp --entities /private/path/entities.yaml
也可以使用 uvx 固定完整提交 SHA(应固定 SHA,而非标签:完整 SHA 不可变且可安全用于缓存,而标签可能被移动):
uvx --from 'git+https://github.com/dkaleganov/mercury-multiorg-mcp@<FULL_COMMIT_SHA>' \
mercury-multiorg-mcp --entities /private/path/entities.yaml
配置
- 在每个 Mercury 组织中:组织切换器 → All Settings → Tokens → 创建一个 只读令牌(无需 IP 允许列表)。
- 将
entities.example.yaml复制到此仓库之外的私有位置,并 列出你的组织(key、display_name、token_env;环境变量名称必须以MERCURY_TOKEN_开头)。 - 在启动服务的环境中,为每个组织导出一个环境变量,名称按注册表中的设置填写(
.env.example展示了这些名称)。配置 仅从进程环境变量中读取;除非传入--env-file <path>,否则不会读取.env文件,因此不会意外从 仓库、主目录或uvx缓存中加载任何内容。 - 可选:使用沙盒中创建的令牌时,设置
MERCURY_API_BASE=https://api-sandbox.mercury.com。 - 可选:设置
--allow-documents(或MERCURY_ALLOW_DOCUMENTS=1)以注册 两个 PDF 工具。除非会话确实需要 未脱敏的文档,否则请勿启用。
命令行
| 标志 / 环境变量 | 含义 |
|---|---|
--entities PATH / MERCURY_ENTITIES_FILE | 实体注册表 YAML。必需(标志优先于环境变量);没有隐式默认值。 |
--env-file PATH | 在解析令牌前加载此 dotenv 文件。现有环境变量优先。未指定此标志时,不会从任何位置读取 dotenv 文件。 |
--api-base URL / MERCURY_API_BASE | Mercury API 主机,默认为 https://api.mercury.com。允许使用:生产环境、https://api-sandbox.mercury.com,或用于模拟的 localhost / 127.0.0.1 上的纯 http://。 |
--allow-custom-api-base | 允许使用其他任意 https:// 主机。切勿通过环境变量设置此项;此选项的存在是为了确保自定义主机始终由命令行明确指定。 |
--allow-documents / MERCURY_ALLOW_DOCUMENTS=1 | 注册 get_statement_pdf 和 get_invoice_pdf(返回的文档不会经过脱敏)。默认关闭:不启用时有 24 个工具,启用后有 26 个。 |
--version | 打印软件包版本并退出。 |
启动问题(注册表缺失或格式错误、YAML 无效、文件不可读、API 主机地址错误)会向 stderr 打印一行错误信息并以状态码 2 退出。Stdout 保留给 MCP 协议使用。
Mercury 会在 API 令牌闲置 45 天后将其删除(令牌闲置计时),并单独降级 45 天未使用的权限。请定期运行 mercury-multiorg-mcp-keepalive,以确保闲置计时永不过期;cron 和 launchd 示例请参阅 docs/keepalive.md。
适用于本地 stdio MCP 客户端
兼容支持本地 stdio 服务和协商后的协议版本的 MCP 客户端。在客户端主机上配置以下命令,并确保其可以访问私有注册表和环境文件。各客户端的文档显示和审批策略各不相同。此服务不提供 HTTP 或 SSE。所有客户端使用的命令和参数都相同:
command: uvx
args: [email protected] --entities /private/path/entities.yaml
optional extra arg: --allow-documents (registers the two unredacted PDF tools)
若要运行固定提交版本而非 PyPI 发行版,请将第一个参数替换为 --from、git+https://github.com/dkaleganov/mercury-multiorg-mcp@<FULL_COMMIT_SHA>、mercury-multiorg-mcp(参见“从源码安装 / 固定提交版本”)。
令牌会作为注册表中指定名称的环境变量传递给服务。提供令牌有两种方式:在客户端配置中使用 env 块(仅适用于会从 shell 展开 ${MERCURY_TOKEN_ACME_MAIN} 等占位符的客户端;在配置文件中直接写入令牌会使其成为磁盘上的秘密),或使用私有 dotenv 文件。通过 --env-file /private/path/mercury.env 传入私有 dotenv 文件,可避免依赖特定客户端的占位符展开。客户端主机必须能够读取该文件;现有进程环境变量优先。请将注册表和 dotenv 文件保存在所有代码仓库之外,并确保只有你的用户可以读取。
Claude Code(.mcp.json)
Claude Code 会从其环境中展开 ${VAR}。本仓库包含一个示例 .mcp.json;能够发现此格式的客户端可能会提供启动选项。该文件指向合成示例注册表,不含凭据(因此 list_accounts 会返回干净的逐实体错误)。
{
"mcpServers": {
"mercury-multiorg": {
"command": "uvx",
"args": [
"[email protected]",
"--entities",
"/private/path/entities.yaml"
],
"env": {
"MERCURY_TOKEN_ACME_MAIN": "${MERCURY_TOKEN_ACME_MAIN}"
}
}
}
}
Claude Desktop(claude_desktop_config.json)
打开 Settings → Developer → Edit Config。使用 --env-file,使此配置不依赖特定客户端的占位符展开:
{
"mcpServers": {
"mercury-multiorg": {
"command": "uvx",
"args": [
"[email protected]",
"--entities",
"/private/path/entities.yaml",
"--env-file",
"/private/path/mercury.env"
]
}
}
}
Codex CLI(~/.codex/config.toml)
[mcp_servers.mercury-multiorg]
command = "uvx"
args = [
"[email protected]",
"--entities", "/private/path/entities.yaml",
"--env-file", "/private/path/mercury.env",
]
# `env = { MERCURY_TOKEN_ACME_MAIN = "..." }` is also accepted, but values there are
# literal, so prefer --env-file over putting a token in this file.
Cursor / Windsurf 旧版 Cascade(mcp.json)
Cursor 使用 .cursor/mcp.json 或 ~/.cursor/mcp.json。Windsurf 旧版 Cascade 使用 ~/.codeium/windsurf/mcp_config.json。当前默认的 Devin Local Agent 使用自己的 CLI 配置;此示例针对旧版 Cascade。两者都使用 mcpServers 映射。除非客户端文档说明其会展开环境变量占位符,否则请使用 --env-file。
{
"mcpServers": {
"mercury-multiorg": {
"command": "uvx",
"args": [
"[email protected]",
"--entities",
"/private/path/entities.yaml",
"--env-file",
"/private/path/mercury.env"
]
}
}
}
VS Code(.vscode/mcp.json)
VS Code 使用 servers 映射(而非 mcpServers),并显式指定 "type": "stdio":
{
"servers": {
"mercury-multiorg": {
"type": "stdio",
"command": "uvx",
"args": [
"[email protected]",
"--entities", "/private/path/entities.yaml",
"--env-file", "/private/path/mercury.env"
]
}
}
}
Gemini CLI(~/.gemini/settings.json 或 .gemini/settings.json)
{
"mcpServers": {
"mercury-multiorg": {
"command": "uvx",
"args": [
"[email protected]",
"--entities",
"/private/path/entities.yaml",
"--env-file",
"/private/path/mercury.env"
]
}
}
}
其他 stdio 客户端
任何支持本地 stdio 服务和协商后的协议版本、且运行所在主机可以读取私有注册表和环境文件的客户端:将其指向相同的 uvx 命令和参数即可。服务不会打开网络监听器,因此不提供 HTTP 或 SSE 传输。
工具
每个访问 Mercury 的工具都需要显式指定 entity,并在成功结果中标明该实体;list_entities 和 server_info 无需实体参数。七个带有 limit 参数的工具会返回 count 和 truncated。完整列表工具没有公开的限制。分页结果还会显示重复项诊断信息(duplicates_dropped:遍历过程中丢弃的相同行)。完整的逐字段参考文档:
docs/tools.md。
| 工具 | 参数 | 返回值 |
|---|---|---|
list_entities | — | 实体键、显示名称、各令牌环境变量是否已设置 |
server_info | — | 软件包版本、API 基址、实体数量、documents_enabled(不含机密) |
list_accounts | entity | 账户及余额、accountNumberLast4 |
list_transactions | entity、account_id?、start?、end?、search?、limit=100 | 按 Mercury API 的 desc 顺序排列的交易、truncated 标志 |
reportable_totals | entity、year、threshold?(截至 2025 年默认为 600,自 2026 年起默认为 2000,适用于非雇员服务和某些 MISC 付款;必须为有限数值,且不超过 1,000,000,000) | 每位收款人的 1099 交叉核对总额;needs_review 分类、unclassified、excluded_summary |
list_recipients | entity | 收款人:ID、姓名、昵称、状态、默认付款方式、最近付款日期、电子邮件、isBusiness |
list_tax_docs | entity | 每位收款人的税务表单附件,以及 recipients_without_docs |
get_org | entity | ID、法定名称、DBA、类别、订阅层级、账单周期、einLast4 |
list_statements | entity、account_id、start?、end?、limit=100 | 按 Mercury API 的 desc 顺序排列的对账单元数据(已屏蔽的账户号码和 EIN、transactionCount) |
get_statement_pdf(可选启用) | entity、statement_id | 以嵌入式 blob 返回对账单 PDF(≤ 10 MB),未脱敏;仅在启用 --allow-documents 时可用 |
list_treasury | entity | 国库账户及余额和月度净收益 |
list_treasury_transactions | entity、treasury_id、start?、end?、limit=100 | 按 Mercury API 的 desc 顺序排列的国库账本行;指定日期范围时,会遍历整个账本、筛选并按 canonicalDay 从新到旧排序 |
list_treasury_statements | entity、treasury_id、document_type? | 国库对账单和税务文件(元数据) |
list_credit_accounts | entity | 信用账户及余额 |
list_cards | entity、account_id?、status?、limit=100 | 卡片:末四位数字、姓名、昵称、类别、类型、状态、限额、预算、锁定状态 |
get_card | entity、card_id | 单张卡片,字段相同 |
list_categories | entity | 自定义支出类别 |
list_merchants | entity、search?、limit=100 | 优先商户(ID、名称) |
list_customers | entity | 应收账款客户:ID、姓名、电子邮件、deletedAt |
list_invoices | entity、status?、start?、end?、limit=100 | 应收账款发票(完整遍历后在客户端应用筛选条件) |
get_invoice | entity、invoice_id | 单张发票,含服务期间和行项目 |
get_invoice_pdf(可选启用) | entity、invoice_id | 以嵌入式 blob 返回发票 PDF(≤ 10 MB),未脱敏;仅在启用 --allow-documents 时可用 |
list_invoice_attachments | entity、invoice_id | 附件 ID 和文件名(不含 URL) |
list_users | entity | 用户:ID、名字和姓氏、电子邮件、角色 |
list_events | entity、since?、resource_type?、limit=100 | 按 Mercury API 的 desc 顺序排列的变更事件;指定 since 时,会遍历整个 90 天事件流、筛选并按 occurredAt 从新到旧排序;按资源允许列表重新投影补丁 |
list_webhooks | entity | webhook 端点:ID、url_fingerprint、状态、enabled、事件类型、筛选路径(绝不返回密钥或接收端 URL 的任何部分) |
list_transactions 中的 start / end 按 createdAt 筛选(格式为 YYYY-MM-DD 或 ISO 8601)。Mercury 控制面板可能显示 postedAt,因此日期范围可能与界面不同。
第 1 和第 2 阶段工具的返回值
list_entities entities[] {entity, display_name, token_configured}
server_info name, version, api_base, entity_count, entities_with_token, transport, read_only,
documents_enabled
list_accounts entity, duplicates_dropped, accounts[] {id, name, nickname, legalBusinessName, kind, type,
status, availableBalance, currentBalance, createdAt, canReceiveTransactions,
dashboardLink, accountNumberLast4}
list_transactions entity, filters, count, truncated, duplicates_dropped, transactions[] {id, accountId,
amount, status, kind, createdAt, postedAt, estimatedDeliveryDate, failedAt,
reasonForFailure, counterpartyId, counterpartyName, counterpartyNickname,
bankDescription, externalMemo, note, mercuryCategory,
categoryData {id, name, visibleForCardSpend, visibleForOther, visibleForReimbursements} | null,
merchant {id, category, categoryCode, currency, amount}, checkNumber, cardId,
currencyExchangeInfo {convertedFromAmount, convertedFromCurrency, convertedToAmount,
convertedToCurrency, exchangeRate, feeAmount, feePercentage, feeTransactionId},
dashboardLink}
list_recipients entity, count, duplicates_dropped, recipients[] {id, name, nickname, status,
defaultPaymentMethod, dateLastPaid, emails [strings], contactEmail, isBusiness}
list_tax_docs see the `list_tax_docs` section below (documents[] {id, recipientId, recipientName,
fileName, formType, uploadedAt})
reportable_totals see the `reportable_totals` section below
阶段 3 工具的返回值
get_org entity, organization {id, legalBusinessName, dbas [{dbaName, dbaIsDefault}], kind,
subscriptionTier, billingCadence, einLast4}
list_statements entity, account_id, filters, count, truncated, duplicates_dropped,
statements[] {id, startDate, endDate, endingBalance, companyLegalName,
accountNumberLast4, einLast4, transactionCount}
get_statement_pdf content[0] text {entity, statement_id, mimeType, bytes, encoding, redacted: false};
content[1] embedded resource {uri, mimeType: application/pdf, blob (base64)}
list_treasury entity, count, duplicates_dropped, treasury_accounts[] {id, status, availableBalance, currentBalance,
createdAt, netReturns[] {month, netAmount, treasuryFee, status,
dividends[] {id, type, securityName, amount}}}
list_treasury_transactions entity, treasury_id, filters, count, truncated, duplicates_dropped, transactions[] {id, accountId, type,
amount, balance, canonicalDay, description, additionalDetails, security,
details {creditDescription, depositCounterpartyId, feeDescription,
manualAmendmentDescription, security, sweepDirection, tradeAction,
withdrawalCounterpartyId}}
list_treasury_statements entity, treasury_id, filters, count, duplicates_dropped, statements[] {id, accountId, documentType,
description, periodStart, periodEnd, creationDate, createdAt, updatedAt}
list_credit_accounts entity, count, credit_accounts[] {id, status, availableBalance, currentBalance, createdAt}
list_cards entity, filters, count, truncated, duplicates_dropped, cards[] {id, accountId, userId, nameOnCard, nickname,
lastFour, kind, type, status, physicalCardStatus, isAgentCard, spendLimitType,
spendLimit {amountCents, atmAmountCents, interval},
budgets[] {id, name, amountCents, remainingAmountCents}, merchantLock {id, name},
categoryLocks [strings], createdAt, updatedAt}
get_card entity, card {same fields as one list_cards row}
list_categories entity, count, duplicates_dropped, categories[] {id, name, visibleForCardSpend, visibleForOther,
visibleForReimbursements}
list_merchants entity, filters, count, truncated, duplicates_dropped, merchants[] {id, name}
list_customers entity, count, duplicates_dropped, customers[] {id, name, email, deletedAt}
list_invoices entity, filters, count, truncated, duplicates_dropped, invoices[] {id, invoiceNumber, status, amount,
currencyCode, customerId, destinationAccountId, invoiceDate, dueDate, createdAt,
updatedAt, canceledAt, poNumber, payerMemo, internalNote, ccEmails, achDebitEnabled,
creditCardEnabled, useRealAccountNumber}
get_invoice entity, invoice {list fields + servicePeriodStartDate, servicePeriodEndDate,
lineItems[] {name, quantity, unitPrice, salesTaxRate}}
get_invoice_pdf same two blocks as get_statement_pdf, keyed by invoice_id
list_invoice_attachments entity, invoice_id, count, attachments[] {id, fileName}
list_users entity, count, duplicates_dropped, users[] {userId, firstName, lastName, email, organizationRole}
list_events entity, filters, count, truncated, duplicates_dropped, events[] {id, resourceType,
resourceId, operationType, resourceVersion, occurredAt, changedPaths, mergePatch,
previousValues, patchOmitted?}
list_webhooks entity, count, duplicates_dropped, webhooks[] {id, url_fingerprint (first 8 hex chars of sha256 of the
receiver URL), status, enabled, eventTypes, filterPaths, createdAt, updatedAt}
上方每个嵌套对象都有自己的允许列表;Mercury 明天在任何深度新增的键都会被丢弃,不会直接传递。
列表保持 API 的默认顺序(按未公开的排序键升序排列),但交易、对账单、资金管理交易和事件除外,这些数据会按 Mercury API 的 desc 顺序请求。Mercury 未说明排序键,因此只有带时间窗口的调用才能保证按时间顺序(最新的在前)排列:带时间窗口的资金管理调用按 canonicalDay 排序,带 since 的事件按 occurredAt 排序,然后才应用 limit。不带时间窗口的调用会原样返回 Mercury API 的 desc 顺序。当 truncated 为 true 时,保留的行是适用顺序中的开头部分。
对于 Mercury API 没有服务端筛选器的已记录参数(事件的 since、资金管理交易和发票的 start/end、发票的 status),工具会遍历整个数据流,在此处应用筛选,并在 docs/tools.md 中说明。
reportable_totals
仅统计已完成资金转移(状态为 sent)且金额为支出的记录,并按 UTC 时区的 postedAt 归入日历年(仪表板可能显示的日期)。API 查询使用前后各延长一天的 postedStart / postedEnd;年份以外的记录会在客户端过滤,并计入 excluded_summary.outside_year。系统会遍历该年度的所有分页;若无法完成遍历,则视为错误,绝不会返回部分总额。在线文档未定义交易 kind 的含义,因此此表仅根据 kind 名称所支持的含义作出判断;2026 年 9 月对实际组织的验收发现,负数金额的 externalTransfer 记录是该组织关联的外部账户及跨组织转账,而真正由供应商发起的 ACH 扣款则以 kind other 返回。因此,这两种 kind 会暂不计入,留待人工审核。
| 决策 | Kinds | 备注 |
|---|---|---|
| 纳入 | outgoingPayment | 付款详情中的方式:ach、domesticWire、internationalWire、check 或 unknown |
| 纳入 | exogenousWireDrawdown(负数金额) | 电汇提款,推定由交易对手发起;未记录在文档中(wireDrawdown) |
| 需审核 | externalTransfer(负数金额) | linked_account_transfers:通常是你自己的关联/外部账户或跨组织转账;也可能是供应商发起的 ACH 扣款 |
| 需审核 | other(负数金额) | unlabeled_debits:没有方式标识;通常是供应商发起的 ACH 扣款或 Mercury 产品付款 |
| 排除 | internalTransfer、treasuryTransfer | 组织自己的账户 |
| 排除 | creditCardTransaction、debitCardTransaction、creditCardCredit、debitCardCredit | 发卡处理机构会提交 1099-K 表格 |
| 排除 | wireFee、personalBankingSubscriptionFee、billingEngineSubscriptionFee、cardInternationalTransactionFee* | 银行费用和返款 |
| 排除 | incomingDomesticWire、incomingInternationalWire、checkDeposit、interestPayment | 收到的款项 |
| 排除 | currencyCloudReturn | 被退回的国际电汇;原始款项可能已计入,需手动冲减 |
| 排除 | 任何可纳入、需审核或未分类的 kind,但状态不是 sent 或金额非负 | not_settled:<status> / incoming |
| 未分类 | 表中未列出的任何 kind,或缺少金额 | 逐条列出并说明原因 |
收款方按 counterpartyId 分组(与 GET /recipients 中的收款方匹配时,置信度为 high),否则按交易对手名称分组(置信度为 low)。名称标准化后相同的 ID 分组会相互交叉引用,以便发现付款对象被拆分到两个 ID 的情况。默认门槛会根据年份调整:截至 2025 纳税年度为 600,从 2026 年起为 2000(从 2027 年起按通胀指数调整)。该默认门槛适用于非雇员服务及某些 MISC 付款;请提供适用的类别/年份门槛(参阅 IRS 的 1099-MISC 和 1099-NEC 表格说明)。解析后的数值会在结果中回显。门槛必须是介于 0 和 1,000,000,000 之间的有限数字;否则会报错(绝不会静默设为 0)。实时付款会显示为 ach 或 unknown,具体取决于 API 是否返回其路由详情。
返回:
entity, year, threshold resolved threshold (default depends on year)
date_basis {field: "postedAt", timezone: "UTC",
fallback_to_createdAt_count, api_filter: {postedStart, postedEnd}}
status_basis ["sent"]
totals reportable_total, reportable_payment_count, recipient_count,
flagged_count, needs_review_total, needs_review_count,
reportable_total_upper_bound (= reportable_total + needs_review_total),
unclassified_count, transactions_scanned,
duplicates_dropped (transaction rows), recipient_duplicates_dropped
recipients[] display_name, recipient_id (known recipient) | null, counterparty_id | null,
grouping (counterparty_id | name | transaction), confidence (high | medium | low),
total, payment_count, by_method {label: {count, total}}, flagged,
possible_same_payee [other counterparty ids with the same normalised name],
name_merged_total, flagged_for_review
needs_review {linked_account_transfers: [...], unlabeled_debits: [...]}; each entry:
display_name, counterparty_id | null, count, total, by_kind {kind: {count, total}},
would_flag (total >= threshold), sample_transaction_ids (max 3), hint (fixed string),
possible_same_payee [ids], name_merged_total, would_flag_merged
unclassified[] id, kind, status, amount, postedAt, counterpartyName, reason
excluded_summary {category: {count, amount (signed, as returned by Mercury)}}
fallback_to_createdAt_count 统计缺少 postedAt、因此改用 createdAt 归类的已纳入记录数。这类记录无法通过已入账日期筛选查询到,因此该计数通常为 0。提示内容是固定字符串,根据 kind 和 Mercury 名称前缀选择;交易对手文本本身只是数据,绝不是指令。
list_tax_docs
返回:
entity
document_count, recipient_count, recipients_with_docs
duplicates_dropped {attachments, recipients}
documents[] id, recipientId, recipientName | null, fileName (verbatim third-party text),
formType (w9 | w8BEN | w8BENE | unknown | null), uploadedAt
recipients_without_docs[] id, name | null, status | null (every recipient of any status with no attachment)
绝不会返回下载 URL。
保活
uvx --from 'mercury-multiorg-mcp==0.1.6' mercury-multiorg-mcp-keepalive --entities /private/path/entities.yaml
保活可执行文件的名称与软件包名称不同,因此 uvx 需要
--from;从克隆的仓库运行时,uv run mercury-multiorg-mcp-keepalive 会运行
相同的命令。
每个已配置实体执行一次经过身份验证的 GET /accounts,每个实体输出一行
(<timestamp> OK|FAIL <entity> HTTP <status>);如果任何实体失败,或没有实体配置令牌,则退出码为 1;配置错误时退出码为 2。主机规则与服务相同(非生产、沙盒或环回地址时使用 --allow-custom-api-base)。详情、运行频率以及 cron / launchd 示例见
docs/keepalive.md。
开发
uv sync
uv run pytest
测试仅使用合成 JSON 固定数据和模拟 HTTP 传输。本软件包、其测试或历史记录中均不得包含真实姓名、令牌或账户标识符(唯一的历史例外是公开的银行路由号码,见上文的历史记录说明)。
许可证
MIT;请参阅 LICENSE,该文件也随软件包一同发布。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。