✨ feat(kebab-mcp): doctor tool (fb-30)

Second tool — `doctor` (no input args, returns doctor.v1 JSON via
kebab_app::doctor_with_config_path). Mirrors schema tool's manual-dispatch
pattern: Tool::new entry in list_tools, match arm in call_tool, per-tool
module in tools/doctor.rs.

doctor_with_config_path takes Option<&Path> (not &Config), so KebabAppState
is extended with config_path: Option<PathBuf>. All existing callers
(initialize.rs, tools_call_schema.rs, serve_stdio_async) pass None for now;
Plan Task 10 (Cmd::Mcp wiring) will thread the actual --config path through.
doctor_with_config falls back to XDG default when config_path is None —
same behavior as bare `kebab doctor`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
th-kim0823
2026-05-07 15:41:13 +09:00
parent 8ca8e18d12
commit 360fa53b02
7 changed files with 107 additions and 10 deletions

View File

@@ -0,0 +1,28 @@
//! `doctor` tool — wraps `kebab_app::doctor_with_config_path`.
//! Input: {} (no args). Output: doctor.v1 JSON.
//!
//! `doctor_with_config_path(Option<&Path>)` re-reads config from disk so
//! the report reflects the live file state. We forward `config_path` from
//! `KebabAppState` so `--config <path>` users see results for their file;
//! callers that pass `None` fall back to the XDG default (same as the CLI
//! bare `kebab doctor`).
use rmcp::model::CallToolResult;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::error::{to_tool_error, to_tool_success};
use crate::state::KebabAppState;
#[derive(Debug, Default, Deserialize, Serialize, JsonSchema)]
pub struct DoctorInput {}
pub fn handle(state: &KebabAppState, _input: DoctorInput) -> CallToolResult {
match kebab_app::doctor_with_config_path(state.config_path.as_deref()) {
Ok(report) => match serde_json::to_string(&report) {
Ok(json) => to_tool_success(json),
Err(e) => to_tool_error(&anyhow::anyhow!(e)),
},
Err(e) => to_tool_error(&e),
}
}

View File

@@ -1,6 +1,6 @@
//! Tool implementations — one module per tool.
pub mod schema;
// pub mod doctor; // wired in Plan Task 5
pub mod doctor;
// pub mod search; // wired in Plan Task 6
// pub mod ask; // wired in Plan Task 7