理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP?
模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。
MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。
可以把它想象成你的 AI 模型 和想要使用它们的应用程序之间的通用翻译器。就像 HTTP 帮助 Web 浏览器与 Web 服务器通信一样,MCP 帮助应用程序与 AI 模型通信!
模型上下文协议架构
🚀 为什么选择 MCP?
模型的好坏取决于提供给它们的上下文。我们可以拥有一个近在咫尺的强大模型,但如果它没有能力连接外部世界并检索必要的数据和上下文,那么它就不会像它可能的那样有用。
我们将要用 MCP 做的所有事情,没有 MCP 也能实现。但是,想想要让 LLM 更具推理能力,我们需要连接的每一个工具。假设我们必须使用不同的 API 来满足不同的服务需求。但每个服务提供商构建其 API 的方式可能不同,甚至使用不同的语言。
在这里,我们希望确保我们使用同一种语言与所有必需的 API 进行通信。这就是 MCP 发挥作用的地方。它标准化了我们的 AI 应用程序与外部系统的交互方式。它有助于我们一次性构建所需的功能并重复使用,而不是根据不同的数据源一次又一次地为它们构建相同的集成。
💪 MCP 的主要优势
🔌 即插即用集成
- 连接任何 AI 模型到任何应用程序
- 切换模型时无需重写代码
- 标准化的通信协议
🛠️ 工具优先方法
- 模型将其能力作为工具暴露出来
- 应用程序可以动态发现和使用工具
- 非常适合智能体和自治系统
🌐 语言无关
- 可以用任何编程语言编写客户端
- 模型可以用任何框架实现
- 实现整个 AI 生态系统的真正互操作性
⚡ 实时通信
- 支持服务器发送事件 (SSE)
- 结果可用时流式传输
- 非常适合聊天应用程序和交互式系统
🏗️ 架构深入探讨
🖥️ 服务端 (server.py)
@mcp.tool()
def add_data(query: str) -> bool:"""Add new data to the people table""" // 使用 SQL INSERT 查询向 people 表添加新数据# Tool implementation // 工具实现
服务端:
- 📝 将工具定义为简单的 Python 函数
- 🎯 通过 MCP 装饰器暴露工具
- 🔄 处理请求并返回响应
- 📚 维护工具文档和模式 (schema)
📡 服务端 (server.py) 组件
- FastMCP 服务器
- MCP 工具
- 数据库管理
- 错误处理
👥 客户端 (langchain_client.py)
class LangchainMCPClient:async def initialize_agent(self):"""Initialize the agent with tools""" // 使用工具初始化智能体# Client implementation // 客户端实现
客户端:
- 🤝 连接到 MCP 服务器
- 🔍 发现可用工具
- 🤖 创建一个 AI 智能体来使用工具
- 💬 处理用户交互
👥 客户端组件 (langchain_client.py)
- LangChain 集成
- 智能体系统
- 工具管理
- 对话历史
🔗 MCP 层
- 工具注册
- 请求处理
- 响应处理
- 事件流
🔄 工作流
-
🚀 服务器启动
- 服务器初始化并加载工具
- 工具注册其能力
- 服务器开始监听连接
-
🤝 客户端连接
- 客户端发现服务器
- 获取可用工具
- 创建具有工具访问权限的智能体
-
💬 用户交互
- 用户发送请求
- 智能体处理请求
- 工具在服务器上执行
- 结果返回给用户
-
📊 数据流
添加记录:
用户: "add John 30 Engineer" // 添加 John 30 岁 工程师 ↓ 智能体: Formats SQL query // 格式化 SQL 查询 ↓ MCP 工具: INSERT INTO people VALUES ('John', 30, 'Engineer') ↓ 服务器: Executes SQL // 执行 SQL ↓ 数据库: Stores data // 存储数据 ↓ 响应: "Successfully added John (age: 30, profession: Engineer)" // 成功添加 John(年龄:30,职业:工程师)
读取记录:
用户: "show all records" // 显示所有记录 ↓ 智能体: Formats SELECT query // 格式化 SELECT 查询 ↓ MCP 工具: SELECT * FROM people ↓ 服务器: Fetches data // 获取数据 ↓ 客户端: Formats table // 格式化表格 ↓ 响应: Displays formatted table // 显示格式化表格
🎯 真实世界示例
我们经常使用 Cursor IDE 或 Claude Desktop 作为 MCP 主机,其中客户端依赖于外部 LLM(Claude Sonnet, GPT-4 等)。虽然这些工具非常出色,但在某些情况下——尤其是在处理敏感数据时——完全安全和私密的 MCP 客户端至关重要。在我们的实现中,我们创建了一个由本地 LLM 驱动的 MCP 客户端,该客户端可以向 SQLite 数据库添加行并从 SQLite(数据库管理系统)中选择行,其中:
- 📥 添加数据
- 用户请求添加人员
- 智能体格式化 SQL 查询
- MCP 工具执行查询
- 确认信息返回给用户
- 📤 读取数据
- 用户请求查看记录
- 智能体创建 SELECT 查询
- MCP 工具获取数据
- 结果格式化为漂亮的表格
🛠️ MCP 实现的技术栈
1. 🐍 Python 框架和库
- Python 3.x — 核心编程语言
- FastMCP — MCP 服务器实现
- LangChain — AI/LLM 框架集成
- SQLite3 — 数据库管理
- asyncio — 异步 I/O 操作
- nest_asyncio — 嵌套事件循环支持
2. 🤖 AI/LLM 集成
- Ollama — 本地 LLM 模型托管(“llama3.2”)
3. 🗃️ 数据库层
- SQLite — 轻量级数据库
def init_db():conn = sqlite3.connect('demo.db')cursor = conn.cursor()# Schema creation... // 模式创建...
4. 🔌 通信协议
- SSE (服务器发送事件) — 实时更新
- MCP 协议 — 工具通信
server_config = {"default": {"url": f"{mcp_server_url}/sse","transport": "sse","options": {...}}}
代码实现
- 安装所需库
# 🔄 核心 MCP 和 LangChain 包
pip install langchain # LangChain 框架
pip install langchain-core # 核心 LangChain 功能
pip install langchain-community # 社区工具和集成
pip install langchain-mcp-adapters # 用于 LangChain 的 MCP 适配器
pip install fastmcp # FastMCP 服务器实现# 🤖 LLM 集成
pip install langchain-ollama # LangChain 的 Ollama 集成# 🔌 网络和异步
pip install httpx # 异步 HTTP 客户端
pip install nest-asyncio # 嵌套异步支持
- server.py
import sqlite3
import argparse
from mcp.server.fastmcp import FastMCPmcp = FastMCP('sqlite-demo') // 初始化 FastMCP 实例def init_db():conn = sqlite3.connect('demo.db') // 连接数据库cursor = conn.cursor()cursor.execute('''CREATE TABLE IF NOT EXISTS people ( // 如果 people 表不存在则创建id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,age INTEGER NOT NULL,profession TEXT NOT NULL)''')conn.commit()return conn, cursor@mcp.tool() // 定义为 MCP 工具
def add_data(query: str) -> bool:"""使用 SQL INSERT 查询向 people 表添加新数据。Args:query (str): SQL INSERT 查询,遵循以下格式:INSERT INTO people (name, age, profession)VALUES ('John Doe', 30, 'Engineer')Schema (模式):- name: 文本字段 (必需)- age: 整数字段 (必需)- profession: 文本字段 (必需)注意:'id' 字段是自动生成的Returns:bool: 如果数据添加成功则返回 True,否则返回 FalseExample (示例):>>> query = '''... INSERT INTO people (name, age, profession)... VALUES ('Alice Smith', 25, 'Developer')... '''>>> add_data(query)True"""conn, cursor = init_db()try:print(f"\n\n正在使用查询执行 add_data:{query}")cursor.execute(query)conn.commit()return Trueexcept sqlite3.Error as e:print(f"添加数据时出错:{e}")return Falsefinally:conn.close()@mcp.tool() // 定义为 MCP 工具
def read_data(query: str = "SELECT * FROM people") -> list:"""使用 SQL SELECT 查询从 people 表读取数据。Args:query (str, optional): SQL SELECT 查询。默认为 "SELECT * FROM people"。示例:- "SELECT * FROM people"- "SELECT name, age FROM people WHERE age > 25"- "SELECT * FROM people ORDER BY age DESC"Returns:list: 包含查询结果的元组列表。对于默认查询,元组格式为 (id, name, age, profession)Example (示例):>>> # 读取所有记录>>> read_data()[(1, 'John Doe', 30, 'Engineer'), (2, 'Alice Smith', 25, 'Developer')]>>> # 使用自定义查询读取>>> read_data("SELECT name, profession FROM people WHERE age < 30")[('Alice Smith', 'Developer')]"""conn, cursor = init_db()try:print(f"\n\n正在使用查询执行 read_data:{query}")cursor.execute(query)return cursor.fetchall()except sqlite3.Error as e:print(f"读取数据时出错:{e}")return []finally:conn.close()if __name__ == "__main__":# Start the server // 启动服务器print("🚀正在启动服务器... ")parser = argparse.ArgumentParser()parser.add_argument("--server_type", type=str, default="sse", choices=["sse", "stdio"],)args = parser.parse_args()# Only pass server_type to run() // 只将 server_type 传递给 run()mcp.run(args.server_type)
- langchain_client.py
import asyncio
import nest_asyncio
from langchain_ollama import ChatOllama
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain_mcp_adapters.tools import MCPTool
from langchain.agents.format_scratchpad import format_log_to_str
from langchain.agents.output_parsers import ReActSingleInputOutputParser, ReActJsonSingleInputOutputParser
from langchain.agents import AgentExecutor, create_react_agent
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder, HumanMessagePromptTemplate
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
import httpx
from langchain.tools import Tool
from typing import Optional, Any, Callable, Awaitable# Enable nested asyncio for Jupyter-like environments // 为类似 Jupyter 的环境启用嵌套 asyncio
nest_asyncio.apply()REACT_TEMPLATE = """尽力回答以下问题。你可以使用以下工具:{tools}使用以下格式:Question: 你必须回答的输入问题
Thought: 你应该总是思考该做什么
Action: {tool_names}
Action Input: 要执行的 SQL 查询
Observation: 操作的结果
Thought: 我现在知道最终答案了
Final Answer: [用于 read_data 的格式化表格或用于 add_data 的成功消息]例如:
Question: add John Doe 30 year old Engineer
Thought: 我需要向数据库添加一个新人员
Action: add_data
Action Input: INSERT INTO people (name, age, profession) VALUES ('John Doe', 30, 'Engineer')
Observation: 数据添加成功
Thought: 我已成功添加该人员
Final Answer: 成功将 John Doe (年龄: 30, 职业: Engineer) 添加到数据库Question: show all records
Thought: 我需要从数据库检索所有记录
Action: read_data
Action Input: SELECT * FROM people
Observation: [包含记录的格式化表格]
Thought: 我已检索所有记录
Final Answer: [显示所有记录的格式化表格]开始!Question: {input}
{agent_scratchpad}"""class LangchainMCPClient:def __init__(self, mcp_server_url="http://127.0.0.1:8000"):print("正在初始化 LangchainMCPClient...")self.llm = ChatOllama(model="llama3.2",temperature=0.6,streaming=False # Disable streaming for better compatibility // 禁用流式传输以获得更好的兼容性)# Updated server configuration with shorter timeouts // 更新了服务器配置,使用更短的超时时间server_config = {"default": {"url": f"{mcp_server_url}/sse","transport": "sse","options": {"timeout": 10.0, // 连接超时"retry_connect": True, // 重试连接"max_retries": 2, // 最大重试次数"read_timeout": 5.0, // 读取超时"write_timeout": 5.0 // 写入超时}}}print(f"正在连接到 MCP 服务器于 {mcp_server_url}...")self.mcp_client = MultiServerMCPClient(server_config)self.chat_history = []# System prompt for the agent // 智能体的系统提示self.SYSTEM_PROMPT = """你是一个 AI 助手,帮助用户与数据库交互。你可以使用可用工具从数据库中添加和读取数据。添加数据时:1. 正确格式化 SQL 查询:INSERT INTO people (name, age, profession) VALUES ('Name', Age, 'Profession')2. 确保在文本值周围使用单引号3. 不要在数值周围使用引号读取数据时:1. 使用 SELECT * FROM people 获取所有记录2. 使用 WHERE 子句进行过滤:SELECT * FROM people WHERE condition3. 以清晰、格式化的方式呈现结果始终:1. 仔细思考每一步2. 验证操作是否成功3. 提供清晰的操作摘要"""async def check_server_connection(self):"""Check if the MCP server is accessible""" // 检查 MCP 服务器是否可访问base_url = self.mcp_client.connections["default"]["url"].replace("/sse", "")try:print(f"正在测试连接到 {base_url}...")async with httpx.AsyncClient(timeout=5.0) as client: # Shorter timeout // 更短的超时时间# Try the SSE endpoint directly // 直接尝试 SSE 端点sse_url = f"{base_url}/sse"print(f"正在检查 SSE 端点于 {sse_url}...")response = await client.get(sse_url, timeout=5.0)print(f"获取到响应:{response.status_code}")if response.status_code == 200:print("SSE 端点可访问!")return Trueprint(f"服务器响应状态码:{response.status_code}")return Falseexcept httpx.ConnectError:print(f"无法连接到服务器于 {base_url}")print("请确保服务器正在运行且端口正确")return Falseexcept httpx.ReadTimeout:print("连接已建立但在读取时超时")print("这对于 SSE 连接是正常的 - 继续...")return Trueexcept Exception as e:print(f"连接 MCP 服务器时出错:{type(e).__name__} - {str(e)}")return Falseasync def initialize_agent(self):"""Initialize the agent with tools and prompt template""" // 使用工具和提示模板初始化智能体print("\n正在初始化智能体...")if not await self.check_server_connection():raise ConnectionError("无法连接到 MCP 服务器。请确保服务器正在运行。")try:print("正在获取可用工具...")mcp_tools = await self.mcp_client.get_tools()# Verify tools are properly initialized // 验证工具是否正确初始化print("正在验证工具...")for i, tool in enumerate(mcp_tools):print(f"\n工具 {i}:")print(f" 名称: {tool.name if hasattr(tool, 'name') else '无名称'}")print(f" 描述: {tool.description if hasattr(tool, 'description') else '无描述'}")print(f" 类型: {type(tool)}")print(f" 可调用: {callable(tool)}")# 省略调试输出的翻译print(f" 方法: {[method for method in dir(tool) if not method.startswith('_')]}")print(f" 完整工具: {tool.__dict__}")# Test call // 测试调用try:print(" 正在测试工具调用...")if i == 0:test_query = "INSERT INTO people (name, age, profession) VALUES ('Test', 30, 'Test')"else:test_query = "SELECT * FROM people"result = await tool.ainvoke({"query": test_query})print(f" 测试结果: {result}")except Exception as e:print(f" 测试错误: {type(e).__name__} - {str(e)}")if len(mcp_tools) < 2:raise ValueError(f"期望 2 个工具,得到 {len(mcp_tools)}")# Create async wrapper functions with better error handling // 创建具有更好错误处理的异步包装函数async def add_data_wrapper(query: str):try:tool = mcp_tools[0] # add_data tool // add_data 工具if not tool:print("工具 0 (add_data) 未正确初始化")return "错误:添加数据工具未正确初始化"print(f"正在使用查询执行 add_data:{query}")# Clean up the query // 清理查询query = query.strip().replace('\\n', ' ').replace(' ', ' ')# Fix common formatting issues // 修复常见的格式问题if "VALUES" in query:parts = query.split("VALUES")if len(parts) == 2:values = parts[1].strip()if values.startswith("(") and values.endswith(")"):values = values[1:-1].split(",")if len(values) == 3:name = values[0].strip().strip("'")age = values[1].strip()profession = values[2].strip().strip("'")query = f"INSERT INTO people (name, age, profession) VALUES ('{name}', {age}, '{profession}')"# Call the tool using the async method // 使用异步方法调用工具result = await tool.ainvoke({"query": query})print(f"添加数据结果: {result}")if result:return "数据添加成功" # Clear success message // 清晰的成功消息return "未能添加数据" # Clear failure message // 清晰的失败消息except Exception as e:print(f"add_data_wrapper 中出错:{type(e).__name__} - {str(e)}")return f"添加数据时出错:{str(e)}"async def read_data_wrapper(query: str = "SELECT * FROM people"):try:tool = mcp_tools[1] # read_data tool // read_data 工具if not tool:print("工具 1 (read_data) 未正确初始化")return "错误:读取数据工具未正确初始化"print(f"正在使用查询执行 read_data:{query}")# Clean up the query // 清理查询query = query.strip().replace('\\n', ' ').replace(' ', ' ')# Call the tool using the async method // 使用异步方法调用工具result = await tool.ainvoke({"query": query})print(f"读取数据结果: {result}")if not result:return "未找到记录"# Format results in a table // 将结果格式化为表格records = []for i in range(0, len(result), 4):records.append({'name': result[i+1],'age': result[i+2],'profession': result[i+3]})# Create table header // 创建表头output = [f"显示 {len(records)} 条记录:","","| Name | Age | Profession |","|---------------|-----|------------------|"]# Add each record // 添加每条记录for record in records:name = record['name'].ljust(13)age = str(record['age']).ljust(5)profession = record['profession'].ljust(16)output.append(f"| {name} | {age} | {profession} |")return "\n".join(output)except Exception as e:print(f"read_data_wrapper 中出错:{type(e).__name__} - {str(e)}")return f"读取数据时出错:{str(e)}"# Create Langchain tools with async functions // 使用异步函数创建 Langchain 工具self.tools = [Tool(name="add_data",description="向数据库添加人员。示例:INSERT INTO people (name, age, profession) VALUES ('John Doe', 30, 'Engineer')",func=lambda x: "使用异步版本",coroutine=add_data_wrapper),Tool(name="read_data",description="从数据库读取。示例:SELECT * FROM people",func=lambda x: "使用异步版本",coroutine=read_data_wrapper)]print(f"找到 {len(self.tools)} 个工具")# Create the prompt template with system message // 创建带有系统消息的提示模板system_message = SystemMessage(content=self.SYSTEM_PROMPT)human_message = HumanMessagePromptTemplate.from_template(REACT_TEMPLATE)prompt = ChatPromptTemplate.from_messages([system_message,human_message]).partial(tool_names="add_data or read_data")# Create the agent with simpler configuration // 使用更简单的配置创建智能体self.agent = create_react_agent(llm=self.llm,tools=self.tools,prompt=prompt)# Create the executor with better configuration // 使用更好的配置创建执行器self.agent_executor = AgentExecutor(agent=self.agent,tools=self.tools,verbose=True, // 详细输出handle_parsing_errors=True, // 处理解析错误max_iterations=1, # Only try once // 只尝试一次early_stopping_method="force", # Stop after max_iterations // 在 max_iterations 后停止return_intermediate_steps=True # Ensure we get the steps // 确保我们得到步骤)print("\n可用工具:")for tool in self.tools:print(f"- {tool.name}: {tool.description}")except Exception as e:print(f"\n初始化智能体时出错:{e}")raiseasync def process_message(self, user_input: str) -> str:"""Process a single user message and return the agent's response""" // 处理单个用户消息并返回智能体的响应try:print("\n正在处理消息:", user_input)# Execute the agent // 执行智能体response = await self.agent_executor.ainvoke({"input": user_input,"chat_history": self.chat_history})print("\n原始响应:", response)final_result = None# Get the result from intermediate steps // 从中间步骤获取结果if isinstance(response, dict) and "intermediate_steps" in response:steps = response["intermediate_steps"]if steps and isinstance(steps[-1], tuple):action, observation = steps[-1]# Handle add_data response // 处理 add_data 响应if "add_data" in str(action):query = str(action.tool_input)if "VALUES" in query:values = query[query.find("VALUES")+7:].strip("() ")name, age, profession = [v.strip().strip("'") for v in values.split(",")]final_result = f"成功将 {name} (年龄: {age}, 职业: {profession}) 添加到数据库"# Handle read_data response // 处理 read_data 响应elif "read_data" in str(action):if isinstance(observation, str) and "Showing" in observation:final_result = observation # Use the formatted table // 使用格式化的表格else:final_result = str(observation) # Use any other read response // 使用任何其他读取响应# Use raw observation if no specific handling // 如果没有特定处理,则使用原始观察结果if final_result is None:final_result = str(observation)# Update response output and chat history // 更新响应输出和聊天历史response["output"] = final_resultself.chat_history.extend([HumanMessage(content=user_input),AIMessage(content=final_result)])print("\n最终结果:", final_result)return final_resultreturn "无法处理请求。请重试。"except Exception as e:error_msg = f"处理消息时出错:{type(e).__name__} - {str(e)}\n请尝试重新表述您的请求。"print(f"\n处理消息时出错:{type(e).__name__} - {str(e)}")print(f"完整错误:{e.__dict__}")return error_msgasync def interactive_chat(self):"""Start an interactive chat session""" // 开始交互式聊天会话print("聊天会话已开始。输入 'exit' 退出。")while True:user_input = input("\n您:")if user_input.lower() == "exit":print("正在结束聊天会话...")breakresponse = await self.process_message(user_input)print("\n智能体:", response)async def main():try:print("正在启动 Langchain MCP 客户端...")client = LangchainMCPClient()print("\n正在初始化智能体...")await client.initialize_agent()print("\n正在启动交互式聊天...")await client.interactive_chat()except ConnectionError as e:print(f"\n连接错误:{e}")print("请检查:")print("1. MCP 服务器正在运行 (python server.py --server_type=sse)")print("2. 服务器 URL 正确 (http://127.0.0.1:8000)")print("3. 服务器可以从您的机器访问")except Exception as e:print(f"\n意外错误:{type(e).__name__} - {str(e)}")if __name__ == "__main__":# Run the async main function // 运行异步 main 函数asyncio.run(main())
⚠️ 重要说明:
-
系统要求:
- Python 3.8 或更高版本
- SQLite3 (Python 自带)
- 足够的磁盘空间用于 LLM 模型
-
Ollama 设置:
- 单独从以下地址安装 Ollama:Ollama
- 拉取所需模型:
ollama run llama3.2
🚀 开始使用
# Start the MCP server // 启动 MCP 服务器
python server.py --server_type=sse# Run the client // 运行客户端
python langchain_client.py
1. 🚀 初始化阶段
- 服务器启动并注册工具
- 客户端连接到服务器
- 客户端发现可用工具
- 智能体使用工具进行初始化
2. 💬 用户交互阶段
当用户输入:“add Panama 55 year old as the SME” (添加 Panama 55 岁作为 SME)
- 输入传递给智能体
- 智能体格式化 SQL 查询
- 查询传递给 MCP 工具
- 工具在服务器上执行
- 结果返回给用户
响应日志
server.py 日志
langchain_client.py 响应日志
(注意:日志中的大部分内容保持英文原文以反映程序输出,仅翻译关键启动信息、用户输入和最终智能体回复)
(.venv) C:\Users\PLNAYAK\Documents\local_mcp_server>python langchain_client.py
Starting Langchain MCP Client... // 正在启动 Langchain MCP 客户端...
Initializing LangchainMCPClient... // 正在初始化 LangchainMCPClient...
Connecting to MCP server at http://127.0.0.1:8000... // 正在连接到 MCP 服务器于 http://127.0.0.1:8000...Initializing agent... // 正在初始化智能体...
Testing connection to http://127.0.0.1:8000... // 正在测试连接到 http://127.0.0.1:8000...
Checking SSE endpoint at http://127.0.0.1:8000/sse... // 正在检查 SSE 端点于 http://127.0.0.1:8000/sse...
Connection established but timed out while reading // 连接已建立但在读取时超时
This is normal for SSE connections - proceeding... // 这对于 SSE 连接是正常的 - 继续...
Getting available tools... // 正在获取可用工具...
Verifying tools... // 正在验证工具...
(工具验证细节省略)
Found 2 tools // 找到 2 个工具Available tools: // 可用工具:
- add_data: Add a person to the database... (向数据库添加人员...)
- read_data: Read from the database... (从数据库读取...)Starting interactive chat... // 正在启动交互式聊天...
Chat session started. Type 'exit' to quit. // 聊天会话已开始。输入 'exit' 退出。您:add Samiksha 30 years old Data ScientistProcessing message: add Samiksha 30 years old Data Scientist // 正在处理消息...> Entering new AgentExecutor chain...
Question: add Samiksha 30 years old Data Scientist
Thought: I need to add a new person to the database
Action: add_data
Action Input: INSERT INTO people (name, age, profession) VALUES ('Samiksha', 30, 'Data Scientist')Executing add_data with query: INSERT INTO people (name, age, profession) VALUES ('Samiksha', 30, 'Data Scientist')
Add data result: true
Data added successfully> Finished chain.Raw response: ... (原始响应省略)Final result: Successfully added Samiksha (age: 30, profession: Data Scientist) to the database // 最终结果: 成功将 Samiksha (年龄: 30, 职业: Data Scientist) 添加到数据库智能体:Successfully added Samiksha (age: 30, profession: Data Scientist) to the database您:Show all recordsProcessing message: Show all records // 正在处理消息: Show all records> Entering new AgentExecutor chain...
Question: show all records
Thought: I need to retrieve all records from the database
Action: read_data
Action Input: SELECT * FROM peopleExecuting read_data with query: SELECT * FROM people
Read data result: ... (读取数据结果省略)
Showing 19 records:
... (表格内容省略)> Finished chain.Raw response: ... (原始响应省略)Final result: Showing 19 records:\n\n| Name | Age | Profession |\n|---------------|-----|------------------|\n| Test | 30 | Test |\n... (其他记录省略) ...\n| Samiksha | 30 | Data Scientist | // 最终结果: 显示 19 条记录: ...智能体:Showing 19 records: // 显示 19 条记录:| Name | Age | Profession |
|---------------|-----|------------------|
| Test | 30 | Test |
| plaban nayak | 45 | manager |
| plaban nayak | 45 | manager |
| plaban nayak | 45 | manager |
| Test | 30 | Test |
| soma | 34 | HR |
| Test | 30 | Test |
| salmon | 35 | accountant |
| Test | 30 | Test |
| Kamilla | 24 | Receptionist |
| Test | 30 | Test |
| kishore | 27 | facility manager |
| Test | 30 | Test |
| Test | 30 | Test |
| Test | 30 | Test |
| Test | 30 | Test |
| Panama | 55 | SME |
| Test | 30 | Test |
| Samiksha | 30 | Data Scientist |您:
🎯 此工作流的优势
- 🔌 模块化
- 易于添加新工具
- 易于修改现有工具
- 清晰的关注点分离
- 🚀 可扩展性
- 异步操作
- 连接池
- 资源管理
- 👥 用户体验
- 自然语言输入
- 格式化输出
- 错误处理
- 🛠️ 可维护性
- 清晰的代码结构
- 分离的组件
- 易于调试
这个工作流通过自然语言命令创建了一个健壮、可扩展且用户友好的数据库操作系统! 🎉
🔮 未来可能性
- 🎨 创意应用
- AI 艺术生成
- 自然语言处理
- 自治智能体
- 🏢 企业用例
- 数据库管理
- 客户服务
- 流程自动化
- 🔬 研究应用
- 模型比较
- 工具组合
- 智能体开发
🎉 结论
MCP 代表了 AI 集成方面向前迈出的重要一步,使得连接模型与应用程序比以往任何时候都更容易。无论我们是在构建聊天界面、数据库管理器还是自治智能体,MCP 都为您提供了所需的基础!
相关文章:

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...