Skip to main content

agent_code_lib/tools/
mcp_resources.rs

1//! MCP resource tools: list and read resources from MCP servers.
2
3use async_trait::async_trait;
4use serde_json::json;
5
6use super::{Tool, ToolContext, ToolResult};
7use crate::error::ToolError;
8
9pub struct ListMcpResourcesTool;
10
11#[async_trait]
12impl Tool for ListMcpResourcesTool {
13    fn name(&self) -> &'static str {
14        "ListMcpResources"
15    }
16
17    fn description(&self) -> &'static str {
18        "List available resources from connected MCP servers."
19    }
20
21    fn input_schema(&self) -> serde_json::Value {
22        json!({
23            "type": "object",
24            "properties": {
25                "server": {
26                    "type": "string",
27                    "description": "Filter by server name (optional)"
28                }
29            }
30        })
31    }
32
33    fn is_read_only(&self) -> bool {
34        true
35    }
36
37    fn is_concurrency_safe(&self) -> bool {
38        true
39    }
40
41    async fn call(
42        &self,
43        _input: serde_json::Value,
44        _ctx: &ToolContext,
45    ) -> Result<ToolResult, ToolError> {
46        Ok(ToolResult::success(
47            "MCP resource listing requires connected servers. \
48             Configure servers in .agent/settings.toml under [mcp_servers].",
49        ))
50    }
51}
52
53pub struct ReadMcpResourceTool;
54
55#[async_trait]
56impl Tool for ReadMcpResourceTool {
57    fn name(&self) -> &'static str {
58        "ReadMcpResource"
59    }
60
61    fn description(&self) -> &'static str {
62        "Read a resource from an MCP server by URI."
63    }
64
65    fn input_schema(&self) -> serde_json::Value {
66        json!({
67            "type": "object",
68            "required": ["uri"],
69            "properties": {
70                "uri": {
71                    "type": "string",
72                    "description": "Resource URI to read"
73                }
74            }
75        })
76    }
77
78    fn is_read_only(&self) -> bool {
79        true
80    }
81
82    fn is_concurrency_safe(&self) -> bool {
83        true
84    }
85
86    async fn call(
87        &self,
88        input: serde_json::Value,
89        _ctx: &ToolContext,
90    ) -> Result<ToolResult, ToolError> {
91        let uri = input
92            .get("uri")
93            .and_then(|v| v.as_str())
94            .ok_or_else(|| ToolError::InvalidInput("'uri' is required".into()))?;
95
96        Ok(ToolResult::success(format!(
97            "MCP resource read for '{uri}' requires a connected server \
98             that provides this resource."
99        )))
100    }
101}