Skip to main content
Glama

Eureka Labo Task Management MCP Server

by mazemaze
index.ts12.4 kB
#!/usr/bin/env node /** * Eureka Labo MCP Server * Task management with automated change tracking */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { getConfig } from './config.js'; import { listTasks, getTask, createTask, updateTask, listProjectMembers, uploadTaskAttachment, } from './tools/task-tools.js'; import { startWorkOnTask, completeTaskWork, getActiveSessions, cancelWorkSession, } from './tools/work-session.js'; import { listBranchTasks, createPullRequest, } from './tools/pr-tools.js'; // Initialize MCP server const server = new Server( { name: 'eurekalabo-mcp-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // ===== Tool Definitions ===== server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ // Task Management Tools { name: 'list_tasks', description: 'List tasks for the project. Optionally filter by status, assignee, or search term.', inputSchema: { type: 'object', properties: { status: { type: 'string', description: 'Filter by status (todo, in_progress, done, cancelled)', }, assigneeId: { type: 'string', description: 'Filter by assignee user ID', }, search: { type: 'string', description: 'Search in task title and description', }, limit: { type: 'number', description: 'Maximum number of tasks to return', }, }, }, }, { name: 'get_task', description: 'Get detailed information about a specific task, including change history.', inputSchema: { type: 'object', properties: { taskId: { type: 'string', description: 'Task ID', }, }, required: ['taskId'], }, }, { name: 'create_task', description: 'Create a new task in the project.', inputSchema: { type: 'object', properties: { title: { type: 'string', description: 'Task title', }, description: { type: 'string', description: 'Task description', }, status: { type: 'string', description: 'Initial status (default: todo)', }, priority: { type: 'string', description: 'Priority level (low, medium, high, critical)', }, assigneeId: { type: 'string', description: 'User ID to assign task to', }, dueDate: { type: 'string', description: 'Due date (ISO 8601 format)', }, }, required: ['title'], }, }, { name: 'update_task', description: 'Update an existing task.', inputSchema: { type: 'object', properties: { taskId: { type: 'string', description: 'Task ID', }, title: { type: 'string', description: 'New task title', }, description: { type: 'string', description: 'New task description', }, status: { type: 'string', description: 'New status', }, priority: { type: 'string', description: 'New priority', }, assigneeId: { type: 'string', description: 'New assignee user ID', }, }, required: ['taskId'], }, }, // Work Session Tools { name: 'start_work_on_task', description: 'Begin working on a task. Captures git baseline for change tracking. Requires clean working directory (no uncommitted changes).', inputSchema: { type: 'object', properties: { taskId: { type: 'string', description: 'Task ID to start working on', }, }, required: ['taskId'], }, }, { name: 'complete_task_work', description: 'Complete work on a task. Captures all git changes since work started and logs them to the task.', inputSchema: { type: 'object', properties: { taskId: { type: 'string', description: 'Task ID to complete', }, summary: { type: 'string', description: 'Brief summary of work completed', }, }, required: ['taskId', 'summary'], }, }, { name: 'get_active_sessions', description: 'List all active work sessions.', inputSchema: { type: 'object', properties: {}, }, }, { name: 'cancel_work_session', description: 'Cancel an active work session without logging changes.', inputSchema: { type: 'object', properties: { taskId: { type: 'string', description: 'Task ID to cancel session for', }, }, required: ['taskId'], }, }, // Utility Tools { name: 'list_project_members', description: 'List all members of the project (for task assignment). Project is automatically determined from API key.', inputSchema: { type: 'object', properties: {}, }, }, { name: 'upload_task_attachment', description: 'Upload a file attachment to a task.', inputSchema: { type: 'object', properties: { taskId: { type: 'string', description: 'Task ID', }, filePath: { type: 'string', description: 'Local file path to upload', }, }, required: ['taskId', 'filePath'], }, }, // PR Integration Tools { name: 'list_branch_tasks', description: 'List all tasks worked on in the current git branch. Shows tasks that are part of the branch session.', inputSchema: { type: 'object', properties: {}, }, }, { name: 'create_pull_request', description: 'Create a GitHub pull request for all tasks in the current branch. Generates PR description from work sessions. Requires GitHub integration configured for the project.', inputSchema: { type: 'object', properties: { title: { type: 'string', description: 'PR title (optional - will auto-generate from tasks if not provided)', }, baseBranch: { type: 'string', description: 'Base branch to merge into (default: main)', }, }, }, }, ], }; }); // ===== Tool Execution Handler ===== server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const { name, arguments: args } = request.params; switch (name) { // Task Management case 'list_tasks': return { content: [ { type: 'text', text: JSON.stringify(await listTasks(args as any), null, 2), }, ], }; case 'get_task': return { content: [ { type: 'text', text: JSON.stringify(await getTask(args.taskId as string), null, 2), }, ], }; case 'create_task': return { content: [ { type: 'text', text: JSON.stringify(await createTask(args as any), null, 2), }, ], }; case 'update_task': return { content: [ { type: 'text', text: JSON.stringify( await updateTask(args.taskId as string, args as any), null, 2 ), }, ], }; // Work Sessions case 'start_work_on_task': return { content: [ { type: 'text', text: JSON.stringify( await startWorkOnTask(args.taskId as string), null, 2 ), }, ], }; case 'complete_task_work': return { content: [ { type: 'text', text: JSON.stringify( await completeTaskWork( args.taskId as string, args.summary as string ), null, 2 ), }, ], }; case 'get_active_sessions': return { content: [ { type: 'text', text: JSON.stringify( { sessions: getActiveSessions() }, null, 2 ), }, ], }; case 'cancel_work_session': return { content: [ { type: 'text', text: JSON.stringify( await cancelWorkSession(args.taskId as string), null, 2 ), }, ], }; // Utilities case 'list_project_members': return { content: [ { type: 'text', text: JSON.stringify( await listProjectMembers(), null, 2 ), }, ], }; case 'upload_task_attachment': return { content: [ { type: 'text', text: JSON.stringify( await uploadTaskAttachment( args.taskId as string, args.filePath as string ), null, 2 ), }, ], }; // PR Integration case 'list_branch_tasks': return { content: [ { type: 'text', text: JSON.stringify( await listBranchTasks(), null, 2 ), }, ], }; case 'create_pull_request': return { content: [ { type: 'text', text: JSON.stringify( await createPullRequest(args as any), null, 2 ), }, ], }; default: throw new Error(`Unknown tool: ${name}`); } } catch (error: any) { return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: error.message, }, null, 2 ), }, ], isError: true, }; } }); // ===== Start Server ===== async function main() { try { // Validate configuration const config = getConfig(); console.error(`[MCP] Starting Eureka Labo MCP Server`); console.error(`[MCP] API URL: ${config.apiUrl}`); console.error(`[MCP] Workspace: ${config.workspacePath}`); const transport = new StdioServerTransport(); await server.connect(transport); console.error('[MCP] Server ready'); } catch (error: any) { console.error('[MCP] Failed to start server:', error.message); process.exit(1); } } main();

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/mazemaze/mcp-server'

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