Skip to main content
Glama

MCP-REPL

by AnEntrypoint
MIT License
3,295
104
  • Linux
  • Apple
mcp-pagination.js4.43 kB
import { generateId } from './utilities.js'; class PaginationManager { constructor() { this.cursors = new Map(); this.defaultPageSize = 50; this.maxCursorAge = 30 * 60 * 1000; } createCursor(data, position = 0) { const cursorId = generateId(); this.cursors.set(cursorId, { data, position, timestamp: Date.now(), totalItems: data.length }); return cursorId; } getCursor(cursorId) { const cursor = this.cursors.get(cursorId); if (!cursor) { throw new Error('Invalid or expired cursor'); } if (Date.now() - cursor.timestamp > this.maxCursorAge) { this.cursors.delete(cursorId); throw new Error('Cursor expired'); } return cursor; } removeCursor(cursorId) { this.cursors.delete(cursorId); } cleanup() { const now = Date.now(); const expiredTime = now - this.maxCursorAge; for (const [cursorId, cursor] of this.cursors.entries()) { if (cursor.timestamp < expiredTime) { this.cursors.delete(cursorId); } } } createPaginatedResponse(items, cursor = null, pageSize = null) { this.cleanup(); const effectivePageSize = pageSize || this.defaultPageSize; if (!cursor) { const pageItems = items.slice(0, effectivePageSize); const hasNext = items.length > effectivePageSize; const response = { items: pageItems, hasNext, totalItems: items.length }; if (hasNext) { const remainingItems = items.slice(effectivePageSize); response.nextCursor = this.createCursor(remainingItems, effectivePageSize); } return response; } try { const cursorData = this.getCursor(cursor); const remainingItems = cursorData.data; const pageItems = remainingItems.slice(0, effectivePageSize); const hasNext = remainingItems.length > effectivePageSize; const response = { items: pageItems, hasNext, totalItems: cursorData.totalItems }; if (hasNext) { const newRemaining = remainingItems.slice(effectivePageSize); response.nextCursor = this.createCursor(newRemaining, cursorData.position + effectivePageSize); } else { this.removeCursor(cursor); } return response; } catch (error) { throw new Error(`Invalid cursor: ${error.message}`); } } } const paginationManager = new PaginationManager(); export function createMCPResponse(data, options = {}) { const { cursor = null, pageSize = null, transform = null, metadata = {} } = options; const items = transform ? data.map(transform) : data; const response = paginationManager.createPaginatedResponse(items, cursor, pageSize); if (Object.keys(metadata).length > 0) { response.metadata = metadata; } return response; } export function createResourceReference(uri, name, metadata = {}) { return { uri, name, metadata: { ...metadata, createdAt: new Date().toISOString() } }; } export function createResourceResponse(resources, options = {}) { return createMCPResponse(resources, { ...options, metadata: { type: 'resource-list', ...options.metadata } }); } export function createPaginationError(error) { return { items: [], hasNext: false, error: error.message, isError: true }; } export function withPagination(handler, resourceName = 'items') { return async (args) => { try { const result = await handler(args); if (Array.isArray(result)) { const paginatedResult = createMCPResponse(result, { cursor: args.cursor, pageSize: args.pageSize, metadata: { resource: resourceName, timestamp: new Date().toISOString() } }); return { content: [{ type: "text", text: JSON.stringify(paginatedResult, null, 2) }] }; } if (result && result.content) { return result; } return { content: [{ type: "text", text: typeof result === 'string' ? result : JSON.stringify(result, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true }; } }; } export default paginationManager;

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/AnEntrypoint/mcp-repl'

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