LINE公式のMCPサーバーを使ってみた話

# LINE公式のMCPサーバーを使ってみた話

こんにちは。今回は [LINEのMCPサーバー](https://github.com/line/line-bot-mcp-server) を使ってみた記録を共有します。

## 🎯 この記事でやること

- DBと連携して公式アカウントと繋がっているユーザーの情報を取得
- ユーザーに対してメッセージを送信
- 【補足】`replyToken` がある場合はリプライ優先に切り替える


## 1. 🚀 LINE公式のMCPの確認


GitHubで公開されている [`line-bot-mcp-server`](https://github.com/line/line-bot-mcp-server) に含まれるサンプルをそのまま動かすと、  
以下のような基本機能がすぐ使えます。

### 📦 初期状態でできること

- 環境変数 `LINE_USER_ID` に指定したユーザーに対して**プッシュメッセージを送信可能**
- 同様に、そのユーザーの **ユーザー情報（プロフィール）を取得可能**
- `flexMessage` も簡単に送信できる

例えば、Claude Desktopに自然言語でお願いすると、以下のようなメッセージ送信ができます（作るだけじゃなくて本当に送ってくれる）

```json
{
  "type": "flex",
  "altText": "注文が入りました！",
  "contents": {
    "type": "bubble",
    "body": {
      "type": "box",
      "layout": "vertical",
      "contents": [
        { "type": "text", "text": "注文が入りました！", "weight": "bold", "size": "xl" }
      ]
    }
  }
}
```


## 2. DB連携で任意のユーザーに送信できるようにした

デフォルトでは環境変数で指定したユーザーIDに対してしか処理ができない仕様になっています。

```typescript
const userIdSchema = z
  .string()
  .default(destinationId)
  .describe(
    "The user ID to receive a message. Defaults to DESTINATION_USER_ID.",
  );
```

他の人にも送るためにはその人のuserIdが必要になります。
そのため、以下のフローを取りました。

### 🔁 実行したフロー

1. 公式アカウントからの WebhookEvent を受け取るための API サーバーを作成

2. API サーバーから DBへ userId を含むイベント履歴を保存

3. DB を読み取る MCP サーバーを作成

4. DB 用 MCP サーバーと LINE 公式の MCP サーバーを連携

これにより、アクションのあったメンバー全員に対してメッセージを送ることができるようになりました。

![MCPサーバー関連システム.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628974/2d2d9ec5-bf1d-4fe7-8000-f1280e3d4f3c.jpeg)

## 3. 使ってみた

まず公式アカウントをフォローした履歴を見てもらいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628974/c46aca7c-03c0-4c7d-a022-20248792bc84.png)

これらのユーザーに対してプロフィールを取得してもらいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628974/82ca4e22-de92-4bcd-a57d-c673f3b28cd0.png)

次にメッセージの送信です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628974/0995e894-5307-4eca-aa8e-152a5815e84f.png)

すぐにこんなメッセージが届きました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628974/057e6fde-8e30-4aa5-b0b1-c18d326f3521.png)


## 補足. 💬 replyToken があればリプライを優先するようにした

LINE Messaging API の仕様では、ユーザーのアクションから20分以内だと、そのアクションに対するリプライメッセージを送信できます。（プッシュメッセージよりお財布に優しい）

そのため、デフォルトのMCPサーバーにリプライメッセージ送信用のツールを一つ追加しました。
「リプライ送れそうなら送ってみて」とかお願いすると、できる場合は送るし、できないときはプッシュメッセージに切り替えてくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628974/376fe043-26ae-4b70-aa28-50feaa68db53.png)


```typescript

// 引数用のスキーマ
const replyMessageSchema = z
  .object({
    flexMessage: flexMessageSchema.optional(),
    textMessage: textMessageSchema.optional(),
  })
  .describe(
    "A message object that can be either a flex message or a text message. " +
      "when use this schema, flexMessage or textMessage is required",
  );
const replyTokenSchema = z
  .string()
  .describe("The token to reply to the user.");

// 返信用ツール
server.tool(
  "reply_text_message",
  "Reply to a user with a simple text message via LINE. Use this for sending plain text messages without formatting.",
  {
    replyToken: replyTokenSchema,
    message: replyMessageSchema,
  },
  async ({ replyToken, message }) => {
    if (!replyToken) {
      return createErrorResponse("Error: replyToken is required.");
    }
    const msg = message.flexMessage ?? message.textMessage;
    if (!msg) {
      return createErrorResponse("Error: message is required.");
    }
    try {
      const response = await messagingApiClient.replyMessage({
        replyToken,
        messages: [msg as unknown as line.messagingApi.Message],
      });
      return createSuccessResponse(response);
    } catch (error) {
      return createErrorResponse(`Failed to reply message: ${error.message}`);
    }
  },
);
```


## 📝 最後に

色々便利だけど、使いこなせていない感。何かもっとこんなことすると面白いというアイデア思いつきたいなと思っています。

あと、Webhookイベントを綺麗に取得sるAPIサーバーの整備をしたけど、そっちの方もすごく便利だなと思いました。GW中にそれの記事書いてみようかな。