plain-sight
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@plain-sightDescribe this image in a detailed paragraph: /Users/me/photo.jpg"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Version: 1.1.0
An AI says what it sees. Generative image describer — MCP server + CLI wrapping Florence-2 (MIT) for prose descriptions, OCR, and LoRA-dataset caption sidecars. Runs locally, deterministic against a pinned model revision.
The sibling of ai-eyes-mcp:
ai-eyes-mcp | plain-sight | |
Job | judges images | describes images |
Model | SigLIP2 (discriminative) | Florence-2 (generative) |
Output | calibrated scores | prose / OCR / caption files |
Failure mode | can't narrate | can hallucinate detail |
Reach for it when | "does this image contain X?" | "what is in this image?" |
Honesty contract
Descriptions are generative: fluent, usually accurate, and capable of inventing
detail. plain-sight makes output reproducible — deterministic decoding against a
pinned model revision, so the same image yields the same caption — not
guaranteed true. For verifying a specific claim about an image, use
ai-eyes-mcp's image_verify; it measures, it doesn't narrate. The two tools are
different model families by design, so one can check the other.
Three specific limits, stated because they are easy to discover the hard way:
OCR cannot report the absence of text. Florence-2 emits a decoded string for every image, including images containing no text at all — a photograph may return
'2'. That output is lexically indistinguishable from a correct reading of a numeral. Every OCR result therefore carriesabsence_of_text_unreliable: true(MCP) or a[OCR_CAVEAT]line on stderr (CLI). plain-sight never suppresses or empties the result, because a short reading may be genuine — it tells you the signal does not exist.Captions describe; they do not verify. A confident sentence about an image is not evidence the thing described is present.
Reproducibility is per-revision. Pinning is what makes the determinism claim meaningful across time; see Provenance.
Related MCP server: fm-mcp-comfyui-bridge
Tools (MCP)
Tool | What it does |
| One image → prose description (3 detail tiers) |
| N images → |
| OCR — decode text from an image, with an absence caveat |
| Health check: model, device, resolved revision, loaded state |
| Describe bundled reference images, sanity-check output |
Every payload that carries model output also carries model_id and
revision_resolved — see Provenance.
Quick Start
pip install -e .
plain-sight-mcp # starts the STDIO MCP serverOr run as a module: python -m plain_sight
CLI
# One image, full paragraph
plain-sight describe hero.png
# One short sentence
plain-sight describe hero.png --detail low
# OCR (the absence caveat goes to stderr; the text goes to stdout)
plain-sight ocr screenshot.png
# See the plan before writing anything — no model load, no files
plain-sight batch ./dataset --prefix "mcpt_style, " --dry-run
# The dataset lane: caption a directory into .txt sidecars with a trigger token
plain-sight batch ./dataset --prefix "mcpt_style, " --detail high
# Record provenance for the run alongside it
plain-sight batch ./dataset --prefix "mcpt_style, " --manifest ./dataset-run.json
# Re-runs are idempotent — existing sidecars are skipped unless you --overwrite
plain-sight batch ./dataset --prefix "mcpt_style, " --overwritebatch flags: --detail · --prefix · --suffix · --out-dir · --overwrite
· --max-new-tokens · --manifest · --dry-run. Run plain-sight batch --help
for the full text; plain-sight --help documents exit codes and which stream
carries what.
What a long run looks like
Progress goes to stderr; results go to stdout, so
plain-sight describe x.png > caption.txt works.
plain-sight: loading florence-community/Florence-2-large rev=4271c66b… caption=4820 skip=0
(first caption includes model load, ~10s; first-ever run downloads ~1.5 GB)
[1/4820] wrote img_0001.txt
[heartbeat] 1840/4820 written=1801 skipped=32 failed=7 1.4 img/s ETA 35mThe load is announced before work begins, with the count of images that will actually be captioned, so a pause never appears mid-run. Skipped images are counted on the heartbeat rather than printed one line each — a re-run over a finished set is quiet. Failures stay one line each.
Claude Code config
{
"mcpServers": {
"plain-sight": {
"command": "plain-sight-mcp",
"env": {
"PLAIN_SIGHT_MODEL_DIR": "/path/to/model/cache"
}
}
}
}The caption contract (dataset lane)
Built for LoRA training sets (style-dataset-lab and friends):
Exact basename pairing:
img_0042.png→img_0042.txt. No counter suffix — unlike ComfyUI's SaveText node, which appends_00001.Bare concatenation: the sidecar contains
prefix + caption + suffixwith no delimiter injected. Want"mcpt_style, <caption>"? Put the comma-space in the prefix.Colliding stems are refused, never merged. Two images whose stems match —
img.pngandimg.jpgin one folder, or same-stem files from two folders under one--out-dir— would claim a single.txt. plain-sight refuses the whole batch before loading the model, names the offenders, and exits1. It will not rename a sidecar to dodge the clash: trainers pair by exact stem, so a rename would orphan the caption and leave the image uncaptioned.Writes are atomic. Each sidecar is written to a temp file in the same directory and moved into place, so an interrupt never leaves a partial caption at the final path. A sidecar that exists but is empty is treated as unfinished and re-captioned.
Idempotent re-runs: existing non-empty sidecars are skipped, and cost nothing, unless
--overwrite/overwrite=true.Deterministic:
do_sample=false+ beam search against a pinned revision — re-captioning an unchanged image reproduces the same text, so diffs mean something.
Provenance
The dataset lane produces training data. Six months on, the question is which weights produced which captions — so the answer travels with the output.
The model revision is pinned by default to
4271c66b88cdbc05735372ec13b2360108de5317. Without a pin, HuggingFace resolves to whatever the repository's default branch currently points at, and a silent retag would change captions under unchanged inputs. Override withPLAIN_SIGHT_MODEL_REVISION.Every output payload names the weights.
describe_image,read_text,describe_batch,sight_selftest, and the CLI's--jsonmodes and batch summary all carrymodel_idandrevision_resolved— the revision the loaded model actually reports, not the constant that was requested.sight_statusreports both, so a mismatch is visible.--manifest PATHwrites a run record — tool version, model id, requested and resolved revision, device, dtype, detail tier, prefix/suffix, per-image results and counts. Opt-in and never inferred: no manifest is written unless you pass a path, and a path that collides with a computed sidecar is refused. It contains a timestamp, so unlike the captions it is not byte-reproducible.
Detail tiers
Florence-2's native task ladder:
Tier | Task token | Output |
|
| one short sentence |
|
| a few sentences |
|
| a full paragraph |
high is a paragraph, not an essay — Florence-2 is a compact (0.77B) model.
Its edge is throughput and license, not art-critic depth. If a caption looks
truncated, raise max_new_tokens (default 1024, max 4096).
Configuration
Env Var | Default | Purpose |
|
| HuggingFace model |
|
| Model revision; the mechanism behind the reproducibility claim |
| HF default cache | Model cache directory |
|
| torch device |
|
|
|
|
| Default generation cap |
|
| Beam width (deterministic decoding) |
|
|
|
| unset | If truthy, load the model at server start |
Logging: stderr only (stdout is the MCP protocol channel), logger name
plain_sight. PLAIN_SIGHT_LOG_LEVEL is honoured on both surfaces.
Eager load: with PLAIN_SIGHT_EAGER_LOAD truthy, the MCP server loads at
start rather than on first call. A failure there never kills the server import —
it is reported by sight_status as eager_load_error and raised as a ToolError
on the first tool call that needs the model.
First call: the model loads lazily by default — the first describe/OCR call
loads Florence-2 (~10–20s on GPU; the first-ever call downloads ~1.5 GB).
Subsequent calls are ~1–2s per image at high detail on a modern GPU.
License posture
This tool: MIT.
The model: pinned to
florence-community/Florence-2-large— the official native-transformers conversion of Microsoft's Florence-2 release. MIT (hub license tag verified 2026-08-19). Commercial use clean.Why not
microsoft/Florence-2-large? Same weights, same MIT license, but the original repos ship pre-native configs that only load viatrust_remote_code— which this tool refuses on principle. The community conversion loads with transformers' built-in Florence-2 classes.Deliberately not offered: the Florence-2 fine-tune zoo (MiaoshouAI PromptGen, CogFlorence, SD3/Flux captioners, Castollux). Their licenses are unverified; they stay out until cleared. Overriding
PLAIN_SIGHT_MODEL_IDto one of them is possible but puts the license question on you.No remote code: the engine uses transformers' native Florence-2 support only —
trust_remote_codeis never passed, so no hub-fetched Python ever executes. This requirestransformers >= 4.51.
Security and Trust
This tool operates locally only.
Data touched: local image files (read-only); the HuggingFace model cache (written once on first download); and the files it writes —
.txtcaption sidecars, only where the caller asked (out_diror next to the image), plus one JSON manifest if and only if--manifest/manifest_pathsupplies an explicit path. Existing sidecars are replaced only under explicit--overwrite.No network egress at runtime — the model downloads once on first use, then all inference is local.
No remote code execution — native transformers classes only;
trust_remote_codeis never passed, so no hub-fetched Python ever executes.No secrets handling, no telemetry — nothing is read from or sent anywhere.
Structured errors only — raw stack traces never reach MCP clients or CLI users. CLI exit codes: 0 ok · 1 user error · 2 runtime error · 3 partial success.
Full policy: SECURITY.md. Actively maintained; supported versions listed there.
Requirements
Python >= 3.10
transformers >= 4.51(native Florence-2)CUDA GPU recommended (~2 GB VRAM at FP16); CPU fallback works (slower)
Model downloads ~1.5 GB on first use
Development
# Install in editable mode with dev dependencies
pip install -e ".[dev]"
# CI-safe suite (no model, no GPU) — this is what CI runs
pytest -m "not dogfood" -v
# Dogfood suite (real model + GPU, local only)
pytest -m dogfood -v
# Everything
pytest
# Full verify: imports, MCP tool surface, CI-safe tests, wheel + sdist build
bash verify.shTests select by marker, not by filename, so a new CI-safe test file is picked up
without touching CI. On Windows, a stale reparse point in the shared system temp
can break pytest's default temp root; verify.sh relocates it via
PYTEST_DEBUG_TEMPROOT, and pythonpath = ["."] keeps the console script and
python -m pytest in agreement.
Architecture
engine.py Standalone Florence-2 wrapper — no MCP dependency.
Lazy-loads the model; validation runs BEFORE the load.
Owns the provenance stamp and the shared logging setup.
Importable directly: from plain_sight.engine import Florence2Engine
sidecars.py The training-data contract, pure stdlib: basename pairing,
bare concatenation, collision detection, atomic writes,
directory expansion. Testable without torch.
server.py FastMCP wrapper exposing engine methods as MCP tools.
Thin layer: validation, error shaping, tool metadata.
cli.py argparse CLI over the same engine (describe / ocr / batch /
status / selftest). Structured errors, meaningful exit codes.The architecture is borrowed deliberately from
ai-eyes-mcp — same
engine/server split, same error shaping, same selftest pattern. A cloud
sibling of the same contract runs on Comfy Cloud as the
caption-florence2-v1 workflow (one-image-per-job metadata rider; this tool
is the bulk lane).
License
MIT
Built by MCP Tool Shop
Available Tools
5 toolsdescribe_batchDescribe BatchA
Blocks until every image completes -- roughly 1-2 s per image plus ~10-20 s if the model is not yet loaded. Chunk large sets. Existing sidecars are skipped unless overwrite=true, so a retry is cheap.
Caption a batch of images, writing .txt sidecars -- the dataset lane. The training-data contract: EXACT basename pairing (img_0042.png -> img_0042.txt, no counter suffix) and BARE prefix+caption+suffix concatenation (no delimiter injected).
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | Detail tier: 'low' | 'medium' | 'high' (default) | high |
| prefix | No | Text prepended to every caption, bare concatenation — include your own separator (e.g. 'mcpt_style, ') | |
| suffix | No | Text appended to every caption, bare concatenation | |
| out_dir | No | Directory for sidecar files (created if missing). Default: next to each image | |
| overwrite | No | Re-caption images whose sidecar already exists (default false: skip them, so re-runs are idempotent and cheap) | |
| image_paths | Yes | List of absolute image file paths (max 100) | |
| manifest_path | No | Optional explicit JSON provenance path. Default none — no manifest is written. Refused if it collides with a sidecar. | |
| max_new_tokens | No | Generation length cap (default 1024, max 4096) | |
| write_sidecars | No | Write each caption to <image-stem>.txt (exact basename pairing). When false, captions are returned in the response instead |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden and does so well: it discloses blocking behavior, per-image latency (~1-2 s plus ~10-20 s model load), idempotency via sidecar skipping, and the exact sidecar/manifest naming contract. These are behavioral traits an agent cannot infer from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight paragraphs, no filler, every clause earns its place. The purpose sentence is slightly buried behind the latency note, so the front-loading is not ideal, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, and the description still covers latency, idempotency, and the sidecar contract for a 9-parameter tool. The main omission is routing guidance versus describe_image and any failure/error behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters (prefix/suffix bare concatenation, overwrite skip semantics, manifest collision refusal) are already fully documented in the schema. Baseline 3 applies because the description largely restates those semantics rather than adding new parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Caption a batch of images, writing .txt sidecars') and the 'dataset lane' scope, which separates it from the singular describe_image sibling. It never names describe_image explicitly, so the differentiation rests on the word 'batch' rather than a direct contrast.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives operational guidance ('Chunk large sets', retries are cheap because existing sidecars are skipped), which implies when this tool is appropriate. It does not, however, state when to prefer describe_image or describe_batch, nor any preconditions beyond chunking.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_imageDescribe ImageA
Describe an image in prose — an AI says what it sees.
Uses Florence-2 (MIT-licensed, runs locally) with deterministic decoding: the same image at the same tier reproduces the same description.
Descriptions are generative and can hallucinate detail — for verifying a specific claim about the image, prefer ai-eyes-mcp's image_verify.
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | Detail tier: 'low' (one sentence), 'medium' (a few sentences), 'high' (full paragraph — default) | high |
| image_path | Yes | Absolute path to the image file | |
| max_new_tokens | No | Generation length cap (default 1024, max 4096) — raise if a high-detail caption looks truncated |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: it discloses local execution, licensing, deterministic decoding with reproducibility guarantees, and the hallucination risk inherent to generative captioning. It also explains the max_new_tokens escape hatch for truncated output — behavioral context no structured field provides.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose, then behavior, then the routing caveat in three tight paragraphs. The opening clause 'an AI says what it sees' is mildly redundant with the name but the rest earns its place with zero filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values need no explanation, and the tool is a single-shot read. The description covers execution model, reproducibility, failure mode, and the alternative tool — nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents detail tiers, image_path, and max_new_tokens semantics. The description only echoes the tier concept ('same image at the same tier') without adding syntax or format detail. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Describe an image in prose') and names the underlying mechanism (Florence-2, local, deterministic). It implicitly contrasts with read_text (OCR) and explicitly with image_verify, so an agent can distinguish it from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names when NOT to use it ('for verifying a specific claim about the image, prefer ai-eyes-mcp's image_verify') and explains the tier behavior that selects output depth. This is the when/when-not/alternative pattern at full strength.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_textRead TextA
Extract visible text from an image (Florence-2 task).
Returns the text the model reads off the pixels — signage, UI labels, documents. Like all generative output it can misread; treat low-stakes.
| Name | Required | Description | Default |
|---|---|---|---|
| image_path | Yes | Absolute path to the image file | |
| max_new_tokens | No | Generation length cap (default 1024, max 4096) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does real work: it discloses that output is generative, may misread, and is low-stakes. This is genuine behavioral context about reliability. It stops short of covering determinism, retry behavior, or failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short lines with the core action front-loaded. The model-task parenthetical and misread caveat are compact. Slightly fragmentary but nothing wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return shape need not be explained, and annotations are absent. The description covers purpose, examples, and the key reliability caveat for a 2-param generative tool. Adequate without being exhaustive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters (image_path, max_new_tokens) are already documented with defaults and limits. The description adds no parameter detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (extract) and resource (visible text from an image), and names the underlying model task (Florence-2 <OCR>). An agent can distinguish this from describe_image's broader captioning role by the scoped 'visible text' target.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage through examples (signage, UI labels, documents) but never explicitly states when to choose this over describe_image or describe_batch. No exclusions or routing guidance are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sight_selftestSight SelftestA
Self-test: describe the bundled reference images and confirm the outputs are sane (non-trivial, on-subject, tier ordering holds) — proves the install loaded correctly. Loads the model if it isn't already.
Returns {passed, checks: [{name, expected, measured, ok}], model_id, device, torch_version, transformers_version}.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden well: it discloses the side effect ('Loads the model if it isn't already') and enumerates the returned check structure. It does not mention cost, duration, or failure modes when checks fail, keeping it short of full transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action and the rationale, and every sentence adds information about scope, side effects, or output. The trailing return-value sentence slightly duplicates the existing output schema, which is the only waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter diagnostic with an output schema, the description covers what it does, why it exists, and the model-loading side effect. It could be more complete by stating what a failed test implies or recommending a follow-up action, but nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline of 4 applies; there is nothing for the description to disambiguate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource — run a self-test that describes bundled reference images and validates the outputs — and clarifies the goal ('proves the install loaded correctly'). It is clearly distinguishable from describe_image/describe_batch, though it never names those siblings directly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by 'proves the install loaded correctly', which suggests running it as a post-install verification, and it notes the side effect of loading the model. However, it does not tell the agent when to prefer this over the sibling sight_status or when not to run it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sight_statusSight StatusA
Check plain-sight server status.
Returns model info, device, and whether the model is currently loaded. The model loads lazily on first tool call — this tool does NOT trigger loading.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose a genuinely useful behavior: the model loads lazily and this call deliberately avoids triggering that load. That is a real side-effect disclosure an agent needs. It stops short of stating whether the call has any other cost or failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the purpose and followed by return contents and the key caveat. No filler, every sentence carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the description needn't restate return values, and the one non-obvious behavior (lazy loading, no load triggered) is covered. It could have pointed to sight_selftest as the follow-up, but nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing to document; baseline for a no-parameter tool is 4. The description correctly adds no parameter noise.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Check plain-sight server status') and enumerates what comes back (model info, device, load state). It distinguishes itself from the describe/read siblings by being a diagnostic call, though it doesn't explicitly contrast with sight_selftest.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The note that the tool does NOT trigger loading implicitly tells the agent when to prefer it (a non-invasive status check), but there is no explicit when-to-use statement nor a routing hint toward sight_selftest for deeper diagnostics. Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v1.1.0- First observed
describe_batch - First observed
describe_image - First observed
read_text - First observed
sight_selftest - First observed
sight_status
TDQS
Scored across 5 tools
Tools have distinct purposes: single image description, batch captioning with sidecars, OCR, status check, and self-test. The only mild overlap is between describe_image and describe_batch, but the sidecar/dataset contract and blocking behavior make them clearly separable.
Three tools follow verb_noun (describe_image, describe_batch, read_text) while two follow noun_noun with a sight_ prefix (sight_status, sight_selftest). The split is readable but not a single consistent pattern.
Five tools is well within the ideal range for a focused image description/OCR server; each tool has a clear role and none feels redundant.
Core workflows are covered: single and batch description, OCR, status, and self-test. Minor gaps exist, such as no explicit tier selection tool or a way to get batch captions without writing sidecars, but these are workable.
Maintenance
Related MCP Connectors
MCP server for Qwen Image 3 AI image generation
MCP server for Flux AI image generation
Focused MCP server for OpenAI image/audio generation (v2.0.0). Wraps endpoints via HAPI CLI.
MCP server for Grok Imagine AI video generation
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn MCP server that enables any LLM to describe images from file paths, URLs, or base64 data by forwarding them to a supported vision provider such as OpenAI, Anthropic, or local Ollama models.624 npm10MIT
- AlicenseAqualityDmaintenanceMCP server that provides image generation, captioning, and tagging via ComfyUI API, configurable for agent tools.43MIT
- FlicenseNot gradedqualityCmaintenanceMCP server for local image generation using FLUX.2 via Hugging Face diffusers, designed to run on a Windows GPU and be called remotely by Claude Cowork over Tailscale.-
- AlicenseNot gradedqualityCmaintenanceA local MCP server that gives LLMs eyes for images by performing object detection (YOLOv8) and text recognition (EasyOCR), outputting descriptive statements about objects and text positions without any API key or cloud dependency.MIT