use rmcp::{
ErrorData as McpError,
handler::server::wrapper::Parameters,
model::*,
tool, tool_router,
};
use serde::Deserialize;
use crate::server::GDriveServer;
#[derive(Debug, Deserialize, schemars::JsonSchema)]
pub struct PermissionsCreateParams {
pub file_id: String,
pub role: String,
#[serde(rename = "type")]
pub perm_type: String,
#[serde(default)]
pub email_address: Option<String>,
#[serde(default)]
pub domain: Option<String>,
#[serde(default)]
pub send_notification: Option<bool>,
#[serde(default)]
pub email_message: Option<String>,
}
#[derive(Debug, Deserialize, schemars::JsonSchema)]
pub struct PermissionsListParams {
pub file_id: String,
}
#[derive(Debug, Deserialize, schemars::JsonSchema)]
pub struct PermissionsGetParams {
pub file_id: String,
pub permission_id: String,
}
#[derive(Debug, Deserialize, schemars::JsonSchema)]
pub struct PermissionsUpdateParams {
pub file_id: String,
pub permission_id: String,
pub role: String,
}
#[derive(Debug, Deserialize, schemars::JsonSchema)]
pub struct PermissionsDeleteParams {
pub file_id: String,
pub permission_id: String,
}
#[tool_router(router = permissions_tool_router, vis = "pub")]
impl GDriveServer {
#[tool(name = "gdrive_permissions_create")]
async fn permissions_create(
&self,
Parameters(params): Parameters<PermissionsCreateParams>,
) -> Result<CallToolResult, McpError> {
let mut perm = google_drive3::api::Permission::default();
perm.role = Some(params.role);
perm.type_ = Some(params.perm_type);
perm.email_address = params.email_address;
perm.domain = params.domain;
let mut req = self.client.hub().permissions().create(perm, ¶ms.file_id);
req = req.supports_all_drives(true);
if let Some(send) = params.send_notification {
req = req.send_notification_email(send);
}
if let Some(msg) = ¶ms.email_message {
req = req.email_message(msg);
}
let (_, result) = req.doit().await.map_err(drive_err)?;
let json = serde_json::to_string_pretty(&result)
.map_err(|e| McpError::internal_error(e.to_string(), None))?;
Ok(CallToolResult::success(vec![Content::text(format!(
"Permission created:\n{json}"
))]))
}
#[tool(name = "gdrive_permissions_list")]
async fn permissions_list(
&self,
Parameters(params): Parameters<PermissionsListParams>,
) -> Result<CallToolResult, McpError> {
let (_, list) = self
.client
.hub()
.permissions()
.list(¶ms.file_id)
.supports_all_drives(true)
.param("fields", "permissions(id,type,role,emailAddress,domain,displayName)")
.doit()
.await
.map_err(drive_err)?;
let json = serde_json::to_string_pretty(&list.permissions)
.map_err(|e| McpError::internal_error(e.to_string(), None))?;
Ok(CallToolResult::success(vec![Content::text(json)]))
}
#[tool(name = "gdrive_permissions_get")]
async fn permissions_get(
&self,
Parameters(params): Parameters<PermissionsGetParams>,
) -> Result<CallToolResult, McpError> {
let (_, perm) = self
.client
.hub()
.permissions()
.get(¶ms.file_id, ¶ms.permission_id)
.supports_all_drives(true)
.param("fields", "id,type,role,emailAddress,domain,displayName,expirationTime")
.doit()
.await
.map_err(drive_err)?;
let json = serde_json::to_string_pretty(&perm)
.map_err(|e| McpError::internal_error(e.to_string(), None))?;
Ok(CallToolResult::success(vec![Content::text(json)]))
}
#[tool(name = "gdrive_permissions_update")]
async fn permissions_update(
&self,
Parameters(params): Parameters<PermissionsUpdateParams>,
) -> Result<CallToolResult, McpError> {
let mut perm = google_drive3::api::Permission::default();
perm.role = Some(params.role);
let (_, result) = self
.client
.hub()
.permissions()
.update(perm, ¶ms.file_id, ¶ms.permission_id)
.supports_all_drives(true)
.doit()
.await
.map_err(drive_err)?;
let json = serde_json::to_string_pretty(&result)
.map_err(|e| McpError::internal_error(e.to_string(), None))?;
Ok(CallToolResult::success(vec![Content::text(format!(
"Permission updated:\n{json}"
))]))
}
#[tool(name = "gdrive_permissions_delete")]
async fn permissions_delete(
&self,
Parameters(params): Parameters<PermissionsDeleteParams>,
) -> Result<CallToolResult, McpError> {
self.client
.hub()
.permissions()
.delete(¶ms.file_id, ¶ms.permission_id)
.supports_all_drives(true)
.doit()
.await
.map_err(drive_err)?;
Ok(CallToolResult::success(vec![Content::text(format!(
"Permission {} removed from file {}",
params.permission_id, params.file_id
))]))
}
}
fn drive_err(e: google_drive3::Error) -> McpError {
McpError::internal_error(format!("Google Drive API error: {e}"), None)
}