Skip to main content

Roots 演练

交互式练习:对照下面这个完整的 MCP 聊天项目,逐步查看根目录(roots)如何在客户端定义并通过回调提供给服务器,以及服务器如何读取根目录列表并据此授权文件访问。点击"下一步"会自动打开对应文件并高亮相关代码。

教程步骤

让我们通过一个示例项目来更好地了解如何实现此功能。

理想情况下,用户将指定 MCP 服务器可以访问哪些文件/文件夹。

该程序设置为接受一个 CLI 参数列表,这些参数被解释为用户希望允许访问的路径。

该路径列表在第 42 行提供给 MCPClient。

import asyncio
import sys
import os
from dotenv import load_dotenv
from contextlib import AsyncExitStack
from mcp_client import MCPClient
from core.claude import Claude
from core.cli_chat import CliChat
from core.cli import CliApp
load_dotenv()
# Anthropic Config
claude_model = os.getenv("CLAUDE_MODEL", "claude-sonnet-4-5")
anthropic_api_key = os.getenv("ANTHROPIC_API_KEY", "")
assert claude_model, "Error: CLAUDE_MODEL cannot be empty. Update .env"
assert anthropic_api_key, (
"Error: ANTHROPIC_API_KEY cannot be empty. Update .env"
)
async def main():
claude_service = Claude(model=claude_model)
# Get root directories from command line arguments
root_paths = sys.argv[1:]
if not root_paths:
print("Usage: uv run main.py <root1> [root2] ...")
print("Example: uv run main.py /path/to/videos /another/path")
sys.exit(1)
clients = {}
async with AsyncExitStack() as stack:
# Create the MCP client with the provided root directories
doc_client = await stack.enter_async_context(
MCPClient(
command="uv", args=["run", "mcp_server.py"], roots=root_paths
)
)
clients["doc_client"] = doc_client
chat = CliChat(
doc_client=doc_client,
clients=clients,
claude_service=claude_service,
)
cli = CliApp(chat)
await cli.initialize()
await cli.run()
if __name__ == "__main__":
if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
asyncio.run(main())