
Mercury Multiorg Mcp
io.github.dkaleganov由 GitHub 帳號 dkaleganov 發布v0.1.6更新於 Oct 24, 2026
Unofficial read-only MCP server exposing several Mercury banking organizations to one AI session.
概覽
非官方唯讀 MCP 伺服器,讓單一 AI 工作階段存取多個 Mercury 銀行組織,依組織使用權杖並回傳去識別化結果。
- 可以做什麼
- 列出已設定的實體,並回報版本、API 位址、是否啟用文件工具等伺服器資訊,不需指定實體。依明確指定的實體讀取帳戶與餘額、交易、收款人、稅務文件、組織資訊、對帳單、國庫帳戶與交易、信用帳戶、卡片、分類、商家、客戶、發票、附件、使用者、變更事件和 webhook。依年度彙總每位收款人的 1099 交叉核對金額,並標出需要人工複核的類別。啟用文件工具後,可將對帳單和發票 PDF 以內嵌資料回傳。
- 適用情境
- 適合讓助手在同一個工作階段中跨多個 Mercury 組織回答問題,例如查看餘額、交易、發票或 1099 彙總,而不必切換後台。它是唯讀的,不用於轉帳或修改任何內容。
- 執行需求
- 以 PyPI 套件透過 uvx 在本機以 stdio 執行,需要 Python 3.11+ 和 uv。需要一份私有的實體登錄 YAML,透過 --entities 或 MERCURY_ENTITIES_FILE 傳入,並為每個組織提供一個唯讀 Mercury API 權杖,放在以 MERCURY_TOKEN_ 開頭、後綴自選的環境變數中。需要能存取 Mercury API 主機;使用沙箱權杖時支援沙箱主機。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Mercury Multiorg Mcp,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
mercury-multiorg-mcp
Unofficial. Not affiliated with or endorsed by Mercury.
Read-only MCP server that exposes several
Mercury organizations to one AI session. A Mercury API token is created from
inside a single organization, so this server holds one read-only token per org
and routes every tool call by an explicit entity key.
Version 0.1.6 (see CHANGELOG.md). The maintainer tags
releases as vX.Y.Z; find the commit to pin with
git ls-remote --tags https://github.com/dkaleganov/mercury-multiorg-mcp 'v0.1.6^{}'.
The complete tool reference with every returned field is in
docs/tools.md; design notes and the build history are in
the project brief on GitHub,
CLAUDE.md
(not shipped in the sdist).
Security model
What leaves this server falls into four classes, and the guarantees differ:
The rest of the model:
- Read-only. Only
GETendpoints have client methods; the package has no code path that can move money, edit recipients, or change anything. - Stdio only. The server never opens a network listener.
- Explicit entity. Call
list_entitiesto discover entity keys. Every tool that accesses Mercury requires an explicitentityand identifies it in its successful result.list_entitiesandserver_inforequire no entity argument. There is no default entity. - Tokens stay in the environment. The registry names an env var per org
(it must be named
MERCURY_TOKEN_…, so a registry cannot point the server at some other secret); the server reads that env var and nothing else. Errors and logs never contain more than the last four characters of a token. Literal known-token scrubbing applies to values of 8 or more characters; a shorter configured value is not literal-scrubbed (thesecret-token:shape scrub and theAuthorizationheader scrub still apply, and no message quotes upstream or caller data in the first place). At startup the server warns, per entity, when a configured value does not carry Mercury's documentedsecret-token:prefix. - Only Mercury hosts.
--api-base/MERCURY_API_BASEmust behttps://api.mercury.com,https://api-sandbox.mercury.com, or a loopback mock, unless--allow-custom-api-baseis passed on the command line. An inherited environment variable alone can never redirect the bearer token to another host. - Byte limits on wire bytes. Every request declines compression
(
Accept-Encoding: identity). JSON/PDF reads reject nonidentity encoding before reading. Keepalive closes bodies unread. Limits are 10 MiB (10,485,760 bytes) for PDF and 32 MiB (33,554,432 bytes) for JSON, enforced on the bytes actually received while streaming. A small compressed body can no longer expand past the limit in memory. Error responses are never read at all. - Complete or loud. Walks stop at the requested limit or API end.
Missing/wrong
pageobjects fail; optional terminalnextPagemay be absent or null. Exact duplicate IDs are dropped and counted; conflicting contents fail. A page with no fresh usable rows while more are advertised fails. A walk that needs more than 200 pages fails, and a treasurycursorthat is not a non-negative integer fails. Duplicate counts are reported asduplicates_droppedon every paginated result and underreportable_totals.totals, so a total is never built on a stalled, malformed, or double-counted walk. - Windowed feeds are walked in full. Mercury documents no sort key for
events or treasury transactions, so a client-side window (
sinceonlist_events,start/endonlist_treasury_transactions) walks the whole bounded feed (90 days of events; the treasury ledger up to 200 pages), filters and sorts newest first here, then applieslimit.truncatedis exact. The cost is proportional to the feed, not the window. - Binary documents stay in memory. PDFs come back as an embedded
application/pdfblob (base64), never written to disk. - Path ids are validated. Every id that becomes part of a request path must be a single safe segment; nothing can redirect a call to another endpoint.
- Startup errors are one line, exit 2. A missing or malformed registry
(including non-string YAML keys), an unreadable file, a bad
--env-file, or a disallowed API host prints one line to stderr and exits with status 2. The redacting exception hooks are installed before anything is loaded, so no startup path can print an unredacted traceback. - Never files anything.
reportable_totalsis a pre-filing cross-check. Mercury has no 1099 filing endpoint; filing happens in each org's dashboard.
Hygiene. This package lives in a public repository. Tracked files,
fixtures, and commit messages carry no tokens, account numbers, or
financial identifiers, with two deliberate exceptions. First, the
maintainer's own name appears in the package authors metadata (approved
by the repository owner); business and personal names of anyone else do
not appear. Second, a history note: the first Phase 1 commit's fixtures
used a real, public ABA routing number as sample data; it was replaced
with an obviously fake value in the next commit, so it is absent from
every tagged file tree but remains in their ancestry. It identifies a
bank, not an account, and the history was deliberately not rewritten. This release passed a full-history gitleaks scan.
Repository history. This package was developed in an earlier
multi-project monorepo through v0.1.3 and moved to this repository at v0.1.4
with its history preserved (the same commits, rewritten to this repository's
layout, so their SHAs differ from the originals). Releases up to 0.1.3 were
tagged mercury-v0.1.x there and are tagged v0.1.x here; release tags are
vX.Y.Z from now on. Both hygiene exceptions above apply to this history
unchanged.
Install
From PyPI, running the pinned release with uvx (no clone needed):
uvx <package>@<version> runs exactly that release in an isolated, cached
environment. pip install 'mercury-multiorg-mcp==0.1.6' also works and puts
mercury-multiorg-mcp and mercury-multiorg-mcp-keepalive on your PATH.
Requires Python 3.11+ and uv (for uvx).
From source / pinned commit
From a clone:
Or pin a full commit SHA with uvx (pin a SHA, not a tag: a full SHA is
immutable and cache-safe, while a tag can be moved):
Configure
- In each Mercury org: org switcher → All Settings → Tokens → create a Read Only token (no IP allowlist required).
- Copy
entities.example.yamlto a private location outside this repo and list your orgs (key,display_name,token_env; the env var name must start withMERCURY_TOKEN_). - Export one env var per org, named as in the registry, in the environment
that launches the server (
.env.exampleshows the names). Configuration is read from process environment variables only; no.envfile is read unless you pass--env-file <path>, so nothing is picked up by accident from the repo, your home directory, or auvxcache. - Optional:
MERCURY_API_BASE=https://api-sandbox.mercury.comwith sandbox-created tokens. - Optional:
--allow-documents(orMERCURY_ALLOW_DOCUMENTS=1) to register the two PDF tools. Leave it off unless the session really needs unredacted documents.
Command line
Startup problems (missing or malformed registry, invalid YAML, unreadable file, bad API base) print one line to stderr and exit with status 2. Stdout is reserved for the MCP protocol.
Mercury deletes an API token after 45 days of inactivity (the token
inactivity clock) and separately downgrades permissions unused for 45 days.
Run mercury-multiorg-mcp-keepalive on a schedule so the inactivity clock
never expires; see docs/keepalive.md for cron and
launchd snippets.
Works with local stdio MCP clients
Compatible with MCP clients that support local stdio servers and the negotiated protocol version. Configure the following command on the client host, with access to the private registry and environment file. Document display and client approval policies vary. This server does not expose HTTP or SSE. The command and arguments are the same in every client:
To run a pinned commit instead of the PyPI release, replace the first
argument with --from, git+https://github.com/dkaleganov/mercury-multiorg-mcp@<FULL_COMMIT_SHA>, mercury-multiorg-mcp
(see "From source / pinned commit").
Tokens reach the server as environment variables named in your registry.
Two ways to supply them: an env block in the client's config (only where
the client expands placeholders such as ${MERCURY_TOKEN_ACME_MAIN} from
your shell; a literal token in a config file is a secret on disk), or a
private dotenv file. A private dotenv file passed with
--env-file /private/path/mercury.env avoids client-specific placeholder
expansion. The client host must be able to read it; existing process
environment variables win. Keep the registry and the dotenv file outside
any repository and readable only by your user.
Claude Code (.mcp.json)
Claude Code expands ${VAR} from its environment. This repository includes
an example .mcp.json; clients that discover this format may offer to
launch it. It points to the synthetic example registry and contains no
credentials (so list_accounts returns a clean per-entity error).
Claude Desktop (claude_desktop_config.json)
Open Settings → Developer → Edit Config. Use --env-file so this setup
does not depend on client-specific placeholder expansion:
Codex CLI (~/.codex/config.toml)
Cursor / Windsurf legacy Cascade (mcp.json)
Cursor uses .cursor/mcp.json or ~/.cursor/mcp.json. Windsurf legacy
Cascade uses ~/.codeium/windsurf/mcp_config.json. The current default
Devin Local agent uses its own CLI configuration; this example targets
legacy Cascade. Both use an mcpServers map. Use --env-file unless your
client's documentation says it expands environment placeholders.
VS Code (.vscode/mcp.json)
VS Code uses a servers map (not mcpServers) and an explicit
"type": "stdio":
Gemini CLI (~/.gemini/settings.json or .gemini/settings.json)
Any other stdio client
Any client that supports local stdio servers and the negotiated protocol
version, running on a host that can read the private registry and
environment file: point it at the same uvx command and arguments. The
server never opens a network listener, so an HTTP or SSE transport is not
offered.
Tools
Every tool that accesses Mercury requires an explicit entity and
identifies it in its successful result; list_entities and server_info
require no entity argument. The seven tools with a limit argument return
count and truncated. Full-list tools have no public limit. Paginated
results also expose duplicate diagnostics (duplicates_dropped: identical
rows the walk dropped). Full field-by-field reference:
docs/tools.md.
start / end on list_transactions filter on createdAt (YYYY-MM-DD or
ISO 8601). The Mercury dashboard may display postedAt, so a date range
may differ from the UI.
Returns for the Phase 1 and 2 tools
Returns for the Phase 3 tools
Every nested object above has its own allowlist; a key Mercury adds tomorrow at any depth is dropped, not passed through.
Lists keep the API's default order (ascending by an undocumented sort key)
except transactions, statements, treasury transactions, and events, which
are requested in Mercury API desc order. Mercury documents no sort key,
so chronological (newest-first) order is guaranteed only for windowed
calls: windowed treasury calls sort by canonicalDay, and events with
since sort by occurredAt, before limit applies. An unwindowed call
returns Mercury API desc order as is. When truncated is true, the rows
kept are the head of whichever order applies.
Where the Mercury API has no server-side filter for a documented argument
(since on events, start/end on treasury transactions and invoices,
status on invoices) the tool walks the whole feed, applies the filter
here, and says so in docs/tools.md.
reportable_totals
Counts only completed money movement (status sent) with an outgoing
amount, attributed to the calendar year by postedAt in UTC (the date
the dashboard may show). The API is queried with postedStart / postedEnd
padded by one day on each side; rows outside the year are dropped
client-side and counted under excluded_summary.outside_year. Every page
of the year is walked; a walk that cannot complete is an error, never a
partial total. The live docs define no semantics for transaction kind,
so the table only asserts what the kind name supports; real-organization
acceptance (September 2026) showed that negative externalTransfer rows
were the organization's own linked external accounts and cross-org
transfers, while genuine vendor-initiated ACH debits arrived as kind
other. Those two kinds are therefore set aside for a human rather than
counted.
Recipients group by counterpartyId (confidence high when it matches a
recipient from GET /recipients, else medium) or, failing that, by
counterparty name (low). Id-groups that share a normalised name are
cross-referenced so a payee split across two ids is visible. The default
threshold is year-aware: 600 through tax year 2025, 2000 from 2026
(inflation-indexed from 2027). It is the default for nonemployee services
and certain MISC payments; supply the applicable category/year threshold
(see the IRS instructions for Forms 1099-MISC and 1099-NEC). The resolved
value is echoed. A threshold must be a finite
number between 0 and 1,000,000,000; anything else is an error (never
silently zero). Real-time payments appear under ach or unknown
depending on whether the API returns routing details for them.
Returns:
fallback_to_createdAt_count counts included rows that had no postedAt
and were placed by createdAt instead. Such rows cannot come back from the
posted-date filter, so the count is normally 0. Hints are fixed strings
chosen by kind and by a Mercury name prefix; counterparty text itself
is data, never an instruction.
list_tax_docs
Returns:
Download URLs are never returned.
Keepalive
The keepalive executable is not named after the package, so uvx needs
--from; from a clone, uv run mercury-multiorg-mcp-keepalive runs the
same command.
One authenticated GET /accounts per configured entity, one line each
(<timestamp> OK|FAIL <entity> HTTP <status>), exit 1 if any entity fails
or no entity has a token, exit 2 on a configuration error. Same host rules
as the server (--allow-custom-api-base for anything but production,
sandbox, or loopback). Details, cadence, and cron / launchd snippets in
docs/keepalive.md.
Develop
Tests use synthetic JSON fixtures and a mock HTTP transport only. Nothing in this package, its tests, or its history may contain real names, tokens, or account identifiers (see the history note above for the one historical exception, a public bank routing number).
License
MIT; see LICENSE, which also ships in the package.
來源:README.md,提交 f0ff539
工具
0版本歷史
1- v0.1.6最新Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分