feat(mcp): gate meta-function emission on advertised server capabilities
Per-server McpServerFeatures (tools fail-open, resources/prompts fail-closed) now drive which meta-functions are declared, with gated_meta_function_prefixes as the single gating seam; read/prompt declarations land together with their handlers. The server-enablement sentinel keys on the always-emitted search name so resources-only servers survive role filtering. Implements plans/mcp-resources-prompts-design.md §4.4/D7 (T5).
This commit is contained in:
@@ -630,14 +630,14 @@ async fn populate_agent_mcp_runtime(ctx: &mut RequestContext, server_ids: &[Stri
|
||||
}
|
||||
|
||||
fn sync_agent_functions_to_ctx(ctx: &mut RequestContext) -> Result<()> {
|
||||
let server_names = ctx.tool_scope.mcp_runtime.server_names();
|
||||
let server_features = ctx.tool_scope.mcp_runtime.server_features();
|
||||
let functions = {
|
||||
let agent = ctx
|
||||
.agent
|
||||
.as_mut()
|
||||
.with_context(|| "Agent should be initialized")?;
|
||||
if !server_names.is_empty() {
|
||||
agent.append_mcp_meta_functions(server_names);
|
||||
if !server_features.is_empty() {
|
||||
agent.append_mcp_meta_functions(server_features);
|
||||
}
|
||||
agent.functions().clone()
|
||||
};
|
||||
@@ -1453,7 +1453,8 @@ async fn summarize_output(ctx: &RequestContext, agent_name: &str, output: &str)
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::config::{AppState, WorkingMode};
|
||||
use crate::config::test_fixtures::{FixtureServer, fixture_runtime};
|
||||
use crate::config::{AgentConfig, AppState, WorkingMode};
|
||||
use crate::supervisor::escalation::{EscalationQueue, EscalationRequest};
|
||||
use serde_json::json;
|
||||
use serial_test::serial;
|
||||
@@ -1510,6 +1511,27 @@ mod tests {
|
||||
.block_on(f)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn sync_agent_functions_gates_meta_functions_on_live_capabilities() {
|
||||
let mut ctx = RequestContext::new(default_app_state(), WorkingMode::Cmd);
|
||||
ctx.agent = Some(Agent::test_new(AgentConfig::default()));
|
||||
let (runtime, _server) = fixture_runtime(FixtureServer {
|
||||
tools_capability: false,
|
||||
resources_capability: true,
|
||||
..FixtureServer::default()
|
||||
})
|
||||
.await;
|
||||
ctx.tool_scope.mcp_runtime = runtime;
|
||||
|
||||
sync_agent_functions_to_ctx(&mut ctx).unwrap();
|
||||
|
||||
let functions = &ctx.tool_scope.functions;
|
||||
assert_eq!(functions.declarations().len(), 2);
|
||||
assert!(functions.contains("mcp_search_fixture"));
|
||||
assert!(functions.contains("mcp_describe_fixture"));
|
||||
assert!(!functions.contains("mcp_invoke_fixture"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handle_list_running_empty_supervisor() {
|
||||
let mut ctx = ctx_with_supervisor(4, 3);
|
||||
|
||||
Reference in New Issue
Block a user