title: 本地AI进阶:Function Calling与MCP协议完全指南——让AI Agent帮你自动执行任务
tags: AI Agent,Function Calling,MCP协议,OpenWebUI,工具调用,本地AI,自动化,Ollama
category: 人工智能

本地AI进阶:Function Calling与MCP协议完全指南——让AI Agent帮你自动执行任务

本文是《本地AI配置完全攻略》系列第8篇。前7篇分别介绍了DeepSeek部署、Page Assist、OpenWebUI、联网搜索、知识库RAG、多模态语音、手机远程访问。本篇介绍如何让本地AI从"对话工具"进化为能自主调用工具的 AI Agent

场景:你的本地AI已经能聊天、搜索、读文档,但它还只能"说"不能"做"。本篇教你用 Function Calling 和 MCP 协议,让AI能自主调用工具、执行任务、自动化工作流——全部在本地运行。


目录

  1. AI Agent 是什么?为什么需要它?
  2. Function Calling 原理与协议标准
  3. 本地模型工具调用能力对比
  4. OpenWebUI 中配置 Function Calling
  5. 实战:编写自定义工具函数
  6. MCP 协议:连接一切的标准接口
  7. OpenWebUI + MCP 完整配置
  8. 实战案例:文件管理 Agent
  9. 定时任务:让 Agent 自动执行
  10. 安全与权限控制
  11. 总结与下一步

1. AI Agent 是什么?为什么需要它?

1.1 传统对话 AI 的局限

能力维度 传统对话AI AI Agent
信息处理 ✅ 理解和生成文本 ✅ + 能操作外部系统
任务执行 ❌ 只能建议 ✅ 能实际执行
多步骤规划 ❌ 单轮对话 ✅ 自主规划步骤
工具使用 ❌ 无法调用 ✅ 自主选择和调用工具
持续运行 ❌ 需人工触发 ✅ 可定时/事件触发

1.2 AI Agent 架构

┌─────────────────────────────────────────────┐
│                AI Agent 系统                │
├─────────────────────────────────────────────┤
│  🧠 LLM 核心(DeepSeek-R1 / Qwen2.5)    │
│       ↓ 生成工具调用决策                     │
│  🔧 Function Calling 层                    │
│       ↓ 执行工具                            │
│  📦 工具集                                 │
│    ├── 网页搜索(SearXNG)                 │
│    ├── 文件读写(MCP Filesystem)          │
│    ├── 数据库查询(MCP SQLite)            │
│    ├── 日程管理(MCP Calendar)            │
│    └── 自定义API(用户编写)               │
│       ↓ 结果返回                            │
│  💬 生成最终回答                           │
└─────────────────────────────────────────────┘

2. Function Calling 原理与协议标准

2.1 工作流程

Function Calling 的核心思想是:让LLM输出结构化的"工具调用指令",由外部程序执行工具,再把结果喂回LLM

用户: "深圳今天天气怎么样?"
    ↓
LLM判断: 需要调用 get_weather(city="深圳")
    ↓
程序执行: get_weather("深圳") → {temperature: 28, condition: "晴"}
    ↓
LLM接收结果: 基于{28℃,晴}生成回答
    ↓
用户收到: "深圳今天28℃,晴天。"

2.2 OpenAI Function Calling 格式(Ollama 兼容)

{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "获取指定城市的当前天气",
        "parameters": {
          "type": "object",
          "properties": {
            "city": {"type": "string", "description": "城市名称"}
          },
          "required": ["city"]
        }
      }
    }
  ]
}

Ollama 从 0.3.0 版本开始支持 tools 参数,格式与 OpenAI 兼容。


3. 本地模型工具调用能力对比

3.1 支持 Function Calling 的本地模型

模型 参数量 工具调用质量 推荐场景 拉取命令
Qwen2.5 7B/14B/32B ⭐⭐⭐⭐⭐ 通用Agent ollama pull qwen2.5:14b
DeepSeek-R1 14B/32B/70B ⭐⭐⭐⭐ 推理+工具 ollama pull deepseek-r1:14b
Llama 3.2 8B/70B ⭐⭐⭐⭐ 通用 ollama pull llama3.2:8b
Mistral Nemo 12B ⭐⭐⭐ 轻量Agent ollama pull mistral-nemo:12b
Command-R 35B ⭐⭐⭐⭐ RAG+工具 ollama pull command-r:35b

💡 建议:Qwen2.5 14B 的工具调用格式最稳定,推荐作为 Agent 主力模型。

