提到mcp,或许大家或多或少都已经有听说或使用过。Model Context Protocol 简称 MCP,即模型上下文协议。简单类比如笔记本的USB接口,为鼠标、键盘、打印机提供统一的接入标准。而MCP的出现,正是为了解决AI模型与外部世界沟通的“接口混乱”问题。它提供了一套标准化的协议,让AI大模型能够通过统一的方式安全、高效地调用外部工具、读取数据源。那么,一个标准的MCP服务是如何创建的,今天就基于一个类似服务器日志操作案例编写一个入门级的MCP服务,以及在大模型中调用后的实际效果。
MCP协议本身很强大,但直接实现它可能会比较复杂。本篇基于Python生态框架进行快速服务的构建,在本地创建一个Python项目后安装以下依赖:本项目基于Python3.8
一、安装依赖
pip install mcp fastmcp uvicorn
二、示例代码如下
创建项目后编写一个server.py文件
import json
import re
from datetime import datetime
from pathlib import Path
from typing import Dict, Any
from fastmcp import FastMCP
# 初始化MCP服务器,Log Analyzer为服务器自定义名称
mcp = FastMCP("Log Analyzer")
# 日志文件路径(可以替换成真实的)
LOG_FILE = Path("./server.log")
# 如果未存在日志文件可进行模拟日志测试数据
def init_mock_logs():
"""生成模拟的系统日志"""
if not LOG_FILE.exists():
logs = [
"[2026-04-05 10:23:15] INFO - User login successful: admin@example.com",
"[2026-04-05 10:25:42] ERROR - Database connection timeout after 30s",
"[2026-04-05 10:26:01] WARNING - High memory usage detected: 85%",
"[2026-04-05 10:28:33] INFO - File upload completed: report.pdf",
"[2026-04-05 10:30:17] ERROR - API request failed: 500 Internal Server Error",
"[2026-04-05 10:32:45] INFO - Cache cleared successfully",
"[2026-04-05 10:35:22] WARNING - Slow query detected: SELECT * FROM users (took 5.2s)",
"[2026-04-05 10:38:09] ERROR - Disk space low: only 2.3GB remaining",
"[2026-04-05 10:40:55] INFO - Backup completed successfully",
"[2026-04-05 10:43:11] CRITICAL - Service crash detected, restarting...",
"[2026-04-05 10:45:30] INFO - Service restarted successfully",
"[2026-04-05 10:48:02] ERROR - Failed to send email: SMTP server unreachable"
]
with open(LOG_FILE, 'w', encoding='utf-8') as f:
f.write('\n'.join(logs))
#这是最核心的部分。通过@mcp.tool装饰器,将普通的Python函数变成AI可以理解和调用的工具。函数的文档字符串(docstring)是给AI看的“说明书”,一定要写得清晰明了
# AI每次调用时进行记录工具,log_query默认为工具名称
@mcp.tool
def log_query(query: str, tool: str = ""):
"""记录 AI 查询(AI 应在执行任何查询前调用)"""
with open("log_query.log", 'a', encoding='utf-8') as f:
f.write(f"[{datetime.now()}] {tool}: {query}\n")
return "记录成功"
# 解析日志行
def parse_log_line(line: str) -> Dict[str, Any]:
"""解析单行日志"""
pattern = r'\[(.*?)\] (\w+) - (.*)'
match = re.match(pattern, line)
if match:
return {
"timestamp": match.group(1),
"level": match.group(2),
"message": match.group(3)
}
return {"raw": line}
# 获取最近N条日志
@mcp.tool
def get_recent_logs(lines: int = 50) -> str:
"""
获取最近的系统日志记录
Args:
lines: 要获取的日志行数,默认50条
"""
init_mock_logs()
with open(LOG_FILE, 'r', encoding='utf-8') as f:
all_logs = f.readlines()
recent_logs = all_logs[-lines:]
return json.dumps({
"total_lines": len(all_logs),
"returned_lines": len(recent_logs),
"logs": [parse_log_line(log.strip()) for log in recent_logs]
}, ensure_ascii=False, indent=2)
# 按错误级别筛选日志
@mcp.tool
def filter_logs_by_level(level: str, limit: int = 20) -> str:
"""
按日志级别筛选日志(ERROR, WARNING, INFO, CRITICAL等)
Args:
level: 日志级别,如 ERROR, WARNING, INFO, CRITICAL
limit: 返回的最大条数,默认20
"""
init_mock_logs()
with open(LOG_FILE, 'r', encoding='utf-8') as f:
logs = f.readlines()
filtered = []
for log in logs:
if f" {level} - " in log:
filtered.append(parse_log_line(log.strip()))
if len(filtered) >= limit:
break
return json.dumps({
"level": level,
"count": len(filtered),
"logs": filtered
}, ensure_ascii=False, indent=2)
# 搜索包含关键词的日志
@mcp.tool
def search_logs(keyword: str, case_sensitive: bool = False) -> str:
"""
在日志中搜索特定关键词
Args:
keyword: 要搜索的关键词
case_sensitive: 是否区分大小写,默认False
"""
init_mock_logs()
with open(LOG_FILE, 'r', encoding='utf-8') as f:
logs = f.readlines()
results = []
for log in logs:
log_text = log.strip()
if case_sensitive:
found = keyword in log_text
else:
found = keyword.lower() in log_text.lower()
if found:
results.append(parse_log_line(log_text))
return json.dumps({
"keyword": keyword,
"case_sensitive": case_sensitive,
"count": len(results),
"logs": results
}, ensure_ascii=False, indent=2)
# 获取日志统计摘要
@mcp.tool
def get_log_summary() -> str:
"""
获取日志统计摘要,包括各级别日志数量和常见错误类型
"""
init_mock_logs()
with open(LOG_FILE, 'r', encoding='utf-8') as f:
logs = f.readlines()
stats = {
"total": len(logs),
"levels": {"INFO": 0, "WARNING": 0, "ERROR": 0, "CRITICAL": 0},
"common_errors": []
}
error_count = {}
for log in logs:
parsed = parse_log_line(log.strip())
level = parsed.get("level", "")
if level in stats["levels"]:
stats["levels"][level] += 1
# 统计常见错误
if level == "ERROR":
msg = parsed.get("message", "")
# 提取错误类型
error_type = msg.split(":")[0] if ":" in msg else msg[:30]
error_count[error_type] = error_count.get(error_type, 0) + 1
# 取前5个常见错误
stats["common_errors"] = sorted(error_count.items(), key=lambda x: x[1], reverse=True)[:5]
return json.dumps(stats, ensure_ascii=False, indent=2)
if __name__ == "__main__":
# 初始化日志文件
init_mock_logs()
# 使用HTTP传输模式
print("MCP Log Analyzer Server 启动中...")
print(f"日志文件路径: {LOG_FILE.absolute()}")
print("服务运行在: http://localhost:8000/mcp")
# 运行HTTP服务器(端口8000)
mcp.run(transport='http', host='0.0.0.0', port=8000)
执行python server.py后启动服务,界面运行如下:

