Skip to content

Add immich.search.ocr tool for Immich 2.2+ OCR text search#7

Open
benjaminfrombe wants to merge 2 commits into
barryw:mainfrom
benjaminfrombe:feat/search-ocr-tool
Open

Add immich.search.ocr tool for Immich 2.2+ OCR text search#7
benjaminfrombe wants to merge 2 commits into
barryw:mainfrom
benjaminfrombe:feat/search-ocr-tool

Conversation

@benjaminfrombe
Copy link
Copy Markdown

Summary

  • New MCP tool immich.search.ocr that hits POST /api/search/smart with the ocr filter only (Immich 2.2+ OCR-in-image text index).
  • Adds Ocr field on SmartSearchRequest and makes Query nullable so the serializer omits it when only OCR is set.
  • Two new tests: payload shape and empty-text validation.

Why a separate tool

Keeps CLIP semantic search and OCR text search discoverable as distinct capabilities for the model. Both still go through /api/search/smart, so the underlying client stays unchanged.

Test plan

  • dotnet test passes (36/36) on .NET 10 SDK
  • Verified against a live Immich v2.7.5 server that {"ocr":"..."} is the correct payload shape (server-side BaseSearchSchema.ocr: z.string().optional()).

🤖 Generated with Claude Code

benjaminfrombe and others added 2 commits May 6, 2026 16:12
Exposes the new OCR text-in-image filter that Immich 2.2 added to the
/api/search/smart endpoint as a dedicated MCP tool, so the model can
discover OCR search as a distinct capability from CLIP semantic search.

- Add Ocr property to SmartSearchRequest (maps to the server-side
  BaseSearchSchema.ocr string field).
- Make Query nullable so the serializer omits it when only OCR is set
  (DefaultIgnoreCondition = WhenWritingNull).
- New SearchTools.OcrSearch tool with the same filter set as SmartSearch
  (paging, type, dates, location, camera, persons).
- Tests: verify payload contains the ocr field and not query; verify
  empty-text validation error.

Verified against a live Immich v2.7.5 server that {\"ocr\":\"...\"} on
/api/search/smart is the correct shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The smart endpoint requires a `query` (CLIP) or `queryAssetId`, so passing
only `ocr` returns 400 "Either `query` or `queryAssetId` must be set".

The metadata endpoint accepts the same `ocr` filter (defined on
BaseSearchSchema) and has no such requirement. Verified live against
Immich v2.7.5: POST /api/search/metadata with {"ocr":"Portefeuille"}
returns matched assets without any query.

Move the Ocr property from SmartSearchRequest to MetadataSearchRequest
and revert SmartSearchRequest.Query to its original non-nullable
default. OcrSearch tool now calls SearchMetadataAsync with WithExif=true
to match the existing MetadataSearch behaviour.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Copy link
Copy Markdown
Owner

@barryw barryw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this — nice clean feature addition that follows the existing patterns well.

A few things to address:

  1. PR description is misleading — The body says this "hits POST /api/search/smart with the ocr filter", but the code actually routes through SearchMetadataAsync which hits POST /api/search/metadata. The code is correct (OCR is a metadata search field in Immich's API), but the description should be updated to avoid confusing future readers.

  2. Tool name should use underscores — The tool is registered as immich.search.ocr with dots. We're moving to underscores for Claude Desktop compatibility (see PR #8 / #5), so this should be immich_search_ocr. Ideally this PR lands after the rename PR so everything stays consistent.

Code and tests look good otherwise — the validation, pagination, and response shaping all match the existing search tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants