AI聊天助手工具调用演示

一个全栈AI聊天应用,展示结合LLM功能调用的模型上下文协议(MCP)模式,适用于需动态工具调用的对话场景。

  • by ANKIT9263
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 ANKIT9263/mcp_demo

使用说明

MCP演示-带工具调用的AI聊天助手

一个全栈AI聊天应用程序,演示了具有LLM函数调用功能的模型上下文协议(MCP)模式。该应用程序使用多层架构,包括Streamlit UI、FastAPI中间件、OpenAI集成和用于工具执行的MCP服务器。

目录


建筑

该应用程序遵循 三层微服务架构:

┌─────────────────────────────────────────────────────────────────┐
│                         USER INTERFACE                           │
│                                                                   │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                    Streamlit App                           │  │
│  │                   (Port: 8501)                             │  │
│  │  - Chat UI                                                 │  │
│  │  - Message History                                         │  │
│  │  - Tool Call Display                                       │  │
│  └────────────────────────┬──────────────────────────────────┘  │
└────────────────────────────┼─────────────────────────────────────┘
                             │ HTTP POST /chat
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│                      APPLICATION LAYER                           │
│                                                                   │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                     Chat API                               │  │
│  │                   (Port: 8000)                             │  │
│  │  - FastAPI Server                                          │  │
│  │  - Request/Response Handling                               │  │
│  └────────────────────────┬──────────────────────────────────┘  │
│                           │                                      │
│  ┌────────────────────────▼──────────────────────────────────┐  │
│  │                   LLM Client                               │  │
│  │  - OpenAI Integration (GPT-4o-mini)                        │  │
│  │  - Function Calling Logic                                  │  │
│  │  - Conversation Management                                 │  │
│  └────────────────────────┬──────────────────────────────────┘  │
└────────────────────────────┼─────────────────────────────────────┘
                             │ HTTP POST /tools/execute
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│                       TOOL EXECUTION LAYER                       │
│                                                                   │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                   MCP Server                               │  │
│  │                   (Port: 8001)                             │  │
│  │  - FastMCP Framework                                       │  │
│  │  - Tool Registry                                           │  │
│  │  - Tool Execution                                          │  │
│  │                                                            │  │
│  │  Available Tools:                                          │  │
│  │  • add_numbers(a, b)                                       │  │
│  │  • greet(name)                                             │  │
│  │  • get_info()                                              │  │
│  │  • get_config()                                            │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

流程图

完成请求响应流

sequenceDiagram
    participant User
    participant Streamlit as Streamlit UI<br/>(Port 8501)
    participant ChatAPI as Chat API<br/>(Port 8000)
    participant Client as LLM Client
    participant OpenAI as OpenAI API<br/>(GPT-4o-mini)
    participant MCP as MCP Server<br/>(Port 8001)

    User->>Streamlit: 1. Enter message<br/>"Add 15 and 27"

    Streamlit->>ChatAPI: 2. POST /chat<br/>{message, history}

    ChatAPI->>Client: 3. process_message()

    Client->>Client: 4. Build conversation<br/>with tool definitions

    Client->>OpenAI: 5. chat.completions.create()<br/>with tools parameter

    OpenAI-->>Client: 6. Response with<br/>tool_calls

    Note over Client: LLM decides to call<br/>add_numbers(15, 27)

    Client->>MCP: 7. POST /tools/execute<br/>{tool_name, arguments}

    MCP->>MCP: 8. Execute tool:<br/>add_numbers(15, 27)

    MCP-->>Client: 9. Return result:<br/>{result: 42, status: "success"}

    Client->>Client: 10. Add tool result<br/>to conversation

    Client->>OpenAI: 11. Send conversation<br/>with tool result

    OpenAI-->>Client: 12. Final natural<br/>language response

    Client-->>ChatAPI: 13. Return response<br/>+ tool_calls + history

    ChatAPI-->>Streamlit: 14. JSON response<br/>{response, tool_calls, history}

    Streamlit-->>User: 15. Display:<br/>"The sum is 42"<br/>+ Show tool call details

