Skip to main content
Glama
camiloluvino

Roam Research MCP Server

by camiloluvino

roam_process_batch_actions

Execute multiple Roam Research block operations (create, update, move, delete) in a single batch to manage knowledge graphs efficiently.

Instructions

Executes a sequence of low-level block actions (create, update, move, delete) in a single, non-transactional batch. Actions are executed in the provided order. For creating nested blocks, you can use a temporary client-side UID in a parent block and refer to it in a child block within the same batch. For actions on existing blocks, a valid block UID is required. Note: Roam-flavored markdown, including block embedding with ((UID)) syntax, is supported within the string property for create-block and update-block actions. For actions on existing blocks or within a specific page context, it is often necessary to first obtain valid page or block UIDs. Tools like roam_fetch_page_by_title or other search tools can be used to retrieve these UIDs before executing batch actions. For simpler, sequential outlines, roam_create_outline is often more suitable. IMPORTANT: Before using this tool, ensure that you have loaded into context the 'Roam Markdown Cheatsheet' resource.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionsYesAn array of action objects to execute in order.

Implementation Reference

  • Core handler implementation: transforms input actions into Roam SDK batch format and executes them.
    async processBatch(actions: any[]): Promise<any> {
      const batchActions: RoamBatchAction[] = actions.map(action => {
        const { action: actionType, ...rest } = action;
        const roamAction: any = { action: actionType };
    
        if (rest.location) {
          roamAction.location = {
            'parent-uid': rest.location['parent-uid'],
            order: rest.location.order,
          };
        }
    
        const block: any = {};
        if (rest.string) block.string = rest.string;
        if (rest.uid) block.uid = rest.uid;
        if (rest.open !== undefined) block.open = rest.open;
        if (rest.heading !== undefined && rest.heading !== null && rest.heading !== 0) {
          block.heading = rest.heading;
        }
        if (rest['text-align']) block['text-align'] = rest['text-align'];
        if (rest['children-view-type']) block['children-view-type'] = rest['children-view-type'];
    
        if (Object.keys(block).length > 0) {
          roamAction.block = block;
        }
    
        return roamAction;
      });
    
      return await roamBatchActions(this.graph, {actions: batchActions});
    }
  • Registers the tool handler in the MCP server switch statement for tool calls.
    case BASE_TOOL_NAMES.PROCESS_BATCH_ACTIONS: {
      const { actions } = request.params.arguments as {
        actions: any[];
      };
      const result = await this.toolHandlers.processBatch(actions);
      return {
        content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
      };
    }
  • Input schema and metadata definition for the tool, including description and validation rules.
    [toolName(BASE_TOOL_NAMES.PROCESS_BATCH_ACTIONS)]: {
      name: toolName(BASE_TOOL_NAMES.PROCESS_BATCH_ACTIONS),
      description: 'Executes a sequence of low-level block actions (create, update, move, delete) in a single, non-transactional batch. Actions are executed in the provided order. For creating nested blocks, you can use a temporary client-side UID in a parent block and refer to it in a child block within the same batch. For actions on existing blocks, a valid block UID is required. Note: Roam-flavored markdown, including block embedding with `((UID))` syntax, is supported within the `string` property for `create-block` and `update-block` actions. For actions on existing blocks or within a specific page context, it is often necessary to first obtain valid page or block UIDs. Tools like `roam_fetch_page_by_title` or other search tools can be used to retrieve these UIDs before executing batch actions. For simpler, sequential outlines, `roam_create_outline` is often more suitable.\nIMPORTANT: Before using this tool, ensure that you have loaded into context the \'Roam Markdown Cheatsheet\' resource.',
      inputSchema: {
        type: 'object',
        properties: {
          actions: {
            type: 'array',
            description: 'An array of action objects to execute in order.',
            items: {
              type: 'object',
              properties: {
                "action": {
                  type: 'string',
                  description: 'The specific action to perform.',
                  enum: ['create-block', 'update-block', 'move-block', 'delete-block']
                },
                "uid": {
                  type: 'string',
                  description: 'The UID of the block to target for "update-block", "move-block", or "delete-block" actions.'
                },
                "string": {
                  type: 'string',
                  description: 'The content for the block, used in "create-block" and "update-block" actions.'
                },
                "open": {
                  type: "boolean",
                  description: "Optional: Sets the open/closed state of a block, used in 'update-block' or 'create-block'. Defaults to true."
                },
                "heading": {
                  type: "integer",
                  description: "Optional: The heading level (1, 2, or 3) for 'create-block' or 'update-block'.",
                  enum: [1, 2, 3]
                },
                "text-align": {
                  type: "string",
                  description: "Optional: The text alignment for 'create-block' or 'update-block'.",
                  enum: ["left", "center", "right", "justify"]
                },
                "children-view-type": {
                  type: "string",
                  description: "Optional: The view type for children of the block, for 'create-block' or 'update-block'.",
                  enum: ["bullet", "document", "numbered"]
                },
                "location": {
                  type: 'object',
                  description: 'Specifies where to place a block, used in "create-block" and "move-block" actions.',
                  properties: {
                    "parent-uid": {
                      type: 'string',
                      description: 'The UID of the parent block or page.'
                    },
                    "order": {
                      type: ['integer', 'string'],
                      description: 'The position of the block under its parent (e.g., 0, 1, 2) or a keyword ("first", "last").'
                    }
                  }
                }
              },
              required: ['action']
            }
          }
        },
        required: ['actions']
      }
    },
  • Wrapper method in ToolHandlers class that delegates to BatchOperations.processBatch.
    async processBatch(actions: any[]) {
      return this.batchOps.processBatch(actions);
    }
  • Constant mapping base name to prefixed tool name used in schema and registration.
    PROCESS_BATCH_ACTIONS: 'roam_process_batch_actions',
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 does well by describing the execution order ('Actions are executed in the provided order'), transactional nature ('non-transactional batch'), and specific capabilities like temporary UIDs for nested blocks and support for Roam-flavored markdown. However, it doesn't mention error handling, rate limits, or authentication requirements, which are common behavioral traits for batch operations.

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 in the first sentence. Each subsequent sentence adds valuable information about usage, prerequisites, and alternatives. While comprehensive, it could be slightly more concise by combining some of the guidance sentences, but overall it earns its place with useful content.

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 complexity of a batch operation tool with no annotations and no output schema, the description does well to cover execution behavior, prerequisites, alternatives, and specific capabilities. It mentions the need for UIDs from other tools and references the markdown cheatsheet resource. The main gap is the lack of information about return values or error responses, which would be helpful given there's no output schema.

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 single 'actions' parameter thoroughly. The description adds some context about how parameters are used (e.g., 'For creating nested blocks, you can use a temporary client-side UID...'), but doesn't provide significant additional semantic meaning beyond what the schema already specifies. This meets the baseline of 3 when schema coverage is high.

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 tool 'executes a sequence of low-level block actions (create, update, move, delete) in a single, non-transactional batch,' specifying both the verb (execute) and resource (block actions). It distinguishes from siblings by explicitly mentioning 'roam_create_outline' as an alternative for simpler outlines, showing clear differentiation.

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 provides explicit guidance on when to use this tool vs alternatives: 'For simpler, sequential outlines, `roam_create_outline` is often more suitable.' It also specifies prerequisites: 'Before using this tool, ensure that you have loaded into context the 'Roam Markdown Cheatsheet' resource,' and mentions when other tools are needed first: 'Tools like `roam_fetch_page_by_title` or other search tools can be used to retrieve these UIDs before executing batch actions.'

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