NexBank MCP Server
by xencio
README.md
# NexBank MCP Server
独立的 NexBank API v2 MCP Server。提供 Stateless Streamable HTTP、Bearer Token、可选 OAuth 授权码接入、MySQL Connection 解析和六个业务工具。
## 准备
1. 使用 Node.js 20 或更高版本安装依赖:`npm install`。
2. 数据库执行唯一脚本 `sql/001_init.sql`。脚本第一部分会删除旧表及其全部数据,第二部分创建统一使用 `nxb_mcp_` 前缀的新表;执行前必须确认旧数据无需保留或已完成备份。
3. 复制 `config/application.example.yaml` 为部署配置,并填写 MySQL 与两个环境的 API Base URL。
4. 通过 `--config <文件>` 或 `NEXBANK_MCP_CONFIG_FILE` 指定配置文件。
不要把真实 AppSecret、Bearer Token 或生产配置提交到仓库。
Token 有效期使用可读 Duration 配置,支持 `s`(秒)、`m`(分钟)、`h`(小时)、`d`(天)。Access Token 默认 1 小时,Refresh Token 默认 365 天:
```yaml
auth:
accessTokenTtl: "1h"
refreshTokenTtl: "365d"
```
OAuth `/token` 响应中的 `expires_in` 始终按秒返回。验证自动刷新时,可在重新授权前暂时设置 `accessTokenTtl: "30s"` 和 `refreshTokenTtl: "10m"`。
## 运行
```text
npm run build
npm start -- --config ./config/application.yaml
```
开发模式:
```text
npm run dev -- --config ./config/application.yaml
```
日志默认同时输出到控制台和 `./logs`,并按照服务所在时区的自然日写入
`nexbank-mcp-server-YYYY-MM-DD.log`。可以通过部署配置调整文件日志:
```yaml
logging:
level: "info"
file:
enabled: true
directory: "./logs"
prefix: "nexbank-mcp-server"
```
设置 `file.enabled: false` 可以只保留控制台日志。日志滚动不会改变既有敏感字段脱敏规则。
MCP 入口默认为 `POST /mcp`,请求必须包含:
```http
Authorization: Bearer <26-character-ULID>.<22-character-random-secret>
```
完整 Token 固定为 49 个字符。第一部分是 26 字符 ULID,第二部分是 16 字节密码学安全随机数的 Base64URL 编码。
Stateless 模式不提供 GET/SSE 会话,`GET /mcp` 和 `DELETE /mcp` 返回 405。
## OAuth 简易绑定
在配置中增加 `oauth` 后,Server 同时支持原有 Bearer Token 和 OAuth 2.1 授权码流程:
```yaml
oauth:
issuerUrl: "https://mcp.example.com"
bindingEnvironment: "sandbox"
```
- `issuerUrl` 必须是对外可访问的 HTTPS Origin;仅本机开发允许 `localhost`、`127.0.0.1` 或 `[::1]` 使用 HTTP。
- `bindingEnvironment` 决定授权页凭证绑定到沙盒还是正式环境。页面本身只填写 `App ID`、`AppSecret`、`customerCode`,不要求用户登录。
- 服务端保留 PKCE、OAuth state、redirect URI 和 resource 校验。授权成功后在同一个数据库事务中创建 Bearer Token 与 `nxb_mcp_connection`,OAuth `/token` 返回的 `expires_in` 与数据库 `expires_at` 的剩余有效期一致。
- OAuth 公共客户端注册信息持久化在 `nxb_mcp_oauth_client`;未完成授权请求和授权码仍只在进程内短期保存。
- 授权码交换同时返回 Access Token、`expires_in` 和 Refresh Token。Refresh Token 只保存 SHA-256 哈希,并绑定 `client_id`、scope 和 resource;每次刷新都会同时轮换 Access Token 与 Refresh Token。
- 已使用 Refresh Token 被再次提交时,服务端会撤销整个 Token Family 及当前 Access Token,客户端必须重新授权。
- OAuth 请求参数会写入结构化日志。`AppSecret`、授权码、PKCE verifier、token 不记录原值,`appId`、`customerCode` 只记录脱敏值。
启用 OAuth 的部署必须通过 HTTPS 暴露授权端点。删除整个 `oauth` 配置块即可继续只使用手工生成的 Bearer Token。
## Token 与 Connection
生成 Token:
```text
npm run token:generate -- --name "调用方名称" --config ./config/application.yaml
```
完整 Token 只显示一次,同时会显示过期时间。随后在 `nxb_mcp_connection` 中按生成记录的数据库主键维护 Sandbox Connection;付费并取得正式配置后,为同一 `access_token_id` 增加 Production Connection。
只有未过期、`enabled=1` 且 `status='active'` 的 Connection 能调用 NexBank。停用 Token 可直接把 `nxb_mcp_access_token.enabled` 更新为 `0`。
## 测试
```text
npm test
npm run test:e2e
```
MySQL 集成测试只允许连接专用测试库:
```text
NEXBANK_MCP_TEST_CONFIG_FILE=./config/application.test.yaml
NEXBANK_MCP_ALLOW_DB_TESTS=true
npm run test:integration
```
集成测试不会创建或删除数据库。真实 Sandbox 联调仅执行只读工具;签约链接生成不属于默认自动化测试。
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues