从零开始: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数据库智能助手的基础,下一章将实现更多的工具函数。

相关推荐
小小呱呱蛙1 小时前
Claude Code 自下而上分析(Slash/Sub Agents/Skills/MCP)带来的启发
agent·claude·mcp
callJJ2 小时前
MCP配置与实战:深入理解现代开发工具链
javascript·node.js·vue·mcp·windsurf
谷哥的小弟5 小时前
Brave Search MCP服务器安装以及客户端连接配置
搜索引擎·大模型·spring ai·mcp·brave search
太空眼睛5 小时前
【MCP】使用SpringBoot基于Streamable-HTTP构建MCP-Client
spring boot·ai·llm·sse·mcp·mcp-client·streamable
kaizq16 小时前
AI-MCP-SQLite-SSE本地服务及CherryStudio便捷应用
python·sqlite·llm·sse·mcp·cherry studio·fastmcp
太空眼睛19 小时前
【MCP】使用SpringBoot基于Streamable-HTTP构建MCP-Server
spring boot·sse·curl·mcp·mcp-server·spring-ai·streamable
康de哥1 天前
MCP Unity + Claude Code 配置关键步骤
unity·mcp·claude code
田井中律.1 天前
MCP协议
mcp
通义灵码2 天前
Qoder 支持通过 DeepLink 添加 MCP Server
人工智能·github·mcp
酩酊仙人3 天前
fastmcp构建mcp server和client
python·ai·mcp