1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
//! Example: Client resource access
//!
//! This example demonstrates:
//! - Listing available resources
//! - Reading resource contents
//! - Handling different content types
//! - Resource pagination
use pmcp::{Client, ClientCapabilities, StdioTransport};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize logging
tracing_subscriber::fmt()
.with_env_filter("pmcp=info")
.init();
println!("=== MCP Client Resources Example ===\n");
// Create and initialize client
let transport = StdioTransport::new();
let mut client = Client::new(transport);
// Use minimal capabilities - client doesn't need to advertise any special features
// to access resources from a server
let capabilities = ClientCapabilities::minimal();
println!("Connecting to server...");
let _server_info = client.initialize(capabilities).await?;
println!("✅ Connected!\n");
// List all resources with pagination
println!("📋 Listing all available resources:\n");
let mut cursor: Option<String> = None;
let mut page = 1;
loop {
let result = client.list_resources(cursor).await?;
if !result.resources.is_empty() {
println!("📄 Page {}:", page);
for resource in &result.resources {
println!("\n 🔗 URI: {}", resource.uri);
println!(" Name: {}", resource.name);
if let Some(desc) = &resource.description {
println!(" Description: {}", desc);
}
if let Some(mime) = &resource.mime_type {
println!(" MIME type: {}", mime);
}
}
}
cursor = result.next_cursor;
if cursor.is_none() {
break;
}
page += 1;
println!("\n--- More resources available ---");
}
// Read specific resources
println!("\n\n📖 Reading specific resources:");
// Example 1: Read a JSON configuration file
println!("\n1️⃣ Reading JSON config:");
match client
.read_resource("file://config/app.json".to_string())
.await
{
Ok(result) => {
for content in result.contents {
match content {
pmcp::types::Content::Resource {
uri,
text: Some(text),
ref mime_type,
..
} => {
println!(" URI: {}", uri);
if let Some(mime) = mime_type {
println!(" Type: {}", mime);
}
println!(" Content:\n{}", text);
// Parse JSON if it's JSON
if mime_type.as_ref().map(|s| s.as_str()) == Some("application/json") {
match serde_json::from_str::<serde_json::Value>(&text) {
Ok(json) => {
println!(" Parsed JSON: {:#?}", json);
},
Err(e) => {
println!(" Failed to parse JSON: {}", e);
},
}
}
},
pmcp::types::Content::Resource {
uri,
text: None,
mime_type,
..
} => {
println!(" URI: {} (no text content)", uri);
if let Some(mime) = mime_type {
println!(" Type: {}", mime);
}
},
pmcp::types::Content::Text { text } => {
println!(" Text content:\n{}", text);
},
pmcp::types::Content::Image { data, mime_type } => {
println!(
" Image content: {} (data length: {})",
mime_type,
data.len()
);
},
_ => {
println!(" [Other content type]");
},
}
}
},
Err(e) => {
println!(" ❌ Error: {}", e);
},
}
// Example 2: Read a CSV file
println!("\n2️⃣ Reading CSV data:");
match client
.read_resource("file://data/users.csv".to_string())
.await
{
Ok(result) => {
for content in result.contents {
if let pmcp::types::Content::Resource {
text: Some(text), ..
} = content
{
println!(" CSV Content:");
for line in text.lines() {
println!(" {}", line);
}
}
}
},
Err(e) => {
println!(" ❌ Error: {}", e);
},
}
// Example 3: Read a template resource with parameters
println!("\n3️⃣ Reading template resource:");
match client
.read_resource("template://greeting/Alice".to_string())
.await
{
Ok(result) => {
for content in result.contents {
match content {
pmcp::types::Content::Resource {
text: Some(text), ..
} => {
println!(" Message: {}", text);
},
pmcp::types::Content::Text { text } => {
println!(" Message: {}", text);
},
_ => {},
}
}
},
Err(e) => {
println!(" ❌ Error: {}", e);
},
}
// Example 4: Handle non-existent resource
println!("\n4️⃣ Testing error handling:");
match client
.read_resource("file://nonexistent.txt".to_string())
.await
{
Ok(_) => {
println!(" Unexpected success!");
},
Err(e) => {
println!(" ✅ Error caught: {}", e);
match &e {
pmcp::Error::Protocol { code, message, .. }
if code.as_i32() == pmcp::ErrorCode::METHOD_NOT_FOUND.as_i32() =>
{
println!(" Resource not found: {}", message);
},
_ => {
println!(" Other error type: {:?}", e);
},
}
},
}
Ok(())
}