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::{op_error_to_tool_error, text_result};
#[mcp_tool(
name = "secret_read",
description = "Read a secret value using a 1Password secret reference (op:// URL). Format: op://vault/item/field or op://vault/item/section/field. Returns the raw secret value."
)]
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct SecretReadTool {
pub reference: String,
}
impl SecretReadTool {
pub async fn call(&self, client: &OpClient) -> Result<CallToolResult, CallToolError> {
let result = client
.read(&self.reference)
.await
.map_err(op_error_to_tool_error)?;
text_result(result)
}
}
#[mcp_tool(
name = "secret_inject",
description = "Inject 1Password secrets into a template string. Secret references in op:// format within the template will be replaced with their actual values. Useful for generating configuration files."
)]
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct SecretInjectTool {
pub template: String,
}
impl SecretInjectTool {
pub async fn call(&self, client: &OpClient) -> Result<CallToolResult, CallToolError> {
let result = client
.inject(&self.template)
.await
.map_err(op_error_to_tool_error)?;
text_result(result)
}
}
#[mcp_tool(
name = "secret_run",
description = "Run a command with 1Password secrets injected as environment variables. Secret references (op://) in the environment or .env file will be replaced with actual values. Note: This executes a command on the system."
)]
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct SecretRunTool {
pub command: String,
#[serde(default)]
pub env: Option<Vec<String>>,
#[serde(default)]
pub env_file: Option<String>,
#[serde(default)]
pub no_masking: bool,
}
impl SecretRunTool {
pub async fn call(&self, client: &OpClient) -> Result<CallToolResult, CallToolError> {
let env_refs: Option<Vec<&str>> = self
.env
.as_ref()
.map(|e| e.iter().map(|s| s.as_str()).collect());
let result = client
.run(
&self.command,
env_refs.as_deref(),
self.env_file.as_deref(),
self.no_masking,
)
.await
.map_err(op_error_to_tool_error)?;
text_result(result)
}
}