Skip to main content
Glama

PDF Reader MCP Server

by sylphxltd
parser.test.ts5.95 kB
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js'; import { describe, expect, it, vi } from 'vitest'; import { determinePagesToProcess, getTargetPages, parsePageRanges } from '../../src/pdf/parser.js'; describe('parser', () => { describe('parsePageRanges', () => { it('should parse single page', () => { expect(parsePageRanges('5')).toEqual([5]); }); it('should parse simple range', () => { expect(parsePageRanges('1-3')).toEqual([1, 2, 3]); }); it('should parse multiple ranges and pages', () => { expect(parsePageRanges('1-3,5,7-9')).toEqual([1, 2, 3, 5, 7, 8, 9]); }); it('should handle open-ended range', () => { const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); const result = parsePageRanges('1-'); expect(result.length).toBe(10001); // 1 to 10001 inclusive expect(result[0]).toBe(1); expect(result[result.length - 1]).toBe(10001); expect(consoleWarnSpy).toHaveBeenCalledWith( expect.stringContaining('Open-ended range starting at 1 was truncated') ); consoleWarnSpy.mockRestore(); }); it('should deduplicate and sort pages', () => { expect(parsePageRanges('3,1,2,1,3')).toEqual([1, 2, 3]); }); it('should handle ranges with spaces', () => { expect(parsePageRanges(' 1 - 3 , 5 ')).toEqual([1, 2, 3, 5]); }); it('should throw on invalid range format', () => { expect(() => parsePageRanges('-5')).toThrow('Invalid page'); }); it('should throw on invalid page number', () => { expect(() => parsePageRanges('0')).toThrow('Invalid page number: 0'); expect(() => parsePageRanges('-1')).toThrow('Invalid page'); expect(() => parsePageRanges('abc')).toThrow('Invalid page number'); }); it('should throw on invalid range values', () => { expect(() => parsePageRanges('5-3')).toThrow('Invalid page range values'); expect(() => parsePageRanges('0-5')).toThrow('Invalid page range values'); }); it('should throw on empty or invalid input', () => { expect(() => parsePageRanges('')).toThrow('Invalid page'); }); }); describe('getTargetPages', () => { it('should return undefined when sourcePages is undefined', () => { expect(getTargetPages(undefined, 'test.pdf')).toBeUndefined(); }); it('should parse string ranges', () => { expect(getTargetPages('1-3,5', 'test.pdf')).toEqual([1, 2, 3, 5]); }); it('should validate array of numbers', () => { expect(getTargetPages([1, 3, 5], 'test.pdf')).toEqual([1, 3, 5]); }); it('should deduplicate array of numbers', () => { expect(getTargetPages([3, 1, 2, 1, 3], 'test.pdf')).toEqual([1, 2, 3]); }); it('should throw McpError on invalid page numbers in array', () => { expect(() => getTargetPages([1, 0, 3], 'test.pdf')).toThrow(McpError); expect(() => getTargetPages([1, 0, 3], 'test.pdf')).toThrow( 'Invalid page specification for source test.pdf' ); }); it('should throw McpError on non-integer page numbers', () => { expect(() => getTargetPages([1, 2.5, 3], 'test.pdf')).toThrow(McpError); expect(() => getTargetPages([1, 2.5, 3], 'test.pdf')).toThrow( 'Page numbers in array must be positive integers' ); }); it('should throw McpError on negative page numbers', () => { expect(() => getTargetPages([1, -1, 3], 'test.pdf')).toThrow(McpError); }); it('should throw McpError when result is empty after deduplication', () => { expect(() => getTargetPages([], 'test.pdf')).toThrow(McpError); expect(() => getTargetPages([], 'test.pdf')).toThrow( 'Page specification resulted in an empty set of pages' ); }); it('should throw McpError with proper error code', () => { try { getTargetPages([0], 'test.pdf'); expect.fail('Should have thrown'); } catch (error) { expect(error).toBeInstanceOf(McpError); expect((error as McpError).code).toBe(ErrorCode.InvalidParams); } }); it('should handle non-Error exceptions from parsePageRanges', () => { // This tests the String(error) path expect(() => getTargetPages('invalid-range', 'test.pdf')).toThrow(McpError); }); }); describe('determinePagesToProcess', () => { it('should filter valid target pages', () => { const result = determinePagesToProcess([1, 2, 5, 10, 15], 10, false); expect(result.pagesToProcess).toEqual([1, 2, 5, 10]); expect(result.invalidPages).toEqual([15]); }); it('should return all pages when includeFullText is true and no target', () => { const result = determinePagesToProcess(undefined, 5, true); expect(result.pagesToProcess).toEqual([1, 2, 3, 4, 5]); expect(result.invalidPages).toEqual([]); }); it('should return empty when no target and includeFullText is false', () => { const result = determinePagesToProcess(undefined, 10, false); expect(result.pagesToProcess).toEqual([]); expect(result.invalidPages).toEqual([]); }); it('should handle all target pages being invalid', () => { const result = determinePagesToProcess([11, 12, 13], 10, false); expect(result.pagesToProcess).toEqual([]); expect(result.invalidPages).toEqual([11, 12, 13]); }); it('should handle all target pages being valid', () => { const result = determinePagesToProcess([1, 2, 3], 10, false); expect(result.pagesToProcess).toEqual([1, 2, 3]); expect(result.invalidPages).toEqual([]); }); it('should work with target pages when includeFullText is true', () => { // Target pages override includeFullText const result = determinePagesToProcess([2, 4], 10, true); expect(result.pagesToProcess).toEqual([2, 4]); expect(result.invalidPages).toEqual([]); }); }); });

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/sylphxltd/pdf-reader-mcp'

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