update_reading_goal
Modify your reading goal by adjusting the target number of books and updating your current progress to track reading achievements in Micro.blog.
Instructions
Update reading goal.
Args: goal_id: The ID of the reading goal value: The target number of books for the goal progress: The current progress (number of books read, optional)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| goal_id | Yes | ||
| value | Yes | ||
| progress | No |
Implementation Reference
- dxt-extension/server/index.js:189-211 (handler)Core implementation of the update_reading_goal tool: validates inputs and makes HTTP POST request to Micro.blog API to update the reading goal.async updateReadingGoal(goalId, value, progress = null) { if (!Number.isInteger(goalId) || goalId <= 0) { throw new Error("Goal ID must be a positive integer"); } if (!Number.isInteger(value) || value <= 0) { throw new Error("Goal value must be a positive integer"); } const data = { value: value.toString() }; if (progress !== null) { if (!Number.isInteger(progress) || progress < 0) { throw new Error("Progress must be a non-negative integer"); } data.progress = progress.toString(); } await this.makeRequest(`/books/goals/${goalId}`, { method: "POST", body: new URLSearchParams(data), }); return { success: true, message: "Reading goal updated successfully" }; }
- Input schema definition for the update_reading_goal tool, specifying parameters goal_id, value (required), and optional progress.type: "object", properties: { goal_id: { type: "integer", description: "The ID of the reading goal", minimum: 1, }, value: { type: "integer", description: "The target number of books for the goal", minimum: 1, }, progress: { type: "integer", description: "The current progress (number of books read, optional)", minimum: 0, }, }, required: ["goal_id", "value"], },
- dxt-extension/server/index.js:427-451 (registration)Tool registration in the list of available tools, including name, description, and schema.{ name: "update_reading_goal", description: "Update a reading goal's target or progress", inputSchema: { type: "object", properties: { goal_id: { type: "integer", description: "The ID of the reading goal", minimum: 1, }, value: { type: "integer", description: "The target number of books for the goal", minimum: 1, }, progress: { type: "integer", description: "The current progress (number of books read, optional)", minimum: 0, }, }, required: ["goal_id", "value"], }, },
- dxt-extension/server/index.js:595-606 (handler)MCP dispatch handler case that invokes the tool implementation for update_reading_goal.case "update_reading_goal": { const { goal_id, value, progress } = args; const result = await client.updateReadingGoal(goal_id, value, progress); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; }
- dxt-extension/server/index.js:15-212 (helper)MicroBooksClient class providing HTTP client utilities, including the update_reading_goal method.class MicroBooksClient { constructor(bearerToken) { if (!bearerToken) { throw new Error("Bearer token is required"); } this.bearerToken = bearerToken; this.headers = { "Authorization": `Bearer ${bearerToken}`, "User-Agent": "Micro Books MCP Server DXT/1.0.0", "Content-Type": "application/x-www-form-urlencoded", }; } async makeRequest(path, options = {}) { const url = new URL(path, BASE_URL); const requestOptions = { ...options, headers: { ...this.headers, ...options.headers, }, }; try { const response = await fetch(url, requestOptions); if (!response.ok) { const errorText = await response.text(); throw new Error(`HTTP ${response.status}: ${response.statusText}${errorText ? ` - ${errorText}` : ''}`); } const data = await response.json(); return data; } catch (error) { if (error.name === 'TypeError' && error.message.includes('fetch')) { throw new Error(`Network error: Unable to connect to ${url}`); } throw error; } } async getBookshelves() { return await this.makeRequest("/books/bookshelves"); } async getBookshelfBooks(bookshelfId) { if (!Number.isInteger(bookshelfId) || bookshelfId <= 0) { throw new Error("Bookshelf ID must be a positive integer"); } return await this.makeRequest(`/books/bookshelves/${bookshelfId}`); } async addBookshelf(name) { if (!name || typeof name !== 'string' || name.trim().length === 0) { throw new Error("Bookshelf name is required and must be a non-empty string"); } await this.makeRequest("/books/bookshelves", { method: "POST", body: new URLSearchParams({ name: name.trim() }), }); return { success: true, message: `Bookshelf '${name.trim()}' created successfully` }; } async renameBookshelf(bookshelfId, name) { if (!Number.isInteger(bookshelfId) || bookshelfId <= 0) { throw new Error("Bookshelf ID must be a positive integer"); } if (!name || typeof name !== 'string' || name.trim().length === 0) { throw new Error("Bookshelf name is required and must be a non-empty string"); } await this.makeRequest(`/books/bookshelves/${bookshelfId}`, { method: "POST", body: new URLSearchParams({ name: name.trim() }), }); return { success: true, message: `Bookshelf renamed to '${name.trim()}' successfully` }; } async addBook(title, author, bookshelfId, isbn = null, coverUrl = null) { if (!title || typeof title !== 'string' || title.trim().length === 0) { throw new Error("Book title is required and must be a non-empty string"); } if (!author || typeof author !== 'string' || author.trim().length === 0) { throw new Error("Book author is required and must be a non-empty string"); } if (!Number.isInteger(bookshelfId) || bookshelfId <= 0) { throw new Error("Bookshelf ID must be a positive integer"); } const data = { title: title.trim(), author: author.trim(), bookshelf_id: bookshelfId.toString(), }; if (isbn && typeof isbn === 'string' && isbn.trim().length > 0) { data.isbn = isbn.trim(); } if (coverUrl && typeof coverUrl === 'string' && coverUrl.trim().length > 0) { data.cover_url = coverUrl.trim(); } await this.makeRequest("/books", { method: "POST", body: new URLSearchParams(data), }); return { success: true, message: `Book '${title.trim()}' by ${author.trim()} added successfully` }; } async moveBook(bookId, bookshelfId) { if (!Number.isInteger(bookId) || bookId <= 0) { throw new Error("Book ID must be a positive integer"); } if (!Number.isInteger(bookshelfId) || bookshelfId <= 0) { throw new Error("Bookshelf ID must be a positive integer"); } await this.makeRequest(`/books/bookshelves/${bookshelfId}/assign`, { method: "POST", body: new URLSearchParams({ book_id: bookId.toString() }), }); return { success: true, message: `Book moved to bookshelf ${bookshelfId} successfully` }; } async removeBook(bookshelfId, bookId) { if (!Number.isInteger(bookshelfId) || bookshelfId <= 0) { throw new Error("Bookshelf ID must be a positive integer"); } if (!Number.isInteger(bookId) || bookId <= 0) { throw new Error("Book ID must be a positive integer"); } await this.makeRequest(`/books/bookshelves/${bookshelfId}/remove/${bookId}`, { method: "DELETE", }); return { success: true, message: "Book removed from bookshelf successfully" }; } async changeBookCover(bookshelfId, bookId, coverUrl) { if (!Number.isInteger(bookshelfId) || bookshelfId <= 0) { throw new Error("Bookshelf ID must be a positive integer"); } if (!Number.isInteger(bookId) || bookId <= 0) { throw new Error("Book ID must be a positive integer"); } if (!coverUrl || typeof coverUrl !== 'string' || coverUrl.trim().length === 0) { throw new Error("Cover URL is required and must be a non-empty string"); } await this.makeRequest(`/books/bookshelves/${bookshelfId}/cover/${bookId}`, { method: "POST", body: new URLSearchParams({ cover_url: coverUrl.trim() }), }); return { success: true, message: "Book cover updated successfully" }; } async getReadingGoals() { return await this.makeRequest("/books/goals"); } async getGoalProgress(goalId) { if (!Number.isInteger(goalId) || goalId <= 0) { throw new Error("Goal ID must be a positive integer"); } return await this.makeRequest(`/books/goals/${goalId}`); } async updateReadingGoal(goalId, value, progress = null) { if (!Number.isInteger(goalId) || goalId <= 0) { throw new Error("Goal ID must be a positive integer"); } if (!Number.isInteger(value) || value <= 0) { throw new Error("Goal value must be a positive integer"); } const data = { value: value.toString() }; if (progress !== null) { if (!Number.isInteger(progress) || progress < 0) { throw new Error("Progress must be a non-negative integer"); } data.progress = progress.toString(); } await this.makeRequest(`/books/goals/${goalId}`, { method: "POST", body: new URLSearchParams(data), }); return { success: true, message: "Reading goal updated successfully" }; } }