mcpField
C
concur-mcp

concur-mcp

本地服务
github.com/chrischall金融数据06 天前更新

关于 concur-mcp

concur-mcp 是连接 Claude 等 MCP 客户端与 SAP Concur 的非官方 MCP 服务,可管理报销单、费用、收据和行程。它使用已登录的浏览器会话,所有写入操作都需确认。

主要功能

  1. 01读取报销单、费用和行程
  2. 02创建和更新报销单及费用
  3. 03下载、上传和附加收据
  4. 04查看可用费用和收据
  5. 05写入前确认每项更改

适用场景

  1. 01查找未提交的报销单及阻止提交的问题
  2. 02将银行卡交易移入报销单
  3. 03上传并附加收据
  4. 04查看即将开始的行程

MCP 相关

向 MCP 客户端提供 SAP Concur 会话、报销单、费用、收据和旅行操作工具。写入操作需确认。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"chrischall-concur": {
"command": "npx",
"args": [
"-y",
"@chrischall/concur-mcp"
],
"env": {
"CONCUR_DC": "<CONCUR_DC>",
"CONCUR_WS_PORT": "<CONCUR_WS_PORT>",
"CONCUR_OUTPUT_DIR": "<CONCUR_OUTPUT_DIR>",
"CONCUR_UPLOAD_ROOTS": "<CONCUR_UPLOAD_ROOTS>",
"CONCUR_INLINE_RECEIPTS": "<CONCUR_INLINE_RECEIPTS>"
}
}
}
}
启动命令npx -y @chrischall/concur-mcp
需要配置的环境变量
CONCUR_DCConcur datacenter from your signed-in tab's host (e.g. us2, eu2). Defaults to us2.
CONCUR_WS_PORTfetchproxy bridge concentrator port. Defaults to the fleet-shared 37149.
CONCUR_OUTPUT_DIRWhere `concur_get_receipt` saves downloaded receipts (never overwriting an existing file). Defaults to ~/Downloads/concur-mcp.
CONCUR_UPLOAD_ROOTSThe only folders `concur_upload_receipt` will read from (a path-delimiter-separated list; `~` expanded). Hosted (with `MCP_DATA_DIR` set) the default is `$MCP_DATA_DIR/uploads`. Defaults to ~/Downloads, ~/Documents and ~/Desktop, plus the working directory when it is a folder inside your home directory (never `/` or home itself).
CONCUR_INLINE_RECEIPTS`true` makes `concur_get_receipt` return the image in the result instead of writing a file. Off locally, on when hosted.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@chrischall/concur-mcp0.3.3

工具

39

收录的工具列表 · 更新于 1 周前

此工具无需参数。

详细介绍

SAP Concur MCP

CI npm license

一个 Model Context Protocol 服务,可将 Claude 连接到 SAP Concur:你的费用报告、报告中的费用、可用(未分配)的费用、收据和 Concur Travel 行程——既可读取**,也**可写入,而且每次写入都必须经过确认。

警告

由 AI 开发的项目。 此代码库完全由 Claude 构建并主动维护。没有人审查过其实现。使用前请检查所有代码和工具权限。

注意

非官方且不受支持。 此服务不使用 Concur 的公开合作伙伴 API,而是调用 Concur Web 应用本身使用的内部 GraphQL API,并通过你已登录的浏览器会话进行身份验证。此服务可能会在没有通知的情况下失效,自动化使用也可能违反 SAP Concur 或你雇主的条款。请仅用于你自己的账户,并自行承担风险。

你可以做什么

可以向 Claude 提出这些问题:

  • “我的 Concur 报告中,哪些尚未提交?是什么原因导致无法提交?”
  • “显示还没有添加到报告中的银行卡交易。”
  • “创建一份名为 ‘Austin offsite’ 的报告,并将上周的 Uber 和酒店费用移到该报告中。”
  • “上传 ~/Downloads/dinner.pdf,并将其附加到晚餐费用。”
  • “我的下一趟行程什么时候出发?我会住在哪家酒店?”

