MCP (Model Context Protocol) server for IIIF (International Image Interoperability Framework) integration.
npm install npm run buildSingle-file Bundle (v1.1.0+)
npm run bundle # Creates iiif-mcp-bundle.js - no npm install needed for deployment
Add to your MCP client configuration:
{ "mcpServers": { "iiif": { "command": "node", "args": ["/path/to/mcp_iiif/dist/index.js"] } } }Single-file Bundle (v1.1.0+)
{ "mcpServers": { "iiif": { "command": "node", "args": ["/path/to/iiif-mcp-bundle.js"] } } }Structured Output Support
All tools now support a structured
parameter that returns JSON data instead of formatted text. This enables better integration with other MCP servers and programmatic processing.
// 1. Get structured image URL from IIIF MCP Server const imageResult = await iiifServer.callTool('iiif-image', { imageUrl: 'https://iiif.lib.ncsu.edu/iiif/technician-basketballpreview-1997-11-10_0001', region: 'pct:25,25,50,50', size: '500,', quality: 'gray', format: 'png', structured: true }); // 2. Parse the structured result const imageData = JSON.parse(imageResult); // { // "url": "https://iiif.lib.ncsu.edu/iiif/.../pct:25,25,50,50/500,/0/gray.png", // "metadata": { // "suggested_filename": "technician_preview_crop_gray.png", // "original_id": "technician-basketballpreview-1997-11-10_0001" // } // } // 3. Pass to download MCP server const downloadResult = await downloadServer.callTool('download_image', { url: imageData.url, filename: imageData.metadata.suggested_filename });✅ iiif-image-fetch (v1.1.0)
Fetch actual IIIF image data with automatic size constraints.
Parameters:
imageUrl
(string, required): Image API base URL (e.g., "https://example.org/iiif/image123")region
(string, optional): Image region - "full" (default), "square", "x,y,w,h", or "pct:x,y,w,h"size
(string, optional): Image size - "max" (default), "w,", ",h", "pct:n", "w,h", or "!w,h"rotation
(string, optional): Rotation - "0" (default) to "359", optionally prefixed with "!" for mirroringquality
(string, optional): Image quality - "default", "color", "gray", or "bitonal"format
(string, optional): Output format - "jpg" (default), "png", "webp", "tif", "gif", or "pdf"maxDimension
(number, optional): Maximum dimension constraint (default: 1500)maxPixels
(number, optional): Maximum total pixels (default: 1000000)Example:
{ "tool": "iiif-image-fetch", "arguments": { "imageUrl": "https://iiif.lib.ncsu.edu/iiif/technician-basketballpreview-1997-11-10_0001", "region": "pct:25,25,50,50", "size": "800,", "format": "png" } }
Response: Returns image data as Base64-encoded blob with MIME type and original URL.
✅ iiif-manifest-canvases (v1.1.0)List all canvases within a IIIF manifest.
Parameters:
manifestUrl
(string, required): The URL of the IIIF manifestfilter
(object, optional): Filtering options
hasImage
(boolean): Only include canvases with imageshasAnnotation
(boolean): Only include canvases with annotationslabelPattern
(string): Regular expression to filter by labelincludeMetadata
(boolean, optional): Include canvas metadata (default: false)includeThumbnail
(boolean, optional): Include thumbnail URLs (default: true)structured
(boolean, optional): Return structured JSON dataExample:
{ "tool": "iiif-manifest-canvases", "arguments": { "manifestUrl": "https://d.lib.ncsu.edu/collections/catalog/technician-basketballpreview-1997-11-10/manifest.json", "filter": { "hasAnnotation": true } } }✅ iiif-canvas-info (v1.1.0)
Get detailed information about a specific canvas.
Parameters:
manifestUrl
(string, required): The URL of the IIIF manifestcanvasId
(string, optional): Canvas ID (if omitted, returns first canvas)canvasIndex
(number, optional): Canvas index (0-based)includeAnnotations
(boolean, optional): Include annotation details (default: true)includeImageInfo
(boolean, optional): Fetch Image API info.json (default: false)includeStructures
(boolean, optional): Include structural information (default: false)structured
(boolean, optional): Return structured JSON dataExample:
{ "tool": "iiif-canvas-info", "arguments": { "manifestUrl": "https://d.lib.ncsu.edu/collections/catalog/technician-basketballpreview-1997-11-10/manifest.json", "canvasIndex": 0, "includeImageInfo": true } }
Response: Returns detailed canvas information including dimensions, associated images, annotations, and metadata.
Search within IIIF resources using the Content Search API.
Parameters:
searchServiceUrl
(string, required): The URL of the IIIF Content Search service endpointquery
(string, required): The search query stringstructured
(boolean, optional): Return structured JSON data instead of formatted textExample:
{ "tool": "iiif-search", "arguments": { "searchServiceUrl": "https://iiif.lib.harvard.edu/manifests/drs:48309543/svc/searchwithin", "query": "Paris" } }
Response: Returns formatted search results including:
Retrieve manifest metadata from IIIF Presentation API.
Parameters:
manifestUrl
(string, required): The URL of the IIIF manifestproperties
(array, optional): Specific properties to retrieve. Options include:
label
: Title of the resourceid
: Unique identifiertype
: Resource typesummary
: Description (v3) or description (v2)metadata
: Descriptive metadata pairsrights
: Rights/license informationprovider
: Provider informationviewingDirection
: Reading directionitems
: Canvas/page informationstructures
: Table of contentsthumbnail
: Thumbnail image URLstructured
(boolean, optional): Return structured JSON data instead of formatted textRetrieve and navigate IIIF collections with support for hierarchical structures.
Parameters:
collectionUrl
(string, required): The URL of the IIIF collectionincludeItems
(boolean, optional): Include detailed list of collection items (default: true)structured
(boolean, optional): Return structured JSON data instead of formatted textExample:
{ "tool": "iiif-collection", "arguments": { "collectionUrl": "https://iiif.bodleian.ox.ac.uk/iiif/collection/top", "includeItems": true } }
Response:
Build IIIF Image API URLs and retrieve image information.
Parameters:
imageUrl
(string, required): Base URL of the IIIF image (without parameters)region
(string, optional): Image region (full, square, x,y,w,h, or pct:x,y,w,h)size
(string, optional): Image size (max, w,h, w,, ,h, pct:n, or !w,h)rotation
(string, optional): Rotation in degrees (0-360, optionally prefixed with ! for mirroring)quality
(string, optional): Image quality (default, color, gray, bitonal)format
(string, optional): Image format (jpg, tif, png, gif, jp2, pdf, webp)info
(boolean, optional): If true, retrieve image information instead of building URLstructured
(boolean, optional): Return structured JSON data instead of formatted textExample:
{ "tool": "iiif-image", "arguments": { "imageUrl": "https://ids.lib.harvard.edu/ids/iiif/47174896", "region": "1000,2000,3000,4000", "size": "500,", "rotation": "90", "quality": "gray", "format": "jpg" } }
Response:
info: true
: Returns formatted image information including dimensions, available sizes, tile information, and supported featuresExtract and analyze annotations from IIIF resources, including text transcriptions, translations, and commentary.
Parameters:
source
(string, required): Either an annotation URL or a manifest URL to extract annotations fromlanguage
(string, optional): Filter annotations by language code (e.g., "en", "fr")groupByCanvas
(boolean, optional): Group annotations by their target canvasincludeNonText
(boolean, optional): Include non-text annotations in the resultsstructured
(boolean, optional): Return structured JSON data instead of formatted textExample:
{ "tool": "iiif-annotation", "arguments": { "source": "https://example.org/manifest.json", "language": "en", "groupByCanvas": true } }
Response:
Track changes and updates to IIIF resources using the Change Discovery API.
Parameters:
activityStreamUrl
(string): The URL of the IIIF Activity Stream (OrderedCollection)pageUrl
(string): The URL of a specific activity page (OrderedCollectionPage)structured
(boolean, optional): Return structured JSON data instead of formatted textNote: Either activityStreamUrl
or pageUrl
must be provided.
Example:
{ "tool": "iiif-activity", "arguments": { "activityStreamUrl": "https://example.org/activity-stream" } }
Response:
Extract and analyze audio/video content from IIIF manifests.
Parameters:
manifestUrl
(string, required): The URL of the IIIF manifest containing A/V contentincludeRanges
(boolean, optional): Include structural ranges/chapters in the outputstructured
(boolean, optional): Return structured JSON data instead of formatted textExample:
{ "tool": "iiif-av", "arguments": { "manifestUrl": "https://example.org/av-manifest.json", "includeRanges": true } }
Response:
Full authentication support for IIIF resources with session management and protected content access.
Parameters:
action
(string, required): The authentication action to perform
info
: Get authentication requirements without logging inauthenticate
: Perform authentication with credentialsprobe
: Check access to a resourcelogout
: End authentication sessionget-protected
: Fetch protected resource with active sessionresourceUrl
(string, required): The URL of the IIIF resourceusername
(string, optional): Username for authentication (when action is authenticate
)password
(string, optional): Password for authentication (when action is authenticate
)token
(string, optional): Manually provide an access token (when action is authenticate
)sessionId
(string, optional): Manually provide a session ID (when action is authenticate
)interactive
(boolean, optional): Use interactive browser-based authentication (when action is authenticate
)structured
(boolean, optional): Return structured JSON data instead of formatted textExamples:
{ "tool": "iiif-auth", "arguments": { "action": "info", "resourceUrl": "https://example.org/protected-manifest.json" } }
{ "tool": "iiif-auth", "arguments": { "action": "authenticate", "resourceUrl": "https://example.org/protected-manifest.json", "username": "testuser", "password": "testpass" } }
{ "tool": "iiif-auth", "arguments": { "action": "authenticate", "resourceUrl": "https://example.org/protected-manifest.json", "interactive": true } }
{ "tool": "iiif-auth", "arguments": { "action": "authenticate", "resourceUrl": "https://example.org/protected-manifest.json", "token": "your-access-token-here" } }
{ "tool": "iiif-auth", "arguments": { "action": "probe", "resourceUrl": "https://example.org/protected-manifest.json" } }
{ "tool": "iiif-auth", "arguments": { "action": "get-protected", "resourceUrl": "https://example.org/protected-manifest.json" } }
Features:
⚠️ CLI Authentication Limitations:
Due to the nature of command-line environments, browser-based authentication has inherent limitations:
Cookie Isolation: Browser authentication sessions cannot be shared with the CLI process
IIIF Authentication Design: The IIIF Auth API was designed for browser-based viewers
Recommended Authentication Methods for CLI:
Direct Authentication (Preferred for CLI):
{ "action": "authenticate", "resourceUrl": "https://example.org/protected-manifest.json", "username": "your-username", "password": "your-password" }
Manual Token Authentication:
{ "action": "authenticate", "resourceUrl": "https://example.org/protected-manifest.json", "token": "your-access-token" }
Interactive Browser Authentication (Limited Support):
Testing with IIIF Auth Demonstrator:
https://iiifauth.digtest.co.uk/
username=username, password=password
https://iiifauth.digtest.co.uk/manifestcookie.json
For Full Authentication Support: Consider using browser-based IIIF viewers (Mirador, Universal Viewer) which can properly handle the complete IIIF authentication flow with cookies and postMessage.
🚧 iiif-range (Coming Soon)Navigate structural ranges (chapters, sections) within IIIF resources.
Planned Parameters:
manifestUrl
(string, required): URL of the manifestrangeId
(string, optional): Specific range to retrievenpm run dev # Run in development mode npm test # Run testsAuthentication and Protected Resources
// Check if a resource requires authentication const authInfo = await client.callTool('iiif-auth', { action: 'info', resourceUrl: 'https://iiifauth.digtest.co.uk/manifestcookie.json' }); // Authenticate with credentials const session = await client.callTool('iiif-auth', { action: 'authenticate', resourceUrl: 'https://iiifauth.digtest.co.uk/manifestcookie.json', username: 'username', password: 'password' }); // Check access to protected resource const access = await client.callTool('iiif-auth', { action: 'probe', resourceUrl: 'https://iiifauth.digtest.co.uk/manifestcookie.json' }); // Get protected content after authentication const protectedData = await client.callTool('iiif-auth', { action: 'get-protected', resourceUrl: 'https://iiifauth.digtest.co.uk/manifestcookie.json' }); // Logout when done await client.callTool('iiif-auth', { action: 'logout', resourceUrl: 'https://iiifauth.digtest.co.uk/manifestcookie.json' });Search within a IIIF resource
// Search for "Paris" in a Harvard manuscript const result = await client.callTool('iiif-search', { searchServiceUrl: 'https://iiif.lib.harvard.edu/manifests/drs:48309543/svc/searchwithin', query: 'Paris' }); // Search in NC State University collections const result = await client.callTool('iiif-search', { searchServiceUrl: 'https://ocr.lib.ncsu.edu/search/technician-basketballpreview-1997-11-10', query: 'basketball' }); // Get structured search results for processing const structuredResult = await client.callTool('iiif-search', { searchServiceUrl: 'https://ocr.lib.ncsu.edu/search/technician-basketballpreview-1997-11-10', query: 'basketball', structured: true }); // Returns JSON with results array, total count, etc.
// Retrieve all metadata for a specific manifest const manifest = await client.callTool('iiif-manifest', { manifestUrl: 'https://d.lib.ncsu.edu/collections/catalog/technician-basketballpreview-1997-11-10/manifest.json' }); // Retrieve specific properties only const manifest = await client.callTool('iiif-manifest', { manifestUrl: 'https://iiif.bodleian.ox.ac.uk/iiif/manifest/e32a277e-91e2-4a6d-8ba6-cc4bad230410.json', properties: ['label', 'metadata', 'items'] }); // Get structured manifest data for processing const structuredManifest = await client.callTool('iiif-manifest', { manifestUrl: 'https://d.lib.ncsu.edu/collections/catalog/technician-basketballpreview-1997-11-10/manifest.json', structured: true }); // Returns JSON with images array, metadata, thumbnail URL, etc.Retrieve a specific image region
// Get a 500px wide crop of a specific region const image = await client.callTool('iiif-image', { imageUrl: 'https://ids.lib.harvard.edu/ids/iiif/47174896', region: '1000,2000,3000,4000', size: '500,', format: 'jpg' }); // Get image information const info = await client.callTool('iiif-image', { imageUrl: 'https://ids.lib.harvard.edu/ids/iiif/47174896', info: true }); // Get structured image URL with metadata const structuredImage = await client.callTool('iiif-image', { imageUrl: 'https://ids.lib.harvard.edu/ids/iiif/47174896', region: '1000,2000,3000,4000', size: '500,', format: 'jpg', structured: true }); // Returns JSON with URL, suggested filename, parameters, etc.Navigate IIIF collections
// Get top-level collection const collection = await client.callTool('iiif-collection', { collectionUrl: 'https://iiif.bodleian.ox.ac.uk/iiif/collection/top' }); // Get collection without detailed item listing const summary = await client.callTool('iiif-collection', { collectionUrl: 'https://iiif.bodleian.ox.ac.uk/iiif/collection/top', includeItems: false }); // Get structured collection data for processing const structuredCollection = await client.callTool('iiif-collection', { collectionUrl: 'https://digital.library.yale.edu/collections/iiif', structured: true }); // Returns JSON with sub-collections and manifests arrays
// Extract all text annotations from a manifest const annotations = await client.callTool('iiif-annotation', { source: 'https://example.org/manifest-with-transcriptions.json' }); // Filter annotations by language const frenchAnnotations = await client.callTool('iiif-annotation', { source: 'https://gallica.bnf.fr/iiif/ark:/12148/btv1b8449691v/manifest.json', language: 'fr' }); // Get structured annotation data for processing const structuredAnnotations = await client.callTool('iiif-annotation', { source: 'https://example.org/annotations/list1.json', structured: true }); // Returns JSON with full text, language breakdown, and annotation metadata
// Get activity stream overview const activities = await client.callTool('iiif-activity', { activityStreamUrl: 'https://example.org/activity-stream' }); // Fetch a specific page of activities const page = await client.callTool('iiif-activity', { pageUrl: 'https://example.org/activity-stream/page/1' }); // Get structured activity data for processing const structuredActivities = await client.callTool('iiif-activity', { pageUrl: 'https://example.org/activity-stream/page/1', structured: true }); // Returns JSON with activities array, pagination info, etc.Process audio/video content
// Extract A/V content from a manifest const avContent = await client.callTool('iiif-av', { manifestUrl: 'https://example.org/av-manifest.json' }); // Include chapter/range information const avWithChapters = await client.callTool('iiif-av', { manifestUrl: 'https://example.org/lecture-recording.json', includeRanges: true }); // Get structured A/V data for processing const structuredAV = await client.callTool('iiif-av', { manifestUrl: 'https://example.org/video-collection.json', structured: true }); // Returns JSON with media items, durations, dimensions, etc.
This server implements tools based on the following IIIF specifications:
{ "url": "https://ocr.lib.ncsu.edu/search/...", "service_url": "https://ocr.lib.ncsu.edu/search/...", "query": "basketball", "total_results": 24, "api_version": "http://iiif.io/api/search/0/context.json", "results": [ { "id": "urn:ocracoke:...", "type": "oa:Annotation", "label": "Page 1", "matches": [ { "text": "basketball", "context": "NC State [basketball] team..." } ] } ] }
{ "url": "https://d.lib.ncsu.edu/.../manifest", "id": "https://d.lib.ncsu.edu/.../manifest", "type": "sc:Manifest", "label": "Technician Basketball Preview", "thumbnail": "https://iiif.lib.ncsu.edu/.../thumbnail.jpg", "images": [ { "id": "https://d.lib.ncsu.edu/.../canvas/page_0001", "label": "[1]", "width": 3573, "height": 4425 } ], "metadata": [ { "label": "Creator", "value": "Technician (Raleigh, N.C.)" } ] }
{ "url": "https://iiif.lib.ncsu.edu/.../pct:25,25,50,50/500,/0/gray.png", "base_url": "https://iiif.lib.ncsu.edu/.../image_0001", "parameters": { "region": "pct:25,25,50,50", "size": "500,", "rotation": "0", "quality": "gray", "format": "png" }, "metadata": { "suggested_filename": "image_0001_crop_gray.png", "original_id": "image_0001" } }
{ "url": "https://iiif.bodleian.ox.ac.uk/iiif/collection/top", "id": "https://iiif.bodleian.ox.ac.uk/iiif/collection/top", "type": "Collection", "label": "Bodleian Libraries: Top Collection", "total_items": 25, "collections": [ { "id": "https://iiif.bodleian.ox.ac.uk/.../medieval", "type": "Collection", "label": "Medieval Manuscripts" } ], "manifests": [ { "id": "https://iiif.bodleian.ox.ac.uk/.../ms-canon-misc-213", "type": "Manifest", "label": "MS. Canon. Misc. 213", "navDate": "1450-01-01" } ], "partOf": [ { "id": "https://iiif.bodleian.ox.ac.uk/.../parent", "label": "Parent Collection" } ] }
{ "url": "https://example.org/annotations/list1", "total_annotations": 15, "languages": ["en", "fr"], "motivations": ["painting", "commenting", "transcribing"], "annotations": [ { "id": "https://example.org/annotation/1", "type": "Annotation", "motivation": ["transcribing"], "text": "This is the transcribed text from the manuscript", "language": "en", "format": "text/plain", "target": "https://example.org/canvas/1#xywh=100,100,500,300" } ], "text_content": { "full_text": "This is the transcribed text from the manuscript...", "by_language": { "en": ["This is the transcribed text..."], "fr": ["Ceci est le texte transcrit..."] } } }Activity Stream Structure
{ "url": "https://example.org/activity-stream/page/1", "type": "OrderedCollectionPage", "page_info": { "current_page": "https://example.org/activity-stream/page/1", "next_page": "https://example.org/activity-stream/page/2", "prev_page": "https://example.org/activity-stream/page/0", "part_of": "https://example.org/activity-stream", "start_index": 0 }, "activities": [ { "id": "https://example.org/activity/1", "type": "Update", "object_id": "https://example.org/manifest/1", "object_type": "Manifest", "canonical_uri": "https://example.org/iiif/manifest/1", "timestamp": "2024-01-15T10:00:00Z", "summary": "Manifest metadata updated" }, { "id": "https://example.org/activity/2", "type": "Create", "object_id": "https://example.org/collection/1", "object_type": "Collection", "timestamp": "2024-01-14T15:30:00Z" } ] }
{ "url": "https://example.org/av-manifest", "id": "https://example.org/av-manifest", "type": "Manifest", "label": "Lecture Recording", "total_duration": 3600, "media_items": [ { "id": "https://example.org/lecture-part1.mp4", "type": "Video", "format": "video/mp4", "label": "Part 1: Introduction", "duration": 1200, "dimensions": { "width": 1920, "height": 1080 }, "canvas_id": "https://example.org/canvas/1" }, { "id": "https://example.org/lecture-part2.mp4", "type": "Video", "format": "video/mp4", "label": "Part 2: Main Content", "duration": 2400, "dimensions": { "width": 1920, "height": 1080 }, "canvas_id": "https://example.org/canvas/2" } ], "ranges": [ { "id": "https://example.org/range/intro", "label": "Introduction", "start_time": 0, "end_time": 300, "items": ["https://example.org/canvas/1"] }, { "id": "https://example.org/range/main", "label": "Main Presentation", "start_time": 300, "end_time": 3600, "items": ["https://example.org/canvas/1", "https://example.org/canvas/2"] } ] }
{ "resource_url": "https://example.org/protected-manifest.json", "requires_auth": true, "auth_api_version": "v2", "login_services": [ { "id": "https://example.org/auth/login", "profile": "http://iiif.io/api/auth/2/login", "label": "Login to Example Library", "header": "Please authenticate", "description": "Access requires institutional login", "confirm_label": "Login", "auth_api_version": "v2" } ], "token_services": [ { "id": "https://example.org/auth/token", "profile": "http://iiif.io/api/auth/2/token", "auth_api_version": "v2" } ], "logout_services": [ { "id": "https://example.org/auth/logout", "profile": "http://iiif.io/api/auth/2/logout", "label": "Logout", "auth_api_version": "v2" } ], "probe_services": [], "auth_services": [ // Complete list of all auth-related services ] }Authentication Session Response
{ "success": true, "session": { "resourceUrl": "https://example.org/protected-manifest.json", "authType": "cookie", "expiresAt": "2024-01-15T11:00:00Z", "hasToken": false, "hasCookie": true } }
{ "resourceUrl": "https://example.org/protected-manifest.json", "hasAccess": true }
When implementing new features:
For detailed information about planned improvements and architectural enhancements, see FUTURE_ENHANCEMENTS.md.
Key areas under consideration:
MIT
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4