Skip to main content
Glama

create_folder

Create a new notebook or folder in Joplin by specifying a title and optional parent notebook ID for organization and structure.

Instructions

Create a new folder/notebook in Joplin

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
parent_idNoID of parent notebook
titleYesNotebook title

Implementation Reference

  • The core handler implementation: CreateFolder class with async call() method that validates input, calls Joplin API to create folder, handles parent info, errors, and formats a rich success response.
    class CreateFolder extends BaseTool { async call(options: CreateFolderOptions): Promise<string> { if (!options || typeof options !== "object") { return 'Please provide folder creation options. Example: create_folder {"title": "My Notebook"}' } // Validate required title if (!options.title || typeof options.title !== "string" || options.title.trim() === "") { return 'Please provide a title for the folder/notebook. Example: create_folder {"title": "My Notebook"}' } // Validate parent_id if provided if (options.parent_id && (options.parent_id.length < 10 || !options.parent_id.match(/[a-f0-9]/i))) { return `Error: "${options.parent_id}" does not appear to be a valid parent notebook ID.\n\nNotebook IDs are long alphanumeric strings like "58a0a29f68bc4141b49c99f5d367638a".\n\nUse list_notebooks to see available notebooks and their IDs, or omit parent_id to create a top-level notebook.` } try { // Prepare the request body const requestBody: CreateFolderOptions = { title: options.title.trim(), } if (options.parent_id) { requestBody.parent_id = options.parent_id } // Create the folder const createdFolder = await this.apiClient.post<CreateFolderResponse>("/folders", requestBody) // Validate response if (!createdFolder || typeof createdFolder !== "object" || !createdFolder.id) { return "Error: Unexpected response format from Joplin API when creating folder" } // Get parent notebook info if available let parentInfo = "Top level" if (createdFolder.parent_id) { try { const parentNotebook = await this.apiClient.get(`/folders/${createdFolder.parent_id}`, { query: { fields: "id,title" }, }) if (parentNotebook && parentNotebook.title) { parentInfo = `Inside "${parentNotebook.title}" (notebook_id: "${createdFolder.parent_id}")` } } catch { // Continue even if we can't get parent info parentInfo = `Parent notebook ID: ${createdFolder.parent_id}` } } // Format success response const resultLines: string[] = [] resultLines.push(`✅ Successfully created notebook!`) resultLines.push("") resultLines.push(`📁 Notebook Details:`) resultLines.push(` Title: "${createdFolder.title}"`) resultLines.push(` Notebook ID: ${createdFolder.id}`) resultLines.push(` Location: ${parentInfo}`) const createdDate = this.formatDate(createdFolder.created_time) resultLines.push(` Created: ${createdDate}`) resultLines.push("") resultLines.push(`🔗 Next steps:`) resultLines.push(` - View notebook: read_notebook notebook_id="${createdFolder.id}"`) resultLines.push(` - Create a note in it: create_note {"title": "My Note", "parent_id": "${createdFolder.id}"}`) resultLines.push(` - View all notebooks: list_notebooks`) return resultLines.join("\n") } catch (error: any) { if (error.response) { // Handle specific API errors if (error.response.status === 400) { return `Error creating notebook: Invalid request data.\n\nPlease check your input parameters. ${error.response.data?.error || ""}` } if (error.response.status === 404 && options.parent_id) { return `Error: Parent notebook with ID "${options.parent_id}" not found.\n\nUse list_notebooks to see available notebooks and their IDs, or omit parent_id to create a top-level notebook.` } if (error.response.status === 409) { return `Error: A notebook with the title "${options.title}" might already exist in this location.\n\nTry a different title or check existing notebooks with list_notebooks.` } } return this.formatError(error, "creating notebook") } } }
  • MCP tool registration in FastMCP server: defines name 'create_folder', description, Zod input schema, and execute handler delegating to JoplinServerManager.createFolder.
    // Add create_folder tool server.addTool({ name: "create_folder", description: "Create a new folder/notebook in Joplin", parameters: z.object({ title: z.string().describe("Notebook title"), parent_id: z.string().optional().describe("ID of parent notebook"), }), execute: async (args) => { return await manager.createFolder(args) }, })
  • TypeScript interface defining input parameters for the create_folder tool (title required, parent_id optional).
    interface CreateFolderOptions { title: string parent_id?: string | undefined }
  • Instantiation and registration of CreateFolder tool instance within JoplinServerManager's tools object.
    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), }
  • JoplinServerManager.createFolder method that delegates execution to the CreateFolder tool's call method.
    async createFolder(params: { title: string; parent_id?: string | undefined }): Promise<string> { return await this.tools.createFolder.call(params) }

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