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',

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