基于MCP协议与游戏MOD的AI智能体框架:以《杀戮尖塔2》为例
2026/4/26 11:15:00 网站建设 项目流程

1. 项目概述:当AI智能体成为你的爬塔队友

如果你是一位《杀戮尖塔2》(Slay the Spire 2, 以下简称STS2)的硬核玩家,同时又对AI技术充满好奇,那么你很可能已经厌倦了在“重开”与“学习”之间反复横跳。每一局爬塔都是一次复杂的决策树遍历,从卡牌选择、遗物搭配到战斗中的能量分配、目标优先级,每一个环节都充满了变数。现在,想象一下,你有一个永不疲倦、能瞬间分析所有可能性的“超级大脑”作为你的队友,它会是什么样子?

CharTyr/STS2-Agent项目,正是这样一个将幻想变为现实的桥梁。它不是一个外挂,也不是一个简单的脚本,而是一个结构精巧的“AI智能体集成框架”。其核心由两部分构成:一个注入到STS2游戏进程中的MOD(STS2AIAgent),以及一个遵循MCP(Model Context Protocol)标准的服务器(mcp_server)。MOD负责“感知”游戏世界,实时抓取每一帧的游戏状态——包括你的手牌、敌人的意图、场上的增益减益、地图节点信息等,并通过一个本地的HTTP API(默认在127.0.0.1:8080)暴露出来。而MCP服务器则扮演“翻译官”和“调度员”的角色,它将这个原始的HTTP API包装成一套标准化、结构化的工具(Tools),使得任何支持MCP协议的AI客户端(例如Claude Desktop、Cursor AI、甚至是你可以编程调用的自定义客户端)都能像调用本地函数一样,读取游戏状态,并下达“出这张牌”、“移动到下一个节点”、“购买这个遗物”等指令。

简单来说,这个项目为STS2这个单机游戏打开了一扇“自动化”与“AI辅助决策”的大门。它适合以下几类人:一是希望用AI来测试自己游戏策略极限的硬核玩家;二是对游戏AI、强化学习感兴趣,想以STS2为沙盒环境进行算法研究的开发者;三是想要打造个性化游戏助手,实现半自动爬塔或数据收集的技术爱好者。通过这个项目,你不再仅仅是游戏的参与者,更成为了游戏规则的观察者与交互架构的设计者。

2. 核心架构与设计思路拆解

2.1 为什么是“MOD + MCP Server”的双层架构?

这个设计是项目成功的关键,它清晰地分离了关注点,并充分利用了现有生态。

2.1.1 MOD层:游戏内部的“传感器”与“执行器”

MOD(STS2AIAgent.dll)是直接与游戏引擎(Unity)交互的部分。它的首要任务是“无侵入”或“低侵入”地获取游戏内存中的数据。对于像STS2这样逻辑复杂的游戏,直接通过内存地址读取状态是极其脆弱且容易随游戏更新而失效的。因此,一个更稳健的做法是利用游戏原有的Mod支持框架(如果存在),或者通过Harmony等库对游戏方法进行“织入”(Hook),在游戏逻辑执行的关键节点(如回合开始、卡牌打出后、伤害计算时)截获数据。

这个MOD的核心功能是:

  • 状态暴露:将游戏内部复杂的、面向渲染和逻辑的对象模型,序列化为结构化的JSON数据。这不仅仅是简单的数据转储,它需要做大量的“语义化”工作。例如,将“敌人意图”从内部的枚举值翻译成“攻击”、“防御”、“施加虚弱”等可读描述,并计算出预期的伤害数值。
  • 动作抽象:将玩家的操作(点击、拖拽)抽象为一套原子性的API指令。比如,/play_card接口需要接收卡牌ID、目标ID等参数,MOD在内部将其转换为模拟一次鼠标点击和拖放事件,或者直接调用游戏内部的出牌函数。
  • HTTP服务:提供一个轻量级的Web服务器。选择HTTP协议而非更底层的TCP或IPC,极大地降低了外部程序连接的复杂性。任何能发送HTTP请求的工具(如curl、Postman、Python的requests库)都能立即与游戏交互,便于调试和快速验证。

2.1.2 MCP Server层:生态系统的“适配器”

