npm package: @lmcl/ailo-mcp-sdk
Description: Ailo MCP SDK - 通道通过 MCP 注册发送消息能力，用于开发感知通道
Latest version: 0.2.5
Deprecated: This package is no longer maintained

# @lmcl/ailo-mcp-sdk

**AILO 通道与工具开发 SDK** —— 在标准 MCP 基础上，提供**双向通道**能力：既能接收平台消息推送给 AILO，也能让 AILO 通过工具向平台发送消息。

```bash
npm install @lmcl/ailo-mcp-sdk
```

---

## 核心概念

| 概念 | 说明 |
|------|------|
| **MCP** | Model Context Protocol，标准工具协议。AILO 通过 stdio 调用你的工具，你返回结果 |
| **通道** | 感知通道。平台（飞书、Telegram 等）有消息时推送给 AILO，AILO 通过工具发消息回平台 |
| **双向** | 通道 = MCP 工具（出站）+ WebSocket 推送（入站）。本 SDK 将二者统一 |

**通道名**：就是 MCP 名。

---

## 快速开始

### 场景一：纯工具（AILO 调用你，你返回结果）

```typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { runMcp } from "@lmcl/ailo-mcp-sdk";

const server = new McpServer({ name: "my-tools", version: "1.0.0" });

server.registerTool(
  "get_weather",
  { description: "查询天气", inputSchema: { city: z.string() } },
  async ({ city }) => ({ content: [{ type: "text", text: `${city}: 晴 25°C` }] })
);

runMcp(server);
```

### 场景二：双向通道（接收平台消息 + 工具发消息）

```typescript
import type { ChannelHandler, ChannelContext } from "@lmcl/ailo-mcp-sdk";
import { runMcpChannel, textPart } from "@lmcl/ailo-mcp-sdk";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

class MyHandler implements ChannelHandler {
  private ctx!: ChannelContext;

  async start(ctx: ChannelContext) {
    this.ctx = ctx;
    // 启动平台连接（WebSocket / long polling 等）
    // 收到消息时：await ctx.accept({ content: [textPart("...")], contextTags })
    // 读写持久化数据：await ctx.storage.getData("key") / setData / deleteData
  }

  async stop() {
    // 断开平台连接
  }
}

const handler = new MyHandler();
const server = new McpServer({ name: "channel:my-platform", version: "1.0.0" });
// 注册出站工具...

runMcpChannel({
  handler,
  mcpServer: server,
  displayName: "我的平台",
  buildChannelPrompt: () => "本通道规则说明",
});
```

---

## 重要：stdio 与日志

MCP 使用 **stdio** 传输，**stdout 只能输出 JSON-RPC 消息**。任何 `console.log`、第三方库日志写入 stdout 都会破坏协议，导致解析错误。

**本 SDK 已内置保护**：自动拦截 stdout，仅 JSON-RPC 转发到 stdout，其余重定向到 stderr。你可以自由使用 `console.log`、`console.info`、`console.debug`，以及会打日志的第三方库，无需额外处理。

**入口顺序**：请将 `import { runMcpChannel } from "@lmcl/ailo-mcp-sdk"` 作为入口文件的**首个 import**，确保保护在 dotenv、平台 SDK 等之前生效。

---

## ChannelHandler 接口

通道需实现 `ChannelHandler`，SDK 保证 `start(ctx)` 调用时 `ctx` 已就绪：

| 方法 | 说明 |
|------|------|
| `start(ctx)` | 启动平台连接。`ctx.accept(msg)` 投递消息到 AILO，`ctx.storage` 读写持久化数据 |
| `stop()` | 优雅停止。SDK 在 SIGINT/SIGTERM 时调用 |

### ChannelContext

| 字段 | 类型 | 说明 |
|------|------|------|
| `accept(msg)` | `(msg: ChannelMessage) => Promise<void>` | 投递入站消息到 AILO。SDK 内部做空消息过滤 |
| `storage` | `ChannelStorage` | 通道级 KV 存储（`getData`/`setData`/`deleteData`），数据持久化在 AILO 侧 |

### ChannelMessage（与 Ailo Message 结构对齐）

| 字段 | 类型 | 说明 |
|------|------|------|
| `content` | ContentPart[] | 内容数组，按序：text part 与 media part |
| `contextTags` | ContextTag[] | 时空场标签，必须 |
| `requiresResponse` | boolean? | 覆盖通道级 defaultRequiresResponse |

辅助：`textPart(text)`、`mediaPart(type, media)` 用于构造 content。

---

## 配置项（runMcpChannel）

| 字段 | 必填 | 说明 |
|------|------|------|
| `handler` | 是 | ChannelHandler 实例 |
| `mcpServer` | 是 | MCP Server 实例（需注册工具，AILO 才能调用） |
| `displayName` | 是 | 中文通道显示名（如 "飞书"） |
| `buildChannelPrompt` | 否 | 通道规则提示词，connect 时注册 |
| `defaultRequiresResponse` | 否 | 默认 true（主动信号） |
| `channelName` | 否 | 不传则从 `AILO_MCP_NAME` 读取 |

---

## 环境变量

由 AILO 主程序在拉起 MCP 时注入，通道通常无需手动配置：

| 变量 | 说明 |
|------|------|
| `AILO_WS_URL` | AILO WebSocket 网关地址 |
| `AILO_TOKEN` | 认证 Token |
| `AILO_MCP_NAME` | MCP 名（即通道名） |
| `AILO_MCP_WORKDIR` | MCP 专属工作目录（绝对路径） |

**获取工作目录**：`import { getWorkDir } from "@lmcl/ailo-mcp-sdk"`，`getWorkDir()` 返回 `AILO_MCP_WORKDIR` 或 `null`。

---

## 类型与导出

```typescript
import {
  runMcp,
  runMcpChannel,
  getWorkDir,
  AiloClient,
  tagValue,
  defaultBuildChannelPrompt,
} from "@lmcl/ailo-mcp-sdk";
import type {
  ChannelContext,
  ChannelHandler,
  ChannelMessage,
  ChannelStorage,
  ContentPart,
  ContextTag,
  McpChannelConfig,
  AiloClientConfig,
} from "@lmcl/ailo-mcp-sdk";
```

---

## AiloClient 特性

- 指数退避自动重连（1s → 2s → 4s → ... → 60s max）
- 请求超时（30s，防止 Promise 泄漏）
- WebSocket 心跳（ping/pong，30s 间隔，10s 超时检测半死连接）
- 断线时自动清理所有 pending 请求

---

## 依赖

- Node.js >= 18
- `@modelcontextprotocol/sdk` ^1.26.0
- `ws` ^8.18.0