从零开始:MCP数据库助手(一)- 基础搭建

MCP是什么?为什么要用它?

MCP全称Model Context Protocol,简单说就是让AI助手能够调用外部工具的标准协议。想象一下,如果AI只能聊天,那就像一个很聪明但没有手的人。MCP就是给AI装上了"手",让它能够真正操作数据库、文件系统等等。

对于数据库操作来说,MCP的优势特别明显:

  • 一问即答:直接问AI就能获取数据库信息
  • 安全可控:AI只能调用你预设的工具函数
  • 智能分析:AI能理解数据关系,给出有用的建议

第一步:项目结构搭建

咱们先把项目的骨架搭起来。

bash 复制代码
v1/
├── pyproject.toml            # uv 项目配置
├── README.md                # 项目说明
├── src/
│   └── mcp_datatools/       # 主包
│       ├── __init__.py
│       ├── server.py        # MCP 服务器
│       └── database.py      # 数据库管理
├── data/
│   ├── init_scripts/
│   │   └── init_sqlite_db.py   # 初始化 SQLite 数据库脚本
│   └── test.db             # SQLite 测试数据库
└── tests/                  # 测试文件目录

为什么这样设计?

  • 使用 uv 作为包管理器,更现代更快速
  • src/ 目录让代码结构更清晰
  • data/ 存放测试数据和初始化脚本
  • tests/ 目录为后续单元测试预留
  • 配置文件简洁,专注核心功能

第二步:环境配置和依赖

咱们使用现代的 uv 包管理器来管理依赖:

bash 复制代码
# 安装 uv (如果还没有安装)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 进入项目目录
cd v1

# 安装依赖
uv sync

pyproject.toml 文件内容:

toml 复制代码
[project]
name = "mcp-datatools"
version = "0.1.0"
description = "A MCP server that connects to your database"
requires-python = ">=3.10"

dependencies = [
    "mcp>=1.0.0",
    "sqlalchemy>=2.0.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

为什么选择 uv

  • 速度极快:比 pip 快 10-100 倍
  • 依赖解析:更智能的依赖管理
  • 项目隔离:自动创建虚拟环境
  • 现代标准:支持最新的 Python 包管理标准

第三步:数据库连接管理

数据库连接是整个项目的基础,咱们先把这部分搞定。我设计了一个DatabaseManager类来管理连接:

python 复制代码
"""
database.py - 数据库管理模块
"""

import os
from typing import List
from contextlib import contextmanager
from sqlalchemy import create_engine,inspect,text
from sqlalchemy.exc import SQLAlchemyError
from mcp.server.fastmcp.utilities.logging import get_logger


logger = get_logger(__name__)

class DatabaseManager:
    """数据库管理器"""
    def __init__(self):
        """初始化数据库管理器"""
        
        self.database_url = os.getenv("DB_URL")
        self.engine = None
        self._connect()


    def _connect(self) -> None:
        """连接数据库"""
        try:
            self.engine = create_engine(self.database_url, echo=False)
            logger.info(f"成功连接到数据库: {self.database_url}")
        except Exception as e:
            logger.error(f"连接数据库时出错: {str(e)}")
            raise

    @contextmanager
    def get_connection(self):
        """获取数据库连接的上下文管理器"""
        if not self.engine:
            raise RuntimeError("数据库未连接")
        
        conn = self.engine.connect()
        try:
            yield conn
        finally:
            conn.close()
    
    def get_table_names(self) -> List[str]:
        """获取数据库中的所有表名"""
        try:
            with self.get_connection() as conn:
                inspector = inspect(conn)
                table_names = inspector.get_table_names()
                return table_names
        except SQLAlchemyError as e:
            logger.error(f"获取表名失败: {e}")
            raise

    def test_connection(self) -> bool:
        """测试数据库连接"""
        try:
            with self.get_connection() as conn:

                result = conn.execute(text("SELECT 1")).scalar()
                return result == 1
        except Exception as e:
            logger.error(f"测试数据库连接时出错: {str(e)}")
            return False

    def get_db_info(self) -> str:
        try:
            tables = self.get_table_names()
            return f"数据库URL: {self.database_url}\n共有 {len(tables)} 个表"
        except Exception:
            return f"数据库URL: {self.database_url}\n数据库连接失败"

    def close(self) -> None:
        """关闭数据库连接"""
        if self.engine:
            self.engine.dispose()
            logger.info("数据库连接已关闭")
        

第四步:第一个MCP工具函数

现在是最重要的部分 - 实现第一个MCP工具函数list_tables()

python 复制代码
"""
server.py - MCP服务器主文件
"""

import os
from mcp.server.fastmcp import FastMCP
from mcp.server.fastmcp.utilities.logging import get_logger
from .database import DatabaseManager

mcp = FastMCP("MCP DataTools")
logger = get_logger(__name__)
db_manager = None

def get_database_manager():
    """获取数据库管理器实例"""
    global db_manager
    if db_manager is None:
        db_manager = DatabaseManager()
    return db_manager
    
@mcp.tool(description="查询数据库中的所有表")
def list_tables() -> str:
    """获取数据库表列表"""
    try:
        db_mgr = get_database_manager()
        tables = db_mgr.get_table_names()
        
        if tables:
            table_list = ",".join(tables)
            result = f"数据库中共有 {len(tables)} 个表:\n\n"
            for i,table in enumerate(tables,1):
                result += f"{i}. {table}\n"
            logger.info(f"成功返回 {len(tables)} 个表: {table_list}")
            return result
        else:
            return "数据库中没有表"

    except Exception as e:
        error_msg = f"获取数据库表列表失败: {str(e)}"
        logger.error(error_msg)
        return f"{error_msg}\n\n请检查数据库连接。"


def main():
    try:
        logger.info("启动MCP DataTools服务器")

        db_mgr = get_database_manager()

        if db_mgr.test_connection():
            logger.info("数据库连接测试成功")
        else:
            logger.warning("数据库连接测试失败,但服务器仍会启动")
            logger.info("提示:运行 'python data/init_scripts/init_sqlite_db.py' 创建测试数据库")

        logger.info("当前功能:list_tables() - 获取数据库表列表")
        logger.info("MCP服务器启动成功,等待客户端连接...")
        
        mcp.run()

    except Exception as e:
        logger.error(f"服务器启动失败: {str(e)}")
        raise

if __name__ == "__main__":
    main()

第五步:测试数据准备

光有工具还不行,得有数据来测试。第1周我们创建一个超级简单的测试数据库,重点是能让list_tables()功能工作:

python 复制代码
"""
data/init_sqlite_db.py - 初始化 SQLite 数据库
"""

import sqlite3
import os
from pathlib import Path

def create_simple_test_database():
    """创建简单测试数据库"""
    
    data_dir = Path(__file__).parent.parent / "data"
    db_path = data_dir / "test.db"
    
    print(" 测试数据库创建器")
    print(f"数据库路径: {db_path}")
    
    if db_path.exists():
        os.remove(db_path)
        print("删除旧数据库文件")
    
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    
    try:
        print("创建基础表结构...")
        
        # 创建用户表
        cursor.execute("""
            CREATE TABLE users (
                id INTEGER PRIMARY KEY,
                name VARCHAR(50) NOT NULL,
                email VARCHAR(100) NOT NULL
            )
        """)
        
        # 创建产品表
        cursor.execute("""
            CREATE TABLE products (
                id INTEGER PRIMARY KEY,
                name VARCHAR(100) NOT NULL,
                price DECIMAL(10, 2) NOT NULL
            )
        """)
        
        # 创建订单表
        cursor.execute("""
            CREATE TABLE orders (
                id INTEGER PRIMARY KEY,
                user_id INTEGER,
                total_amount DECIMAL(10, 2)
            )
        """)
        
        print("插入测试数据...")
        
        # 插入测试数据
        cursor.execute("INSERT INTO users (name, email) VALUES ('Alice', 'alice@test.com')")
        cursor.execute("INSERT INTO users (name, email) VALUES ('Bob', 'bob@test.com')")
        
        cursor.execute("INSERT INTO products (name, price) VALUES ('笔记本电脑', 5999.99)")
        cursor.execute("INSERT INTO products (name, price) VALUES ('鼠标', 129.99)")
        
        cursor.execute("INSERT INTO orders (user_id, total_amount) VALUES (1, 6129.98)")
        cursor.execute("INSERT INTO orders (user_id, total_amount) VALUES (2, 129.99)")
        
        conn.commit()
        
        print("测试数据库创建成功!")
        print("数据库包含表:")
        print("  1. users - 用户表 (2条记录)")
        print("  2. products - 产品表 (2条记录)")
        print("  3. orders - 订单表 (2条记录)")
        
    except Exception as e:
        print(f"创建数据库时出错: {e}")
        conn.rollback()
        raise
    finally:
        conn.close()

if __name__ == "__main__":
    create_simple_test_database()

运行这个脚本:

bash 复制代码
python data/init_scripts/init_sqlite_db.py

你就会得到一个包含3个基础表的测试数据库。

第六步:Cursor 集成测试

配置 Cursor

在 Cursor 的 MCP 配置中添加我们的服务器。打开 Cursor 设置,找到 MCP 配置部分:

json 复制代码
{
  "mcpServers": {
    "mcp-datatools": {
      "command": "uv",
      "args": ["run", "--project", "/path", "python", "-m", "mcp_datatools.server"],
      "env": {
        "DB_URL": "sqlite:///data/test.db"
      }
    }
  }
}

正常来说是能开启的:

测试功能

总结与预告

第1章我们成功搭建了MCP数据库智能助手的基础,下一章将实现更多的工具函数。

相关推荐
红鼻子时代2 小时前
从零开始:MCP数据库助手(二)- 核心功能实现
mcp
Light601 天前
【MCP原生时代】第7篇|治理与合规:在模型驱动自动化中把控法律、隐私与伦理风险——把“能做什么”变成可审计、可解释、可追责的企业能力
人工智能·隐私·审计·治理·合规·mcp·伦理
12344521 天前
【MCP入门篇】从0到1教你搭建MCP服务
后端·mcp
csdn5659738501 天前
借助 MCP 赋能数据可视化,让数据‘燃’起来
信息可视化·mcp
阿湯哥2 天前
基于MCP协议的LLM-Agent数据流转与业务实现详解
llm·框架·agent·mcp·分工
阿湯哥2 天前
MCP协议核心概念与通信机制
ai·mcp
许泽宇的技术分享2 天前
解密Anthropic的MCP Inspector:从协议调试到AI应用开发的全栈架构之旅
人工智能·架构·typescript·mcp·ai开发工具
iFlow_AI2 天前
知识驱动开发:用iFlow工作流构建本地知识库
前端·ai·rag·mcp·iflow·iflow cli·iflowcli
qdprobot2 天前
齐护机器人AiTallpro小智AI图形化编程Mixly Scratch MQTT MCP远程控制
人工智能·mqtt·机器人·图形化编程·ai对话·mcp·小智ai