From d57e44efe19274235d90c6ff1e85a5563498e2d7 Mon Sep 17 00:00:00 2001 From: Gabriel Gordon-Hall Date: Thu, 17 Jul 2025 10:20:49 +0100 Subject: [PATCH] chore: update `rmcp` crate version (#221) * update rmcp crate and mcp protocol version * update mcp prompt to encourage it to call list_tasks --- backend/Cargo.toml | 2 +- backend/src/mcp/task_server.rs | 49 +++++++++++++++++----------------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 5fe28d9e..a23d7630 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -37,7 +37,7 @@ ignore = "0.4" command-group = { version = "5.0", features = ["with-tokio"] } nix = { version = "0.29", features = ["signal", "process"] } openssl-sys = { workspace = true } -rmcp = { version = "0.1.5", features = ["server", "transport-io"] } +rmcp = { version = "0.2.1", features = ["server", "transport-io"] } schemars = "0.8" regex = "1.11.1" notify-rust = "4.11" diff --git a/backend/src/mcp/task_server.rs b/backend/src/mcp/task_server.rs index 875d8623..bff338a3 100644 --- a/backend/src/mcp/task_server.rs +++ b/backend/src/mcp/task_server.rs @@ -1,8 +1,11 @@ +use std::future::Future; + use rmcp::{ + handler::server::tool::{Parameters, ToolRouter}, model::{ CallToolResult, Content, Implementation, ProtocolVersion, ServerCapabilities, ServerInfo, }, - schemars, tool, Error as RmcpError, ServerHandler, + schemars, tool, tool_handler, tool_router, Error as RmcpError, ServerHandler, }; use serde::{Deserialize, Serialize}; use serde_json; @@ -24,11 +27,6 @@ pub struct CreateTaskRequest { pub description: Option, } -#[derive(Debug, Deserialize, schemars::JsonSchema)] -pub struct ListProjectsRequest { - // Empty for now, but we can add filtering options later -} - #[derive(Debug, Serialize, schemars::JsonSchema)] pub struct CreateTaskResponse { pub success: bool, @@ -196,27 +194,31 @@ pub struct GetTaskResponse { #[derive(Debug, Clone)] pub struct TaskServer { pub pool: SqlitePool, + tool_router: ToolRouter, } impl TaskServer { #[allow(dead_code)] pub fn new(pool: SqlitePool) -> Self { - Self { pool } + Self { + pool, + tool_router: Self::tool_router(), + } } } -#[tool(tool_box)] +#[tool_router] impl TaskServer { #[tool( description = "Create a new task/ticket in a project. Always pass the `project_id` of the project you want to create the task in - it is required!" )] async fn create_task( &self, - #[tool(aggr)] CreateTaskRequest { + Parameters(CreateTaskRequest { project_id, title, description, - }: CreateTaskRequest, + }): Parameters, ) -> Result { // Parse project_id from string to UUID let project_uuid = match Uuid::parse_str(&project_id) { @@ -298,10 +300,7 @@ impl TaskServer { } #[tool(description = "List all the available projects")] - async fn list_projects( - &self, - #[tool(aggr)] _request: ListProjectsRequest, - ) -> Result { + async fn list_projects(&self) -> Result { match Project::find_all(&self.pool).await { Ok(projects) => { let count = projects.len(); @@ -352,11 +351,11 @@ impl TaskServer { )] async fn list_tasks( &self, - #[tool(aggr)] ListTasksRequest { + Parameters(ListTasksRequest { project_id, status, limit, - }: ListTasksRequest, + }): Parameters, ) -> Result { let project_uuid = match Uuid::parse_str(&project_id) { Ok(uuid) => uuid, @@ -491,13 +490,13 @@ impl TaskServer { )] async fn update_task( &self, - #[tool(aggr)] UpdateTaskRequest { + Parameters(UpdateTaskRequest { project_id, task_id, title, description, status, - }: UpdateTaskRequest, + }): Parameters, ) -> Result { let project_uuid = match Uuid::parse_str(&project_id) { Ok(uuid) => uuid, @@ -626,10 +625,10 @@ impl TaskServer { )] async fn delete_task( &self, - #[tool(aggr)] DeleteTaskRequest { + Parameters(DeleteTaskRequest { project_id, task_id, - }: DeleteTaskRequest, + }): Parameters, ) -> Result { let project_uuid = match Uuid::parse_str(&project_id) { Ok(uuid) => uuid, @@ -720,10 +719,10 @@ impl TaskServer { )] async fn get_task( &self, - #[tool(aggr)] GetTaskRequest { + Parameters(GetTaskRequest { project_id, task_id, - }: GetTaskRequest, + }): Parameters, ) -> Result { let project_uuid = match Uuid::parse_str(&project_id) { Ok(uuid) => uuid, @@ -802,11 +801,11 @@ impl TaskServer { } } -#[tool(tool_box)] +#[tool_handler] impl ServerHandler for TaskServer { fn get_info(&self) -> ServerInfo { ServerInfo { - protocol_version: ProtocolVersion::V_2024_11_05, + protocol_version: ProtocolVersion::V_2025_03_26, capabilities: ServerCapabilities::builder() .enable_tools() .build(), @@ -814,7 +813,7 @@ impl ServerHandler for TaskServer { name: "vibe-kanban".to_string(), version: "1.0.0".to_string(), }, - instructions: Some("A task and project management server. If you need to create or update tickets or tasks then use these tools. Most of them absolutely require that you pass the `project_id` of the project that you are currently working on. This should be provided to you. TOOLS: 'list_projects', 'list_tasks', 'create_task', 'get_task', 'update_task', 'delete_task'. Make sure to pass `project_id` or `task_id` where required. You can use list tools to get the available ids.".to_string()), + instructions: Some("A task and project management server. If you need to create or update tickets or tasks then use these tools. Most of them absolutely require that you pass the `project_id` of the project that you are currently working on. This should be provided to you. Call `list_tasks` to fetch the `task_ids` of all the tasks in a project`. TOOLS: 'list_projects', 'list_tasks', 'create_task', 'get_task', 'update_task', 'delete_task'. Make sure to pass `project_id` or `task_id` where required. You can use list tools to get the available ids.".to_string()), } } }