When Schwab uses modern blob URLs (increasingly common), find_report()
returns __CLICK_TO_OPEN__ and the scraper skips storing a report_url
even though the PDF downloads and parses successfully. This caused
agents to see report_url=None for tickers like PEP/BR/DPZ/MSCI/BMI.
Changes:
- Fix serialize() to use dataclasses.asdict() instead of str() for
dataclass payloads, producing proper JSON objects instead of Python
repr strings
- Add /reports/{ticker}/pdf endpoint to serve cached Morningstar PDFs
- Enrich report_url with the MCP's own PDF endpoint when blob URLs
were used and the report was successfully downloaded
- Add SCHWAB_MCP_BASE_URL env var to compose for self-referential URLs
- login tool was calling api.login() which did not exist in unified_api,
causing AttributeError on every invocation. Now calls login_to_schwab
directly with proper credential fallback to config.json.
- upload_cookies hardcoded 'cookies.json' instead of get_cookies_path(),
and did not handle wrapped export formats ({cookies: [...]}). Both fixed.
- Result envelopes now match the standard {success, data, error, error_type,
retryable} shape used by other tools.
Add diagnostic logging to the MCP login tool handler:
- Log whether username/password were provided explicitly
- If falling back to config, log the resolved config path and whether it exists
- This complements upstream scraper v0.6.18 credential diagnostics
Bumps version to 0.2.1.
- Set up logging.basicConfig() at module load so scraper logs reach stderr
(visible in docker logs instead of silently dropped)
- Replace StringIO-only capture with TeeHandler that writes to BOTH stderr
and the StringIO buffer, so logs remain visible in docker while also
being returned in tool responses
- Add explicit 'LOGIN TOOL CALLED' and 'DEBUG MODE ENABLED' log lines
at the start of the login tool so users can verify logging is active
Scraper debug output goes to stderr which is invisible in MCP stdio mode.
Add capture_logs context manager that attaches a StringIO handler to the
schwab_scraper logger during tool execution, then includes captured logs
in the response envelope when debug=True or on failure.
Applied to login() and refresh_session() which are the critical paths
for authentication diagnostics.
Patch RequestResponder.respond() and cancel() at startup to handle
the race where a notifications/cancelled arrives between handler
return and respond(), which crashes the session with
"AssertionError: Request already responded to".
Also improve build.sh to handle registry push failures gracefully
and auto-restart the container after building.