fix(mcp): exclude debug tools from release builds
This commit is contained in:
parent
c66e4d9a1e
commit
93ac65ab43
|
|
@ -13,6 +13,10 @@ description = "OpenPencil desktop host — winit + skia-safe binary that drives
|
|||
name = "openpencil-desktop"
|
||||
path = "src/main.rs"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
mcp-debug-tools = ["op-mcp/debug-tools"]
|
||||
|
||||
# File-association metadata for `cargo-bundle` (`cargo bundle`). This
|
||||
# declares OpenPencil as the OS-level handler for `.op` / `.pen`
|
||||
# documents: macOS writes `CFBundleDocumentTypes` into the `.app`
|
||||
|
|
|
|||
|
|
@ -21,22 +21,21 @@ use op_mcp::{
|
|||
codegen_clean_snapshot, codegen_plan_snapshot, codegen_submit_chunk_snapshot,
|
||||
copy_node_snapshot, copy_selected_snapshot, count_nodes_snapshot, create_component_snapshot,
|
||||
create_variable_snapshot, cut_selected_snapshot, cycle_active_axis_value_snapshot,
|
||||
debug_logs_tail_snapshot, debug_screenshot_snapshot, debug_tools_enabled,
|
||||
debug_validation_report_snapshot, delete_component_snapshot, delete_node_snapshot,
|
||||
delete_page_snapshot, delete_selected_snapshot, delete_variable_snapshot,
|
||||
design_content_snapshot, design_refine_snapshot, design_skeleton_snapshot,
|
||||
document_info_snapshot, duplicate_page_snapshot, duplicate_selected_snapshot,
|
||||
export_design_md_snapshot, find_empty_space_snapshot, find_node_by_name_snapshot,
|
||||
get_active_theme_snapshot, get_canvas_bounds_snapshot, get_component_snapshot,
|
||||
get_design_md_snapshot, get_design_prompt_snapshot, get_history_depth_snapshot,
|
||||
get_node_children_snapshot, get_node_parent_snapshot, get_node_snapshot,
|
||||
get_selection_set_snapshot, get_style_guide_snapshot, get_style_guide_tags_snapshot,
|
||||
get_variables_snapshot, get_viewport_snapshot, group_selected_snapshot, import_svg_snapshot,
|
||||
insert_node_snapshot, instantiate_component_snapshot, list_components_snapshot,
|
||||
list_node_kinds_snapshot, list_pages_snapshot, list_theme_presets_snapshot,
|
||||
list_variables_snapshot, load_theme_preset_snapshot, move_node_snapshot,
|
||||
nudge_selected_snapshot, open_document_snapshot, paste_clipboard_snapshot, read_nodes_snapshot,
|
||||
redo_snapshot, remove_node_effect_snapshot, remove_page_snapshot, rename_component_snapshot,
|
||||
debug_tools_enabled, delete_component_snapshot, delete_node_snapshot, delete_page_snapshot,
|
||||
delete_selected_snapshot, delete_variable_snapshot, design_content_snapshot,
|
||||
design_refine_snapshot, design_skeleton_snapshot, document_info_snapshot,
|
||||
duplicate_page_snapshot, duplicate_selected_snapshot, export_design_md_snapshot,
|
||||
find_empty_space_snapshot, find_node_by_name_snapshot, get_active_theme_snapshot,
|
||||
get_canvas_bounds_snapshot, get_component_snapshot, get_design_md_snapshot,
|
||||
get_design_prompt_snapshot, get_history_depth_snapshot, get_node_children_snapshot,
|
||||
get_node_parent_snapshot, get_node_snapshot, get_selection_set_snapshot,
|
||||
get_style_guide_snapshot, get_style_guide_tags_snapshot, get_variables_snapshot,
|
||||
get_viewport_snapshot, group_selected_snapshot, import_svg_snapshot, insert_node_snapshot,
|
||||
instantiate_component_snapshot, list_components_snapshot, list_node_kinds_snapshot,
|
||||
list_pages_snapshot, list_theme_presets_snapshot, list_variables_snapshot,
|
||||
load_theme_preset_snapshot, move_node_snapshot, nudge_selected_snapshot,
|
||||
open_document_snapshot, paste_clipboard_snapshot, read_nodes_snapshot, redo_snapshot,
|
||||
remove_node_effect_snapshot, remove_page_snapshot, rename_component_snapshot,
|
||||
rename_page_snapshot, rename_variable_snapshot, reorder_page_snapshot,
|
||||
reorder_selected_snapshot, replace_all_matching_properties_snapshot, replace_node_snapshot,
|
||||
run_stdio_with_applier, save_document_snapshot, save_theme_preset_snapshot,
|
||||
|
|
@ -53,6 +52,10 @@ use op_mcp::{
|
|||
toggle_node_selection_snapshot, undo_snapshot, ungroup_selected_snapshot, update_node_snapshot,
|
||||
McpTool, ToolRegistry,
|
||||
};
|
||||
#[cfg(feature = "mcp-debug-tools")]
|
||||
use op_mcp::{
|
||||
debug_logs_tail_snapshot, debug_screenshot_snapshot, debug_validation_report_snapshot,
|
||||
};
|
||||
|
||||
pub(crate) mod file_path;
|
||||
|
||||
|
|
@ -512,6 +515,7 @@ fn rebuild_registry(doc: &EditorState, requested_tool: Option<&str>) -> ToolRegi
|
|||
register_tool!("get_history_depth", get_history_depth_snapshot(doc));
|
||||
register_tool!("get_viewport", get_viewport_snapshot(doc));
|
||||
register_tool!("get_selection_set", get_selection_set_snapshot(doc));
|
||||
#[cfg(feature = "mcp-debug-tools")]
|
||||
if debug_tools_enabled() {
|
||||
register_tool!(
|
||||
"debug_validation_report",
|
||||
|
|
@ -775,6 +779,9 @@ pub(crate) use doc_sync::*;
|
|||
fn tools_list_response(id_raw: &str, state: &EditorState, debug_enabled: bool) -> String {
|
||||
let mut entries: Vec<String> = TOOL_SCHEMAS.iter().map(|s| (*s).to_string()).collect();
|
||||
entries.extend(op_mcp::element_tools::element_tool_schemas(state));
|
||||
#[cfg(not(feature = "mcp-debug-tools"))]
|
||||
let _ = debug_enabled;
|
||||
#[cfg(feature = "mcp-debug-tools")]
|
||||
if debug_enabled {
|
||||
entries.extend(DEBUG_TOOL_SCHEMAS.iter().map(|s| (*s).to_string()));
|
||||
}
|
||||
|
|
@ -785,6 +792,9 @@ fn tools_list_response(id_raw: &str, state: &EditorState, debug_enabled: bool) -
|
|||
}
|
||||
|
||||
mod schemas;
|
||||
#[cfg(not(feature = "mcp-debug-tools"))]
|
||||
pub(crate) use schemas::TOOL_SCHEMAS;
|
||||
#[cfg(feature = "mcp-debug-tools")]
|
||||
pub(crate) use schemas::{DEBUG_TOOL_SCHEMAS, TOOL_SCHEMAS};
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ pub(crate) const TOOL_SCHEMAS: &[&str] = &[
|
|||
r#"{"name":"replace_node","description":"Swap an existing node at the same parent slot with a freshly-built leaf. Accepts Rust flat fields or TS-style nodeId + data object. Set drop_children=true to discard a container's subtree.","inputSchema":{"type":"object","properties":{"filePath":{"type":"string","description":"Optional target .op file path; omit to use the server document"},"node_id":{"type":"string"},"nodeId":{"type":"string"},"kind":{"type":"string","enum":["frame","group","rect","ellipse","polygon","line","text","path"]},"name":{"type":"string"},"x":{"type":"string"},"y":{"type":"string"},"width":{"type":"string"},"height":{"type":"string"},"fill_hex":{"type":"string"},"data":{"type":"object","description":"TS-style PenNode data; rich fields are preserved as a subtree"},"postProcess":{"type":"boolean","description":"Accepted for TS compatibility; Rust replace path ignores post-processing"},"canvasWidth":{"type":"number","description":"Accepted for TS compatibility; Rust replace path ignores post-processing width"},"drop_children":{"type":"string","enum":["true","false"]},"dropChildren":{"type":"string","enum":["true","false"]},"pageId":{"type":"string","description":"optional target page id or legacy page index; omitted = active page"}}}}"#,
|
||||
];
|
||||
|
||||
#[cfg(feature = "mcp-debug-tools")]
|
||||
pub(crate) const DEBUG_TOOL_SCHEMAS: &[&str] = &[
|
||||
r#"{"name":"debug_validation_report","description":"Run the op-design-lint detectors over the active page and return the design-issue list. Read-only, no parameters. Result: count + categories (`;`-separated `category|count`) + issues (JSON-serialized Issue array). Gated behind the OPENPENCIL_DEBUG_TOOLS=1 env flag.","inputSchema":{"type":"object","properties":{},"additionalProperties":false}}"#,
|
||||
r#"{"name":"debug_logs_tail","description":"Read the tail of ~/.openpencil/logs/server-YYYY-MM-DD.log with API keys and Authorization headers redacted. Gated behind OPENPENCIL_DEBUG_TOOLS=1.","inputSchema":{"type":"object","properties":{"tailLines":{"type":"number","description":"Maximum lines to return (default 100, max 500)."},"sinceMs":{"type":"number","description":"Unix ms timestamp; only return lines newer than this."},"grep":{"type":"string","description":"Regex to filter lines by content after redaction."}}}}"#,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,20 @@ fn tools_list_response_includes_all_registered_tools() {
|
|||
!r.contains("debug_validation_report"),
|
||||
"production tools/list must not advertise the debug tool: {r}"
|
||||
);
|
||||
#[cfg(not(feature = "mcp-debug-tools"))]
|
||||
{
|
||||
let r_forced_debug = tools_list_response("3", &state, true);
|
||||
for name in [
|
||||
"debug_validation_report",
|
||||
"debug_logs_tail",
|
||||
"debug_screenshot",
|
||||
] {
|
||||
assert!(
|
||||
!r_forced_debug.contains(name),
|
||||
"formal release catalog must exclude {name} even if debug listing is requested: {r_forced_debug}"
|
||||
);
|
||||
}
|
||||
}
|
||||
// UIKit element tools are appended dynamically — one per
|
||||
// built-in starter-kit component (6) — and ride alongside
|
||||
// the static schemas in the tools/list response.
|
||||
|
|
@ -172,8 +186,10 @@ fn tools_list_response_includes_all_registered_tools() {
|
|||
assert!(r.contains(name), "tools/list must include {name}: {r}");
|
||||
}
|
||||
|
||||
// Gate open (debug_enabled = true) — the debug tools join the catalog.
|
||||
// Gate open (debug_enabled = true) — internal debug builds can opt in
|
||||
// to the debug tools catalog.
|
||||
let r_debug = tools_list_response("3", &state, true);
|
||||
#[cfg(feature = "mcp-debug-tools")]
|
||||
for name in [
|
||||
"debug_validation_report",
|
||||
"debug_logs_tail",
|
||||
|
|
@ -184,6 +200,11 @@ fn tools_list_response_includes_all_registered_tools() {
|
|||
"debug tools/list must advertise {name}: {r_debug}"
|
||||
);
|
||||
}
|
||||
#[cfg(not(feature = "mcp-debug-tools"))]
|
||||
assert!(
|
||||
!r_debug.contains("debug_validation_report"),
|
||||
"default release feature set must not include debug tools: {r_debug}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -10,10 +10,14 @@ description = "OpenPencil MCP server — JSON-RPC tool registry over op-editor-c
|
|||
name = "op_mcp"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
debug-tools = ["dep:op-design-lint"]
|
||||
|
||||
[dependencies]
|
||||
jian-ops-schema = { path = "../../vendor/jian/crates/jian-ops-schema" }
|
||||
op-ai-skills = { path = "../op-ai-skills" }
|
||||
op-design-lint = { path = "../op-design-lint" }
|
||||
op-design-lint = { path = "../op-design-lint", optional = true }
|
||||
op-editor-core = { path = "../op-editor-core" }
|
||||
op-editor-ui = { path = "../op-editor-ui" }
|
||||
op-pen-loader = { path = "../op-pen-loader" }
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ pub mod component_tools;
|
|||
mod component_tools_tests;
|
||||
#[cfg(test)]
|
||||
mod copy_node_tests;
|
||||
#[cfg(feature = "debug-tools")]
|
||||
pub mod debug_tools;
|
||||
pub mod design_md_tools;
|
||||
#[cfg(test)]
|
||||
|
|
@ -180,10 +181,15 @@ pub use component_tools::{
|
|||
rename_component_snapshot, set_node_collapsed_snapshot, CreateComponent, DeleteComponent,
|
||||
InstantiateComponent, RenameComponent, SetNodeCollapsed,
|
||||
};
|
||||
#[cfg(feature = "debug-tools")]
|
||||
pub use debug_tools::{
|
||||
debug_logs_tail_snapshot, debug_screenshot_snapshot, debug_tools_enabled,
|
||||
debug_validation_report_snapshot, DebugLogsTail, DebugScreenshot, DebugValidationReport,
|
||||
};
|
||||
#[cfg(not(feature = "debug-tools"))]
|
||||
pub fn debug_tools_enabled() -> bool {
|
||||
false
|
||||
}
|
||||
pub use design_md_tools::{
|
||||
export_design_md_snapshot, get_design_md_snapshot, set_design_md_snapshot, ExportDesignMd,
|
||||
GetDesignMd, SetDesignMd,
|
||||
|
|
|
|||
Loading…
Reference in a new issue