A face detection and embedding extraction server using ONNX models with OpenTelemetry instrumentation
FaceTron exposes 4 tools via FastAPI HTTP endpoints. All tools have names and descriptions present in routes.py, but quality is inconsistent. Tool naming follows verb_noun convention adequately (get_models, infer, infer_visualize, download_image). However, descriptions are terse (avg ~50 chars, well below the 194 char production baseline), lacking WHEN/WHY context for LLM selection. Input schemas are declared in the form parameters (model_name, image_format, file) but lack formal JSON Schema documentation in the MCP registration layer, the schemas exist as FastAPI Form/File declarations but are not exposed as structured tool definitions for MCP clients. Parameter descriptions are sparse or missing entirely (e.g., 'file_path' in download_image has a description but lacks format/constraint detail). Error handling is minimal, HTTPException for 404 when model not found, but no guidance on recovery or alternative actions. Security concerns: the 'file_path' parameter in download_image uses string path input without visible path traversal protection (ALLOWED_EXTENSIONS check is present in code but not enforced in schema). Output schemas are not documented in tool definitions, responses are raw JSONResponse/FileResponse without structured metadata describing what fields agents should expect.
Downloads a previously saved image file
Retrieves list of available face embedding models
Performs face detection and embedding extraction on an uploaded image
Performs face detection and embedding extraction, then returns an annotated image with bounding boxes and face IDs
Tool descriptions are consistently below the 194 char production baseline (avg ~55 chars). Descriptions lack WHEN/WHY context, dependency hints, and clear output structure. LLMs cannot reliably select between tools without richer descriptions.
Input schemas lack formal JSON Schema declarations with type, enum, and pattern constraints. image_format parameter accepts free-form strings instead of constrained enum [jpg|jpeg|png]. model_name is unbounded string rather than enum of valid models. File size and dimension limits not declared.
Output schemas are completely undocumented in tool definitions. Responses like {"faces": results} do not specify the structure of 'results' array, field types, or required IDs for downstream chaining. Agents cannot plan multi-step operations without knowing output shape.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 44 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 44 | - | v1 |
download_image accepts file_path as free-form string without path traversal protection in schema. Although code checks ALLOWED_EXTENSIONS, the schema itself exposes no enum or regex constraint. Malicious agents could pass '../../../sensitive_file.jpg' if server-side validation is bypassed.
infer_visualize and infer produce different output structures (infer returns 'faces' array, infer_visualize returns 'saved_image_path' string) but have nearly identical names and responsibilities. Combined with naming confusion ('infer_visualize' suggests two actions), agents may choose wrong tool or fail to chain results.
Error handling is minimal. HTTPException(404, 'Model not found') provides no recovery guidance. LLMs receive bare errors with no hint to call get_models() first or suggest valid model names. Errors do not categorize as retryable vs fatal vs user-fixable.
infer_visualize is marked as WRITE (correct) but no confirmation or dry-run pattern documented. Agents can call it without preview, creating and storing images without recourse. No undo tool offered.
No pagination or result limiting pattern on get_models(). If model registry grows large, response could explode context window. No limit or cursor documented.