//! Server-functions for the MCP-tokens management UI. //! //! These wrap the agent's `/api/v1/mcp-tokens` CRUD endpoints. The raw //! token returned by `create_mcp_token` is only visible at creation //! time — the agent's storage never holds the plaintext. use dioxus::prelude::*; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct McpTokenView { pub id: String, pub name: String, pub token_prefix: String, pub created_by: String, pub created_at: serde_json::Value, #[serde(default)] pub last_used_at: Option, #[serde(default)] pub revoked: bool, } #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct McpTokensListResponse { pub data: Vec, } #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct CreateMcpTokenResponse { /// Raw token. Shown ONCE — the user must copy it now. pub token: String, pub view: McpTokenView, } #[server] pub async fn fetch_mcp_tokens() -> Result { let resp = super::agent_client::agent_get("/api/v1/mcp-tokens") .await? .send() .await .map_err(|e| ServerFnError::new(e.to_string()))?; let body: McpTokensListResponse = resp .json() .await .map_err(|e| ServerFnError::new(e.to_string()))?; Ok(body) } #[server] pub async fn create_mcp_token(name: String) -> Result { if name.trim().is_empty() { return Err(ServerFnError::new("Name is required")); } let resp = super::agent_client::agent_request(reqwest::Method::POST, "/api/v1/mcp-tokens") .await? .json(&serde_json::json!({ "name": name.trim() })) .send() .await .map_err(|e| ServerFnError::new(e.to_string()))?; if !resp.status().is_success() { let body = resp.text().await.unwrap_or_default(); return Err(ServerFnError::new(format!( "Failed to create token: {body}" ))); } let body: CreateMcpTokenResponse = resp .json() .await .map_err(|e| ServerFnError::new(e.to_string()))?; Ok(body) } #[server] pub async fn revoke_mcp_token(id: String) -> Result<(), ServerFnError> { let resp = super::agent_client::agent_request( reqwest::Method::DELETE, &format!("/api/v1/mcp-tokens/{id}"), ) .await? .send() .await .map_err(|e| ServerFnError::new(e.to_string()))?; if !resp.status().is_success() { let body = resp.text().await.unwrap_or_default(); return Err(ServerFnError::new(format!( "Failed to revoke token: {body}" ))); } Ok(()) }