Skip to content

fix: pass mime_type from Bricks API to Kreuzberg for correct file type detection#37

Merged
Kaiohz merged 2 commits into
mainfrom
fix/simplify-mcp-tool-response
May 20, 2026
Merged

fix: pass mime_type from Bricks API to Kreuzberg for correct file type detection#37
Kaiohz merged 2 commits into
mainfrom
fix/simplify-mcp-tool-response

Conversation

@Kaiohz
Copy link
Copy Markdown
Collaborator

@Kaiohz Kaiohz commented May 20, 2026

Summary

  • Pass mime_type from Bricks API through download_documentReadBricksDocumentUseCaseKreuzbergAdapter.extract_contentextract_file(mime_type=...)
  • Kreuzberg supports mime_type parameter to override format detection — no need to rely on temp file extension
  • Fixes ValidationError: Unknown extension: ._pdf caused by S3 URL paths producing malformed extensions
  • Add _normalize_extension as safety net for future edge cases
  • Update BricksApiPort.download_document signature: (bytes, str)(bytes, str, str) (data, filename, mime_type)
  • Update DocumentReaderPort.extract_content signature: add optional mime_type param

Test plan

  • 441 unit tests passing
  • New: TestNormalizeExtension (6 tests), test_extract_content_passes_mime_type, test_extract_content_without_mime_type, test_execute_passes_mime_type_to_document_reader

Kaiohz added 2 commits May 20, 2026 13:11
- Replace BricksDocumentInfo (16 fields) with DocumentSummary (5 fields) in list_bricks_documents
- Bedrock returns 400 'compiled grammar is too large' when tool schemas are too complex
- Only expose what the LLM needs: id, file_name, mime_type, size, status
…e detection

Instead of relying on the temp file extension (which was producing ._pdf
from S3 URL paths), pass the mime_type directly to Kreuzberg's extract_file()
which supports a mime_type parameter for format override. Also adds
_normalize_extension as a safety net for malformed extensions.
Copy link
Copy Markdown
Collaborator Author

@Kaiohz Kaiohz left a comment

Choose a reason for hiding this comment

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

Review PR #37 — fix: pass mime_type from Bricks API to Kreuzberg

Score : 8/10 🟢


✅ Ce qui est excellent

  1. Propagation du mime_type bout en bout — Le flux est clean et logique : BricksApiAdapter.download_documentReadBricksDocumentUseCaseKreuzbergAdapter.extract_contentextract_file(mime_type=...). Chaque couche fait son job, pas de court-circuit.

  2. DocumentSummary Pydantic model — Remplacer le list non typé par un modèle structuré sur list_bricks_documents est un vrai plus pour les consumers MCP. Ça donne de l'autocomplétion et de la validation. 💪

  3. _normalize_extension comme safety net — La regex re.sub(r"^[^a-zA-Z]+", ".", ext.lower()) gère proprement les cas tordus (._pdf, ..pdf). Le log en warning quand ça normalise est bien pensé.

  4. Tests — 6 nouveaux tests pour _normalize_extension, 2 pour KreuzbergAdapter (avec et sans mime_type), 1 pour le use case. Bonne couverture des nouveaux chemins.

  5. Compat arrièremime_type: str = "" en paramètre optionnel sur extract_content → pas de breaking change pour les autres callers.


⚠️ Points à améliorer

  1. tuple[bytes, str, str] est fragile — Le retour non nommé (data, filename, mime_type) sur download_document est un pattern error-prone. Si un jour on ajoute un 4ème élément, les déstructurations content, filename, mime_type = ... vont péter silencieusement ou nécessiter un refactor massif.

    • 💡 Suggestion : Utiliser un NamedTuple ou un BaseModel :
    class DownloadedDocument(BaseModel):
        data: bytes
        filename: str
        mime_type: str

    Ça rend le code auto-documenté et résistant aux refactorings.

  2. _normalize_extension : le cas ..pdf — Le test test_double_dot_extension s'attend à ce que report..pdf reste report..pdf, ce qui est probablement un bug ou à tout le moins un cas que Kreuzberg va rejeter. La regex supprime les caractères non-alpha au début de l'extension, mais .. contient un . qui est alpha... Du coup "..pdf""..pdf" inchangé. Est-ce intentionnel ? Si oui, un commentaire expliquant pourquoi serait utile.

  3. Fichiers sans newline finalebricks_api_adapter.py et le fichier tests finissent sans newline (\ No newline at end of file dans le diff). C'est un détail mais ça fait râler certains linters.

  4. DocumentSummary.mime_type default "" — Un mime_type vide n'est pas un MIME type valide. Ça serait plus propre d'utiliser Optional[str] = None pour distinguer « pas de MIME type connu » d'une chaîne vide qui pourrait être interprétée comme une valeur.

  5. Logging dans _extract_filename — Les logger.debug ajoutés sont utiles au debug, mais url[:200] pour tronquer est un peu magique. Un helper ou une constante MAX_LOG_URL_LEN = 200 rendrait l'intention explicite.


💡 Suggestions optionnelles

  • Typer le retour de list_bricks_documents : list[DocumentSummary] c'est bien, mais si DocumentSummary est aussi utilisé côté client MCP, envisager de le mettre dans un module schemas ou dto séparé plutôt que dans le fichier tools MCP.
  • _normalize_extension pourrait être une @staticmethod ou une fonction utilitaire dans un module utils.py si elle est appelée à grossir — pour l'instant inline c'est ok.

Verdict

PR solide qui fixe un vrai bug de production (._pdfValidationError). La propagation du mime_type est la bonne approche, Kreuzberg supportant nativement ce paramètre. Les tests couvrent bien les nouveaux chemins.

Les points d'amélioration sont surtout des questions de robustesse long-terme (NamedTuple/Model au lieu de tuple, Optional[str] au lieu de ""). Rien de bloquant.

🟢 Approuvée avec suggestions — merge OK, mais les suggestions ci-dessus méritent un coup d'œil dans un follow-up.

@Kaiohz Kaiohz merged commit acf63f6 into main May 20, 2026
1 check passed
@Kaiohz Kaiohz deleted the fix/simplify-mcp-tool-response branch May 20, 2026 16:15
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.

1 participant