游戏分析MCP服务器
生产就绪的MCP服务器+AI代理系统,用于使用RAWGneneneba API分析视频游戏数据,部署在CloudflareWorkers上。
概述
该项目实现了一个模型上下文协议(MCP)服务器,该服务器提供用于获取和分析视频游戏数据的工具。人工智能代理精心策划这些工具,以回答有关游戏的分析问题。
建筑
- MCP服务器:提供
fetch_game_data和execute_calculation通过流式HTTP传输工具 - RAWG客户端:RAWG-视频游戏数据库API的类型安全客户端
- 代码执行器:安全、动态的代码执行,实现灵活的计算
- AI 代理:使用OpenAI或Anthropic模型来编排工具
- 用户界面:带有评估指标显示的聊天界面
与光标一起使用
此服务器实现了模型上下文协议,可以作为远程MCP服务器直接连接到Cursor。看 CURSOR_MCP_SETUP.md 以获取配置说明。
服务器URL: https://cf-rawg.dkalaslioglu.workers.dev/mcp
评估面板(前端)
聊天UI包括一个右侧评估面板,该面板:
- 显示最后一个
fetch_game_data筛选器、计数、摘要和警告 - 捕获每个
execute_calculation以快照形式调用(代码+数据) - 允许您在本地重新运行计算(使用
avg,sum,min,max,groupBy) - 将手动结果与服务器结果进行比较,并报告通过/失败
请参阅中的详细行为和用法 docs/EVALUATION.md.
设置
先决条件
- Node.js 20+
- pnpm 10+
- Cloudflare帐户
- 原始API密钥:https://rawg.io/apidocs
- 无烟煤API密钥:https://console.anthropic.com/
安装
pnpm install安装过程将自动从以下位置复制QuickJS WASM文件 node_modules 到 src/ 目录通过 postinstall 脚本。如果需要手动复制WASM文件(例如,在更新依赖关系后),请运行:
pnpm copy-wasm这运行 scripts/copy-wasm-file-into-src.sh 其复制Cloudflare Workers中代码执行所需的WASM文件。
环境变量
对于本地开发(wrangler-dev),请复制 .dev.vars.example 到 .dev.vars 并填写您的密钥:
cp .dev.vars.example .dev.vars这些变量在本地运行时由Worker加载。
对于基于节点的测试(vitest/集成),使用 dotenv,您可以选择复制 .env.example 到 .env 并填写相同的密钥:
cp .env.example .env在生产中,使用设置变量 wrangler secret put 或者在Cloudflare仪表板中。
本地开发
pnpm dev这将在本地启动Cloudflare Worker http://localhost:8787
测试
# Unit tests
pnpm test:unit
# Integration tests (actual API calls)
pnpm test:integration部署
pnpm deploy身份验证(仅限测试)
对于这个项目,我们添加了简单的无数据库身份验证:
- 应用程序(UI和
/api/chat):HTTP基本身份验证
- 变量: BASIC_AUTH_USER, BASIC_AUTH_PASS - 例子: - 头球 Authorization: Basic base64(username:password)
- MCP(
/mcp可流式传输的HTTP):API密钥头
- 变量: MCP_API_KEY - 头球 x-api-key:
这些仅用于演示。对于生产环境,我们更倾向于Cloudflare Access或OAuth。
项目结构
cf-rawg/
├── src/
│ ├── mcp-server/ # MCP Server Domain
│ ├── rawg/ # RAWG API Client Domain
│ ├── executor/ # Code Execution Domain
│ ├── agent/ # Agent Orchestration Domain
│ ├── ui/ # UI/Presentation Domain
│ ├── RELEASE_SYNC.wasm # QuickJS WASM module (generated and not tracked by Git)
│ └── index.ts # Worker entry point
├── scripts/
│ └── copy-wasm-file-into-src.sh # Script to copy WASM files from node_modules
├── tests/
│ ├── unit/ # Unit tests
│ └── integration/ # Actual test scripts
└── wrangler.toml # Cloudflare config开发方法
该项目遵循领域驱动、测试优先的方法:
- 为每个域编写单元测试
- 实现代码以通过测试
- 编写实际的测试脚本(无模拟)以验证真实行为
- 只有在测试通过后才能进入下一阶段
已知限制
Metacritic分数覆盖率
RAWG数据库的Metacritic评分覆盖范围有限,每年差异很大:
- 2001-2010:最佳覆盖率(5-15%的游戏有Metacritic评分)
- 2011-2021:覆盖率下降(游戏的0.1-1%)
- 2022+:覆盖率非常低(不到游戏的0.1%)
- 2024:在所有平台上,总共只有2款游戏有Metacritic分数
- 2025:Metacritic评分为零的游戏
有关最近的游戏(2022+)的查询,我们使用 rating 相反,它的覆盖率为85-100%。这 rating 该字段包含RAWG社区评级(0-5级),对于最近的数据来说更可靠。
这 fetch_game_data 当Metacritic数据稀疏时,该工具会自动发出警告,并建议使用评级字段作为替代。
响应大小和性能限制
在开发过程中,我们在处理分析查询时遇到了严重的性能问题:
问题
- 大响应有效载荷:RAWGneneneba API返回带有许多嵌套字段(平台数组、流派数组、评级对象等)的完整游戏对象,每个游戏对象的大小为4-7KB
- 令牌使用过量:向LLM发送40多个完整的游戏对象,每次查询消耗2000-4000个令牌,仅用于数据有效载荷
- 查询处理速度慢:当LLM处理大量数据时,大型有效载荷导致10-30秒的响应时间
- 成本影响:高代币使用率显著增加了API成本
解决方案
我们实施了一些优化来解决这些限制:
- 智能默认页面大小:设置默认值
page_size到20个游戏(而不是没有默认游戏),这为大多数计算提供了足够的统计有效性,同时将有效载荷大小减少了50%
- 响应修剪:自动将游戏对象修剪到仅基本字段(
id,name,metacritic,rating,released),将每个游戏对象从4-7KB减少到1-2KB
- 选择性字段包含:平台和流派数组仅在按这些字段过滤时才包括在内,避免了不必要的嵌套数据
- 概要统计:对于大型数据集,包括预先计算的汇总统计数据(平均值、最小值/最大值),这样LLM就可以在不处理所有单个游戏的情况下回答查询
- 代理效率指南:更新了系统提示,以指导代理在大多数查询中使用小页面大小(20-30个游戏)
结果
这些优化实现了:
- 减少80% 响应大小(150-300KB→ 20-40KB)
- 减少75% 代币使用量(约2000-4000→约500-1000个代币)
- 速度提高60-70% 查询处理(10-30s→ 3-8s)
- 成本降低80% 每次查询
该系统现在可以有效地处理分析查询,同时保持计算精度,因为20-30个游戏为平均值和比较等统计操作提供了足够的样本量。
Cloudflare Workers代码执行限制
Cloudflare Workers有严格的安全限制,可以阻止传统的JavaScript代码执行方法:
为什么 new Function() 不起作用
Cloudflare Workers运行时使用以下方式阻止动态代码生成 new Function() 构造函数和 eval() 功能。当尝试使用这些方法时,运行时抛出:
"Code generation from strings disallowed for this context"这是一种安全功能,用于防止代码注入攻击并保持工作实例之间的隔离。
为什么直接QuickJS WASM加载不起作用
最初,我们试图使用 quickjs-emscripten 库直接,但它失败了,因为:
- 动态WASM加载:库试图通过以下方式加载WASM文件
fetch()使用self.location.href,这在Cloudflare Workers环境中不存在 - 错误:
TypeError: Cannot read properties of undefined (reading 'href') - 根本原因:Cloudflare Workers在构建时捆绑所有代码,不支持通过网络请求加载运行时WASM模块
解决方案:嵌入式WASM文件
我们通过以下方式解决了这个问题:
- 在构建时嵌入WASM:使用
scripts/copy-wasm-file-into-src.sh从中复制WASM文件的脚本node_modules进入src/目录 - 自动设置:脚本通过自动运行
postinstall钩后pnpm install - 直接进口:直接将WASM文件作为模块导入:
import cloudflareWasmModule from '../RELEASE_SYNC.wasm' - 自定义变量:使用创建Cloudflare特定变体
newVariant()它使用嵌入式WASM模块,而不是试图动态加载它 - QuickJS运行时:使用QuickJS
evalCode()方法而不是new Function()安全地执行JavaScript代码
手动WASM副本:如果需要手动复制WASM文件(例如,在更新依赖关系后),请运行:
pnpm copy-wasm代码执行约束
- 无顶级回报:QuickJS不支持顶级
return声明。代码与return语句必须包装在IIFE(立即调用函数表达式)中 - 上下文序列化:所有上下文数据必须可序列化为JSON(函数被过滤掉,并作为代码字符串单独提供)
- 内存限制:QuickJS运行时每次执行的内存限制为10MB
- 超时:最大执行时间为5秒
捆绑尺寸影响
QuickJS WASM模块增加了大约 600KB 对于worker捆绑包:
- 之前:约894 KB
- 之后:~1495 KB(gzip:~420 KB)
这对于所提供的功能来说是可以接受的,因为它可以在沙盒环境中实现完整的JavaScript执行。
时光流逝
大致工作量分解:
- 第0阶段——架构和研究(项目制定、RAWG文档、MCP文档、计划细化):~1.0小时
- 第一阶段——RAWG客户端域(类型、过滤器、客户端、集成测试):约1.0小时
- 第2阶段——代码执行域(QuickJS WASM沙箱、验证器、运行时):~3.5小时
- 阶段3-MCP服务器域(工具、服务器布线、单元测试):~1.0小时
- 第4阶段——代理编排(AI SDK集成、工具映射、提示):约1.5小时
- 第5阶段——用户界面和评估显示(聊天用户界面、流媒体、评估面板):~2.0小时
- 第6阶段——测试和改进(单元+集成、流式抛光):~1.0小时
- 第7阶段——部署(Cloudflare配置、牧者、产品检查):约0.5小时
- 调试和抛光(性能微调、CORS、游标流式HTTP):约2.5小时
总计:约14.0小时
未来改进
- 将UI和MCP的仅测试身份验证替换为Cloudflare Access或OAuth。
- 具有轮换和范围的单个或单个API键。
- 通过QuickJS中断回调抢占无限循环的执行器硬超时。
- 工具调用和计算的使用指标和审计日志。
- 可选的RAWG-响应持久缓存,以减少API调用和延迟。
许可证
ISC