如果只有HTTP API,那么每次想要让AI(比如Claude)来玩游戏,你都需要写一大堆胶水代码来告诉AI每个API的用法、参数格式、返回结构。这非常低效且容易出错。

MCP(Model Context Protocol)是由Anthropic提出的一种开放协议,旨在标准化AI模型与外部工具、数据源之间的交互方式。你可以把它想象成AI世界的“USB标准”。一个MCP Server对外提供一组定义清晰的Tools(工具)和Resources(资源)。

sts2-mcp-server的作用就是:

  • 工具封装:将/game_state/legal_actions/play_card等HTTP端点,包装成MCP标准的Tool。每个Tool都有严格的输入输出JSON Schema描述。AI客户端在连接时,会一次性获取所有可用的Tool定义,之后就可以像调用函数一样使用它们,完全无需关心底层的网络通信。
  • 协议转换:处理MCP的stdio或HTTP传输层。stdio模式允许AI客户端(如Claude Desktop)以子进程方式启动MCP Server,通过标准输入输出进行通信,集成度最高。HTTP模式则提供了网络灵活性,允许远程连接或多客户端连接。
  • 提供上下文:除了动态的游戏状态,MCP Server还可以将静态的游戏元数据(如所有卡牌的完整描述、所有遗物的效果、所有敌人的行为模式)作为Resources提供给AI。这相当于给了AI一本完整的游戏百科全书,使其决策基础更加牢固。

这种双层架构的优势在于:MOD层保持轻量和专注,只负责与游戏对话;MCP Server层负责与AI生态对话。任何支持MCP的新AI客户端出现,都能立即与这个项目兼容,无需修改MOD代码。这种设计极大地提升了项目的可扩展性和生命周期。

2.2 关键特性:事件驱动与状态轮询的权衡

在实时交互系统中,一个核心问题是:AI如何知道游戏状态发生了变化?项目文档提到了“reducing polling through SSE events”,这指向了两种典型的模式。

  • 轮询(Polling):AI客户端每隔一个固定时间(比如100毫秒)就主动调用一次get_game_state工具来获取最新状态。这种方式实现简单,但会产生大量无效请求(尤其在游戏动画播放、玩家思考等状态未变化的时段),浪费资源且可能给游戏带来不必要的性能压力。
  • 事件驱动(Event-Driven):游戏状态一旦发生重要变化(如回合结束、新敌人出现、获得新卡牌),MOD主动通过Server-Sent Events (SSE) 向MCP Server推送一个事件。AI客户端可以订阅这个事件流,仅在状态真正更新时才被唤醒进行处理。这种方式更高效、更实时。

从项目描述看,它很可能采用了混合模式:MCP Server通过SSE从MOD获取事件通知,从而知道何时该去主动拉取(poll)新的完整状态。这是一种最佳实践,既保证了响应的实时性,又避免了高频轮询的 overhead。对于AI Agent的设计者而言,理解这一点至关重要:你的Agent不应该在一个死循环里疯狂轮询,而应该设计成事件监听模式,在收到“turn_start”事件后才开始规划本回合操作,在收到“card_played”事件后更新内部状态模型。

3. 从零开始:环境部署与核心配置详解

3.1 MOD安装:不仅仅是复制粘贴

虽然快速指南列出了步骤,但其中隐藏着许多新手容易踩坑的细节。

3.1.1 定位准确的游戏目录

对于Steam版游戏,默认路径通常是正确的。但如果你使用了Steam库文件夹转移、或者通过其他平台(如GOG)购买,游戏路径可能不同。一个万无一失的方法是:

  1. 在Steam库中右键点击《Slay the Spire 2》。
  2. 选择“管理” -> “浏览本地文件”。这将直接打开正确的游戏根目录。

3.1.2 理解mods/目录的机制

STS2很可能使用了与一代类似的Mod加载机制。mod_id.json文件是这个MOD的“身份证”,游戏启动时会扫描mods/文件夹下的所有此类文件,然后加载对应的.dll(Windows)或.so(Linux)文件。关键点在于:你必须确保三个文件直接位于mods/下,而不是在一个子文件夹里。错误的放置方式(如mods/STS2AIAgent/STS2AIAgent.dll)会导致Mod加载失败。

