MCP API Bridge
by dtyg123
README.md
# MCP ⇄ API Bridge
[](https://github.com/dtyg123/mcp-api-bridge/actions/workflows/ci.yml)
[](LICENSE)
[](package.json)
[](https://github.com/dtyg123/mcp-api-bridge/pkgs/container/mcp-api-bridge)
A bidirectional MCP ⇄ API gateway. Expose any MCP server as a REST/OpenAPI service,
or turn any OpenAPI / Swagger 2.0 service into an MCP server — in one process, one
Docker image, with a web admin UI for adding sources. TypeScript, no database, no build
step for the UI.
一个**双向协议网关**:把 MCP Server 变成 REST/OpenAPI 接口,也把 REST/OpenAPI 服务变成 MCP Server。
TypeScript 实现,单进程、单个 Docker 镜像、HTTP 与 stdio 双形态。
<img src="docs/admin.jpg" alt="Web 管理台" width="540" />
**特性**
- **双向**:MCP → REST/OpenAPI,API → MCP,同一份注册表同时对外提供两套接口
- **文档通吃**:OpenAPI 3.0 / 3.1,以及**自动转换的 Swagger 2.0**(`in: body`、`definitions`、`securityDefinitions`,实测雨云 API 217 个操作)
- **零配置接入**:`spec` 支持 URL / 本地文件 / 粘贴文本,`$ref` 自动内联(含外部引用、JSON/YAML)
- **Web 管理台**:可视化添加来源、逐项测试接口、管理可复用的「认证信息」、用左右字段映射编排返回数据、生成可直接粘给 AI 的接入提示词
- **数据编排**:响应到达调用方前重新组装——挑字段、改名、补当前时间 / 固定文本 / 计数,无需改上游或写代码;新增来源后先「编排」再对外提供 MCP 工具
- **原生 MCP**:Streamable HTTP(stateful / stateless)、单来源端点 `/mcp/{source}`、stdio 模式
- **部署友好**:单镜像、非 root、健康检查、`data/` 卷持久化、环境变量插值,上游挂了网关照常启动(降级)
```
┌──────────────────────────────────────────┐
MCP 客户端 │ mcp-api-bridge │ REST 客户端
(Claude Desktop, │ │ (curl, Postman,
Cursor, Cline, │ POST /mcp Streamable HTTP │ ChatGPT Actions,
Agent, ...) ────┼──► /mcp/{source} (MCP 协议) │◄──── 自研服务, ...)
│ │
│ GET /openapi.json 自动生成的 API 文档 │
│ POST /api/{source}/{tool} (REST 调用) │
└───────────────┬──────────────────────────┘
│
┌─────────────────────┴──────────────────────┐
│ │
MCP Server(stdio / Streamable HTTP / SSE) OpenAPI / Swagger 服务(HTTP + JSON)
```
两个方向**同时可用**:同一份工具注册表,同时对外提供 MCP 和 REST 两套接口。
| 方向 | 输入 | 输出 | 典型用途 |
| --- | --- | --- | --- |
| **MCP → API** | `mcpServers[]`(stdio / http / sse) | `POST /api/{source}/{tool}` + `/openapi.json` | 让不支持 MCP 的系统(脚本、低代码平台、Actions)调用 MCP 工具 |
| **API → MCP** | `apis[]`(OpenAPI 3.x / Swagger 2.0 文档,URL 或本地文件) | `POST /mcp`(Streamable HTTP)、`--stdio` | 把已有业务 API 直接接入 Claude / Cursor / Agent |
---
## 快速开始
### Docker Compose(推荐)
```bash
cp bridge.config.example.yaml bridge.config.yaml # 然后按需修改
docker compose up -d --build
curl http://localhost:8080/health
```
### Docker
```bash
docker build -t mcp-api-bridge:latest .
docker run -d --name mcp-bridge \
-p 8080:8080 \
-v "$PWD/bridge.config.yaml:/app/bridge.config.yaml:ro" \
-v "$PWD/data:/app/data" \
-e PUBLIC_BASE_URL=http://localhost:8080 \
mcp-api-bridge:latest
```
也可以直接用发布镜像(打 tag 后自动构建):
```bash
docker run -d --name mcp-bridge -p 8080:8080 \
-v "$PWD/bridge.config.yaml:/app/bridge.config.yaml:ro" \
-v "$PWD/data:/app/data" \
ghcr.io/dtyg123/mcp-api-bridge:latest
```
### 本地运行
```bash
npm install
npm run build
node dist/src/index.js --config bridge.config.example.yaml
```
启动后:
```
GET /health 健康检查
GET /openapi.json 生成的 OpenAPI 文档(全部 REST 侧工具)
GET /tools 工具清单 + JSON Schema
POST /api/{source}/{tool} 调用工具(body = 工具参数)
GET /api/{source}/{tool} 调用工具(query = 工具参数,适合简单工具)
POST /mcp 聚合 MCP 端点(Streamable HTTP)
POST /mcp/{source} 单个来源的 MCP 端点
GET /admin Web 管理台(添加来源 / 测试 / 生成接入提示词)
POST /admin/reload 重新加载 spec / 刷新上游工具列表
GET /admin/api/credentials 认证信息列表(值已掩码)
POST /admin/api/credentials 新增 / 更新认证信息
GET /admin/api/transforms 数据编排列表
PUT /admin/api/transforms 保存某来源 / 接口的编排
POST /admin/api/transforms/preview 用示例响应试算编排(不保存)
GET /admin/api/sources/:kind/:name/discover?tool= 探测某接口返回,递归列出可用字段路径(用于编排)
```
---
## Web 管理台(`/admin`)
启动后打开 `http://localhost:8080/admin`,不用写 YAML 就能接入来源:
| 页面 | 作用 |
| --- | --- |
| **概览** | 来源列表:类型、状态、工具数、是否来自管理台;每行可「测试 / 接口 / 编排 / 编辑 / 提示词 / 删除」 |
| **接口测试** | 逐项调用某个来源的每个接口,填写参数、查看真实响应(请求会真实发往上游) |
| **添加来源** | MCP(stdio / Streamable HTTP / SSE)与 OpenAPI 两个表单,保存后**立即生效**,无需重启;OpenAPI 表单可直接勾选「认证信息」 |
| **认证信息** | 可复用的请求头 / Bearer / Basic 凭证;值保存在服务器本地并始终以掩码显示,来源按名称引用 |
| **数据编排** | 左右字段映射:左列是「探测字段」得到的上游字段(可手动补),右列是自定义输出名(明亮可改);一键「快速编排」原样照搬,再补当前时间 / 固定值 / 模板文本;带示例响应实时预览。新增来源后会自动跳到这里,提示先完成编排 |
| **接入提示词** | 四类提示词一键复制:① 让 AI 通过 MCP 接入 ② 让 AI 通过 REST/OpenAPI 接入 ③ 让 AI 生成「新增 MCP 来源」配置 ④ 让 AI 生成「新增 OpenAPI 来源」配置 |
| **JSON 导入** | 粘贴单条 `{ "type": "mcp" \\| "api", ... }`、批量 `{ mcpServers: [], apis: [] }`,或直接粘贴 Claude Desktop / Cursor 的 `mcpServers` 配置 |
几个关键设计:
- 管理台新增的来源写入 `data/managed-sources.json`(`server.admin.storeFile` / `BRIDGE_DATA_DIR` 可改位置),**不会改写** `bridge.config.yaml`;同名条目以管理台版本为准,所以也能「接管」手写来源。
- 删除只删除管理台条目;配置文件里声明的来源会提示你去改 YAML。
- 「粘贴文档」方式添加 OpenAPI 时,文档会保存到 `data/specs/`,重启后依然可用。
- 「认证信息」和「数据编排」分别持久化到 `data/credentials.json`、`data/transforms.json`(与 `managed-sources.json` 同目录),同样依赖挂载的 `data/` 卷。
- 提示词里的端点、鉴权、工具清单都来自当前运行状态,复制即可粘给 Claude / Cursor / ChatGPT 等工具。
> 公网部署务必设置 `server.adminToken`(或 `BRIDGE_ADMIN_TOKEN`),否则任何能访问 `/admin` 的人都能增删来源。页面里的 Token 只保存在浏览器 localStorage。
Docker 部署时记得挂载数据目录,否则容器重建后管理台新增的来源会丢:
```yaml
volumes:
- ./bridge.config.yaml:/app/bridge.config.yaml:ro
- ./data:/app/data
```
---
## 用法一:把 MCP Server 变成 REST API
配置里加上 MCP Server:
```yaml
mcpServers:
- name: filesystem
transport:
type: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
exposure:
rest: true # 暴露成 REST
mcp: true # 同时在 /mcp 上暴露
prefix: "" # 工具名前缀
- name: remote
transport:
type: http # 也支持 type: sse
url: https://example.com/mcp
headers:
Authorization: Bearer ${REMOTE_MCP_TOKEN}
```
调用:
```bash
# POST:body 就是工具参数
curl -X POST http://localhost:8080/api/filesystem/read_file \
-H 'content-type: application/json' \
-d '{"path":"/data/notes.md"}'
# GET:参数放 query(仅当参数都是基础类型时)
curl 'http://localhost:8080/api/filesystem/read_file?path=/data/notes.md'
```
返回统一封装:
```json
{
"ok": true,
"source": "filesystem",
"tool": "read_file",
"name": "filesystem__read_file",
"isError": false,
"text": "文件内容……",
"data": "文件内容……",
"content": [{ "type": "text", "text": "文件内容……" }],
"meta": { "source": "filesystem", "tool": "read_file" }
}
```
- `content` 是原始 MCP 内容块(text / image / resource …),不做信息丢失
- `data` 是结构化载荷:`structuredContent`,或能被 JSON 解析的文本,否则为原文
- 配置了「数据编排」时,`data` / `text` 会被积木重新组装,并附带 `transformed: true`(详见下文)
- 工具级失败(MCP `isError: true`)返回 **HTTP 200 + `ok: false`**,与 MCP 语义一致;网关级错误用 400 / 404 / 502
- 同时 `GET /openapi.json` 会自动生成完整 OpenAPI 文档,可直接导入 Postman、Dify、ChatGPT Actions 等
---
## 用法二:把 OpenAPI 服务变成 MCP Server
```yaml
apis:
- name: petstore
spec: https://petstore3.swagger.io/api/v3/openapi.json
baseUrl: https://petstore3.swagger.io/api/v3 # 可选,覆盖 servers[0].url
headers:
User-Agent: mcp-api-bridge
include: ["GET /pet/*"] # 可选:只暴露部分操作,支持 * 通配
exclude: ["DELETE /pet/*"] # 可选:排除操作
security: # 可选:按 securitySchemes 注入凭证
ApiKeyAuth: { token: ${PETSTORE_KEY} }
BearerAuth: { token: ${PETSTORE_TOKEN} }
BasicAuth: { username: admin, password: ${PETSTORE_PASS} }
exposure:
rest: true
mcp: true
prefix: ""
```
`spec` 可以是 URL、绝对路径,或相对配置文件所在目录的路径(JSON / YAML 均可,支持 `$ref` 内联,含外部引用)。
**Swagger 2.0 会自动转换**:文档里写 `"swagger": "2.0"`(`in: body` 请求体、`definitions`、`securityDefinitions`、`host`/`basePath`/`schemes`)也能直接接入,网关在内存里转成 OpenAPI 3.1 后再生成工具,不需要事先跑 `swagger2openapi`。例如雨云 API:
```yaml
apis:
- name: rainyun
spec: https://api.rainyun.com/openapi.json # Swagger 2.0,217 个操作
security:
ApiKey: { token: ${RAINYUN_API_KEY} } # -> 请求头 X-Api-Key
```
接入后每个操作一个工具,例如 `POST /product/domain/register` 变成 `rainyun__registerDomain`(未写 `operationId` 时命名为 `post_product_domain_register`),`in: body` 里的字段(`domain`、`duration`、`type`……)会直接展开成工具的入参。
### 接入 MCP 客户端
Streamable HTTP(Claude Desktop、Cursor、Cline、自研 Agent 等):
```json
{
"mcpServers": {
"bridge": {
"type": "http",
"url": "http://localhost:8080/mcp",
"headers": { "Authorization": "Bearer <BRIDGE_MCP_TOKEN>" }
}
}
}
```
也可以按来源拆开,一个来源一个端点:`http://localhost:8080/mcp/petstore`。
### stdio 模式
同一个镜像也能作为本地 stdio MCP Server 使用:
```bash
docker run -i --rm \
-v "$PWD/bridge.config.yaml:/app/bridge.config.yaml:ro" \
mcp-api-bridge:latest --stdio
```
```json
{
"mcpServers": {
"bridge": {
"command": "docker",
"args": ["run", "-i", "--rm", "-v", "/abs/bridge.config.yaml:/app/bridge.config.yaml:ro", "mcp-api-bridge:latest", "--stdio"]
}
}
}
```
---
## 认证信息(可复用凭证)
管理台「认证信息」页把密钥集中保存成**命名凭证**,来源只需按名称引用。轮换密钥时改一处,所有引用它的来源立即生效,不用重写配置。
| 类型 | 生成的请求头 | 字段 |
| --- | --- | --- |
| `header` | `<key>: <value>` | `key`(如 `X-Api-Key`)、`value` |
| `bearer` | `Authorization: Bearer <value>` | `value` |
| `basic` | `Authorization: Basic base64(user:pass)` | `username`、`password` |
列表接口永远只返回掩码(`se••••23`);编辑时留空表示「保持原值」。凭证保存在 `data/credentials.json`,引用关系可以写进 YAML:
```yaml
apis:
- name: rainyun
spec: https://api.rainyun.com/openapi.json
credentialRefs: [rainyun] # 引用「认证信息」里名为 rainyun 的凭证
headers: # 显式请求头优先,同名(忽略大小写)只保留一份
User-Agent: mcp-api-bridge
```
管理台新增 / 编辑来源时也可以直接勾选凭证;保存后立即重建配置并重新加载上游。
---
## 数据编排(字段映射)
「数据编排」在响应到达调用方之前重新组装数据:挑出需要的字段、改名、补上当前时间或固定文本,适合把上游的原始响应整理成前端 / AI 直接可用的形状。**新增来源后必须先完成编排,才对外提供 MCP 工具**(概览页会给未编排的来源打上「未编排」标记,添加来源成功也会自动跳到编排页)。
配置以 `source + tool` 为键(`tool: "*"` 是该来源全部接口的默认规则),保存在 `data/transforms.json`,只作用于 **REST 面**(`/api/{source}/{tool}`)和管理台「接口测试」;MCP 面的 `structuredContent` 保持原样。
### 管理台怎么用(更简单了)
编排页改成**左右字段映射**,不再需要拖积木:
1. 选「来源 / 接口」→ 点 **🔍 探测字段**:后端会真实调用一次该接口(无参,best-effort),把返回 JSON 递归展开成一条条字段路径,例如 `data[].Title`、`code`。数组元素会标成 `data[].xxx` 方便逐条映射。
2. 左侧「可用字段」里每条后面点 **+** 就加到右侧「编排输出」;也可以手动填路径添加自定义字段。
3. 右侧每条都能改**输出名(自定义,明亮显示)**,并能补「当前时间 / 固定值 / 模板文本」这类计算字段。
4. 想省事就点 **🚀 快速编排**:把左侧所有字段**原样照搬**到右侧(输出名默认取末级字段名),之后再挑着改。
5. 底部「示例响应」+「预览」可实时试算;「保存编排」后才生效。没探测到字段时,快速编排会自动开启「保留原字段(passthrough)」。
> 历史里保存过的「逐项编排 / 计数 / 拼接」等复杂编排不会丢:管理台会把它作为只读的「其他」行显示,依然照常在 REST 面生效。
### 配置格式(也可直接写 JSON)
```json
{
"root": "data",
"passthrough": false,
"blocks": [
{ "op": "field", "from": "Title", "as": "title" },
{ "op": "field", "from": "TimeStamp", "as": "time" },
{ "op": "count", "from": "", "as": "total" },
{ "op": "now", "as": "fetchedAt", "format": "iso" }
]
}
```
对应 REST 返回:
```json
{
"ok": true,
"source": "petstore",
"tool": "get_news",
"transformed": true,
"data": {
"title": "……",
"time": "2026-10-04T09:52:13.654Z",
"total": 10,
"fetchedAt": "2026-11-01T04:08:37.457Z"
}
}
```
支持的算子(`op`):
| 算子(`op`) | 作用 | 参数 | 管理台 |
| --- | --- | --- | --- |
| `field` | 取一个字段,可改名 | `from`、`as`(留空 = 同名) | ✅ 字段映射 |
| `text` | 模板文本,`{{path}}` 用数据填充 | `as`、`template` | ✅ 计算字段 |
| `constant` | 固定值(字符串 / 数字 / JSON 对象) | `as`、`value` | ✅ 计算字段 |
| `now` | 当前时间 | `as`、`format`(`iso` / `date` / `time` / `timestamp` / `locale`)、`offsetSeconds` | ✅ 计算字段 |
| `count` | 数组长度 / 对象键数 | `from`、`as` | 仅 JSON / API |
| `join` | 把数组拼成字符串 | `from`、`as`、`separator` | 仅 JSON / API |
| `omit` | 删掉一个字段(配合 `passthrough`) | `from` | 仅 JSON / API |
| `each` | 对数组每个元素执行一组子积木 | `from`、`as`、`blocks` | 仅 JSON / API(历史只读显示) |
几点约定:
- `root` 为空表示整个 `data` 载荷;`from` 留空表示「当前根」,所以 `root` 指向数组时可以用 `count` / `each` 直接处理整个数组。
- 没被选中的字段默认丢弃;`passthrough: true` 保留原字段,再用 `omit` 删掉敏感字段。
- 子积木最多嵌套 5 层;每层的路径都相对于它处理的那个元素。
- 编排本身出错不会吞掉响应:封装里会带 `transformed: false` 和 `transformError`,同时仍然返回原数据。
- 管理台「接口测试」可以传 `raw: true` 查看未编排的原始响应。
---
## 配置说明
```yaml
server:
host: 0.0.0.0
port: 8080
publicBaseUrl: ${PUBLIC_BASE_URL:-} # 生成 /openapi.json 里的 servers[0].url
basePath: "" # 全局路径前缀,例如 /bridge
cors: true
bodyLimit: 10mb
auth:
rest: ${BRIDGE_REST_TOKEN:-} # /api、/openapi.json、/tools
mcp: ${BRIDGE_MCP_TOKEN:-} # /mcp、/mcp/{source}
adminToken: ${BRIDGE_ADMIN_TOKEN:-} # /admin 管理台与 /admin/api/**
admin:
enabled: true # false = 完全关闭管理台
path: /admin
storeFile: ./data/managed-sources.json # 管理台新增的来源(相对配置文件目录)
specsDir: ./data/specs # 「粘贴 OpenAPI 文档」的存放目录
mcp:
path: /mcp
sessionMode: stateful # stateful | stateless
jsonResponse: false # true = 用 JSON 响应替代 SSE 流
rest:
path: /api
openapi:
version: "3.1" # 3.1 | 3.0
title: MCP Bridge API
logging:
level: info # debug | info | warn | error
format: text # text | json
```
- 字符串值支持 `${VAR}` 与 `${VAR:-默认值}` 环境变量插值,敏感信息不必写进文件
- `auth.*` 留空表示关闭鉴权;填值后需 `Authorization: Bearer <token>`(或 `x-api-key`)
- `exposure.{rest,mcp}` 控制某个来源是否出现在对应面上;`exposure.prefix` 用于避免工具名冲突
- `sessionMode: stateless` 时每个请求独立建连,适合多副本无状态部署
- `server.adminToken` 只保护管理台;留空时管理台完全开放(启动日志会警告)
环境变量:`BRIDGE_CONFIG`、`PORT`、`HOST`、`PUBLIC_BASE_URL`、`LOG_LEVEL`、`BRIDGE_REST_TOKEN`、`BRIDGE_MCP_TOKEN`、`BRIDGE_ADMIN_TOKEN`、`BRIDGE_DATA_DIR`。
优先级:命令行参数 > 配置文件 > 环境变量 > 默认值。
---
## 转换规则
### API → MCP(OpenAPI 操作 → 工具)
| 规则 | 说明 |
| --- | --- |
| 工具名 | `{prefix}{source}__{operationId}`,非法字符替换为 `_`,超过 64 字符自动加哈希后缀;重名追加 `_2` |
| 参数 | `path` / `query` / `header` / `cookie` 参数合并到顶层对象;描述前加 `(path)`、`(query)` 等标记 |
| 请求体 | JSON 对象体直接**展开**到顶层(`body.name` → `name`),与参数重名时自动加 `body_` 前缀;数组/字符串等非对象体放进 `body` |
| 必填 | `path` 参数恒为必填;`requestBody.required` 为真时其 `required` 字段才生效 |
| 组合 schema | `$defs` / `definitions` 提升到根级并重写 `$ref` |
| 鉴权 | 按 `securitySchemes` + `security` 自动注入 `Authorization` / `x-api-key` / query / cookie |
| Swagger 2.0 | `in: body` / `in: formData` 先转成 `requestBody`,`definitions` → `components.schemas`,`securityDefinitions` → `securitySchemes`,`collectionFormat` → `style`/`explode`,`host`+`basePath`+`schemes` → `servers[0].url` |
| 媒体类型 | `application/json`、`+json`、`x-www-form-urlencoded`、`multipart/form-data`、`text/*`、二进制 |
| 响应 | JSON → text 内容块 + `structuredContent`;图片 → `image` 内容块;其余 → 文本(超过 200 KB 截断) |
### MCP → API(工具 → OpenAPI)
| 规则 | 说明 |
| --- | --- |
| 路径 | `{rest.path}/{source}/{originalName}` |
| 方法 | 每个工具生成 `POST`(body = 参数对象);参数均为基础类型时额外生成 `GET`(query 参数) |
| Schema | MCP `inputSchema` 原样作为 `requestBody` schema,`$defs` 提升到 `components.schemas` |
| 响应 | 统一 `BridgeToolResult` 封装(`ok` / `isError` / `text` / `data` / `content`) |
| 版本 | `?version=3.0` 可即时获取 3.0 版本(`nullable`、`exclusiveMinimum`、`$ref` 兄弟节点等自动降级) |
---
## 命令行
```
--config <path> 配置文件(YAML/JSON),默认 ./bridge.config.yaml 或 $BRIDGE_CONFIG
--host <host> 覆盖 server.host
--port <port> 覆盖 server.port
--stdio 以 stdio 方式提供 MCP(本地客户端用)
--list-tools 连接上游、打印工具清单后退出(自检用)
--print-config 打印合并后的配置
--log-level <lvl> debug | info | warn | error
--version / --help
```
---
## 已知限制
- 只转发 MCP 的 **tools**;`resources` / `prompts` 暂未桥接
- 文档支持 OpenAPI 3.0 / 3.1 与 Swagger 2.0(自动转换;Swagger 1.x 会给出明确报错)。OpenAPI 3.2 尚未适配
- `multipart/form-data` 的文件字段:传普通字符串时按文本字段发送;需要真实文件时传 `{"filename":"a.png","contentType":"image/png","content":"<base64>"}`
- 会话默认保存在内存中;多副本部署请用 `sessionMode: stateless` 或做粘性会话
- 上游不可达时不影响网关启动,`/health` 会标记 `degraded`(`/health?strict=1` 返回 503)
---
## 开发
```bash
npm install
npm run build # 编译到 dist/
npm test # 编译 + 运行 node:test(含端到端:真实 MCP stdio 上游 + 模拟 REST 上游)
npm run dev # tsx watch
```
```
src/
index.ts CLI 入口(HTTP / stdio / 自检)
config.ts 配置加载、环境变量插值、校验
registry.ts 来源与工具注册表(热重载、命名去重、降级保留)
convert/
openapi-to-tools.ts OpenAPI 操作 → MCP 工具(参数映射 + 请求构造 + 响应转换)
tools-to-openapi.ts MCP 工具 → OpenAPI 文档
schema.ts JSON Schema 提升 / 3.0 降级 / 对象化
openapi/
resolve.ts $ref 内联(本地 + 外部、JSON/YAML、循环检测)
loader.ts 文档加载、baseUrl 解析
upstream/mcp.ts MCP 客户端(stdio / Streamable HTTP / SSE)
mcp/gateway.ts 聚合 MCP Server(动态 tools/list + tools/call)
admin/
store.ts 来源持久化与热重载(managed-sources.json)
credentials.ts 认证信息保险库(credentials.json)
transforms.ts 数据编排积木引擎(transforms.json)
service.ts 来源连通性测试
prompts.ts 接入提示词生成
http/
server.ts Express 路由、鉴权、REST/RPC 封装
mcp-endpoint.ts Streamable HTTP 会话管理(stateful / stateless)
test/ 单元测试 + 端到端测试
```
## 贡献
欢迎 PR,开发约定见 [CONTRIBUTING.md](CONTRIBUTING.md)。安全漏洞请按 [SECURITY.md](SECURITY.md) 私下报告,不要开公开 Issue。
## License
MIT © [dtyg123](https://github.com/dtyg123)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues