Skip to main content
Glama
return-billing-mcp-server

return-billing-mcp-server

by GT5041

return-billing-mcp-server

CCAR-F 認定試験の学習対策として作成した、返品・請求問い合わせ振り分けサーバーの MCP (Model Context Protocol) サーバー実装です。ローカル JSON を「注文DB(+請求データ)」に 見立て、lookup_order / check_return_eligibility / process_return / get_billing_status / escalate_to_human の5つのツールを提供します。

会話フロー(ユーザーID確認 → 返品/請求/それ以外への振り分け → オペレーター対応の ターン数制御)そのものは MCP ツールの範囲外(呼び出し側 LLM エージェントの役割)のため、 ORCHESTRATION.md に呼び出し側へ設定するシステムプロンプト例を まとめています。

セットアップ

npm install
npm run build

起動(stdio)

npm start

デモ用のダミー注文データは 2026年8月/7月/6月の1日に登録されている想定のため、 判定結果を本タスク記載の想定どおりに再現するには MCP_TODAY で「今日」を固定してください。

MCP_TODAY=2026-08-11 npm start

MCP_TODAY を指定しない場合は実際のシステム時刻が使われます。

Claude Desktop などからの利用例

{
  "mcpServers": {
    "return-billing": {
      "command": "node",
      "args": ["/absolute/path/to/return-billing-mcp-server/dist/index.js"],
      "env": {
        "MCP_TODAY": "2026-08-11"
      }
    }
  }
}

起動(Streamable HTTP・外部公開用)

stdio(ローカルプロセス起動)に加えて、通常のHTTPサーバーとして起動できる Streamable HTTP transport 版のエントリポイントも用意しています。これを使うと、 https://your-domain/mcp のような URLをエンドポイントに MCPクライアントから 接続できます。

MCP_HTTP_TOKEN=<任意の秘密トークン> MCP_TODAY=2026-08-11 npm run start:http
  • MCP_HTTP_TOKEN は必須です。未設定の場合、認証なしでの誤公開を防ぐため 起動時にエラーで終了します。クライアント側は Authorization: Bearer <token> ヘッダーを付与してリクエストしてください。

  • PORT(既定 3000)・HOST(既定 0.0.0.0)で待受先を変更できます。

  • GET /healthz は認証不要のヘルスチェック用エンドポイントです(デプロイ先の ロードバランサ等からの疎通確認を想定)。

  • セッション状態(mcp-session-id ごとの McpServer/Transport ペア)はプロセス内 メモリで管理しています。複数インスタンスへスケールする場合は、ロードバランサの セッションアフィニティ設定、または外部ストアへの置き換えが必要です。

注意: このリポジトリのコードはHTTPサーバーとして起動できるようにするところ までが範囲です。実際に「外部からアクセス可能なURL」にするには、どこかのサーバー・ PaaS(自前VM、Fly.io、Render 等)にこのプロセスをデプロイし、ドメインとTLS (HTTPS)を用意する必要があります。ローカルで一時的に外部公開して試したいだけの 場合は、ngrok http 3000 や Cloudflare Tunnel などのトンネリングツールで npm run dev:http のプロセスを一時公開する方法が手軽です。

Claude Desktop などからの利用例(HTTP)

{
  "mcpServers": {
    "return-billing-http": {
      "url": "https://your-domain.example.com/mcp",
      "headers": {
        "Authorization": "Bearer <MCP_HTTP_TOKENと同じ値>"
      }
    }
  }
}

テスト

@modelcontextprotocol/sdk の Client / StdioClientTransport を使い、実際に サーバープロセスを起動して5ツール全てを検証する統合テストを用意しています。

npm test

HTTP transport 版の簡易疎通確認用スクリプトも用意しています (サーバーを別途起動した状態で実行してください)。

MCP_HTTP_TOKEN=test-secret-token PORT=3917 npm run start:http &
node tests/http.smoke.mjs http://127.0.0.1:3917/mcp test-secret-token

Related MCP server: Support Ticket Triage MCP

ディレクトリ構成

