Skip to main content
Glama

update_workspace

Modify workspace settings in AFFiNE by updating workspace ID, public visibility, and AI feature status to customize and enhance workspace functionality.

Instructions

Update workspace settings

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
enableAiNoEnable AI features
idYesWorkspace ID
publicNoMake workspace public

Implementation Reference

  • The main handler function for the update_workspace tool. It constructs a GraphQL mutation to update the workspace's public status and AI enablement, executes it via the GraphQL client, and returns the result.
    const updateWorkspaceHandler = async ({ id, public: isPublic, enableAi }: { id: string; public?: boolean; enableAi?: boolean }) => { try { const mutation = ` mutation UpdateWorkspace($input: UpdateWorkspaceInput!) { updateWorkspace(input: $input) { id public } } `; const input: any = { id }; if (isPublic !== undefined) input.public = isPublic; const data = await gql.request<{ updateWorkspace: any }>(mutation, { input }); return text(data.updateWorkspace); } catch (error: any) { return text({ error: error.message }); } };
  • Primary registration of the 'update_workspace' tool with the MCP server, including input schema using Zod.
    server.registerTool( "update_workspace", { title: "Update Workspace", description: "Update workspace settings", inputSchema: { id: z.string().describe("Workspace ID"), public: z.boolean().optional().describe("Make workspace public"), enableAi: z.boolean().optional().describe("Enable AI features") } }, updateWorkspaceHandler as any );
  • Secondary registration of the 'affine_update_workspace' tool alias using the same handler and schema.
    server.registerTool( "affine_update_workspace", { title: "Update Workspace", description: "Update workspace settings", inputSchema: { id: z.string().describe("Workspace ID"), public: z.boolean().optional().describe("Make workspace public"), enableAi: z.boolean().optional().describe("Enable AI features") } }, updateWorkspaceHandler as any );
  • Zod-based input schema definition for the tool parameters: workspace ID (required), public and enableAi (optional booleans).
    inputSchema: { id: z.string().describe("Workspace ID"), public: z.boolean().optional().describe("Make workspace public"), enableAi: z.boolean().optional().describe("Enable AI features") }
  • The registerWorkspaceTools function that sets up all workspace-related tools, including the update_workspace handler and registrations.
    export function registerWorkspaceTools(server: McpServer, gql: GraphQLClient) { // LIST WORKSPACES const listWorkspacesHandler = async () => { try { const query = `query { workspaces { id public enableAi createdAt } }`; const data = await gql.request<{ workspaces: any[] }>(query); return text(data.workspaces || []); } catch (error: any) { return text({ error: error.message }); } }; server.registerTool( "list_workspaces", { title: "List Workspaces", description: "List all available AFFiNE workspaces" }, listWorkspacesHandler as any ); server.registerTool( "affine_list_workspaces", { title: "List Workspaces", description: "List all available AFFiNE workspaces" }, listWorkspacesHandler ); // GET WORKSPACE const getWorkspaceHandler = async ({ id }: { id: string }) => { try { const query = `query GetWorkspace($id: String!) { workspace(id: $id) { id public enableAi createdAt permissions { Workspace_Read Workspace_CreateDoc } } }`; const data = await gql.request<{ workspace: any }>(query, { id }); return text(data.workspace); } catch (error: any) { return text({ error: error.message }); } }; server.registerTool( "get_workspace", { title: "Get Workspace", description: "Get details of a specific workspace", inputSchema: { id: z.string().describe("Workspace ID") } }, getWorkspaceHandler as any ); server.registerTool( "affine_get_workspace", { title: "Get Workspace", description: "Get details of a specific workspace", inputSchema: { id: z.string().describe("Workspace ID") } }, getWorkspaceHandler as any ); // CREATE WORKSPACE const createWorkspaceHandler = async ({ name, avatar }: { name: string; avatar?: string }) => { try { // Get endpoint and headers from GraphQL client const endpoint = (gql as any).endpoint || process.env.AFFINE_BASE_URL + '/graphql'; const headers = (gql as any).headers || {}; const cookie = (gql as any).cookie || headers.Cookie || ''; // Create initial workspace data const { workspaceUpdate, firstDocId, docUpdate } = createInitialWorkspaceData(name); // Only send workspace update - document will be created separately const initData = Buffer.from(workspaceUpdate); // Create multipart form const form = new FormData(); // Add GraphQL operation form.append('operations', JSON.stringify({ name: 'createWorkspace', query: `mutation createWorkspace($init: Upload!) { createWorkspace(init: $init) { id public createdAt enableAi } }`, variables: { init: null } })); // Map file to variable form.append('map', JSON.stringify({ '0': ['variables.init'] })); // Add workspace init data form.append('0', initData, { filename: 'init.yjs', contentType: 'application/octet-stream' }); // Send request const response = await fetch(endpoint, { method: 'POST', headers: { ...headers, 'Cookie': cookie, ...form.getHeaders() }, body: form as any }); const result = await response.json() as any; if (result.errors) { throw new Error(result.errors[0].message); } const workspace = result.data.createWorkspace; // Now create the actual document via WebSocket const wsUrl = endpoint.replace('https://', 'wss://').replace('http://', 'ws://').replace('/graphql', ''); return new Promise((resolve) => { const socket = io(wsUrl, { transports: ['websocket'], path: '/socket.io/', extraHeaders: cookie ? { Cookie: cookie } : undefined }); socket.on('connect', () => { // Join the workspace socket.emit('space:join', { spaceType: 'workspace', spaceId: workspace.id }); // Send the document update setTimeout(() => { const docUpdateBase64 = Buffer.from(docUpdate).toString('base64'); socket.emit('space:push-doc-update', { spaceType: 'workspace', spaceId: workspace.id, docId: firstDocId, update: docUpdateBase64 }); // Wait longer for sync and disconnect setTimeout(() => { socket.disconnect(); resolve(text({ ...workspace, name: name, avatar: avatar, firstDocId: firstDocId, status: "success", message: "Workspace created successfully", url: `${process.env.AFFINE_BASE_URL}/workspace/${workspace.id}` })); }, 3000); }, 1000); }); socket.on('error', () => { socket.disconnect(); // Even if WebSocket fails, workspace was created resolve(text({ ...workspace, name: name, avatar: avatar, firstDocId: firstDocId, status: "partial", message: "Workspace created (document sync may be pending)", url: `${process.env.AFFINE_BASE_URL}/workspace/${workspace.id}` })); }); // Timeout setTimeout(() => { socket.disconnect(); resolve(text({ ...workspace, name: name, avatar: avatar, firstDocId: firstDocId, status: "success", message: "Workspace created", url: `${process.env.AFFINE_BASE_URL}/workspace/${workspace.id}` })); }, 10000); }); } catch (error: any) { return text({ error: error.message, status: "failed" }); } }; server.registerTool( "create_workspace", { title: "Create Workspace", description: "Create a new workspace with initial document (accessible in UI)", inputSchema: { name: z.string().describe("Workspace name"), avatar: z.string().optional().describe("Avatar emoji or URL") } }, createWorkspaceHandler as any ); server.registerTool( "affine_create_workspace", { title: "Create Workspace", description: "Create a new workspace with initial document (accessible in UI)", inputSchema: { name: z.string().describe("Workspace name"), avatar: z.string().optional().describe("Avatar emoji or URL") } }, createWorkspaceHandler as any ); server.registerTool( "affine_create_workspace_fixed", { title: "Create Workspace (Fixed)", description: "Create a new workspace with initial document (backward compatible alias)", inputSchema: { name: z.string().describe("Workspace name"), avatar: z.string().optional().describe("Avatar emoji or URL") } }, createWorkspaceHandler as any ); // UPDATE WORKSPACE const updateWorkspaceHandler = async ({ id, public: isPublic, enableAi }: { id: string; public?: boolean; enableAi?: boolean }) => { try { const mutation = ` mutation UpdateWorkspace($input: UpdateWorkspaceInput!) { updateWorkspace(input: $input) { id public } } `; const input: any = { id }; if (isPublic !== undefined) input.public = isPublic; const data = await gql.request<{ updateWorkspace: any }>(mutation, { input }); return text(data.updateWorkspace); } catch (error: any) { return text({ error: error.message }); } }; server.registerTool( "update_workspace", { title: "Update Workspace", description: "Update workspace settings", inputSchema: { id: z.string().describe("Workspace ID"), public: z.boolean().optional().describe("Make workspace public"), enableAi: z.boolean().optional().describe("Enable AI features") } }, updateWorkspaceHandler as any ); server.registerTool( "affine_update_workspace", { title: "Update Workspace", description: "Update workspace settings", inputSchema: { id: z.string().describe("Workspace ID"), public: z.boolean().optional().describe("Make workspace public"), enableAi: z.boolean().optional().describe("Enable AI features") } }, updateWorkspaceHandler as any ); // DELETE WORKSPACE const deleteWorkspaceHandler = async ({ id }: { id: string }) => { try { const mutation = ` mutation DeleteWorkspace($id: String!) { deleteWorkspace(id: $id) } `; const data = await gql.request<{ deleteWorkspace: boolean }>(mutation, { id }); return text({ success: data.deleteWorkspace, message: "Workspace deleted successfully" }); } catch (error: any) { return text({ error: error.message }); } }; server.registerTool( "delete_workspace", { title: "Delete Workspace", description: "Delete a workspace permanently", inputSchema: { id: z.string().describe("Workspace ID") } }, deleteWorkspaceHandler as any ); server.registerTool( "affine_delete_workspace", { title: "Delete Workspace", description: "Delete a workspace permanently", inputSchema: { id: z.string().describe("Workspace ID") } }, deleteWorkspaceHandler as any ); }

Latest Blog Posts

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