Skip to main content

rustapi_mcp/
types.rs

1//! Core MCP data types (tool definitions, requests, responses, capabilities).
2//!
3//! These types are intentionally high-level for the foundation phase.
4//! They will be expanded with full JSON-RPC message shapes when we implement transports.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9/// A capability that this MCP server advertises during `initialize`.
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
11#[serde(rename_all = "camelCase")]
12pub enum McpCapability {
13    /// The server can list and invoke tools.
14    Tools,
15    /// Future: resources, prompts, sampling, etc.
16    #[serde(other)]
17    Other,
18}
19
20/// A tool description that will be sent to MCP clients in `tools/list`.
21#[derive(Debug, Clone, Serialize, Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub struct McpTool {
24    /// Stable name of the tool (usually derived from path + method or a slug).
25    pub name: String,
26
27    /// Human readable description (comes from OpenAPI `summary` / `description` when available).
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub description: Option<String>,
30
31    /// JSON Schema for the input parameters (reused from `rustapi-openapi` / `Schema` derive).
32    pub input_schema: serde_json::Value,
33
34    /// Optional JSON Schema for the output (when we have good response schemas).
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub output_schema: Option<serde_json::Value>,
37
38    /// Tags associated with this tool (used for filtering via `McpConfig`).
39    #[serde(default, skip_serializing_if = "Vec::is_empty")]
40    pub tags: Vec<String>,
41}
42
43/// Request from an MCP client to call a tool.
44#[derive(Debug, Clone, Deserialize)]
45#[serde(rename_all = "camelCase")]
46pub struct ToolCallRequest {
47    /// Name of the tool to invoke.
48    pub name: String,
49    /// Arguments passed to the tool (will be turned into extractors later).
50    #[serde(default)]
51    pub arguments: HashMap<String, serde_json::Value>,
52}
53
54/// Successful result of a tool call.
55#[derive(Debug, Clone, Serialize)]
56#[serde(rename_all = "camelCase")]
57pub struct ToolCallResponse {
58    /// The actual content returned by the underlying handler (serialized appropriately).
59    pub content: serde_json::Value,
60
61    /// Whether this result should be treated as an error by the agent (even if HTTP 2xx).
62    #[serde(default)]
63    pub is_error: bool,
64
65    /// Optional metadata (token counts when using TOON, execution path, etc.).
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub meta: Option<serde_json::Value>,
68}
69
70impl ToolCallResponse {
71    /// Construct a successful tool response.
72    pub fn success(content: impl Serialize) -> Self {
73        Self {
74            content: serde_json::to_value(content).unwrap_or(serde_json::json!({})),
75            is_error: false,
76            meta: None,
77        }
78    }
79
80    /// Construct an error tool response (from the agent's perspective).
81    pub fn error(message: impl Into<String>) -> Self {
82        Self {
83            content: serde_json::json!({ "error": message.into() }),
84            is_error: true,
85            meta: None,
86        }
87    }
88}