CodeBuddy 学习(7):MCP 集成与工具开发

一、概述:AI 的边界与 MCP 的使命

1.1 AI 的天然局限

AI 能做到的 AI 做不到的
读写项目文件 查询数据库看真实表结构
修改代码 调用 GitHub API 看 Issue 内容
执行终端命令 搜索互联网获取最新资料
分析上下文 感知外部系统的状态变化

1.2 MCP 是什么

MCP(Model Context Protocol)= AI 的感官延伸。

它是 Anthropic 推出的开放标准协议,让 AI 能够访问外部数据和工具——就像给 AI 装上了"眼睛"(看数据库)、“手”(操作第三方服务)和"搜索"(查互联网)。

工作原理

  1. 你在 CodeBuddy 中配置 MCP Server(如 SQLite Server、GitHub Server)。
  2. 当你提出需求时,AI 判断是否需要调用 MCP 工具。
  3. AI 通过 Client ↔ Server 通信获取真实数据。
  4. AI 基于真实数据生成代码——而不是"猜测"你的数据库结构。

核心价值:AI 不再猜你的表结构——它直接看到了。


二、六个核心概念

概念 角色 一句话描述
MCP Host 发起方 CodeBuddy 本身
MCP Client 通信组件 负责与 Server 建立连接并传输数据
MCP Server 能力提供方 数据库、GitHub、搜索引擎的代理服务
Tools 可执行动作 Server 提供的具体功能(如执行 SQL 查询)
Resources 可读取数据 Server 提供的数据源(如表结构信息)
Prompts 可复用模板 Server 预定义的提示词模板

2.2 六步工作流

步骤 做什么 示例
1. 请求 你说"生成用户 CRUD" AI 判断需要查数据库
2. 匹配 AI 从已注册的 Server 中匹配 “这个任务需要 SQLite MCP”
3. 连接 Client 连接 SQLite Server stdin/stdout 通信
4. 查询 Server 执行 SQL 获取表结构 SELECT * FROM sqlite_master
5. 返回 Server 返回真实表结构 users(id, name, email, created_at)
6. 生成 AI 基于真实结构生成代码 完整的 CRUD 接口

三、实战主线:SQLite MCP 从零到全栈

3.1 原理讲解

SQLite MCP Server 是一个标准的 MCP 服务实现,它接受 SQL 查询并返回结果。CodeBuddy 通过它获得实时读取数据库的能力,这意味着:

  • AI 看到的表结构永远是最新的(你加了字段,AI 自动感知)。
  • 不需要手动告诉 AI “users 表有 name 字段”——它会自己查。
  • 生成的 SQL 查询和 ORM Schema 会精确匹配当前数据库结构。

3.2 步骤一:准备数据库

创建测试数据库文件 data/app.db,包含以下三张表:

