use elicitation::elicit_tool;
use rmcp::ErrorData;
use rmcp::model::{CallToolResult, Content};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use tracing::instrument;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type")]
pub enum InputActionJson {
KeyPressed {
key: String,
},
KeyReleased {
key: String,
},
KeyDown {
key: String,
},
Modifiers,
PointerPos,
PointerButtonPressed {
button: String,
},
PointerButtonReleased {
button: String,
},
PointerDelta,
ScrollDelta,
ClipboardGet,
ClipboardSet {
text: String,
},
RequestFocus {
widget_id: String,
},
SurrenderFocus {
widget_id: String,
},
HasFocus {
widget_id: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct ModifiersJson {
pub ctrl: bool,
pub shift: bool,
pub alt: bool,
pub command: bool,
}
fn input_result(action: &InputActionJson) -> CallToolResult {
match serde_json::to_string(action) {
Ok(s) => CallToolResult::success(vec![Content::text(s)]),
Err(e) => CallToolResult::error(vec![Content::text(format!("serialize error: {e}"))]),
}
}
#[derive(Debug, Clone, Deserialize, JsonSchema)]
pub struct EmptyInputParams {}
#[derive(Debug, Clone, Deserialize, JsonSchema)]
pub struct KeyParams {
pub key: String,
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_key_pressed",
description = "Check if a key is pressed this frame. Returns InputActionJson::KeyPressed.",
emit = Auto
)]
#[instrument(skip_all)]
async fn egui_key_pressed(p: KeyParams) -> Result<CallToolResult, ErrorData> {
let a = InputActionJson::KeyPressed { key: p.key };
Ok(input_result(&a))
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_key_released",
description = "Check if a key was released this frame. Returns InputActionJson::KeyReleased.",
emit = Auto,
emit = None
)]
#[instrument(skip_all)]
async fn egui_key_released(p: KeyParams) -> Result<CallToolResult, ErrorData> {
let a = InputActionJson::KeyReleased { key: p.key };
Ok(input_result(&a))
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_key_down",
description = "Check if a key is currently held down. Returns InputActionJson::KeyDown.",
emit = Auto,
emit = None
)]
#[instrument(skip_all)]
async fn egui_key_down(p: KeyParams) -> Result<CallToolResult, ErrorData> {
let a = InputActionJson::KeyDown { key: p.key };
Ok(input_result(&a))
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_modifiers",
description = "Get current modifier key state (ctrl, shift, alt, command). Returns InputActionJson::Modifiers.",
emit = Auto
)]
#[instrument(skip_all)]
async fn egui_modifiers(p: EmptyInputParams) -> Result<CallToolResult, ErrorData> {
let _ = p;
Ok(input_result(&InputActionJson::Modifiers))
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_pointer_pos",
description = "Get current pointer/mouse position. Returns InputActionJson::PointerPos.",
emit = Auto,
emit = None
)]
#[instrument(skip_all)]
async fn egui_pointer_pos(p: EmptyInputParams) -> Result<CallToolResult, ErrorData> {
let _ = p;
Ok(input_result(&InputActionJson::PointerPos))
}
#[derive(Debug, Clone, Deserialize, JsonSchema)]
pub struct PointerButtonParams {
pub button: String,
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_pointer_button_pressed",
description = "Check if a mouse button was pressed. Returns InputActionJson::PointerButtonPressed.",
emit = Auto
)]
#[instrument(skip_all)]
async fn egui_pointer_button_pressed(p: PointerButtonParams) -> Result<CallToolResult, ErrorData> {
let a = InputActionJson::PointerButtonPressed { button: p.button };
Ok(input_result(&a))
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_pointer_button_released",
description = "Check if a mouse button was released. Returns InputActionJson::PointerButtonReleased.",
emit = Auto,
emit = None
)]
#[instrument(skip_all)]
async fn egui_pointer_button_released(p: PointerButtonParams) -> Result<CallToolResult, ErrorData> {
let a = InputActionJson::PointerButtonReleased { button: p.button };
Ok(input_result(&a))
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_pointer_delta",
description = "Get pointer movement delta this frame. Returns InputActionJson::PointerDelta.",
emit = Auto,
emit = None
)]
#[instrument(skip_all)]
async fn egui_pointer_delta(p: EmptyInputParams) -> Result<CallToolResult, ErrorData> {
let _ = p;
Ok(input_result(&InputActionJson::PointerDelta))
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_scroll_delta",
description = "Get scroll wheel delta. Returns InputActionJson::ScrollDelta.",
emit = Auto,
emit = None
)]
#[instrument(skip_all)]
async fn egui_scroll_delta(p: EmptyInputParams) -> Result<CallToolResult, ErrorData> {
let _ = p;
Ok(input_result(&InputActionJson::ScrollDelta))
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_clipboard_get",
description = "Get text from clipboard. Returns InputActionJson::ClipboardGet.",
emit = Auto,
emit = None
)]
#[instrument(skip_all)]
async fn egui_clipboard_get(p: EmptyInputParams) -> Result<CallToolResult, ErrorData> {
let _ = p;
Ok(input_result(&InputActionJson::ClipboardGet))
}
#[derive(Debug, Clone, Deserialize, JsonSchema)]
pub struct ClipboardSetParams {
pub text: String,
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_clipboard_set",
description = "Set text to clipboard. Returns InputActionJson::ClipboardSet.",
emit = Auto
)]
#[instrument(skip_all)]
async fn egui_clipboard_set(p: ClipboardSetParams) -> Result<CallToolResult, ErrorData> {
let a = InputActionJson::ClipboardSet { text: p.text };
Ok(input_result(&a))
}
#[derive(Debug, Clone, Deserialize, JsonSchema)]
pub struct FocusParams {
pub widget_id: String,
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_request_focus",
description = "Request keyboard focus for a widget by ID. Returns InputActionJson::RequestFocus.",
emit = Auto
)]
#[instrument(skip_all)]
async fn egui_request_focus(p: FocusParams) -> Result<CallToolResult, ErrorData> {
let a = InputActionJson::RequestFocus {
widget_id: p.widget_id,
};
Ok(input_result(&a))
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_surrender_focus",
description = "Release keyboard focus from a widget. Returns InputActionJson::SurrenderFocus.",
emit = Auto,
emit = None
)]
#[instrument(skip_all)]
async fn egui_surrender_focus(p: FocusParams) -> Result<CallToolResult, ErrorData> {
let a = InputActionJson::SurrenderFocus {
widget_id: p.widget_id,
};
Ok(input_result(&a))
}
#[elicit_tool(
plugin = "egui_input",
name = "egui_has_focus",
description = "Check if a widget has keyboard focus. Returns InputActionJson::HasFocus.",
emit = Auto,
emit = None
)]
#[instrument(skip_all)]
async fn egui_has_focus(p: FocusParams) -> Result<CallToolResult, ErrorData> {
let a = InputActionJson::HasFocus {
widget_id: p.widget_id,
};
Ok(input_result(&a))
}