tokensave 7.16.0

Code intelligence tool that builds a semantic knowledge graph from Rust, Go, Java, Scala, TypeScript, Python, C, C++, Kotlin, C#, Swift, and many more codebases
//! MCP tool definitions and dispatch for the code graph.
//!
//! Split into two sub-modules:
//! - `definitions`: JSON Schema tool descriptors (`def_*` functions)
//! - `handlers`: tool call implementations (`handle_*` functions)

mod accounting;
mod definitions;
mod handlers;

use std::sync::atomic::{AtomicBool, Ordering};

use serde::{Deserialize, Serialize};
use serde_json::Value;

pub use accounting::{
    baseline_policy, cap_baseline, request_overhead_tokens, schema_overhead_tokens,
    settle_session_debt, BaselinePolicy,
};
pub(crate) use definitions::is_always_load;
pub use definitions::{
    ast_grep_available, core_toolset_instructions, get_always_load_tool_definitions,
    get_installable_tool_definitions, get_listed_tool_definitions, get_tool_definitions,
    is_graph_scoped_tool, is_hidden_tool, is_read_only_tool, is_selectorless_local_graph_tool,
    is_tool_area, reachable_tool_name, tool_area, CONTEXT_DESCRIPTION, CORE_TOOLS,
    GRAPH_SELECTOR_INSTRUCTIONS, MORE_TOOL, RENAME_DESCRIPTION, TOOL_AREAS,
};
pub use handlers::{handle_tool_call, handle_tool_call_with_session, SessionState};

/// Maximum character length for a tool response before truncation.
const MAX_RESPONSE_CHARS: usize = 15_000;

/// Set once by `tokensave tool` so the CLI prints whole results (#673).
static RESPONSE_LIMIT_DISABLED: AtomicBool = AtomicBool::new(false);

/// Lifts the tool response size cap for the rest of this process.
///
/// The cap exists to protect an agent's context window. `tokensave tool` on
/// the CLI is read by a script or a person, so it calls this before
/// dispatching; the MCP server never does.
pub fn disable_response_limit() {
    RESPONSE_LIMIT_DISABLED.store(true, Ordering::Relaxed);
}

/// The response size cap in effect: [`MAX_RESPONSE_CHARS`], or unlimited
/// after [`disable_response_limit`].
fn response_limit() -> usize {
    if RESPONSE_LIMIT_DISABLED.load(Ordering::Relaxed) {
        usize::MAX
    } else {
        MAX_RESPONSE_CHARS
    }
}

/// A tool definition exposed by the MCP server.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolDefinition {
    /// Unique tool name.
    pub name: String,
    /// Human-readable description of what the tool does.
    pub description: String,
    /// JSON Schema describing the tool's input parameters.
    #[serde(rename = "inputSchema")]
    pub input_schema: Value,
    /// MCP tool annotations (readOnlyHint, title, etc.).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub annotations: Option<Value>,
    /// MCP tool metadata (e.g. anthropic/alwaysLoad).
    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
    pub meta: Option<Value>,
}

/// The result of a tool call, including the JSON response and the file
/// paths that were touched (used to track saved tokens).
pub struct ToolResult {
    /// The JSON-RPC result payload.
    pub value: Value,
    /// Unique file paths referenced in the result.
    pub touched_files: Vec<String>,
}