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
use rmcp::{transport::StreamableHttpClientTransport, ServiceExt};
use unia::{
mcp::MCPServer,
providers::{openai::OpenAI, Provider},
Agent,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// ============================================================================================
// Step 1: Setup Client
// ============================================================================================
let api_key = std::env::var("OPENAI_API_KEY").expect("OPENAI_API_KEY must be set");
let client = OpenAI::create(api_key, "gpt-5".to_string());
let agent = Agent::new(client);
// ============================================================================================
// Step 2: Connect to External MCP Server (Streamable HTTP)
// ============================================================================================
// We connect to the hosted GitHub MCP server via Streamable HTTP.
// URL: https://api.githubcopilot.com/mcp/
//
// For more information on how to connect to different MCP servers (stdio, SSE, etc.),
// please refer to the `rmcp` documentation.
println!("Connecting to GitHub MCP server...");
let transport = StreamableHttpClientTransport::from_uri("https://api.githubcopilot.com/mcp/");
let mcp_client = ().serve(transport).await?;
// Use the rmcp client directly as it implements MCPServer
let mcp_server = mcp_client;
// ============================================================================================
// Step 3: List Prompts
// ============================================================================================
// Prompts are reusable templates provided by the server.
println!("Listing prompts...");
// We use the MCPServer trait method here
let prompts = mcp_server.list_prompts().await?;
for prompt in &prompts {
println!("- {}", prompt.value.name);
}
// ============================================================================================
// Step 4: List Resources
// ============================================================================================
// Resources are data sources (files, logs, etc.) exposed by the server.
println!("Listing resources...");
let resources = mcp_server.list_resources().await?;
for resource in &resources {
println!("- {}", resource.value.uri);
}
// ============================================================================================
// Step 5: Use Prompts and Resources with Agent
// ============================================================================================
// Example: Get a prompt and convert it to messages
if let Some(first_prompt) = prompts.first() {
println!("Getting prompt: {}", first_prompt.value.name);
let prompt_result = mcp_server.get_prompt(first_prompt, None).await?;
// Convert Served<GetPromptResult> to Vec<Message> using From implementation
let messages: Vec<unia::model::Message> = prompt_result.into();
println!("Converted prompt to {} messages", messages.len());
// You can now pass these messages to the agent
// let response = agent.chat("...", messages).await?;
}
// Example: Read a resource and convert it to parts
if let Some(first_resource) = resources.first() {
println!("Reading resource: {}", first_resource.value.uri);
let resource_result = mcp_server.read_resource(first_resource).await?;
// Convert Served<ReadResourceResult> to Vec<Part> using From implementation
let parts: Vec<unia::model::Part> = resource_result.into();
println!("Converted resource to {} parts", parts.len());
// You can attach these parts to a user message
// let message = unia::model::Message::User(parts);
}
let _agent = agent.with_server(mcp_server);
// The agent can now use tools provided by GitHub.
// You can use `agent.chat(...)` to interact with the tools.
Ok(())
}