Skip to main content
Glama
camiloluvino

Roam Research MCP Server

by camiloluvino

roam_add_todo

Add todo items as individual blocks to today's daily page in Roam Research, creating actionable tasks with todo status for each item.

Instructions

Add a list of todo items as individual blocks to today's daily page in Roam. Each item becomes its own actionable block with todo status. NOTE on Roam-flavored markdown: For direct linking: use [[link]] syntax. For aliased linking, use alias syntax. Do not concatenate words in links/hashtags - correct: #[[multiple words]] #self-esteem (for typically hyphenated words). IMPORTANT: Before using this tool, ensure that you have loaded into context the 'Roam Markdown Cheatsheet' resource.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
todosYesList of todo items to add

Implementation Reference

  • Core handler implementation for roam_add_todo: adds todo items as individual TODO blocks to today's daily page, creating the page if necessary.
    async addTodos(todos: string[]): Promise<{ success: boolean }> {
      if (!Array.isArray(todos) || todos.length === 0) {
        throw new McpError(
          ErrorCode.InvalidRequest,
          'todos must be a non-empty array'
        );
      }
    
      // Get today's date
      const today = new Date();
      const dateStr = formatRoamDate(today);
      
      // Try to find today's page
      const findQuery = `[:find ?uid :in $ ?title :where [?e :node/title ?title] [?e :block/uid ?uid]]`;
      const findResults = await q(this.graph, findQuery, [dateStr]) as [string][];
      
      let targetPageUid: string;
      
      if (findResults && findResults.length > 0) {
        targetPageUid = findResults[0][0];
      } else {
        // Create today's page if it doesn't exist
        try {
          await createPage(this.graph, {
            action: 'create-page',
            page: { title: dateStr }
          });
    
          // Get the new page's UID
          const results = await q(this.graph, findQuery, [dateStr]) as [string][];
          if (!results || results.length === 0) {
            throw new Error('Could not find created today\'s page');
          }
          targetPageUid = results[0][0];
        } catch (error) {
          throw new Error('Failed to create today\'s page');
        }
      }
    
      const todo_tag = "{{TODO}}";
      const actions = todos.map((todo, index) => ({
        action: 'create-block',
        location: {
          'parent-uid': targetPageUid,
          order: index
        },
        block: {
          string: `${todo_tag} ${todo}`
        }
      }));
    
      const result = await batchActions(this.graph, {
        action: 'batch-actions',
        actions
      });
    
      if (!result) {
        throw new Error('Failed to create todo blocks');
      }
      
      return { success: true };
    }
  • Input schema definition for the roam_add_todo tool, specifying an array of todo strings.
    [toolName(BASE_TOOL_NAMES.ADD_TODO)]: {
      name: toolName(BASE_TOOL_NAMES.ADD_TODO),
      description: 'Add a list of todo items as individual blocks to today\'s daily page in Roam. Each item becomes its own actionable block with todo status.\nNOTE on Roam-flavored markdown: For direct linking: use [[link]] syntax. For aliased linking, use [alias]([[link]]) syntax. Do not concatenate words in links/hashtags - correct: #[[multiple words]] #self-esteem (for typically hyphenated words).\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
      inputSchema: {
        type: 'object',
        properties: {
          todos: {
            type: 'array',
            items: {
              type: 'string',
              description: 'Todo item text'
            },
            description: 'List of todo items to add'
          }
        },
        required: ['todos'],
      },
    },
  • Tool registration in the MCP server's callTool handler switch statement, dispatching to toolHandlers.addTodos.
    case BASE_TOOL_NAMES.ADD_TODO: {
      const { todos } = request.params.arguments as { todos: string[] };
      const result = await this.toolHandlers.addTodos(todos);
      return {
        content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
      };
    }
  • Wrapper handler in ToolHandlers class that delegates to TodoOperations.addTodos.
    async addTodos(todos: string[]) {
      return this.todoOps.addTodos(todos);
    }
  • Instantiation of TodoOperations instance in ToolHandlers constructor for use by addTodos wrapper.
    private todoOps: TodoOperations;
    private outlineOps: OutlineOperations;
    private batchOps: BatchOperations;
    private cachedCheatsheet: string | null = null;
    
    constructor(private graph: Graph) {
      this.pageOps = new PageOperations(graph);
      this.blockOps = new BlockOperations(graph);
      this.blockRetrievalOps = new BlockRetrievalOperations(graph); // Initialize new instance
      this.searchOps = new SearchOperations(graph);
      this.memoryOps = new MemoryOperations(graph);
      this.todoOps = new TodoOperations(graph);
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior (adding todos as individual blocks with todo status) and includes important usage notes on Roam-flavored markdown syntax, which adds valuable context beyond basic functionality. However, it doesn't mention potential side effects like rate limits or authentication needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded with the core purpose, followed by important notes. While informative, the markdown syntax section could be more concise, but overall it maintains good structure without unnecessary verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (single parameter, no output schema, no annotations), the description is reasonably complete. It covers purpose, usage guidelines, and behavioral notes, though it lacks details on return values or error handling, which would be helpful for a mutation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents the 'todos' parameter as a list of todo item texts. The description adds minimal value beyond this, mentioning that items become 'individual blocks' but not providing additional semantic context about parameter usage or constraints.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Add a list of todo items as individual blocks') and target resource ('today's daily page in Roam'), distinguishing it from siblings like roam_create_page or roam_import_markdown. It specifies that each item becomes an actionable block with todo status, providing precise functionality.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use this tool ('add... to today's daily page') and includes a prerequisite ('Before using this tool, ensure that you have loaded into context the 'Roam Markdown Cheatsheet' resource'), providing clear guidance on timing and preparation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/camiloluvino/roamMCP'

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