use serde_json::{json, Value};
use super::pagination::paginate;
use super::router::McpState;
use super::tools::{list_tools, McpContext};
fn cursor_of(params: &Option<Value>) -> Option<&str> {
params
.as_ref()
.and_then(|p| p.get("cursor"))
.and_then(Value::as_str)
}
use super::types::{
codes, Implementation, InitializeResult, JsonRpcError, ServerCapabilities, PROTOCOL_VERSION,
};
pub(crate) async fn dispatch(
state: &McpState,
method: &str,
params: Option<Value>,
ctx: Option<McpContext>,
request_id: Option<&str>,
) -> Result<Value, JsonRpcError> {
match method {
"initialize" => initialize(params),
"ping" => Ok(json!({})),
"tools/list" => {
let ctx = ctx.ok_or_else(auth_required)?;
paginate(
list_tools(&ctx.agent),
"tools",
cursor_of(¶ms),
state.page_size,
ctx.agent.agent_id,
)
}
"tools/call" => {
let ctx = ctx.ok_or_else(auth_required)?;
super::tools::call_tool_with(ctx, params.unwrap_or_else(|| json!({})), request_id).await
}
"prompts/list" => {
let ctx = ctx.ok_or_else(auth_required)?;
let full = super::resources::list_prompts(&ctx).await?;
let agent_id = ctx.agent.agent_id;
paginate(
full,
"prompts",
cursor_of(¶ms),
state.page_size,
agent_id,
)
}
"prompts/get" => {
let ctx = ctx.ok_or_else(auth_required)?;
super::resources::get_prompt(&ctx, params.unwrap_or_else(|| json!({}))).await
}
"resources/list" => {
let ctx = ctx.ok_or_else(auth_required)?;
let full = super::resources::list_resources(&ctx).await?;
let agent_id = ctx.agent.agent_id;
paginate(
full,
"resources",
cursor_of(¶ms),
state.page_size,
agent_id,
)
}
"resources/read" => {
let ctx = ctx.ok_or_else(auth_required)?;
super::resources::read_resource(&ctx, params.unwrap_or_else(|| json!({}))).await
}
"resources/templates/list" => {
ctx.ok_or_else(auth_required)?;
Ok(json!({ "resourceTemplates": [] }))
}
"logging/setLevel" => {
ctx.ok_or_else(auth_required)?;
super::utilities::set_log_level(params.unwrap_or_else(|| json!({})))
}
"completion/complete" => {
let ctx = ctx.ok_or_else(auth_required)?;
super::utilities::complete(&ctx, params.unwrap_or_else(|| json!({}))).await
}
other => Err(JsonRpcError::method_not_found(other)),
}
}
fn auth_required() -> JsonRpcError {
JsonRpcError::new(
codes::INVALID_REQUEST,
"tools require an authenticated agent (mount the agent-guarded MCP router)",
)
}
fn initialize(_params: Option<Value>) -> Result<Value, JsonRpcError> {
let result = InitializeResult {
protocol_version: PROTOCOL_VERSION,
capabilities: ServerCapabilities {
tools: Some(json!({ "listChanged": true })),
prompts: Some(json!({ "listChanged": true })),
resources: Some(json!({ "listChanged": true, "subscribe": false })),
logging: Some(json!({})),
completions: Some(json!({})),
},
server_info: Implementation {
name: "rustango",
version: env!("CARGO_PKG_VERSION"),
},
};
serde_json::to_value(result)
.map_err(|e| JsonRpcError::new(super::types::codes::INTERNAL_ERROR, e.to_string()))
}