模型上下文协议(MCP)本身提供的是一套标准化的通信规则和接口,简化了客户端应用的开发。
MCP 实际上是一套规范,官方把整套协议分成「传输层 + 协议层 + 功能层」三大块,并对初始化握手、能力协商、数据/工具暴露、安全约束等均给出了约束性 JSON-Schema。
基于 JSON-RPC 2.0 的开放协议,目标是像 USB-C 一样为 LLM 应用提供统一“插槽”。它定义三方角色——Host(应用)/Client(适配层)/Server(能力提供者),通过标准消息把 资源、工具、提示模板 等上下文按需送进 LLM,同时保留“人-机共管”审批流程,实现安全、可组合的本地或远程代理体系。
但是,需要注意,不要连接不信任的 server,MCP 没有在数据安全上提供任何保障。
下面我们可以实现一个最简的 MCP 服务。
0 先决条件
软件 | 版本建议 | 作用 |
---|---|---|
操作系统 | Windows 10/11、macOS 13+ 或任何较新的 Linux | 仅需能运行 Ollama |
Ollama | ≥ 0.1.34 | 本地大语言模型后端 |
Python | 3.10 – 3.12 | 运行 FastAPI 服务 |
Git | 最新 | 克隆或管理代码 |
CUDA 12+(可选) | 若使用 NVIDIA GPU | 提升推理速度 |
CPU 也可运行,但 LLaMA 3-8B 在 GPU 上体验最佳。
1 安装 Ollama 并拉取 LLaMA 3
# 1.1 安装(macOS / Linux)
curl -fsSL https://ollama.com/install.sh | sh
# Windows 请下载 .msi 并双击安装# 1.2 启动后台(首次安装会自动启动)
ollama serve# 1.3 拉取 8B 模型(约 4.7 GB)
ollama pull llama3:8b
2 创建最小可用的 MCP 后端
2.1 目录结构
mcp-ollama/
│
├── app/
│ ├── main.py # FastAPI 入口
│ ├── mcp.py # 协议封装
│ └── store.py # 简易上下文存储
└── requirements.txt
2.2 requirements.txt
fastapi==0.110.*
uvicorn[standard]==0.29.*
httpx==0.27.*
python-dotenv==1.0.*
2.3 MCP 协议封装(app/mcp.py)
from typing importList, Dictdefbuild_prompt(history: List[Dict[str, str]], user_msg: str) -> str:"""把历史消息与当前输入拼接成大模型 prompt。MCP 规定 key 为 role / content,与 OpenAI messages 一致。"""lines = []for msg in history:lines.append(f"{msg['role'].upper()}: {msg['content']}")lines.append(f"USER: {user_msg}")return"\n".join(lines)SYSTEM_PROMPT = ("You are an AI assistant that follows instructions precisely. ""Answer in the same language as the question."
)
2.4 上下文存储(app/store.py)
from collections import defaultdict, deque_MAX_TURNS = 8 # 只保留最近 8 轮
_history = defaultdict(lambda: deque(maxlen=_MAX_TURNS))def add_msg(session_id: str, role: str, content: str):_history[session_id].append({"role": role, "content": content})def get_history(session_id: str):return list(_history[session_id])
2.5 FastAPI 入口(app/main.py)
import os, uuid, httpx
from fastapi import FastAPI
from pydantic import BaseModel
from app.mcp import build_prompt, SYSTEM_PROMPT
from app.store import add_msg, get_historyOLLAMA_URL = os.getenv("OLLAMA_URL", "http://localhost:11434")classChatReq(BaseModel):session_id: str | None = Nonemessage: strclassChatResp(BaseModel):session_id: stranswer: strapp = FastAPI(title="MCP Demo")@app.post("/chat", response_model=ChatResp) async def chat(req: ChatReq):sid = req.session_id orstr(uuid.uuid4())history = get_history(sid)prompt = f"{SYSTEM_PROMPT}\n{build_prompt(history, req.message)}"payload = {"model": "llama3:8b", "prompt": prompt, "stream": False}asyncwith httpx.AsyncClient() as client:r = await client.post(f"{OLLAMA_URL}/api/generate", json=payload, timeout=120)r.raise_for_status()ans = r.json()["response"]add_msg(sid, "user", req.message)add_msg(sid, "assistant", ans)return ChatResp(session_id=sid, answer=ans)
2.6 运行服务
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000
3 验证接口
# 第一次调用
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"message":"Hello, what is MCP?"}' # 记录返回的 session_id# 带历史上下文的第二次调用
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"session_id":"<上一步返回的id>","message":"Explain in Chinese."}'
你将看到回答中自动继承了第一轮对话,上下文逻辑即生效。