Skip to main content
Glama
IAmAlexander

Readwise MCP Server

by IAmAlexander
save-document.ts3.39 kB
import { BaseMCPTool } from '../mcp/registry/base-tool.js'; import { ReadwiseAPI } from '../api/readwise-api.js'; import { SaveDocumentParams, SaveDocumentResponse, MCPToolResult, isAPIError } from '../types/index.js'; import { ValidationResult, validateRequired } from '../types/validation.js'; import type { Logger } from '../utils/logger-interface.js'; /** * Tool for saving new documents to Readwise */ export class SaveDocumentTool extends BaseMCPTool<SaveDocumentParams, SaveDocumentResponse> { /** * The name of the tool */ readonly name = 'save_document'; /** * The description of the tool */ readonly description = 'Save a new document (URL, article, or webpage) to your Readwise library'; /** * The JSON Schema parameters for the tool */ readonly parameters = { type: 'object', properties: { url: { type: 'string', description: 'The URL of the content to save' }, title: { type: 'string', description: 'Optional title override for the document' }, author: { type: 'string', description: 'Optional author override for the document' }, html: { type: 'string', description: 'Optional HTML content if not scraping from URL' }, tags: { type: 'array', items: { type: 'string' }, description: 'Optional tags to apply to the saved content' }, summary: { type: 'string', description: 'Optional summary of the content' }, notes: { type: 'string', description: 'Optional notes about the content' }, location: { type: 'string', enum: ['new', 'later', 'archive', 'feed'], description: 'Where to save the content (new, later, archive, or feed)' }, category: { type: 'string', description: 'Optional category for the document (e.g., article, email, rss)' }, published_date: { type: 'string', description: 'Optional published date in ISO 8601 format' }, image_url: { type: 'string', description: 'Optional cover image URL' } }, required: ['url'] }; /** * Create a new SaveDocumentTool */ constructor(private api: ReadwiseAPI, logger: Logger) { super(logger); } /** * Validate the parameters */ validate(params: SaveDocumentParams): ValidationResult { const validations = [ validateRequired(params, 'url', 'URL is required') ]; // Check each validation result for (const validation of validations) { if (!validation.valid) { return validation; } } // All validations passed return super.validate(params); } /** * Execute the tool */ async execute(params: SaveDocumentParams): Promise<MCPToolResult<SaveDocumentResponse>> { try { this.logger.debug('Executing save_document tool', params as any); const result = await this.api.saveDocument(params); this.logger.debug(`Saved document: ${result.id}`); return { result }; } catch (error) { this.logger.error('Error executing save_document tool', error as any); // Re-throw API errors if (isAPIError(error)) { throw error; } // Handle unexpected errors with proper result format throw error; } } }

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/IAmAlexander/readwise-mcp'

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