3.2 验证模型工具调用能力

# 用 Ollama API 测试工具调用
curl http://localhost:11434/api/chat -d '{
  "model": "qwen2.5:14b",
  "messages": [{"role": "user", "content": "深圳今天天气怎么样?"}],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "获取城市天气",
        "parameters": {
          "type": "object",
          "properties": {
            "city": {"type": "string"}
          },
          "required": ["city"]
        }
      }
    }
  ]
}'

如果模型支持工具调用,返回中会包含 "tool_calls" 字段。


4. OpenWebUI 中配置 Function Calling

OpenWebUI 内置了对工具调用的支持,并通过 Functions(函数) 机制允许用户输入自定义工具。

4.1 启用工具调用(确认模型支持)

在 OpenWebUI 设置中:

  1. Settings → Models:确保选中的模型支持工具调用(Ollama 0.3+)
  2. Settings → Functions:查看已安装的函数

4.2 编写并安装自定义 Function

OpenWebUI 的 Function 使用 Python 编写,格式如下:

"""
name: get_weather
description: 获取指定城市的当前天气信息。当用户询问天气时调用。
"""

import requests

def get_weather(city: str):
    """
    调用 wttr.in 免费天气API
    """
    try:
        resp = requests.get(f"https://wttr.in/{city}?format=j1", timeout=10)
        data = resp.json()
        current = data["current_condition"][0]
        return {
            "city": city,
            "temperature": current["temp_C"] + "°C",
            "condition": current["weatherDesc"][0]["value"],
            "humidity": current["humidity"] + "%"
        }
    except Exception as e:
        return {"error": str(e)}

安装步骤

  1. 打开 OpenWebUI → 左下角头像 → Settings
  2. 点击 Functions+ 创建
  3. 粘贴以上代码 → 保存
  4. 在聊天界面中,AI 会自动发现并使用这个工具

5. 实战:编写自定义工具函数

5.1 工具函数编写规范

每个工具函数应遵循以下规范:

"""
name: tool_name
description: 清晰描述工具的用途、何时调用、参数是什么。
  好的description能让LLM准确判断何时调用此工具。
"""

def tool_name(param1: str, param2: int = 10):
    """
    函数文档字符串:说明参数含义、返回值格式
    """
    # 1. 参数校验
    if not param1:
        return {"error": "param1 is required"}
    
    # 2. 执行操作
    result = do_something(param1, param2)
    
    # 3. 返回结构化结果(JSON序列化友好的dict)
    return {
        "status": "success",
        "data": result,
        "count": len(result)
    }

5.2 实用工具示例:知识库搜索工具

"""
name: search_knowledge_base
description: 在本地知识库中搜索相关信息。当用户询问需要查阅知识库内容时调用。
"""

import requests

def search_knowledge_base(query: str, max_results: int = 5):
    """
    调用 OpenWebUI 内置的 RAG 检索接口
    (需要 OpenWebUI 已配置知识库)
    """
    try:
        # 调用 OpenWebUI 内部 RAG API
        # 注意:这需要 OpenWebUI 的 Python 环境内有相应上下文
        # 实际部署时,建议通过 OpenWebUI 插件机制实现
        return {
            "query": query,
            "results": [],
            "note": "需通过OpenWebUI插件机制实现"
        }
    except Exception as e:
        return {"error": str(e)}

6. MCP 协议:连接一切的标准接口

6.1 MCP 是什么?

MCP(Model Context Protocol) 是 Anthropic 于2024年推出的开放标准协议,用于解决 AI 应用与外部工具/数据源之间的连接问题。

核心价值

  • 对工具开发者:只需实现一次 MCP Server,所有支持 MCP 的 AI 应用都能用
  • 对 AI 应用:只需支持 MCP Client,就能连接所有 MCP Server
  • 对用户:像"插USB设备"一样给 AI 添加新能力

6.2 MCP 架构

┌─────────────────┐     MCP协议      ┌─────────────────┐
│   AI应用         │ ←────────────→  │   MCP Server     │
│ (OpenWebUI/      │   标准JSON-RPC  │ (提供工具/数据)   │
│  Claude等)      │                 │                 │
└─────────────────┘                 └─────────────────┘

6.3 官方 MCP Server 列表

