安装
内容详情
安装
{
"mcpServers": {
"amp": {
"command": "node",
"args": ["/absolute/path/to/amp-mcp-server/dist/index.js"],
"env": {
"AMP_URL": "https://amp.example.local",
"AMP_USERNAME": "admin",
"AMP_PASSWORD": "..."
}
}
}
}
{
"mcpServers": {
"amp": { "url": "http://localhost:3000/mcp" }
}
}🎮 amp-mcp-server
一个封装 CubeCoders AMP 的 MCP 服务器,让 MCP 客户端(Claude Desktop、Claude Code 等)能够列出、查看并控制由 AMP 管理的游戏服务器实例。
本项目是 AMP 公共 REST API 的客户端 —— 不重新分发任何 AMP 源码或二进制文件。请自行准备已授权的 AMP 安装。
🛠️ 对外暴露的工具
只读工具(始终启用):
amp_list_instances— 枚举所有由 AMP 管理的实例amp_get_instance_status— 获取单个实例的状态、运行时长、CPU/RAM/玩家数amp_get_active_users— 获取单个实例的已连接用户amp_get_console_output— 获取单个实例的最近控制台输出amp_get_host_status— 获取 AMP 控制主机本身的状态、运行时长、CPU/RAMamp_get_running_tasks— 获取单个实例当前正在运行的任务(含进度百分比)amp_get_update_info— 获取单个实例待处理的游戏服务器更新amp_list_backups— 列出单个实例的本地备份
写入工具(由 AMP_ALLOW_WRITES=true 控制):
amp_start_instance/amp_stop_instance/amp_restart_instance— 实例生命周期管理amp_sleep_instance— 软关闭(恢复速度比 Stop 更快;依赖具体模块)amp_send_console_command— 向某个实例的控制台发送命令amp_take_backup— 触发备份(可通过amp_get_running_tasks轮询完成状态)amp_update_application— 应用待处理的游戏服务器更新(长时间运行)amp_end_user_session— 断开某个用户会话(跨模块通用踢出)
⚠️ 重要提示
写入工具默认关闭,以防止意外的破坏性调用。
⚙️ 环境变量
| 变量 | 必填 | 默认值 | 用途 |
|---|---|---|---|
AMP_URL |
是 | — | AMP 安装的基础 URL,例如 https://amp.example.local |
AMP_USERNAME |
是 | — | AMP 管理员用户名 |
AMP_PASSWORD |
是 | — | AMP 密码(或记住的 token) |
AMP_ALLOW_WRITES |
否 | false |
设为 true 以启用可变更(写入)工具 |
MCP_TRANSPORT |
否 | stdio |
stdio(作为子进程使用)或 http(Docker / 远程) |
MCP_PORT |
否 | 3000 |
HTTP 监听端口(仅 HTTP 传输) |
MCP_HOST |
否 | 127.0.0.1 |
HTTP 绑定主机(仅 HTTP 传输)。Docker 镜像会覆盖为 0.0.0.0。 |
MCP_ALLOWED_HOSTS |
否 | — | 逗号分隔的 Host 头允许列表(防止 DNS 重绑定)。当 MCP_HOST 为 0.0.0.0/:: 且 MCP_AUTH_MODE=none 时必填。 |
MCP_ALLOWED_ORIGINS |
否 | — | 逗号分隔的 Origin 允许列表。Origin 不匹配的请求返回 403;无 Origin 的请求(服务端到服务端)则允许通过。 |
MCP_TRUST_PROXY |
否 | — | 转发给 Express 的 trust proxy 设置。部署在 nginx/Caddy 之后时设置,使 req.ip 为真实客户端 IP。 |
MCP_ALLOW_INSECURE |
否 | false |
覆盖启动守卫:该守卫会拒绝 0.0.0.0 + none 认证 + 无主机允许列表的组合。 |
MCP_RATE_LIMIT |
否 | 120 |
/mcp 每个窗口内允许的最大请求数。设为 0 可禁用。 |
MCP_RATE_WINDOW_MS |
否 | 60000 |
限流窗口长度(毫秒)。 |
MCP_AUTH_MODE |
否 | none |
none / bearer / oauth —— 见身份验证 |
MCP_PUBLIC_URL |
当 oauth 时 |
— | 本服务器的规范外部 URL(资源 id + JWT audience) |
MCP_AUTH_TOKEN |
当 bearer 时 |
— | 逗号分隔的可用 bearer token 列表 |
MCP_OAUTH_ISSUER |
当 oauth 时 |
— | OAuth 2.1 授权服务器的 issuer URL |
MCP_OAUTH_AUDIENCE |
否 | MCP_PUBLIC_URL |
覆盖期望的 JWT aud 声明 |
MCP_OAUTH_JWKS_URL |
否 | 通过 OIDC 发现 | 覆盖 JWKS URL(跳过 OIDC 发现) |
MCP_OAUTH_REQUIRED_SCOPES |
否 | — | 每个请求都必须具备的、逗号分隔的 scope 列表 |
LOG_LEVEL |
否 | info |
pino 日志级别:trace / debug / info / warn / error / fatal。所有日志输出到 stderr。 |
💡 使用建议
将
.env.example复制为.env并填入真实值。切勿提交.env。
🚀 快速开始 — Docker(HTTP)
cp .env.example .env
# edit .env with your AMP credentials
docker compose up -d --build
docker compose logs -f
服务器监听 http://127.0.0.1:3000/mcp(无状态 Streamable HTTP 传输)。compose 文件仅将端口发布到宿主机 loopback;如需对外暴露,请在 .env 中设置 MCP_BIND=0.0.0.0 并启用认证(MCP_AUTH_MODE=bearer/oauth),或设置 MCP_ALLOWED_HOSTS —— 除非设置 MCP_ALLOW_INSECURE=true,否则服务器会拒绝在 0.0.0.0 + 无认证 + 无允许列表模式下启动。
冒烟测试:
curl -X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
HTTP 传输还暴露 GET /health(返回 {"status":"ok"})供 Docker/k8s 存活探针使用 —— 该端点绕过认证、限流与 origin 检查。Dockerfile 内置了命中此端点的 HEALTHCHECK。
💻 快速开始 — 本地 Node(stdio 或 HTTP)
需要 Node 20+。
npm install
npm run build
# stdio (for an MCP client to spawn as a subprocess)
AMP_URL=... AMP_USERNAME=... AMP_PASSWORD=... npm start
# HTTP (local)
MCP_TRANSPORT=http AMP_URL=... AMP_USERNAME=... AMP_PASSWORD=... npm start
交互式查看工具:
npx @modelcontextprotocol/inspector node dist/index.js
🔐 身份验证
HTTP 传输支持三种认证模式,由 MCP_AUTH_MODE 选择。stdio 传输会忽略所有这些设置 —— 它的信任边界是操作系统进程,MCP 客户端通过其配置中的 env 块传递凭据。
| 模式 | 适用场景 | 行为说明 |
|---|---|---|
none(默认) |
stdio,或仅绑定到 127.0.0.1 / 私有网络(Tailscale、WireGuard、LAN)的 HTTP |
完全不认证。仅靠网络层信任阻止调用方。 |
bearer |
将 HTTP 暴露给一个或两个你控制的客户端(例如个人云 VM) | 静态 Authorization: Bearer <token> 校验。常量时间比较。 |
oauth |
公开/多用户部署,或任何期望符合规范的 MCP 认证的客户端(例如 Claude.ai 连接远程 MCP 服务器) | OAuth 2.1 资源服务器。校验由你的授权服务器签发的 JWT。发布 RFC 9728 受保护资源元数据。 |
这些模式互斥 —— 只能选其一。它们都不能替代 AMP_ALLOW_WRITES;该标志仍单独控制写入工具是否被注册。
Bearer 模式
MCP_AUTH_MODE=bearer
MCP_AUTH_TOKEN=$(openssl rand -hex 32)
客户端以 Authorization: Bearer <token> 调用 /mcp。多个 token 可通过逗号分隔列表同时接受(每个客户端一个,便于通过删除条目并重启来吊销)。缺失/无效 token 返回 401 并附 WWW-Authenticate: Bearer realm="mcp"。
curl -X POST http://localhost:3000/mcp \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
OAuth 2.1 模式
本服务器充当 OAuth 2.1 资源服务器 —— 它校验访问令牌,但不签发令牌。你需要自备授权服务器(Keycloak、Auth0、Authentik、Duende、Okta 等)。
各角色如何协作
OAuth 涉及三个角色,amp-mcp-server 只是其中之一:
- 资源服务器 —— 就是
amp-mcp-server本身。 校验传入的 JWT,提供工具。没有回调 URL,也从不参与重定向流程。 位于MCP_PUBLIC_URL。 - 授权服务器(AS) —— 你自己运行的另一个服务(Keycloak、Duende、Auth0、Authentik……)。在用户登录后签发令牌。位于
MCP_OAUTH_ISSUER。 - MCP 客户端 —— Claude.ai、Claude Desktop、自定义 CLI 工具等。 针对 AS 驱动用户登录流程,收到令牌后将其发送给资源服务器。每个客户端拥有自己的重定向/回调 URL。
当用户把你的 MCP 服务器添加到 Claude.ai 这类客户端时的流程:
user
│
▼
MCP client ── (1) fetch PRM ─────► amp-mcp-server (resource server)
│ (says "use AS_X")
│
│ (2) Auth Code + PKCE ──────► AS (Keycloak / Duende / etc.)
│ user logs in + consents
│ AS redirects to the *client's* callback
│
└── (3) bearer JWT ─────────► amp-mcp-server
因此你在 AS 上配置的重定向 URI 不是 https://your-mcp-server/callback —— 而是客户端所需的 URL。对 Claude.ai 而言是 claude.ai 上的某个地址;对桌面或 CLI 工具则通常是 loopback URL,例如 http://127.0.0.1:8765/callback(RFC 8252)。
这意味着一个部署决策:
- 少量已知客户端 → 在 AS 管理界面中逐个预注册(每个消费者一个客户端条目,使用该消费者的回调 URL)。如果只是你添加一两个 MCP 客户端,这样做即可。
- 大量或未知客户端 → 在 AS 上启用动态客户端注册(Dynamic Client Registration,RFC 7591),让客户端在运行时自行注册。MCP 授权规范建议公开部署启用 DCR。Keycloak、Duende、Auth0 和 Authentik 都支持作为可选功能。
amp-mcp-server 本身不关心你选哪条路径 —— 它只看到最终得到的 bearer JWT。
必需的环境变量
MCP_AUTH_MODE=oauth
MCP_PUBLIC_URL=https://amp-mcp.example.com # exact URL clients hit; used as JWT audience
MCP_OAUTH_ISSUER=https://auth.example.com/realms/amp
# Optional:
MCP_OAUTH_REQUIRED_SCOPES=mcp:read,mcp:write
MCP_OAUTH_ISSUER 的确切形态取决于你使用的授权服务器 —— 它必须与 AS 在令牌中签发的 iss 声明匹配:
| 授权服务器 | 典型 issuer URL |
|---|---|
| Keycloak | https://auth.example.com/realms/<realm>(realm 是 Keycloak 租户 —— 拥有自己的用户/客户端/角色) |
| Duende IdentityServer | https://auth.example.com(裸域名,无路径) |
| Auth0 | https://<tenant>.auth0.com/ |
| Authentik | https://authentik.example.com/application/o/<slug>/ |
| Okta | https://<org>.okta.com/oauth2/<server-id> |
有疑问时,抓取 <issuer>/.well-known/openid-configuration 并检查其中的 issuer 字段 —— 那才是此处应使用的规范值。
服务器在以下地址发布受保护资源元数据(Protected Resource Metadata)文档:
GET /.well-known/oauth-protected-resource
以便符合规范的 MCP 客户端能自动发现授权服务器。对没有有效令牌的 /mcp 调用,服务器返回 401 并附:
WWW-Authenticate: Bearer realm="mcp", resource_metadata="https://amp-mcp.example.com/.well-known/oauth-protected-resource"
JWT 校验要求:
- 签名有效(JWKS 从 AS 获取)
iss与MCP_OAUTH_ISSUER匹配aud包含MCP_OAUTH_AUDIENCE(默认:MCP_PUBLIC_URL)exp处于未来- 所有
MCP_OAUTH_REQUIRED_SCOPES(若设置)出现在scope或scp声明中
⚠️ 重要提示
MCP_PUBLIC_URL必须与客户端调用的地址完全一致。Audience 不匹配是最常见的配置错误 —— 如果客户端看似认证成功却收到 401,请检查 AS 是否为该 URL 签发了令牌。
Keycloak 快速开始
docker run -d --name kc -p 8080:8080 \
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:latest start-dev
在 Keycloak 管理界面中:
- 创建一个 realm(例如
amp)。 - 创建一个客户端
amp-mcp-test,客户端类型OpenID Connect,public,启用 PKCE;开启 standard flow。 - 创建一个用户并设置密码。
- 添加一个 client scope
mcp:read,映射为默认 scope。 - 将客户端的 "Valid post logout redirect URIs" / "Valid redirect URIs" 设置为你的 MCP 客户端所期望的地址(例如 Claude.ai 的回调)。
以如下配置运行 amp-mcp-server:
MCP_TRANSPORT=http \
MCP_AUTH_MODE=oauth \
MCP_PUBLIC_URL=http://localhost:3000 \
MCP_OAUTH_ISSUER=http://localhost:8080/realms/amp \
MCP_OAUTH_AUDIENCE=http://localhost:3000 \
AMP_URL=... AMP_USERNAME=... AMP_PASSWORD=... \
npm start
验证 PRM 端点:
curl http://localhost:3000/.well-known/oauth-protected-resource
验证 401 挑战:
curl -i -X POST http://localhost:3000/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# expect: 401 + WWW-Authenticate: Bearer realm="mcp", resource_metadata="..."
如需使用真实的 Auth Code + PKCE 浏览器登录流程(Claude.ai 及其他合规 MCP 客户端使用的同一流程)进行端到端测试,本仓库在 scripts/oauth-token.mjs 提供了一个一次性辅助脚本:
# Configure a public client at your AS with redirect_uri http://127.0.0.1:8765/callback,
# PKCE required, and the scope(s) you want. Then:
TOKEN=$(node scripts/oauth-token.mjs \
--issuer http://localhost:8080/realms/amp \
--client-id amp-mcp-test \
--scope "openid mcp:read")
# Open the printed URL in your browser, log in, and the script captures the
# token and prints it to stdout.
curl -X POST http://localhost:3000/mcp \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
如需对 Machine-to-Machine 客户端进行更快的非交互式检查,也可以直接使用 client_credentials 授权:
TOKEN=$(curl -s -X POST http://localhost:8080/realms/amp/protocol/openid-connect/token \
-d 'grant_type=client_credentials' \
-d 'client_id=<m2m-client-id>' \
-d 'client_secret=<secret>' \
-d 'scope=mcp:read' | jq -r .access_token)
🔌 接入 Claude Desktop
stdio(本地 Node):
{
"mcpServers": {
"amp": {
"command": "node",
"args": ["/absolute/path/to/amp-mcp-server/dist/index.js"],
"env": {
"AMP_URL": "https://amp.example.local",
"AMP_USERNAME": "admin",
"AMP_PASSWORD": "..."
}
}
}
}
HTTP(Docker / 远程):
{
"mcpServers": {
"amp": { "url": "http://localhost:3000/mcp" }
}
}
📦 安装为 CubeCoders AMP 实例
amp-mcp-server 的 CubeCoders AMP 自定义应用模板存放在一个独立仓库中:eddinsw/amp-templates。该仓库提供两个变体 —— 宿主进程版(适用于任意 AMP 版本)和 Docker 版(AMP Enterprise + Docker 实例)。
快速安装:在 AMP Web 界面进入 Configuration → Instance Deployment → Configuration Repositories,添加 eddinsw/amp-templates:main,点击 Fetch Latest。之后 amp-mcp-server 与 amp-mcp-server (Docker) 都会出现在 New Instance 向导中。
Docker 变体拉取 ghcr.io/eddinsw/amp-mcp-server:latest,该镜像由本仓库通过 .github/workflows/publish-image.yml 在每次打 tag 和推送到 main 时发布。
完整操作指南、变体对比、配置参考与故障排查:见 amp-templates README。
🛡️ 生产环境部署
如需在本机之外暴露服务:
-
使用带 TLS 的反向代理。 不要把纯 HTTP 直接放到公网。Caddy 是最简单的路径:
amp-mcp.example.com { reverse_proxy 127.0.0.1:3000 }Caddy 会自动申请 Let's Encrypt 证书。nginx 和 Traefik 同理。
-
设置
MCP_TRUST_PROXY。 若不设置,限流器会把每个请求都视为来自代理,从而在阈值处把合法客户端锁死:MCP_TRUST_PROXY=loopback # proxy on same host # or MCP_TRUST_PROXY=10.0.0.5/32 # CIDR for a specific upstream -
选择一种认证模式。 一两个已知客户端用
bearer;多用户场景或任何期望符合规范的 MCP 认证的客户端(例如 Claude.ai 连接远程 MCP 服务器)用oauth。 -
MCP_PUBLIC_URL必须与客户端实际调用的地址完全一致(即代理的外部 URL 带 scheme,而非内部 Docker URL)。Audience 不匹配是 OAuth 最常见的配置错误。
Docker 镜像默认的 MCP_HOST=0.0.0.0 不会启动,除非 MCP_AUTH_MODE 为 bearer/oauth、设置了 MCP_ALLOWED_HOSTS,或显式使用 MCP_ALLOW_INSECURE=true 覆盖。这是有意为之 —— 可防止意外产生"公网可访问但无认证"的部署。
🔧 故障排查
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
服务器立即退出并提示 refusing to start: MCP_HOST binds to all interfaces... |
不安全绑定的安全守卫 | 设置 MCP_AUTH_MODE=bearer/oauth、设置 MCP_ALLOWED_HOSTS,或用 MCP_ALLOW_INSECURE=true 覆盖 |
OAuth:令牌看起来有效却返回 401 |
JWT aud 与 MCP_OAUTH_AUDIENCE(未设置 audience 覆盖时为 MCP_PUBLIC_URL)不匹配 |
解码 JWT,检查 aud 数组是否精确包含所配置的 audience |
OAuth:登录成功后出现 401 invalid_token |
令牌 issuer 与 MCP_OAUTH_ISSUER 不一致,或 AS 轮换了签名密钥而 JWKS 缓存陈旧 |
确认 MCP_OAUTH_ISSUER 与令牌的 iss 匹配;重启服务器以刷新 JWKS 缓存 |
一个客户端异常后所有客户端都收到 429 |
未设置 MCP_TRUST_PROXY,导致所有流量被视为同一 IP |
将 MCP_TRUST_PROXY 设为代理 CIDR 或 loopback |
Duende:客户端明明显示了该 scope 却报 invalid_scope |
该 scope 在客户端的允许 scope 列表中,但未在 IdentityServer 中定义为 ApiScope |
在 "API Scopes" + "API Resources" 下添加,并重启 Duende 以刷新配置缓存 |
| Duende:同意页之后重定向又跳回登录 | 同意后重定向的 Cookie/SameSite 问题 | 作为临时方案禁用客户端的 RequireConsent,或修复 Duende 的 cookie 配置 |
npm test 报 "no tests" 但无错误 |
连续执行 build + test 时 vitest 缓存抖动 |
重新运行 npm test |
🏗️ 架构
MCP client (Claude Desktop / Code)
│ stdio ── or ── HTTP (stateless Streamable)
▼
amp-mcp-server ── REST/JSON ──▶ AMP install
│
└─▶ @neuralnexus/ampapi (typed AMP client; no transitive deps)
HTTP 传输以无状态模式运行:每个请求都会获得一个新的 StreamableHTTPServerTransport 和 McpServer,因此写入工具的门控会反映当前的 AMP_ALLOW_WRITES 值。AmpClient 上的认证状态(AMP 会话)则作为单例在请求之间共享。
📄 许可证
MIT —— 见 LICENSE。
内置的 AMP 客户端 @neuralnexus/ampapi 采用 GPL-3.0 / MIT 双许可,此处以 MIT 方式使用。
替代品








VIP会员