Skip to main content
Glama
jordanburke

joplin-mcp-server

read_notebook

Extract and retrieve contents of a specific notebook by providing its unique ID, enabling efficient data access and management in Joplin MCP Server.

Instructions

Read the contents of a specific notebook

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
notebook_idYesID of the notebook to read

Implementation Reference

  • The ReadNotebook class extending BaseTool implements the core execution logic for the read_notebook tool. The `call` method fetches notebook details, retrieves its notes, sorts them by update time, and formats a response listing all notes with instructions.
    class ReadNotebook extends BaseTool {
      async call(notebookId: string): Promise<string> {
        const validationError = this.validateId(notebookId, "notebook")
        if (validationError) {
          return validationError
        }
    
        try {
          // First, get the notebook details
          const notebook = await this.apiClient.get<JoplinFolder>(`/folders/${notebookId}`, {
            query: { fields: "id,title,parent_id" },
          })
    
          // Validate notebook response
          if (!notebook || typeof notebook !== "object" || !notebook.id) {
            return `Error: Unexpected response format from Joplin API when fetching notebook`
          }
    
          // Get all notes in this notebook
          const notes = await this.apiClient.get<NotebookNotesResponse>(`/folders/${notebookId}/notes`, {
            query: { fields: "id,title,updated_time,is_todo,todo_completed" },
          })
    
          // Validate notes response
          if (!notes || typeof notes !== "object") {
            return `Error: Unexpected response format from Joplin API when fetching notes`
          }
    
          if (!notes.items || !Array.isArray(notes.items) || notes.items.length === 0) {
            return `Notebook "${notebook.title}" (notebook_id: "${notebook.id}") is empty.\n\nTry another notebook ID or use list_notebooks to see all available notebooks.`
          }
    
          // Format the notebook contents
          const resultLines: string[] = []
          resultLines.push(`# Notebook: "${notebook.title}" (notebook_id: "${notebook.id}")`)
          resultLines.push(`Contains ${notes.items.length} notes:\n`)
          resultLines.push(`NOTE: This is showing the contents of notebook "${notebook.title}", not a specific note.\n`)
    
          // If multiple notes were found, add a hint about read_multinote
          if (notes.items.length > 1) {
            const noteIds = notes.items.map((note) => note.id)
            resultLines.push(`TIP: To read all ${notes.items.length} notes at once, use:\n`)
            resultLines.push(`read_multinote note_ids=${JSON.stringify(noteIds)}\n`)
          }
    
          // Sort notes by updated_time (newest first)
          const sortedNotes = [...notes.items].sort((a, b) => b.updated_time - a.updated_time)
    
          sortedNotes.forEach((note) => {
            const updatedDate = this.formatDate(note.updated_time)
    
            // Add checkbox for todos
            if (note.is_todo) {
              const checkboxStatus = note.todo_completed ? "✅" : "☐"
              resultLines.push(`- ${checkboxStatus} Note: "${note.title}" (note_id: "${note.id}")`)
            } else {
              resultLines.push(`- Note: "${note.title}" (note_id: "${note.id}")`)
            }
    
            resultLines.push(`  Updated: ${updatedDate}`)
            resultLines.push(`  To read this note: read_note note_id="${note.id}"`)
            resultLines.push("") // Empty line between notes
          })
    
          return resultLines.join("\n")
        } catch (error: any) {
          if (error.response && error.response.status === 404) {
            return `Notebook with ID "${notebookId}" not found.\n\nThis might happen if:\n1. The ID is incorrect\n2. You're using a note title instead of a notebook ID\n3. The notebook has been deleted\n\nUse list_notebooks to see all available notebooks with their IDs.`
          }
          return (
            this.formatError(error, "reading notebook") +
            `\n\nMake sure you're using a valid notebook ID, not a note title.\nUse list_notebooks to see all available notebooks with their IDs.`
          )
        }
      }
    }
    
    export default ReadNotebook
  • Input schema definition for the read_notebook tool in the stdio MCP server list tools response.
    {
      name: "read_notebook",
      description: "Read the contents of a specific notebook",
      inputSchema: {
        type: "object",
        properties: {
          notebook_id: { type: "string", description: "ID of the notebook to read" },
        },
        required: ["notebook_id"],
      },
  • src/index.ts:235-238 (registration)
    Tool dispatch handler in stdio MCP server that calls manager.readNotebook for read_notebook.
    case "read_notebook": {
      const notebookResult = await manager.readNotebook(args.notebook_id as string)
      return { content: [{ type: "text", text: notebookResult }], isError: false }
    }
  • Registration of read_notebook tool in FastMCP server including schema (Zod) and execute handler calling manager.readNotebook.
    server.addTool({
      name: "read_notebook",
      description: "Read the contents of a specific notebook",
      parameters: z.object({
        notebook_id: z.string().describe("ID of the notebook to read"),
      }),
      execute: async (args) => {
        return await manager.readNotebook(args.notebook_id)
      },
    })
  • Instantiation of ReadNotebook tool instance in JoplinServerManager for use by manager.readNotebook method.
    this.tools = {
      listNotebooks: new ListNotebooks(this.apiClient),
      searchNotes: new SearchNotes(this.apiClient),
      readNotebook: new ReadNotebook(this.apiClient),
      readNote: new ReadNote(this.apiClient),
      readMultiNote: new ReadMultiNote(this.apiClient),
      createNote: new CreateNote(this.apiClient),
      createFolder: new CreateFolder(this.apiClient),
      editNote: new EditNote(this.apiClient),
      editFolder: new EditFolder(this.apiClient),
      deleteNote: new DeleteNote(this.apiClient),
      deleteFolder: new DeleteFolder(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