use mcp_client_fishcode2025::{
client::{ClientCapabilities, ClientInfo, McpClient, McpClientTrait},
transport::{StdioTransport, Transport},
McpService,
};
use serde_json::json;
use std::{collections::HashMap, env, time::Duration};
fn print_usage() {
println!("SQLite MCP 客户端示例");
println!("用法:");
println!(" cargo run --example client -- [服务器路径] [选项]");
println!();
println!("参数:");
println!(" [服务器路径] SQLite MCP 服务器可执行文件的路径 (默认: ./mcp-sqlite)");
println!();
println!("选项:");
println!(" --db <路径> SQLite 数据库文件路径 (默认: :memory:)");
println!(" --help 显示此帮助信息");
println!();
println!("示例:");
println!(" cargo run --example client -- ./target/release/mcp-sqlite");
println!(" cargo run --example client -- ./target/release/mcp-sqlite --db ./test.db");
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().collect();
if args.len() > 1 && (args[1] == "--help" || args[1] == "-h") {
print_usage();
return Ok(());
}
let server_path = if args.len() > 1 && !args[1].starts_with("-") {
args[1].clone()
} else {
"./mcp-sqlite".to_string()
};
let mut db_path = ":memory:".to_string();
let mut server_args = Vec::new();
let mut i = 2;
while i < args.len() {
match args[i].as_str() {
"--db" => {
if i + 1 < args.len() {
db_path = args[i + 1].clone();
i += 2;
} else {
println!("错误: --db 参数需要指定数据库路径");
print_usage();
return Ok(());
}
}
"--help" | "-h" => {
print_usage();
return Ok(());
}
arg => {
server_args.push(arg.to_string());
i += 1;
}
}
}
server_args.push("--db".to_string());
server_args.push(db_path.clone());
println!("使用服务器: {}", server_path);
println!("使用数据库: {}", db_path);
println!("服务器参数: {:?}", server_args);
let transport = StdioTransport::new(server_path, server_args, HashMap::new());
let handle = transport.start().await?;
let service = McpService::with_timeout(handle, Duration::from_secs(30));
let mut client = McpClient::new(service);
let info = ClientInfo {
name: "mcp-sqlite-client".to_string(),
version: "1.0.0".to_string(),
};
let capabilities = ClientCapabilities::default();
client.initialize(info, capabilities).await?;
println!("已连接到SQLite MCP服务器");
println!("创建users表...");
let result = client.call_tool("execute", json!({
"statement": "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"
})).await?;
println!("插入数据...");
let result = client
.call_tool(
"execute",
json!({
"statement": "INSERT INTO users (name, email) VALUES (?, ?)",
"params": ["张三", "zhangsan@example.com"]
}),
)
.await?;
println!("插入结果: {:?}", result);
println!("批量插入数据...");
let result = client
.call_tool(
"executemany",
json!({
"statement": "INSERT INTO users (name, email) VALUES (?, ?)",
"params_list": [
["李四", "lisi@example.com"],
["王五", "wangwu@example.com"],
["赵六", "zhaoliu@example.com"]
]
}),
)
.await?;
println!("批量插入结果: {:?}", result);
println!("查询所有用户...");
let result = client
.call_tool(
"query",
json!({
"query": "SELECT * FROM users"
}),
)
.await?;
println!("查询结果:");
if let Some(content) = result.content.first() {
match content {
mcp_core_fishcode2025::content::Content::Text(text_content) => {
if let Ok(json_value) =
serde_json::from_str::<serde_json::Value>(&text_content.text)
{
if let (Some(columns), Some(rows)) = (
json_value.get("columns").and_then(|v| v.as_array()),
json_value.get("rows").and_then(|v| v.as_array()),
) {
let header: Vec<String> = columns
.iter()
.map(|c| c.as_str().unwrap_or("").to_string())
.collect();
println!("{}", header.join(" | "));
println!("{}", "-".repeat(header.join(" | ").len()));
for row in rows {
if let Some(row_array) = row.as_array() {
let row_str: Vec<String> = row_array
.iter()
.map(|v| match v {
serde_json::Value::Null => "NULL".to_string(),
_ => v.to_string().replace('"', ""),
})
.collect();
println!("{}", row_str.join(" | "));
}
}
}
}
}
_ => println!("无法解析结果内容"),
}
}
println!("\n按名称查询用户...");
let result = client
.call_tool(
"query",
json!({
"query": "SELECT * FROM users WHERE name = ?",
"params": ["张三"]
}),
)
.await?;
println!("查询结果: {:?}", result);
println!("\n执行SQL脚本...");
let result = client
.call_tool(
"executescript",
json!({
"script": "
CREATE TABLE IF NOT EXISTS products (id INTEGER PRIMARY KEY, name TEXT, price REAL);
INSERT INTO products (name, price) VALUES ('产品A', 99.99);
INSERT INTO products (name, price) VALUES ('产品B', 199.99);
"
}),
)
.await?;
println!("脚本执行结果: {:?}", result);
println!("\n查询products表...");
let result = client
.call_tool(
"query",
json!({
"query": "SELECT * FROM products"
}),
)
.await?;
println!("查询结果: {:?}", result);
println!("\n示例完成");
Ok(())
}