模型上下文协议 (MCP) 提供了一种标准化方式,供客户端向服务器暴露文件系统“根目录”。根目录告知服务器客户端认为相关的目录和文件,以便服务器可以相应地集中其操作。它们是信息指导而非访问控制机制。协议不强制服务器停留在根目录内。服务器可以向支持的客户端请求根目录列表,并在该列表更改时接收通知。
用户交互模型
MCP 中的根目录通常通过工作区或项目配置界面暴露。
例如,实现可以提供工作区/项目选择器,允许用户选择服务器应有权访问的目录和文件。这可以与来自版本控制系统或项目文件的自动工作区检测相结合。
然而,实现可以通过任何适合其需求的界面模式暴露根目录——协议本身不强制任何特定的用户交互模型。
服务器必须仅在与发起的客户端请求关联时发送服务器到客户端的请求(例如 roots/list、sampling/createMessage 或 elicitation/create)(例如,在 tools/call、resources/read 或 prompts/get 处理期间)。不支持在独立通信流上(与任何客户端请求无关)独立发起的此类服务器请求,且不得实现。未来的传输实现不需要支持此模式。
支持根目录的客户端必须在 初始化 期间声明 roots 能力:
{
"capabilities": {
"roots": {
"listChanged": true
}
}
}
listChanged 指示客户端是否会在根目录列表更改时发出通知。
协议消息
列出根目录
要检索根目录,服务器发送 roots/list 请求:
请求:
{
"jsonrpc": "2.0",
"id": 1,
"method": "roots/list"
}
响应:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"roots": [
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
]
}
}
根目录列表更改
当根目录更改时,支持 listChanged 的客户端必须发送通知:
{
"jsonrpc": "2.0",
"method": "notifications/roots/list_changed"
}
消息流
数据类型
根目录
根目录定义包括:
uri: 根目录的唯一标识符。在当前规范中,这必须是 file:// URI。
name: 可选的人类可读名称,用于显示目的。
不同用例的根目录示例:
项目目录
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
多个仓库
[
{
"uri": "file:///home/user/repos/frontend",
"name": "Frontend Repository"
},
{
"uri": "file:///home/user/repos/backend",
"name": "Backend Repository"
}
]
错误处理
客户端应该为常见失败情况返回标准 JSON-RPC 错误:
- 客户端不支持根目录:
-32601 (方法未找到)
- 服务器发送
roots/list 请求且没有关联的客户端到服务器请求:-32602 (无效参数)
- 内部错误:
-32603
错误示例:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Roots not supported",
"data": {
"reason": "Client does not have roots capability"
}
}
}
安全考虑
-
客户端必须:
- 仅暴露具有适当权限的根目录
- 验证所有根目录 URI 以防止路径遍历
- 实施适当的访问控制
- 监控根目录可访问性
-
服务器应该:
- 处理根目录变得不可用的情况
- 在操作期间尊重根目录边界
- 针对提供的根目录验证所有路径
实现指南
-
客户端应该:
- 在暴露根目录给服务器之前提示用户同意
- 提供清晰的根目录管理用户界面
- 暴露前验证根目录可访问性
- 监控根目录更改
-
服务器应该:
- 使用前检查根目录能力
- 优雅地处理根目录列表更改
- 在操作中尊重根目录边界
- 适当缓存根目录信息