项目简介

'claude-agent-sdk-rs' 是一个Rust语言开发的SDK,用于与Claude Code命令行工具(CLI)进行交互。它不仅提供客户端功能,实现对Claude AI的程序化访问和双向流式通信,还包含了一项独特的能力:在Rust应用程序内部运行“Model Context Protocol (MCP)”服务器,以托管和提供自定义工具给Claude Code CLI使用。这意味着您可以利用Rust的强大性能和类型安全来创建Claude AI可调用的个性化功能。

主要功能点

  • 嵌入式MCP工具服务器: 在您的Rust应用中创建并运行轻量级的MCP服务器,用于向Claude AI暴露自定义工具。
  • 工具注册与执行: 通过简单的宏定义('tool!'),快速注册自定义函数作为Claude可调用的工具,并处理其调用逻辑。
  • JSON-RPC协议支持: SDK内部的MCP服务器遵循JSON-RPC协议,确保与Claude Code CLI的标准化通信。
  • 高度可扩展: 允许您以类型安全的方式扩展Claude的功能,集成各种外部服务或业务逻辑。

安装步骤

  1. Rust环境: 确保您已安装Rust编程语言(版本1.70或更高)。
  2. Claude Code CLI: 这是一个外部依赖,请按照Claude官方指南安装Claude Code CLI工具(版本2.0.0或更高)。
  3. API Key: 配置Anthropic API Key,可以设置为环境变量'ANTHROPIC_API_KEY'或通过Claude Code CLI进行配置。
  4. 添加依赖: 在您的Rust项目的'Cargo.toml'文件中添加'claude-agent-sdk-rs'和'tokio'作为依赖:
    [dependencies]
    claude-agent-sdk-rs = "0.1"
    tokio = { version = "1", features = ["full"] }
    或者使用'cargo add'命令:
    cargo add claude-agent-sdk-rs
    cargo add tokio --features full

服务器配置

要在您的Rust应用程序中启动一个MCP服务器来托管自定义工具,您需要先定义工具,然后将它们集合成一个SDK MCP服务器实例,最终在Claude客户端配置中引用它。MCP服务器的配置信息将作为Claude客户端启动参数的一部分,由Claude Code CLI(MCP客户端)来解析和连接。

以下是MCP客户端(Claude Code CLI)所需的配置信息格式及参数注释,您的Rust MCP工具服务器将作为其中的'sdk'类型服务器被引用:

{
  "mcp_servers": {
    "your-server-name": {  // 您为MCP服务器定义的唯一名称
      "type": "sdk"        // 表明这是一个SDK内部实现的MCP服务器
      // 注意:SDK内部服务器实例本身无法直接序列化到JSON。
      // 在实际运行中,Rust SDK会将您的 'SdkMcpServer' 实例
      // 传递给内部逻辑,Claude Code CLI通过Rust SDK的控制协议
      // 直接与该内部实例通信。因此,这里的JSON配置仅为概念性说明,
      // 实际Rust代码中是直接构建 'McpServerConfig::Sdk(server)'。
    }
  },
  "allowed_tools": [
    "mcp__your-server-name__your-tool-1", // 允许Claude Code CLI调用您的自定义工具
    "mcp__your-server-name__your-tool-2"  // 格式为 mcp__{服务器名称}__{工具名称}
  ]
  // 其他ClaudeAgentOptions配置,如model、max_turns、permission_mode等
}

您的Rust代码将通过'create_sdk_mcp_server'函数创建MCP服务器实例,并将其传入'ClaudeAgentOptions':

use claude_agent_sdk_rs::{tool, create_sdk_mcp_server, ToolResult, McpToolResultContent, ClaudeAgentOptions, McpServers};
use serde_json::json;
use std::collections::HashMap;

// 1. 定义工具的处理逻辑
async fn greet_handler(args: serde_json::Value) -> anyhow::Result<ToolResult> {
    let name = args["name"].as_str().unwrap_or("World");
    Ok(ToolResult {
        content: vec![McpToolResultContent::Text {
            text: format!("Hello, {}!", name),
        }],
        is_error: false,
    })
}

// 2. 使用 'tool!' 宏创建工具定义
let greet_tool = tool!(
    "greet", // 工具名称,会出现在 allowed_tools 中
    "Greet a user", // 工具描述
    json!({
        "type": "object",
        "properties": {
            "name": { "type": "string" }
        },
        "required": ["name"]
    }), // 工具的JSON Schema输入定义
    greet_handler // 工具的处理函数
);

