Skip to main content
Glama
jordanburke

joplin-mcp-server

read_note

Retrieve the full content of a specific note by providing its unique ID, enabling quick access to detailed information stored in the Joplin MCP Server.

Instructions

Read the full content of a specific note

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
note_idYesID of the note to read

Implementation Reference

  • Core handler logic in ReadNote.call(): validates note ID, fetches note and parent notebook details via Joplin API, formats metadata, todo status, timestamps, body content, and helpful commands.
    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.`
        )
      }
    }
  • Registers the read_note tool with FastMCP server, defining name, description, input schema (note_id), and execution delegating to manager.readNote.
    // Add read_note tool
    server.addTool({
      name: "read_note",
      description: "Read the full content of a specific note",
      parameters: z.object({
        note_id: z.string().describe("ID of the note to read"),
      }),
      execute: async (args) => {
        return await manager.readNote(args.note_id)
      },
    })
  • Zod schema for tool input: requires note_id as string.
    parameters: z.object({
      note_id: z.string().describe("ID of the note to read"),
    }),
  • JoplinServerManager.readNote(): delegates execution to the ReadNote tool instance.
    async readNote(noteId: string): Promise<string> {
      return await this.tools.readNote.call(noteId)
    }
  • Instantiates ReadNote tool with API client in JoplinServerManager constructor.
    readNote: new ReadNote(this.apiClient),
Install Server

Other Tools

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

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