MCP Server 功能 安装
@modelcontextprotocol/server-filesystem 文件系统读写 npm install -g @modelcontextprotocol/server-filesystem
@modelcontextprotocol/server-brave-search 网页搜索 npm install -g @modelcontextprotocol/server-brave-search
@modelcontextprotocol/server-sqlite SQLite数据库 npm install -g @modelcontextprotocol/server-sqlite
@modelcontextprotocol/server-git Git仓库操作 npm install -g @modelcontextprotocol/server-git
@modelcontextprotocol/server-fetch 获取URL内容 npm install -g @modelcontextprotocol/server-fetch
@modelcontextprotocol/server-postgres PostgreSQL npm install -g @modelcontextprotocol/server-postgres

7. OpenWebUI + MCP 完整配置

7.1 OpenWebUI 的 MCP 支持现状

截至 2025 年初,OpenWebUI 对 MCP 的支持处于实验阶段,主要通过以下方式实现:

方式一:通过 OpenWebUI Functions 调用 MCP Server

在 Function 中,使用 subprocess 调用 MCP Server 的 stdio 接口:

"""
name: mcp_filesystem
description: 通过MCP协议访问文件系统
"""

import subprocess
import json

def mcp_filesystem(operation: str, path: str, content: str = ""):
    """
    调用 MCP filesystem server
    """
    # 构建 MCP 请求
    request = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/call",
        "params": {
            "name": "read_file" if operation == "read" else "write_file",
            "arguments": {"path": path, "content": content}
        }
    }
    
    # 通过 stdin 发送给 MCP Server
    result = subprocess.run(
        ["npx", "@modelcontextprotocol/server-filesystem", "/allowed/path"],
        input=json.dumps(request),
        capture_output=True,
        text=True
    )
    return json.loads(result.stdout)

方式二:等待 OpenWebUI 原生 MCP 支持

OpenWebUI 开发团队已在 roadmap 中规划原生 MCP 支持,未来可直接在 UI 中配置 MCP Server 地址。

7.2 当前推荐方案:用 OpenWebUI Functions 替代 MCP

在 OpenWebUI 原生支持 MCP 之前,直接用 Functions 编写工具函数是最稳定的方案。


8. 实战案例:文件管理 Agent

8.1 目标

让 AI 能:

  • 列出指定目录的文件
  • 读取文件内容并总结
  • 写入新文件

8.2 实现:文件操作工具函数

"""
name: file_manager
description: 管理指定目录下的文件。支持列出文件、读取文件、写入文件。当用户需要操作文件时调用。
"""

import os
import json

# 安全限制:只能访问这些目录
ALLOWED_DIRS = [
    "D:/AI_Workspace",
    "D:/UserData/Desktop/workspace"
]

def _check_path(path: str) -> bool:
    """检查路径是否在允许范围内"""
    return any(os.path.abspath(path).startswith(os.path.abspath(d)) for d in ALLOWED_DIRS)

def list_files(directory: str = "D:/AI_Workspace") -> dict:
    """列出目录下的所有文件"""
    if not _check_path(directory):
        return {"error": "Path not allowed"}
    try:
        files = []
        for f in os.listdir(directory):
            fp = os.path.join(directory, f)
            files.append({
                "name": f,
                "size": os.path.getsize(fp) if os.path.isfile(fp) else 0,
                "is_dir": os.path.isdir(fp)
            })
        return {"directory": directory, "files": files, "count": len(files)}
    except Exception as e:
        return {"error": str(e)}

def read_file(path: str) -> dict:
    """读取文件内容"""
    if not _check_path(path):
        return {"error": "Path not allowed"}
    try:
        with open(path, "r", encoding="utf-8") as f:
            content = f.read()
        return {"path": path, "content": content, "length": len(content)}
    except Exception as e:
        return {"error": str(e)}

def write_file(path: str, content: str) -> dict:
    """写入文件(仅允许写入AI_Workspace目录)"""
    if not _check_path(path):
        return {"error": "Path not allowed"}
    try:
        with open(path, "w", encoding="utf-8") as f:
            f.write(content)
        return {"path": path, "status": "success", "bytes": len(content)}
    except Exception as e:
        return {"error": str(e)}

8.3 使用效果

在 OpenWebUI 中安装上述 Function 后:

用户:帮我看看 D:/AI_Workspace 里有哪些文件?
AI:(调用 list_files)→ 有3个文件:note.txt、todo.md、draft.md

用户:帮我总结一下 note.txt 的内容
AI:(调用 read_file)→ 总结了文件内容


9. 定时任务:让 Agent 自动执行

9.1 方案架构

Windows任务计划程序 / cron
        ↓ 定时触发
Python脚本(调用Ollama API)
        ↓ 构造prompt
