mcp_ectors/examples/
hello_world.rs1use actix::ResponseFuture;
2use serde_json::Value;
3
4use crate::router::{router::CapabilitiesBuilder, Router};
5use mcp_spec::{handler::ResourceError, prompt::Prompt, protocol::{CallToolResult, GetPromptResult, ReadResourceResult, ServerCapabilities}, Content, Resource, Tool, ToolError};
6
7#[derive(Clone)]
9pub struct HelloWorldRouter;
10
11impl HelloWorldRouter {
12 pub fn new() -> Self {
13 Self {}
14 }
15}
16
17
18impl Router for HelloWorldRouter {
19 fn name(&self) -> String {
20 "hello_world".to_string()
21 }
22
23 fn instructions(&self) -> String {
24 "This server responds with a greeting, 'Hello {name}', where 'name' is the parameter passed.".to_string()
25 }
26
27 fn capabilities(&self) -> ServerCapabilities {
28 CapabilitiesBuilder::new()
29 .with_tools(true)
30 .with_prompts(false)
31 .with_resources(false, false)
32 .build()
33 }
34
35 fn list_tools(&self) -> Vec<Tool> {
36 vec![
37 Tool::new(
38 "greet".to_string(),
39 "Responds with a greeting 'Hello {name}'".to_string(),
40 serde_json::json!({
41 "type": "object",
42 "properties": {
43 "name": { "type": "string" }
44 },
45 "required": ["name"]
46 }),
47 ),
48 ]
49 }
50
51 fn call_tool(
52 &self,
53 tool_name: &str,
54 arguments: Value,
55 ) -> ResponseFuture<Result<CallToolResult, ToolError>> {
56 let tool_name = tool_name.to_string();
57
58 Box::pin(async move {
59 match tool_name.as_str() {
60 "greet" => {
61 if let Some(name) = arguments.get("name").and_then(|v| v.as_str()) {
63 let greeting = format!("Hello {}", name);
64 let result = CallToolResult{ content: vec![Content::text(greeting)], is_error: Some(false) };
65 Ok(result)
66 } else {
67 Err(ToolError::InvalidParameters("Missing or invalid 'name' parameter.".to_string()))
68 }
69 }
70 _ => Err(ToolError::NotFound(format!("Tool {} not found", tool_name))),
71 }
72 })
73 }
74
75 fn list_resources(&self) -> Vec<Resource> {
76 vec![]
77 }
78
79 fn read_resource(
80 &self,
81 _uri: &str,
82 ) -> ResponseFuture<Result<ReadResourceResult, ResourceError>> {
83 Box::pin(async { Err(ResourceError::NotFound("Resource not found".to_string())) })
84 }
85
86 fn list_prompts(&self) -> Vec<Prompt> {
87 vec![]
88 }
89
90 fn get_prompt(&self, _prompt_name: &str) -> ResponseFuture<Result<GetPromptResult, ResourceError>> {
91
92 let result = GetPromptResult{ description: None, messages: vec![] };
93 Box::pin(async move {
94 Ok(result)
95 })
96 }
97}
98