Skip to content

MCP server — contract

The post-implementation contract for iiiris's Model Context Protocol server (roadmap 2.0-era platform glue). Operator/consumer how-to lives in ../mcp.md; this file is the durable "what this subsystem guarantees" a re-implementation must satisfy.

What it does

iiiris exposes its read-only IIIF capabilities to MCP hosts (Claude Desktop/Code, the Claude API remote-MCP connector) over a single Streamable HTTP endpoint at /mcp. An agent can browse a source, read image metadata, render image regions (returned as pictures), and read Presentation manifests/collections — as MCP tools plus a manifest resource template. The surface is off by default and enforces the same IIIF Auth as the Image API.

Surface

HTTP route

Method Path Purpose
POST/GET/DELETE /mcp MCP Streamable HTTP endpoint (the SDK handler dispatches by method)

Mounted only when mcp.enabled.

Config

mcp:
  enabled: false   # default false; true mounts /mcp

mcp.enabled is the only field; it maps to server.Deps.MCPEnabled. Off by default (a new protocol surface and dependency).

Tools

Tool Input Result
browse path (empty = root) JSON entries {identifier, name, type}, typeimage|collection
get_image_info identifier JSON {identifier, width, height, formats, qualities, maxWidth, maxHeight}
get_region identifier, region, size, rotation, quality, format (IIIF Image API 3.0 grammar; empty → full/max/0/default/jpg) an MCP image content block
get_manifest identifier Presentation JSON (stored served as-is, or derived)

Resources

A resource template iiiris:///presentation/{+identifier} (RFC 6570 reserved expansion, so the identifier may contain slashes). Reading a matching URI returns the manifest as application/ld+json.

Public Go API — internal/mcp

The only consumer of github.com/modelcontextprotocol/go-sdk (pinned). Pure protocol glue over a Backend interface the server layer implements:

  • NewHandler(backend Backend, version string, baseURL func(*http.Request) string) http.Handler
  • BackendBrowse / ImageInfo / Region / Manifest, each taking the originating *http.Request; plus the Entry, ImageInfo, RegionSelector types.

Contracts

  • Off by default, opt-in. /mcp mounts only when mcp.enabled: true. Nothing under mcp: is required; the zero-config, Image, Presentation, and Content-State paths are unaffected whether MCP is on or off.
  • Single SDK consumer. github.com/modelcontextprotocol/go-sdk is imported only by internal/mcp (mirrors govipsinternal/image, prometheusinternal/metrics). The version is pinned; SDK/spec churn is contained to this one package.
  • Read-only, stateless. No tool mutates state. The endpoint runs in the SDK's stateless Streamable HTTP mode (no session tracking).
  • Tools reuse the IIIF core. Tool handlers wrap the existing resolve/probe/render/list and Presentation serve/derive primitives — they do not re-derive IIIF behaviour. get_region enforces the same pipeline limits (maxWidth/maxHeight/maxArea) as the Image API; identifiers returned by browse are the identifiers the other tools accept.
  • Auth is enforced, not bypassed. Every tool and the resource read route through the configured auth.Authorizer, evaluated against the credentials on the /mcp request (an MCP host presents its IIIF access token as a Bearer token or session cookie — the same token the Image API accepts). No separate MCP credential, no extra config. A gated identifier is denied (get_image_info/get_region/get_manifest return an error result); browse omits entries the caller can't access. With the zero-config AllowAll authorizer nothing is gated.
  • Per-request server. The MCP server is rebuilt per HTTP request (in the Streamable HTTP getServer closure), so each tool/resource handler closes over that request's public base URL (for canonical URLs) and its credentials (for auth). internal/mcp forwards the request; the server-side Backend owns authorization.
  • Manifest resource ≡ tool. The iiiris:///presentation/{+identifier} resource read reuses Backend.Manifest, so it is authorised and derive-capable identically to get_manifest; no duplicated logic.
  • Honesty gate. A source without listing support reports a browse error rather than an empty listing; capabilities advertised (get_image_info formats/qualities) come from the same single-sourced v3 slices info.json uses.

Out of scope

  • Write tools (ingest, annotate) — stateful; roadmap Phase 3.
  • stdio transport — iiiris is a networked server; only Streamable HTTP is served.
  • Prompts primitive — no templated-workflow surface is offered.
  • Presentation 2.1 over MCPget_manifest and the manifest resource emit 3.0 only.
  • Full-tree resource enumeration — manifests are addressable via the template; discovery of which identifiers exist is via browse, not a server-enumerated resource list.
  • MCP client — iiiris is an MCP server; it does not call out to MCP servers.