use std::collections::HashMap;
use std::sync::Arc;
use heartbit_core::tool::builtins::{BuiltinToolsConfig, builtin_tools};
use heartbit_core::{AgentRunner, AnthropicProvider, BoxedProvider, McpClient, RetryingProvider};
#[tokio::main]
async fn main() -> Result<(), heartbit_core::Error> {
let api_key =
std::env::var("ANTHROPIC_API_KEY").expect("set ANTHROPIC_API_KEY environment variable");
let provider = Arc::new(BoxedProvider::new(RetryingProvider::with_defaults(
AnthropicProvider::new(&api_key, "claude-sonnet-4-20250514"),
)));
let mut tools = builtin_tools(BuiltinToolsConfig::default());
let mcp_args: Vec<String> = std::env::args().skip(1).collect();
if !mcp_args.is_empty() {
eprintln!("[connecting to MCP server: {}]", mcp_args.join(" "));
match McpClient::connect_stdio(&mcp_args[0], &mcp_args[1..], &HashMap::new()).await {
Ok(client) => {
let mcp_tools = client.into_tools();
eprintln!("[discovered {} MCP tools]", mcp_tools.len());
tools.extend(mcp_tools);
}
Err(e) => {
eprintln!("[MCP connection failed: {e}; falling back to built-ins]");
}
}
}
let agent = AgentRunner::builder(provider)
.system_prompt("You are a helpful assistant. Prefer MCP tools when available.")
.tools(tools)
.max_turns(10)
.build()?;
let task = if mcp_args.is_empty() {
"List the names of the built-in tools you have access to."
} else {
"List the tools you have access to from the connected MCP server."
};
let output = agent.execute(task).await?;
println!("{}", output.result);
Ok(())
}