内容
# goagain
一款用于[Flesh and Blood](https://fabtcg.com)卡牌游戏数据的REST API和MCP(Model Context Protocol)服务器。
## 功能
- **REST API** - 查询卡牌、卡牌集、关键词和能力,支持筛选和分页
- **MCP Server** - 将Flesh and Blood卡牌数据集成到AI助手(如Claude等)
- **格式合法性** - 检查 Blitz、Classic Constructed、Commoner、Living Legend、Silver Age 和 UPF 等格式的卡牌合法性
- **全文搜索** - 搜索卡牌能力和效果
- **可观察性** - 生产环境部署的OpenTelemetry跟踪、指标和日志
- **Docker就绪** - 用于轻松部署的多平台容器镜像
## 主机服务
公共实例可访问:
- **REST API**:https://api.goagain.dev
- **MCP Server**:https://mcp.goagain.dev
## 快速开始
### 使用Go运行
```bash
# 克隆仓库
git clone --recursive https://github.com/oleiade/goagain.git
cd goagain
# 运行API服务器(默认端口8080)
go run ./cmd/api
# 或运行MCP服务器(默认端口8081)
go run ./cmd/mcp
```
### 使用Docker运行
```bash
# API服务器
docker run -p 8080:8080 ghcr.io/oleiade/goagain-api
# MCP服务器(HTTP模式)
docker run -p 8081:8081 -e MCP_MODE=http ghcr.io/oleiade/goagain-mcp
```
## REST API
### 端点
| 端点 | 描述 |
| --- | --- |
| `GET /` | 首页(HTML)或API信息(JSON with `Accept: application/json`) |
| `GET /health` | 健康检查,包含数据统计 |
| `GET /docs` | 交互式Swagger UI文档 |
| `GET /openapi.yaml` | OpenAPI 3.0规范 |
| `GET /cards` | 列出/搜索卡牌 |
| `GET /cards/{id}` | 通过唯一ID或名称获取卡牌 |
| `GET /cards/{id}/legality` | 获取卡牌在所有格式中的合法性 |
| `GET /sets` | 列出/搜索卡牌集 |
| `GET /sets/{id}` | 获取卡牌集详情,包含卡牌列表 |
| `GET /keywords` | 列出所有关键词 |
| `GET /keywords/{name}` | 获取关键词描述 |
| `GET /abilities` | 列出所有能力 |
### 卡牌搜索参数
| 参数 | 描述 |
| --- | --- |
| `name` | 通过卡牌名称筛选(部分匹配) |
| `type` | 通过卡牌类型筛选(例如,`Action`,`Attack`,`Equipment`) |
| `class` | 通过职业筛选(例如,`Warrior`,`Ninja`,`Wizard`) |
| `set` | 通过卡牌集代码筛选(例如,`WTR`,`ARC`,`MON`) |
| `pitch` | 通过出牌值筛选(`1`,`2`或`3`) |
| `keyword` | 通过关键词筛选(例如,`Go again`,`Dominate`) |
| `q` | 卡牌能力全文搜索 |
| `legal_in` | 通过格式合法性筛选(`blitz`,`cc`,`commoner`,`ll`,`silver_age`,`upf`) |
| `limit` | 每页结果数(默认50,最大100) |
| `offset` | 分页偏移量 |
### 示例
```bash
# 搜索忍者攻击动作
curl "https://api.goagain.dev/cards?class=Ninja&type=Attack"
# 查找卡牌文本中包含“draw”的卡牌
curl "https://api.goagain.dev/cards?q=draw"
# 获取特定卡牌
curl "https://api.goagain.dev/cards/WTR001"
# 检查格式合法性
curl "https://api.goagain.dev/cards/WTR001/legality"
# 列出所有卡牌集
curl "https://api.goagain.dev/sets"
```
## MCP服务器
MCP服务器允许AI助手查询Flesh and Blood卡牌数据。它支持stdio(用于本地集成)和HTTP传输。
### 工具
| 工具 | 描述 |
| --- | --- |
| `search_cards` | 通过名称、类型、职业、卡牌集、出牌值或关键词搜索卡牌 |
| `get_card` | 通过ID或名称获取卡牌完整详情 |
| `list_sets` | 列出所有卡牌集 |
| `search_sets` | 通过名称或代码搜索卡牌集 |
| `get_set` | 获取卡牌集详情,包含可选的卡牌列表 |
| `search_card_text` | 卡牌能力全文搜索 |
| `get_format_legality` | 检查卡牌在所有格式中的合法性 |
| `list_keywords` | 列出所有游戏关键词 |
| `get_keyword` | 获取关键词描述 |
### Claude桌面集成
添加到Claude桌面配置(`claude_desktop_config.json`):
**使用托管服务:**
```json
{
"mcpServers": {
"fab-cards": {
"url": "https://mcp.goagain.dev/mcp"
}
}
}
```
**使用本地二进制文件:**
```json
{
"mcpServers": {
"fab-cards": {
"command": "/path/to/goagain-mcp"
}
}
}
```
**使用本地HTTP模式:**
```json
{
"mcpServers": {
"fab-cards": {
"url": "http://localhost:8081/mcp"
}
}
}
```
## 配置
所有配置均通过环境变量进行。完整的模板请参见`.env.example`。
### API服务器
| 变量 | 默认值 | 描述 |
| --- | --- | --- |
| `PORT` | `8080` | API服务器端口 |
| `CORS_ORIGINS` | `*` | 以逗号分隔的允许来源 |
| `RATE_LIMIT_RPS` | `100` | 速率限制(每秒请求数,每IP) |
| `TRUSTED_PROXIES` | | 以逗号分隔的CIDR块,用于代理头信任 |
| `API_BASE_URL` | `https://api.goagain.dev` | 首页和文档中显示的基本URL |
| `MCP_BASE_URL` | `https://mcp.goagain.dev` | 首页中显示的MCP URL |
### MCP服务器
| 变量 | 默认值 | 描述 |
| --- | --- | --- |
| `MCP_MODE` | `stdio` | MCP传输:`stdio`或`http` |
| `MCP_PORT` | `8081` | MCP HTTP服务器端口 |
### 可观察性
| 变量 | 默认值 | 描述 |
| --- | --- | --- |
| `LOG_LEVEL` | `info` | 日志级别:`debug`,`info`,`warn`,`error` |
| `LOG_FORMAT` | `json` | 日志格式:`json`或`text` |
| `SERVICE_NAME` | `goagain-api` / `goagain-mcp` | 日志服务名称 |
| `METRICS_ENABLED` | `true` | 启用OTel指标收集 |
### OpenTelemetry
| 变量 | 默认值 | 描述 |
| --- | --- | --- |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | _(无)_ | OTLP端点(例如,`localhost:4318`)。如果未设置,遥测数据将输出到stdout |
| `OTEL_SERVICE_NAME` | `goagain-api` / `goagain-mcp` | 跟踪、指标和日志的服务名称 |
| `OTEL_SERVICE_VERSION` | `0.1.0` | 遥测中报告的服务版本 |
| `OTEL_ENVIRONMENT` | `development` | 部署环境(例如,`production`,`staging`) |
## 可观察性
两个服务器都包含用于生产部署的内置OpenTelemetry可观察性,提供分布式跟踪、指标和结构化日志。
### OpenTelemetry集成
默认情况下,所有遥测数据都输出到stdout(适用于本地开发)。要将遥测数据发送到OTLP兼容的收集器(例如Grafana Alloy、Jaeger或任何OTel收集器),请设置`OTEL_EXPORTER_OTLP_ENDPOINT`环境变量:
```bash
# 将遥测数据发送到本地收集器(适用于API和MCP服务器)
export OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4318
# 可选:自定义服务元数据
export OTEL_SERVICE_NAME=goagain-api # 或goagain-mcp适用于MCP服务器
export OTEL_SERVICE_VERSION=1.0.0
export OTEL_ENVIRONMENT=production
```
API服务器(`cmd/api`)和MCP服务器(`cmd/mcp`)使用相同的OTel配置,并将跟踪、指标和日志导出到同一个端点。
### 分布式跟踪
**HTTP请求** (适用于API和MCP服务器):
HTTP请求使用`otelhttp`自动跟踪。每个请求都会创建一个span,包含:
- HTTP方法、路由和状态码
- 请求/响应大小
- 时间信息
- 跟踪上下文传播(W3C TraceContext和Baggage)
**MCP工具调用** (仅限MCP服务器):
每个MCP工具调用都会创建一个子span(`mcp.tool.<name>`),包含:
- 工具名称和执行时间
- 结果计数和错误状态
- 与父HTTP span链接(在HTTP模式下)
### 指标
使用OTel指标API收集指标,并通过OTLP导出。
**HTTP指标:**
- `http.server.request.total` - 总HTTP请求
- `http.server.request.duration` - 请求延迟直方图(秒)
- `http.server.active_requests` - 当前正在进行的请求
- `http.server.response.size` - 响应大小直方图(字节)
- `http.server.rate_limit.rejected` - 速率限制拒绝(仅限API)
**MCP工具指标:**
- `mcp.tool.invocations.total` - 工具调用总数
- `mcp.tool.duration` - 工具执行延迟(秒)
- `mcp.tool.result_count` - 每次调用返回的结果数
- `mcp.tool.active` - 正在进行的工具调用
**应用程序指标:**
- `goagain.data.cards` - 加载的卡牌总数
- `goagain.data.sets` - 加载的卡牌集总数
- `goagain.data.keywords` - 加载的关键词总数
- `goagain.data.abilities` - 加载的能力总数
- `goagain.data.index_entries` - 按索引名称划分的索引条目
### 结构化日志记录
日志以结构化JSON格式输出到stdout,并发送到OTel日志管道:
```json
{
"time": "2025-01-25T14:30:00.123Z",
"level": "INFO",
"msg": "HTTP请求完成",
"service": "goagain-api",
"request_id": "01HQXYZ123ABC",
"method": "GET",
"path": "/cards",
"status": 200,
"duration_ms": 12.5,
"client_ip": "192.168.1.100"
}
```
### Grafana Cloud集成
对于Grafana Cloud,请配置[Grafana Alloy](https://grafana.com/docs/alloy/)以接收OTLP遥测:
```alloy
otelcol.receiver.otlp "default" {
grpc { endpoint = "0.0.0.0:4317" }
http { endpoint = "0.0.0.0:4318" }
output {
traces = [otelcol.exporter.otlp.grafana.input]
metrics = [otelcol.exporter.otlp.grafana.input]
logs = [otelcol.exporter.otlp.grafana.input]
}
}
```
然后将应用程序指向Alloy:
```bash
export OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4318
```
## 开发
### 前提条件
- Go 1.25+
- [golangci-lint](https://golangci-lint.run/)(用于 linting)
- [k6](https://k6.io/)(用于负载测试,可选)
### 命令
```bash
# 构建
go build -v ./...
# 测试
go test -race -v ./...
# linting
golangci-lint run
# 运行负载测试(需要运行API服务器)
k6 run tests/k6/api.js
```
### 更新卡牌数据
卡牌数据来源于上游子模块。要更新:
```bash
./scripts/sync-data.sh
```
## 贡献
欢迎贡献!请:
1. 分叉仓库
2. 创建一个功能分支(`git checkout -b feature/amazing-feature`)
3. 进行更改
4. 运行测试和linting(`go test -race -v ./... && golangci-lint run`)
5. 使用[约定提交](https://www.conventionalcommits.org/)提交更改
6. 推送到您的分支(`git push origin feature/amazing-feature`)
7. 打开拉取请求
## 数据归属
所有卡牌数据来源于[flesh-and-blood-cards](https://github.com/the-fab-cube/flesh-and-blood-cards)项目,由[The Fab Cube](https://github.com/the-fab-cube)维护。本项目对[flesh-and-blood-cards](https://github.com/the-fab-cube/flesh-and-blood-cards)项目表示深深的感谢。
## 法律免责声明
**Flesh and Blood**是Legend Story Studios(LSS)的商标。所有卡牌名称、艺术作品和游戏机制都是Legend Story Studios的知识产权。
本项目不是由Legend Story Studios生产、认可、支持或附属的。本项目是一个非官方的、由粉丝制作的项目,旨在教育和社区目的。
本API提供的卡牌数据来源于公开可用的信息,旨在帮助玩家、开发者和内容创作者为Flesh and Blood社区构建工具和应用程序。
使用Flesh and Blood卡牌数据应遵守Legend Story Studios的[社区准则](https://fabtcg.com/resources/community-guidelines/)和[知识产权政策](https://fabtcg.com/resources/ip-policy/)。
## 许可证
本项目是开源的。请参见[LICENSE](LICENSE)获取详细信息。