上周有朋友看了我分享的如何用golang实现一个MCP Server,问我能分享个数据库的mcp server吗?我想着也没多难,那就实现一个吧。接下来我将详细的介绍如何使用github.com/mark3labs/mcp-go 实现一个PostgreSQL MCP Server。
1. 功能说明
首先,在开发前我们得明确下需求,我们的 MCP Server 需要支持以下功能:
- 创建表
- 展示表
- 执行读数据操作
- 执行写数据操作
2. 实现 MCP Server Tools
上面明确了需要实现的功能,下面我们来实现对应的Tools。
go
func createCreateTableTool() mcp.Tool {
return mcp.NewTool("create_table",
mcp.WithDescription("Create a new table in the postgres database"),
mcp.WithString("schema",
mcp.Required(),
mcp.Description("CREATE TABLE SQL statement"),
),
)
}
func createListTablesTool() mcp.Tool {
return mcp.NewTool("list_tables",
mcp.WithDescription("List all user tables in the database"),
mcp.WithString("schema",
mcp.Description("Optional schema name to filter tables"),
),
)
}
func createReadQueryTool() mcp.Tool {
return mcp.NewTool("read_query",
mcp.WithDescription("Execute a SELECT query on the postgres database"),
mcp.WithString("query",
mcp.Required(),
mcp.Description("SELECT SQL query to execute"),
),
)
}
func createWriteQueryTool() mcp.Tool {
return mcp.NewTool("write_query",
mcp.WithDescription("Execute an INSERT, UPDATE, or DELETE query on the postgres database"),
mcp.WithString("query",
mcp.Required(),
mcp.Description("SQL query to execute"),
),
)
}
3. 连接 PostgreSQL
在数据库操作的Tools定义完后,还需要实现对应的handle方法,但是在这之前得先建立和数据库的连接, 下面代码给出数据库的连接:
go
func initConnectionPool() error {
// 获取数据库连接信息
port, err := strconv.Atoi(os.Getenv("DB_PORT"))
if err != nil {
return fmt.Errorf("invalid DB_PORT: %w", err)
}
connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
os.Getenv("DB_HOST"),
port,
os.Getenv("DB_USER"),
os.Getenv("DB_PASSWORD"),
os.Getenv("DB_NAME"),
os.Getenv("DB_SSLMODE"),
)
// 连接数据库
db, err = sql.Open("postgres", connStr)
if err != nil {
return fmt.Errorf("database connection failed: %w", err)
}
if err = db.Ping(); err != nil {
return fmt.Errorf("database ping failed: %w", err)
}
log.Println("Successfully connected to database")
return nil
}
4. 添加handle函数
上面操作完成后,已经可以操作数据库了,接下来需要添加handle函数,用于处理来自mcp client的请求。
下面给出读取数据库表的handle函数的示例代码:
go
func readQueryToolHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
query, ok := request.Params.Arguments["query"].(string)
if !ok {
return nil, errors.New("invalid query parameter")
}
// 验证查询语句是否为SELECT语句
if !selectStmt.MatchString(query) {
return nil, errors.New("only SELECT queries are allowed")
}
rows, err := db.QueryContext(ctx, query)
if err != nil {
log.Printf("Query error: %v\n", err)
return nil, fmt.Errorf("query execution failed")
}
defer rows.Close()
results, err := parseSQLRows(rows)
if err != nil {
return nil, fmt.Errorf("result parsing failed")
}
return mcp.NewToolResultText(fmt.Sprintf("Query results: %v", results)), nil
}
5. 测试
因为框架这边已经做了listTools的能力,所以我们的开发工作基本完成,接下来就是测试功能是否正常了 之前有分享过Mcp Inspector来验证mcp server的功能,这里我们还是使用这个工具来测试我们的pgsql-mcp-server是否可以正常工作 测试步骤如下:
- 启动mcp inspector和待测代码建立连接
bash
npx @modelcontextprotocol/inspector go run main.go
- 跳转到http://localhost:5173 地址,在ui界面上测试功能
- 点击对应的tools进行测试
6. 配置到集成了mcp client的llm程序或插件
上面的测试验证基本没啥问题,这里我们可以用cline插件进行调式功能了。 首先是配置:
json
{
"mcpServers": {
"pgsql-mcp-server": {
"command": "C:\\Users\\Administrator\\go\\bin\\sql-mcp-server.exe",
"args": [],
"env": {
"GOPATH": "C:\\Users\\Administrator\\go",
"GOMODCACHE": "C:\\Users\\Administrator\\go\\pkg\\mod",
"DB_HOST": "localhost",
"DB_PORT": "5432",
"DB_NAME": "postgres",
"DB_USER": "admin",
"DB_PASSWORD": "postgres",
"DB_SSLMODE": "disable"
},
"disabled": false,
"autoApprove": []
}
}
}
保存配置后cline会自动尝试连接,当连接没问题会显示如下内容:
点击done即可在对话框中使用pgsql-mcp-server了,可以看到它对我输入的数据库的操作会调用tool去执行
查询表操作
总结
以上就是完整的使用 MCP-Go 开发一个 PostgreSQL MCP Server的流程。通过这个实现,你可以轻松地将 PostgreSQL 数据库功能暴露为 MCP 服务,供其他应用程序使用。 完整的代码我已经发布到github/pgsql-mcp-server上了,欢迎大家参考。