IntentKit Tools 开发指南:从原生工具到 MCP 服务器集成的完整实战手册 📅 发布时间:2026/9/17 5:10:24 👁 浏览次数: IntentKit Tools 开发指南从原生工具到 MCP 服务器集成的完整实战手册【免费下载链接】intentkitIntentKit is an open-source, self-hosted cloud agent cluster that manages a collaborative team of AI agents for you.项目地址: https://gitcode.com/GitHub_Trending/int/intentkit导读本文是 IntentKit 开源仓库中 agent_docs/tool_development.md 的深度扩展版面向希望在 IntentKit 中为 AI Agent 添加新能力的开发者。你将掌握两种工具开发路径一是原生Native工具——在 Python 中直接实现、拥有细粒度开关与版本化 schema 的能力扩展二是MCP 工具类别集成——以极少量代码把任意远程 MCP 服务器包装成工具类别由框架自动完成工具发现、schema 生成与运行时调用。文中所有配置、接口与流程均以当前仓库源码为依据并给出可直接对照的实现路径。工具体系总览IntentKit 是一个开源的、可自托管的云 Agent 集群为 Agent 团队提供协作能力。工具的载体是intentkit/tools/目录每个子目录就是一个工具类别Tool Category一个类别下可以包含多个工具类别既可以按功能主题划分也可以按品牌如 Twitter、CoinGecko划分。从 agent_docs/tool_development.md 的定义看创建工具类别有两种方式原生工具Native tools直接在 Python 中实现工具拥有完整控制力MCP 包装工具MCP-wrapped tools把远程 MCP 服务器包装为工具类别代码量极小。无论哪种方式都需要遵守一条硬性依赖规则工具只能依赖models、abstracts、utils、clients四个模块中的内容以避免循环依赖详见 依赖规则。原生工具类别的标准结构一个原生工具类别文件夹需要包含以下要素范式可参考现有实现 intentkit/tools/twitter/。1. 基类base.py基类继承自IntentKitTool定义于 intentkit/tools/base.py把本类别共用的函数写在基类里。最典型的例子就是get_api_key以 intentkit/tools/twitter/base.py 为例它从context.agent.tool_config(self.category)中读取配置并校验consumer_key、consumer_secret、access_token、access_token_secret四个必需字段缺失时抛出ToolException。IntentKitTool还预置了一批开箱即用的能力全部定义于 intentkit/tools/base.py异常处理策略handle_tool_error与handle_validation_error被覆写为默认处理器L73-L82工具抛出的异常会以tool error: ...的形式返回给 Agent限流能力提供user_rate_limit/global_rate_limit及其按工具_by_tool与按类别_by_category四个变体L97-L233底层基于 Redis 的INCREXPIRE原子操作实现超限时抛出RateLimitExceeded工具级持久化get/save/delete_agent_tool_data与get/save_thread_tool_dataL247-L306分别把数据持久化到 Agent 作用域AgentToolData与当前会话作用域ChatToolData上下文访问get_context()通过 LangGraph 运行时取出AgentContextL240-L245内含agent_id、chat_id、user_id等信息。此外基类还定义了price默认Decimal(1)与available()钩子价格注册表build_tool_prices()L324-L362会在启动时递归扫描所有工具子类把{name: price}收集为全局价格表。2. 单个工具文件每个工具拥有独立文件文件名与工具名保持一致。以 intentkit/tools/twitter/post_tweet.py 为范式关键点如下类继承工具类继承本类别的BaseClass如TwitterPostTweet(TwitterBaseTool)Name 属性name必须带类别前缀如twitter_post_tweet保证全系统唯一Description 属性description是给 LLM 看的工具说明直接影响模型选工具Args Schemaargs_schema是 Pydantic 参数模型例如TwitterPostTweetInput定义了text必填最大 25000 字符与image可选图片 URL两个字段主逻辑_arun方法这是工具的核心实现。其特殊之处在于可通过IntentKitTool提供的context_from_config/get_context()从 LangChain runnable config 中获取上下文遇到异常直接向上抛出即可Agent 有专门的模块兜底处理工具异常无需自行捕获详见下文异常处理若返回值不是字符串建议在description中注明返回格式。post_tweet.py还展示了几个工程细节使用price: Decimal Decimal(60)覆盖默认价格对图片 URL 校验是否来自系统 S3 CDNconfig.aws_s3_cdn_url非 CDN 图片会被忽略并附带警告信息返回对非 OAuth 场景调用check_rate_limit(max_requests24, interval1440)做每日限额。3. 初始化文件__init__.py__init__.py必须导出以下两个函数契约由 intentkit/core/executor.py 强制校验async def get_tools( config: Config, is_private: bool, **_, ) - list[OpenAIBaseTool]Config继承自ToolsetConfig定义于 intentkit/tools/base.py其states是一个 dictkey 为工具名、value 为工具状态。若类别需要 Agent 创建者配置其他字段可自行扩展 Config。ToolsetConfig的基础形态包含enabled: bool与states: Any两个键Caching无状态工具可添加模块级_cache字典避免每次重复创建对象——intentkit/tools/twitter/init.py 就是系统级缓存的标准写法Available 检查同时必须提供available()函数def available() - bool: Check if this tool category is available based on system config.该函数用于检查所需系统配置变量是否存在若工具依赖平台托管的 API key如config.tavily_api_key则返回该 key 是否存在若工具只使用 Agent 所有者自带的 key则直接返回True。twitter 的实现 就是检查twitter_oauth2_client_id与twitter_oauth2_client_secret是否同时存在。4. 视觉素材图标类别文件夹内需要一张方形图标schema.json通过x-icon字段引用x-icon: /tools/{category_name}/{icon_filename}.{ext}支持 SVG、PNG、JPEG、WebP 四种格式图标由 API 在GET /tools/{category}/{icon_name}.{ext}路径下对外提供。仓库中 twitter 类别使用的即 intentkit/tools/twitter/twitter.png。5. 配置 Schemaschema.json为配置补充schema.json文件格式遵循 JSON Schema draft-07。由于 Config 继承自ToolsetConfig可直接参考现有类别如 intentkit/tools/twitter/schema.json的写法。该文件的要点顶层enabled布尔字段默认falsestates对象为每个工具声明enum: [disabled, public, private]三态并配x-enum-title呈现Disabled / Agent Owner All Users / Agent Owner Only的可读文案敏感凭证字段如consumer_key标记x-sensitive: true支持if/then条件校验——twitter 的 schema 中当enabled: true时强制要求四个凭证字段x-tags取值必须来自固定列表AI、Analytics、Audio、Communication、Crypto、DeFi、Developer Tools、Entertainment、Identity、Image、Infrastructure、Knowledge Base、NFT、Search、Social。异常处理约定工具内无需捕获异常Agent 有专门的模块负责拦截工具异常并向 LLM 反馈。如需补充额外信息可以捕获后重新抛出合适的异常类型。在 intentkit/tools/twitter/post_tweet.py 中可以观察到捕获 → 包装上下文 → 重抛的标准写法异常信息被加上[agent:{context.agent_id}]前缀后以原类型重抛。而 MCP 工具侧McpToolTool._arun会把McpToolError及任何未知异常统一包装为ToolException再抛出见 intentkit/tools/mcp/tool.py最终交由 Agent 处理。MCP 工具类别集成MCPModel Context Protocol是连接 LLM 与外部工具/数据源的标准协议。IntentKit 可以把任意远程 MCP 服务器包装成一个工具类别框架自动完成工具发现、schema 生成与运行时调用——你只需注册服务器并运行同步脚本。架构分层intentkit/clients/mcp/ # MCP 协议客户端clients 层 ├── registry.py # 服务器定义McpServerDef └── client.py # HTTP 客户端SSE / Streamable HTTP 传输 intentkit/tools/mcp/ # MCP → IntentKit 工具适配器tools 层 ├── wrapper.py # McpCategoryModule — 提供 get_tools/available/Config └── tool.py # McpToolTool — 把单个 MCP 工具包装为 IntentKit 工具 intentkit/tools/mcp_{name}/ # 生成的按服务器划分的工具类别 ├── __init__.py # 薄封装由同步脚本自动生成 ├── schema.json # 工具状态 配置由同步脚本自动生成 └── {name}.{ext} # 图标手动添加 scripts/sync_mcp_schemas.py # 生成固定的 schema.json __init__.py 样板粗粒度、防漂移的配置设计这是 MCP 集成最重要的设计决策远程 MCP 服务器拥有自己的工具列表且随时可能变更因此 MCP 类别不会对单个工具做快照或开关。其schema.json只携带一个服务器级可见性开关以服务器名为 key开启后Agent 获得服务器当前提供的全部工具——这些工具在运行时实时发现。由于 schema 从不枚举具体工具服务器变更时 schema 也不会过期无需重新同步。代价是 UI 中无法对单个工具做开关。如果确实需要按工具控制或重度依赖某供应商的数据应改写成原生工具类别其 schema 与代码一起纳入版本管理。这一点在 agent_docs/tool_development.md 的 MCP 章节中明确强调。分步实操接入一个新的 MCP 服务器步骤 1添加 API key 配置如需要若 MCP 服务器需要 API key在 intentkit/config/config.py 中追加配置项。仓库内已有的例子是第 237 行的self.coingecko_api_key: str | None self.load(COINGECKO_API_KEY)步骤 2在注册表中登记服务器向 intentkit/clients/mcp/registry.py 的MCP_SERVERS字典添加条目mcp_myservice: McpServerDef( namemcp_myservice, # 必须与 dict key 及 tools/ 目录名一致 display_nameMy Service, # UI 展示的人类可读名称 descriptionWhat this service does, urlhttps://mcp.myservice.com/sse, # MCP 服务器端点 transportsse, # sse 或 streamable_http api_key_config_attrmy_service_api_key, # config.py 中的属性名或 None api_key_headerAuthorization, # 携带 key 的 HTTP 头或 None api_key_prefixBearer, # key 前缀或 None 表示裸 key tags[Developer Tools], # 取自上方 x-tags 列表 ),McpServerDef是frozenTrue的 dataclass字段语义见 intentkit/clients/mcp/registry.py。关键字段name— 必须是mcp_{service}且与MCP_SERVERS的 dict key 一致transport—sse走 Server-Sent Eventsstreamable_http走 HTTP 流式传输api_key_config_attr— 服务器无需鉴权时设为Noneapi_key_prefix— 设为None则发送不带前缀的裸 key。仓库内置的 CoinGecko 示例 展示了api_key_prefixNone且自定义 headerx-cg-demo-api-key的用法在 intentkit/clients/mcp/client.py 的_build_headers中可以看到前缀拼接逻辑有前缀时发送{prefix} {api_key}无前缀时发送裸 key。步骤 3运行同步脚本source .venv/bin/activate python scripts/sync_mcp_schemas.py脚本逻辑见 scripts/sync_mcp_schemas.pyschema 形状只来自服务器定义而非实时工具列表——脚本对服务器的探测仅为信息性可达性检查探测失败不会中止同步工具仍在运行时发现。同步会生成intentkit/tools/mcp_myservice/__init__.py— 薄封装委托给McpCategoryModuleintentkit/tools/mcp_myservice/schema.json— 包含enabled、唯一的服务器级可见性开关states以及可选的api_key字段。脚本还会保留现有 schema.json 中手工添加的x-icon字段L139-L146__init__.py只有不存在或为自动生成内容时才会覆写L149-L155。生成后的__init__.py形如 intentkit/tools/mcp_coingecko/init.py。步骤 4添加图标下载服务官方 logo方形SVG/PNG/JPEG/WebP放入工具目录intentkit/tools/mcp_myservice/myservice.svg然后在schema.json的title之后添加x-icon: /tools/mcp_myservice/myservice.svg,步骤 5验证工具类别由执行器通过importlib.import_module(fintentkit.tools.{k})自动发现无需手工注册——见 intentkit/core/executor.py 与 intentkit/tools/availability.pyavailable()在无需 API key 或系统级 key 已配置时返回Trueintentkit/tools/mcp/wrapper.pyAgent 所有者还可以通过工具配置中的api_key字段提供按 Agent 的独立 key。运行时工作机制门控GatingMcpCategoryModule.get_tools()读取服务器级可见性states[server_name]intentkit/tools/mcp/wrapper.py。值为public时总是开启为private且调用者是所有者时开启否则返回空列表。判定逻辑复用is_tool_visible()intentkit/tools/base.py发现Discovery开启后向服务器查询当前工具列表并全部暴露不做单工具过滤。结果以{(server_name, api_key): (instances, timestamp)}为键缓存 1 小时intentkit/tools/mcp/wrapper.py——缓存 key 包含解析后的 API key因为同一服务器对不同 key 可能暴露不同工具集执行ExecutionMcpToolTool._arun()调用call_mcp_tool()打开 MCP 会话、按原始未加前缀工具名调用远程工具并返回文本结果intentkit/tools/mcp/tool.py。协议层call_mcp_tool位于 intentkit/clients/mcp/client.py它会检查result.isError并拼接全部TextContent工具名映射逻辑在create_mcp_toolintentkit/tools/mcp/tool.py——LangChain 侧名称加{server_name}_前缀防冲突远程只认原名API key 解析McpToolTool._resolve_api_key()intentkit/tools/mcp/tool.py遵循按 Agent 的 key 优先于系统 key的优先级先从context.agent.tool_config(category)取api_key没有则回落到系统配置。Schema 自动生成的细节scripts/sync_mcp_schemas.py 的generate_schema揭示了生成 schema 的完整形态顶层为$schemadraft-07、type: object、title、description、x-tagsproperties含enabled默认false与statesstates内是单个服务器级开关enum为[disabled, public, private]默认disabled并带x-enum-title可读文案。若服务器需要鉴权api_key_config_attr非空还会追加可选的api_key字段标记x-sensitive: true说明为留空则使用系统 key。结语两种工具开发路径各有适用场景需要细粒度按工具开关、重度依赖供应商数据或追求 schema 版本化时选择原生工具参考 intentkit/tools/twitter/ 的完整实现希望以最小成本接入外部 MCP 生态、且能接受粗粒度服务器级开关时选择MCP 包装参考 intentkit/tools/mcp_coingecko/ 与 intentkit/clients/mcp/ 的既有实现。无论哪条路径遵守依赖规则、__init__.py双函数契约与schema.json规范就能让新工具被执行器自动发现、被 Agent 正确选用。仓库中的测试如 tests/tools/test_tool_listing.py、tests/tools/test_tool_registry.py、tests/tools/test_mcp_wrapper.py可进一步帮助你验证工具注册、可用性与 schema 状态同步行为。【免费下载链接】intentkitIntentKit is an open-source, self-hosted cloud agent cluster that manages a collaborative team of AI agents for you.项目地址: https://gitcode.com/GitHub_Trending/int/intentkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考