关于 Number Guessing Game MCP Server
这是一个用 TypeScript 编写的数字猜谜 MCP 服务示例,面向学习动态、多用户 MCP 应用开发的开发者。它按用户会话隔离游戏状态,并动态管理工具和资源。
主要功能
- 01独立的多用户游戏会话
- 02按游戏状态启用工具
- 03按会话创建和销毁资源
- 04Firestore 持久化状态与高分
- 05TypeScript 状态模式架构
适用场景
- 01学习构建动态 MCP 服务
- 02测试按会话变化的工具与资源
- 03探索 HTTP 会话生命周期管理
MCP 相关
它向 MCP 客户端提供数字猜谜游戏工具和 game_state 资源。每个用户会话拥有独立且随游戏状态变化的工具与资源。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
数字猜谜游戏 MCP 服务
一个使用 TypeScript 实现的示例模型上下文协议(MCP)服务。它展示了动态、基于会话的架构:每位用户都有自己的一组工具和资源,由中央控制器管理。此服务承载一个简单的数字猜谜游戏。
访问地址:https://mcp.number-guessing-game.portal.one/mcp
查看更多远程服务:https://remote-mcp-servers.com/
阅读我们的文章,了解动态 MCP 服务的优势:
https://portal.one/blog/dynamic-mcp-servers-tame-complexity/
以下是手动与服务交互的示例。请注意,工具会根据当前游戏状态发生变化。
https://github.com/user-attachments/assets/8bb15870-2adc-4412-a072-4fc4eb14bbef
以下是 Agent 与服务交互的视频。视频中看不到,但 Agent 可用的工具也会根据游戏状态发生变化。
https://github.com/user-attachments/assets/d7d338a2-8a93-46c3-b4a9-1a6b4caf9dc0
本项目旨在作为学习资源,并为构建动态、多用户 MCP 应用提供实践示例。
目录
主要功能
- 真正的多用户会话: 每位连接的用户都有各自隔离的游戏状态和一组 MCP 实体。
- 动态 MCP 工具: 工具(
start_game、guess_number、give_up)会按用户启用或禁用,以反映各自的游戏状态。 - 动态 MCP 资源:
game_state资源会随用户开始和结束游戏而创建和销毁。 - 简洁、可扩展的架构:
- 单个全局
McpServer处理所有连接。 - Express.js 控制器管理每个用户会话的生命周期。
- 按会话划分的实体(工具、资源、游戏逻辑)按需创建。
- 状态模式: 管理每位用户的游戏流程(大厅、游戏中)。
- 单个全局
- TypeScript 实现: 完整的类型定义,提升可维护性和开发体验。
- Firestore 集成: 持久化游戏状态和最高分,使服务具备无状态性和可扩展性。
架构概览
该服务采用一种现代且可扩展的模式,由中央控制器管理临时的、特定于会话的资源。
-
全局服务配置(
src/mcp_setup/index.ts): 应用启动时会创建一个 McpServer 实例。它充当“空白”的连接管理器,本身不包含任何工具或资源。 -
HTTP 控制器(
src/controllers/mcp.controller.ts): 这是应用的核心。- 它负责处理发往
/mcp端点的所有传入 HTTP 请求。 - 新用户连接时,它会创建一个
StreamableHTTPServerTransport。 - 它利用传输层的生命周期钩子(
onsessioninitialized和onclose)管理用户会话。
- 它负责处理发往
-
会话初始化(
onsessioninitialized): 用户的传输层就绪后,控制器会:- 调用
src/mcp_setup/tools和src/mcp_setup/resources中的设置函数,为该用户创建一组全新的、唯一的 MCP 实体。 - 创建一个全新的
GameContext实例,并将其关联到用户的会话 ID 及其专属 MCP 实体。 - 通过
GameSessionService从 Firestore 加载用户状态,并使用状态模式(LobbyState或PlayingState)为其会话启用/禁用相应的工具。
- 调用
-
会话销毁(
onclose): 用户断开连接时,控制器会:- 注销并销毁专为该用户创建的所有工具和资源,以防止内存泄漏。
- 从活动连接列表中清理该传输层。
此架构可确保每位用户的 UI 状态(例如,启用了哪些工具)都完全隔离、具有状态且可动态管理,同时服务本身仍可扩展。
前置条件
- Node.js(建议使用 v18.x 或更高版本)
- npm 或 yarn
- 可访问已启用 Firestore 的 Google Cloud 项目。
开始使用
安装
- 克隆代码仓库:
git clone https://github.com/portal-labs-infrastructure/number-guessing-game-mcp-server cd number-guessing-game-mcp-server - 安装依赖项:
npm install # or yarn install
配置
- 设置 Google Cloud 身份验证: 确保你的环境已通过身份验证,可访问 Google Cloud 项目。本地开发时,可以使用 gcloud CLI:
gcloud auth application-default login - 创建
.env文件: 复制示例文件。cp .env.example .env - 编辑
.env: 填写所需的环境变量。PORT:服务运行的端口(例如,8083)。GCP_PROJECT_ID:你的 Google Cloud 项目 ID。BASE_URL:服务的公网 URL(例如,http://localhost:8083)。OAUTH_ISSUER_URL:OAuth 提供方的基础 URL。DOCS_URL:服务文档链接。
运行服务
开发模式(用于支持热重载的开发):
npm run dev
生产模式:
编译 TypeScript:
npm run build
启动服务:
npm start
你应该会看到表明服务正在运行并已连接到 Firestore 的输出。
与服务交互
在线服务
你需要使用支持以下功能的 MCP 客户端:
- OAuth2(支持动态客户端注册)
- 工具通知
- 资源通知
你可以使用 MCP Inspector,但它不支持工具和资源通知,因此你必须手动刷新工具和资源。
使用 Portal One Web 客户端,在可用 MCP 服务列表中找到该服务,然后点击“连接”。
如需查看其他支持动态 MCP 工具和资源(发现)的客户端,请参阅 MCP SDK 示例客户端。
本地
确保客户端可以访问服务。如果你在本地运行服务,并使用基于 Web 的客户端,可以使用 ngrok 等工具将服务暴露到互联网:
ngrok http http://localhost:8083
如果你使用的是 localhost 上的客户端,可以直接连接到 http://localhost:8083/mcp。
项目结构
src/
├── config/
│ └── index.ts # Loads and exports environment variables
├── controllers/
│ └── mcp.controller.ts # Manages session lifecycles and creates entities on-demand
├── game/
│ ├── commands/ # Command Pattern: Encapsulates user actions
│ │ ├── command.interface.ts
│ │ ├── give-up.command.ts
│ │ ├── guess-number.command.ts
│ │ └── start-game.command.ts
│ ├── core/
│ │ ├── game-context.ts # Central game logic coordinator for a SINGLE session
│ │ ├── game-session-service.ts # Handles all Firestore interactions (get/set state)
│ │ ├── game-types.ts # Core TypeScript interfaces for the game
│ │ ├── resource-factory.ts # (Not used in current setup, but available)
│ │ └── tool-factory.ts # (Not used in current setup, but available)
│ ├── states/ # State Pattern: Manages game flow (Lobby, Playing)
│ │ ├── game-state.interface.ts
│ │ ├── lobby.state.ts
│ │ └── playing.state.ts
│ └── utils/
│ └── game-constants.ts # Shared game constants
├── index.ts # Main application entry point (Express server setup)
├── mcp_setup/
│ ├── index.ts # Creates the single, global McpServer instance
│ ├── resources/ # Factory functions for creating MCP resources
│ │ ├── index.ts # Barrel file for exporting all resource setups
│ │ └── ... (setup-banner-image-resource.ts, etc.)
│ └── tools/ # Factory functions for creating MCP tools
│ ├── index.ts # Barrel file for exporting all tool setups
│ └── ... (setup-guess-number-tool.ts, etc.)
├── routes/
│ └── mcp.routes.ts # Defines the Express routes for /mcp
└── services/
└── firestore.service.ts # Initializes the global Firestore client
展示的核心概念
- 动态的、会话级的 MCP: 这是此架构的核心。工具和资源不是全局的;它们会针对每个用户会话创建和销毁。
- 生命周期管理: 使用传输钩子(
onsessioninitialized、onclose)管理会话资源的设置和拆除。 - 基于 HTTP 的有状态服务: 通过无状态协议实现持久且相互隔离的用户会话。
- 状态模式: 管理每个用户游戏流程中的复杂状态转换。
- 使用 Firestore 持久化状态: 将服务的运行时与游戏状态解耦,从而支持水平扩展和提升弹性。
- TypeScript 最佳实践: 在真实且可扩展的应用结构中使用类型,以编写稳健的代码。
贡献
欢迎贡献!如果你有改进建议、新功能想法或发现了 Bug,欢迎提交 issue 或 pull request。
许可证
本项目采用 MIT 许可证授权,详情请参阅 LICENSE 文件。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。