Ollama(本地模型)
        ↓ 生成结果
发送到邮箱 / 微信 / 本地通知

9.2 实现:每日工作总结脚本

# D:/AI_Workspace/daily_agent.py
import requests
import json
from datetime import datetime

API_URL = "http://localhost:11434/api/chat"
MODEL = "qwen2.5:14b"

def ask_agent(prompt: str) -> str:
    """调用本地Ollama API"""
    payload = {
        "model": MODEL,
        "messages": [{"role": "user", "content": prompt}],
        "stream": False
    }
    resp = requests.post(API_URL, json=payload, timeout=120)
    return resp.json()["message"]["content"]

def main():
    today = datetime.now().strftime("%Y-%m-%d")
    
    prompt = f"""
今天是{today}。
请基于你的知识,生成今日工作建议,包括:
1. 今日优先级最高的3件事
2. 需要注意的事项
3. 一句鼓励的话
(500字以内,语气积极)
"""
    
    result = ask_agent(prompt)
    
    # 保存结果
    with open(f"D:/AI_Workspace/daily_{today}.txt", "w", encoding="utf-8") as f:
        f.write(result)
    
    print("生成完成:")
    print(result)

if __name__ == "__main__":
    main()

9.3 配置 Windows 任务计划程序

# 创建一个基本任务
# 触发器:每天早上 8:00
# 操作:启动程序
# 程序:python.exe
# 参数:D:\AI_Workspace\daily_agent.py

10. 安全与权限控制

10.1 安全风险分析

风险类型 描述 防护措施
路径遍历 AI被诱导读取 /etc/passwd 等敏感文件 白名单限制允许路径
命令注入 工具函数中使用 os.system 导致代码执行 禁止在工具函数中使用shell命令
无限循环 AI反复调用工具耗尽资源 限制单轮对话最大工具调用次数
提示词注入 外部内容(网页/文档)中包含恶意指令 不信任外部输入,隔离工具执行

10.2 安全编码规范

"""
安全工具函数模板
"""

import os
import re

# 严格定义允许的操作范围
ALLOWED_DIR = os.path.abspath("D:/AI_Workspace")
MAX_FILE_SIZE = 10 * 1024 * 1024  # 10MB
MAX_CALLS_PER_TURN = 10  # 单轮最大调用次数

def safe_path(path: str) -> str:
    """将路径规范化为绝对路径,并检查安全性"""
    abs_path = os.path.abspath(path)
    if not abs_path.startswith(ALLOWED_DIR):
        raise ValueError(f"Path {path} is not allowed")
    return abs_path

def safe_read(path: str) -> dict:
    """安全读取文件"""
    try:
        path = safe_path(path)
        if not os.path.isfile(path):
            return {"error": "Not a file"}
        if os.path.getsize(path) > MAX_FILE_SIZE:
            return {"error": "File too large"}
        
        with open(path, "r", encoding="utf-8") as f:
            return {"content": f.read()}
    except Exception as e:
        return {"error": str(e)}

11. 总结与下一步

11.1 本文回顾

章节 核心内容
Function Calling 原理 LLM生成工具调用指令 → 程序执行 → 结果返回LLM
模型选择 Qwen2.5 14B 工具调用最稳定
OpenWebUI Functions 用Python编写自定义工具函数
MCP 协议 标准化工具接入协议,未来主流方向
文件管理Agent 实战案例:让AI读写指定目录
定时任务 用任务计划程序 + Ollama API 实现定时Agent
安全规范 路径白名单、禁止shell命令、限制调用次数

11.2 系列进度

篇目 主题 状态
第1-7篇 基础部署到远程访问
第8篇 AI Agent + Function Calling 新!
第9篇(下篇) 高性能优化:GPU加速+模型量化 🔜 下周更新

11.3 下一步可以做什么?

  • 接入 Home Assistant:让AI控制智能家居
  • 接入企业微信/钉钉:让AI成为企业助手
  • 多Agent协作:一个Agent搜索、一个Agent总结、一个Agent发送
  • Fine-tuning:用你的数据微调模型,提升工具调用准确率

系列文章导航:

💬 互动话题:你最想让AI Agent帮你自动完成什么任务?是文件整理、信息汇总、还是定时提醒?评论区分享你的想法,说不定下一篇就讲你需要的方案!🎉

🏷️ 发布提示:发布时请添加标签「本地AI」「AI Agent」「Function Calling」「MCP协议」「Python」,以提升推荐曝光。

参考资料:

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