😃
MCPってなんぞやって疑問を解決できる
🚀 MCP/MCPO/OpenWebUI/Zen MCP を“社内導入”目線で徹底整理(実装例つき)
「OpenWebUIはUIって言うけど、もうスーパーUIでは?」
「MCPのホスト/クライアント/サーバ、MCPOを噛ませた接続は?」
——概念の整理から、実際に動く Compose まで一気通貫でまとめます。
🧭 この記事でわかること
- MCPの三層(ホスト/クライアント/サーバ)の正しい頭の置き方
- OpenWebUIが“UI以上”に担っていること(LLM接続・履歴・RAG・OpenAPIツール連携)
- MCPOを噛ませて OpenWebUI →(OpenAPI)→ MCPサーバ群 を使う構成
- Zen MCP(多機能ツール箱)と Fetch MCP(汎用RESTクライアント)を一括でOpenWebUIに接続
- 本番運用の勘所(SSE常駐・ヘルスチェック・鍵・権限・監査)
📚 用語の辞典(最短で腹落ちする定義)
MCP(Model Context Protocol)
-
目的:LLMが外部ツールを“標準手順”で見つけて呼び出すためのプロトコル
-
三層:
- ホスト(Host):アプリ側の“司令塔”。複数のクライアントを管理(例:Claude Desktop 等)
- クライアント(Client):1対1でサーバに接続するセッション単位
- サーバ(Server):ツール/リソース/プロンプトの提供者(例:Zen MCP / Fetch MCP / 社内独自MCP)
OpenWebUI(“スーパーUI”)
-
名称は“UI”だが、実際は UI+アプリ基盤:
- LLM接続(OpenAI/ Azure / OpenRouter / LM Studio / Ollama / LocalAI / vLLM…)
- チャット履歴DB(SQLite/Postgres)
- 知識ベース(RAG;VectorDB統合)
- OpenAPI準拠ツールの読み込み・実行(※MCPそのものは直接は話せない)
MCPO(MCP→OpenAPI Proxy)
- 役割:MCPサーバ群をOpenAPI化して外部アプリから使えるようにする“ゲートウェイ”
- 中身:MCPOは実質 MCPホストの役。内部でサーバごとにMCPクライアントを起動(1対1)して接続し、それらをOpenAPIとしてエクスポート
- ポイント:ツール選定の意思決定はしない(どのエンドポイントを叩くかは上位アプリ=OpenWebUI側の役割)
Zen MCP(MCPサーバ)
-
多機能ツール箱:
planner / codereview / debug / tracer / testgen / … - バックエンドLLMはOpenAIでもローカルでもOK
- 社内向けに“DB/ファイル等の独自ツール”を増やしていける
Fetch MCP(MCPサーバ)
- REST API呼び出し特化:GitHub/Backlog/Jira/Slack/自社APIなど、HTTPで叩けるなら広く扱える
🧩 全体構成(アーキテクチャ図)
[人間/ブラウザ]
│
▼ (OpenAPI)
OpenWebUI ─────────→ MCPO(OpenAPIサーバ + MCPホスト)
├─ (MCPクライアントA) → Zen MCP(MCPサーバ:社内ツール/多機能)
└─ (MCPクライアントB) → Fetch MCP(MCPサーバ:REST汎用)
- 会話生成は OpenWebUI 側の設定LLM(OpenAIやローカル)が担当
- ツール実行は OpenWebUI →(OpenAPI呼び出し)→ MCPO →(MCP)→ 各サーバ
🛠️ 実装:Docker Compose 一式
スタック:OpenWebUI + OpenAI(クラウド) + MCPO + Zen MCP + Fetch MCP
(ローカルLLMに切り替えたい場合の注記も併記)
📁 ディレクトリ構成(例)
project-root/
├─ docker-compose.yml
├─ .env
├─ mcpo/
│ └─ config.json
└─ zenmcp/
└─ Dockerfile
1) .env(APIキーや基本設定)
# === LLM: OpenAI を使う場合 ===
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx
# OpenWebUIが叩く先(LM Studio/LocalAI等のOpenAI互換に切替も可能)
OPENAI_API_BASE_URL=https://api.openai.com/v1
# === MCPO ===
MCPO_API_KEY=mcpo-secret # OpenWebUI→MCPO の認証ヘッダに使う
# === Zen MCP(任意)===
DEFAULT_MODEL=gpt-4o-mini # Zen MCP側の既定モデル
LOG_LEVEL=INFO
ローカルLLMにしたいときは
OPENAI_API_BASE_URLを
http://lmstudio:1234/v1やhttp://localai:8080/v1に差し替えればOK。
2) mcpo/config.json(複数MCPサーバの集約設定)
{
"mcpServers": {
"zenmcp": {
"type": "sse",
"url": "http://zenmcp:3001/sse"
},
"fetch": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-fetch"]
}
},
"security": {
"apiKey": "${MCPO_API_KEY}"
}
}
-
zenmcpは SSE/HTTP で待ち受ける想定 -
fetchは stdio で子プロセス起動(Nodeが必要) - MCPOはこの定義を読み込み、
/zenmcpと/fetch配下にOpenAPIを公開
3) zenmcp/Dockerfile(SSE/HTTP 常駐で起動)
FROM python:3.11-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
git curl ca-certificates && rm -rf /var/lib/apt/lists/*
# 依存解決を速めたいなら uv を採用(任意)
RUN pip install --no-cache-dir uv
WORKDIR /app
# 公式リポジトリを取得(固定タグにする運用推奨)
RUN git clone https://github.com/BeehiveInnovations/zen-mcp-server.git .
# 依存インストール
RUN uv pip install --system -r requirements.txt
EXPOSE 3001
ENV PORT=3001
# SSE/HTTP モードで常駐(実装に合わせて調整)
CMD ["bash","-lc","python -u server.py --sse --host 0.0.0.0 --port 3001"]
重要:MCPをDocker常駐させるなら stdioではなくSSE/HTTP で立てるのが安定(stdioは“接続が切れたら終了”特性)。
4) docker-compose.yml
services:
openwebui:
image: ghcr.io/open-webui/open-webui:latest
container_name: openwebui
restart: unless-stopped
ports: ["3000:8080"]
environment:
OPENAI_API_KEY: ${OPENAI_API_KEY}
OPENAI_API_BASE_URL: ${OPENAI_API_BASE_URL}
ENABLE_PERSISTENT_CONFIG: "true"
depends_on: [mcpo]
volumes:
- openwebui_data:/app/backend/data
# Zen MCP(SSEで待受)
zenmcp:
build:
context: ./zenmcp
dockerfile: Dockerfile
container_name: zenmcp
restart: unless-stopped
ports: ["3001:3001"]
environment:
OPENAI_API_KEY: ${OPENAI_API_KEY}
DEFAULT_MODEL: ${DEFAULT_MODEL}
LOG_LEVEL: ${LOG_LEVEL}
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3001/healthz"]
interval: 20s
timeout: 3s
retries: 5
# MCPO(MCP→OpenAPI 変換 & 集約)
mcpo:
image: ghcr.io/open-webui/mcpo:main
container_name: mcpo
restart: unless-stopped
ports: ["8000:8000"]
environment:
MCPO_API_KEY: ${MCPO_API_KEY}
volumes:
- ./mcpo/config.json:/app/config.json:ro
command: >
--port 8000
--api-key ${MCPO_API_KEY}
--config /app/config.json
depends_on: [zenmcp]
# Fetch MCP を“stdioサーバ”として子プロセス起動させるなら
# MCPOから起動するので、別コンテナは不要。ただし Node が必要なら
# 以下のようなランタイムを用意して MCPO に /usr/local/bin/npx を提供する方法もあり。
node-runtime:
image: node:20-alpine
container_name: node-runtime
command: ["sh","-lc","sleep infinity"]
# MCPOコンテナに npx を提供したい場合は、ボリューム共有や単一コンテナ化を検討
# 本例では単に“参考”として掲載(必須ではない)
volumes:
openwebui_data:
補足
fetchを MCPOが子プロセス起動するなら、MCPOコンテナ内にnpxが必要。mcpoのDockerfileを自作しnodeを入れる or--commandを別の方法に変える、など運用に合わせて調整してね。- あるいは Fetch MCPを独立コンテナで立て、SSE/HTTP で公開して MCPOから
type: "sse"で接続する構成でもOK。
5) 起動手順
# ビルド & 起動
docker compose up -d --build
# 動作確認
docker compose ps
docker logs -f zenmcp
curl -s http://localhost:8000/docs | head # MCPOのOpenAPIが生きてるか確認
OpenWebUIでの設定
-
Settings → Tools → Manage Tool Servers → Add Connection- URL:
http://mcpo:8000(Compose内ならサービス名、ホストなら http://localhost:8000) - Header:
Authorization: Bearer <MCPO_API_KEY>
- URL:
-
ツール一覧(
zenmcp/fetch)が同期 → 有効化して利用開始
🔒 本番運用の勘所
- SSE常駐:MCPサーバは SSE/HTTP で常駐。stdioは“接続が切れると終了”なのでDocker常駐に不向き
- レートと鍵:OpenWebUIの会話LLMとZen MCPの内部LLMを同じAPIキーにするとレート衝突しやすい(429)。用途別キーやバックオフを
- 権限分離:OpenWebUI(社内全体向けUI)に出すツールは読み取り中心+限定導線。IDE向けの強権ツールはZen MCP側で
- 監査ログ:ツールAPI(DB/FSなど)で “誰が何にアクセスしたか”を必ずロギング。後追い可能に
- ネットワーク:全サービスを社内VPC/セグメントに閉じる。MCPOにはAPIキー必須
- OpenWebUIのPersistentConfig:一部環境変数は初回起動時に内部DBへ固定。設定変更はUIから or 再初期化で
🧪 トラブルシュート早見表
-
zenmcp が再起動ループ:SSEじゃなくstdio起動になってない?
server.py --sse --host 0.0.0.0 --port 3001を確認 -
MCPO
/docsが404:--configのパス・フォーマット、mcpServersのtype/url/commandを再確認 - OpenWebUIからツールが見えない:Tool ServerのURL/認証ヘッダ(Bearer)ミスが多い
- 429/RateLimit:OpenWebUIとZen MCPで別APIキーに分ける or モデル負荷を調整
- CORS/ネットワーク:社内DNS名/サービス名で解決できているか、ポート開放/Firewallもチェック
🧷 付録:ローカルLLMに切り替えるとき
-
.envのOPENAI_API_BASE_URLをローカルのOpenAI互換に変更(例:http://lmstudio:1234/v1) - 追加で
lmstudioコンテナを起動し、OpenWebUIはそのURLを叩く - Zen MCP 側も同じベースURL/キーに切り替えて二系統のLLMを揃えると迷いが少ない
(会話LLM=OpenWebUI、ツール内部LLM=Zen MCP、で別モデルにして分離運用もアリ)
✅ まとめ(要点だけ)
- OpenWebUI は“UI以上”の スーパーUI(LLM接続・履歴管理・OpenAPIツール連携)
- MCP は ホスト/クライアント(1対1)/サーバ の三層で考える
- MCPO を噛ませると OpenWebUI→(OpenAPI)→ MCPサーバ群 が実現
- Zen MCP(多機能ツール)+ Fetch MCP(REST汎用)をMCPOで集約し、OpenWebUIから一元利用
- SSE常駐/鍵/権限/監査 を抑えれば、社内運用も十分実用的
Discussion