内容
# kicktipp-mcp
一款用于 [KickTipp](https://www.kicktipp.de) 的TypeScript MCP服务器和命令行工具(CLI)。可读取比赛轮次、比赛、赔率、排名和大众预测分布;计算预期积分最优预测;并(先进行模拟运行)提交预测结果——适用于多个社区和账户,通过快速的HTTP直接核心(无需浏览器)。
## 要求
- Node.js 22+
- macOS(使用钥匙串存储凭证;其他平台则使用加密文件作为备用方案)
## 安装
```bash
npm install -g kicktipp-mcp
```
或直接启动MCP服务器,无需全局安装(对于Claude Code集成非常有用,无需将`kicktipp-mcp`添加到PATH中):
```bash
npx kicktipp-mcp
```
> **注意:** `npx kicktipp-mcp` 启动MCP标准输入/输出服务器,而非 `ktipp` 命令行工具。若要使用 `ktipp` 命令行工具,请使用 `npm install -g kicktipp-mcp`。
## 快速入门
### 1. 登录
```bash
ktipp login
```
系统将提示您输入KickTipp邮箱和密码。凭证将安全地存储在macOS钥匙串中,键名为 `kicktipp:<email>`。
### 2. 设置默认社区
```bash
ktipp communities # 列出您的Tipprunden
ktipp use <slug> # 设置默认社区(例如 "bundesliga-tippspiel")
```
### 3. 读取比赛日数据
```bash
ktipp matchday # 当前比赛日:比赛、赔率、您的预测
ktipp matchday -d 5 # 指定比赛日索引
ktipp distribution # 大众预测分布(Tippverteilung)
ktipp predict # 预期积分最优预测
ktipp standings # 足球联赛排名
```
### 4. 提交预测(默认先进行模拟运行)
```bash
# 预览差异(无更改):
ktipp bet --scores "101=2:1,102=0:0"
# 确认后实际提交:
ktipp bet --scores "101=2:1,102=0:0" --yes
```
## 命令行工具参考
所有命令均接受 `--json` 以获取机器可读的输出,`-c <slug>` 以覆盖社区,`-p <email>` 以选择不同的配置文件。
| 命令 | 描述 |
|---|---|
| `login` | 提示输入凭证并保存到钥匙串 |
| `communities` | 列出所有您的Tipprunden |
| `use <slug>` | 为当前配置文件设置默认社区 |
| `matchday [-d N]` | 比赛日索引N的比赛、赔率和当前预测(默认:当前) |
| `distribution [-d N]` | 比赛日索引N的大众预测分布(Tippverteilung) |
| `predict [-d N]` | 基于公布赔率的预期积分最优预测 |
| `standings` | 社区的足球联赛排名 |
| `bet --scores <pairs> [--yes] [-d N]` | 预览(默认)或提交预测。格式:`<matchId>=<home>:<away>,...` |
## MCP服务器 — Claude Code设置
使用 `ktipp login` 保存的会话注册MCP服务器到Claude Code(需要保存的会话):
```bash
claude mcp add kicktipp -- kicktipp-mcp
```
如果您更喜欢通过环境变量传递凭证而不是钥匙串:
```bash
claude mcp add kicktipp \
-e KICKTIPP_EMAIL=you@example.com \
-e KICKTIPP_PASSWORD=secret \
-- kicktipp-mcp
```
### 验证注册
```bash
claude mcp list
```
服务器名称 `kicktipp` 应该出现在列表中,状态为 `connected`。
## MCP工具参考
服务器暴露以下工具。Claude Code将自动调用 `get_status`(服务器 `instructions` 引导它这样做)。
| 工具 | 参数 | 描述 |
|---|---|---|
| `get_status` | — | 账户状态和社区列表。首先调用。 |
| `list_communities` | — | 列出所有您的Tipprunden |
| `get_matchday` | `community`, `spieltagIndex?` | 比赛、赔率和当前预测 |
| `get_schedule` | `community`, `spieltagIndex?` | 比赛日程和结果 |
| `get_standings` | `community` | 足球联赛排名 |
| `get_rules` | `community` | 评分规则(精确/进球差/趋势积分) |
| `get_tip_distribution` | `community`, `spieltagIndex?` | 比赛的大众预测分布(Tippverteilung) |
| `predict_matchday` | `community`, `spieltagIndex?` | 基于赔率的预期积分最优预测 |
| `place_bets` | `community`, `bets[]`, `dry_run?`, `spieltagIndex?` | 提交预测。破坏性操作。`dry_run` 默认 `true`。差异行带有 `status`(`ok`/`locked`/`unknown`);实际提交通过表单读取回执(`verified`)。 |
| `get_bonus_questions` | `community` | 奖金问题(世界杯冠军、小组冠军等)及答案选项、截止日期和当前答案 |
| `place_bonus_bets` | `community`, `bets[]`, `dry_run?` | 按问题/答案文本提交奖金答案(不区分大小写)。多答案问题按槽顺序接受 `answers`。破坏性操作。与 `place_bets` 相同的 `dry_run`/差异/读取回执-`verified` 合同。 |
| `list_accounts` | — | 列出配置的账户。其他工具均接受可选 `account`(邮箱)以作为该账户;省略 = 默认。 |
### 多账户
服务器提供您本地登录的每个账户。添加一个:
```bash
ktipp login # 交互式;仅存储会话cookie(钥匙串)+ 配置文件
```
然后重新连接MCP服务器(例如Claude Code中的 `/mcp`)。`list_accounts`
显示所有账户;传递 `account: "email"` 以使用任何工具作为该账户。`KICKTIPP_EMAIL`(如果设置)选择默认账户。
### 示例:预测分布API
`get_tip_distribution` 返回比赛日每个比赛的大众预测分布:
```json
{
"community": "bundesliga-tippspiel",
"spieltagIndex": 12,
"visibility": "Nach Ablauf der Tippzeit sichtbar",
"matches": [
{
"matchId": 1503034391,
"home": "拜仁慕尼黑",
"away": "多特蒙德",
"byTendency": { "home": 42, "draw": 18, "away": 12 },
"byResult": [
{ "score": "2:1", "pct": 22.5 },
{ "score": "2:0", "pct": 18.3 }
],
"dataAvailable": true
}
]
}
```
可见性由每轮控制(“Sichtbarkeit der Tipps”)。公共轮在投注截止日期后显示数据;私有轮在任何时候都显示数据,只要设置了“立即可见”。
## 预测引擎
`ktipp predict`(命令行工具)和 `predict_matchday`(MCP)使用确定性启发式:
1. 从投注表单中读取公布的赔率(`主胜 / 平局 / 客胜`)。
2. **去边际化:** `p_i = 1/o_i`,然后归一化 `sum(p)` 以去除博彩公司的过盈。
3. **最佳比分:** 对于每种趋势(主胜/平局/客胜),将该趋势的概率分布在小固定比分列表中(例如 `[1:0, 2:1, 2:0, 3:1]` 用于主胜),权重为 `1/(i+1)`。然后扫描有界网格(每边0-4个进球),计算 **预期积分** 作为 `sum_outcomes P(outcome) * points(tip, outcome)`,并选择参数最大值。
4. 返回具有最佳比分、预期积分和理性字符串的预测。
无公布赔率的比赛将被跳过,并附有原因。
## 安全 — 先模拟运行
`place_bets`(命令行工具:`ktipp bet`)默认 **模拟运行模式**。在模拟运行模式下:
- 不执行HTTP写入。
- 返回差异,显示每个比赛的旧预测(如果有)和建议的新预测。
- 每个差异行带有 `status`:`ok`(将提交)、`locked`(投注截止日期后 - 跳过)或 `unknown`(比赛ID不在投注表单上 - 跳过)。因此,模拟运行预览显示实际提交将执行的操作。
在实际提交( `--yes` / `"dry_run": false`):
- 如果没有 `ok` 状态的投注,则不发布任何内容,且 `submitted` 为 `false`。
- 提交POST后,读取回投注表单,并将每个提交的预测与保存状态进行比较:每个 `ok` 行获取 `verified: true/false`,顶级 `verified` 仅当每个提交的预测实际存储时才为 `true`。信任 `verified` 而不是 `submitted` — kicktipp 即使静默删除预测也返回200。
始终在提交前检查差异。服务器指令提醒Claude Code先模拟运行。
## 多账户 / 多社区
`ktipp` 通过存储在 `~/.config/kicktipp-mcp/config.json` 中的配置文件支持多个KickTipp账户。每个配置文件有一个邮箱和一个可选的默认社区。使用 `-p <email>` 为单个命令选择不同的账户,或直接在配置文件中管理配置文件。
## 架构
```
HTTP直接(Node 22原生fetch + cheerio,无浏览器)
纯解析器/优化器(无I/O)-> HTTP客户端 -> 会话(cookie持久性)
-> KickTippClient核心外观 -> MCP适配器 / 命令行工具适配器
```
会话cookie存储在macOS钥匙串中,键名为 `kicktipp:<email>`,并在调用之间重复使用。如果存储的会话过期,则库会自动重新登录。
## 开发
```bash
npm install
npm test # vitest(所有解析器 + 优化器 + 集成测试)
npm run typecheck # tsc --noEmit
npm run build # tsup -> dist/ktipp.js + dist/mcp.js
npm run dev:cli # 运行CLI,无需构建
npm run dev:mcp # 运行MCP服务器,无需构建
```
## 许可证
MIT — 请参阅 [LICENSE](LICENSE)。