// 3. 创建SDK MCP服务器实例
let server_name = "my-rust-tools"; // 您的服务器名称
let server_version = "1.0.0";
let my_mcp_server_instance = create_sdk_mcp_server(
    server_name,
    server_version,
    vec![greet_tool] // 包含所有自定义工具
);

// 4. 将MCP服务器配置到ClaudeAgentOptions
let mut mcp_servers_map = HashMap::new();
mcp_servers_map.insert(
    server_name.to_string(),
    claude_agent_sdk_rs::McpServerConfig::Sdk(my_mcp_server_instance)
);

let options = ClaudeAgentOptions {
    mcp_servers: McpServers::Dict(mcp_servers_map),
    // 允许Claude Code CLI调用您的自定义工具
    allowed_tools: vec![format!("mcp__{}__{}", server_name, "greet")],
    permission_mode: Some(claude_agent_sdk_rs::PermissionMode::AcceptEdits),
    ..Default::default()
};
// 接下来,使用这个 'options' 创建 'ClaudeClient' 并进行交互。

基本使用方法

配置好'ClaudeAgentOptions'并创建'ClaudeClient'后,即可连接Claude Code CLI并与您的自定义工具进行交互。Claude AI会根据您的提示和工具定义,在需要时自动调用您提供的工具。

use claude_agent_sdk_rs::{ClaudeClient, ClaudeAgentOptions, McpServers, McpToolResultContent, Message, ContentBlock, tool, create_sdk_mcp_server, ToolResult};
use serde_json::json;
use std::collections::HashMap;
use futures::StreamExt; // 用于处理异步流

// 定义一个简单的问候工具
async fn greet_handler(args: serde_json::Value) -> anyhow::Result<ToolResult> {
    let name = args["name"].as_str().unwrap_or("World");
    Ok(ToolResult {
        content: vec![McpToolResultContent::Text {
            text: format!("Hello, {}!", name),
        }],
        is_error: false,
    })
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 1. 创建自定义工具
    let greet_tool = tool!(
        "greet",
        "Greet a user by name",
        json!({"type": "object", "properties": {"name": {"type": "string"}}, "required": ["name"]}),
        greet_handler
    );

    // 2. 将工具集合到SDK MCP服务器
    let server_name = "my-custom-tools";
    let my_mcp_server = create_sdk_mcp_server(server_name, "1.0.0", vec![greet_tool]);

    // 3. 配置Claude客户端,使其知晓并允许使用该MCP服务器及其工具
    let mut mcp_servers_map = HashMap::new();
    mcp_servers_map.insert(server_name.to_string(), claude_agent_sdk_rs::McpServerConfig::Sdk(my_mcp_server));

    let options = ClaudeAgentOptions {
        mcp_servers: McpServers::Dict(mcp_servers_map),
        allowed_tools: vec![format!("mcp__{}__{}", server_name, "greet")],
        permission_mode: Some(claude_agent_sdk_rs::PermissionMode::AcceptEdits),
        max_turns: Some(5),
        ..Default::default()
    };

    // 4. 创建并连接Claude客户端
    let mut client = ClaudeClient::new(options);
    client.connect().await?;
    println!("客户端已连接。");

    // 5. 向Claude发送请求,让其使用您的自定义工具
    println!("用户: 问候Alice。");
    client.query("Greet Alice").await?;

    // 6. 接收并处理来自Claude的响应
    let mut stream = client.receive_response();
    while let Some(message) = stream.next().await {
        match message? {
            Message::Assistant(msg) => {
                for block in msg.message.content {
                    if let ContentBlock::Text(text) = block {
                        println!("Claude: {}", text.text);
                    }
                }
            }
            Message::User(user_msg) => { // 工具结果通常作为UserMessage返回
                if let Some(content_blocks) = &user_msg.content {
                    for content in content_blocks {
                        if let ContentBlock::ToolResult(result) = content {
                            if let Some(claude_agent_sdk_rs::ToolResultContent::Text(text)) = &result.content {
                                println!("自定义工具 ({}) 返回: {}", result.tool_use_id, text);
                            }
                        }
                    }
                }
            }
            Message::Result(result) => {
                println!("\n[对话结束] 耗时: {}ms, 成本: ${:.4}\n",
                         result.duration_ms, result.total_cost_usd.unwrap_or(0.0));
            }
            _ => {}
        }
    }
    drop(stream); // 释放对流的借用

    // 7. 断开连接
    client.disconnect().await?;
    println!("客户端已断开连接。");

    Ok(())
}

信息

分类

开发者工具