
Concur Mcp
io.github.chrischallv0.1.0更新於 Oct 9, 2026
Unofficial SAP Concur MCP for Claude — expense reports, expenses, receipts and trips
概覽
非官方 SAP Concur 伺服器,讓助理讀取並在確認後修改你的費用報告、費用、收據與行程。
- 功能
- 透過 Concur 網頁應用程式使用的內部 GraphQL API,將助理連接到你自己的 SAP Concur 帳號。讀取類工具可列出報告、費用、尚未指派的卡交易、收據與差旅行程,並查看報告時間軸與異常項目。寫入類工具可建立、更新、提交、撤回與刪除報告和費用,把可用費用移入報告,上傳、附加、分離與刪除收據,以及寄送行程郵件;所有寫入都需確認。另提供唯讀的原始 GraphQL 查詢與需確認的原始變更。
- 適用情境
- 適合自行管理 Concur 報帳的人:在對話中詢問哪些報告尚未提交或被什麼卡住、哪些卡交易還沒歸入報告、下一趟行程何時出發,並完成建立報告、把費用移入報告或附加收據等日常操作。
- 執行需求
- 以 stdio 在本機執行;需要 Node.js 22.5 或更新版本、Claude Desktop 或 Claude Code 等 MCP 主機、ContextMint Bridge 瀏覽器擴充功能,並保持已登入的 Concur 分頁開啟。以 CONCUR_DC 指定資料中心(預設 us2);CONCUR_WS_PORT 預設 37149。首次需在擴充功能中核准配對碼。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Concur Mcp,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
SAP Concur MCP
A Model Context Protocol server that connects Claude to SAP Concur: your expense reports, the expenses on them, available (unassigned) expenses, receipts, and Concur Travel trips — read and write, with every write confirmation-gated.
[!WARNING] AI-developed project. This codebase was entirely built and is actively maintained by Claude. No human has audited the implementation. Review all code and tool permissions before use.
[!CAUTION] Unofficial and unsupported. This server does not use Concur's documented partner API. It calls the internal GraphQL API the Concur web app itself uses, authenticated with your own signed-in browser session. It may break without notice, and automated use may conflict with SAP Concur's or your employer's terms. Use it only for your own account, at your own discretion.
What you can do
Ask Claude things like:
- "Which of my Concur reports are still unsubmitted, and what's blocking them?"
- "Show me the card transactions that aren't on a report yet."
- "Create a report called 'Austin offsite' and move last week's Uber and hotel charges onto it."
- "Upload ~/Downloads/dinner.pdf and attach it to the dinner expense."
- "When does my next trip leave, and what hotel am I in?"
Requirements
- Claude Desktop, Claude Code, or any MCP host
- Node.js 22.5 or later
- The ContextMint Bridge browser extension and a signed-in Concur tab (
https://<dc>.concursolutions.com/…)
Installation
Claude Code plugin
Any MCP host (npx)
Claude Desktop (.mcpb)
Install the .mcpb bundle from the latest release. The installer asks for your datacenter (default us2).
How it authenticates
Concur's web app authenticates its API calls with an HttpOnly JWT cookie that the page itself cannot read. This server uses the fetchproxy bridge only to read three session cookies from your signed-in Concur tab: JWT, plus Concur's legacy session cookies OTSESSIONAABQRD and OTSESSIONAABQRN. Every API call is then made from Node with Authorization: Bearer <jwt> and a Cookie header carrying whichever OTSESSION cookies the tab had — the parts of Concur still served by its legacy services (report keys, currencies, available receipts, permissions) answer an error without them. The cookies are held in memory only and never appear in an error or a log; the only thing written under your home directory is the bridge's pairing identity.
The token lives 60 minutes. The server re-reads the cookies (all together) from your tab when the token is within two minutes of expiry, or once on a 401 (one re-read and one retry per call, never a loop). A read that fails the way a stale OTSESSION cookie fails gets the same single re-read and retry. Concur keeps the cookies fresh while a tab is open, so keep a signed-in Concur tab open while you use the tools. concur_healthcheck reports which source supplied the token, how many minutes it has left and whether the legacy session cookie was found — never a cookie value.
Upgrading from an earlier build? The bridge scope grew from
JWTalone toJWT+ the two OTSESSION cookies. The pair grant is per-scope, so an already-paired server must be re-approved once: the next call answers with a new pair code (or a scope-changed notice) — approve it in the ContextMint Bridge popup.
Pairing (once)
- Install ContextMint Bridge (Chrome: load the release zip unpacked) and sign in to Concur in that browser.
- Ask Claude to run
concur_healthcheck. The first call answers with a pair code. - Approve that code in the ContextMint Bridge popup. The trust persists across restarts (it lives in
~/.fetchproxy/identity/).
More than one browser? If ContextMint Bridge is installed in several browsers, each one dials the same local port, and the pair code can be approved in any of them. Approve it in the browser that holds your Concur session — the server pins whichever extension approved it, and only that browser's tab can supply the cookie. Lines like refusing an extension whose identity is not the one this MCP paired with on stderr are the other browser being turned away; they are harmless.
Paired the wrong browser, or changed browsers? Revoke concur-mcp in the ContextMint Bridge popup, clear the server's pinned extension with fpx trust clear concur-mcp (from @fetchproxy/cli; or delete ~/.fetchproxy/identity/concur-mcp.extension-trust.json), restart the server, and pair again from the right browser.
Configuration
Confirming writes
Every tool that changes something in Concur (or emails someone) is confirmation-gated:
- Clients that support MCP elicitation show a real confirmation prompt describing exactly what will be sent.
- Elsewhere (claude.ai, Claude Desktop) the first call makes no change: it returns a preview of exactly what would be sent plus a single-use, short-lived
confirmToken. Only a repeat call carrying that token writes, and if anything in the request changed in between, the token is refused.
MCP_CONFIRM_MODE decides who may use that token:
Text that comes back from Concur — vendor names, comments, trip details, emails — is treated as untrusted data: it can never authorise a write.
Tools
Most read tools take view: compact | full | raw (default compact): compact drops the fields you rarely need, full keeps them all, raw is Concur's response unprojected.
Session and lookups
Reports and expenses (read)
Reports and expenses (write — all confirmation-gated)
Receipts
Travel
Escape hatches
Out of scope
These exist in Concur but are deliberately not built. Not built is not the same as refused: the raw escape hatches can still reach anything below that the guard does not name.
Refused by concur_graphql_mutation (matched by operation name and by the field the web app's text selects, so renaming or aliasing does not get through): processApproval, updateWorkItemStatus, startSearch, saveBookingSelections, holdTrip, confirmTrip, commitChange, tryCancelTripOrBooking, and SubmitExpenseReport (use concur_submit_report).
- Approvals — approving or sending back other people's reports (
contextRole: MANAGER). Not built: theapprovalsportal.asppage, theGetApproversListandloadApprovalDetailsreads, and theUpdateTimelineWorkflowcall. Refused: CDSprocessApproval, andupdateWorkItemStatus(updateDelegatesDashboardWorkItemStatus). This server acts only on your own data. - Card-transaction management — the card accounts page and its operations:
/Expense/Client/cardtransactions.asp,GetCardAccounts,GetCardTransaction,MoveCCTransactionsToReport,CreateCBSReportAndMoveCCTransactionsToReport,RefreshYodleeTransactions. (Card charges that already appear as available expenses are covered — list, move to a report, delete.) - Booking or cancelling travel — search, price, book, hold, confirm or cancel (
startSearch,saveBookingSelections,holdTrip,confirmTrip,commitChange,tryCancelTripOrBooking). Trips are read-only apart from emailing the itinerary.
Development
The API surface this is built on — hosts, auth, every operation used, and what was verified live — is in docs/CONCUR-API.md, with verbatim operation texts in docs/api/.
License
MIT
來源:README.md,提交 61f22f4
工具
0版本歷史
1- v0.1.0最新Oct 9, 2026