-- 用户表
CREATE TABLE users (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  email TEXT UNIQUE NOT NULL,
  role TEXT DEFAULT 'user',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 订单表
CREATE TABLE orders (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  user_id INTEGER NOT NULL REFERENCES users(id),
  amount DECIMAL(10,2) NOT NULL,
  status TEXT DEFAULT 'pending',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 商品表
CREATE TABLE products (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  price DECIMAL(10,2) NOT NULL,
  category TEXT,
  stock INTEGER DEFAULT 0
);

-- 插入测试数据
INSERT INTO users (name, email, role) VALUES
  ('张三', 'zhangsan@example.com', 'admin'),
  ('李四', 'lisi@example.com', 'user'),
  ('王五', 'wangwu@example.com', 'user');

INSERT INTO orders (user_id, amount, status) VALUES
  (1, 299.00, 'paid'),
  (2, 159.50, 'pending'),
  (1, 89.00, 'shipped');

INSERT INTO products (name, price, category, stock) VALUES
  ('机械键盘', 399.00, '电子产品', 50),
  ('Python 编程书', 79.00, '图书', 200),
  ('蓝牙耳机', 259.00, '电子产品', 30);

创建数据库(在终端执行):

mkdir -p data
sqlite3 data/app.db < init.sql
# 或手动逐条执行上述 SQL

3.3 步骤二:配置 MCP

编辑 ~/.codebuddy/mcp.json(或项目根目录的 .codebuddy/mcp.json):

{
  "mcpServers": {
    "sqlite": {
      "command": "npx",
      "args": ["-y", "mcp-server-sqlite", "data/app.db"]
    }
  }
}

配置说明

  • sqlite:MCP Server 的名称(可以自定义)。
  • command: "npx":通过 npx 运行(自动下载并使用最新版)。
  • args: ["-y", "mcp-server-sqlite", "data/app.db"]-y 跳过确认,data/app.db 是数据库文件路径(相对于项目根目录)。

3.4 步骤三:验证配置

在 CodeBuddy 对话框中输入:

请列出当前数据库中所有表及其字段结构。

预期输出

数据库包含以下三张表:

users 表:
- id (INTEGER, PRIMARY KEY)
- name (TEXT, NOT NULL)
- email (TEXT, UNIQUE, NOT NULL)
- role (TEXT, DEFAULT 'user')
- created_at (DATETIME, DEFAULT CURRENT_TIMESTAMP)

orders 表:
- id (INTEGER, PRIMARY KEY)
- user_id (INTEGER, REFERENCES users(id))
- amount (DECIMAL(10,2), NOT NULL)
- status (TEXT, DEFAULT 'pending')
- created_at (DATETIME, DEFAULT CURRENT_TIMESTAMP)

products 表:
- id (INTEGER, PRIMARY KEY)
- name (TEXT, NOT NULL)
- price (DECIMAL(10,2), NOT NULL)
- category (TEXT)
- stock (INTEGER, DEFAULT 0)

如果返回了真实的表结构 → 配置成功 ✅。


四、场景一:生成 Prisma Schema

4.1 操作

在对话中输入:

读取所有表结构,生成完整的 Prisma Schema。要求:
- 外键使用 @relation 声明
- 所有注释使用中文
- @@index 覆盖常用查询列
- @@map 映射原表名

4.2 预期输出

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = "file:./data/app.db"
}

/// 用户表
model User {
  id        Int      @id @default(autoincrement()) @map("id")
  name      String   @map("name")
  email     String   @unique @map("email")
  role      String   @default("user") @map("role")
  createdAt DateTime @default(now()) @map("created_at")

  orders    Order[]

  @@index([email])
  @@index([role])
  @@map("users")
}

/// 订单表
model Order {
  id        Int      @id @default(autoincrement()) @map("id")
  userId    Int      @map("user_id")
  amount    Decimal  @map("amount")
  status    String   @default("pending") @map("status")
  createdAt DateTime @default(now()) @map("created_at")

  user      User     @relation(fields: [userId], references: [id])

  @@index([userId])
  @@index([status])
  @@map("orders")
}

/// 商品表
model Product {
  id       Int    @id @default(autoincrement()) @map("id")
  name     String @map("name")
  price    Decimal @map("price")
  category String? @map("category")
  stock    Int    @default(0) @map("stock")

  @@index([category])
  @@map("products")
}

4.3 验证

检查生成的 Schema 是否精确匹配数据库的实际结构:

  • users 字段名与表中 name/email/role/created_at 一一对应。
  • orders.user_iduserId 的驼峰转换正确。
  • @relation 的外键引用正确指向 User.id

五、场景二:自动生成完整 CRUD

5.1 操作

基于 users 表生成完整的 CRUD 接口。要求:
- GET 列表:支持分页(page/pageSize)、role 筛选、name 模糊搜索
- GET 详情:根据 id 获取单个用户
- POST 创建:Zod 校验 name/email 格式
- PUT 更新:部分字段更新
- DELETE 删除:软删除(设置 deleted_at)
- 使用 Prisma ORM,TypeScript 类型安全
- Next.js App Router 的 Route Handler 格式

5.2 预期输出(核心代码)

// src/app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';
import { z } from 'zod';

// 查询参数校验
const querySchema = z.object({
  page: z.coerce.number().int().min(1).default(1),
  pageSize: z.coerce.number().int().min(1).max(100).default(10),
  role: z.enum(['admin', 'user']).optional(),
  search: z.string().optional(),
});

// 创建用户校验
const createSchema = z.object({
  name: z.string().min(1, '姓名不能为空').max(50),
  email: z.string().email('邮箱格式不正确'),
  role: z.enum(['admin', 'user']).default('user'),
});

export async function GET(request: NextRequest) {
  try {
    const { searchParams } = new URL(request.url);
    const { page, pageSize, role, search } = querySchema.parse(
      Object.fromEntries(searchParams)
    );

    // 构建查询条件
    const where: any = { deletedAt: null };
    if (role) where.role = role;
    if (search) {
      where.OR = [
        { name: { contains: search } },
        { email: { contains: search } },
      ];
    }

    // 并行查询数据和总数
    const [users, total] = await Promise.all([
      prisma.user.findMany({
        where,
        skip: (page - 1) * pageSize,
        take: pageSize,
        orderBy: { createdAt: 'desc' },
      }),
      prisma.user.count({ where }),
    ]);

    return NextResponse.json({
      code: 200,
      data: { list: users, total, page, pageSize },
      message: 'success',
    });
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json(
        { code: 400, data: null, message: error.errors[0].message },
        { status: 400 }
      );
    }
    return NextResponse.json(
      { code: 500, data: null, message: '服务器内部错误' },
      { status: 500 }
    );
  }
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const data = createSchema.parse(body);

    // 检查邮箱唯一性
    const existing = await prisma.user.findUnique({
      where: { email: data.email },
    });
    if (existing) {
      return NextResponse.json(
        { code: 400, data: null, message: '该邮箱已被注册' },
        { status: 400 }
      );
    }

    const user = await prisma.user.create({ data });
    return NextResponse.json(
      { code: 200, data: user, message: '创建成功' },
      { status: 201 }
    );
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json(
        { code: 400, data: null, message: error.errors[0].message },
        { status: 400 }
      );
    }
    return NextResponse.json(
      { code: 500, data: null, message: '服务器内部错误' },
      { status: 500 }
    );
  }
}

