Skip to main content
Glama

AFFiNE MCP Server

by DAWNCR0W
userCRUD.ts8.23 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { GraphQLClient } from "../graphqlClient.js"; import { text } from "../util/mcp.js"; export function registerUserCRUDTools(server: McpServer, gql: GraphQLClient) { // UPDATE PROFILE const updateProfileHandler = async ({ name, avatarUrl }: { name?: string; avatarUrl?: string }) => { try { const mutation = ` mutation UpdateProfile($input: UpdateUserInput!) { updateProfile(input: $input) { id name avatarUrl email } } `; const input: any = {}; if (name !== undefined) input.name = name; if (avatarUrl !== undefined) input.avatarUrl = avatarUrl; const data = await gql.request<{ updateProfile: any }>(mutation, { input }); return text(data.updateProfile); } catch (error: any) { return text({ error: error.message }); } }; server.registerTool( "affine_update_profile", { title: "Update Profile", description: "Update current user's profile information.", inputSchema: { name: z.string().optional().describe("Display name"), avatarUrl: z.string().optional().describe("Avatar URL") } }, updateProfileHandler as any ); server.registerTool( "update_profile", { title: "Update Profile", description: "Update current user's profile information.", inputSchema: { name: z.string().optional().describe("Display name"), avatarUrl: z.string().optional().describe("Avatar URL") } }, updateProfileHandler as any ); // UPDATE SETTINGS const updateSettingsHandler = async ({ settings }: { settings: Record<string, any> }) => { try { const mutation = ` mutation UpdateSettings($input: UpdateUserSettingsInput!) { updateSettings(input: $input) { success } } `; const data = await gql.request<{ updateSettings: any }>(mutation, { input: settings }); return text(data.updateSettings); } catch (error: any) { return text({ error: error.message }); } }; server.registerTool( "affine_update_settings", { title: "Update Settings", description: "Update user settings and preferences.", inputSchema: { settings: z.record(z.any()).describe("Settings object with key-value pairs") } }, updateSettingsHandler as any ); server.registerTool( "update_settings", { title: "Update Settings", description: "Update user settings and preferences.", inputSchema: { settings: z.record(z.any()).describe("Settings object with key-value pairs") } }, updateSettingsHandler as any ); // SEND VERIFICATION EMAIL const sendVerifyEmailHandler = async ({ callbackUrl }: { callbackUrl?: string }) => { try { const mutation = ` mutation SendVerifyEmail($callbackUrl: String!) { sendVerifyEmail(callbackUrl: $callbackUrl) } `; const data = await gql.request<{ sendVerifyEmail: boolean }>(mutation, { callbackUrl: callbackUrl || `${process.env.AFFINE_BASE_URL}/verify` }); return text({ success: data.sendVerifyEmail, message: "Verification email sent" }); } catch (error: any) { return text({ error: error.message }); } }; server.registerTool( "affine_send_verify_email", { title: "Send Verification Email", description: "Send email verification link.", inputSchema: { callbackUrl: z.string().optional().describe("Callback URL after verification") } }, sendVerifyEmailHandler as any ); server.registerTool( "send_verify_email", { title: "Send Verification Email", description: "Send email verification link.", inputSchema: { callbackUrl: z.string().optional().describe("Callback URL after verification") } }, sendVerifyEmailHandler as any ); // CHANGE PASSWORD const changePasswordHandler = async ({ token, newPassword, userId }: { token: string; newPassword: string; userId?: string }) => { try { const mutation = ` mutation ChangePassword($token: String!, $newPassword: String!, $userId: String) { changePassword(token: $token, newPassword: $newPassword, userId: $userId) } `; const data = await gql.request<{ changePassword: boolean }>(mutation, { token, newPassword, userId }); return text({ success: data.changePassword, message: "Password changed successfully" }); } catch (error: any) { return text({ error: error.message }); } }; server.registerTool( "affine_change_password", { title: "Change Password", description: "Change user password (requires token from email).", inputSchema: { token: z.string().describe("Password reset token from email"), newPassword: z.string().describe("New password"), userId: z.string().optional().describe("User ID") } }, changePasswordHandler as any ); server.registerTool( "change_password", { title: "Change Password", description: "Change user password (requires token from email).", inputSchema: { token: z.string().describe("Password reset token from email"), newPassword: z.string().describe("New password"), userId: z.string().optional().describe("User ID") } }, changePasswordHandler as any ); // SEND PASSWORD RESET EMAIL const sendPasswordResetHandler = async ({ callbackUrl }: { callbackUrl?: string }) => { try { const mutation = ` mutation SendChangePasswordEmail($callbackUrl: String!) { sendChangePasswordEmail(callbackUrl: $callbackUrl) } `; const data = await gql.request<{ sendChangePasswordEmail: boolean }>(mutation, { callbackUrl: callbackUrl || `${process.env.AFFINE_BASE_URL}/reset-password` }); return text({ success: data.sendChangePasswordEmail, message: "Password reset email sent" }); } catch (error: any) { return text({ error: error.message }); } }; server.registerTool( "affine_send_password_reset", { title: "Send Password Reset", description: "Send password reset email.", inputSchema: { callbackUrl: z.string().optional().describe("Callback URL for password reset") } }, sendPasswordResetHandler as any ); server.registerTool( "send_password_reset", { title: "Send Password Reset", description: "Send password reset email.", inputSchema: { callbackUrl: z.string().optional().describe("Callback URL for password reset") } }, sendPasswordResetHandler as any ); // DELETE ACCOUNT const deleteAccountHandler = async ({ confirm }: { confirm: true }) => { if (!confirm) { return text({ error: "Confirmation required. Set confirm: true to delete account." }); } try { const mutation = ` mutation DeleteAccount { deleteAccount } `; const data = await gql.request<{ deleteAccount: boolean }>(mutation); return text({ success: data.deleteAccount, message: "Account deleted successfully" }); } catch (error: any) { return text({ error: error.message }); } }; server.registerTool( "affine_delete_account", { title: "Delete Account", description: "Permanently delete user account. WARNING: This cannot be undone!", inputSchema: { confirm: z.literal(true).describe("Must be true to confirm account deletion") } }, deleteAccountHandler as any ); server.registerTool( "delete_account", { title: "Delete Account", description: "Permanently delete user account. WARNING: This cannot be undone!", inputSchema: { confirm: z.literal(true).describe("Must be true to confirm account deletion") } }, deleteAccountHandler as any ); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DAWNCR0W/affine-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server