拓冰建站拓冰建站
首页 / 资讯中心 / 正文

使用 mcp-agent 构建 Streamlit 多 MCP 工具 Agent 聊天应用:以 Finder Agent 为例

使用 mcp-agent 构建 Streamlit 多 MCP 工具 Agent 聊天应用以 Finder Agent 为例【免费下载链接】mcp-agentBuild effective agents using Model Context Protocol and simple workflow patterns项目地址: https://gitcode.com/GitHub_Trending/mc/mcp-agent导读本文基于 mcp-agent 仓库中的streamlit_mcp_basic_agent示例examples/usecases/streamlit_mcp_basic_agent/README.md讲解如何用 Streamlit 快速搭建一个可视化聊天界面并在其后接入一个同时拥有fetch抓取 URL与filesystem读取本地文件两个 MCP 服务器的 Finder Agent。读完本文你将掌握 mcp-agent 环境搭建、MCPApp与Agent的初始化模式、Streamlitsession_state与异步 Agent 的配合技巧、会话历史回传以及基于RequestParams的增强 LLM 调用方法可直接复刻或改造成你自己的多工具聊天应用。示例的架构如下Streamlit 前端负责展示与交互Finder Agent 是决策中枢它会根据用户请求自行判断该调用哪个 MCP 服务器提供的工具┌───────────┐ ┌──────────┐ ┌──────────────┐ │ Streamlit │─────▶│ Finder │──┬──▶│ Fetch │ │ App │ │ Agent │ │ │ MCP Server │ └───────────┘ └──────────┘ │ └──────────────┘ │ ┌──────────────┐ └──▶│ Filesystem │ │ MCP Server │ └──────────────┘1. 示例整体概览一个会自己决定用哪个工具的 Finder Agent该示例展示了一个名为 Finder 的 Agent它同时接入fetch与filesystem两个 MCP 服务器因此既能获取网络 URL 的内容也能读取本地文件系统。你无需事先指定用哪个工具——Agent 会根据你的提问例如本地某个文件里写了什么或这个网页讲了什么自行判断何时调用哪个工具最终返回与请求最匹配的结果URI 与内容。从实现层面看Finder Agent 的核心逻辑定义在 examples/usecases/streamlit_mcp_basic_agent/main.py 中state await get_agent_state( keyfinder_agent, agent_classAgent, llm_classOpenAIAugmentedLLM, namefinder, instructionYou are an agent with access to the filesystem, as well as the ability to fetch URLs. Your job is to identify the closest match to a users request, make the appropriate tool calls, and return the URI and CONTENTS of the closest match., server_names[fetch, filesystem], )其中server_names[fetch, filesystem]声明了 Agent 可访问的 MCP 服务器集合instruction以自然语言的方式定义了 Agent 的职责与行为准则识别最接近请求的目标、调用合适工具、返回 URI 和内容这正是 mcp-agent 中Agent 应通过 instruction 定义其用途这一设计思想的体现——在 src/mcp_agent/agents/agent.py 中Agent类的核心字段正是name、instruction与server_names。2. 第一步克隆仓库并定位到示例目录先克隆 mcp-agent 仓库并进入示例目录git clone https://github.com/lastmile-ai/mcp-agent.git cd mcp-agent/examples/usecase/streamlit_mcp_basic_agent注本仓库中该示例的完整文件位于 examples/usecases/streamlit_mcp_basic_agent/包含main.py、mcp_agent.config.yaml、requirements.txt与mcp_agent.secrets.yaml.example。如果你还没有安装uvPython 包管理器先安装它pip install uv同步 mcp-agent 项目本身的依赖uv sync再安装本示例专属的额外依赖uv pip install -r requirements.txtrequirements.txt的内容表明除了以本地路径方式mcp-agent file://../../../指向仓库根目录引入 mcp-agent 框架外本示例还额外依赖openai驱动OpenAIAugmentedLLM与streamlit前端界面# Core framework dependency mcp-agent file://../../../ # Link to the local mcp-agent project root # Additional dependencies specific to this example openai streamlit3. 第二步配置密钥与环境变量复制密钥模板并填写真实配置cp mcp_agent.secrets.yaml.example mcp_agent.secrets.yaml然后打开mcp_agent.secrets.yaml为你选择的 LLM 提供商填入 API Key。模板文件 examples/usecases/streamlit_mcp_basic_agent/mcp_agent.secrets.yaml.example 的默认结构同时预留了 OpenAI 与 Anthropic 两家的密钥位置$schema: ../../../schema/mcp-agent.config.schema.json openai: api_key: openai_api_key anthropic: api_key: anthropic_api_key安全实践mcp_agent.secrets.yaml存放真实密钥应当加入.gitignore切勿提交到版本库。示例中mcp_agent.config.yaml内的注释也明确提示Secrets (API keys, etc.) are stored in an mcp_agent.secrets.yaml file which can be gitignored。4. 第三步在本地运行 Streamlit 应用一切就绪后用uv启动uv run streamlit run main.py启动后浏览器会自动打开 Streamlit 界面默认 http://localhost:8501。在输入框中输入任意与本地文件或 URL 相关的问题Finder Agent 就会开始工作。5. 深入理解应用是如何组装起来的main.py是理解整个示例的关键。它的组装链路可以拆成四层5.1 创建应用入口MCPAppif __name__ __main__: app MCPApp(namemcp_basic_agent) asyncio.run(main())MCPApp是 mcp-agent 的主应用类负责管理全局状态并托管工作流。从 src/mcp_agent/app.py 的实现看它在构造时会自动加载配置当不显式传入settings时会通过get_settings()从mcp_agent.config.yaml读取配置当传入的是字符串时则被当作配置文件路径处理。MCPApp还负责注册 task/decorator/signal 等注册表、初始化日志与追踪系统。在示例的main()中第一行就是await app.initialize()initialize()会完成环境绑定如加载.env文件、创建全局Context、初始化 MCP 服务器连接所需的执行器与服务器注册表等基础设施。5.2 初始化 Agent 并挂载 LLMget_agent_state示例定义了一个AgentState数据类作为 Agent 及其关联 LLM 的容器dataclass class AgentState: Container for agent and its associated LLM agent: Agent llm: Optional[OpenAIAugmentedLLM] None随后get_agent_state是面向 Streamlit 的关键封装——它负责获取或创建 Agent 状态若从会话中取回则重新初始化连接async def get_agent_state( key: str, agent_class: Type[Agent], llm_class: Optional[Type[T]] None, **agent_kwargs, ) - AgentState: if key not in st.session_state: # Create new agent agent agent_class( connection_persistenceFalse, **agent_kwargs, ) await agent.initialize() # Attach LLM if specified llm None if llm_class: llm await agent.attach_llm(llm_class) state: AgentState AgentState(agentagent, llmllm) st.session_state[key] state else: state st.session_state[key] return state这里有两个重要的技术细节connection_persistenceFalse在 Streamlit 这类每次交互可能重新运行脚本的场景中MCP 服务器连接不持久化避免会话复用导致连接状态失效。Agent类的该字段在 src/mcp_agent/agents/agent.py 中默认值为True持久化连接本示例显式关闭以适配 Streamlit 的重运行模型。agent.initialize()与agent.attach_llm(llm_class)initialize()会通过执行器向server_names中声明的 MCP 服务器发起连接并聚合各服务器的工具、提示词、资源元数据从源码看初始化结果会填充_namespaced_tool_map、_server_to_tool_map等内部映射agent.list_tools()后续正是基于这些映射返回工具列表。attach_llm(llm_factory)则为 Agent 创建AugmentedLLM实例此处为OpenAIAugmentedLLM并把 Agent 的instruction关联到 LLM 上。由于st.session_state中缓存的是可序列化之外的对象引用脚本重跑时从 session 取回的 Agent 需要重新建立连接因此该封装把创建与复用两条路径都收敛到了一处。5.3 展示 Agent 可见的工具清单list_toolstools await state.agent.list_tools() tools_str format_list_tools_result(tools)format_list_tools_result将ListToolsResult渲染为 Markdown 列表def format_list_tools_result(list_tools_result: ListToolsResult): res for tool in list_tools_result.tools: res f- **{tool.name}**: {tool.description}\n\n return res随后在界面中通过可折叠区域展示with st.expander(View Tools): st.markdown(tools_str)用户展开 View Tools 即可看到 Finder Agent 当前实际可用的全部工具来自fetch与filesystem两个服务器的工具会被聚合在一起。5.4 搭建聊天界面与消息循环界面主体分为三部分标题区st.title( Basic Agent Chatbot) st.caption( A Streamlit chatbot powered by mcp-agent)消息历史渲染if messages not in st.session_state: st.session_state[messages] [ {role: assistant, content: How can I help you?} ] for msg in st.session_state[messages]: st.chat_message(msg[role]).write(msg[content])输入与生成if prompt : st.chat_input(Type your message here...): st.session_state[messages].append({role: user, content: prompt}) st.chat_message(user).write(prompt) with st.chat_message(assistant): response with st.spinner(Thinking...): # Pass the conversation history to the LLM conversation_history st.session_state[messages][ 1: ] # Skip the initial greeting response await state.llm.generate_str( messageprompt, request_paramsRequestParams( use_historyTrue, historyconversation_history, # Pass the conversation history ), ) st.markdown(response) st.session_state[messages].append({role: assistant, content: response})这段代码的要点用户输入被追加进st.session_state[messages]后脚本用conversation_history st.session_state[messages][1:]切片跳过系统欢迎语把真实对话历史传给 LLM实现多轮上下文理解。state.llm.generate_str(...)是AugmentedLLMProtocol定义的增强生成接口见 src/mcp_agent/workflows/llm/augmented_llm.py它返回字符串形式的生成结果。与普通 LLM 调用不同generate_str内部会运行最多max_iterations默认 10 次的多轮 agentic 循环——模型在循环中自主决定调用哪个 MCP 工具、读取返回结果、继续推理直到得出最终答案。这正是 Finder Agent 自己判断何时用 fetch、何时用 filesystem的能力来源。由于main()是异步函数入口处使用asyncio.run(main())驱动整个事件循环Streamlit 的st.spinner保证了生成期间的界面反馈。5.5RequestParams控制生成行为示例用RequestParams(use_historyTrue, historyconversation_history)显式开启历史注入。RequestParams在 src/mcp_agent/workflows/llm/augmented_llm.py 中定义它继承自 MCP 的CreateMessageRequestParams并扩展了若干生成参数常用字段包括字段默认值含义use_historyTrue是否在生成请求中包含消息历史history无显式传入的历史消息列表配合use_historyTrue使用maxTokens2048允许采样的最大 token 数max_iterations10LLM 循环运行的最大迭代次数工具调用链深度上限modelNone指定生成使用的模型覆盖modelPreferences选择逻辑parallel_tool_callsFalse是否允许并行工具调用reasoning_effortNone仅 OpenAI 系控制 o1/o3/o4/gpt-5 系列模型的推理强度none/low/medium/high在 Finder 场景中把use_historyTrue与传入的历史切片组合即可保证多轮对话中模型始终记得之前问过什么从而在连续追问时做出正确的工具选择。6. 配置文件解析MCP 服务器与模型声明示例的 mcp_agent.config.yaml 声明了执行引擎、日志与两个 MCP 服务器$schema: ../../../schema/mcp-agent.config.schema.json execution_engine: asyncio logger: type: console level: debug batch_size: 100 flush_interval: 2 max_queue_size: 2048 http_endpoint: http_headers: http_timeout: 5 progress_display: false mcp: servers: fetch: command: uvx args: [mcp-server-fetch] filesystem: command: npx args: [-y, modelcontextprotocol/server-filesystem, .] openai: # Secrets (API keys, etc.) are stored in an mcp_agent.secrets.yaml file which can be gitignored default_model: gpt-4o各段含义execution_engine: asyncio选择 asyncio 作为执行引擎mcp-agent 也支持 Temporal 等引擎详见 docs/concepts/execution-engines.mdx。logger控制台日志输出level: debug便于开发期观察工具调用与事件流batch_size、flush_interval、max_queue_size等字段控制异步日志队列行为。mcp.servers以命令 参数方式声明两个 stdio 型 MCP 服务器。fetch通过uvx运行mcp-server-fetch提供 URL 抓取能力filesystem通过npx运行官方modelcontextprotocol/server-filesystem其参数.表示把当前目录作为可访问根目录。openai.default_model: gpt-4o指定默认使用 GPT-4o 模型OpenAIAugmentedLLM正是基于该配置驱动工具调用循环。真正的api_key放在mcp_agent.secrets.yaml中配置文件与密钥文件分离。依赖提示fetch服务器要求环境可运行uvx安装uv后可用filesystem服务器要求环境可运行npxNode.js 生态首次运行会自动下载modelcontextprotocol/server-filesystem包。若机器上缺少对应运行时Agent 初始化阶段会因无法拉起子进程而失败。7. 工作原理小结一条从界面到 MCP 服务器的完整链路结合源码整个应用的一次对话请求会经历如下链路Streamlit 捕获输入并更新st.session_state[messages]main()从 session 中取出或重建Finder Agent 与OpenAIAugmentedLLMllm.generate_str(message, RequestParams(use_historyTrue, history...))启动 agentic 生成循环模型在循环中根据server_names暴露的工具集选择调用fetch或filesystem的工具工具调用经由MCPAggregator与各服务器会话stdin/stdout 传输执行结果回填给模型继续推理src/mcp_agent/mcp/mcp_aggregator.py循环收敛后返回最终字符串Streamlit 以st.markdown渲染并追加到消息历史供下一轮继续使用。8. 扩展思路基于该示例可以低成本地演进出更多能力更换 MCP 服务器在mcp_agent.config.yaml中新增服务器条目并在server_names中声明即可让 Finder Agent 拥有数据库查询、HTTP 请求、浏览器操作等新工具无需改动界面代码。更换模型提供商OpenAIAugmentedLLM替换为其他AugmentedLLM子类或调整openai.default_model即可切换后端模型。接入流式输出改用generate_str_stream逐 token 渲染提升长回复的实时体验。接入结构化输出使用generate_structured让模型输出受 Pydantic 模型约束的结构化结果便于后续程序化处理。参考与延伸阅读示例源码examples/usecases/streamlit_mcp_basic_agent/main.py示例配置examples/usecases/streamlit_mcp_basic_agent/mcp_agent.config.yaml示例密钥模板examples/usecases/streamlit_mcp_basic_agent/mcp_agent.secrets.yaml.exampleAgent类实现src/mcp_agent/agents/agent.pyMCPApp应用入口src/mcp_agent/app.pyRequestParams与AugmentedLLM定义src/mcp_agent/workflows/llm/augmented_llm.pyOpenAIAugmentedLLM实现src/mcp_agent/workflows/llm/augmented_llm_openai.py配置项与执行引擎说明docs/configuration.mdx、docs/concepts/execution-engines.mdx更多 MCP 接入示例examples/mcp/【免费下载链接】mcp-agentBuild effective agents using Model Context Protocol and simple workflow patterns项目地址: https://gitcode.com/GitHub_Trending/mc/mcp-agent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门