内容
# bexio-mcp
**用于 [bexio](https://www.bexio.com) API 的 MCP 服务器和类型化的 TypeScript 客户端** — 瑞士商业软件,涵盖联系人、报价、订单、发票、采购、会计、银行、项目、时间跟踪和工资单。
- **完整**: 通过 35 个描述良好的 MCP 工具,涵盖 [bexio API](https://docs.bexio.com/) 的所有 **310 个已文档化的操作** (通过官方 OpenAPI 规范的覆盖率测试强制执行)。
- **可重用**: 类型化的 API 客户端是一个独立的入口点 (`bexio-mcp/client`),具有零 MCP 依赖项 — 在任何 Node.js 项目中使用。
- **安全**: 只读和保守的仅草稿写入模式、破坏性操作注释、工具组过滤以及 API 错误映射到可行的消息(过期令牌、缺少范围、速率限制)而不是崩溃。
- **健壮**: 在速率限制时自动重试(尊重 `RateLimit-Reset`)、瞬时 GET 失败重试、请求超时、类型化错误层次结构。
## 两分钟快速入门
您需要:
- [Node.js 18 或更新版本](https://nodejs.org/) — 使用 `node --version` 检查
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) — 或选择 [另一个 MCP 客户端](docs/integrations/README.md)
- 来自 [developer.bexio.com/pat](https://developer.bexio.com/pat) 的 bexio 个人访问令牌(PAT)
使用您的 PAT 替换 `YOUR_BEXIO_TOKEN`,将服务器添加到 Claude Code:
```bash
claude mcp add --env BEXIO_API_TOKEN=YOUR_BEXIO_TOKEN \
--transport stdio bexio -- npx -y github:nolen-ai/bexio-mcp
```
验证连接:
```bash
claude mcp list
```
结果应包括:
```text
bexio: npx -y github:nolen-ai/bexio-mcp - ✔ 已连接
```
首次启动时下载并构建服务器,可能需要几秒钟。之后,打开 Claude Code 并尝试:
> 列出我在 bexio 中最近的 10 张开票。
无需克隆或全局安装。Claude Code 将令牌存储在其本地 MCP 配置中,并仅将其传递给本地服务器进程。不要将令牌提交到存储库或粘贴到提示中。
### 以只读模式启动
对于更安全的首次查看,请使用以下命令代替上面的命令。它禁用所有创建、更新、发送和删除操作:
```bash
claude mcp add \
--env BEXIO_API_TOKEN=YOUR_BEXIO_TOKEN BEXIO_READ_ONLY=true \
--transport stdio bexio -- npx -y github:nolen-ai/bexio-mcp
```
### Claude Desktop 和其他客户端
对于 Claude Desktop、Cursor、VS Code、Windsurf、Gemini CLI、Codex CLI、Pi、n8n 和代理 SDK,请使用匹配的 [复制粘贴集成指南](docs/integrations/README.md)。每个指南都使用今天有效的安装方法。
## 身份验证
### 个人访问令牌
个人访问令牌是个人使用的最快捷选项。它具有与您的 bexio 用户相同的访问权限,并在六个月后过期。将其配置为 `BEXIO_API_TOKEN`。
### OAuth 应用工作流
当您需要范围权限、自动令牌刷新或长期部署时,请使用 OAuth:
1. 在 [developer.bexio.com](https://developer.bexio.com) 上创建一个应用,并将其 **允许的回调 URL** 添加到 `http://127.0.0.1:33771/callback`。
2. 在 **应用详情** 下显示 **客户端 ID** 和 **客户端密钥**。
3. 授权一次:
```bash
BEXIO_CLIENT_ID=YOUR_CLIENT_ID \
BEXIO_CLIENT_SECRET=YOUR_CLIENT_SECRET \
npx -y github:nolen-ai/bexio-mcp login
```
浏览器打开以获取许可。令牌存储在 `~/.bexio-mcp/tokens.json` 中;像密码一样对待此文件。
4. 使用 `BEXIO_CLIENT_ID` 和 `BEXIO_CLIENT_SECRET` 而不是 `BEXIO_API_TOKEN` 将服务器添加到您的 MCP 客户端。服务器加载存储的令牌并自动刷新它。
使用 `whoami` 验证已认证的 bexio 用户,或使用 `logout` 注销并删除存储的令牌:
```bash
BEXIO_CLIENT_ID=YOUR_CLIENT_ID BEXIO_CLIENT_SECRET=YOUR_CLIENT_SECRET \
npx -y github:nolen-ai/bexio-mcp whoami
```
## 故障排除
### Claude 报告 `Failed to reconnect … -32000`
确保配置的命令包含 GitHub 包指定符。简短形式 `npx -y bexio-mcp` 在此项目发布到 npm 注册表之前不起作用。
使用以下命令重置不正确的 Claude Code 条目:
```bash
claude mcp remove bexio
claude mcp add --env BEXIO_API_TOKEN=YOUR_BEXIO_TOKEN \
--transport stdio bexio -- npx -y github:nolen-ai/bexio-mcp
claude mcp list
```
### 在 MCP 客户端之外检查服务器
此命令应打印 35 个工具并退出:
```bash
BEXIO_API_TOKEN=YOUR_BEXIO_TOKEN \
npx -y github:nolen-ai/bexio-mcp --list-tools
```
然后验证 bexio 是否接受令牌:
```bash
BEXIO_API_TOKEN=YOUR_BEXIO_TOKEN \
npx -y github:nolen-ai/bexio-mcp whoami
```
如果工具列表失败,请检查 `node --version` 是否为 18 或更新版本,并读取 `npx` 打印的错误。如果 `whoami` 返回 401,请创建新的 PAT 并更新令牌。
## 配置
| 环境变量 | CLI 标志 | 描述 |
| --- | --- | --- |
| `BEXIO_API_TOKEN` | `--token` | 静态令牌(PAT 或 OAuth 访问令牌)。胜过应用工作流。 |
| `BEXIO_CLIENT_ID` | `--client-id` | OAuth 应用客户端 ID(应用工作流)。 |
| `BEXIO_CLIENT_SECRET` | `--client-secret` | OAuth 应用客户端密钥(应用工作流)。 |
| `BEXIO_SCOPES` | `--scopes` | `login` 的范围(默认:从工具组派生)。 |
| `BEXIO_REDIRECT_URI` | `--redirect-uri` | 回调 URI(默认 `http://127.0.0.1:33771/callback`)。 |
| `BEXIO_TOKEN_STORE` | `--token-store` | OAuth 令牌文件(默认 `~/.bexio-mcp/tokens.json`)。 |
| `BEXIO_NO_BROWSER` | `--no-browser` | `login` 打印授权 URL 而不是打开浏览器。 |
| `BEXIO_TOOL_GROUPS` | `--groups` | 要启用的逗号分隔组(默认:全部)。参见下面的组。 |
| `BEXIO_WRITE_MODE` | `--write-mode` | 写入策略:`read-only`、`drafts` 或 `full`(默认:`full`)。 |
| `BEXIO_READ_ONLY` | `--read-only` | 兼容性别名,强制 `BEXIO_WRITE_MODE=read-only`。 |
| `BEXIO_LANGUAGE` | `--language` | 翻译字段的 `Accept-Language`(例如 `de`、`fr`、`it`、`en`)。 |
| `BEXIO_BASE_URL` | `--base-url` | API 主机覆盖(默认 `https://api.bexio.com`)。 |
| `BEXIO_TIMEOUT_MS` | `--timeout-ms` | 每个请求的超时毫秒数(默认 30000)。 |
将这些变量添加到您的 MCP 客户端的 `env` 块或 `--env` 选项中。运行 `npx -y github:nolen-ai/bexio-mcp --help` 获取每个 CLI 选项。
### 写入模式
使用 `BEXIO_WRITE_MODE` 选择服务器端写入策略:
- `read-only` 禁用所有写入。
- `drafts` 允许联系人创建/更新、联系人关系创建/删除、草稿报价创建/更新和未签发草稿报价的自定义位置更改。内联报价位置也必须是自定义位置。它阻止联系人/报价删除、签发/发送/接受/拒绝、所有订单/发票写入以及其他业务变更。
- `full` 暴露令牌允许的每个操作(出于向后兼容性的默认设置)。
```bash
BEXIO_API_TOKEN=YOUR_BEXIO_TOKEN BEXIO_WRITE_MODE=drafts \
npx -y github:nolen-ai/bexio-mcp --list-tools
```
策略禁用的操作从广告的操作枚举中删除,并且在服务器端被拒绝而无需触及 API。在 `read-only` 和 `drafts` 中,`save_path` 被阻止,因为它写入服务器文件系统;省略它以内联返回 PDF。`BEXIO_READ_ONLY=true` 和 `--read-only` 仍然支持作为 `read-only` 的别名。
### 工具组
`contacts`、`sales`、`purchase`、`accounting`、`banking`、`items`、`projects`、`files`、`payroll`、`misc`
```bash
BEXIO_API_TOKEN=YOUR_BEXIO_TOKEN BEXIO_TOOL_GROUPS=contacts,sales,items \
npx -y github:nolen-ai/bexio-mcp --list-tools
```
## 工具
工具按资源分组,具有 `action` 参数;每个工具的描述文档都记录了每个操作及其所需参数。
| 组 | 工具 |
| --- | --- |
| contacts | `bexio_contacts` · `bexio_contact_relations` · `bexio_contact_groups` · `bexio_contact_sectors` · `bexio_additional_addresses` |
| sales | `bexio_quotes` · `bexio_orders` · `bexio_deliveries` · `bexio_invoices` · `bexio_invoice_payments` · `bexio_invoice_reminders` · `bexio_document_positions` · `bexio_document_comments` · `bexio_document_settings` |
| purchase | `bexio_bills` · `bexio_expenses` · `bexio_purchase_orders` · `bexio_outgoing_payments` |
| accounting | `bexio_accounting` · `bexio_currencies` · `bexio_manual_entries` |
| banking | `bexio_bank_accounts` · `bexio_banking_payments` |
| items | `bexio_items` · `bexio_stock` |
| projects | `bexio_projects` · `bexio_project_planning` · `bexio_timesheets` |
| files | `bexio_files` |
| payroll | `bexio_payroll` |
| misc | `bexio_master_data` · `bexio_company_profile` · `bexio_notes` · `bexio_tasks` · `bexio_users` |
亮点:
- 完整的文档生命周期:创建 → 签发 → 发送/标记为已发送 → 付款/提醒 → PDF,用于报价、订单、交付和发票 — 包括将报价转换为订单/发票和订单转换为交付/发票。
- 通过一个通用的 `bexio_document_positions` 工具,在报价、订单和发票上支持七种位置类型(项目、自定义、文本、子总计、折扣、分页符、子位置)。
- PDF 和文件下载接受 `save_path` 参数,以便大型文档存储在磁盘上而不是上下文窗口中。
- 旧搜索端点采用 `search_criteria`:`[{ "field": "name_1", "value": "Muster", "criteria": "like" }]`, 与 AND 结合使用。
## 服务器端和 Docker
当您的 MCP 客户端无法启动本地 stdio 服务器时,或者多个客户端需要相同的部署,请使用发布的 Docker 镜像。
启动服务器:
```bash
docker run -d --name bexio-mcp -p 8722:8722 \
ghcr.io/nolen-ai/bexio-mcp:latest
```
检查:
```bash
curl http://127.0.0.1:8722/healthz
```
MCP 端点是 `http://127.0.0.1:8722/mcp`。在此默认的多用户模式下,每个客户端都发送自己的 bexio 令牌作为 `Authorization: Bearer YOUR_BEXIO_TOKEN`。遵循相关的 [集成指南](docs/integrations/README.md) 获取确切的客户端配置。
### HTTP 身份验证模式
- **多用户(直通)**:不要配置任何服务器凭证。每个客户端都发送自己的 `Authorization: Bearer <bexio PAT 或 OAuth 访问令牌>` 头部;每个 MCP 会话都作为该用户针对 bexio,并且服务器端不存储任何内容。没有令牌的会话被 401 拒绝。
- **共享身份(单租户)**:配置 `BEXIO_API_TOKEN` **或** 应用凭证 — 然后没有自己的承载令牌的会话使用服务器的身份。**这授予对该 bexio 账户的未经身份验证的完全访问权限,适用于可以访问该端口的任何人。** 在非环回绑定(包括 Docker)上,它在您明确设置 `BEXIO_HTTP_SHARED_IDENTITY=true` 之前保持关闭;仅将端口发布到环回或私有网络(`-p 127.0.0.1:8722:8722`)。
对于具有 PAT 的本地、单账户部署:
```bash
docker run -d --name bexio-mcp \
-p 127.0.0.1:8722:8722 \
-e BEXIO_API_TOKEN=YOUR_BEXIO_TOKEN \
-e BEXIO_HTTP_SHARED_IDENTITY=true \
ghcr.io/nolen-ai/bexio-mcp:latest
```
不要将共享身份模式暴露给不受信任的网络:任何可以访问它的人都可以使用配置的 bexio 账户。
### 长期 OAuth 部署
使用 [OAuth 应用工作流](#oauth-app-workflow) 获取刷新令牌,然后播种容器。服务器在命名卷中刷新和持久化轮换令牌:
```bash
docker run -d --name bexio-mcp \
-p 127.0.0.1:8722:8722 \
-v bexio-tokens:/data \
-e BEXIO_CLIENT_ID=YOUR_CLIENT_ID \
-e BEXIO_CLIENT_SECRET=YOUR_CLIENT_SECRET \
-e BEXIO_REFRESH_TOKEN=YOUR_REFRESH_TOKEN \
-e BEXIO_HTTP_SHARED_IDENTITY=true \
ghcr.io/nolen-ai/bexio-mcp:latest
```
对于远程部署,在反向代理中终止 TLS:承载令牌不得通过纯 HTTP 跨网络传输。在代理后面,在 `BEXIO_HTTP_ALLOWED_HOSTS` 中列出其公共主机名。环境变量通过 `docker inspect` 可见;在生产中使用平台的秘密机制。
| 环境变量 | CLI 标志 | 描述 |
| --- | --- | --- |
| `BEXIO_HTTP_HOST` | `--http-host` | 绑定地址(默认 `127.0.0.1`;镜像中的 `0.0.0.0`)。 |
| `BEXIO_HTTP_PORT` | `--http-port` | 端口(默认 `8722`)。 |
| `BEXIO_HTTP_PATH` | `--http-path` | 端点路径(默认 `/mcp`)。 |
| `BEXIO_HTTP_SHARED_IDENTITY` | `--shared-identity` | 选择加入:匿名会话在非环回绑定时可以使用服务器身份(**未经身份验证的帐户访问 - 请参见上文**)。 |
| `BEXIO_HTTP_MAX_SESSIONS` | `--http-max-sessions` | 最大并发 MCP 会话(默认 64)。 |
| `BEXIO_HTTP_ALLOWED_HOSTS` | `--http-allowed-hosts` | 反向代理后面的接受 `Host` 头部值。 |
| `BEXIO_REFRESH_TOKEN` | `--refresh-token` | 无头启动:从刷新令牌播种令牌存储。 |
## 在没有 MCP 的情况下使用客户端
直接从 GitHub 安装:
```bash
npm install github:nolen-ai/bexio-mcp
```
类型化的客户端是无依赖的(使用全局 `fetch`),并且可以独立导入:
```ts
import { BexioClient } from 'bexio-mcp/client';
const bexio = new BexioClient({
token: process.env.BEXIO_API_TOKEN!, // 字符串或异步 () => 字符串
language: 'de',
});
```
OAuth 构建块也被导出 — `BexioOAuth`(带有 PKCE 的授权 URL、代码交换、带有轮换的刷新)和 `OAuthTokenProvider`(自动刷新令牌源)来自 `bexio-mcp/client`,以及 `FileTokenStore` 和 `runLoginFlow` 来自 `bexio-mcp`:
```ts
import { BexioClient, BexioOAuth, OAuthTokenProvider } from 'bexio-mcp/client';
import { FileTokenStore } from 'bexio-mcp';
const oauth = new BexioOAuth({ clientId, clientSecret });
const provider = new OAuthTokenProvider(oauth, new FileTokenStore());
const bexio = new BexioClient({ token: provider.accessTokenProvider() });
// 类型化资源 API 镜像 bexio 文档
const contacts = await bexio.contacts.search([{ field: 'name_1', value: 'Muster' }]);
const invoice = await bexio.invoices.createInvoice({ contact_id: contacts[0]!.id, positions: [/* … */] });
await bexio.invoices.issueInvoice(invoice.id);
// 逃生孔用于其他所有内容
const me = await bexio.http.get('/3.0/users/me');
```
错误是类型化的:`BexioApiError`(带有 `status`、`errorCode`、`body`,以及 `isAuthError`/`isPermissionError`/`isNotFound`/`isRateLimit`)、`BexioRateLimitError`、`BexioNetworkError`、`BexioConfigError`。
将服务器嵌入您自己的进程中:
```ts
import { BexioClient, createBexioMcpServer } from 'bexio-mcp';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = createBexioMcpServer({
client: new BexioClient({ token: myToken }),
groups: ['contacts', 'sales'],
writeMode: 'drafts',
});
await server.connect(new StdioServerTransport());
```
## 开发
```bash
npm install
npm run typecheck # tsc --noEmit
npm test # vitest (包括 API 覆盖率检查)
npm run build # tsup → dist/ (ESM + CJS + d.ts)
```
使用 [just](https://github.com/casey/just):`just check` 运行完整检查,`just docker-build` 构建镜像。
### 发布
发布是基于标签驱动的:推送 `vX.Y.Z` 触发发布工作流,该工作流验证标签是否与 `package.json` 匹配,运行完整检查,将多架构 Docker 镜像推送到 `ghcr.io/nolen-ai/bexio-mcp`(`latest`、`X.Y`、`X.Y.Z`),使用生成的注释创建 GitHub 发布,并在配置了 `NPM_TOKEN` 机密时发布到 npm。
```bash
just bump minor # 升级 package.json + src/version.ts,提交 "Release vX.Y.Z"
git push # 让 CI 在 main 上通过
just tag # 标签 vX.Y.Z(验证干净树、main、推送、版本同步)并推送它
```
参见 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) 获取分层和模块约定。API 表面在 `tests/fixtures/operations.json` 中固定(从官方文档中提取);`tests/coverage.test.ts` 在 bexio 文档的操作而非此包涵盖的操作时失败。
## 注意事项和限制
- bexio 的 API 速率限制是每个公司;大量并行使用工具可能会达到 429 — 客户端等待并自动重试。
- bexio 删除是永久的(无回收站)。破坏性工具操作已注释并在只读模式下被阻止,但请谨慎。
- 信用额度和其他一些商业流程未被 bexio API 本身公开(参见其 [FAQ](https://docs.bexio.com/#section/API-basics/FAQ))。
- 这是一个非官方项目;不隶属于 bexio AG。
## 许可证
MIT
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器