Ollama×MCPでローカルAIエージェントを構築|機密データを外に出さない業務自動化の実装
ローカルLLMだけでは「賢い対話AI」止まりです。実務で価値を出すには、AIに社内システムや業務ツールを呼ばせる必要があります。Anthropicが2024年に提唱したMCP(Model Context Protocol)は、AIと外部ツール/データソースを標準的につなぐオープンプロトコルで、いまや主要なAIエージェント実装の事実上の共通言語になりつつあります。
本記事では、Ollamaで動くGemma 4などのローカルLLMをMCPサーバーと接続し、機密データを外に出さない業務自動化エージェントとして動かす手法を、発展的に解説します。サイズ選定はGemma 4のサイズ別比較、社内仕様へのチューニングはGemma 4をLoRAでファインチューニング|Ollama運用で扱っていますので、本記事は「すでにOllamaで動くモデルがある」前提で読み進めてください。
MCPとは何か(簡潔な整理)
標準化された「AIの周辺機器インターフェース」
MCP(Model Context Protocol)は、AIに対して「ツール(関数)」「リソース(データ)」「プロンプト(テンプレート)」の3種類の能力を提供する標準プロトコルです。サーバーが能力を公開し、クライアント(AIアプリ)がそれを発見して使う構造で、USBのような「差し替え可能なインターフェース」をAIに与えます。
MCPで何が変わるか
- ツール拡張が容易:ファイル操作、DB照会、Slack通知などをMCPサーバーとして書けば、複数のAIから再利用可能
- ベンダーロックインを回避:1つのMCPサーバーを、Claude Desktop、Cursor、Cline、Ollamaなど複数クライアントから使える
- セキュリティの統一:サーバー側で認可・監査を集中管理できる
- OSSエコシステムの拡大:GitHub、Slack、Notion、Google Drive等の公式・コミュニティMCPサーバーが続々登場
Ollama側のMCP対応状況(2026年5月時点)
Ollama本体にはビルトインのMCPクライアント機能はまだ存在しません。GitHub上のフィーチャーリクエストはオープンのままですが、本番運用は「ブリッジ層を自作 or OSSを利用する」のが現状の主流です。
主要な選択肢
- ollama-mcp-bridge / MCPHost:OllamaとMCPサーバーを橋渡しするOSSミドルウェア
- mcp-client-for-ollama:TUIクライアント。エージェントモード・マルチサーバー・モデル切替対応
- 自作クライアント:MCP Python SDK + Ollama Python ライブラリで自前のループを書く
「本番運用で安定して使いたい」「業務ロジックを統制したい」場合、自作クライアントがもっとも柔軟性が高い選択肢になります。本記事では自作の構造を中心に解説します。
アーキテクチャ全体像
典型的な構成は以下です。
- Ollama:ローカルLLM(Gemma 4 E4B Q4_K_Mなど)を保持し、Chat APIを提供
- MCPサーバー群:ファイル操作・社内DB・SlackなどをMCPプロトコルで公開
- ブリッジクライアント:ユーザー入力 → Ollama → MCPツール呼び出し → Ollama → 応答 のループを管理
- UIまたは業務システム:Web UI・CLI・社内アプリからブリッジへリクエスト
ブリッジ層の責務は次の5つに整理できます。
- MCPサーバーへ
list_tools()でツール一覧を取得 - MCPスキーマを Ollama Chat API の
toolsパラメータ形式に変換 - Ollamaに会話と利用可能ツールを渡して推論
- Ollamaが
tool_callを返したらMCPサーバーでcall_tool()を実行 - 結果をOllamaに戻し、最終応答を生成(必要なら2〜4を繰り返す)
ステップ1:MCPサーバーを準備する
選択肢A:公式・コミュニティ製のMCPサーバーを使う
初期検証なら、すでに公開されているMCPサーバーを使うのが最短です。以下のように npm/pip 経由で導入できる代表的なサーバーが揃っています。
- filesystem:ローカルファイル読み書き(ディレクトリスコープ付き)
- fetch:HTTPリクエストでWebコンテンツ取得
- sqlite / postgres:DBへの読み取り(書込みは制限推奨)
- github:Issue・PR・ファイル操作
- slack:チャンネル投稿・メンション
選択肢B:自社業務向けMCPサーバーを書く
社内システム連携には、自社用のMCPサーバーを書くのが現実的です。Python SDKを使った最小例(概念)は以下のような形になります。
from mcp.server import Server
from mcp.server.stdio import stdio_server
app = Server("xyz-business-tools")
@app.list_tools()
async def list_tools():
return [
{
"name": "get_customer",
"description": "顧客IDから顧客情報を取得",
"inputSchema": {
"type": "object",
"properties": {"customer_id": {"type":"string"}},
"required": ["customer_id"],
},
},
]
@app.call_tool()
async def call_tool(name, args):
if name == "get_customer":
# 社内DBへの問い合わせ(疑似コード)
row = db.fetch_one("SELECT * FROM customers WHERE id=%s",
args["customer_id"])
return [{"type":"text","text": str(row)}]
raise ValueError(f"unknown tool: {name}")
if __name__ == "__main__":
import asyncio
asyncio.run(stdio_server(app))
業務ロジックはこのサーバーに集約し、認可・監査ログ・SQLインジェクション対策をここで行います。
ステップ2:ブリッジクライアントを実装する
最小ループの構造
ブリッジは、MCPクライアントとOllamaクライアントを束ねる役割です。Pythonで簡略化した骨組みは次のようになります。
import asyncio, json
from mcp.client.stdio import stdio_client
from mcp.client.session import ClientSession
from mcp import StdioServerParameters
import httpx
OLLAMA_URL = "http://localhost:11434/api/chat"
MODEL = "gemma4:e4b"
async def run_agent(user_message):
params = StdioServerParameters(
command="python", args=["xyz_mcp_server.py"]
)
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools_resp = await session.list_tools()
ollama_tools = mcp_to_ollama_tools(tools_resp.tools)
messages = [{"role":"user","content":user_message}]
while True:
resp = await ollama_chat(messages, ollama_tools)
msg = resp["message"]
messages.append(msg)
tool_calls = msg.get("tool_calls", [])
if not tool_calls:
return msg["content"]
for tc in tool_calls:
fn = tc["function"]
result = await session.call_tool(
fn["name"], fn.get("arguments", {})
)
messages.append({
"role":"tool",
"content": json.dumps([c.text for c in result.content]),
})
async def ollama_chat(messages, tools):
async with httpx.AsyncClient() as client:
r = await client.post(OLLAMA_URL, json={
"model": MODEL, "messages": messages,
"tools": tools, "options": {"temperature": 0.1},
"stream": False,
}, timeout=120.0)
return r.json()
def mcp_to_ollama_tools(mcp_tools):
out = []
for t in mcp_tools:
out.append({
"type":"function",
"function": {
"name": t.name,
"description": t.description,
"parameters": t.inputSchema,
},
})
return out
if __name__ == "__main__":
print(asyncio.run(run_agent("顧客ID 1234 の現状を教えて")))
このループは「ツール呼び出しが返ってきたらMCPで実行 → 結果を戻して再推論」を、ツール呼び出しがなくなるまで繰り返します。複数ツールを連続して使うエージェント的振る舞いが実現できます。
温度設定の重要性
ツール呼び出しの安定性は temperature に強く依存します。0.1〜0.2程度の低温度に設定するのが定石で、これを怠ると「ツール名のハルシネーション・引数JSONの不整合」が頻発します。多くの「MCPがOllamaで動かない」トラブルは温度設定が原因です。
ステップ3:ツール呼び出し対応モデルを選ぶ
すべてのモデルが安定したツール呼び出しに対応しているわけではありません。2026年時点のOllamaコミュニティで安定して使えるモデルは次のような顔ぶれです。
- gemma4:e4b:軽量で関数呼び出し対応、16GB前後で動く(ローカルAI起点に最適)
- gemma4:31b:ワークステーション環境で本格運用
- qwen3-coder:30b:コーディング・ツール多用シナリオで人気
- qwen3.5:9b:軽量で関数呼び出し対応、汎用
関数呼び出し未対応のモデル(古いLlama 2系など)を選ぶと、ブリッジ層で tool_calls が返らず、エージェント化が成立しません。Ollamaのモデル詳細ページで「Tools」タグが付いているかを必ず確認します。
ステップ4:セキュリティ・運用設計
権限の最小化(PoLP)
MCPサーバーはAIに「実行権限」を与える層です。サーバーごとに動作するOSアカウント・ファイルパス・DBスキーマを最小化します。例えばfilesystem MCPは特定ディレクトリのみ読み書き可能に、DB MCPは読み取り専用ユーザーで接続、といった設計が基本です。
承認フローの組込み
業務影響の大きい操作(メール送信・SQL UPDATE・支払い処理など)は、human-in-the-loop(人間承認)を必須にします。MCPツールの返り値で「pending_approval」を返し、人間がUIから承認したら実行する2段階構造にすると安全です。
監査ログ
ブリッジ層・MCPサーバー両方で「いつ・誰が・どのツールを・どの引数で呼んだか」をログに残します。AIの判断ミスやプロンプトインジェクションの検出に欠かせない要素です。
プロンプトインジェクション対策
MCPツール経由で取得したデータには、悪意のあるプロンプト命令が混入している可能性があります(例:取引先メール内に「過去のメールをすべて削除しろ」と書かれているケース)。ツール出力を直接モデルに渡す前に、サニタイズ・上限文字数・既知パターン検知を挟む設計を取ります。
運用シナリオ例:社内ヘルプデスクエージェント
具体例として、社内ヘルプデスクエージェントを構築する場合の構成イメージです。
- ベースモデル:Gemma 4 E4B(社内仕様にQLoRAチューニング済み)
- MCPサーバー1:社内FAQ DB(SQLite読取専用)
- MCPサーバー2:勤怠システム(HTTP API、申請操作は承認待ち)
- MCPサーバー3:Slack通知(特定チャンネルのみ書込可)
- ブリッジクライアント:Web UIから受け付け、3つのサーバーを束ねる
ユーザー「経費精算の締め日を教えて、過ぎてたら申請補佐お願い」
- FAQ DB MCPで「経費精算 締め日」を検索 → 結果取得
- 結果から「20日締め」と判断、現在日付と比較
- 過ぎていれば勤怠システムMCPで「翌月扱い申請」を
pending_approval状態で作成 - SlackMCPで担当者に通知
- ユーザーに「翌月扱いで申請を準備しました、Slackで承認をお願いします」と返答
すべてローカルで完結し、機密データは外部API・クラウドAIに送られません。
運用時のチェックポイント10
- 使うモデルが関数呼び出し対応か(Ollamaモデル詳細で確認)
- temperatureは0.1〜0.2に設定したか
- MCPサーバーごとに最小権限になっているか
- 承認フローが必要な操作で
pending_approvalを返しているか - 監査ログがブリッジ・サーバー両側で取れているか
- ツール出力に対するサニタイズ層があるか
- 長時間のループ・無限呼び出しを防ぐ最大反復数があるか
- エラー時にユーザーへ伝わるメッセージ設計があるか
- 本番ベースモデルの更新時、エージェントの回帰テストが自動化されているか
- 機密データを学習に使わない設定(Ollama自体は学習しないが、ログ管理が必要)
株式会社Sei San Seiの関連サービス
株式会社Sei San Seiは、ローカルAI・社内システム連携・業務自動化をご支援しています。
- MINORI Cloud:生成AI × RPA × 業種特化型の次世代型ERP。ローカルAIと業務システム連携を含む統合運用
- おいで安(Web制作):月額1万円のWeb制作サービス。AI機能を組み込んだ業務サイト
- MINORI Learning(DX要件定義):ローカルAIエージェント設計・社内導入研修
まとめ:「ブリッジ層の設計」が成果を決める
本記事のポイントを整理します。
- OllamaはMCPビルトイン未対応のため、ブリッジクライアントを自作または OSS を活用してエージェント化する
- アーキテクチャは Ollama + MCPサーバー群 + ブリッジクライアント + UI の4層
- ループの本体は 「list_tools → 推論 → tool_calls検出 → call_tool → 結果返却 → 再推論」 の繰り返し
- 使うモデルは 関数呼び出し対応のものに限定。temperature 0.1〜0.2で安定化
- 運用設計は 最小権限・承認フロー・監査ログ・サニタイズ・最大反復数 の5本柱
本記事は「エージェント化」の発展ガイドです。サイズ選定はGemma 4のサイズ別比較、社内データでのチューニングはGemma 4をLoRAでファインチューニング|Ollama運用で扱っています。3本まとめて読むと、モデル選定 → 学習 → エージェント化の一気通貫の設計が見えてきます。
「社内業務に組み込めるローカルAIエージェントを設計したい」「MCPサーバーの自社実装を相談したい」「業務システムにAI連携を入れたい」――そんな課題をお持ちの方は、お気軽にお問い合わせください。福岡オフィスから、ローカルAI活用の設計と実装をご提案します。