From 7b68504b1e10f1bb053390bb036da1172e4a8416 Mon Sep 17 00:00:00 2001 From: hyper Date: Tue, 17 Mar 2026 22:49:47 +0800 Subject: [PATCH] feat: mcp server! --- docs/mcp.md | 222 ++++++++++++++++++++++++++++++++++++++++ src/cli/commands/mcp.ts | 11 +- 2 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 docs/mcp.md diff --git a/docs/mcp.md b/docs/mcp.md new file mode 100644 index 0000000..8666aef --- /dev/null +++ b/docs/mcp.md @@ -0,0 +1,222 @@ +# MCP 服务器使用说明 + +TTRPG Tools 提供了一个 MCP (Model Context Protocol) 服务器,用于与 AI 助手集成,自动化生成卡牌内容。 + +## 命令结构 + +```bash +ttrpg mcp [command] +``` + +### 子命令 + +#### 1. `mcp serve` - 启动 MCP 服务器 + +启动 MCP 服务器,供 AI 助手连接使用。 + +```bash +# 使用 stdio 传输(默认) +ttrpg mcp serve + +# 指定传输方式 +ttrpg mcp serve stdio +``` + +**MCP 客户端配置示例:** + +```json +{ + "mcpServers": { + "ttrpg-card-generator": { + "command": "node", + "args": ["path/to/ttrpg-tools/dist/cli/index.js", "mcp", "serve"] + } + } +} +``` + +#### 2. `mcp generate-card-deck` - 快速生成卡牌组 + +通过命令行快速生成卡牌组,无需 MCP 客户端。 + +```bash +ttrpg mcp generate-card-deck --name "卡牌名称" --output "./输出目录" [选项] +``` + +**选项:** + +| 选项 | 说明 | 默认值 | +|------|------|--------| +| `--name ` | 卡牌组名称(必需) | - | +| `--output ` | 输出目录(必需) | - | +| `-c, --count ` | 卡牌数量 | `10` | +| `--fields ` | 字段列表(逗号分隔) | `name,type,cost,description` | +| `--description ` | 卡牌组描述 | - | +| `--size ` | 卡牌尺寸 | `54x86` | +| `--grid ` | 网格布局 | `5x8` | + +**示例:** + +```bash +# 生成基础魔法物品卡牌 +ttrpg mcp generate-card-deck --name "魔法物品" --output "./content" + +# 生成自定义 NPC 卡牌 +ttrpg mcp generate-card-deck \ + --name "NPC Cards" \ + --output "./content/npcs" \ + --count 20 \ + --fields "name,class,level,background" \ + --description "快速生成游戏中的 NPC 角色" + +# 生成塔罗牌组 +ttrpg mcp generate-card-deck \ + --name "Tarot Deck" \ + --output "./content/tarot" \ + --count 22 \ + --fields "name,number,meaning" \ + --size "70x120" \ + --grid "3x4" +``` + +## MCP 工具:generate_card_deck + +通过 MCP 协议,AI 助手可以调用 `generate_card_deck` 工具生成卡牌组。 + +### 工具参数 + +| 参数 | 类型 | 必需 | 说明 | +|------|------|------|------| +| `deck_name` | string | ✓ | 卡牌组名称 | +| `output_dir` | string | ✓ | 输出目录路径 | +| `card_count` | number | ✗ | 卡牌数量(默认:10) | +| `card_template` | object | ✗ | 卡牌模板定义 | +| `deck_config` | object | ✗ | md-deck 组件配置 | +| `description` | string | ✗ | 卡牌组描述 | + +### card_template 结构 + +```json +{ + "fields": [ + { + "name": "字段名称(英文,用于 CSV 列名)", + "description": "字段描述", + "examples": ["示例值 1", "示例值 2"] + } + ], + "examples": [ + { + "字段名称": "值 1", + "字段名称 2": "值 2" + } + ] +} +``` + +### deck_config 结构 + +```json +{ + "size": "54x86", + "grid": "5x8", + "bleed": 1, + "padding": 2, + "shape": "rectangle", + "layers": "name:1,2-3,12 desc:1,4-8,10", + "back_layers": "back:1,2-8,12" +} +``` + +### 使用示例(AI 助手) + +**用户请求:** +> 帮我生成一个魔法物品卡牌组,包含 15 张卡牌,字段有名称、稀有度、效果描述 + +**AI 助手调用工具:** +```json +{ + "deck_name": "魔法物品", + "output_dir": "./content", + "card_count": 15, + "card_template": { + "fields": [ + { + "name": "name", + "description": "物品名称", + "examples": ["火球术卷轴", "治疗药水", "隐形斗篷"] + }, + { + "name": "rarity", + "description": "稀有度", + "examples": ["稀有", "普通", "珍贵"] + }, + { + "name": "effect", + "description": "效果描述", + "examples": ["造成 5d6 火焰伤害", "恢复 2d4+2 生命值", "隐身 1 小时"] + } + ] + } +} +``` + +**工具返回:** +- 生成的 Markdown 文件路径 +- 生成的 CSV 文件路径 +- `:md-deck` 组件代码 + +## 输出文件 + +运行工具后会生成: + +1. **Markdown 文件** (`{deck_name}.md`) + - 包含卡牌组标题和描述 + - 嵌入 `:md-deck` 组件代码 + - 使用说明 + +2. **CSV 文件** (`{deck_name}.csv`) + - 包含所有卡牌数据 + - 支持 `{{字段名}}` 变量语法 + - 可使用 front matter 添加共享属性 + +3. **组件代码** + - 可直接插入任何 Markdown 文件 + - 格式:`:md-deck[./xxx.csv]{size="54x86" grid="5x8" ...}` + +## 与 TTRPG Tools 集成 + +生成的卡牌组可以直接使用 TTRPG Tools 预览和编译: + +```bash +# 预览卡牌内容 +ttrpg serve ./content + +# 编译为静态网站 +ttrpg compile ./content -o ./dist +``` + +## 开发说明 + +### 添加新的 MCP 工具 + +1. 在 `src/cli/tools/` 目录创建工具模块 +2. 在 `src/cli/commands/mcp.ts` 中注册工具 +3. 实现 `ListToolsRequestSchema` 和 `CallToolRequestSchema` 处理器 + +### 代码结构 + +``` +src/cli/ +├── commands/ +│ ├── serve.ts +│ ├── compile.ts +│ └── mcp.ts # MCP 命令入口 +├── tools/ +│ └── generate-card-deck.ts # 卡牌生成工具 +└── index.ts +``` + +### 依赖 + +MCP 服务器使用 `@modelcontextprotocol/sdk` 包,已包含在项目依赖中。 diff --git a/src/cli/commands/mcp.ts b/src/cli/commands/mcp.ts index c7bccf7..d365b4c 100644 --- a/src/cli/commands/mcp.ts +++ b/src/cli/commands/mcp.ts @@ -9,6 +9,7 @@ import { generateCardDeck, type GenerateCardDeckParams, type CardField } from '. export interface MCPOptions { port?: string; + cwd?: string; } export const mcpCommand = new Command('mcp') @@ -18,6 +19,7 @@ export const mcpCommand = new Command('mcp') .description('启动 MCP 服务器') .argument('[host]', '服务器地址', 'stdio') .option('-p, --port ', 'HTTP 端口(仅 HTTP 传输)', '3001') + .option('--cwd ', '工作目录(工具调用的相对路径基准)', process.cwd()) .action(mcpServeAction) ) .addCommand( @@ -37,6 +39,11 @@ export const mcpCommand = new Command('mcp') * MCP 服务器启动处理函数 */ async function mcpServeAction(host: string, options: MCPOptions) { + // 切换到指定的工作目录 + const cwd = options.cwd || process.cwd(); + process.chdir(cwd); + console.error(`MCP 服务器工作目录:${cwd}`); + // 动态导入 MCP SDK const { Server } = await import('@modelcontextprotocol/sdk/server/index.js'); const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js'); @@ -73,7 +80,7 @@ async function mcpServeAction(host: string, options: MCPOptions) { }, output_dir: { type: 'string', - description: '输出目录路径', + description: '输出目录路径(相对路径相对于 MCP 服务器工作目录)', }, card_count: { type: 'number', @@ -191,7 +198,7 @@ async function mcpServeAction(host: string, options: MCPOptions) { }; } - // 生成卡牌组 + // 生成卡牌组(使用当前工作目录) const result = generateCardDeck(params); return {