1.🎯 日志记录概述 #
Model Context Protocol (MCP) 为服务器向客户端发送结构化日志消息提供了一种标准化方式。客户端可通过设置最低日志级别来控制日志详细程度,服务器会发送包含严重级别、可选记录器名称及任意可JSON序列化数据的通知。
2.🔧 用户交互模型 #
实现可以自由地通过任何适合其需求的接口模式来暴露日志记录功能——协议本身并未强制规定任何特定的用户交互模型。
3.⚙️ 功能声明 #
发出日志消息通知的服务器必须声明 logging 能力:
{
"capabilities": {
"logging": {}
}
}4.📊 日志级别 #
该协议遵循标准syslog严重性等级规范 RFC 5424:
| 级别 | 描述 | 示例用例 |
|---|---|---|
| 调试 | 详细调试信息 | 函数入口/出口点 |
| 信息 | 一般信息性消息 | 操作进度更新 |
| 通知 | 正常但意义重大的事件 | 配置变更 |
| 警告 | 警告条件 | 已弃用的功能用法 |
| 错误 | 错误条件 | 操作失败 |
| 关键 | 关键条件 | 系统组件故障 |
| 警报 | 必须立即采取行动 | 检测到数据损坏 |
| 紧急情况 | 系统无法使用 | 系统完全故障 |
5.📨 协议消息 #
5.1 设置日志级别 #
要配置最低日志级别,客户端可能发送一个 logging/setLevel 请求:
请求示例:
{
"jsonrpc": "2.0",
"id": 1,
"method": "logging/setLevel",
"params": {
"level": "info"
}
}5.2 日志消息通知 #
服务器使用 notifications/message 通知发送日志消息:
通知示例:
{
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": "error",
"logger": "database",
"data": {
"error": "Connection failed",
"details": {
"host": "localhost",
"port": 5432
}
}
}
}6.🔄 消息流 #

7.⚠️ 错误处理 #
服务器应该返回标准JSON-RPC错误以处理常见故障情况:
- 无效的日志级别:
-32602(参数无效) - 配置错误:
-32603(内部错误)
8. 实施考量 #
8.1 服务器应该: #
- 速率限制日志消息 - 避免日志洪水
- 在数据字段中包含相关上下文 - 提供有用的调试信息
- 使用一致的日志记录器名称 - 便于分类和过滤
- 移除敏感信息 - 保护隐私和安全
8.2 客户端可能: #
- 在用户界面中显示日志消息 - 提供实时反馈
- 实现日志过滤/搜索 - 帮助用户找到相关信息
- 视觉化显示严重程度 - 使用颜色和图标区分级别
- 持久化日志消息 - 保存历史记录供后续分析
9.🔒 安全考虑 #
9.1 日志消息不得包含: #
- 凭证或密钥 - 避免泄露敏感认证信息
- 个人身份信息 - 保护用户隐私
- 可能有助于攻击的内部系统细节 - 防止信息泄露
9.2 实现应该: #
- 速率限制消息 - 防止日志攻击
- 验证所有数据字段 - 确保数据完整性
- 控制日志访问 - 限制敏感日志的访问权限
- 监控敏感内容 - 自动检测和过滤敏感信息
10.🎯 最佳实践 #
10.1 服务器端实现示例 #
# 导入logging模块(虽然本例未直接用到,但可用于扩展日志功能)
import logging
# 从typing模块导入Dict和Any类型,用于类型注解
from typing import Dict, Any
# 定义MCPServer类,用于处理日志相关操作
class MCPServer:
# 构造函数,初始化日志级别和日志记录器字典
def __init__(self):
# 默认日志级别为info
self.log_level = "info"
# 初始化日志记录器字典
self.loggers = {}
# 设置日志级别的方法
def set_log_level(self, level: str):
"""设置日志级别"""
# 判断传入的日志级别是否合法
if level not in ["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"]:
# 如果不合法,抛出异常
raise ValueError(f"Invalid log level: {level}")
# 设置当前日志级别
self.log_level = level
# 发送日志消息的方法
def log_message(self, level: str, logger_name: str, data: Dict[str, Any]):
"""发送日志消息"""
# 检查日志级别是否达到当前设置的最低级别
if self._should_log(level):
# 构造日志消息的JSON-RPC结构
message = {
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": level,
"logger": logger_name,
"data": data
}
}
# 调用内部方法将消息发送到客户端
self._send_notification(message)
# 判断是否应该记录该级别日志的内部方法
def _should_log(self, level: str) -> bool:
"""检查是否应该记录该级别的日志"""
# 定义日志级别的顺序列表
levels = ["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"]
# 只有当当前日志级别在设置级别及以上时才记录
return levels.index(level) >= levels.index(self.log_level)10.2 客户端实现示例 #
// 定义MCPClient类,用于处理日志相关功能
class MCPClient {
// 构造函数,初始化日志级别和日志处理器数组
constructor() {
// 设置默认日志级别为info
this.logLevel = 'info';
// 初始化日志处理器数组
this.logHandlers = [];
}
// 设置日志级别的方法
setLogLevel(level) {
// 更新当前日志级别
this.logLevel = level;
// 发送设置日志级别的请求到服务器
this.sendRequest('logging/setLevel', { level });
}
// 处理接收到的日志消息
handleLogMessage(message) {
// 从消息参数中解构出日志级别、记录器名称和数据
const { level, logger, data } = message.params;
// 定义不同日志级别对应的显示颜色
const colors = {
debug: '#6c757d', // 调试级别为灰色
info: '#17a2b8', // 信息级别为蓝色
notice: '#28a745', // 通知级别为绿色
warning: '#ffc107', // 警告级别为黄色
error: '#dc3545', // 错误及以上为红色
critical: '#dc3545',
alert: '#dc3545',
emergency: '#dc3545'
};
// 调用显示日志消息的方法,将日志内容、颜色和时间戳传递过去
this.displayLogMessage({
level,
logger,
data,
color: colors[level] || '#000000', // 未知级别默认黑色
timestamp: new Date().toISOString() // 当前时间ISO格式
});
}
// 显示日志消息的方法
displayLogMessage(logEntry) {
// 在控制台输出格式化的日志信息
console.log(`[${logEntry.level.toUpperCase()}] ${logEntry.logger}:`, logEntry.data);
}
}11. 总结 #
MCP的日志记录功能为服务器和客户端之间提供了标准化的日志通信机制。通过合理使用日志级别、结构化数据和适当的错误处理,可以构建出既功能强大又安全可靠的日志系统。
记住:
- 🎯 选择合适的日志级别 - 平衡信息量和性能
- 🔒 保护敏感信息 - 永远不要在日志中包含密码或密钥
- 📊 提供有用的上下文 - 帮助调试和问题排查
- ⚡ 控制日志频率 - 避免日志洪水影响性能