以上界面提示mcp服务启动成功,基于http协议,同时在命令行可看到该日志:
Starting MCP server ‘Log Analyzer’ with transport ‘http’ on http://0.0.0.0:8000/mcp
三、使用mcp服务
以上MCP服务创建后如何进行测试,本文章基于cline插件进行快速验证,关于cline的使用大家可自行网上搜索和配置使用对应的大模型,本文mcp服务环境是在本地运行,大家也可部署成在线服务线上访问。
在cline中找到MCP Server,点击添加mcp服务:

服务信息填写完后点击AddServer

如图,在server.py中定义的5个工具都能被正确识别,大家勾选需要使用的工具即可,AI会根据工具名称和描述做调用。
接着,在cline交互面板中输入提问,结果如下:


大模型会根据问题自动调用工具并分析,也扩展了对应的能力边界。
四、总结
通过这个简单的日志分析器,从MCP服务的创建到使用,通过定义工具Tools的方式,将外部数据和服务的能力赋予AI。像高德地图等应用也开放一些在线MCP服务,大模型接入后就可以进行位置搜索等能力拓展了。
另外,MCP还支持资源(Resources)和提示词模板(Prompts)等更强大的功能,大家有兴趣可以自行了解,后续本文也会持续更新,有问题的欢迎大家一块交流!


532

被折叠的 条评论
为什么被折叠?



