use rustapi_rs::prelude::*;
use rustapi_rs::protocol::mcp::{run_rustapi_and_mcp_with_shutdown, McpConfig, McpServer};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Schema)]
struct Weather {
city: String,
temperature: i32,
unit: &'static str,
}
#[derive(Deserialize, Serialize, Schema)]
struct SumRequest {
a: i32,
b: i32,
}
#[derive(Serialize, Schema)]
struct SumResponse {
sum: i32,
}
#[rustapi_rs::get("/agent/weather/{city}")]
#[rustapi_rs::tag("agent")]
#[rustapi_rs::summary("Get weather information for a city")]
async fn get_weather(Path(city): Path<String>) -> Json<Weather> {
Json(Weather {
city,
temperature: 23,
unit: "C",
})
}
#[rustapi_rs::post("/agent/sum")]
#[rustapi_rs::tag("agent")]
#[rustapi_rs::summary("Add two integers and return the result")]
async fn sum(Json(req): Json<SumRequest>) -> Json<SumResponse> {
Json(SumResponse { sum: req.a + req.b })
}
#[rustapi_rs::get("/admin/internal-config")]
async fn internal_only() -> &'static str {
"this-should-never-be-visible-to-agents"
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let app = RustApi::auto();
let mcp = McpServer::from_rustapi(
&app,
McpConfig::new()
.name("rustapi-mcp-demo")
.version("0.1.0")
.description("Demo RustAPI instance exposing selected endpoints to AI agents via MCP")
.allowed_tags(["agent"]),
);
let http_addr = "0.0.0.0:8080";
let mcp_addr = "0.0.0.0:9090";
println!("🚀 HTTP API listening on http://{http_addr}");
println!("🧠 MCP server (for agents) http://{mcp_addr}");
println!();
println!("Useful MCP JSON-RPC calls (use tools/list to discover exact tool names):");
println!(" curl -X POST http://{mcp_addr} -H 'content-type: application/json' \\");
println!(" -d '{{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\"}}'");
println!();
println!(" curl -X POST http://{mcp_addr} -H 'content-type: application/json' \\");
println!(" -d '{{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\"}}'");
println!();
println!("Press Ctrl+C to stop both servers cleanly.");
run_rustapi_and_mcp_with_shutdown(app, http_addr, mcp, mcp_addr, async {
let _ = tokio::signal::ctrl_c().await;
})
.await?;
Ok(())
}