关于 Toshl MCP Server
Toshl MCP Server 将 AI Agent 接入 Toshl Finance 数据与操作,涵盖账户、预算、账目和支出分析,并支持 stdio 或经认证的 Streamable HTTP。
主要功能
- 01读取账户、类别、标签和预算
- 02管理账目并拆分交易
- 03创建和更新类别与标签
- 04分析类别支出和预算表现
- 05访问用户资料和账户摘要
- 06通过 stdio 或 Streamable HTTP 运行
适用场景
- 01查看余额和账户详情
- 02检查预算及历史表现
- 03按类别分析支出
- 04创建、更新或拆分财务账目
MCP 相关
将 Toshl Finance 数据作为 MCP 资源提供,并提供读取、管理财务记录及分析支出的工具。默认支持 stdio,也可选用 Streamable HTTP 供远程客户端连接。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Toshl MCP 服务
一个用于将 Toshl Finance 与 AI Agent 集成的 MCP(Model Context Protocol)服务。
概述
Toshl MCP 服务在 AI Agent 与 Toshl Finance API 之间提供桥接。它允许 AI Agent 访问 Toshl 中的财务数据、分析这些数据,并基于数据提供见解和建议。
功能
-
对 Toshl Finance API 端点的只读访问:
- 账户
- 类别
- 标签
- 预算
- 用户信息
- 规划
-
MCP 资源:
- 列出账户
- 获取账户详情
- 列出类别
- 获取类别详情
- 列出标签
- 获取标签详情
- 创建标签
- 列出预算
- 获取预算详情
- 获取预算历史记录
- 获取用户资料
- 获取账户摘要
- 列出条目
-
MCP 工具:
- 账户工具(列出账户、获取账户详情)
- 类别工具(列出类别、获取类别详情、创建类别、更新类别、删除类别)
- 标签工具(列出标签、获取标签详情、创建标签、更新标签、删除标签)
- 预算工具(列出预算、获取预算详情、获取预算历史记录)
- 用户工具(获取资料、获取摘要、获取支付类型、获取支付记录)
- 条目工具(列出条目、获取条目详情、获取条目总和、获取条目时间线、创建条目、更新条目、删除条目、管理条目、拆分条目、撤销拆分)
- 分析工具(按类别分析支出、分析预算表现、分析账户余额)
前提条件
- Node.js(v18.x 或更高版本)
- npm(v8.x 或更高版本)
- Toshl Finance API 令牌
获取 API 令牌
- 前往 https://developer.toshl.com/apps/
- 创建新的个人令牌。在“Description”下填写令牌名称,并在“Password”下填写你的账户密码
安装
- 克隆仓库:
git clone https://github.com/hktari/toshl-mcp-server.git
cd toshl-mcp-server
- 安装依赖项:
npm install
- 根据
.env.example文件创建.env文件:
cp .env.example .env
- 编辑
.env文件并添加你的 Toshl API 令牌:
TOSHL_API_TOKEN=your_api_token
构建
构建项目:
npm run build
运行
启动服务:
npm start
配置 MCP 服务
该服务通过 stdio 使用 MCP。将客户端指向 dist/index.js,并在其环境中传入
TOSHL_API_TOKEN——docs/mcp-clients.md 中提供了适用于 Claude Code、
OpenCode 和 Codex CLI 的分步说明。
对于任何使用通用 mcpServers 配置的其他客户端:
{
"mcpServers": {
"toshl": {
"command": "node",
"args": ["/absolute/path/to/toshl-mcp-server/dist/index.js"],
"env": {
"TOSHL_API_TOKEN": "your-token"
}
}
}
}
远程使用(Streamable HTTP)
stdio 是默认传输方式,无需进行以下配置。若要让无法启动本地进程的客户端(Web 和移动应用、在其他位置运行的服务)访问该服务,请切换为 Streamable HTTP:
MCP_TRANSPORT=http MCP_AUTH_TOKEN="$(openssl rand -hex 32)" TOSHL_API_TOKEN=your-token npm start
服务提供以下端点:
| 路径 | 方法 | 检查项 | 用途 |
|---|---|---|---|
/mcp | POST、GET、DELETE | Host、Origin、Bearer 令牌(静态令牌或 OAuth) | MCP 端点,每个客户端对应一个会话 |
/healthz | GET、HEAD | Host | 存活状态检查。仅返回 {"status":"ok"} |
/.well-known/oauth-*、/oauth/* | 参见 使用 OAuth 登录 | Host | 仅在启用 OAuth 时提供 |
| 变量 | 默认值 | 含义 |
|---|---|---|
MCP_TRANSPORT | stdio | stdio 或 http |
MCP_HTTP_HOST | 127.0.0.1 | 绑定的接口 |
MCP_HTTP_PORT | 3000 | 绑定的端口 |
MCP_AUTH_TOKEN | 未设置 | /mcp 需要 Authorization: Bearer <token>。至少 32 个字符。在 HTTP 模式下,除非启用 OAuth 或设置 MCP_ALLOW_NO_AUTH=true,否则必须设置 |
MCP_ALLOW_NO_AUTH | 未设置 | 精确设置为 true 时,允许 HTTP 模式在未设置 MCP_AUTH_TOKEN 的情况下启动。仅适用于会对每个请求进行身份验证的代理 |
MCP_ALLOWED_HOSTS | 未设置 | 以逗号分隔的 Host 名称列表,除 localhost、127.0.0.1 和 [::1] 外,其他 Host 名称也将被接受 |
MCP_ALLOWED_ORIGINS | 未设置 | 以逗号分隔的来源列表(https://host[:port]),这些来源可通过 /mcp 的 Origin 请求头传入 |
安全性
任何能向 /mcp 发送请求的人都能读取和更改你的 Toshl 数据。
下面每一层都会封堵一种不同的访问途径:
- 必须进行身份验证。 在 HTTP 模式下,如果没有设置
MCP_AUTH_TOKEN或启用内置 OAuth 服务,服务器将拒绝启动;claude.ai 连接器正是通过它登录的。若要改用前置的身份验证代理,请设置MCP_ALLOW_NO_AUTH=true。此时,服务器每次启动都会以错误级别记录SECURITY WARNING。绝不要在未进行身份验证的情况下暴露/mcp,也不要指望难以猜测的 URL 能保护它。 - TLS 和回环地址。 保持默认的回环绑定,并且只通过终止 TLS 的反向代理访问服务器。Bearer 令牌通过请求头传输,因此通过网络使用纯 HTTP 会泄露令牌。
- Host 检查(DNS 重绑定)。 每个请求的
Host都必须是回环地址,或列在MCP_ALLOWED_HOSTS中。这样可以防止你访问的网页将自身域名指向127.0.0.1,再操控本地服务器。代理通常会将公开域名作为Host转发,因此请将该域名列入其中。 - Origin 检查。 按照 MCP 规范的要求,
/mcp会验证Origin。没有Origin的请求会被接受,因为原生客户端、CLI 和服务器端连接器不会发送它。若存在Origin,包括不透明的null,则必须列在MCP_ALLOWED_ORIGINS中,否则请求会被拒绝并返回403,甚至不会进行身份验证检查。默认情况下,该列表为空,因此除非你明确允许,否则任何浏览器页面都无法调用/mcp。
# Caddyfile: automatic TLS, forwards Host unchanged
example.com {
reverse_proxy 127.0.0.1:3000
}
MCP_ALLOWED_HOSTS=example.com
使用 OAuth 登录
claude.ai 连接器(在网页端、Desktop、移动端和 Cowork 上)使用 OAuth 登录,
而不是固定标头。为此,服务器自带一个小型 OAuth 2.1 授权服务器。
这里只有一个用户,批准客户端时需要输入你设置的密码短语。
在 Claude 中添加 https://<your host>/mcp 作为自定义连接器,并将 OAuth 客户端
保留为“Use Claude's published identity”。
| 变量 | 含义 |
|---|---|
MCP_PUBLIC_URL | 公共源站,例如 https://example.com,不带路径。MCP URL 为 <MCP_PUBLIC_URL>/mcp。其主机会自动添加到 MCP_ALLOWED_HOSTS |
MCP_OAUTH_PASSPHRASE | 在登录页面输入,用于批准客户端。至少 20 个字符 |
MCP_OAUTH_SIGNING_KEY | 用于签署访问令牌和登录表单。至少 32 个字符(openssl rand -hex 32) |
MCP_OAUTH_SIGNING_KEY_PREVIOUS | 可选。用于轮换密钥的旧密钥,仍可用于验证,不会让所有用户退出登录 |
MCP_OAUTH_STATE_DIR | 刷新令牌哈希的存储位置。必须能在重启后保留(镜像中为 /app/state) |
MCP_TRUST_PROXY | 设为 true,按代理附加到 X-Forwarded-For 的客户端地址进行速率限制。通过代理运行时请启用此项,否则所有客户端都会共用代理的地址,一个 IP 被锁定就会导致所有人被锁定。如果客户端可以直接访问端口,请保持关闭,因为这样客户端可能伪造此标头 |
设置密码短语和签名密钥后,OAuth 即会启用。它可与
MCP_AUTH_TOKEN 并行使用,因此 Claude Code 或脚本仍可使用静态令牌。
运行方式:
- 客户端。 仅接受 Claude(回调地址
https://claude.ai/api/mcp/auth_callback)和 Claude Code(localhost和127.0.0.1上任意端口的回环回调,遵循 RFC 8252)。 两者均通过已发布的客户端 ID 固定。服务器不会获取元数据文档,因此除 Toshl API 外, 不会连接其他主机。不提供动态客户端注册。 - 必须使用 S256 的 PKCE。
resource参数必须指定此服务器,令牌也会绑定到该服务器。 - 访问令牌的有效期为 1 小时。它们由
MCP_OAUTH_SIGNING_KEY签署,不会存储在任何位置。 更换密钥时若未将旧密钥保留为_PREVIOUS,所有访问令牌都会立即失效。 - 刷新令牌每次使用时都会轮换,未使用 30 天后过期,最长有效期为 180 天,并且仅以 SHA-256 哈希形式存储在
MCP_OAUTH_STATE_DIR/refresh-tokens.json中。- 已使用过的刷新令牌可在 30 秒内重试一次,以兼容客户端同时发起的两次刷新。
- 其他任何重复使用都会撤销该次登录的所有令牌。
- 删除该文件会让所有客户端退出登录。
- 授权码只能使用一次。交换失败会使授权码失效。重放授权码会撤销首次交换所发放的令牌。
- 登录页面:
- 同一 IP(或同一 IPv6 /64)输入错误密码短语 5 次后,该地址会被锁定 15 分钟
- 短时间内来自任何地址的错误次数达到 20 次后,登录会关闭 1 小时。已发放的令牌仍可使用,但这意味着任何人都可以让新登录延迟 1 小时。
- 每次失败都会延迟半秒
- 表单仅接受来自自身源站的 POST 请求,不包含脚本或外部资源,并采用严格的内容安全策略
- 日志会记录登录、失败、锁定和令牌重复使用情况,并包含客户端 ID 和 IP。 密码短语、授权码和令牌绝不会写入日志。
会话
会话保存在内存中。30 分钟没有请求的会话会关闭,客户端会在下一次调用时开启新会话。
退出前,SIGTERM 和 SIGINT 会关闭所有会话。
Docker
Dockerfile 会构建一个以 HTTP 模式启动的镜像,以非特权用户 node 的身份监听端口 3000。在容器内,它会绑定到 0.0.0.0,以便已发布的端口可以访问它。仅在回环地址上发布该端口,并在运行时传入密钥;镜像中不包含任何密钥:
docker build -t toshl-mcp-server .
docker run -d --restart unless-stopped \
-p 127.0.0.1:3000:3000 \
--env-file /path/outside/the/repo/toshl-mcp.env \
toshl-mcp-server
环境变量文件包含 TOSHL_API_TOKEN、MCP_ALLOWED_HOSTS,以及 MCP_AUTH_TOKEN 或 OAuth 设置。若这些设置都未提供,容器会在启动时退出,除非设置了 MCP_ALLOW_NO_AUTH=true。请将该文件的读取权限限制为仅所有者可读(chmod 600)。.dockerignore 会将所有 .env* 文件排除在构建上下文之外。
启用 OAuth 后,请在 /app/state 挂载一个卷(uid 1000 可写),以便重新部署后仍保留登录状态,例如:-v /srv/toshl-mcp/state:/app/state。
开发
以开发模式运行服务:
npm run dev
文档
项目结构
toshl-mcp-server/
├── src/
│ ├── index.ts # Entry point
│ ├── server/ # MCP server implementation
│ │ └── server.ts # Main server class
│ ├── api/ # Toshl API client
│ │ ├── toshl-client.ts # Base API client
│ │ ├── auth.ts # Authentication module
│ │ └── endpoints/ # Endpoint-specific clients
│ │ ├── accounts.ts # Accounts API client
│ │ ├── categories.ts # Categories API client
│ │ ├── tags.ts # Tags API client
│ │ ├── budgets.ts # Budgets API client
│ │ ├── entries.ts # Entries API client
│ │ ├── me.ts # User API client
│ │ └── planning.ts # Planning API client
│ ├── resources/ # MCP resource handlers
│ │ ├── account-resources.ts # Account resources
│ │ ├── category-resources.ts# Category resources
│ │ ├── tag-resources.ts # Tag resources
│ │ ├── budget-resources.ts # Budget resources
│ │ └── user-resources.ts # User resources
│ ├── tools/ # MCP tool handlers
│ │ ├── account-tools.ts # Account tools
│ │ ├── category-tools.ts # Category tools
│ │ ├── tag-tools.ts # Tag tools
│ │ ├── budget-tools.ts # Budget tools
│ │ ├── user-tools.ts # User tools
│ │ └── analysis-tools.ts # Financial analysis tools
│ └── utils/ # Utility functions
│ ├── cache.ts # Caching utilities
│ ├── error-handler.ts # Error handling utilities
│ ├── logger.ts # Logging utilities
│ └── types.ts # TypeScript type definitions
├── dist/ # Compiled JavaScript files
├── .env # Environment variables
├── .env.example # Example environment variables
├── package.json # Project dependencies
├── tsconfig.json # TypeScript configuration
└── README.md # Project documentation
配置
可以使用环境变量配置服务:
TOSHL_API_TOKEN:你的 Toshl API 令牌TOSHL_API_BASE_URL:Toshl API 的基础 URL(默认值:https://api.toshl.com)MCP_SERVER_NAME:MCP 服务的名称(默认值:toshl-mcp-server)MCP_SERVER_VERSION:MCP 服务的版本(默认值:0.1.0)CACHE_TTL:缓存数据的存活时间,单位为秒(默认值:3600)CACHE_ENABLED:是否启用缓存(默认值:true)LOG_LEVEL:日志级别(默认值:info)MCP_TRANSPORT、MCP_HTTP_HOST、MCP_HTTP_PORT、MCP_AUTH_TOKEN、MCP_ALLOW_NO_AUTH、MCP_ALLOWED_HOSTS、MCP_ALLOWED_ORIGINS: 请参阅远程使用(Streamable HTTP)
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。