tsafe-mcp 0.1.0

First-party MCP server for tsafe — exposes action-shaped tools to MCP-aware hosts over stdio JSON-RPC.
Documentation
//! `tools/list` returns exactly the 6 default tools and excludes `tsafe_reveal`
//! when `--allow-reveal` is not set.

use super::common::{make_vault, spawn_serve};

#[test]
fn default_surface_lists_six_tools_without_reveal() {
    let (tmp, vault_dir) = make_vault("demo", "test-password", &[("demo/a", "1"), ("demo/b", "2")]);

    let mut harness = spawn_serve(
        &vault_dir,
        &["--profile", "demo", "--allowed-keys", "demo/*"],
    );

    // Perform the MCP initialization handshake.
    let init = harness.handshake();
    assert_eq!(init["result"]["protocolVersion"], "2025-06-18");

    harness.send(r#"{"jsonrpc":"2.0","id":2,"method":"tools/list"}"#);
    let list = harness.recv();
    assert_eq!(list["id"], 2);
    let tools = list["result"]["tools"].as_array().expect("tools array");
    assert_eq!(
        tools.len(),
        6,
        "expected exactly 6 default tools, got: {tools:?}"
    );

    let names: Vec<&str> = tools.iter().map(|t| t["name"].as_str().unwrap()).collect();
    for expected in [
        "tsafe_run",
        "tsafe_list_keys",
        "tsafe_search_keys",
        "tsafe_has_key",
        "tsafe_audit_tail",
        "tsafe_status",
    ] {
        assert!(names.contains(&expected), "missing tool {expected}");
    }
    assert!(
        !names.contains(&"tsafe_reveal"),
        "tsafe_reveal must be absent without --allow-reveal"
    );

    let _ = harness.shutdown_and_collect();
    drop(tmp);
}