data/orders.json      注文DB(ユーザー・製品・注文+請求ステータスのダミーデータ)
src/db.ts              JSON読み込み・検索・返品期限計算などのデータアクセス層
src/errors.ts           構造化エラー(AppError / エラー分類)
src/returnEligibility.ts 返品可否判定ロジック(check_return_eligibility / process_return共通)
src/escalation.ts        エスカレーション・セッションのターン数管理
src/mail.ts               返品通知メール送信のシミュレーション(メモリ上にログ)
src/tools/*.ts            5つのMCPツールの実装
src/server.ts             McpServer 定義・起動(stdio/HTTP共通)
src/index.ts               エントリポイント(stdio)
src/httpServer.ts           エントリポイント(Streamable HTTP・Bearer認証付き)
tests/integration.test.mjs 統合テスト(stdio)
tests/http.smoke.mjs        HTTP transport の簡易疎通確認スクリプト
ORCHESTRATION.md            呼び出し側エージェント向けシステムプロンプト例

ダミーデータ

ユーザー

ユーザーID (メールアドレス)

氏名

Ami.Muratsubaki@protiviti.com

Ami Muratsubaki

goshi.tanaka@protiviti.com

Goshi Tanaka

takeharu.mokudai@protiviti.com

Takeharu Mokudai

amigo.murata@protiviti.com

Amigo Murata

takehiro.mokujai@protiviti.com

Mokujyai Takehiro

lookup_order / get_billing_status はユーザーIDを大文字小文字を無視して完全一致で照合します (似た別アドレスへの誤入力を検出できるよう、あえて紛らわしいアドレスを含めています)。

製品

  • コカ・コーラ(500ml) 12本入りパック(¥1,800)

  • 爽健美茶(350ml) 24本入りパック(¥2,400)

  • 吉野家牛丼お得パック 18個入り(¥5,400)

注文

各ユーザーにつき、2026/8/1・2026/7/1・2026/6/1 の3件の注文を用意し(data/orders.json 生成元: scripts/gen-data.mjs)、製品と請求ステータス(未払い/支払い済み)を組み合わせて バリエーションを持たせています。MCP_TODAY=2026-08-11 で実行した場合:

  • 2026/8/1 の注文 → 注文日から1ヶ月以内のため返品可能

  • 2026/7/1・2026/6/1 の注文 → 1ヶ月を超過しているため返品不可

ツール仕様

1. lookup_order

ユーザーIDから注文一覧を取得する。問い合わせ対応の最初のステップ(本人確認)として使用。

  • 入力: { user_id: string }

  • 成功時出力: { user: {user_id, name}, order_count, orders: [{order_id, product_name, quantity, unit_price_jpy, order_date, billing_status, returned}] }

  • エラー: USER_NOT_FOUND

2. check_return_eligibility

注文IDを指定し、返品可否(注文日から1ヶ月以内か)を判定する。

  • 入力: { order_id: string }

  • 出力: { order_id, order_date, deadline_date, days_elapsed, already_returned, eligible, reason: "OK"|"EXPIRED"|"ALREADY_RETURNED", message }

  • エラー: ORDER_NOT_FOUND

期限切れ・返品済みは「エラー」ではなく eligible: false の正常応答として返す設計です (下記「エラー応答の分類」を参照)。

3. process_return

返品可能な注文について、返品理由を受け取り返品を確定する。処理後、ユーザーの登録 メールアドレス宛に返品受付通知メールを送信する(本サンプルでは実送信せず、内容を そのままレスポンスに含めることでシミュレートしています)。

  • 入力: { order_id: string, reason: string }

  • 成功時出力: { return_id, order_id, reason, processed_at, notification: {to, subject, body, sent_at} }

  • エラー: ORDER_NOT_FOUND, RETURN_NOT_ELIGIBLE(details.reason が EXPIRED または ALREADY_RETURNED)

check_return_eligibility を経由せず直接呼ばれた場合に備え、サーバー側でも 返品可否を再検証してから処理します。

4. get_billing_status

ユーザーの全注文について請求ステータス一覧を取得する。未払いの注文には振込先情報が 付与される。

  • 入力: { user_id: string }

  • 出力: { user: {user_id, name}, unpaid_count, billing: [{order_id, product_name, order_date, amount_jpy, billing_status, payment_instructions}] }

  • エラー: USER_NOT_FOUND

payment_instructions(未払いの場合のみ): テストサイトのため固定のダミー口座を返します。

XX株式会社 〇〇銀行 ××支店 普通 XXXXXXX

5. escalate_to_human

返品・請求のいずれにも該当しない問い合わせを有人オペレーターに引き継ぐ際の、 会話セッションのターン数管理を行う。オペレーターの回答文そのものは生成しない (MCP ツールは LLM を呼び出せないため、呼び出し側エージェントが一般的なオペレーターとして 応答内容を作成する前提)。

  • 入力: { session_id: string, user_message: string }

  • 出力: { session_id, turn_count, status: "active"|"confirm_close"|"force_closed", guidance, received_message }

  • エラー: SESSION_CLOSED(force_closed 後に同じ session_id で再度呼び出した場合)

ターン数のルール:

turn_count

status

呼び出し側エージェントの振る舞い

1〜4

active

オペレーターとして回答する

5

confirm_close

回答した上で、終了してよいか確認する

6〜9

active

継続を選んだ場合、通常どおり応答する

10

force_closed

強制終了。新しい問い合わせの起票を依頼する

11以降

—

SESSION_CLOSED エラー

エラー応答の分類と構造化

すべてのツールは、例外発生時に生の例外を投げるのではなく、isError: true とともに 以下の構造化された JSON を返します(src/errors.ts)。

{
  "error": {
    "code": "USER_NOT_FOUND",
    "category": "NOT_FOUND",
    "message": "ユーザーID「...」に該当する顧客情報が見つかりませんでした。...",
    "details": { "user_id": "..." }
  }
}

category

意味

該当する code

NOT_FOUND

対象データが存在しない

USER_NOT_FOUND, ORDER_NOT_FOUND

VALIDATION

入力値が不正

INVALID_INPUT

BUSINESS_RULE

業務ルール上、要求を実行できない

RETURN_NOT_ELIGIBLE

STATE_CONFLICT

現在の状態と矛盾する要求

SESSION_CLOSED

INTERNAL

想定外の内部エラー

INTERNAL_ERROR

設計上の方針: 「返品期限切れ」「返品済み」のようにビジネス上ありうる結果は check_return_eligibility の正常応答(eligible: false + reason)として扱い、 「そもそも処理を実行できない異常系」(対象が存在しない、状態が矛盾している等)のみを 構造化エラーとして分離しています。これにより、呼び出し側エージェントは isError の有無だけで「例外的な失敗」と「業務上の正常な分岐」を区別できます。

Available Tools

5 tools
check_return_eligibility返品可否判定A

注文IDを指定し、注文日から1ヶ月以内かどうかに基づいて返品可能かどうかを判定する。返品期限超過・返品済みの場合も「エラー」ではなく eligible=false の正常応答として返す。

Inputs: order_id (required).

escalate_to_human有人オペレーターへのエスカレーションA

返品にも請求にも該当しない問い合わせについて、有人オペレーターとの会話セッションを管理する。ユーザーの発言1回ごとに呼び出すこと。ターン数をサーバー側で管理し、5ターンで終了確認、10ターンで強制終了(別問い合わせの起票を依頼)という状態を status フィールドで返す。オペレーターの回答文自体はこのツールでは生成しないため、呼び出し側のエージェントが一般的なオペレーターとして応答内容を作成すること。

Inputs: session_id (required), user_message (required).

get_billing_status請求状況照会A

ユーザーID(メールアドレス)から、そのユーザーの全注文の請求ステータス(未払い/支払い済み)一覧を取得する。未払いの注文には振込先情報(payment_instructions)が付与される。

Inputs: user_id (required).

lookup_order注文照会A

ユーザーID(メールアドレス)から、そのユーザーの注文一覧(商品名・数量・注文日・請求ステータス)を取得する。問い合わせ対応の最初のステップとして、ユーザー本人確認を側ねて呼び出す。

Inputs: user_id (required).

process_return返品処理実行A

check_return_eligibility で返品可能と判定された注文について、返品理由を受け取り返品処理を確定する。処理完了後、ユーザーの登録メールアドレス宛てに返品受付通知メールを送信する(本サンプルでは送信をシミュレートする)。返品不可の注文に対して呼び出された場合は RETURN_NOT_ELIGIBLE エラーを返す。

Inputs: reason (required), order_id (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.2/5.0

    Scored across 5 tools

    Disambiguation4/5

    Each tool has a generally distinct purpose, but lookup_order and get_billing_status both return order/billing information and could be confused. The descriptions clarify that lookup_order is for order details while get_billing_status focuses on billing status and payment instructions, but some overlap remains.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun pattern with snake_case (lookup_order, check_return_eligibility, process_return, get_billing_status, escalate_to_human). The verbs vary but the pattern is uniform, making it easy to predict tool names.

    Tool Count5/5

    Five tools is well-scoped for a return/billing MCP server, covering the main customer service actions without unnecessary bloat. Each tool earns its place, and the count is within the ideal 3-15 range.

    Completeness4/5

    The tool surface covers the core return and billing workflows: order lookup, eligibility check, return processing, billing status, and escalation. Minor gaps exist, such as no tool to view or update a return after processing, but the main user journey is complete.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      An MCP server that mocks payments, third-party API responses, and test data to enable QA flows for donation, checkout, SIP, and subscription pages without depending on a live gateway.
      -
    • A
      license
      Not graded
      quality
      B
      maintenance
      MCP server for commerce-operations self-service. Lets an AI agent look up order details and search orders without needing developer or SQL access.
      15 npm
      MIT