read_file gab bei Scan-PDFs (kein extrahierbarer Text) nur nutzlose Rohbytes zurueck -> claude.ai konnte sie nicht lesen. Jetzt: PyMuPDF rendert die Seiten als PNG (150 dpi, max 20 Seiten) -> ImageContent, das LLM liest sie per Vision. Verschluesselte/kaputte PDFs bleiben graceful. TestFileTypes scanned.pdf -> image. Produktiv-Fix fuer alle User. Dep: pymupdf (requirements-extra.txt). 76 Tests gruen.
5.2 KiB
mcptest — isoliertes Test-/Dev-Backend
Die MCP-Test-Suite (test_all.py, taeglich via mcp-tests.timer) laeuft NICHT mehr
auf Stefans echten Daten, sondern auf einem dedizierten mcptest-User mit eigenen
Backends. Dieselbe Umgebung dient als isolierte Dev-Sandbox fuer die MCP-Server.
Routing
common.py: USER_ALIASES = {"test": "mcptest"}. Der Test-OAuth-Client client_id=test
(Secret in config.json -> test.token) wird also auf den User mcptest gemappt.
Alle Server lesen pro User aus config.json.
Backends pro Dienst
- Calendar/Contacts (Radicale): User
mcptest(htpasswd/opt/radicale/config/htpasswd, bcrypt). Collections/mcptest/calendar-test/(VEVENT+VTODO) und/mcptest/contacts-test/(VADDRESSBOOK, Test-Kontakt "Max Mustermann").calendar_paths/addressbook_paths[mcptest]=["/mcptest/"]. - Files (oCIS): kompletter User
mcptest(angelegt via Graph-APIPOST /graph/v1.0/usersals admin).ocis_users[mcptest]. Tests legen/.mcp-testsselbst an + raeumen auf. - Notes (Joplin): lokales joplin-cli-Profil
/mnt/ssd/joplin-mcp/profiles/mcptest(sync.target=0, kein Server-Sync), Data API auf :41186 viajoplin-cli-mcptest.service. NotizbuecherInbox+MCP Testmit Beispielnotizen.joplin_data_api[mcptest]. - Mail: statische Test-Maildir
/opt/mcp-servers/tests/testdata/maildir/mit Kontenmcp-test-mail(INBOX: "Willkommen" + "Rechnung"+PDF-Anhang, Sent) undmcp-test-empty.mail_roots[mcptest]zeigt dahin. (Der Mail-MCP liest Maildirs, kein Live-IMAP.)
Credentials
- Klartext-Backup:
/root/.mcptest-creds(chmod 600). - Aktiv genutzt:
config.json(gitignored) — radicale/ocis Passwoerter, joplin Token. - oCIS-Admin (fuer User-Anlage):
/mnt/ssd/ocis/auth.txt.
Tests laufen lassen
/opt/mcp-servers/venv/bin/python -m pytest /opt/mcp-servers/tests/test_all.py -q
# oder der taegliche Runner:
sudo /opt/mcp-servers/tests/run_tests.sh
Als Dev-Sandbox nutzen
- Direkt gegen die Backends: Radicale
http://127.0.0.1:5232/mcptest/(User mcptest), Joplin Data APIhttp://127.0.0.1:41186(Token aus config.json), Maildir s.o. - Ueber die MCP-Server: mit dem
test-OAuth-Client verbinden -> trifft automatisch mcptest. - Testdaten zuruecksetzen: Collections/Notebooks neu seeden (siehe Provisioning unten).
Provisioning (Recreate)
- Radicale:
htpasswd -bB /opt/radicale/config/htpasswd mcptest <pw>; dann MKCALENDAR/mcptest/calendar-test/+ extended-MKCOL/mcptest/contacts-test/. - oCIS:
POST /graph/v1.0/usersals admin (onPremisesSamAccountName=mcptest, passwordProfile). - Joplin: Profil anlegen (
joplin --profile DIR config api.token ...; sync.target 0),api.port=41186in settings.json,joplin-cli-mcptest.service(Kopie von -stefan), Notebooks/Notizen via Data API seeden. - Mail:
tests/testdata/maildir/(im Repo) — Maildir-Konten mit cur/-Nachrichten. config.json: mcptest in radicale_users, ocis_users, joplin_data_api, mail_roots, calendar_paths, addressbook_paths.common.py:USER_ALIASES = {"test": "mcptest"}.
Verwandt: /opt/mcp-servers/CLAUDE.md.
Testdaten (Dateien + Mail-Anhaenge)
Reichhaltiges Set ueber alle gaengigen Typen (fuer read_file-/Attachment-Tests + Dev):
- oCIS unter
/testdata/{images,audio,video,documents,text,archives}/: Bilder (jpg/png/webp/bmp/gif/tiff/svg), Audio (mp3/ogg/m4a/flac/wav), Video (mp4), PDFs (Text-PDFdocument.pdf+ Scan-PDFscanned.pdf), Office (docx/xlsx/pptx), Text/Daten (md/txt/csv/json/xml/yaml/html/py/vcf/ics), Archive (zip/tar.gz). - Mail-Maildir
tests/testdata/maildir/mcp-test-mail/INBOX: Mails mit diversen Anhaengen (Rechnung Text+Scan-PDF, Fotos, Word+Excel, MP3, ZIP+CSV, PPTX+MP4).
TestFileTypes (test_all.py) liest je Typ eine /testdata-Datei und prueft den
zurueckgegebenen Content-Typ (image/text/resource). Office-Docs liefert der Files-MCP
als extrahierten Text.
Neu generieren
Wegwerf-venv + ffmpeg noetig:
sudo apt-get install -y ffmpeg
python3 -m venv /tmp/gen && /tmp/gen/bin/pip install fpdf2 python-docx openpyxl python-pptx Pillow
/tmp/gen/bin/python tests/testdata/gen_testfiles.py # -> /tmp/mcptest-files
sudo tests/testdata/upload_ocis.sh # -> mcptest oCIS /testdata/
/tmp/gen/bin/python tests/testdata/gen_maildir.py # -> maildir mit Anhaengen
Edge-Cases
/testdata/edge/ + TestFileEdgeCases: leere Datei, 0-Byte-Binary, Name mit
Umlauten/Leerzeichen/Klammern, Unicode/Emoji/RTL-Inhalt, Datei ohne Endung,
passwortgeschuetztes PDF + ZIP, uebergrosse Datei (26 MB > 25-MB-Limit ->
"Datei zu gross"). Alle werden graceful behandelt (kein Crash). Generator:
gen_edge.py (braucht pikepdf + zip), Upload via upload_ocis.sh.
Verbesserung: bildbasierte/gescannte PDFs (2026-06-19)
Frueher gab read_file bei Scan-PDFs (kein extrahierbarer Text) nur Rohbytes
(EmbeddedResource) zurueck — claude.ai konnte den Inhalt nicht lesen. Jetzt werden
solche PDFs mit PyMuPDF seitenweise als PNG-Bilder (150 dpi, max 20 Seiten)
gerendert und als ImageContent zurueckgegeben -> das LLM liest sie per Vision.
Produktiv-Feature (gilt fuer alle User). Test: TestFileTypes scanned.pdf -> image.
Runtime-Dep: pymupdf (siehe requirements-extra.txt).