详细的组件交互

graph TB
    subgraph "Frontend Layer"
        A[User Input] --> B[Streamlit App]
        B --> C[Display Response]
        B --> D[Show Tool Calls]
    end

    subgraph "API Layer"
        E[Chat API Endpoint]
        F[Request Validation]
        E --> F
    end

    subgraph "Business Logic Layer"
        G[Client.process_message]
        H[Build Messages Array]
        I[OpenAI API Call]
        J[Tool Call Handler]
        K[Conversation Manager]

        G --> H
        H --> I
        I --> J
        J --> K
        K --> I
    end

    subgraph "External Services"
        L[OpenAI GPT-4o-mini]
    end

    subgraph "Tool Execution Layer"
        M[MCP Server]
        N[Tool Registry]
        O[Tool Executor]
        P[Tools:<br/>add_numbers<br/>greet<br/>get_info<br/>get_config]

        M --> N
        N --> O
        O --> P
    end

    B -->|POST /chat| E
    F --> G
    I <-->|Function Calling| L
    J -->|POST /tools/execute| M
    P -->|Result| O
    O -->|Response| J
    K -->|Final Response| E
    E -->|JSON| B

    style A fill:#e1f5ff
    style C fill:#e1f5ff
    style D fill:#e1f5ff
    style L fill:#fff4e1
    style P fill:#f0e1ff

技术栈

前端

  • 溪流 -交互式web UI框架
  • 请求: -用于API通信的HTTP客户端

后端

  • 快速API -API的现代web框架
  • Uvicorn -ASGI服务器
  • 派丹蒂克 -数据验证

AI/LLM

  • OpenAI API -GPT-4o-mini型号
  • 函数调用 -工具/功能执行

MCP层

  • FastMCP -模型上下文协议框架
  • Python装饰器 -工具注册

其他

  • python dotenv -环境变量管理

项目结构

mcp_demo/
├── streamlit_app.py              # Frontend UI application
├── main.py                        # Chat API server (port 8000)
├── client.py                      # LLM client with OpenAI integration
├── mcp_components/
│   ├── __init__.py
│   ├── mcp_server.py             # MCP server with tools (port 8001)
│   └── tools.py                  # (Legacy - tools now in mcp_server.py)
├── requirements.txt              # Python dependencies
├── .env                          # Environment variables (create this)
├── README.md                     # This file
└── README_SETUP.md              # Quick setup guide

安装说明

1.克隆或下载项目

cd /Users/ankit/Desktop/varsha_projects/mcp_demo

2.创建虚拟环境(推荐)

python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

3.安装依赖项

pip install -r requirements.txt

4.配置环境变量

创建一个 .env 项目根目录中的文件:

# .env
OPENAI_API_KEY=your_openai_api_key_here

从以下位置获取您的OpenAI API密钥:https://platform.openai.com/api-keys


运行应用程序

你需要奔跑 3个独立的终端窗口 (保持所有设备同时运行):

终端1:启动MCP服务器

cd /Users/ankit/Desktop/varsha_projects/mcp_demo
python mcp_components/mcp_server.py

预期产量:

INFO:     Started server process [xxxxx]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8001 (Press CTRL+C to quit)

终端2:开始聊天API

cd /Users/ankit/Desktop/varsha_projects/mcp_demo
python main.py

预期产量:

INFO:     Started server process [xxxxx]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

终端3:启动Streamlit UI

cd /Users/ankit/Desktop/varsha_projects/mcp_demo
streamlit run streamlit_app.py

预期产量:

  You can now view your Streamlit app in your browser.

  Local URL: http://localhost:8501
  Network URL: http://192.168.x.x:8501

访问应用程序

打开浏览器并导航到: http://localhost:8501


API 文档

