基于MCP协议构建AI工具服务器:从原理到实践,扩展大模型能力边界

news2026/5/14 3:16:59
1. 项目概述一个连接AI与真实世界的“翻译官”如果你最近在折腾AI应用开发特别是想让大语言模型LLM能直接操作你电脑上的文件、查询数据库或者调用某个API那你大概率已经听说过“MCP”Model Context Protocol这个概念了。简单来说MCP就像是为AI模型和外部工具之间建立的一套标准“对话协议”让模型能安全、可控地使用各种外部能力。而今天要聊的这个wazionapps/mcp-server就是一个开箱即用的MCP服务器实现。你可以把它想象成一个“万能适配器”或者“翻译官”。大语言模型本身是个“大脑”它很聪明但手脚被束缚住了——它无法直接读取你本地的一个Excel文件也无法直接去查询你公司内网的数据库。这时候mcp-server就登场了。它部署在你的环境里负责接收AI模型发出的标准化指令比如“读取/home/user/data.xlsx文件”然后将其“翻译”成具体的、可执行的操作调用Python的pandas库打开文件最后再将操作结果文件内容整理成标准格式返回给AI模型。整个过程AI模型不需要知道文件具体怎么打开它只需要知道“有一个叫read_file的工具可用”这就大大扩展了AI的能力边界。这个项目特别适合两类人一是AI应用开发者你正在构建一个需要复杂工具调用的AI智能体Agent不想从零开始造轮子二是技术爱好者或效率追求者你想为自己常用的开发环境比如VS Code的Cursor、Claude Desktop等支持MCP的客户端增加一些自定义的超能力比如一键分析日志、管理Docker容器等。wazionapps/mcp-server提供了一个坚实的起点它封装了MCP的核心通信逻辑让你可以专注于实现具体的工具Tools和资源Resources快速搭建起属于自己的AI“外挂”。2. 核心架构与设计思路拆解要理解wazionapps/mcp-server的价值我们得先掰开揉碎了看看MCP协议到底在解决什么问题以及这个服务器是如何围绕这些目标来设计的。2.1 为什么需要MCP从“硬编码”到“动态发现”在没有MCP之前让AI调用外部工具通常有两种方式但都有明显短板。一种是“硬编码”在开发AI应用时开发者预先定义好一系列工具函数并把它们的描述“写死”在提示词Prompt里。比如你告诉模型“你现在可以调用get_weather(city)函数来查询天气。” 这种方式的问题在于灵活性极差。每增加、修改或删除一个工具都需要重新调整提示词并可能涉及代码发布无法实现工具的“热插拔”。另一种是依赖特定平台的封闭生态。某些AI应用平台提供了自己的工具扩展机制但你的工具只能在这个平台内使用一旦换一个客户端或环境所有工具都得重写。这造成了严重的“供应商锁定”Vendor Lock-in。MCP协议的核心创新在于“标准化”和“动态发现”。它定义了一套基于JSON-RPC的通信标准。一个MCP服务器启动后会主动向连接的客户端比如Claude Desktop“广告”自己提供了哪些工具和资源。客户端在运行时动态地获取这份清单并将其整合到给模型的上下文Context中。这意味着工具可发现AI客户端无需预先知道你有什么工具启动时一问便知。生态可移植一个按照MCP标准实现的服务器理论上可以被任何兼容MCP的客户端使用。你今天为VS Code Cursor写的文件管理工具明天也能用在Claude Desktop上。权限可控服务器运行在用户自己的环境敏感操作如读写数据库、执行命令的权限完全由用户控制避免了将敏感信息发送到云端AI服务的风险。wazionapps/mcp-server正是基于这个理念构建的。它不是一个提供具体功能的“成品”服务器而是一个框架或样板。它帮你处理了所有繁琐的底层协议通信、连接管理、消息序列化/反序列化让你可以像写普通Python函数一样快速定义出符合MCP标准的工具。2.2wazionapps/mcp-server的模块化设计打开这个项目的源码结构你能清晰地看到它的设计思路是高度模块化的mcp-server/ ├── server.py # 服务器主入口与核心事件循环 ├── protocols/ # MCP协议实现层 │ ├── mcp_protocol.py # 协议消息定义Request, Response, Notification │ └── session_handler.py # 管理客户端会话、路由请求 ├── tools/ # 工具Tools实现区 │ ├── __init__.py │ ├── file_tools.py # 示例文件操作工具 │ └── system_tools.py # 示例系统信息工具 ├── resources/ # 资源Resources实现区 │ └── __init__.py ├── clients/ # 客户端连接适配器可选 │ └── stdio_client.py # 标准输入输出适配器用于对接IDE/桌面客户端 └── config.py # 服务器配置管理核心流程是这样的你通过继承或组合的方式在tools/和resources/目录下注册你的自定义工具。启动server.py它会加载所有注册的工具和资源。当有MCP客户端如Cursor通过标准输入输出stdio或SSE连接上来时session_handler.py会接管连接。客户端发送initialize请求服务器返回能力声明包括工具列表。客户端需要时发送tools/call请求session_handler根据工具名路由到对应的工具函数执行并将结果封装成MCP响应返回。这种设计的好处是关注点分离。作为开发者你99%的时间只需要关心tools/目录下的内容实现你的业务逻辑。至于协议细节、网络通信、错误处理框架已经帮你搞定了。注意MCP中的“工具”Tools和“资源”Resources是两个关键概念容易混淆。简单区分工具是“动词”代表一个可执行的操作如read_file,run_query资源是“名词”代表一个可被读取或订阅的数据源如file:///path/to/log.txt客户端可以“读”资源的内容。wazionapps/mcp-server对两者都提供了支持框架。3. 从零开始构建你的第一个自定义工具理论讲得再多不如动手做一遍。我们以“为一个本地开发AI助手添加项目文件树浏览能力”为目标基于wazionapps/mcp-server框架实现一个list_project_files工具。3.1 环境准备与项目初始化首先你需要一个Python环境建议3.8以上。我们通过克隆和安装依赖来开始。# 1. 克隆仓库假设你fork或直接使用wazionapps的模板 git clone https://github.com/wazionapps/mcp-server.git my-mcp-server cd my-mcp-server # 2. 创建虚拟环境强烈推荐避免污染系统环境 python -m venv venv # 3. 激活虚拟环境 # Linux/macOS source venv/bin/activate # Windows venv\Scripts\activate # 4. 安装依赖 pip install -r requirements.txt # 通常基础依赖包括pydantic用于数据验证、anyio异步库等现在看一下tools/目录下的示例文件file_tools.py它已经实现了一个read_file工具。我们来依葫芦画瓢。3.2 实现list_project_files工具我们的目标是输入一个项目根目录路径工具返回该目录下的文件树结构以缩进或JSON格式并忽略一些常见的不需要给AI看的目录如.git,__pycache__,node_modules。在tools/目录下新建一个文件project_tools.pyimport os import json from pathlib import Path from typing import List, Optional from pydantic import BaseModel, Field # 从框架导入必要的装饰器和基类 from .base import Tool, ToolResult # 1. 定义工具的输入参数模型 class ListProjectFilesInput(BaseModel): 列出项目文件的输入参数 root_path: str Field( default., description项目的根目录路径。默认为当前目录。 ) max_depth: Optional[int] Field( default3, description遍历的最大深度。默认为3避免列出过深的目录。, ge1, le10 # 参数验证大于等于1小于等于10 ) exclude_dirs: Optional[List[str]] Field( default_factorylambda: [.git, __pycache__, node_modules, venv, .idea, .vscode], description需要排除的目录名列表。 ) # 2. 实现工具函数本身 async def list_project_files(root_path: str ., max_depth: int 3, exclude_dirs: List[str] None) - str: 递归列出项目目录下的文件树结构。 参数: root_path: 起始目录。 max_depth: 最大递归深度。 exclude_dirs: 要排除的目录名列表。 返回: 格式化的文件树字符串。 if exclude_dirs is None: exclude_dirs [.git, __pycache__, node_modules, venv] root Path(root_path).resolve() if not root.exists() or not root.is_dir(): return f错误路径 {root_path} 不存在或不是一个目录。 output_lines [f项目根目录: {root}] def _walk(dir_path: Path, current_depth: int, prefix: str ): if current_depth max_depth: return try: # 使用 scandir 提高效率 entries sorted(os.scandir(dir_path), keylambda e: (not e.is_dir(), e.name)) for index, entry in enumerate(entries): is_last index len(entries) - 1 connector └── if is_last else ├── # 检查是否需要排除 if entry.name in exclude_dirs and entry.is_dir(): output_lines.append(f{prefix}{connector}{entry.name}/ [已排除]) continue display_name f{entry.name}{/ if entry.is_dir() else } output_lines.append(f{prefix}{connector}{display_name}) if entry.is_dir(): extension if is_last else │ _walk(Path(entry.path), current_depth 1, prefix extension) except PermissionError: output_lines.append(f{prefix}└── [权限不足无法访问]) _walk(root, current_depth1) return \n.join(output_lines) # 3. 使用框架的装饰器将函数包装成MCP工具 # 这里假设框架提供了一个 register_tool 装饰器或类似机制。 # 实际在 wazionapps/mcp-server 中你可能需要在某个地方如 tools/__init__.py手动注册。 # 我们模拟一个注册过程 from .base import register_tool register_tool( namelist_project_files, description递归列出指定目录下的文件树结构默认排除版本控制和缓存目录。, input_modelListProjectFilesInput ) class ListProjectFilesTool(Tool): 工具类封装负责调用实际的函数 async def execute(self, input_data: ListProjectFilesInput) - ToolResult: result_text await list_project_files( root_pathinput_data.root_path, max_depthinput_data.max_depth, exclude_dirsinput_data.exclude_dirs ) # ToolResult 是框架定义的结果包装类通常包含 content 和 is_error 等字段 return ToolResult(content[{type: text, text: result_text}])关键点解析输入模型ListProjectFilesInput使用Pydantic定义这不仅是类型提示更是自动生成的工具说明书。MCP客户端会读取这个模型将其转化为AI模型能理解的工具描述包括参数名、类型、默认值、说明。清晰的描述能极大提升AI调用工具的准确性。异步函数MCP服务器通常是异步的基于asyncio以高效处理多个并发请求。工具函数最好也定义为async def。错误处理在工具函数内部我们对路径不存在的情况进行了友好提示。更复杂的错误如磁盘IO错误也应该被捕获并返回清晰的错误信息而不是抛出异常导致服务器崩溃。性能与安全max_depth参数防止遍历过深导致卡死。使用Path.resolve()解析绝对路径避免符号链接等问题。列出目录时使用os.scandir()它比os.listdir()更高效。非常重要这个工具会读取本地文件系统。在真实部署中你必须考虑沙箱或路径白名单机制防止AI被诱导去读取敏感文件如~/.ssh/id_rsa。wazionapps/mcp-server框架本身可能不提供强隔离这需要开发者自己通过配置或工具逻辑来约束。3.3 注册工具并启动服务器实现工具后需要将其注册到服务器。通常框架会在tools/__init__.py或一个专门的注册表中管理所有工具。打开tools/__init__.py你可能看到类似下面的内容from .file_tools import ReadFileTool from .system_tools import GetSystemInfoTool # 导入我们新写的工具 from .project_tools import ListProjectFilesTool # 所有可用工具的列表 __all__ [ReadFileTool, GetSystemInfoTool, ListProjectFilesTool] # 或者一个注册函数 def get_all_tools(): return [ ReadFileTool(), GetSystemInfoTool(), ListProjectFilesTool(), # 添加这一行 ]现在启动服务器。查看server.py的入口它通常会调用get_all_tools()来加载工具。# 在项目根目录下运行 python server.py如果一切正常服务器会启动并监听标准输入输出stdio等待MCP客户端连接。你会看到类似“MCP Server started...”的日志。4. 在客户端中连接与使用你的MCP服务器服务器跑起来了怎么用呢这取决于你的AI客户端。目前支持MCP的客户端越来越多如Claude Desktop、VS Code with Cursor、Continue.dev等。这里以配置相对简单的 Claude Desktop 为例。4.1 配置 Claude Desktop 连接自定义MCP服务器Claude Desktop 允许通过配置文件添加自定义的MCP服务器。找到配置文件位置macOS:~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:%APPDATA%\Claude\claude_desktop_config.jsonLinux:~/.config/Claude/claude_desktop_config.json编辑配置文件如果文件不存在就创建它。我们需要添加一个mcpServers配置项。{ mcpServers: { my-local-project-explorer: { command: /absolute/path/to/your/my-mcp-server/venv/bin/python, args: [ /absolute/path/to/your/my-mcp-server/server.py ], env: { PYTHONPATH: /absolute/path/to/your/my-mcp-server } } } }配置详解my-local-project-explorer这是你给这个服务器起的名字会在Claude内部显示。command必须是虚拟环境中Python解释器的绝对路径。这是最常见的问题来源。使用which python在激活的虚拟环境下来获取。args启动脚本server.py的绝对路径。env设置PYTHONPATH确保服务器脚本能找到你的自定义模块。重启Claude Desktop保存配置文件后完全退出并重启Claude Desktop应用。4.2 在对话中验证工具调用重启后新建一个对话。如果配置成功Claude的输入框上方可能会提示“已连接至工具”或类似信息。更直接的方式是你可以直接问它“你现在可以使用哪些工具”或者更具体地“请使用list_project_files工具查看一下/Users/YourName/Projects/my-web-app这个目录的结构深度设为2。”Claude会识别出这个工具并在后台调用你的MCP服务器。服务器执行list_project_files函数将目录树返回Claude再将其整理后呈现给你。整个过程Claude并不需要预先知道这个工具的存在也不需要理解文件系统API它只是按照MCP协议发送了一个格式化的请求。实操心得路径问题在配置command和args时使用绝对路径是最稳妥的。相对路径在复杂的启动环境下很容易出错。权限问题确保Claude Desktop有权限执行你指定的Python解释器和脚本。日志调试如果工具调用失败首先查看服务器启动时的日志以及Claude Desktop自身的日志通常可以在应用设置中找到日志文件位置。服务器代码中增加详细的日志输出如打印接收到的请求和返回的响应是快速定位问题的关键。5. 进阶实现更复杂、更实用的工具基础的目录浏览只是开始。wazionapps/mcp-server的真正威力在于你可以将任何本地或网络能力封装成AI可用的工具。下面构思几个更实用的场景。5.1 场景一数据库查询工具假设你经常需要让AI分析业务数据。你可以创建一个run_sql_query工具。# tools/database_tools.py import sqlite3 # 或用 asyncpg, aiomysql 等异步驱动 from pydantic import BaseModel, Field, SecretStr from .base import Tool, ToolResult, register_tool class SQLQueryInput(BaseModel): query: str Field(description要执行的SQL查询语句。) # 安全警告在实际生产中数据库凭据不应硬编码应从环境变量或配置文件中读取。 # 这里为了示例简化使用Pydantic的SecretStr来隐藏日志输出中的密码。 db_path: str Field(default:memory:, descriptionSQLite数据库文件路径。) register_tool(namerun_sql_query, description在指定的SQLite数据库上执行只读查询并返回结果。, input_modelSQLQueryInput) class SQLQueryTool(Tool): async def execute(self, input_data: SQLQueryInput) - ToolResult: # 1. 简单的SQL注入防护限制为SELECT语句根据需求调整 if not input_data.query.strip().upper().startswith(SELECT): return ToolResult(content[{type: text, text: 错误此工具仅支持SELECT查询。}], is_errorTrue) try: conn sqlite3.connect(input_data.db_path) cursor conn.cursor() cursor.execute(input_data.query) rows cursor.fetchall() column_names [description[0] for description in cursor.description] if cursor.description else [] conn.close() # 2. 格式化结果可以转为Markdown表格或JSON if not rows: result_text 查询成功但未返回任何数据。 else: # 简单转为Markdown表格 header | | .join(column_names) | separator | |.join([---] * len(column_names)) | data_rows [] for row in rows: data_rows.append(| | .join(str(cell) for cell in row) |) result_text \n.join([header, separator] data_rows[:20]) # 限制返回行数 if len(rows) 20: result_text f\n\n仅显示前20行共 {len(rows)} 行 return ToolResult(content[{type: text, text: result_text}]) except sqlite3.Error as e: return ToolResult(content[{type: text, text: f数据库错误: {e}}], is_errorTrue) except Exception as e: return ToolResult(content[{type: text, text: f执行查询时发生未知错误: {e}}], is_errorTrue)安全与性能考量权限最小化此工具明确只允许SELECT查询防止数据被意外修改或删除。在生产环境中你可能需要更细粒度的权限控制甚至使用具有只读权限的数据库用户。查询限制对返回的行数做了限制前20行防止一个SELECT * FROM huge_table拖垮服务器或导致响应过大。连接管理示例中为每个查询新建连接对于高频工具你需要实现一个连接池来提升性能。凭据管理绝对不要将数据库密码硬编码在代码中。应该通过环境变量、配置文件或安全的密钥管理服务传入。5.2 场景二调用外部API的工具让AI帮你查天气、翻译文本、调用公司内部API。# tools/api_tools.py import httpx from pydantic import BaseModel, Field from .base import Tool, ToolResult, register_tool class WeatherQueryInput(BaseModel): city: str Field(description城市名称例如北京、Shanghai。) units: str Field(defaultmetric, description单位制。metric 为摄氏度imperial 为华氏度。) register_tool(nameget_weather, description查询指定城市的当前天气情况。, input_modelWeatherQueryInput) class WeatherQueryTool(Tool): def __init__(self): # 从环境变量获取API Key self.api_key os.getenv(WEATHER_API_KEY) if not self.api_key: raise ValueError(未设置 WEATHER_API_KEY 环境变量。) self.base_url http://api.openweathermap.org/data/2.5/weather self.client httpx.AsyncClient(timeout10.0) # 使用异步HTTP客户端 async def execute(self, input_data: WeatherQueryInput) - ToolResult: params { q: input_data.city, appid: self.api_key, units: input_data.units } try: response await self.client.get(self.base_url, paramsparams) response.raise_for_status() data response.json() # 解析并格式化天气信息 city data.get(name, 未知城市) temp data[main][temp] feels_like data[main][feels_like] humidity data[main][humidity] description data[weather][0][description] wind_speed data[wind][speed] result_text ( f{city}的当前天气\n f- 天气状况{description}\n f- 温度{temp}°C (体感 {feels_like}°C)\n f- 湿度{humidity}%\n f- 风速{wind_speed} m/s ) return ToolResult(content[{type: text, text: result_text}]) except httpx.HTTPStatusError as e: return ToolResult(content[{type: text, text: fAPI请求失败状态码{e.response.status_code}}], is_errorTrue) except Exception as e: return ToolResult(content[{type: text, text: f获取天气信息时出错{e}}], is_errorTrue)关键设计异步HTTP客户端使用httpx.AsyncClient避免阻塞服务器事件循环。超时设置为网络请求设置合理的超时如10秒防止一个慢API拖死整个服务器。错误处理对HTTP错误状态码和网络异常进行捕获返回友好的错误信息。敏感信息API Key通过环境变量传入确保安全。5.3 场景三组合工具与工作流单个工具能力有限但AI可以串联多个工具完成复杂任务。例如你可以创建一个“分析项目日志”的复合场景AI先调用list_project_files找到日志目录。再调用read_file读取最新的日志文件。最后AI自己分析日志内容或调用另一个analyze_log_pattern工具你实现的来提取错误信息。你不需要显式地编码这个工作流。只需要把list_project_files和read_file工具都注册到服务器AI在理解了你的意图“帮我看看项目日志里最近有什么错误”后会自动规划并调用这些工具。这就是MCP和AI智能体Agent结合的强大之处动态的任务分解与工具调用。6. 生产环境部署与安全加固指南将个人玩具升级为可稳定运行的生产级服务需要考虑更多因素。6.1 部署方式选择本地进程开发/个人使用如上所述通过stdio与桌面客户端通信。最简单但服务器进程生命周期与客户端绑定。独立HTTP/SSE服务器wazionapps/mcp-server框架可能也支持以HTTP服务器或SSEServer-Sent Events模式运行。这样服务器可以独立部署在一台机器上多个客户端通过网络连接。你需要处理认证与授权谁可以连接简单的可以使用API Key。网络暴露服务器不应暴露在公网最好在内网或通过反向代理如Nginx提供有限的访问。容器化部署使用Docker封装你的MCP服务器及其所有依赖Python环境、工具脚本、配置文件。这保证了环境一致性便于分发和部署。一个简单的Dockerfile示例FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . # 假设你的入口点是 server.py CMD [python, server.py]6.2 安全加固策略安全是MCP服务器的生命线因为它赋予了AI直接操作你环境的能力。工具权限隔离沙箱路径白名单对于文件操作类工具不要允许任意路径访问。在配置中定义一个允许访问的根目录列表所有传入的路径参数都需解析并检查是否在白名单内。子进程限制对于执行命令的工具如run_shell_command必须极其谨慎。考虑使用subprocess的timeout参数并限制可执行的命令列表。更好的做法是避免提供通用shell工具而是提供具体的、安全的工具如restart_service,run_linter。网络访问控制对于调用外部API的工具可以设置允许访问的域名或IP白名单。输入验证与净化充分利用Pydantic在工具输入模型中使用Field的约束条件如ge,le,regex进行第一道验证。业务逻辑验证在工具函数内部对输入进行二次验证。例如SQL查询工具检查是否以SELECT开头。凭据与配置管理永远不要硬编码数据库密码、API密钥等必须通过环境变量、Docker Secrets或专业的密钥管理服务如HashiCorp Vault注入。配置文件安全如果使用配置文件确保其权限设置为仅当前用户可读。审计与日志记录所有工具调用的详细信息谁客户端标识、何时、调用了什么工具、输入参数是什么敏感参数如密码需脱敏、执行结果成功/失败。这便于事后审计和问题排查。6.3 性能优化与监控异步与并发确保你的工具函数是异步的并且不会进行长时间的阻塞操作如同步的CPU密集型计算。对于耗时操作考虑使用asyncio.to_thread将其放到线程池中执行避免阻塞事件循环。资源管理像数据库连接、HTTP客户端会话这类资源应该在工具类初始化时创建并在服务器生命周期内复用而不是每次调用都新建。健康检查如果以HTTP服务器模式运行暴露一个/health端点用于监控服务是否存活。指标收集可以集成像prometheus-client这样的库收集工具调用次数、耗时、错误率等指标方便监控。7. 常见问题与排查技巧实录在实际搭建和使用过程中你肯定会遇到各种问题。下面是我踩过的一些坑和解决方法。7.1 连接与配置问题问题1Claude Desktop 提示“无法连接到MCP服务器”或没有任何反应。检查点1配置文件路径和格式。确保claude_desktop_config.json文件在正确的位置并且是合法的JSON格式可以用在线JSON校验工具检查。一个多余的逗号都可能导致解析失败。检查点2命令和路径。command和args中的路径必须是绝对路径。特别是command它应该是虚拟环境中的Python可执行文件而不是系统Python。在终端中激活你的虚拟环境然后执行which python将输出的完整路径复制过来。检查点3环境变量。确保PYTHONPATH设置正确指向你的项目根目录这样Python才能找到你的server.py和自定义模块。检查点4手动测试服务器。在终端中直接用配置中的命令和参数启动服务器看是否能正常启动不报错。例如/path/to/venv/bin/python /path/to/server.py。如果这里就报错如模块导入错误那问题出在服务器代码本身。检查点5查看客户端日志。Claude Desktop通常有日志文件位置因系统而异。在日志中搜索 “mcp” 或 “server” 关键词能看到更详细的错误信息。问题2服务器启动后立即退出。可能原因服务器代码中有未捕获的异常或者在初始化工具时出错例如上面Weather工具中如果没设置WEATHER_API_KEY环境变量__init__中抛出的ValueError会导致服务器启动失败。排查在server.py的入口点添加try...except块打印异常信息。或者在命令行手动运行服务器查看标准错误输出。7.2 工具调用问题问题3AI看不到我新添加的工具。排查首先确认服务器重启后客户端如Claude Desktop也重启了。MCP工具列表是在客户端初始化连接时从服务器获取的。如果服务器更新了工具但客户端未重启它不会主动重新获取。验证你可以写一个简单的测试脚本来模拟客户端发送initialize和tools/list请求看看服务器返回的工具列表是否正确包含了你的新工具。问题4AI调用了工具但返回错误或没有结果。查看服务器日志在工具函数内部添加详细的日志打印记录接收到的参数和执行过程。这是最直接的调试方式。参数格式确认AI传递的参数符合你定义的Pydantic模型。例如如果某个参数定义为int类型但AI传递了字符串5Pydantic可能会尝试转换也可能报错。确保工具描述清晰。异步函数确认你的工具函数是async def并且在需要await的地方正确使用了await。问题5工具执行速度慢影响了AI响应速度。分析瓶颈使用import time; start time.time()在工具函数内打点找出耗时的操作。优化网络请求设置合理的超时使用连接池。文件/数据库操作考虑缓存频繁读取的数据。复杂计算如果工具涉及大量CPU计算考虑将其移出主事件循环使用asyncio.to_thread或单独的进程池。7.3 安全与权限问题问题6担心AI通过文件操作工具访问敏感文件。解决方案实现路径白名单。在工具函数开头解析请求的路径并检查其是否在以某个安全目录如你的项目目录、家目录下的特定文件夹为根目录的子树下。可以使用Path.resolve()和pathlib.PurePath.is_relative_to()Python 3.9来判断。allowed_roots [Path(/safe/path1), Path(/safe/path2)] requested_path Path(input_path).resolve() is_allowed any(requested_path.is_relative_to(root) for root in allowed_roots) if not is_allowed: return ToolResult(content[{type: text, text: 访问被拒绝路径不在允许范围内。}], is_errorTrue)问题7如何控制不同工具对不同用户的访问权限现状基础的MCP协议和wazionapps/mcp-server框架可能不包含复杂的用户身份认证和授权机制。这通常需要你在上层实现。思路如果你以HTTP服务器模式运行可以在HTTP层实现认证如JWT Token。然后将用户身份信息或角色通过某种方式如自定义的请求头传递到工具执行上下文中。在每个工具的执行逻辑里根据用户身份决定是否允许操作。这需要你对框架进行一定程度的定制。最后我个人在实际使用中的体会是wazionapps/mcp-server这类项目最大的价值在于它降低了AI工具化的门槛。它把复杂的协议通信标准化让开发者能聚焦于业务逻辑本身。开始的时候可以从一两个简单、安全、高频的工具入手比如文件搜索、日志尾随。在获得正反馈后再逐步扩展。同时务必时刻绷紧安全这根弦尤其是在考虑将服务器开放给他人使用时。一个好的实践是为每个工具都编写清晰的文档字符串并设计严谨的输入验证这不仅能提升AI调用的准确性也是对自己系统的一种保护。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2596428.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…