Current User
current_userRetrieve details of the currently authenticated user to verify identity and access session information.
Instructions
Get current signed-in user.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/user.ts:6-10 (handler)The handler function that executes the 'current_user' tool logic. It makes a GraphQL query for the current user's id, name, email, emailVerified, avatarUrl, disabled fields and returns the result.
const currentUserHandler = async () => { const query = `query Me { currentUser { id name email emailVerified avatarUrl disabled } }`; const data = await gql.request<{ currentUser: any }>(query); return text(data.currentUser); }; - src/tools/user.ts:14-17 (schema)Input/output schema for the 'current_user' tool. Defined inline with server.registerTool, has an empty inputSchema (no parameters) and a title/description.
{ title: "Current User", description: "Get current signed-in user.", inputSchema: {} - src/tools/user.ts:12-20 (registration)Tool registration via server.registerTool('current_user', ...). Maps the handler and schema to the MCP server.
server.registerTool( "current_user", { title: "Current User", description: "Get current signed-in user.", inputSchema: {} }, currentUserHandler as any ); - src/index.ts:10-10 (registration)Import of registerUserTools from ./tools/user.js in the main entry point.
import { registerUserTools } from "./tools/user.js"; - src/index.ts:184-184 (registration)Invocation of registerUserTools(server, gql) which registers the 'current_user' tool with the MCP server.
registerUserTools(server, gql); - src/util/mcp.ts:8-24 (helper)The text() utility function used by the handler to format the response as MCP text content.
export function text(data: unknown) { if (typeof data === "string") { return { content: [{ type: "text" as const, text: data }] }; } if (data !== null && typeof data === "object" && !Array.isArray(data)) { const structuredContent = cloneJsonValue(data); return { content: [{ type: "text" as const, text: JSON.stringify(structuredContent) }], structuredContent, }; } return { content: [{ type: "text" as const, text: JSON.stringify(data) }], }; } - src/graphqlClient.ts:68-131 (helper)The GraphQLClient.request() method used by the handler to execute the GraphQL query.
async request<T>(query: string, variables?: Record<string, any>): Promise<T> { const headers: Record<string, string> = { "Content-Type": "application/json", "User-Agent": `affine-mcp-server/${VERSION}`, ...this._headers, }; const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), GQL_FETCH_TIMEOUT_MS); let res; try { res = await fetch(this.opts.endpoint, { method: "POST", headers, body: JSON.stringify({ query, variables }), signal: controller.signal, }); } catch (err: any) { if (err.name === "AbortError") throw new Error(`GraphQL request timed out after ${GQL_FETCH_TIMEOUT_MS / 1000}s`); throw err; } finally { clearTimeout(timer); } // Handle redirects (undici may follow them but strip auth headers) if (res.status >= 300 && res.status < 400) { const location = res.headers.get("location"); throw new Error( `GraphQL endpoint returned redirect ${res.status} -> ${location || "(no location)"}. ` + `Check AFFINE_BASE_URL.` ); } const contentType = res.headers.get("content-type") || ""; // Guard against non-JSON responses (Cloudflare challenges, HTML error pages) if (!contentType.includes("application/json") && !contentType.includes("application/graphql")) { const body = await res.text(); const snippet = sanitizeErrorBody(body); throw new Error( `GraphQL endpoint returned non-JSON response (${res.status} ${res.statusText}, ` + `Content-Type: ${contentType || "(none)"}). Body: ${snippet}` ); } if (!res.ok) { // Try to parse error body as JSON let body: string; try { const json = await res.json() as any; body = json.errors?.map((e: any) => e.message).join("; ") || JSON.stringify(json); } catch { body = await res.text().catch(() => "(unreadable body)"); } throw new Error(`GraphQL HTTP ${res.status}: ${sanitizeErrorBody(body)}`); } const json = await res.json() as any; if (json.errors) { const msg = json.errors.map((e: any) => e.message).join("; "); throw new Error(`GraphQL error: ${sanitizeErrorBody(msg)}`); } return json.data as T; } - src/toolSurface.ts:23-86 (registration)Tool name listed in the ALL_TOOLS constant which defines the known tool surface.
"current_user", "delete_blob", "delete_block", "delete_collection", "delete_comment", "delete_database_row", "delete_doc", "delete_folder", "delete_organize_link", "delete_surface_element", "delete_workspace", "export_doc_markdown", "export_with_fidelity_report", "generate_access_token", "get_capabilities", "get_collection", "get_doc", "get_edgeless_canvas", "get_orphan_docs", "get_workspace", "inspect_template_structure", "instantiate_template_native", "list_access_tokens", "list_children", "list_collections", "list_comments", "list_docs", "list_docs_by_tag", "list_histories", "list_notifications", "list_organize_nodes", "list_surface_elements", "list_tags", "list_workspace_tree", "list_workspaces", "move_doc", "move_organize_node", "publish_doc", "read_all_notifications", "read_database_cells", "read_database_columns", "read_doc", "remove_doc_from_collection", "remove_tag_from_doc", "rename_folder", "replace_doc_with_markdown", "resolve_comment", "revoke_access_token", "revoke_doc", "search_docs", "sign_in", "update_collection", "update_collection_rules", "update_comment", "update_database_row", "update_doc_title", "update_edgeless_block", "update_frame_children", "update_profile", "update_settings", "update_surface_element", "update_workspace", "upload_blob", ] as const; - src/toolSurface.ts:113-113 (registration)Tool group scopes for 'current_user': ['users', 'users.read', 'read'].
current_user: ["users", "users.read", "read"], - src/toolSurface.ts:180-180 (registration)current_user included in READ_ONLY_TOOLS set.
"current_user", - src/toolSurface.ts:218-218 (registration)current_user included in CORE_TOOLS set.
"current_user",