Skip to main content

cpex_core/extensions/
mcp.rs

1// Location: ./crates/cpex-core/src/extensions/mcp.rs
2// Copyright 2025
3// SPDX-License-Identifier: Apache-2.0
4// Authors: Teryl Taylor
5//
6// MCPExtension — tool, resource, or prompt metadata.
7// Mirrors cpex/framework/extensions/mcp.py.
8
9use std::collections::HashMap;
10
11use serde::{Deserialize, Serialize};
12
13/// MCP tool metadata.
14#[derive(Debug, Clone, Default, Serialize, Deserialize)]
15pub struct ToolMetadata {
16    /// Tool name.
17    pub name: String,
18
19    /// Human-readable title.
20    #[serde(default, skip_serializing_if = "Option::is_none")]
21    pub title: Option<String>,
22
23    /// Tool description.
24    #[serde(default, skip_serializing_if = "Option::is_none")]
25    pub description: Option<String>,
26
27    /// Input JSON schema.
28    #[serde(default, skip_serializing_if = "Option::is_none")]
29    pub input_schema: Option<serde_json::Value>,
30
31    /// Output JSON schema.
32    #[serde(default, skip_serializing_if = "Option::is_none")]
33    pub output_schema: Option<serde_json::Value>,
34
35    /// Source server ID.
36    #[serde(default, skip_serializing_if = "Option::is_none")]
37    pub server_id: Option<String>,
38
39    /// Tool namespace.
40    #[serde(default, skip_serializing_if = "Option::is_none")]
41    pub namespace: Option<String>,
42
43    /// Tool annotations.
44    #[serde(default)]
45    pub annotations: HashMap<String, serde_json::Value>,
46}
47
48/// MCP resource metadata.
49#[derive(Debug, Clone, Default, Serialize, Deserialize)]
50pub struct ResourceMetadata {
51    /// Resource URI.
52    pub uri: String,
53
54    /// Human-readable name.
55    #[serde(default, skip_serializing_if = "Option::is_none")]
56    pub name: Option<String>,
57
58    /// Resource description.
59    #[serde(default, skip_serializing_if = "Option::is_none")]
60    pub description: Option<String>,
61
62    /// MIME type.
63    #[serde(default, skip_serializing_if = "Option::is_none")]
64    pub mime_type: Option<String>,
65
66    /// Source server ID.
67    #[serde(default, skip_serializing_if = "Option::is_none")]
68    pub server_id: Option<String>,
69
70    /// Resource annotations.
71    #[serde(default)]
72    pub annotations: HashMap<String, serde_json::Value>,
73}
74
75/// MCP prompt metadata.
76#[derive(Debug, Clone, Default, Serialize, Deserialize)]
77pub struct PromptMetadata {
78    /// Prompt name.
79    pub name: String,
80
81    /// Prompt description.
82    #[serde(default, skip_serializing_if = "Option::is_none")]
83    pub description: Option<String>,
84
85    /// Prompt arguments schema.
86    #[serde(default, skip_serializing_if = "Option::is_none")]
87    pub arguments: Option<Vec<serde_json::Value>>,
88
89    /// Source server ID.
90    #[serde(default, skip_serializing_if = "Option::is_none")]
91    pub server_id: Option<String>,
92
93    /// Prompt annotations.
94    #[serde(default)]
95    pub annotations: HashMap<String, serde_json::Value>,
96}
97
98/// MCP-specific metadata extension.
99///
100/// Carries tool, resource, or prompt metadata for the entity
101/// being processed. Immutable — set by the host.
102#[derive(Debug, Clone, Default, Serialize, Deserialize)]
103pub struct MCPExtension {
104    /// Tool metadata (if this message involves a tool).
105    #[serde(default, skip_serializing_if = "Option::is_none")]
106    pub tool: Option<ToolMetadata>,
107
108    /// Resource metadata (if this message involves a resource).
109    #[serde(default, skip_serializing_if = "Option::is_none")]
110    pub resource: Option<ResourceMetadata>,
111
112    /// Prompt metadata (if this message involves a prompt).
113    #[serde(default, skip_serializing_if = "Option::is_none")]
114    pub prompt: Option<PromptMetadata>,
115}