- Added _fetch_s3_text() helper that handles non-JSON content gracefully
(auto_sum_note may be HTML/plain text, not JSON — previous code errored)
- plaud_get_summary now tries auto_sum_note first, falls back to outline
- plaud_get_notes now routes auto_sum_note through _fetch_s3_text
- plaud_get_recording_detail now correctly flags has_summary=true when
auto_sum_note is present (previously only checked "outline")
- Response includes summary_type field: "auto_sum_note", "outline", or "none"
Token resolution order:
1. PLAUD_TOKEN env var
2. ~/.plaud/tokens-mcp.json (desktop app authToken, ~6-month expiry)
Written by plaud_decrypt_tokens.py via Electron safeStorage decryption
3. ~/.plaud/config.json (legacy 24-hour web token fallback)
The Plaud desktop app stores a standard JWT authToken in Chromium v10
Electron safeStorage (AES-128-CBC / PBKDF2-SHA1). plaud_decrypt_tokens.py
extracts this token and saves it to tokens-mcp.json. Current token expires
2026-11-25; re-run the decrypt script on that date to renew.
- Switch urllib to curl subprocess to bypass Cloudflare Error 1010
- Add _fetch_s3_json() for gzipped content from signed S3 URLs
- Fix list endpoint key: data_file_list (not data)
- Fix detail endpoint title field: file_name (not filename)
- Fix token key: support both token and accessToken in config
- Add _format_transcript() with speaker grouping
- plaud_get_transcript: fetch from content_list S3 URLs (transaction_polish → transaction)
- plaud_get_summary: fetch outline from S3
- plaud_get_notes: fetch all non-transcript content_list items from S3
- plaud_get_recording_detail: derive has_transcript from content_types list