Skip to main content
Glama
read-note.ts3.38 kB
import BaseTool, { JoplinNote, JoplinFolder } from "./base-tool.js" class ReadNote extends BaseTool { async call(noteId: string): Promise<string> { const validationError = this.validateId(noteId, "note") if (validationError) { return validationError } try { // Get the note details with all relevant fields const note = await this.apiClient.get<JoplinNote>(`/notes/${noteId}`, { query: { fields: "id,title,body,parent_id,created_time,updated_time,is_todo,todo_completed,todo_due", }, }) // Validate note response if (!note || typeof note !== "object" || !note.id) { return `Error: Unexpected response format from Joplin API when fetching note` } // Get the notebook info to show where this note is located let notebookInfo = "Unknown notebook" if (note.parent_id) { try { const notebook = await this.apiClient.get<JoplinFolder>(`/folders/${note.parent_id}`, { query: { fields: "id,title" }, }) if (notebook && notebook.title) { notebookInfo = `"${notebook.title}" (notebook_id: "${note.parent_id}")` } } catch (err: unknown) { process.stderr.write(`Error fetching notebook info: ${err}\n`) // Continue even if we can't get the notebook info } } // Format the note content const resultLines: string[] = [] // Add note header with metadata resultLines.push(`# Note: "${note.title}"`) resultLines.push(`Note ID: ${note.id}`) resultLines.push(`Notebook: ${notebookInfo}`) // Add todo status if applicable if (note.is_todo) { const status = note.todo_completed ? "Completed" : "Not completed" resultLines.push(`Status: ${status}`) if (note.todo_due) { const dueDate = this.formatDate(note.todo_due) resultLines.push(`Due: ${dueDate}`) } } // Add timestamps const createdDate = this.formatDate(note.created_time) const updatedDate = this.formatDate(note.updated_time) resultLines.push(`Created: ${createdDate}`) resultLines.push(`Updated: ${updatedDate}`) // Add a separator before the note content resultLines.push("\n---\n") // Add the note body if (note.body) { resultLines.push(note.body) } else { resultLines.push("(This note has no content)") } // Add a footer with helpful commands resultLines.push("\n---\n") resultLines.push("Related commands:") resultLines.push(`- To view the notebook containing this note: read_notebook notebook_id="${note.parent_id}"`) resultLines.push('- To search for more notes: search_notes query="your search term"') return resultLines.join("\n") } catch (error: any) { if (error.response && error.response.status === 404) { return `Note with ID "${noteId}" not found.\n\nThis might happen if:\n1. The ID is incorrect\n2. You're using a notebook ID instead of a note ID\n3. The note has been deleted\n\nUse search_notes to find notes and their IDs.` } return ( this.formatError(error, "reading note") + `\n\nMake sure you're using a valid note ID.\nUse search_notes to find notes and their IDs.` ) } } } export default ReadNote

Implementation Reference

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/jordanburke/joplin-mcp-server'

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