Skip to main content
Glama
liu04919

fortune-mcp-server

by liu04919
README.md
# fortune-mcp-server

一个面向远程 AI Host 的只读命理 MCP Server。它通过 Streamable HTTP 暴露八字、黄历和塔罗工具,程序负责计算与抽取,语言模型负责理解问题和自然语言解释。

> 所有结果仅用于传统文化研究与娱乐,不应作为医疗、法律、投资或其他重大决定的依据。

## 工具

| Tool | 输入 | 输出 | 性质 |
| --- | --- | --- | --- |
| `calculate_bazi_chart` | 出生日期、时间、性别、可选地点 | 八字命盘与真太阳时信息 | 确定性计算 |
| `get_daily_almanac` | `YYYY-MM-DD` 公历日期 | 农历、干支、宜忌、神煞、方位、时辰宜忌 | 确定性计算 |
| `draw_tarot_reading` | 单牌或三牌阵、是否启用逆位 | 牌位、牌名、正逆位和关键词 | 安全随机抽取 |

三个 Tool 都会同时返回:

- `content`:方便语言模型阅读的 JSON 文本;
- `structuredContent`:方便 MCP Host 做结构化处理的数据。

## 设计边界

```text
AI Host
  │  Bearer Token
  ▼
POST /mcp
  │  Streamable HTTP(无会话)
  ▼
McpServer
  ├─ calculate_bazi_chart ── shunshi-bazi-core
  ├─ get_daily_almanac ───── shunshi-bazi-core / tyme4ts
  └─ draw_tarot_reading ──── 78 张静态牌组 + crypto.randomInt
```

- 只提供远程 Streamable HTTP,不发布 npm CLI,也不提供 stdio 入口;
- 不访问本机文件,不执行任意代码,不发送邮件;
- 不保存用户输入、抽牌记录或 MCP 会话;
- `/mcp` 必须携带 Bearer Token,`/health` 可以匿名访问;
- Server 只返回事实、计算结果和简短关键词,不在工具内部生成大段命理解读。

## 本地运行

要求 Node.js 20+ 与 pnpm 10。

```powershell
pnpm install
$env:MCP_API_KEY="replace-with-a-long-random-token"
pnpm dev
```

默认地址:

- MCP:`http://127.0.0.1:3100/mcp`
- 健康检查:`http://127.0.0.1:3100/health`

可选环境变量:

| 环境变量 | 默认值 | 说明 |
| --- | --- | --- |
| `HOST` | `127.0.0.1` | HTTP 监听地址 |
| `PORT` | `3100` | HTTP 监听端口 |
| `MCP_API_KEY` | 无 | 必填,至少 24 个字符 |
| `MCP_ALLOWED_HOSTS` | 无 | 逗号分隔的 Host 白名单 |

## Docker

复制环境变量示例并替换密钥:

```powershell
Copy-Item .env.example .env
docker compose up --build
```

Compose 只把端口映射到本机 `127.0.0.1:3100`。正式部署时可以由 Caddy、Nginx 或其他网关代理 `/mcp`,同时设置实际域名对应的 `MCP_ALLOWED_HOSTS`。

## MCP Client 示例

使用官方 TypeScript SDK 连接:

```ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const client = new Client({ name: "example-host", version: "1.0.0" });
const transport = new StreamableHTTPClientTransport(
  new URL("http://127.0.0.1:3100/mcp"),
  {
    requestInit: {
      headers: {
        Authorization: `Bearer ${process.env.MCP_API_KEY}`,
      },
    },
  },
);

await client.connect(transport);
const tools = await client.listTools();
console.log(tools.tools.map((tool) => tool.name));
await transport.close();
```

## 开发检查

```powershell
pnpm check
```

检查内容包括 ESLint、TypeScript、领域单元测试、真实 Streamable HTTP MCP Client 集成测试和生产构建。

## 目录结构

```text
src/
├─ index.ts                         # 进程启动与优雅关闭
├─ app.ts                           # HTTP 路由与无会话 MCP transport
├─ config.ts                        # 环境变量解析
├─ http/
│  └─ auth.ts                       # Bearer Token 校验
├─ server/
│  └─ create-fortune-server.ts      # 每个请求创建独立 McpServer
├─ tools/
│  ├─ register-bazi-tool.ts
│  ├─ register-almanac-tool.ts
│  ├─ register-tarot-tool.ts
│  └─ tool-result.ts
└─ domain/
   ├─ date.ts
   └─ tarot/
      ├─ cards.ts                   # 完整 78 张牌数据
      └─ draw.ts                    # Fisher–Yates 与正逆位抽取
```