3.1.3 验证MOD加载成功

启动游戏后,访问http://127.0.0.1:8080/health。如果返回一个包含"status": "ok"的JSON,恭喜你,MOD运行正常。如果无法连接,请按顺序排查:

  1. 游戏是否真正启动?请确认游戏窗口已经出现,并过了初始加载画面。有时启动器进程和游戏进程是分开的。
  2. 防火墙拦截?Windows Defender或第三方防火墙可能会阻止本地回环地址(127.0.0.1)的特定端口。首次运行时,请留意是否有防火墙弹窗询问是否允许SlayTheSpire2.exe访问网络。
  3. 端口冲突?8080端口可能被其他程序占用。你可以查看MOD的配置文件(如果有的话)或源代码,看是否可以修改默认端口。通常这类信息会在config.json或环境变量中设置。

3.2 Python环境与uv工具链的搭建

项目推荐使用uv,这是一个用Rust写的、速度极快的Python包管理器和运行器。它解决了传统pipvenv的诸多痛点,如依赖解析慢、环境隔离繁琐等。

3.2.1 安装Python 3.11+

确保你的Python版本符合要求。在命令行输入python --versionpython3 --version查看。如果版本过低,建议从Python官网下载安装。重要提示:在Windows上安装时,务必勾选“Add Python to PATH”,否则后续命令可能找不到Python。

3.2.2 安装并配置uv

按照文档的命令安装即可。安装完成后,一个很好的实践是配置uv的镜像源以加速国内下载。你可以设置环境变量:

# Linux/macOS export UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple export UV_PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple # Windows (PowerShell) $env:UV_INDEX_URL="https://pypi.tuna.tsinghua.edu.cn/simple" $env:UV_PIP_INDEX_URL="https://pypi.tuna.tsinghua.edu.cn/simple"

或者在项目目录下创建一个.env文件,写入上述内容。这能显著提升依赖安装速度。

3.2.3 启动MCP Server的两种模式

项目提供了两种启动脚本,对应MCP的两种传输方式:

  • start-mcp-stdio.sh/ps1:启动stdio模式。这是与桌面AI客户端(如Claude Desktop)集成的推荐方式。该脚本会使用uv run启动MCP Server,并将其输入输出连接到标准流。当你在Claude Desktop的设置中添加此MCP Server时,实际上就是配置它执行这个启动脚本。
  • start-mcp-network.sh/ps1:启动HTTP模式。这会启动一个监听在http://127.0.0.1:8765的服务器。任何能发送HTTP请求的客户端(包括你自己写的脚本、Postman、或者支持HTTP MCP的AI客户端)都可以连接。这种方式更适合调试、多客户端连接或远程连接场景。

实操心得:初次接触时,建议先使用HTTP模式进行测试。你可以用简单的cURL命令来验证服务器是否工作:

curl -X POST http://127.0.0.1:8765/mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {} }'

如果返回一个包含所有工具定义的JSON列表,说明MCP Server运行成功且协议通信正常。

4. 核心功能实操:打造你的第一个STS2 AI Agent

4.1 理解MCP工具集:AI的“游戏手柄”

连接上MCP Server后,AI客户端会获得一套工具。根据项目文档,这套工具至少涵盖以下核心领域:

  1. 状态读取工具:如get_game_state。这是最重要的工具,返回一个庞大的JSON对象,包含run(当前运行信息,如生命、金币、药水、地图路径)、combat(战斗状态,如玩家能量、手牌、抽牌堆、弃牌堆、耗牌堆、敌人列表及意图)、screen(当前游戏处于哪个界面,如战斗、地图、商店、宝箱、事件)等。
  2. 动作查询工具:如get_legal_actions。在给定当前状态下,返回所有可执行的操作列表。例如在战斗中,可能返回[{"type": "play_card", "card_id": "strike", "target": "enemy_0"}, {"type": "end_turn"}]。这比让AI去解析完整状态再推断合法动作要可靠得多。
  3. 动作执行工具:一系列工具,如play_card,end_turn,choose_map_path,purchase_item,choose_event_option等。每个工具都需要特定的参数(如card_id,target)。
  4. 元数据查询工具:如get_card_metadata,get_relic_metadata。这些工具提供静态数据,帮助AI理解“打击”这张牌的基础伤害是多少,“蛇眼”这个遗物有什么效果。

