ferridriver-mcp 0.1.0

ferridriver MCP server library -- browser automation via Model Context Protocol
Documentation
use crate::params::StorageParams;
use crate::server::{McpServer, sess};
use rmcp::{
  ErrorData,
  handler::server::wrapper::Parameters,
  model::{CallToolResult, Content},
  tool, tool_router,
};

#[tool_router(router = storage_router, vis = "pub")]
impl McpServer {
  #[tool(
    name = "storage",
    description = "Manage localStorage. Actions: get (read key), set (write key=value), list (all entries), clear (remove all)."
  )]
  async fn storage(&self, Parameters(p): Parameters<StorageParams>) -> Result<CallToolResult, ErrorData> {
    let s = sess(p.session.as_opt());
    let _guard = self.session_guard(s).await;
    let page = Box::pin(self.page(s)).await?;
    match p.action.as_str() {
      "get" => {
        let key = p.key.as_deref().ok_or_else(|| Self::err("'key' required for get"))?;
        let r = page
          .evaluate(&format!("localStorage.getItem('{}')", key.replace('\'', "\\'")))
          .await
          .map_err(Self::err)?;
        Ok(CallToolResult::success(vec![Content::text(
          r.map_or("null".into(), |v| v.to_string()),
        )]))
      },
      "set" => {
        let key = p.key.as_deref().ok_or_else(|| Self::err("'key' required for set"))?;
        let value = p
          .value
          .as_deref()
          .ok_or_else(|| Self::err("'value' required for set"))?;
        page
          .evaluate(&format!(
            "localStorage.setItem('{}', '{}')",
            key.replace('\'', "\\'"),
            value.replace('\'', "\\'")
          ))
          .await
          .map_err(Self::err)?;
        Ok(CallToolResult::success(vec![Content::text(format!(
          "Set '{key}'='{value}'."
        ))]))
      },
      "list" => {
        let r = page
          .evaluate("JSON.stringify(Object.fromEntries(Object.entries(localStorage)))")
          .await
          .map_err(Self::err)?;
        let val = r.as_ref().and_then(|v| v.as_str()).unwrap_or("{}");
        let parsed: serde_json::Value = serde_json::from_str(val).unwrap_or_default();
        Ok(CallToolResult::success(vec![Content::text(
          serde_json::to_string_pretty(&parsed).unwrap_or_default(),
        )]))
      },
      "clear" => {
        page.evaluate("localStorage.clear()").await.map_err(Self::err)?;
        Ok(CallToolResult::success(vec![Content::text("localStorage cleared.")]))
      },
      other => Err(Self::err(format!(
        "Unknown action '{other}'. Use: get, set, list, clear."
      ))),
    }
  }
}