聊天API(端口8000)

健康检查

GET http://localhost:8000/

答复:

{
  "message": "Chat API is running",
  "status": "ok"
}

聊天端点

POST http://localhost:8000/chat
Content-Type: application/json

{
  "message": "Add 15 and 27",
  "conversation_history": []
}

答复:

{
  "response": "The sum of 15 and 27 is 42.",
  "conversation_history": [...],
  "tool_calls": [
    {
      "tool": "add_numbers",
      "arguments": {"a": 15, "b": 27}
    }
  ]
}

MCP服务器(端口8001)

健康检查

GET http://localhost:8001/

答复:

{
  "message": "MCP Server is running",
  "status": "ok"
}

列出工具

GET http://localhost:8001/tools/list

答复:

{
  "tools": [
    {
      "name": "add_numbers",
      "description": "Add two numbers together",
      "parameters": {
        "type": "object",
        "properties": {
          "a": {"type": "integer", "description": "The a parameter"},
          "b": {"type": "integer", "description": "The b parameter"}
        },
        "required": ["a", "b"]
      }
    },
    ...
  ]
}

执行工具

POST http://localhost:8001/tools/execute
Content-Type: application/json

{
  "tool_name": "add_numbers",
  "arguments": {
    "a": 15,
    "b": 27
  }
}

答复:

{
  "result": 42,
  "status": "success"
}

可用工具

1.添加_编号

说明: 将两个数字相加

参数:

  • a (整数):第一个数字
  • b (整数):第二个数字

例子: “15加27等于多少?”


2.问候

说明: 用名字问候某人

参数:

  • name (string):要问候的人的名字

例子: “问候爱丽丝”


3.获取信息

说明: 获取服务器信息

参数: 无

例子: “服务器信息是什么?”或“显示服务器详细信息”


4.get_config

说明: 获取服务器配置

参数: 无

例子: “显示配置”或“配置是什么?”


示例用法

示例1:数学运算

User: "What is 123 plus 456?"

Flow:
1. OpenAI LLM analyzes the question
2. LLM decides to call add_numbers(123, 456)
3. MCP server executes the tool
4. Returns result: 579
5. LLM generates natural response: "The sum of 123 and 456 is 579."

Tool Call Displayed:
{
  "tool": "add_numbers",
  "arguments": {"a": 123, "b": 456}
}

示例2:问候

User: "Greet John"

Flow:
1. LLM calls greet("John")
2. MCP server returns: "Hello, John! Welcome to the MCP server."
3. LLM response: "I've greeted John!"

Tool Call Displayed:
{
  "tool": "greet",
  "arguments": {"name": "John"}
}

示例3:服务器信息

User: "What's the server info?"

Flow:
1. LLM calls get_info()
2. MCP server returns server details
3. LLM formats the response for the user

Tool Call Displayed:
{
  "tool": "get_info",
  "arguments": {}
}

示例4:无工具对话

User: "Hello, how are you?"

Flow:
1. LLM determines no tool is needed
2. Responds directly without tool execution
3. No tool calls displayed

运作原理

1.用户输入处理

  • 用户在Streamlit UI中键入消息
  • 消息被发送到聊天API,其中包含对话历史记录

2.法学硕士决策

  • 客户端向OpenAI发送带有工具定义的消息
  • GPT-4o-mini分析请求
  • LLM根据消息内容决定是否调用工具

3.工具执行(如需要)

  • 客户端从LLM响应中提取工具名称和参数
  • HTTP POST请求发送到MCP服务器
  • MCP服务器执行请求的工具
  • 结果返回给客户端

4.响应生成

  • 工具结果添加到对话上下文中
  • 客户端将更新的对话发送回OpenAI
  • LLM生成包含工具结果的自然语言响应

5.向用户显示

  • Streamlit中显示的最终响应
  • 可展开部分显示的工具调用
  • 为上下文维护对话历史记录

故障排除

端口已在使用中

