feat(mcp): add mcp_tools allowlist config surfaces across roles, sessions, agents, graphs, and skills

This commit is contained in:
Dark-Alex-17 committed 2026-08-27 14:13:35 -06:00
1 parent 5711432ac4
commit a92ebb5b94
9 files changed
+480

No files matched your search

+47
View File
@@ -37,6 +37,9 @@ pub struct Graph {
#[serde(default)]
pub mcp_servers: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub mcp_tools: Option<IndexMap<String, Vec<String>>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub skills_enabled: Option<bool>,
@@ -285,6 +288,9 @@ pub struct LlmNode {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub mcp_tools: Option<IndexMap<String, Vec<String>>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
@@ -530,6 +536,47 @@ nodes:
}
}
#[test]
fn deserializes_mcp_tools_at_graph_and_node_level() {
let yaml = r#"
name: g
mcp_servers: [github]
mcp_tools:
github:
- get_*
- list_*
start: l
nodes:
l:
id: l
type: llm
prompt: hi
mcp_tools:
github:
- search_code
next: e
e:
id: e
type: end
output: done
"#;
let graph: Graph = serde_yaml::from_str(yaml).unwrap();
assert_eq!(
graph.mcp_tools.as_ref().unwrap().get("github"),
Some(&vec!["get_*".to_string(), "list_*".to_string()])
);
match &graph.get_node("l").unwrap().node_type {
NodeType::Llm(llm) => {
assert_eq!(
llm.mcp_tools.as_ref().unwrap().get("github"),
Some(&vec!["search_code".to_string()])
);
}
_ => panic!("expected Llm variant"),
}
}
#[test]
fn deserializes_every_node_type() {
let yaml = r#"