要求

  • Claude Desktop、Claude Code 或任何 MCP 主机
  • Node.js 22.5 或更高版本
  • ContextMint Bridge 浏览器扩展,以及一个已登录 Concur 的标签页(https://<dc>.concursolutions.com/…)

安装

Claude Code 插件
claude plugin marketplace add chrischall/concur-mcp
claude plugin install concur@chrischall
任何 MCP 主机(npx)
{
  "mcpServers": {
    "concur": {
      "command": "npx",
      "args": ["-y", "@chrischall/concur-mcp"],
      "env": { "CONCUR_DC": "us2" }
    }
  }
}
Claude Desktop(.mcpb)

从最新版本安装 .mcpb 包。安装程序会询问你的数据中心(默认值为 us2)。

身份验证方式

Concur 的 Web 应用使用 HttpOnly JWT Cookie 对 API 调用进行身份验证,页面本身无法读取该 Cookie。本服务仅通过 fetchproxy 桥接程序,从你已登录的 Concur 标签页中读取三个会话 Cookie:JWT,以及 Concur 的旧版会话 Cookie OTSESSIONAABQRD 和 OTSESSIONAABQRN。之后,每次 API 调用都由 Node 发起,并携带 Authorization: Bearer <jwt> 和 Cookie 标头,其中包含该标签页持有的 OTSESSION Cookie——Concur 中仍由旧版服务提供的部分(报告密钥、货币、可用收据、权限)若缺少这些 Cookie,就会返回错误。Cookie 仅保存在内存中,不会出现在错误或日志里;你的主目录下唯一写入的内容是桥接程序的配对身份。

令牌有效期为 60 分钟。当令牌将在两分钟内过期时,服务器会从你的标签页重新读取 Cookie(一次性读取全部 Cookie);遇到 401 时也会重新读取一次(每次调用仅重新读取并重试一次,不会循环)。如果读取失败的原因与 OTSESSION Cookie 过期时相同,也会进行同样的一次重新读取和重试。Concur 会在标签页打开期间保持 Cookie 有效,因此使用这些工具时,请保持一个已登录的 Concur 标签页处于打开状态。concur_healthcheck 会报告令牌来源、剩余有效时间(分钟)以及是否找到旧版会话 Cookie,但绝不会显示任何 Cookie 值。

从早期版本升级? 桥接范围已从仅包含 JWT 扩大为包含 JWT 和两个 OTSESSION Cookie。配对授权按范围区分,因此已配对的服务器必须重新批准一次:下次调用会返回新的配对码(或范围变更通知)——请在 ContextMint Bridge 弹出窗口中批准。

配对(仅需一次)
  1. 安装 ContextMint Bridge(Chrome:解压发布 zip 后以未打包方式加载),并在该浏览器中登录 Concur。
  2. 请 Claude 运行 concur_healthcheck。首次调用会返回一个配对码。
  3. 在 ContextMint Bridge 弹出窗口中批准该配对码。信任关系会在重启后继续保留(存储于 ~/.fetchproxy/identity/)。

使用多个浏览器? 如果在多个浏览器中安装了 ContextMint Bridge,每个浏览器都会连接到同一个本地端口,并且可以在任意一个浏览器中批准配对码。请在持有 Concur 会话的浏览器中批准——服务器会锁定批准配对的扩展,只有该浏览器中的标签页才能提供 Cookie。stderr 中类似 refusing an extension whose identity is not the one this MCP paired with 的行,表示其他浏览器被拒绝;这不会造成影响。

配错了浏览器,或更换了浏览器? 在 ContextMint Bridge 弹出窗口中撤销 concur-mcp,使用 @fetchproxy/cli 中的 fpx trust clear concur-mcp 清除服务器锁定的扩展(或删除 ~/.fetchproxy/identity/concur-mcp.extension-trust.json),重启服务器,然后在正确的浏览器中重新配对。

配置

环境变量默认值用途
CONCUR_DCus2你的数据中心:已登录标签页主机名的第一个标签(us2 对应 us2.concursolutions.com,eu2 等)。必须与会话令牌的签发者匹配,否则每次调用都会失败,并提示应使用哪个值。
CONCUR_WS_PORT37149fetchproxy 桥接端口。整个 fetchproxy 集群和 ContextMint Bridge 共用 37149;仅在本地测试时(或主机为每个注册项注入独立端口时)覆盖此值。
CONCUR_OUTPUT_DIR~/Downloads/concur-mcpconcur_get_receipt 保存已下载收据的位置(绝不覆盖现有文件)。
CONCUR_UPLOAD_ROOTS~/Downloads、~/Documents、~/Desktop,以及当当前工作目录是你主目录下的文件夹时的该目录(绝不会是 / 或主目录本身 — Claude Desktop 会在 / 中启动服务)concur_upload_receipt 唯一会读取的文件夹(以路径分隔符分隔的列表;会展开 ~)。托管环境中(设置了 MCP_DATA_DIR 时),默认值为 $MCP_DATA_DIR/uploads。
CONCUR_INLINE_RECEIPTS本地为 off,托管环境中为 ontrue 会让 concur_get_receipt 在结果中返回图片,而不是写入文件。
MCP_USER_TZ服务所在时区你的 IANA 时区(例如 America/New_York),当 concur_create_report 默认设置 reportDate 时用于确定“今天”。托管环境中请设置此值 — 托管服务运行在 UTC 时区,因此晚间创建的报告日期可能会变成明天。
CONCUR_DEBUGoff将桥接的角色和生命周期记录到 stderr。
MCP_CONFIRM_MODEask-user客户端无法显示确认提示时,写入操作的处理方式 — 见下文。
MCP_CONFIRM_ELICITATIONonoff 表示永不显示确认提示,因此所有客户端都会采用 MCP_CONFIRM_MODE 指定的处理路径(适用于声明支持提示但从不显示提示的客户端)。

确认写入操作

每个会更改 Concur 中内容(或发送邮件)的工具都需要经过确认:

  • 支持 MCP elicitation 的客户端会显示真实的确认提示,准确说明将要发送的内容。
  • **其他客户端(claude.ai、Claude Desktop)**的首次调用不会进行任何更改:它会返回将要发送内容的预览,以及一个一次性、短时有效的 confirmToken。只有再次调用并附带该令牌才会执行写入;如果期间请求中的任何内容发生变化,令牌将被拒绝。

MCP_CONFIRM_MODE 决定谁可以使用该令牌:

值行为
ask-user(默认)模型必须向你展示预览,并在聊天中获得你的批准后才能再次使用该令牌。
auto模型查看预览后可以自行使用该令牌。
refuse在没有确认提示的客户端上拒绝写入操作。无法识别的值会按 refuse 处理。

从 Concur 返回的文本 — 供应商名称、评论、行程详情、邮件 — 都被视为不可信数据:它们绝不能授权写入操作。

工具

大多数读取工具都接受 view: compact | full | raw(默认值为 compact):compact 会省略你很少需要的字段,full 会保留所有字段,raw 则是未经投影处理的 Concur 响应。

会话与查询
工具功能
concur_healthcheck令牌由哪个来源提供、API 是否接受该令牌、往返时间、距离过期还有多少分钟
concur_whoami你的 Concur 用户 ID、数据中心、令牌剩余有效分钟数,以及已启用的功能
concur_list_expense_types报告政策允许的费用类型(ID、名称、分组)
concur_list_payment_types可用于费用的付款类型(现金、公司卡等)
concur_list_currenciesConcur 接受的货币,可按条件筛选
concur_search_locations按城市查询费用地点(可选国家/行政区划)
报告和费用(读取)
工具功能
concur_list_reports按状态(ALL、ACTIVE、UNSUBMITTED、SENT_FOR_PAYMENT)和日期范围筛选你的报告
concur_get_report获取一份报告:抬头、所有费用条目及其例外情况(阻止提交的例外情况)
concur_get_report_timeline获取报告的时间线(评论和工作流事件)及审计跟踪
concur_get_expense获取一笔费用:按标签显示的表单字段、明细项、收据、评论和例外情况
concur_list_available_expenses获取尚未添加到报告的卡交易、电子收据和移动端采集的费用
报告和费用(写入——所有操作均需确认)
工具功能可撤销?
concur_create_report创建一份未提交的报告是(concur_delete_report)
concur_update_report更改抬头字段;仅发送有变更的内容是
concur_delete_report删除一份未提交的报告及其上的所有费用否
concur_add_report_comment添加审批人可见的评论否(评论无法删除)
concur_submit_report将报告发送给审批人否——报告会送达他人;审批前可通过 concur_recall_report 撤回
concur_recall_report撤回已提交但尚未获批的报告是
concur_create_expense向未提交的报告添加一笔费用;可按标签填写任何可编辑的表单字段(自定义字段、Ticket Number、From/To Location 等);外币将使用 Concur 针对该日期的汇率是
concur_update_expense更改一笔费用,包括表单字段和汇率;仅发送有变更的内容是
concur_delete_expenses从报告中删除费用(卡交易会返回可用费用列表)否
concur_copy_expense复制一笔费用是
concur_move_available_expenses_to_report将可用费用移至报告否(Concur 不支持移回)
concur_delete_available_expenses删除可用费用否
出席者
工具功能可撤销?
concur_search_attendees按姓名或电子邮件搜索出席者目录(同事、已保存的访客)读取
concur_set_attendees替换一笔费用的出席者列表(默认先添加你自己),并平均分摊金额——需确认否(没有工具可以读取之前的列表或清空列表)
收据
工具功能需确认?
concur_list_available_receipts列出收据存储区中尚未附加到费用的收据图片读取
concur_get_receipt将收据图片下载到 CONCUR_OUTPUT_DIR(或以内联形式返回)仅本地文件
concur_upload_receipt从允许的文件夹上传 png / jpg / pdf(≤ 25 MB)是
concur_attach_receipt将已存储的图片附加到尚无收据的费用是
concur_append_receipt将已存储的图片作为费用收据的额外页面添加是
concur_detach_receipt从费用中移除图片是
concur_add_missing_receipt_declaration为没有收据的费用添加 Missing Receipt Declaration(宣誓书)——你需要确认收据确实遗失;预览会显示你所在组织的声明文本。没有工具可以移除声明(附加收据会替换声明)是
concur_delete_receipt删除尚未附加的收据图片——无法撤销是
差旅
工具功能
concur_list_trips列出你的差旅(默认显示即将开始的行程;也可查看过去的行程或所有行程),支持筛选
concur_get_trip获取一趟行程及其航班、酒店、租车和铁路预订信息
concur_get_trip_history获取一趟行程的历史记录:变更、审批、行程单邮件
concur_send_itinerary通过电子邮件发送行程单——会发送真实邮件,需确认
应急接口
工具功能
concur_list_operationsConcur 网页应用使用的 GraphQL 操作——名称、端点、用途,以及已有哪个专用工具会运行该操作
concur_graphql_query运行原始只读查询(spend 或 cds 端点);拒绝任何可能写入数据的操作
concur_graphql_mutation运行原始变更操作,需经完整文档预览确认;拒绝「范围外」中列出的操作,包括提交(请使用 concur_submit_report)

范围外

Concur 中存在这些功能,但本项目有意不实现。不实现不等于拒绝:原始应急接口仍可访问以下任何未被防护机制明确限制的功能。

concur_graphql_mutation 会拒绝以下操作(按操作名称以及网页应用文本所选的字段匹配,因此改名或使用别名也无法绕过):processApproval、updateWorkItemStatus、startSearch、saveBookingSelections、holdTrip、confirmTrip、commitChange、tryCancelTripOrBooking 和 SubmitExpenseReport(请使用 concur_submit_report)。

  • 审批——审批或退回他人的报告(contextRole: MANAGER)。未实现:approvalsportal.asp 页面、GetApproversList 和 loadApprovalDetails 读取操作,以及 UpdateTimelineWorkflow 调用。拒绝:CDS processApproval 和 updateWorkItemStatus(updateDelegatesDashboardWorkItemStatus)。此服务仅处理你自己的数据。
  • 卡片交易管理——卡片账户页面及其操作:/Expense/Client/cardtransactions.asp、GetCardAccounts、GetCardTransaction、MoveCCTransactionsToReport、CreateCBSReportAndMoveCCTransactionsToReport、RefreshYodleeTransactions。(已显示为可用费用的卡片交易已覆盖——列出、移至报告、删除。)
  • 预订或取消旅行——搜索、查询价格、预订、暂存、确认或取消(startSearch、saveBookingSelections、holdTrip、confirmTrip、commitChange、tryCancelTripOrBooking)。除发送行程邮件外,行程信息均为只读。

开发

npm install
npm run build        # tsc → dist/, then esbuild → dist/bundle.js (the .mcpb entry)
npm test             # typecheck + vitest
npm run test:coverage

本项目所基于的 API 接口——包括主机、身份验证、所用的每项操作以及已在线验证的内容——详见 docs/CONCUR-API.md,操作原文见 docs/api/。

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。