# Find process using port 8000
lsof -i :8000
# Kill the process
kill -9 <PID>

# Or use different ports by modifying:
# - main.py: uvicorn.run(app, host="0.0.0.0", port=8000)
# - mcp_components/mcp_server.py: uvicorn.run(app, host="0.0.0.0", port=8001)
# - streamlit_app.py: API_URL = "http://localhost:8000"
# - client.py: MCP_SERVER_URL = "http://localhost:8001"

OpenAI API错误

Error: Invalid API key
Solution: Check your .env file and ensure OPENAI_API_KEY is set correctly

MCP服务器连接错误

Error: Cannot connect to MCP server
Solution: Ensure MCP server is running on port 8001

工具未注册

Problem: /tools/list returns empty array
Solution: Restart the MCP server (Terminal 1)

添加新工具

要添加新工具,请编辑 mcp_components/mcp_server.py:

@mcp.tool()
def your_new_tool(param1: str, param2: int) -> str:
    """Description of what the tool does"""
    # Your implementation here
    result = f"Processed {param1} with {param2}"
    return result

然后更新 client.py 包括新的工具定义:

tools = [
    # ... existing tools ...
    {
        "type": "function",
        "function": {
            "name": "your_new_tool",
            "description": "Description of what the tool does",
            "parameters": {
                "type": "object",
                "properties": {
                    "param1": {
                        "type": "string",
                        "description": "Description of param1"
                    },
                    "param2": {
                        "type": "integer",
                        "description": "Description of param2"
                    }
                },
                "required": ["param1", "param2"]
            }
        }
    }
]

重新启动MCP服务器和Chat API。


架构优势

1.关注点分离

  • 界面层:仅处理用户交互
  • API层:管理业务逻辑和编排
  • 工具层:单独执行特定工具

2.可扩展性

  • 每个组件都可以独立缩放
  • MCP服务器可以同时处理多个工具请求
  • 无状态设计允许水平扩展

3.可维护性

  • 工具是独立的,易于添加/修改
  • 清除层之间的API合同
  • 易于测试单个组件

4.灵活性

  • 将Streamlit替换为任何其他前端(React、Vue等)
  • 在不影响工具执行的情况下更改LLM提供程序
  • 在不修改核心逻辑的情况下添加新工具

5.安全

  • 敏感数据的环境变量
  • API层提供验证和错误处理
  • 工具执行与用户输入隔离

技术选择

为什么选择FastMCP?

  • 专为模型上下文协议构建
  • 与装饰师轻松注册工具
  • 与FastAPI无缝集成

为什么要调用OpenAI函数?

  • 对工具/功能执行的原生支持
  • 何时调用工具的智能决策
  • 自动处理参数提取

为什么是三层架构?

  • UI、逻辑和执行之间的明确分离
  • 每个服务都可以独立开发/部署
  • 更易于调试和维护

为什么选择Streamlit?

  • 快速UI开发
  • 内置状态管理
  • 非常适合AI/ML应用程序

未来的增强功能

  • []添加身份验证和用户管理
  • []实施速率限制
  • []添加对话持久性数据库
  • []创建用于工具管理的管理面板
  • []添加日志记录和监控
  • []为重复查询实现缓存
  • []添加对文件上传的支持
  • []与更多法学硕士提供者(Claude、Gemini)整合
  • []添加流媒体响应
  • []实现工具结果缓存

许可证

该项目用于教育和示范目的。


贡献

贡献:

  1. 分叉存储库
  2. 创建要素分支
  3. 进行更改
  4. 彻底测试
  5. 提交拉取请求

联系

如有疑问或问题,请在存储库中创建问题。


致谢

  • Anthropic -对于模型上下文协议概念
  • 开放人工智能 -对于GPT-4o-mini和函数调用API
  • FastAPI和Streamlit -对于优秀的框架

最后更新时间: 2024年12月11日 版本: 1.0.0