Skip to main content
Glama

create_todo

Create a TODO list with optional tasks and markdown support to organize multi-step work, track bug fixes, or plan feature development. Use for explicit requests and structured task management.

Instructions

Create a new TODO list with optional initial tasks and rich markdown support.

When to use this tool:

  • User explicitly requests "create a TODO"

  • Planning multi-step implementation tasks

  • Organizing feature development work

  • Tracking bug fixes or improvements

  • Creating task lists for later execution

Key features:

  • Rich markdown support in task content

  • Optional initial task list

  • Auto-incrementing TODO numbers

  • Task content supports code blocks

  • Hierarchical task organization

You should:

  1. ONLY create when user explicitly requests

  2. Include clear, actionable task descriptions

  3. Break complex work into subtasks

  4. Use markdown for code examples in tasks

  5. Number tasks logically

  6. Keep descriptions concise but complete

  7. Group related tasks together

DO NOT use when:

  • User hasn't explicitly asked for TODO

  • Tasks are trivial or single-step

  • Work will be done immediately

  • TODO already exists for this work

Tasks need {title: str, content?: str} format Returns: {success: bool, todo_number: int, message: str, error?: str}

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
descriptionYesDescription of the TODO list
project_idYesThe project identifier
tasksNoOptional initial tasks as {title, content} objects

Implementation Reference

  • The core handler function that executes the create_todo tool. Creates project/TODO/{number} directory, writes index.json metadata, creates initial TASK markdown files with frontmatter, and auto-commits to git.
    async createTodoAsync(params: { project_id: z.infer<typeof secureProjectIdSchema>; description: z.infer<typeof secureTodoDescriptionSchema>; tasks?: z.infer<typeof taskInputSchema>[]; }): Promise<string> { const context = this.createContext('create_todo', params); try { const { project_id, description, tasks = [] } = params; const [originalId, projectPath] = await createProjectEntryAsync(this.storagePath, project_id); const todoPath = join(projectPath, 'TODO'); // Create TODO directory if it doesn't exist await mkdir(todoPath, { recursive: true }); // Get next TODO number const todoNumber = await this.getNextTodoNumberAsync(todoPath); const todoDir = join(todoPath, todoNumber.toString()); // Create TODO directory await mkdir(todoDir); // Create index.json const metadata: TodoMetadata = { created: new Date().toISOString(), description, }; await writeFile(join(todoDir, 'index.json'), JSON.stringify(metadata, null, 2)); // Create initial tasks if provided for (let i = 0; i < tasks.length; i++) { const task = tasks[i]; const taskNumber = i + 1; const taskFilename = `TASK-${taskNumber.toString().padStart(3, '0')}-${slugify(task.title ?? 'task', { lower: true, strict: true })}.md`; const taskMetadata: TaskMetadata = { completed: false, created: new Date().toISOString(), updated: new Date().toISOString(), }; const frontmatter = yaml.dump(taskMetadata); const taskContent = `---\n${frontmatter}---\n\n# ${task.title}\n\n${task.content ?? ''}`; await writeFile(join(todoDir, taskFilename), taskContent); } // Auto-commit await autoCommitAsync(this.storagePath, `Create TODO #${todoNumber} in ${originalId}`); this.logSuccess('create_todo', { project_id, todo_number: todoNumber }, context); return this.formatSuccessResponse({ todo_number: todoNumber, message: tasks.length > 0 ? `Created TODO #${todoNumber} with ${tasks.length} initial task${tasks.length !== 1 ? 's' : ''}` : `Created TODO #${todoNumber}`, }); } catch (error) { const mcpError = error instanceof MCPError ? error : new MCPError( MCPErrorCode.FILE_SYSTEM_ERROR, `Failed to create TODO: ${error instanceof Error ? error.message : String(error)}`, { project_id: params.project_id, traceId: context.traceId } ); this.logError('create_todo', params, mcpError, context); return this.formatErrorResponse(mcpError, context); }
  • MCP server registration of the create_todo tool, defining input schema with Zod validation and wiring to TodoToolHandler.createTodoAsync.
    server.registerTool( 'create_todo', { title: 'Create TODO', description: TOOL_DESCRIPTIONS.create_todo, inputSchema: { project_id: secureProjectIdSchema.describe('The project identifier'), description: secureTodoDescriptionSchema.describe('Description of the TODO list'), tasks: z .array( z.object({ title: secureTaskTitleSchema.describe('Brief task title (max 200 chars)'), content: secureTaskContentSchema.describe('Full markdown content with details'), }) ) .optional() .describe('Optional initial tasks as {title, content} objects'), }, }, async ({ project_id, description, tasks }) => { const result = await todoHandler.createTodoAsync({ project_id, description, tasks }); return { content: [ { type: 'text', text: result, }, ], }; } );
  • Zod schemas defining input validation for create_todo parameters: project_id (shared), todo description, task title/content, and composite taskInputSchema for tasks array.
    export const secureTodoNumberSchema = z .number() .int('TODO number must be an integer') .positive('TODO number must be positive') .max(99999, 'TODO number too large'); export const secureTodoDescriptionSchema = z .string() .min(1, 'TODO description cannot be empty') .max(500, 'TODO description too long (max 500 characters)') .refine((val) => !val.includes('\0'), 'TODO description cannot contain null bytes') .refine((val) => val.trim() === val, 'TODO description cannot have leading/trailing spaces'); // Task title for brief identification (used in filenames) export const secureTaskTitleSchema = z .string() .min(1, 'Task title cannot be empty') .max(200, 'Task title too long (max 200 characters)') .refine((val) => !val.includes('\0'), 'Task title cannot contain null bytes') .refine((val) => val.trim() === val, 'Task title cannot have leading/trailing spaces'); // Full markdown content for task details export const secureTaskContentSchema = z .string() .max(100 * 1024, 'Task content too large (max 100KB)') .refine((val) => !val.includes('\0'), 'Task content cannot contain null bytes') .optional(); // Task input schema for new markdown-based tasks export const taskInputSchema = z.object({ title: secureTaskTitleSchema, content: secureTaskContentSchema, });
  • Detailed usage description string for the create_todo tool, used in server registration to guide LLM tool usage.
    create_todo: `Create a new TODO list with optional initial tasks and rich markdown support. When to use this tool: - User explicitly requests "create a TODO" - Planning multi-step implementation tasks - Organizing feature development work - Tracking bug fixes or improvements - Creating task lists for later execution Key features: - Rich markdown support in task content - Optional initial task list - Auto-incrementing TODO numbers - Task content supports code blocks - Hierarchical task organization You should: 1. ONLY create when user explicitly requests 2. Include clear, actionable task descriptions 3. Break complex work into subtasks 4. Use markdown for code examples in tasks 5. Number tasks logically 6. Keep descriptions concise but complete 7. Group related tasks together DO NOT use when: - User hasn't explicitly asked for TODO - Tasks are trivial or single-step - Work will be done immediately - TODO already exists for this work Tasks need {title: str, content?: str} format Returns: {success: bool, todo_number: int, message: str, error?: str}`,

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/sven-borkert/knowledge-mcp'

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