注意事项:AI在决策时,必须先调用get_legal_actions,然后从返回的列表中选择一个动作来执行。直接根据状态“想象”出一个动作并调用执行工具,很可能会因为动作非法而失败。这是设计AI决策循环时的铁律。

4.2 构建一个简单的回合制战斗AI

让我们设想一个最简单的AI:一个只会出攻击牌的打脸机器人。它的决策逻辑可以这样实现(以伪代码描述):

# 伪代码:简单攻击AI决策循环 while game_is_in_combat: # 1. 获取当前游戏状态 state = call_tool("get_game_state") # 2. 检查是否是我的回合(player_turn 为 true) if not state.combat.player_turn: wait_for_event("turn_start") # 等待事件通知 continue # 3. 获取当前所有合法动作 legal_actions = call_tool("get_legal_actions") # 4. 过滤出“出牌”动作,并优先选择攻击牌 play_actions = [a for a in legal_actions if a.type == "play_card"] attack_actions = [] for action in play_actions: card_meta = call_tool("get_card_metadata", {"id": action.card_id}) if "攻击" in card_meta.keywords or card_meta.type == "ATTACK": # 假设有关键字 attack_actions.append(action) # 5. 执行动作:有攻击牌则打出第一张,否则结束回合 if attack_actions: target_action = attack_actions[0] # 可能需要选择目标,这里简单选第一个敌人 if target_action.needs_target: target_action.target = state.combat.enemies[0].id call_tool("play_card", target_action) else: call_tool("end_turn") # 6. 短暂等待,避免请求过快 sleep(0.1)

这个AI虽然简单,但已经包含了核心循环:获取状态 -> 检查合法性 -> 决策 -> 执行 -> 等待反馈。在实际项目中,你会用更复杂的策略(如价值网络、规则引擎、大语言模型提示)来替换第4步的决策逻辑。

4.3 利用SSE事件优化AI响应

如前所述,轮询get_game_state是低效的。更优雅的方式是让AI客户端订阅MCP Server提供的事件流。虽然项目文档没有给出具体的事件列表,但我们可以推断出可能的事件类型:

  • game_state_updated: 通用状态更新。
  • turn_start: 玩家回合开始。
  • turn_end: 玩家回合结束。
  • card_played: 一张牌被打出。
  • combat_end: 战斗结束。

在支持SSE的客户端中,你的AI可以这样工作:

# 伪代码:基于事件的AI import asyncio async def event_listener(): async for event in subscribe_to_sse("http://localhost:8765/events"): if event.type == "turn_start": # 回合开始,触发决策流程 asyncio.create_task(make_decision()) elif event.type == "card_played": # 更新内部状态模型 update_internal_state(event.data) # ... 处理其他事件 async def make_decision(): # 这里是你的核心决策逻辑,同上一节的循环体,但只在收到事件后触发 legal_actions = await call_tool("get_legal_actions") # ... 决策并执行 # 启动事件监听和决策循环 asyncio.run(event_listener())

这种方式将AI从繁忙的轮询中解放出来,使其行为更贴近真实玩家的“事件-反应”模式,同时也大幅降低了系统负载。

5. 高级应用与自定义开发指南

5.1 集成大型语言模型(LLM)作为决策核心

