op-mcp 0.1.0

MCP server providing LLM access to 1Password CLI
Documentation
//! Account management tools for 1Password

use rust_mcp_schema::schema_utils::CallToolError;
use rust_mcp_schema::CallToolResult;
use rust_mcp_sdk::macros::{mcp_tool, JsonSchema};
use serde::{Deserialize, Serialize};

use crate::op::OpClient;
use crate::tools::{json_result, op_error_to_tool_error, text_result};

// ============================================================================
// account_list Tool
// ============================================================================

/// List all configured 1Password accounts.
#[mcp_tool(
    name = "account_list",
    description = "List all 1Password accounts configured on this device. Shows account URL, email, user UUID, and account UUID for each account."
)]
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct AccountListTool {}

impl AccountListTool {
    pub async fn call(&self, client: &OpClient) -> Result<CallToolResult, CallToolError> {
        let result = client.account_list().await.map_err(op_error_to_tool_error)?;
        json_result(&result)
    }
}

// ============================================================================
// account_get Tool
// ============================================================================

/// Get details about a specific 1Password account.
#[mcp_tool(
    name = "account_get",
    description = "Get detailed information about a specific 1Password account. Returns account UUID, name, domain, type, state, and creation date."
)]
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct AccountGetTool {
    /// The account URL, shorthand, email, user UUID, or account UUID. If not specified, uses the current account.
    #[serde(default)]
    pub account: Option<String>,
}

impl AccountGetTool {
    pub async fn call(&self, client: &OpClient) -> Result<CallToolResult, CallToolError> {
        let result = client
            .account_get(self.account.as_deref())
            .await
            .map_err(op_error_to_tool_error)?;
        json_result(&result)
    }
}

// ============================================================================
// account_add Tool
// ============================================================================

/// Add a new 1Password account to this device.
#[mcp_tool(
    name = "account_add",
    description = "Add a new 1Password account to this device. This typically requires interactive authentication. The account will be available for use after successful sign-in."
)]
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct AccountAddTool {
    /// The 1Password account sign-in address (e.g., 'my.1password.com' or 'myteam.1password.com').
    pub address: String,

    /// The email address for the account.
    pub email: String,

    /// A shorthand name for the account (for easier command-line access).
    #[serde(default)]
    pub shorthand: Option<String>,
}

impl AccountAddTool {
    pub async fn call(&self, client: &OpClient) -> Result<CallToolResult, CallToolError> {
        let result = client
            .account_add(&self.address, &self.email, self.shorthand.as_deref())
            .await
            .map_err(op_error_to_tool_error)?;
        text_result(result)
    }
}

// ============================================================================
// account_forget Tool
// ============================================================================

/// Remove a 1Password account from this device.
#[mcp_tool(
    name = "account_forget",
    description = "Remove a 1Password account from this device. This signs out and removes all local data for the account. The account itself is not deleted, only removed from this device."
)]
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct AccountForgetTool {
    /// The account URL, shorthand, email, user UUID, or account UUID to forget.
    pub account: String,
}

impl AccountForgetTool {
    pub async fn call(&self, client: &OpClient) -> Result<CallToolResult, CallToolError> {
        let result = client
            .account_forget(&self.account)
            .await
            .map_err(op_error_to_tool_error)?;
        text_result(result)
    }
}