Skip to main content
Glama

add_canvas_node

Add nodes to Obsidian canvases including files, text, links, or groups with specified position and dimensions to organize visual knowledge structures.

Instructions

Add a node to canvas (file, text, link, or group)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
canvasPathYesPath to canvas file
colorNoNode color (1-6)
fileNoFile path (for file nodes)
heightYesNode height
labelNoLabel (for group nodes)
nodeTypeYesType of node
textNoText content (for text nodes)
urlNoURL (for link nodes)
vaultYesVault name
widthYesNode width
xYesX coordinate
yYesY coordinate

Implementation Reference

  • src/index.ts:239-260 (registration)
    Registration of the 'add_canvas_node' tool in the ListTools handler, including full input schema definition.
    { name: 'add_canvas_node', description: 'Add a node to canvas (file, text, link, or group)', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, canvasPath: { type: 'string', description: 'Path to canvas file' }, nodeType: { type: 'string', enum: ['file', 'text', 'link', 'group'], description: 'Type of node' }, x: { type: 'number', description: 'X coordinate' }, y: { type: 'number', description: 'Y coordinate' }, width: { type: 'number', description: 'Node width' }, height: { type: 'number', description: 'Node height' }, file: { type: 'string', description: 'File path (for file nodes)' }, text: { type: 'string', description: 'Text content (for text nodes)' }, url: { type: 'string', description: 'URL (for link nodes)' }, label: { type: 'string', description: 'Label (for group nodes)' }, color: { type: 'string', description: 'Node color (1-6)' }, }, required: ['vault', 'canvasPath', 'nodeType', 'x', 'y', 'width', 'height'], }, },
  • Handler for 'add_canvas_node' tool call in the main switch statement, dispatching to CanvasService based on nodeType.
    case 'add_canvas_node': { const connector = this.connectors.get(args?.vault as string); if (!connector || !connector.vaultPath) { throw new Error(`Vault "${args?.vault}" not found or not a local vault`); } const nodeType = args?.nodeType as string; const canvasPath = args?.canvasPath as string; const commonOpts = { x: args?.x as number, y: args?.y as number, width: args?.width as number, height: args?.height as number, color: args?.color as any, }; let result; switch (nodeType) { case 'file': result = await this.canvasService.addFileNode(connector.vaultPath, canvasPath, { ...commonOpts, file: args?.file as string, subpath: args?.subpath as string | undefined, }); break; case 'text': result = await this.canvasService.addTextNode(connector.vaultPath, canvasPath, { ...commonOpts, text: args?.text as string, }); break; case 'link': result = await this.canvasService.addLinkNode(connector.vaultPath, canvasPath, { ...commonOpts, url: args?.url as string, }); break; case 'group': result = await this.canvasService.addGroupNode(connector.vaultPath, canvasPath, { ...commonOpts, label: args?.label as string | undefined, }); break; default: throw new Error(`Unknown node type: ${nodeType}`); } return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; }
  • Core implementation for adding file nodes to canvas (one of four node types). Reads canvas, adds node, writes back.
    async addFileNode( vaultPath: string, canvasPath: string, options: CreateFileNodeOptions ): Promise<VaultOperationResult<CanvasFileNode>> { const canvasResult = await this.readCanvas(vaultPath, canvasPath); if (!canvasResult.success || !canvasResult.data) { return { success: false, error: canvasResult.error }; } const node: CanvasFileNode = { id: options.id || this.generateId(), type: 'file', file: options.file, subpath: options.subpath, x: options.x, y: options.y, width: options.width, height: options.height, color: options.color }; canvasResult.data.nodes.push(node); const writeResult = await this.writeCanvas(vaultPath, canvasPath, canvasResult.data); if (!writeResult.success) { return { success: false, error: writeResult.error }; } return { success: true, data: node }; }
  • Core implementation for adding text nodes to canvas.
    async addTextNode( vaultPath: string, canvasPath: string, options: CreateTextNodeOptions ): Promise<VaultOperationResult<CanvasTextNode>> { const canvasResult = await this.readCanvas(vaultPath, canvasPath); if (!canvasResult.success || !canvasResult.data) { return { success: false, error: canvasResult.error }; } const node: CanvasTextNode = { id: options.id || this.generateId(), type: 'text', text: options.text, x: options.x, y: options.y, width: options.width, height: options.height, color: options.color }; canvasResult.data.nodes.push(node); const writeResult = await this.writeCanvas(vaultPath, canvasPath, canvasResult.data); if (!writeResult.success) { return { success: false, error: writeResult.error }; } return { success: true, data: node }; }
  • Core implementation for adding link nodes to canvas.
    async addLinkNode( vaultPath: string, canvasPath: string, options: CreateLinkNodeOptions ): Promise<VaultOperationResult<CanvasLinkNode>> { const canvasResult = await this.readCanvas(vaultPath, canvasPath); if (!canvasResult.success || !canvasResult.data) { return { success: false, error: canvasResult.error }; } const node: CanvasLinkNode = { id: options.id || this.generateId(), type: 'link', url: options.url, x: options.x, y: options.y, width: options.width, height: options.height, color: options.color }; canvasResult.data.nodes.push(node); const writeResult = await this.writeCanvas(vaultPath, canvasPath, canvasResult.data); if (!writeResult.success) { return { success: false, error: writeResult.error }; } return { success: true, data: node }; }

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

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