Skip to main content
Glama
sureshsankaran

Obsidian Tools MCP Server

insert_at_heading

Insert content under a specific heading in an Obsidian note to organize information within sections.

Instructions

Insert content under a specific heading in a note

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the note
headingYesThe heading text to insert content under
contentYesContent to insert
positionNoInsert at start or end of the heading section. Default: endend

Implementation Reference

  • The core handler function that executes the tool: reads the note, finds the specified heading using regex, determines the section end by next higher/same level heading, inserts content at start or end of the section, and writes back the file.
    async function handleInsertAtHeading(args: { path: string; heading: string; content: string; position?: "start" | "end"; }): Promise<string> { const fullPath = resolvePath(args.path); const position = args.position ?? "end"; if (!(await fileExists(fullPath))) { throw new Error(`Note not found at ${args.path}`); } const fileContent = await fs.readFile(fullPath, "utf-8"); const lines = fileContent.split("\n"); // Find the heading const headingPattern = new RegExp(`^#+\\s+${args.heading}\\s*$`); let headingIndex = -1; for (let i = 0; i < lines.length; i++) { if (headingPattern.test(lines[i])) { headingIndex = i; break; } } if (headingIndex === -1) { throw new Error(`Heading "${args.heading}" not found in ${args.path}`); } // Find the end of this section (next heading of same or higher level) const headingLevel = (lines[headingIndex].match(/^#+/) || [""])[0].length; let sectionEnd = lines.length; for (let i = headingIndex + 1; i < lines.length; i++) { const lineHeadingMatch = lines[i].match(/^#+/); if (lineHeadingMatch && lineHeadingMatch[0].length <= headingLevel) { sectionEnd = i; break; } } // Insert content if (position === "start") { lines.splice(headingIndex + 1, 0, "", args.content); } else { lines.splice(sectionEnd, 0, args.content, ""); } await fs.writeFile(fullPath, lines.join("\n"), "utf-8"); return `Successfully inserted content under heading "${args.heading}" in ${args.path}`; }
  • The input schema definition for the insert_at_heading tool, specifying parameters like path, heading, content, and optional position.
    { name: "insert_at_heading", description: "Insert content under a specific heading in a note", inputSchema: { type: "object", properties: { path: { type: "string", description: "Path to the note", }, heading: { type: "string", description: "The heading text to insert content under", }, content: { type: "string", description: "Content to insert", }, position: { type: "string", enum: ["start", "end"], description: "Insert at start or end of the heading section. Default: end", default: "end", }, }, required: ["path", "heading", "content"], }, },
  • src/index.ts:920-928 (registration)
    The switch case in the CallToolRequest handler that routes calls to 'insert_at_heading' to the handleInsertAtHeading function.
    case "insert_at_heading": result = await handleInsertAtHeading( args as { path: string; heading: string; content: string; position?: "start" | "end"; } );

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/sureshsankaran/obsidian-tools-mcp'

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