Files
yvgude--lean-ctx/rust/tests/plugin_tools_e2e.rs
T
wehub-resource-sync 26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

55 lines
2.2 KiB
Rust

//! End-to-end proof for manifest-declared tools (EPIC 12.11): a plugin that
//! ships a `[[tools]]` entry is discovered, registered as a native MCP tool
//! **without forking** `build_registry()`, and invocable as a sandboxed
//! subprocess. Own integration-test binary so the global plugin registry
//! (`OnceLock`) is fresh. Unix-only: the tool is the `cat` echo binary.
#![cfg(unix)]
use std::fs;
use lean_ctx::core::plugins::PluginManager;
use lean_ctx::core::plugins::tools::invoke;
use lean_ctx::server::registry::build_registry;
#[test]
fn manifest_tool_is_discovered_registered_and_invocable() {
let root = tempfile::tempdir().expect("tempdir");
let plugin_dir = root.path().join("weather-plugin");
fs::create_dir_all(&plugin_dir).expect("plugin dir");
// `cat` echoes the JSON args we pass on stdin straight back as the result —
// a real subprocess round-trip with no mock layer.
fs::write(
plugin_dir.join("plugin.toml"),
"[plugin]\nname = \"weather-plugin\"\nversion = \"1.0.0\"\n\n\
[[tools]]\nname = \"weather_lookup\"\n\
description = \"Look up the weather\"\ncommand = \"cat\"\ntimeout_ms = 5000\n\
input_schema = { type = \"object\", properties = { city = { type = \"string\" } } }\n",
)
.expect("manifest");
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::set_var("LEAN_CTX_PLUGINS_DIR", root.path()) };
PluginManager::init();
// 1) Discovered from the manifest (no fork).
let specs = PluginManager::tool_specs();
let spec = specs
.iter()
.find(|s| s.name == "weather_lookup")
.expect("manifest tool should be discovered");
assert_eq!(spec.plugin_name, "weather-plugin");
// 2) Appears in the native tool surface (gateway / list_tools).
let registry = build_registry();
assert!(
registry.contains("weather_lookup"),
"manifest tool must register as a native MCP tool without a code edit"
);
// 3) Runs sandboxed: the subprocess echoes our arguments back.
let out = invoke(spec, "{\"city\":\"Bern\"}").expect("tool invocation");
assert!(out.contains("Bern"), "tool output should echo args: {out}");
}