MCP的魅力在于它能无缝对接各种AI。你可以将Claude、GPT-4等LLM作为决策大脑。基本流程如下:

  1. 系统提示词设计:这是最关键的一步。你需要给LLM一个清晰的角色定义和游戏规则。

    你是一个《杀戮尖塔2》的专家玩家。你将通过一系列工具与游戏交互。 游戏状态会以JSON格式提供给你。你的目标是赢得每一场战斗,并尽可能高效地通关。 在每一轮你的回合中,请遵循以下步骤: 1. 使用`get_game_state`工具获取当前状态。 2. 使用`get_legal_actions`工具了解你能做什么。 3. 分析状态:计算伤害、评估威胁、规划能量使用。 4. 从合法动作中选择你认为最优的一个,并使用对应的工具执行它(如`play_card`)。 5. 重复直到你的回合结束。 记住:不要假设任何游戏规则,所有信息都从工具调用中获得。
  2. 上下文管理:LLM有token限制。你不能每次都把完整的游戏状态(可能很大)塞给它。需要设计一个“状态摘要”函数,从完整的game_state中提取最关键的信息(如玩家血量、能量、手牌简述、敌人血量及意图),以简洁的文本形式提供给LLM。

  3. 工具调用:使用支持“Function Calling”或“Tool Use”的LLM API(如OpenAI的gpt-4-turbo或Anthropic的Claude 3)。将MCP Server提供的工具列表以JSON Schema格式传给LLM。LLM会在回复中指定它想调用哪个工具以及参数是什么,由你的客户端程序负责解析并实际调用MCP工具,然后将结果返回给LLM进行下一步推理。

  4. 记忆与规划:简单的回合制决策可能不需要长期记忆,但对于跨回合的策略(如保留一张关键牌到下回合)、跨房间的路线选择,LLM需要记住之前发生的事。这可以通过在对话历史中保留关键摘要来实现,或者引入更复杂的向量数据库来存储游戏历史片段。

5.2 构建分层智能体与技能系统

项目仓库中有一个skills/目录,这暗示了更高级的架构可能性:分层智能体

  • 底层技能:封装原子操作。例如,一个“计算最优攻击序列”的技能,输入是手牌、能量、敌人血量,输出是一套出牌顺序。另一个“评估遗物价值”的技能,专门用于商店购买决策。
  • 中层管理器:根据当前游戏阶段(战斗、地图、商店、事件)调用相应的技能。战斗管理器调用战斗技能,商店管理器调用评估技能。
  • 高层控制器:负责最顶层的目标制定和资源分配。例如,“本局游戏目标是走最大化精英怪的路线来获取遗物”,或者“当前血量危险,优先选择篝火路径恢复”。

你可以利用MCP Server作为这些技能的统一执行后端。每个技能都是一个独立的模块,它们通过调用标准的MCP工具来感知和行动。这种架构使得AI系统更模块化、更易维护和调试。

5.3 从零构建自定义MCP客户端

如果你想完全掌控AI逻辑,或者进行强化学习训练,你可能需要构建自己的MCP客户端。这个过程并不复杂:

  1. 建立连接:根据MCP Server的模式(stdio或HTTP),建立相应的通信通道。
  2. 初始化:发送initialize请求,协商协议版本。
  3. 列出工具:发送tools/list请求,获取所有可用工具的定义。
  4. 主循环: a. 调用get_game_state。 b. 你的自定义AI算法(可以是规则引擎、神经网络、搜索树)根据状态计算出一个动作意图。 c. 调用get_legal_actions验证该意图是否合法,或直接从合法动作中选择。 d. 调用对应的工具执行动作。 e. 等待下一次状态更新(通过轮询或SSE事件)。

使用Python,一个极简的HTTP模式客户端框架如下:

import requests import json class STS2MCPClient: def __init__(self, server_url="http://127.0.0.1:8765/mcp"): self.url = server_url self.request_id = 1 def call(self, method, params=None): payload = { "jsonrpc": "2.0", "id": self.request_id, "method": method, "params": params or {} } self.request_id += 1 response = requests.post(self.url, json=payload).json() if "error" in response: raise Exception(f"RPC Error: {response['error']}") return response.get("result") def get_tools(self): return self.call("tools/list") def call_tool(self, tool_name, arguments): return self.call("tools/call", {"name": tool_name, "arguments": arguments}) # 封装具体工具 def get_game_state(self): return self.call_tool("get_game_state", {}) def play_card(self, card_id, target=None): args = {"card_id": card_id} if target: args["target"] = target return self.call_tool("play_card", args) # ... 封装其他工具 # 使用客户端 client = STS2MCPClient() state = client.get_game_state() print(f"当前生命值: {state['run']['current_hp']}")

有了这个基础客户端,你就可以在其中集成任何你想要的AI算法了。

6. 故障排查、性能优化与注意事项

6.1 常见问题与解决方案速查表

