用本地LLM构建私有MCP服务器 — Gemma 4 + FastMCP 完全离线AI工具指南
使用Ollama + Gemma 4 + FastMCP构建无需互联网的离线AI工具管道。适用于医疗、法律、金融环境中数据不能外发的实战实现指南。
“在不允许使用云端AI的环境中工作” — 第一次听到这句话时,我老实说没什么感触。但实际上,处理医院病历、审查法律文件、分析金融客户数据的团队真的不少。对这些团队说”粘贴到Claude或GPT里试试”根本行不通。
上周我写了一篇用FastMCP从零构建MCP服务器的文章,展示了如何将Claude Code作为客户端连接。文章发布后马上收到了一个问题:“能用本地LLM代替Claude作为客户端吗?”
好问题。我也想试试。
这篇文章就是那个问题的答案。用Ollama + Gemma 4 + FastMCP,我构建了一个完全不需要互联网连接的离线AI工具管道。
先理清架构
标准MCP结构是这样的:
[Claude / GPT-4] ←→ [MCP服务器] ←→ [实际工具]
云端LLM充当MCP客户端。问题在于,这种情况下提示词和上下文会经过Anthropic或OpenAI的服务器。
我们要构建的结构不同:
[用户提示词]
|
[Python编排器]
↙ ↘
[Ollama:11434] [FastMCP:8000]
(Gemma 4) (本地工具)
一切都在本地运行。Ollama将Gemma 4作为OpenAI兼容API提供服务,FastMCP充当工具服务器,Python编排器将两者连接起来。
Step 1:Ollama + Gemma 4 配置
正如Gemma 4本地安装经验中所述,安装本身只需一行命令:
ollama pull gemma4
由于我们需要使用函数调用,先验证模型是否正确加载:
ollama run gemma4 '请返回这个JSON: {"status": "ok"}'
如果输出是有效的JSON,准备工作完成。Ollama默认在http://localhost:11434提供OpenAI兼容API。
# 确认Ollama API正常运行
curl http://localhost:11434/v1/models
Step 2:FastMCP服务器(工具提供方)
我们构建一个读取本地文件和列出目录的工具服务器。在实际使用中,可以替换为内部DB查询、内部API调用等。
# local_tools_server.py
from fastmcp import FastMCP
import os
mcp = FastMCP("local-tools")
@mcp.tool()
def read_file(path: str) -> str:
"""读取指定路径的文件内容并返回。"""
with open(path, "r", encoding="utf-8") as f:
return f.read()
@mcp.tool()
def list_directory(path: str = ".") -> list[str]:
"""返回目录中的文件列表。"""
return os.listdir(path)
@mcp.tool()
def write_summary(path: str, content: str) -> str:
"""将摘要内容保存到文件。"""
summary_path = path.replace(".txt", "_summary.txt")
with open(summary_path, "w", encoding="utf-8") as f:
f.write(content)
return f"保存完成:{summary_path}"
if __name__ == "__main__":
mcp.run(transport="streamable-http", host="127.0.0.1", port=8000)
pip install fastmcp uvicorn
python local_tools_server.py
服务器在http://127.0.0.1:8000启动。
Step 3:编排器实现
这是核心部分。Gemma 4无法直接理解MCP协议。编排器负责:
- 从FastMCP获取可用工具列表
- 转换为OpenAI函数调用格式
- 传递给Gemma 4
- 当Gemma 4请求工具调用时,在FastMCP上执行并将结果返回
# orchestrator.py
import json
import requests
from openai import OpenAI
# Ollama OpenAI兼容客户端
llm = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama", # Ollama不需要真实密钥
)
MCP_SERVER = "http://127.0.0.1:8000"
def get_mcp_tools() -> list[dict]:
"""从FastMCP获取可用工具列表并转换为OpenAI格式。"""
resp = requests.get(f"{MCP_SERVER}/tools")
tools = resp.json().get("tools", [])
return [
{
"type": "function",
"function": {
"name": t["name"],
"description": t.get("description", ""),
"parameters": t.get("inputSchema", {"type": "object", "properties": {}}),
},
}
for t in tools
]
def call_mcp_tool(name: str, args: dict) -> str:
"""向FastMCP服务器请求工具执行并返回结果。"""
resp = requests.post(
f"{MCP_SERVER}/tools/{name}",
json={"arguments": args},
)
result = resp.json()
return json.dumps(result.get("content", [{"text": str(result)}]), ensure_ascii=False)
def run(user_prompt: str) -> str:
tools = get_mcp_tools()
messages = [
{"role": "system", "content": "你是一个有用的AI。需要时请使用提供的工具。"},
{"role": "user", "content": user_prompt},
]
while True:
resp = llm.chat.completions.create(
model="gemma4",
messages=messages,
tools=tools,
tool_choice="auto",
)
msg = resp.choices[0].message
if not msg.tool_calls:
return msg.content # 最终回答
# 处理工具调用
messages.append(msg)
for tc in msg.tool_calls:
args = json.loads(tc.function.arguments)
result = call_mcp_tool(tc.function.name, args)
messages.append({
"role": "tool",
"tool_call_id": tc.id,
"content": result,
})
if __name__ == "__main__":
answer = run("告诉我当前目录的文件列表")
print(answer)
实际运行结果
python orchestrator.py
Gemma 4调用了list_directory工具,FastMCP服务器返回结果,Gemma 4整理后给出回答。所有数据都在我的MacBook内部流转。
我尝试了更复杂的请求:
answer = run("读取README.md文件,用3句话总结核心内容")
Gemma 4按list_directory → read_file("README.md")的顺序调用。经过两次工具调用,生成了最终摘要。花了一些时间(M2 MacBook约12秒)。与云端API相比较慢,但数据从未离开我的机器。
坦诚的局限性
使用过程中注意到的问题:
工具调用可靠性较低。 Gemma 4具备一定的函数调用支持,但偶尔会传入错误参数或调用不存在的工具。与Claude或GPT-4o相比稳定性较差。要弥补这一点,需要在编排器中添加重试逻辑和参数验证。
多步骤中丢失上下文。 连续3〜4次工具调用后,Gemma 4有时会忘记最初的目标。在系统提示词中明确写入”最终目标:[X]“有所帮助。
速度问题。 个人MacBook上需要5〜15秒,响应越长耗时越多。不适合实时交互场景,批处理和后台任务才是现实的使用场景。
何时使用这种架构
| 情况 | 选择 |
|---|---|
| 个人数据、内部文档、受监管数据 | ✅ 此架构 |
| 需要快速响应的交互式UI | ❌ 云端API |
| 无网络的隔离环境 | ✅ 此架构 |
| 复杂的多步骤智能体工作流 | ⚠️ 有限可行 |
| 最小化成本(零API流量) | ✅ 此架构 |
我个人将这种架构视为”带AI功能的本地脚本”的升级版。它为原本用Shell脚本或Python脚本完成的文件操作、数据转换任务提供了自然语言接口。与其说是完整的智能体系统,不如说更接近自动化脚本的下一步演进。
下一步
如果想进一步发展:
- 更换模型:将Gemma 4替换为函数调用支持更强的Qwen3-7B、Mistral Small等模型
- 扩展工具:添加内部DB连接、REST API包装器、文件转换工具
- 团队共享:在前端部署MCP Gateway,让多人共享同一个本地服务器
将这个管道投入生产前,也请检查MCP安全问题。即使是本地部署,工具注入、过度权限等MCP特有的风险依然存在。
代码全部在上面。安装依赖只需pip install fastmcp uvicorn openai requests一条命令。如果运行时遇到问题,分步骤单独测试会比调试整个管道更快。
阅读其他语言版本
- 🇰🇷 한국어
- 🇯🇵 日本語
- 🇺🇸 English
- 🇨🇳 中文(当前页面)
这篇文章有帮助吗?
您的支持能帮助我创作更好的内容。请我喝杯咖啡吧。