Skip to main content
Glama
pmhw

MCP Lottery Demo

by pmhw
server.js8.11 kB
#!/usr/bin/env node /** * MCP 抽签工具服务器 * * 这是一个基于 Model Context Protocol (MCP) 的抽签工具演示 * 提供抽签、投骰子、抛硬币等随机功能 * * 使用方法: * 1. 安装依赖:npm install * 2. 启动服务器:npm start * 3. 在 MCP Inspector 中连接测试 */ // 导入 MCP SDK 相关模块 import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; /** * 创建 MCP 服务器实例 * * @param {Object} serverInfo - 服务器信息 * @param {string} serverInfo.name - 服务器名称 * @param {string} serverInfo.version - 服务器版本 * @param {Object} capabilities - 服务器能力配置 * @param {Object} capabilities.tools - 工具能力配置 */ const server = new Server( { name: 'lottery-tool', // 服务器名称,用于标识 version: '1.0.0', // 服务器版本号 }, { capabilities: { tools: {}, // 声明支持工具功能 }, } ); /** * 定义工具列表 * * 每个工具包含: * - name: 工具名称 * - description: 工具描述 * - inputSchema: 输入参数模式(JSON Schema) */ const tools = [ { name: 'draw_lottery', description: '从给定的选项列表中随机抽取一个或多个结果', inputSchema: { type: 'object', properties: { options: { type: 'array', items: { type: 'string' }, description: '抽签选项列表', }, count: { type: 'number', description: '抽取数量,默认为1', default: 1, }, allow_duplicate: { type: 'boolean', description: '是否允许重复抽取,默认为false', default: false, }, }, required: ['options'], // 必需参数 }, }, { name: 'roll_dice', description: '投掷骰子,支持自定义面数和数量', inputSchema: { type: 'object', properties: { sides: { type: 'number', description: '骰子面数,默认为6', default: 6, }, count: { type: 'number', description: '骰子数量,默认为1', default: 1, }, }, }, }, { name: 'flip_coin', description: '抛硬币,返回正面或反面', inputSchema: { type: 'object', properties: { count: { type: 'number', description: '抛硬币次数,默认为1', default: 1, }, }, }, }, ]; /** * 处理工具列表请求 * * 当客户端请求可用工具列表时,返回所有已注册的工具 */ server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools, // 返回工具列表 }; }); /** * 处理工具调用请求 * * 根据工具名称和参数执行相应的功能 * * @param {Object} request - 工具调用请求 * @param {string} request.params.name - 工具名称 * @param {Object} request.params.arguments - 工具参数 */ server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { // 根据工具名称执行相应的功能 switch (name) { case 'draw_lottery': { // 抽签工具:从选项列表中随机抽取结果 const { options, count = 1, allow_duplicate = false } = args; // 参数验证 if (!Array.isArray(options) || options.length === 0) { throw new Error('选项列表不能为空'); } if (count > options.length && !allow_duplicate) { throw new Error('抽取数量不能超过选项数量(不允许重复时)'); } // 执行抽签逻辑 const results = []; const availableOptions = [...options]; // 创建选项副本 for (let i = 0; i < count; i++) { // 随机选择索引 const randomIndex = Math.floor(Math.random() * availableOptions.length); const selected = availableOptions[randomIndex]; results.push(selected); // 如果不允许重复,从可用选项中移除已选择的 if (!allow_duplicate) { availableOptions.splice(randomIndex, 1); } } // 返回格式化的结果 return { content: [ { type: 'text', text: `🎲 抽签结果:\n${results.map((result, index) => `${index + 1}. ${result}`).join('\n')}`, }, ], }; } case 'roll_dice': { // 投骰子工具:模拟投掷骰子 const { sides = 6, count = 1 } = args; // 参数验证 if (sides < 2) { throw new Error('骰子面数至少为2'); } if (count < 1) { throw new Error('骰子数量至少为1'); } // 执行投骰子逻辑 const results = []; let total = 0; for (let i = 0; i < count; i++) { // 生成 1 到 sides 之间的随机数 const roll = Math.floor(Math.random() * sides) + 1; results.push(roll); total += roll; } // 根据骰子数量格式化输出 const resultText = count === 1 ? `🎲 投掷结果:${results[0]}` : `🎲 投掷结果:${results.join(', ')}\n📊 总计:${total}`; return { content: [ { type: 'text', text: resultText, }, ], }; } case 'flip_coin': { // 抛硬币工具:模拟抛硬币 const { count = 1 } = args; // 参数验证 if (count < 1) { throw new Error('抛硬币次数至少为1'); } // 执行抛硬币逻辑 const results = []; let heads = 0; // 正面次数 let tails = 0; // 反面次数 for (let i = 0; i < count; i++) { // 50% 概率生成正面或反面 const result = Math.random() < 0.5 ? '正面' : '反面'; results.push(result); if (result === '正面') heads++; else tails++; } // 根据抛硬币次数格式化输出 const resultText = count === 1 ? `🪙 抛硬币结果:${results[0]}` : `🪙 抛硬币结果:${results.join(', ')}\n📊 统计:正面 ${heads} 次,反面 ${tails} 次`; return { content: [ { type: 'text', text: resultText, }, ], }; } default: // 未知工具名称 throw new Error(`未知工具:${name}`); } } catch (error) { // 错误处理:返回错误信息 return { content: [ { type: 'text', text: `❌ 错误:${error.message}`, }, ], isError: true, }; } }); /** * 启动服务器 * * 使用标准输入输出传输协议启动 MCP 服务器 * 这种方式适合与 AI 客户端(如 Claude Desktop)集成 */ async function main() { try { // 创建标准输入输出传输实例 const transport = new StdioServerTransport(); // 连接服务器到传输层 await server.connect(transport); // 输出启动信息(使用 stderr 避免干扰 MCP 协议) console.error('🎲 抽签工具 MCP 服务器已启动'); console.error('📡 传输方式:标准输入输出 (stdio)'); console.error('🔧 可用工具:draw_lottery, roll_dice, flip_coin'); } catch (error) { console.error('❌ 服务器启动失败:', error); process.exit(1); } } // 启动服务器并处理错误 main().catch((error) => { console.error('❌ 服务器运行错误:', error); process.exit(1); });

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/pmhw/McpDemo'

If you have feedback or need assistance with the MCP directory API, please join our Discord server