WebAPIのMCPサーバーを自作する【Cline+Docker】

IT・プログラミング

今回は、既存APIをMCPサーバー化する方法を紹介します。
有名なAPI等はすでに多くのMCPサーバーが用意されていますが、まだMCPサーバーが存在していなかったり、自作APIをMCPサーバーに登録して、LLMが使えるようにしたいというような場合もあるので、その方法を紹介します。

開発環境と開発内容

Dockerを使ってuv環境を構築し、PythonベースのMCPサーバーを構築します。
APIとして、WordPressで自作したAPIであるlifetechiaのAPIを使います。

https://lifetechia.com/wp-json/financial/v1/get/

をベースとして、APIキーと企業名などからその企業の財務データを取得できるAPIになります。

API_KEYの取得は以下でユーザー登録すると表示されます。

このAPIをMCPサーバーで使えるようにします。
例えば、「トヨタの財務データ取得して」
とすると

[{'id': '71', 'docID': 'S1001ZP8', 'date': '2014-06-24', 'secCode': '72030', 'filerName': 'トヨタ自動車株式会社', 'EndDate': '2014-04-01', 'sales': '11042163000000.00', 'gross_profit_loss': '2404193000000.00', 'operating_income_loss': '1269004000000.00', 'ordinary_income_loss': '1838450000000.00', 'net_income_loss': '1416810000000.00', 'parent_net_income_loss': None, 'operating_cf': None, 'investing_cf': ...

のようなレスポンスがかえってきます。

FileSystemとも連携して、CSVに出力させると

以下のようにできました。

MCP サーバーの作成

プロジェクトの作成

まず、MCP サーバーのプロジェクトを作成します。

mkdir lifetechia-mcp-server
cd lifetechia-mcp-server

Dockerfile の作成

Dockerfile ファイルを作成し、次のコードを追加します。

FROM python:3.12-slim-bookworm

WORKDIR /app

COPY MCP_financial_data/pyproject.toml ./
COPY MCP_financial_data/lifetechia.py ./
COPY MCP_financial_data/README.md ./

RUN pip install uv
RUN uv venv
RUN . .venv/bin/activate
RUN uv add "mcp[cli]" httpx

CMD ["uv", "run", "lifetechia.py"]

lifetechia.py ファイルの作成

lifetechia.py ファイルを作成し、次のコードを追加します。

import httpx
import os
from urllib.parse import urlencode
from mcp.server.fastmcp import FastMCP


# Initialize FastMCP server
mcp = FastMCP("edinet")

# Constants
API_URL = "https://lifetechia.com/wp-json/financial/v1/get/"
API_KEY = os.environ.get("API_KEY")


async def get_financial_data_from_api(company_name: str = None, sec_code: str = None, doc_id: str = None, start_date: str = None, end_date: str = None) -> str:
    """
    財務データを取得する関数

    Args:
        company_name (str, optional): 企業名
        sec_code (str, optional): 証券コード
        doc_id (str, optional): ドキュメントID
        start_date (str, optional): 開始日(YYYY-MM-DD)
        end_date (str, optional): 終了日(YYYY-MM-DD)

    Returns:
        pd.DataFrame: 取得したデータのデータフレームを文字列として返す
    """
    params = {}

    if not API_KEY:
        raise ValueError("API_KEY environment variable not set")

    if company_name:
        params["company_name"] = company_name

    if sec_code:
        if isinstance(sec_code, list):
            params["sec_code[]"] = sec_code  # リスト形式に対応
        else:
            params["sec_code"] = sec_code

    if doc_id:
        if isinstance(doc_id, list):
            params["doc_id[]"] = doc_id  # リスト形式に対応
        else:
            params["doc_id"] = doc_id

    if start_date:
        params["start_date"] = start_date

    if end_date:
        params["end_date"] = end_date

    # クエリパラメータをエンコード
    query_string = urlencode(params, doseq=True)
    final_url = f"{API_URL}?{query_string}" if params else API_URL  # パラメータがない場合はそのままアクセス

    # APIリクエスト用のヘッダー
    headers = {"X-API-Key": API_KEY}

    async with httpx.AsyncClient() as client:
        # APIリクエストの送信
        response = await client.get(final_url, headers=headers)

        # レスポンスの処理
        if response.status_code == 200:
            data = response.json()
            return data  
        else:
            print(
                "Error:",
                response.status_code,
                response.text.encode().decode("unicode_escape"),
            )
            return API_KEY, response.status_code # 空のデータフレームを返す


@mcp.tool()
async def get_financial_data_by_company_name(company_name: str, start_date: str = None, end_date: str = None) -> str:
    """
    企業名で財務データを取得するツール

    Args:
        company_name (str): 企業名
        start_date (str, optional): 開始日(YYYY-MM-DD)
        end_date (str, optional): 終了日(YYYY-MM-DD)

    Returns:
        str: 取得した財務データを文字列として返す
    """
    data = await get_financial_data_from_api(company_name=company_name, start_date=start_date, end_date=end_date)
    return str(data)


@mcp.tool()
async def get_financial_data_by_sec_code(sec_code: str, start_date: str = None, end_date: str = None) -> str:
    """
    証券コードで財務データを取得するツール

    Args:
        sec_code (str): 証券コード+0 (例: 72030)
        start_date (str, optional): 開始日(YYYY-MM-DD)
        end_date (str, optional): 終了日(YYYY-MM-DD)

    Returns:
        str: 取得した財務データを文字列として返す
    """
    data = await get_financial_data_from_api(sec_code=sec_code, start_date=start_date, end_date=end_date)
    return str(data)


@mcp.tool()
async def get_financial_data_by_doc_id(doc_id: str, start_date: str = None, end_date: str = None) -> str:
    """
    ドキュメントIDで財務データを取得するツール

    Args:
        doc_id (str): ドキュメントID'S100TR7I'など
        start_date (str, optional): 開始日(YYYY-MM-DD)
        end_date (str, optional): 終了日(YYYY-MM-DD)

    Returns:
        str: 取得した財務データを文字列として返す
    """
    data = await get_financial_data_from_api(doc_id=doc_id, start_date=start_date, end_date=end_date)
    return str(data)


if __name__ == "__main__":
    # Initialize and run the server
    mcp.run(transport="stdio")

MCP 設定ファイルへの追加

MCP 設定ファイル (cline_mcp_settings.json) を開き、次の設定を追加します。

{
  "mcpServers": {
    "lifetechia": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "API_KEY",
        "lifetechia-server"
      ],
      "env": {
        "API_KEY": "XXXXXXXXXXXXXXXXXXXXXXX"
      },
      "autoApprove": [],
      "disabled": false,
      "timeout": 60,
      "transportType": "stdio"
    },
  }
}

MCP サーバーの実行

Docker コンテナのビルド

ターミナルで次のコマンドを実行して、Docker コンテナをビルドします。

docker build -t lifetechia-mcp-server .

サーバーの起動

これで、MCP サーバーが起動し、ツールを使用できるようになります。

github

今回の内容は以下のgithubに公開しています。

タイトルとURLをコピーしました