Skip to main content
Glama

Readwise MCP Server

by IAmAlexander
bulk-operations.test.ts9.18 kB
import request from 'supertest'; import express from 'express'; import cors from 'cors'; // Mock Express app for testing const app = express(); app.use(cors()); app.use(express.json()); // Mock bulk save endpoint app.post('/bulk/save', (req, res) => { const { items, confirmation } = req.body; if (!confirmation || confirmation !== 'I confirm saving these items') { return res.status(400).json({ error: 'Missing or invalid confirmation. Please include "confirmation": "I confirm saving these items"' }); } if (!items || !Array.isArray(items) || items.length === 0) { return res.status(400).json({ error: 'Invalid or empty items array' }); } res.status(200).json({ success: true, saved: items.length, failed: 0, results: items.map(item => ({ url: item.url, success: true, document_id: `doc-${Math.floor(Math.random() * 10000)}` })) }); }); // Mock bulk update endpoint app.post('/bulk/update', (req, res) => { const { updates, confirmation } = req.body; if (!confirmation || confirmation !== 'I confirm these updates') { return res.status(400).json({ error: 'Missing or invalid confirmation. Please include "confirmation": "I confirm these updates"' }); } if (!updates || !Array.isArray(updates) || updates.length === 0) { return res.status(400).json({ error: 'Invalid or empty updates array' }); } res.status(200).json({ success: true, updated: updates.length, failed: 0, results: updates.map(update => ({ document_id: update.document_id, success: true })) }); }); // Mock bulk delete endpoint app.post('/bulk/delete', (req, res) => { const { document_ids, confirmation } = req.body; if (!confirmation || confirmation !== 'I confirm deletion of these documents') { return res.status(400).json({ error: 'Missing or invalid confirmation. Please include "confirmation": "I confirm deletion of these documents"' }); } if (!document_ids || !Array.isArray(document_ids) || document_ids.length === 0) { return res.status(400).json({ error: 'Invalid or empty document_ids array' }); } res.status(200).json({ success: true, deleted: document_ids.length, failed: 0, results: document_ids.map(id => ({ document_id: id, success: true })) }); }); // Mock bulk tag endpoint app.post('/bulk/tag', (req, res) => { const { document_ids, tags, replace_existing, confirmation } = req.body; if (!confirmation || confirmation !== 'I confirm these tag changes') { return res.status(400).json({ error: 'Missing or invalid confirmation. Please include "confirmation": "I confirm these tag changes"' }); } if (!document_ids || !Array.isArray(document_ids) || document_ids.length === 0) { return res.status(400).json({ error: 'Invalid or empty document_ids array' }); } if (!tags || !Array.isArray(tags) || tags.length === 0) { return res.status(400).json({ error: 'Invalid or empty tags array' }); } res.status(200).json({ success: true, tagged: document_ids.length, failed: 0, results: document_ids.map(id => ({ document_id: id, success: true, tags: tags })) }); }); describe('Bulk Operations with Confirmation', () => { describe('Bulk Save', () => { it('should require confirmation for bulk save', async () => { const response = await request(app) .post('/bulk/save') .send({ items: [ { url: 'https://example.com/article1' }, { url: 'https://example.com/article2' } ] // Missing confirmation }); expect(response.status).toBe(400); expect(response.body).toHaveProperty('error'); expect(response.body.error).toContain('Missing or invalid confirmation'); }); it('should process bulk save with valid confirmation', async () => { const items = [ { url: 'https://example.com/article1', tags: ['ai'] }, { url: 'https://example.com/article2', tags: ['research'] } ]; const response = await request(app) .post('/bulk/save') .send({ items, confirmation: 'I confirm saving these items' }); expect(response.status).toBe(200); expect(response.body).toHaveProperty('success', true); expect(response.body).toHaveProperty('saved', 2); expect(response.body).toHaveProperty('results'); expect(response.body.results).toHaveLength(2); expect(response.body.results[0]).toHaveProperty('url', items[0].url); expect(response.body.results[1]).toHaveProperty('url', items[1].url); }); }); describe('Bulk Update', () => { it('should require confirmation for bulk update', async () => { const response = await request(app) .post('/bulk/update') .send({ updates: [ { document_id: '123', title: 'New Title 1' }, { document_id: '456', tags: ['updated'] } ] // Missing confirmation }); expect(response.status).toBe(400); expect(response.body).toHaveProperty('error'); expect(response.body.error).toContain('Missing or invalid confirmation'); }); it('should process bulk update with valid confirmation', async () => { const updates = [ { document_id: '123', title: 'New Title 1' }, { document_id: '456', tags: ['updated'] } ]; const response = await request(app) .post('/bulk/update') .send({ updates, confirmation: 'I confirm these updates' }); expect(response.status).toBe(200); expect(response.body).toHaveProperty('success', true); expect(response.body).toHaveProperty('updated', 2); expect(response.body).toHaveProperty('results'); expect(response.body.results).toHaveLength(2); expect(response.body.results[0]).toHaveProperty('document_id', updates[0].document_id); expect(response.body.results[1]).toHaveProperty('document_id', updates[1].document_id); }); }); describe('Bulk Delete', () => { it('should require confirmation for bulk delete', async () => { const response = await request(app) .post('/bulk/delete') .send({ document_ids: ['123', '456', '789'] // Missing confirmation }); expect(response.status).toBe(400); expect(response.body).toHaveProperty('error'); expect(response.body.error).toContain('Missing or invalid confirmation'); }); it('should process bulk delete with valid confirmation', async () => { const document_ids = ['123', '456', '789']; const response = await request(app) .post('/bulk/delete') .send({ document_ids, confirmation: 'I confirm deletion of these documents' }); expect(response.status).toBe(200); expect(response.body).toHaveProperty('success', true); expect(response.body).toHaveProperty('deleted', 3); expect(response.body).toHaveProperty('results'); expect(response.body.results).toHaveLength(3); expect(response.body.results[0]).toHaveProperty('document_id', document_ids[0]); expect(response.body.results[1]).toHaveProperty('document_id', document_ids[1]); expect(response.body.results[2]).toHaveProperty('document_id', document_ids[2]); }); }); describe('Bulk Tag', () => { it('should require confirmation for bulk tag', async () => { const response = await request(app) .post('/bulk/tag') .send({ document_ids: ['123', '456'], tags: ['important', 'reference'], replace_existing: false // Missing confirmation }); expect(response.status).toBe(400); expect(response.body).toHaveProperty('error'); expect(response.body.error).toContain('Missing or invalid confirmation'); }); it('should process bulk tag with valid confirmation', async () => { const document_ids = ['123', '456']; const tags = ['important', 'reference']; const response = await request(app) .post('/bulk/tag') .send({ document_ids, tags, replace_existing: false, confirmation: 'I confirm these tag changes' }); expect(response.status).toBe(200); expect(response.body).toHaveProperty('success', true); expect(response.body).toHaveProperty('tagged', 2); expect(response.body).toHaveProperty('results'); expect(response.body.results).toHaveLength(2); expect(response.body.results[0]).toHaveProperty('document_id', document_ids[0]); expect(response.body.results[0]).toHaveProperty('tags'); expect(response.body.results[0].tags).toEqual(tags); expect(response.body.results[1]).toHaveProperty('document_id', document_ids[1]); expect(response.body.results[1]).toHaveProperty('tags'); expect(response.body.results[1].tags).toEqual(tags); }); }); });

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