内容
<p align="center">
<img src="assets/logo.svg" width="120" alt="agones-conductor-mcp logo" />
</p>
<h1 align="center">agones-conductor-mcp</h1>
<p align="center">
<a href="https://github.com/nicklesimba/agones-conductor-mcp/actions/workflows/ci.yml"><img src="https://github.com/nicklesimba/agones-conductor-mcp/actions/workflows/ci.yml/badge.svg" alt="持续集成" /></a>
<a href="https://github.com/nicklesimba/agones-conductor-mcp/actions/workflows/e2e.yml"><img src="https://github.com/nicklesimba/agones-conductor-mcp/actions/workflows/e2e.yml/badge.svg" alt="端到端测试" /></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg" alt="许可证:Apache-2.0" /></a>
</p>
适用于 [Agones](https://agones.dev) 的 MCP 服务器,这是一个 Kubernetes 原生的专用游戏服务器平台。需要一个您已经可以访问的 Agones 集群(请参见[要求](#要求))。
通用 Kubernetes MCP 服务器将 Agones 集群视为不透明的自定义资源。它们不知道已分配的 `GameServer` 具有实时匹配的玩家,也不知道 Fleet 通过回收 `Ready` 服务器来缩减规模,或者 FleetAutoscaler 达到其上限意味着玩家即将排队。该服务器原生支持 Agones,因此 AI 助手可以调查事件、回答容量问题并安全地操作 Fleet。
## 示例提示
- “为什么欧盟玩家无法进入比赛?”
- “哪些 Fleet 接近其自动缩放器的上限?”
- “显示给我所有不健康的服务器以及它们发生了什么”
- “将练习 Fleet 缩减到 10,而不影响实时比赛”
- “为我从排名 Fleet 中分配一个服务器”
一个真实的例子,“排名 Fleet 的利用率如何?”,调用 `fleet_capacity`:
```json
{"fleets":[{"fleet":"ranked","namespace":"default","allocated":3,"ready":2,"utilizationPct":60,"autoscalerCeiling":6,"atCeiling":false}]}
```
→ “排名 Fleet 的利用率为 60%:3 个比赛正在进行,2 个服务器空闲,自动缩放器可以增长到 6 个,否则就没有空间了。”
## 工具
| 工具 | 类型 | 描述 |
|---|---|---|
| `list_fleets` | 读取 | 具有期望/就绪/已分配/预留计数的 Fleet |
| `list_gameservers` | 读取 | GameServers,可按状态或 Fleet 过滤 |
| `get_gameserver` | 读取 | 一个 GameServer 的完整详细信息:标签、注释、计数器/列表、节点、镜像、终止状态 |
| `gameserver_events` | 读取 | GameServer 的 Kubernetes 事件(诊断故障) |
| `fleet_events` | 读取 | Fleet 及其 GameServerSets 的事件:回答“为什么 Fleet 缩减了?” |
| `autoscaler_events` | 读取 | FleetAutoscaler 的事件:何时以及为什么它被缩放 |
| `gameserver_logs` | 读取 | GameServer 的容器日志(首先验证它是否存在;这不是一个通用的 Pod 日志读取器)。默认为游戏容器,`container` 重写;`previous=true` 用于崩溃实例 |
| `list_autoscalers` | 读取 | 具有策略、边界、缩放限制状态的 FleetAutoscalers |
| `fleet_capacity` | 读取 | 跨 Fleet 利用率报告,根据实时 GameServer 状态计算,而不是聚合 Fleet 状态,它滞后几秒钟。利用率是已分配 / (已分配 + 已就绪):正在使用的可玩服务器份额 |
| `create_fleet` | 写入 | 创建一个具有单个容器 GameServer 模板的 Fleet:端口策略和协议(UDP/TCP/TCPUDP)、资源、调度、初始计数器/列表 |
| `delete_fleet` | 写入 | 删除一个 Fleet 及其 GameServers;如果任何一个已分配,除非 `force=true`,否则拒绝 |
| `scale_fleet` | 写入 | 设置 Fleet 副本;缩减永远不会破坏实时比赛 |
| `allocate_gameserver` | 写入 | 为比赛分配一个服务器;在分配时过滤和更新计数器/列表,在服务器上打上匹配标签/注释,或设置 `preferReuse` 以优先将玩家打包到具有空间的正在运行的比赛中 |
| `delete_gameserver` | 写入 | 删除一个服务器;除非 `force=true`,否则拒绝已分配的服务器 |
| `update_fleet_image` | 写入 | 更新 Fleet 的容器镜像,触发 Agones 自己的分配感知滚动更新 |
| `update_fleet_resources` | 写入 | 更新 Fleet 容器的 CPU/内存请求和限制,触发相同的滚动更新 |
| `update_fleet_health` | 写入 | 更新 Fleet 的健康检查设置(禁用、periodSeconds、failureThreshold、initialDelaySeconds),触发相同的滚动更新 |
| `update_fleet_env` | 写入 | 设置或删除 Fleet 容器上的环境变量,触发相同的滚动更新 |
| `rollout_status` | 读取 | 滚动更新进度:当前与上一个 GameServerSets、完成百分比以及当旧版本服务器仍有实时比赛阻止完成时的警告 |
| `create_autoscaler` | 写入 | 创建一个 FleetAutoscaler:缓冲区策略(保留 N 个就绪服务器)或计数器/列表策略(根据聚合容量缩放,例如总空闲玩家插槽),具有可配置的同步间隔 |
| `update_autoscaler` | 写入 | 更新 FleetAutoscaler 的缓冲区大小、副本边界或同步间隔 |
| `delete_autoscaler` | 写入 | 删除一个 FleetAutoscaler;Fleet 及其 GameServers 不受影响 |
| `agones_health` | 读取 | Agones 本身是否健康?控制器/分配器/扩展/Ping Pod 准备情况和重启次数 |
| `list_clusters` | 读取 | 列出已配置的集群以及哪个是默认集群(仅在多集群模式下有意义) |
| `open_match_create_ticket` | 写入 | 将玩家/队伍带入 [Open Match](https://open-match.dev) 匹配,返回票据 ID |
| `open_match_ticket_status` | 读取 | 检查票据:仍在搜索中,还是与连接分配相匹配 |
| `open_match_cancel_ticket` | 写入 | 从匹配中撤回票据 |
上述除 `list_clusters` 之外的所有工具还接受一个可选的 `cluster` 参数(参见[多集群](#多集群))。除 `allocate_gameserver` 之外的所有写入工具都接受 `dryRun: true` 以进行服务器端验证传递,该传递不会持续任何内容,因此代理可以显示其工作,然后进行实际调用。 `open_match_*` 工具另外需要 Open Match 连接已配置(参见[Open Match](#open-match)),如果未配置,则返回一个明确的错误。
所有 27 个工具都针对一个实时 Agones 集群(kind + Agones 1.57),不仅针对模拟的测试,还进行了单元测试 - 而且不是基于荣誉制度:相同的 45 检查套件在公共 CI 中每次推送都会运行(`test/e2e/mcp_e2e.py`,[e2e.yml](.github/workflows/e2e.yml)),驱动实际的二进制文件通过 MCP 标准输入/输出作为特权最小的 ServiceAccount 针对一个全新的 kind 集群。以下是一些亮点,以及开发过程中完成的个别深入验证:
- `delete_gameserver` 的安全门:拒绝没有 `force` 的操作,成功时带有 `force`,以及一个竞争测试,证明如果服务器在检查和删除之间被分配,拒绝仍然有效。
- `scale_fleet` 缩放/缩减,实时分配不受影响,包括在模拟并发写入(FleetAutoscaler 也写入 `Fleet.Spec.Replicas`)下。
- 一个真正的 `update_fleet_image` 滚动更新,`rollout_status` 正确地将其报告为在两个旧版本服务器仍有实时比赛时卡住 50%。
- 一个完整的 `create_fleet` → `create_autoscaler` → `update_autoscaler` → `delete_autoscaler` → `delete_fleet` 往返,包括一个故意构造的调用,以违反 Agones 自己的准入 webhook 规则(`minReplicas` 必须为 0 或 `>= bufferSize`),以确认客户端拒绝并显示清晰的消息,而不是原始的 webhook 错误。
- `update_fleet_resources` 和 `update_fleet_health`,每个都调用两次以确认部分更新(设置其中一个字段)会使第一个调用未更改的字段保持不变 - 与原始 `kubectl get fleet -o jsonpath` 进行对比,而不仅仅是工具自己的报告输出。
- 实时 Fleet 上的计数器/列表端到端:`create_fleet` 声明初始计数器和列表,`list_gameservers` 在两个就绪服务器上显示初始状态,`allocate_gameserver` 在分配时应用计数器增量和列表追加,然后第二个 `allocate_gameserver` 调用具有计数器选择器,正确跳过现在容量较低的服务器并选择另一个。
- 多集群路由(快乐路径和未知集群错误)针对使用 `AGONES_MCP_CLUSTERS` 启动的实时服务器,包括使用拼写的 `AGONES_MCP_CONTEXT` 时的大声失败。
- 完整的 Open Match 往返针对实时 Open Match 部署:`open_match_create_ticket` 创建真实票据,部署的匹配函数和导演匹配并分配它们,`open_match_ticket_status` 观察到的连接分配,以及 `open_match_cancel_ticket` 删除未匹配的票据(后续 `NotFound` 状态确认)。
- 每个读取和写入工具都在 `deploy/rbac.yaml` 下的 MCP 标准输入/输出中重新运行,绑定到一个全新的、其他方面为空的 ServiceAccount:完整的 Fleet 生命周期,包括 `gameserver_logs`,以及负路径(拒绝无效状态过滤器,拒绝空镜像,拒绝非 GameServer Pod 日志读取)。没有任何权限不足导致失败,并且矩阵检查确认每个动词不授予的权限都被拒绝。
## 安全模型
- 每个破坏性操作都是一个单独的、显式命名的工具,而且危险的操作都是关闭的。
- `delete_gameserver` 除非传递 `force=true`,否则拒绝删除已分配的(实时玩家)服务器,并报告强制断开的后果。其拒绝在检查和删除之间存活:`ResourceVersion` 先决条件捕获服务器在检查和删除之间变为已分配。
- `delete_fleet` 应用相同的实时匹配拒绝,但有一个诚实的警告:检查跨多个对象,因此没有单个先决条件可以完全关闭其竞争窗口。分配在删除的同一瞬间落地,仍可能被破坏。
- `scale_fleet` 依赖于 Agones 调度语义:缩减首先移除 `Ready` 服务器,永远不会破坏 `Allocated` 服务器。
- 工具输出是紧凑的摘要,而不是原始的 Kubernetes 对象,因此代理根据信号而不是 `managedFields` 噪声进行推理。
- `namespace` 在列出多个资源的工具上是可选的(省略以获取所有命名空间)。除此之外,它是必需的,因为每个其他工具都针对一个特定的命名资源。“所有命名空间”不是一个有意义的答案来回答“您指的是哪个 Fleet?”。
- `deploy/rbac.yaml` 授予的权限与工具使用的权限完全相同,没有更多权限。参见[权限](#权限)。
- 计数器/列表更改仅通过 `allocate_gameserver` 的 `counterActions`/`listActions` 进行,这是 Agones 自己的聚合分配 API 对外部公开的相同分配时间机制。故意没有“设置正在运行的 GameServer 上的计数器”工具:实时 GameServer 的 SDK 边车持有自己的内存状态副本,并定期同步到 `Status`,因此外部补丁外部分配会在那一刻发生冲突并被静默覆盖。
- `gameserver_logs` 和 `gameserver_events` 返回集群内部的原始文本(容器日志,事件消息),代理读取这些信息作为其上下文的一部分。受攻击者影响的内容可能会试图引导代理进行写入调用,而没有服务器可以可靠地告诉真正的日志输出与注入的指令有什么不同。这一个做的是:独立于请求的内容限制日志和事件输出,标记两个输出为不受信任的数据并返回它们,而不读取不是 GameServer 的日志的日志。真正的边界是架构上的:您的 MCP 主机应该在每个写入工具调用上都需要批准(Claude Code 默认执行此操作)。该批准门户,而不是此服务器,是阻止注入的内容引起写入的原因。
## 要求
- 具有 [Agones 安装](https://agones.dev/site/docs/installation/) 的 Kubernetes 集群(支持的 Kubernetes:1.33-1.35)
- 具有访问 Agones 资源的 kubeconfig
- Go 1.25+ 安装或构建
- [Open Match](https://open-match.dev/site/docs/installation/)(可选,仅适用于 `open_match_*` 工具)具有匹配函数和导演部署
没有集群? [kind](https://kind.sigs.k8s.io/) 加上 [Agones 安装指南](https://agones.dev/site/docs/installation/install-agones/helm/) 在几分钟内为您创建一个本地集群:
```sh
kind create cluster --name agones-dev
helm repo add agones https://agones.dev/chart/stable
helm install agones agones/agones --namespace agones-system --create-namespace
kubectl apply -f https://raw.githubusercontent.com/googleforgames/agones/release-1.57.0/examples/simple-game-server/fleet.yaml```
## 安装
```sh
go install github.com/nicklesimba/agones-conductor-mcp@latest
```
二进制文件位于 `$(go env GOPATH)/bin`(将其添加到您的 PATH 中,如果它已经不在那里)。或从源代码构建:
```sh
git clone https://github.com/nicklesimba/agones-conductor-mcp
cd agones-conductor-mcp
go build -o agones-conductor-mcp .
```
在 Windows 上,使用 `-o agones-conductor-mcp.exe` 进行构建,并使用 JSON 配置中的反斜杠转义路径(例如 `"C:\\tools\\agones-conductor-mcp.exe"`)。
## 配置
服务器使用您的 [kubeconfig](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/)(`kubectl` 已经使用的文件与您的集群交互,通常是 `~/.kube/config`),或在集群内自动部署时的集群内凭证。kubeconfig 可以定义多个 **contexts**(命名集群+用户+命名空间组合);如果您的 kubeconfig 有多个,而 `kubectl config current-context` 不是正确的,请设置 `AGONES_MCP_CONTEXT` 为要使用的上下文名称。
Claude Code:
```sh
claude mcp add agones -- /path/to/agones-conductor-mcp
```
Claude Desktop / Cursor(`mcpServers` 配置):
```json
{
"mcpServers": {
"agones": {
"command": "/path/to/agones-conductor-mcp",
"env": { "AGONES_MCP_CONTEXT": "my-cluster" }
}
}
}
```
无头运行(`claude -p`,CI,脚本):客户端对每个工具的调用进行权限确认,并在首次使用时提示,而非交互式会话没有 TTY 来回答提示,因此直接挂起。传递 `--allowedTools` 并指定您需要的特定 `mcp__agones__*` 工具名称。
### 多集群
默认情况下,服务器针对单个集群(集群内配置,或由 `AGONES_MCP_CONTEXT` 命名),工具调用永远需要 `cluster` 参数。要管理多个集群,请设置 `AGONES_MCP_CLUSTERS` 为逗号分隔的 kubeconfig 上下文名称列表:
```json
{
"mcpServers": {
"agones": {
"command": "/path/to/agones-conductor-mcp",
"env": { "AGONES_MCP_CLUSTERS": "us-west,us-east,eu-central" }
}
}
}
```
第一个列出的名称是默认的(覆盖 `AGONES_MCP_CONTEXT)。每个工具现在接受一个可选的 `cluster` 参数指定这些上下文中的一个;省略它会目标默认,因此单个集群提示保持不变。 使用 `list_clusters` 查看已配置的内容。
### Open Match
跳过本节,除非您已经运行 [Open Match](https://open-match.dev)。它是一个单独的匹配系统,而不是 Agones 需要的东西。`open_match_*` 工具默认情况下处于关闭状态;如果没有配置,它们只会返回一个明确的“未配置”错误。
如果您确实运行了它,这些工具会通过 gRPC **不使用 TLS** 连接到其前端服务。连接是纯文本的,与 Open Match 自己的默认集群内部署相同,因此请将前端服务保持在不受信任的网络中:使用集群内 DNS 或 `kubectl port-forward` 而不是公开暴露它。`AGONES_MCP_OPEN_MATCH_FRONTEND` 需要一个服务器可以实际访问的主机端口。具体来说,以下任意一种:
- **集群内 DNS 名称**(例如 `open-match-frontend.open-match.svc.cluster.local:50504`)- 如果 `agones-conductor-mcp` 本身作为 Pod 运行在同一个集群中,则有效。
- **节点端口或负载均衡器** - 一种 Kubernetes 服务类型,它将集群内部的内容公开给外部;使用此方法如果 `agones-conductor-mcp` 在集群外部运行。
- **您自己启动的 `kubectl port-forward`** - 最快的本地测试选项;将本地端口转发到前端服务 - 这是您自己启动的最快选项。
设置为以下任意一项:
```json
{
"mcpServers": {
"agones": {
"command": "/path/to/agones-conductor-mcp",
"env": { "AGONES_MCP_OPEN_MATCH_FRONTEND": "open-match-frontend.open-match.svc.cluster.local:50504" }
}
}
}
```
在多集群模式下,使用 `AGONES_MCP_OPEN_MATCH_FRONTENDS` 代替:一个逗号分隔的 `clusterName=host:port` 列表,与 `AGONES_MCP_CLUSTERS` 中的名称匹配。没有条目的集群只需禁用 Open Match 工具。
该服务器本身不执行任何匹配。Open Match 的自身架构需要另外两个部分才能实际将票据转换为匹配:一个 **匹配函数**(您的匹配逻辑 - 哪些玩家属于一起) 和一个 **导演**(轮询 Open Match 以获取提议的匹配并完成它们) 。这些是您编写和部署的单独内容,请遵循 [Open Match 自己的文档](https://open-match.dev/site/docs/) 。`agones-conductor-mcp` 仅针对您已经运行的管道创建、检查和取消票据 - `allocate_gameserver` 与 Agones 自己的分配器具有相同的关系,即调用它而不是自己决定服务器位置。
### 权限
不要以具有广泛的集群管理员权限运行此服务器。 [RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) (基于角色的访问控制)是 Kubernetes 限定身份可以执行的操作的一种方式,而 `deploy/rbac.yaml` 定义了实际需要的最小集合(请参见文件本身的注释以获取确切的列表)。 `ClusterRole` 本身不授予任何内容:它是一个命名的权限包,仅在通过 `ClusterRoleBinding` 绑定到身份时生效。如果此服务器在集群内作为 Pod 运行,请将其绑定到 Pod 的 [ServiceAccount](https://kubernetes.io/docs/concepts/security/service-accounts/) ;如果它通过 kubeconfig 在外部运行,请对该 kubeconfig 验证的身份授予等效授予。
具体来说,对于 `default` 命名空间中的 `agones-conductor-mcp` 服务帐户:
```sh
kubectl apply -f deploy/rbac.yaml
kubectl create serviceaccount agones-conductor-mcp -n default
kubectl create clusterrolebinding agones-conductor-mcp --clusterrole=agones-conductor-mcp --serviceaccount=default:agones-conductor-mcp
```
每个工具都已在没有其他访问权限的新 ServiceAccount 下针对真实集群运行。除了这里授予的内容外,没有任何内容需要更多权限,一份权限矩阵确认多余的动词(pod 读取,秘密访问,游戏服务器写入等)被拒绝。
## 开发
`scripts/simulate-churn.sh [fleet]` 在一个定时器上分配和拆除 GameServers,模拟比赛的开始和结束,以便在交互式测试工具时观察实时状态。默认为上下文 `kind-agones-dev`,命名空间 `default`,fleet `simple-fleet`;使用 `AGONES_CONTEXT`/`AGONES_NAMESPACE` 环境变量或 fleet 名称参数覆盖。
## 贡献
欢迎提出问题和 PR。本项目旨在为任何运行 Agones 的人提供实用工具,无论规模或游戏类型如何。如果这里的某个工具的假设与您的设置不符,那就是一个值得报告的错误。
## 许可证
Apache-2.0。参见 [LICENSE](LICENSE)。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器