File size: 2,976 Bytes
afa0cbf | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | use serde::Deserialize;
use std::collections::BTreeMap;
/// Additional managed MCP restrictions supplied by an environment owner.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct EnvironmentMcpPolicy {
pub servers: Option<BTreeMap<String, McpServerRequirement>>,
pub plugins: Option<BTreeMap<String, PluginMcpRequirements>>,
}
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(untagged)]
pub enum McpServerIdentity {
Command { command: String },
Url { url: String },
}
/// String matching operations available to managed MCP server matchers.
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(tag = "match", rename_all = "snake_case", deny_unknown_fields)]
pub enum McpServerValueMatcher {
Exact { value: String },
Prefix { value: String },
Regex { expression: String },
}
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct McpServerCommandMatcher {
pub executable: String,
pub args: Vec<McpServerValueMatcher>,
}
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
struct RawMcpServerCommandIdentity {
command: McpServerCommandMatcher,
}
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
struct RawMcpServerUrlIdentity {
url: McpServerValueMatcher,
}
/// A requirement for one named MCP server.
///
/// The `Identity` variant preserves the released exact-match contract. The
/// command and URL variants are the normalized matcher-based forms accepted
/// under the `identity` key.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum McpServerRequirement {
Identity { identity: McpServerIdentity },
Command(McpServerCommandMatcher),
Url(McpServerValueMatcher),
}
#[derive(Deserialize)]
struct RawMcpServerRequirement {
identity: RawMcpServerIdentity,
}
#[derive(Deserialize)]
#[serde(untagged)]
enum RawMcpServerIdentity {
Exact(McpServerIdentity),
Command(RawMcpServerCommandIdentity),
Url(RawMcpServerUrlIdentity),
}
impl<'de> Deserialize<'de> for McpServerRequirement {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let RawMcpServerRequirement { identity } =
RawMcpServerRequirement::deserialize(deserializer)?;
match identity {
RawMcpServerIdentity::Exact(identity) => Ok(Self::Identity { identity }),
RawMcpServerIdentity::Command(matcher) => Ok(Self::Command(matcher.command)),
RawMcpServerIdentity::Url(matcher) => Ok(Self::Url(matcher.url)),
}
}
}
/// Managed MCP server requirements for one plugin.
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
pub struct PluginMcpRequirements {
pub mcp_servers: Option<BTreeMap<String, McpServerRequirement>>,
}
impl PluginMcpRequirements {
pub fn is_empty(&self) -> bool {
self.mcp_servers.as_ref().is_none_or(BTreeMap::is_empty)
}
}
|