问题现象可能原因排查步骤与解决方案
访问http://127.0.0.1:8080/health无响应1. MOD未正确安装。
2. 游戏未启动。
3. 防火墙/杀软拦截。
4. 端口冲突。
1. 检查mods/目录下三个文件是否齐全且直接放置。
2. 确认游戏进程已完全启动。
3. 暂时关闭防火墙/杀软测试,或添加出入站规则。
4. 使用netstat -ano | findstr :8080(Win) 或lsof -i :8080(macOS/Linux) 查看端口占用。
MCP Server启动失败,提示Python或uv错误1. Python未安装或版本过低。
2. uv未安装或不在PATH。
3. 项目依赖安装失败。
1. 确认python --version>= 3.11。
2. 重新安装uv,并确认命令行可执行uv --version
3. 在mcp_server/目录下,尝试手动运行uv sync安装依赖。检查网络或配置镜像源。
MCP Server能启动,但调用工具返回“连接游戏失败”1. MOD的HTTP服务未运行。
2. MCP Server配置的MOD地址错误。
1. 首先确保/health端点可访问。
2. 检查MCP Server的配置文件或环境变量(如STS2_AGENT_URL),确认其指向正确的http://127.0.0.1:8080
AI执行动作后游戏无反应1. 动作非法(如目标错误、能量不足)。
2. 游戏处于动画状态,不接受输入。
3. 网络延迟或请求丢失。
1.务必在执行前调用get_legal_actions进行验证。
2. 在AI逻辑中加入等待。例如,执行动作后,等待一段时间或等待特定事件(如card_played)后再进行下一步。
3. 增加简单的重试和错误处理逻辑。
游戏运行卡顿或出现异常1. AI请求频率过高,给游戏造成负担。
2. MOD存在内存泄漏或性能问题。
3. 与其它MOD冲突。
1.最重要的优化:降低轮询频率,改用事件驱动。在非关键时段(如敌人动画)添加休眠(如time.sleep(0.2))。
2. 关注游戏和MOD的更新日志。
3. 尝试在纯净游戏环境下(无其他MOD)运行测试。

6.2 性能优化要点

  1. 减少不必要的状态获取get_game_state返回的数据量可能很大。如果你的AI只关心战斗,那么在非战斗界面(如地图)可以减少调用频率,或者只获取部分字段(如果MCP Server支持)。
  2. 利用本地缓存:静态元数据(卡牌、遗物信息)在一次游戏会话中不会改变。可以在AI客户端启动时一次性获取并缓存,避免重复调用get_card_metadata等工具。
  3. 设计高效的决策间隔:不要试图在每一帧都做决策。人类玩家也有反应时间。设定一个合理的决策周期(如每秒2-5次决策),并在游戏动画期间主动暂停决策循环。
  4. 日志与监控:为你的AI客户端添加详细的日志功能,记录每一个状态、决策和结果。这不仅能帮你调试逻辑错误,还能分析AI的决策质量。可以记录每回合用时、平均伤害输出、胜率等指标。

6.3 伦理、合规与社区准则

  • 并非外挂:请将此项目视为一个“研究辅助工具”或“自动化测试框架”。它的目的是理解和探索游戏机制,而不是在多人游戏或排行榜中获取不公平优势。STS2是纯单机游戏,这降低了相关风险,但仍应秉持尊重游戏设计者和社区的态度。
  • 尊重开源协议:该项目采用AGPL-3.0协议。这意味着如果你修改了项目代码并部署了网络服务,你有义务开源你的修改。在基于此项目进行二次开发或集成时,请仔细阅读许可证条款。
  • 关注游戏更新:游戏更新可能会修改内部数据结构,导致MOD失效。关注项目的GitHub仓库,维护者通常会及时更新。在游戏更新后,如果MOD失效,应耐心等待更新,而非尝试破解或使用过时版本。
  • 分享与贡献:如果你改进了AI策略、修复了bug或增加了新功能,考虑向原项目提交Pull Request。开源社区的力量正是来自于此。

这个项目打开了一扇门,门后是游戏与AI交叉的广阔领域。你可以用它来实践软件集成、智能体架构设计,也可以深入游戏策略的算法求解。最重要的是动手尝试,从让AI打出一张“打击”开始,逐步构建起能征服高进阶难度的智能体。在这个过程中,你收获的将远不止是游戏通关的成就感。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询