5.3 验证

用 curl 或 Postman 测试:

# 列表查询
curl "http://localhost:3000/api/users?page=1&pageSize=10&search=张"

# 创建用户
curl -X POST http://localhost:3000/api/users \
  -H "Content-Type: application/json" \
  -d '{"name":"赵六","email":"zhaoliu@example.com"}'

六、场景三:数据库变更同步

这是 MCP 最有价值的场景——让 AI 自动感知数据库变化并同步所有依赖

场景:你在 users 表中新增了 phone 字段。

-- 在数据库中执行
ALTER TABLE users ADD COLUMN phone TEXT;

然后在对话中输入:

users 表刚刚加了 phone 字段,帮我:
1. 更新 Prisma Schema
2. 更新 TypeScript 类型定义
3. 更新 API 接口中的校验和返回值
4. 更新前端表单
5. 生成变更清单

AI 会通过 MCP 读取最新表结构,感知到 phone 字段的存在,然后自动更新所有相关代码。

最佳实践:始终让 AI 通过 MCP 自己查表结构,不要凭记忆告诉它"users 表有这些字段……"。你在记忆里告诉 AI 的内容可能已经过时了,而 MCP 读取的是实时数据。


七、更多 MCP Server 示例

Server 配置方式 用处
GitHub npx -y @teolin/mcp-github + Token 查 Issue / PR / 代码
DuckDuckGo npx -y @anthropic/mcp-server-duckduckgo-search 免 Key 互联网搜索
PostgreSQL npx -y @modelcontextprotocol/server-postgres 查 PostgreSQL 数据库
文件系统 内置支持 读写本地文件

GitHub MCP 配置示例mcp.json):

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@teolin/mcp-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx"
      }
    }
  }
}

八、调试过程

8.1 MCP 不生效 / 未检测到工具

现象:输入"查数据库表结构",AI 返回"我无法访问数据库"。
原因排查:
  1. mcp.json 格式错误(JSON 语法错误,如多余的逗号)。
  2. 路径问题:data/app.db 相对于项目根目录的路径不正确。
  3. 未重启 CodeBuddy:修改 mcp.json 后需要重启。
排查步骤:
  1. 用 JSON 验证工具检查 mcp.json 格式是否正确。
  2. 在终端中手动验证 Server 能否启动:
     npx -y mcp-server-sqlite data/app.db
     如果有报错,根据报错信息修复。
  3. 重启 CodeBuddy(关闭并重新打开)。
修复:修正 JSON 格式 → 修正路径 → 重启。

8.2 连接失败

现象:MCP Server 配置了但连接失败,AI 请求超时。
原因排查:
  1. 网络问题:npx 首次运行需要下载包,可能超时。
  2. npm 镜像问题:国内网络可能无法直接访问 npm registry。
排查步骤:
  1. 在终端手动执行安装:
     npm install -g mcp-server-sqlite
     然后修改 mcp.json,将 "command": "npx" 改为 "command": "mcp-server-sqlite"。
  2. 如果下载慢,先设置国内镜像:
     npm config set registry https://registry.npmmirror.com/
修复:全局安装 → 改用本地命令 → 或配置代理/VPN。

8.3 Token 无效(GitHub MCP)

现象:GitHub MCP 报 "401 Unauthorized"。
原因排查:
  1. Token 过期或被撤销。
  2. Token 权限不足(没有读取 Issue/PR 的权限)。
排查步骤:
  1. 登录 GitHub → Settings → Developer settings → Personal access tokens。
  2. 检查 Token 状态和权限范围。
  3. 如果过期,重新生成并更新 mcp.json 中的环境变量。
修复:重新生成 Token → 确保勾选 repo 和 read:org 权限 → 更新配置 → 重启。

九、小结

MCP = AI 的感官延伸:看到数据库、触摸 GitHub、搜索互联网
核心价值:AI 不再猜你的表结构——它直接看到了
实战主线:SQLite → 查表 → Schema → CRUD → 智能查询 → 变更同步

一个原则:始终让 AI 通过 MCP 自己查,不要凭记忆告诉它
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