内容
# Steam MCP 服务器
一个 [模型上下文协议(MCP)](https://modelcontextprotocol.io/) 服务器,为 AI 助手提供访问 Steam 个人资料、游戏库、愿望清单和商店数据的能力 — — 构建用于支持 **[Steam 礼物推荐器](.github/agents/steam-gift-recommender.agent.md)** 代理。采用 .NET 编写,通过标准输入/输出进行通信。
指向任何 Steam 个人资料,推荐该用户尚未拥有的游戏,基于证据:他们的愿望清单、游戏时间历史和近期活动。
> **范围说明:** 工具表面故意设计得非常简单 — — 它只实现了推荐器代理所需的确切功能,而不是完整的 Steam 网络 API。它仍然可以用作一般的 Steam MCP 服务器(例如 *"这个用户最近玩了什么?"*、 *"寻找合作 roguelikes"*),但只有在有需求的情况下才会添加新工具。
## Steam 礼物推荐器代理
[`.github/agents/steam-gift-recommender.agent.md`](.github/agents/steam-gift-recommender.agent.md) 为 GitHub Copilot 在 VS Code 中定义了一个自定义代理。给定一个 Steam 个人资料(steamId64、vanity 名称或个人资料网址),它:
1. 将个人资料解析为规范的 steamId64 并检查哪些数据是公开的。
2. 读取已拥有的游戏、最近玩过的游戏和愿望清单。
3. 从强信号中推断口味 — — 愿望清单意图、近期活动、大量玩过的游戏类型、系列亲和力。
4. 按标签搜索商店,验证候选游戏的商店元数据,并排除已拥有的游戏。
5. 返回一个主要推荐和最多两个备份,每个备份都有引用的证据,并在隐藏的个人资料数据使安全的推荐无法实现时明确说明。
要使用它:
1. 在 `.vscode/mcp.json` 中配置 MCP 服务器,名称为 `steamMcp`(参见 [客户端设置](#客户端设置) — — 代理引用其工具为 `steammcp/...`)。
2. 打开 Copilot 聊天并调用 **Steam 礼物推荐器** 代理。
3. 提供个人资料: *"为 steamcommunity.com/id/gaben 推荐一份礼物"*。
代理的约束(从不发明 Steam 数据,从不推荐已拥有的游戏,始终引用证据)决定了此服务器的设计 — — 结构化的 `blocked` 响应和原因代码存在,以便代理可以诚实地推理私有个人资料,而不是编造。
## 工具
| 工具 | 描述 | 需要 API 密钥 |
|---|---|---|
| `steam_resolve_profile_to_steamid64` | 将 vanity ID、个人资料网址或 steamId64 归一化为规范的 steamId64 | 是 |
| `steam_get_player_summary` | 玩家摘要(姓名、头像、状态、可见性) | 是 |
| `steam_get_owned_games` | 按游戏时间排序的已拥有游戏,分页(每次调用最多 100 个) | 是 |
| `steam_get_wishlist` | 公共愿望清单片段,分页(每次调用最多 100 个) | 是 |
| `steam_get_recently_played_games` | 最近两周内玩过的游戏 | 是 |
| `steam_get_profile_data_availability` | 报告个人资料的哪些数据是公开/私有的 | 是 |
| `steam_search_store_apps` | Steam 商店目录的文本搜索(最多 50 个结果) | 是 |
| `steam_search_store_apps_by_tags` | 按 Steam 标签 ID 筛选的商店搜索,可选文本查询 | 否 |
| `steam_get_store_app_metadata` | 最多 25 个 appId 的紧凑型商店元数据(价格、游戏类型、发布日期) | 否 |
每个工具返回一个一致的信封:
```json
{
"status": "ok | blocked",
"steamId": "76561198000000000",
"toolType": "get_owned_games",
"summary": "结果的人类可读摘要。",
"data": { },
"reasonCode": "profile_private"
}
```
`blocked` 响应带有机器可读的 `reasonCode`(例如 `profile_private`、`owned_games_hidden`、`invalid_steam_id`、`rate_limited`、`insufficient_data`),而不是抛出错误,以便助手可以解释 *为什么* 数据不可用。
## 要求
- **Steam 网络 API 密钥** — — 免费,在 [steamcommunity.com/dev/apikey](https://steamcommunity.com/dev/apikey) 获取
- **.NET 10 SDK** ([下载](https://dotnet.microsoft.com/download))— — 或者,如果您更喜欢容器路由,则使用 **Docker**
## 配置
所有配置均通过环境变量进行:
| 变量 | 必需 | 默认值 | 描述 |
|---|---|---|---|
| `STEAM_API_KEY` | 是* | — | Steam 网络 API 密钥。*如果没有它,需要它的工具将返回 `blocked` 响应而不是崩溃。 |
| `CACHE_ENABLED` | 否 | `true` | 启用内存响应缓存 |
| `CACHE_TTL_MINUTES` | 否 | `15` | 缓存条目生命周期 |
| `STEAM_API_BASE_URL` | 否 | `https://api.steampowered.com/` | 用于测试/代理的覆盖 |
## 运行
### 选项 1:dotnet
```sh
dotnet run --project SteamMCP.Host.Stdio -c Release
```
服务器通过标准输入/输出进行 MCP 通信;日志输出到标准错误流。通常,您不会手动运行它 — — 您的 MCP 客户端会启动它(参见下文)。
### 选项 2:Docker
```sh
docker build -t steam-mcp-stdio:local .
```
```sh
docker run --rm -i -e STEAM_API_KEY=your-key steam-mcp-stdio:local
```
## 客户端设置
### Claude 代码
```sh
claude mcp add steam --env STEAM_API_KEY=your-key -- dotnet run --project /path/to/SteamMCP.Host.Stdio -c Release
```
或者使用 Docker:
```sh
claude mcp add steam -- docker run --rm -i -e STEAM_API_KEY=your-key steam-mcp-stdio:local
```
### Claude 桌面版
添加到 `claude_desktop_config.json`:
```json
{
"mcpServers": {
"steam": {
"command": "docker",
"args": ["run", "--rm", "-i", "-e", "STEAM_API_KEY=your-key", "steam-mcp-stdio:local"]
}
}
}
```
### VS Code(GitHub Copilot)
在工作区中创建 `.vscode/mcp.json` — — 此版本提示输入密钥,而不是将其存储在文件中:
```json
{
"servers": {
"steamMcp": {
"type": "stdio",
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "STEAM_API_KEY=${input:steam-api-key}",
"steam-mcp-stdio:local"
]
}
},
"inputs": [
{
"type": "promptString",
"id": "steam-api-key",
"description": "Steam 网络 API 密钥",
"password": true
}
]
}
```
然后从命令面板运行 `MCP: List Servers` 并启动 `steamMcp`。
## 项目结构
```
SteamMCP.Domain 契约、原因代码、模型、Steam ID 解析
SteamMCP.Application 请求验证和编排
SteamMCP.Infrastructure.Steam Steam 网络 API + 商店 HTTP 客户端、缓存、限流
SteamMCP.Host.Stdio MCP 服务器引导和工具定义
```
参见 [docs/solution-structure.md](docs/solution-structure.md),了解分层约定以及如何添加新工具。
## 行为说明
- **私有个人资料永远不会出错** — — 工具返回 `status: "blocked"`,并附有描述隐藏内容的理由代码。
- **商店端点在内部受到限流**,以保持对 Steam 公共端点的礼貌。
- **响应在内存中缓存**(默认 15 分钟),以减少会话内重复的上游调用。
## 许可证
[MIT](LICENSE)