Ollama MCP 流媒体服务器
一个集成了(各种功能)的完整Python后端 Ollama 大语言模型(LLMs) 与;和;带有 模型上下文协议(MCP) 服务器通过WebSocket向React前端提供实时流式响应。
特点/特性
- 流式传输大型语言模型(LLM)响应从Ollama模型中实时逐词流式传输
- MCP集成连接到MCP服务器以增强工具调用功能
- WebSocket APIReact/前端应用的全双工通信
- FastAPI 服务器具备健康检查和CORS支持的生产就绪异步服务器
- 灵活模式使用MCP工具,在简单流媒体模式和完整代理模式之间进行选择
- 类型安全完整的Python类型提示和验证
建筑学
�����������������
React Frontend
��������,��������
WebSocket
��������Ľ������������������������������������
FastAPI Server (server.py)
- WebSocket endpoint (/ws)
- HTTP endpoints (/health, /info, /chat)
��������,������������������������������������
��������Ľ������������������������������������
StreamingOllamaAgent
- Token streaming
- MCP integration
��������,������������������������������������
����Ľ����� ����������
Ollama MCP
Server Server
���������� ����������快速入门
先决条件
- Python 3.13及以上版本
- 紫外线 包管理器
- 本地运行的Ollama(默认地址:http://localhost:11434)
- MCP 服务器正在运行(默认地址:http://localhost:8006/sse)
安装
- 克隆并设置:
# Install dependencies
uv sync
# Copy environment configuration
cp .env.example .env
# Edit .env with your configuration- 配置环境 (
.env):
# MCP Server Configuration
MCP_SERVER_URL=http://localhost:8006/sse
# Ollama Configuration
OLLAMA_MODEL=skaiform-assistant:gpt-oss
OLLAMA_BASE_URL=http://localhost:11434
# Agent Configuration
MAX_STEPS=30
# WebSocket Server Configuration
SERVER_HOST=0.0.0.0
SERVER_PORT=8000
CORS_ORIGINS=http://localhost:3000,http://localhost:5173- 启动服务器:
# Using uv
uv run python server.py
# Or with uvicorn directly
uvicorn server:app --reload --host 0.0.0.0 --port 8000服务器将在 http://localhost:8000
API 文档
WebSocket 终端点: /ws
客户端-服务器消息格式
{
"prompt": "Your question or prompt here",
"mode": "agent" // "agent" or "simple" (optional, default: "agent")
}模式:
agent全代理模式,支持MCP工具调用和多步推理simple直接LLM流式传输,无需代理复杂性
服务器-客户端消息格式
所有消息均遵循此结构:
{
"type": "ollama" | "mcp" | "tool_call" | "tool_result" | "system" | "error" | "done",
"data": "content string or object"
}消息类型:
ollama来自Ollama大型语言模型的标记块
{"type": "ollama", "data": "Hello"}
{"type": "ollama", "data": " world"}mcp来自MCP服务器操作的响应
{"type": "mcp", "data": "Tool execution result"}tool_call当代理调用MCP工具时
{
"type": "tool_call",
"data": {
"name": "calculate_md5",
"args": {"text": "Hello, world!"}
}
}tool_result工具执行结果
{"type": "tool_result", "data": "Result data"}system来自服务器的状态消息
{"type": "system", "data": "Processing your request..."}error错误信息
{"type": "error", "data": "Error description"}done标志着流媒体传输的结束
{"type": "done", "data": "Response completed"}HTTP 端点
GET /
带有服务器信息的根端点。
回应:
{
"name": "Ollama MCP Streaming Server",
"version": "1.0.0",
"status": "running",
"endpoints": {
"websocket": "/ws",
"health": "/health",
"info": "/info"
}
}GET /health
健康检查端点。
回应:
{
"status": "healthy",
"agent_initialized": true
}GET /info
服务器配置和状态。
回应:
{
"ollama_model": "skaiform-assistant:gpt-oss",
"ollama_base_url": "http://localhost:11434",
"mcp_server_url": "http://localhost:8006/sse",
"max_steps": 30,
"server": {
"host": "0.0.0.0",
"port": 8000,
"cors_origins": ["http://localhost:3000"]
}
}POST /chat
用于测试的非流式HTTP终端。
请求:
{
"prompt": "What is the meaning of life?"
}回应:
{
"responses": [
{"type": "ollama", "data": "The"},
{"type": "ollama", "data": " meaning"},
{"type": "done", "data": "Response completed"}
]
}React 前端集成
WebSocket 客户端示例
import { useEffect, useState, useRef } from 'react';
interface Message {
type: 'ollama' | 'mcp' | 'tool_call' | 'system' | 'error' | 'done';
data: string | object;
}
export function useOllamaStream(serverUrl: string = 'ws://localhost:8000/ws') {
const [messages, setMessages] = useState([]);
const [isConnected, setIsConnected] = useState(false);
const [isStreaming, setIsStreaming] = useState(false);
const ws = useRef(null);
useEffect(() => {
// Connect to WebSocket
ws.current = new WebSocket(serverUrl);
ws.current.onopen = () => {
console.log('WebSocket connected');
setIsConnected(true);
};
ws.current.onmessage = (event) => {
const message: Message = JSON.parse(event.data);
setMessages((prev) => [...prev, message]);
if (message.type === 'done') {
setIsStreaming(false);
}
};
ws.current.onerror = (error) => {
console.error('WebSocket error:', error);
setIsConnected(false);
};
ws.current.onclose = () => {
console.log('WebSocket disconnected');
setIsConnected(false);
};
return () => {
ws.current?.close();
};
}, [serverUrl]);
const sendPrompt = (prompt: string, mode: 'agent' | 'simple' = 'agent') => {
if (ws.current && isConnected) {
setMessages([]);
setIsStreaming(true);
ws.current.send(JSON.stringify({ prompt, mode }));
}
};
return { messages, isConnected, isStreaming, sendPrompt };
}在组件中的使用
function ChatInterface() {
const { messages, isConnected, isStreaming, sendPrompt } = useOllamaStream();
const [input, setInput] = useState('');
// Accumulate ollama tokens into a single response
const response = messages
.filter((m) => m.type === 'ollama')
.map((m) => m.data)
.join('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (input.trim()) {
sendPrompt(input);
setInput('');
}
};
return (
Status: {isConnected ? '=â Connected' : '=4 Disconnected'}
{response}
{isStreaming && Š}
setInput(e.target.value)}
placeholder="Ask a question..."
disabled={!isConnected || isStreaming}
/>
Send
{/* Tool calls and system messages */}
{messages
.filter((m) => m.type === 'tool_call' || m.type === 'system')
.map((m, i) => (
{m.type}: {JSON.stringify(m.data)}
))}
);
}项目结构
mcp-ollama/
�� server.py # FastAPI WebSocket server
�� streaming_agent.py # Streaming agent implementation
�� ollama_agent.py # Original non-streaming agent
�� main.py # CLI test script
�� pyproject.toml # Dependencies
�� .env.example # Configuration template
�� .env # Your configuration (create this)
�� README.md # This file核心组件
StreamingOllamaAgent (streaming_agent.py) 翻译为中文是:(流式处理代理脚本.py)
处理核心代理类的:
- Ollama LLM和MCP客户端的初始化
- 从Ollama逐个标记地进行流式传输
- MCP工具集成
- 错误处理与恢复
关键方法:
initialize()建立LLM和MCP连接stream_response(prompt)全代理模式,支持工具调用stream_simple(prompt)简单的大语言模型(LLM)流式处理,无需工具
FastAPI Server (server.py) 翻译为中文是:(服务器.py)
生产就绪的异步服务器,具备:
- 用于实时流传输的WebSocket终端
- 用于健康检查和测试的HTTP端点
- 前端集成的CORS支持
- 全面日志记录
- 代理初始化的生命周期管理
发展
运行测试
# Test the basic agent (non-streaming)
python main.py
# Test WebSocket connection
# Use a WebSocket client like wscat:
npm install -g wscat
wscat -c ws://localhost:8000/ws
# Send a message:
{"prompt": "Hello!", "mode": "simple"}代码检查和格式化
ruff check .
ruff format .添加依赖项
uv add package-name配置选项
环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
MCP_SERVER_URL | http://localhost:8006/sse | MCP服务器SSE端点 |
OLLAMA_MODEL | skaiform-assistant:gpt-oss | Ollama模型名称 |
OLLAMA_BASE_URL | http://localhost:11434 | Ollama 服务器 URL |
MAX_STEPS | 30 | 最大代理推理步骤 |
SERVER_HOST | 0.0.0.0 | WebSocket 服务器主机 |
SERVER_PORT | 8000 | WebSocket 服务器端口 |
CORS_ORIGINS | http://localhost:3000,... | 允许的CORS来源 |
故障排除
WebSocket 连接问题
- CORS 错误将您的前端URL添加到
CORS_ORIGINS在.env - 连接被拒绝确保服务器正在运行且端口正确
- 超时检查Ollama和MCP服务器是否正在运行
Ollama 问题
- 未找到模型先拉出模型:
ollama pull model-name - 连接被拒绝启动Ollama:
ollama serve - 反应迟钝检查Ollama的资源使用情况
MCP服务器问题
- 连接失败验证MCP服务器是否在配置的URL上运行
- 工具错误检查MCP服务器日志中的工具执行错误
高级用法
定制工具处理
修改 streaming_agent.py 为特定工具类型添加自定义处理:
async for chunk in agent.stream_response(prompt):
if chunk["type"] == "tool_call":
tool_name = chunk["data"]["name"]
# Add custom logic for specific tools
if tool_name == "my_custom_tool":
# Handle specially
pass
yield chunk多个MCP服务器
在代理初始化时配置多个MCP服务器:
config = {
"mcpServers": {
"server1": {"url": "http://localhost:8006/sse"},
"server2": {"url": "http://localhost:8007/sse"}
}
}认证
为WebSocket连接添加身份验证:
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket, token: str = Query(...)):
# Verify token
if not verify_token(token):
await websocket.close(code=1008)
return
await websocket.accept()
# ... rest of handler许可证
\[此处填写您的许可证\]
贡献
欢迎贡献!请随时提交拉取请求。
支持
对于问题和疑问:
- 在GitHub上提交一个问题
- 检查现有问题以寻找解决方案
- 查阅相关文件
