Skip to main content
Glama
workspace-tools.ts12 kB
import { Tool } from '@modelcontextprotocol/sdk/types.js' import { WorkspacesApi } from '../api/workspaces.js' import { SidvyApiClient } from '../api/client.js' export class WorkspaceTools { constructor( private workspacesApi: WorkspacesApi, private client: SidvyApiClient, ) {} getTools(): Tool[] { return [ { name: 'list_workspaces', description: 'List all workspaces for the authenticated user with content counts', inputSchema: { type: 'object', properties: { includeStats: { type: 'boolean', description: 'Include content statistics (default: true)', }, }, additionalProperties: false, }, }, { name: 'create_workspace', description: 'Create a new workspace (max 2 workspaces per user)', inputSchema: { type: 'object', properties: { name: { type: 'string', minLength: 1, maxLength: 100, description: 'Workspace name' }, }, required: ['name'], additionalProperties: false, }, }, { name: 'update_workspace', description: 'Update a workspace (currently only name changes supported)', inputSchema: { type: 'object', properties: { workspaceId: { type: 'string', description: 'Workspace ID to update' }, name: { type: 'string', minLength: 1, maxLength: 100, description: 'New workspace name', }, }, required: ['workspaceId'], additionalProperties: false, }, }, { name: 'delete_workspace', description: 'Delete a workspace and all its content (cannot delete default workspace)', inputSchema: { type: 'object', properties: { workspaceId: { type: 'string', description: 'Workspace ID to delete' }, confirmDelete: { type: 'boolean', description: 'Confirmation flag (required for safety)', }, }, required: ['workspaceId', 'confirmDelete'], additionalProperties: false, }, }, { name: 'get_workspace', description: 'Get details of a specific workspace', inputSchema: { type: 'object', properties: { workspaceId: { type: 'string', description: 'Workspace ID to retrieve' }, }, required: ['workspaceId'], additionalProperties: false, }, }, { name: 'get_default_workspace', description: "Get the user's default workspace", inputSchema: { type: 'object', properties: {}, additionalProperties: false, }, }, { name: 'get_workspace_by_name', description: 'Find a workspace by its name', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Workspace name to search for' }, }, required: ['name'], additionalProperties: false, }, }, { name: 'get_workspace_stats', description: 'Get detailed statistics for a workspace', inputSchema: { type: 'object', properties: { workspaceId: { type: 'string', description: 'Workspace ID (optional, uses default if not specified)', }, }, additionalProperties: false, }, }, { name: 'can_create_workspace', description: 'Check if the user can create another workspace (max 2 allowed)', inputSchema: { type: 'object', properties: {}, additionalProperties: false, }, }, { name: 'switch_workspace', description: 'Switch context to a different workspace (for subsequent operations)', inputSchema: { type: 'object', properties: { workspaceId: { type: 'string', description: 'Workspace ID to switch to' }, }, required: ['workspaceId'], additionalProperties: false, }, }, { name: 'rename_workspace', description: 'Rename an existing workspace', inputSchema: { type: 'object', properties: { workspaceId: { type: 'string', description: 'Workspace ID to rename' }, newName: { type: 'string', minLength: 1, maxLength: 100, description: 'New workspace name', }, }, required: ['workspaceId', 'newName'], additionalProperties: false, }, }, ] } async handleToolCall(name: string, arguments_: any): Promise<any> { switch (name) { case 'list_workspaces': return this.handleListWorkspaces(arguments_) case 'create_workspace': return this.handleCreateWorkspace(arguments_) case 'update_workspace': return this.handleUpdateWorkspace(arguments_) case 'delete_workspace': return this.handleDeleteWorkspace(arguments_) case 'get_workspace': return this.handleGetWorkspace(arguments_) case 'get_default_workspace': return this.handleGetDefaultWorkspace(arguments_) case 'get_workspace_by_name': return this.handleGetWorkspaceByName(arguments_) case 'get_workspace_stats': return this.handleGetWorkspaceStats(arguments_) case 'can_create_workspace': return this.handleCanCreateWorkspace(arguments_) case 'switch_workspace': return this.handleSwitchWorkspace(arguments_) case 'rename_workspace': return this.handleRenameWorkspace(arguments_) default: throw new Error(`Unknown tool: ${name}`) } } private async handleListWorkspaces(args: any) { const response = await this.workspacesApi.listWorkspaces() if (this.client.isSuccessResponse(response)) { const workspaces = response.data const defaultWorkspace = workspaces.find((w) => w.isDefault) return { success: true, workspaces, count: workspaces.length, defaultWorkspace: defaultWorkspace?.id, maxWorkspaces: 2, canCreateMore: workspaces.length < 2, } } else { throw new Error(this.client.getErrorMessage(response)) } } private async handleCreateWorkspace(args: any) { const response = await this.workspacesApi.createWorkspaceIfPossible(args.name) if (this.client.isSuccessResponse(response)) { return { success: true, workspace: response.data, message: `Workspace "${response.data.name}" created successfully`, } } else { throw new Error(this.client.getErrorMessage(response)) } } private async handleUpdateWorkspace(args: any) { const response = await this.workspacesApi.updateWorkspace(args) if (this.client.isSuccessResponse(response)) { return { success: true, workspace: response.data, message: `Workspace "${response.data.name}" updated successfully`, } } else { throw new Error(this.client.getErrorMessage(response)) } } private async handleDeleteWorkspace(args: any) { const response = await this.workspacesApi.deleteWorkspaceWithConfirmation( args.workspaceId, args.confirmDelete, ) if (this.client.isSuccessResponse(response)) { return { success: true, deleted: response.data.deleted, workspaceId: response.data.workspaceId, deletedContent: response.data.deletedContent, message: `Workspace deleted successfully. Deleted ${response.data.deletedContent.notes} notes, ${response.data.deletedContent.groups} groups, and ${response.data.deletedContent.todos} todos.`, } } else { throw new Error(this.client.getErrorMessage(response)) } } private async handleGetWorkspace(args: any) { const response = await this.workspacesApi.getWorkspaceById(args.workspaceId) if (this.client.isSuccessResponse(response)) { if (response.data) { return { success: true, workspace: response.data, } } else { return { success: false, error: 'Workspace not found', } } } else { throw new Error(this.client.getErrorMessage(response)) } } private async handleGetDefaultWorkspace(args: any) { const response = await this.workspacesApi.getDefaultWorkspace() if (this.client.isSuccessResponse(response)) { if (response.data) { return { success: true, workspace: response.data, isDefault: true, } } else { return { success: false, error: 'No default workspace found', } } } else { throw new Error(this.client.getErrorMessage(response)) } } private async handleGetWorkspaceByName(args: any) { const response = await this.workspacesApi.getWorkspaceByName(args.name) if (this.client.isSuccessResponse(response)) { if (response.data) { return { success: true, workspace: response.data, searchName: args.name, } } else { return { success: false, error: `Workspace with name "${args.name}" not found`, } } } else { throw new Error(this.client.getErrorMessage(response)) } } private async handleGetWorkspaceStats(args: any) { const response = await this.workspacesApi.getWorkspaceStats(args.workspaceId) if (this.client.isSuccessResponse(response)) { const stats = response.data const totalContent = stats.contentCounts.notes + stats.contentCounts.groups + stats.contentCounts.todos return { success: true, stats, totalContent, message: `Workspace "${stats.name}" contains ${stats.contentCounts.notes} notes, ${stats.contentCounts.groups} groups, and ${stats.contentCounts.todos} todos`, } } else { throw new Error(this.client.getErrorMessage(response)) } } private async handleCanCreateWorkspace(args: any) { try { const canCreate = await this.workspacesApi.canCreateWorkspace() const workspaces = await this.workspacesApi.getAllWorkspaces() return { success: true, canCreate, currentCount: workspaces.length, maxAllowed: 2, remainingSlots: Math.max(0, 2 - workspaces.length), } } catch (error: any) { throw new Error(error.message) } } private async handleSwitchWorkspace(args: any) { const response = await this.workspacesApi.switchWorkspace(args.workspaceId) if (this.client.isSuccessResponse(response)) { if (response.data) { return { success: true, workspace: response.data, message: `Switched to workspace "${response.data.name}"`, currentWorkspaceId: response.data.id, } } else { return { success: false, error: 'Workspace not found', } } } else { throw new Error(this.client.getErrorMessage(response)) } } private async handleRenameWorkspace(args: any) { const response = await this.workspacesApi.renameWorkspace(args.workspaceId, args.newName) if (this.client.isSuccessResponse(response)) { return { success: true, workspace: response.data, oldName: args.currentName, // This would need to be tracked separately newName: response.data.name, message: `Workspace renamed to "${response.data.name}"`, } } else { throw new Error(this.client.getErrorMessage(response)) } } }

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/martinhjartmyr/sidvy-mcp'

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