agpm_cli/mcp/
models.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::collections::HashMap;
4
5/// Settings structure for `.claude/settings.local.json`.
6/// This represents the complete settings file that may contain various configurations.
7#[derive(Debug, Default, Serialize, Deserialize)]
8pub struct ClaudeSettings {
9    /// Map of server names to their configurations
10    #[serde(rename = "mcpServers", skip_serializing_if = "Option::is_none")]
11    pub mcp_servers: Option<HashMap<String, McpServerConfig>>,
12
13    /// Hook configurations for event-based automation
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub hooks: Option<Value>,
16
17    /// Permissions configuration
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub permissions: Option<Value>,
20
21    /// Other settings preserved from the original file
22    #[serde(flatten)]
23    pub other: HashMap<String, Value>,
24}
25
26/// The main MCP configuration file structure for `.mcp.json`.
27///
28/// This represents the complete MCP configuration file that Claude Code reads
29/// to connect to MCP servers. The file may contain both AGPM-managed and
30/// user-managed server configurations.
31#[derive(Debug, Default, Serialize, Deserialize)]
32pub struct McpConfig {
33    /// Map of server names to their configurations
34    #[serde(rename = "mcpServers")]
35    pub mcp_servers: HashMap<String, McpServerConfig>,
36}
37
38/// Individual MCP server configuration.
39///
40/// This structure represents a single MCP server entry in the `.mcp.json` file.
41/// It supports both command-based and HTTP transport configurations.
42#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
43pub struct McpServerConfig {
44    /// The command to execute to start the server (command-based servers)
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub command: Option<String>,
47
48    /// Arguments to pass to the command (command-based servers)
49    #[serde(default, skip_serializing_if = "Vec::is_empty")]
50    pub args: Vec<String>,
51
52    /// Environment variables to set when running the server (command-based servers)
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub env: Option<HashMap<String, Value>>,
55
56    /// Transport type (HTTP-based servers) - Claude Code uses "type" field
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub r#type: Option<String>,
59
60    /// Server URL (HTTP-based servers)
61    #[serde(skip_serializing_if = "Option::is_none")]
62    pub url: Option<String>,
63
64    /// HTTP headers (HTTP-based servers)
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub headers: Option<HashMap<String, Value>>,
67
68    /// AGPM management metadata (only present for AGPM-managed servers)
69    #[serde(rename = "_agpm", skip_serializing_if = "Option::is_none")]
70    pub agpm_metadata: Option<AgpmMetadata>,
71}
72
73/// AGPM management metadata for tracking managed servers.
74///
75/// This metadata is added to server configurations that are managed by AGPM,
76/// allowing us to distinguish between AGPM-managed and user-managed servers.
77#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
78pub struct AgpmMetadata {
79    /// Indicates this server is managed by AGPM
80    pub managed: bool,
81
82    /// Source repository
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub source: Option<String>,
85
86    /// Version or git reference
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub version: Option<String>,
89
90    /// Timestamp when the server was installed/updated
91    pub installed_at: String,
92
93    /// Original manifest dependency name
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub dependency_name: Option<String>,
96}