Skip to content

Open reports via a clickable http:// link (file:// won't open in chat) - #26

Merged
YashvantHange merged 1 commit into
mainfrom
feat/report-open-link
Jul 18, 2026
Merged

Open reports via a clickable http:// link (file:// won't open in chat)#26
YashvantHange merged 1 commit into
mainfrom
feat/report-open-link

Conversation

@YashvantHange

Copy link
Copy Markdown
Owner

What & why

The report tools returned a file:// "open" link, but clicking it does nothing in the Claude Code / VSCode chat — the sandbox blocks file:// from opening a local file. The only link a chat/webview will open is http(s)://. So each report is now served over a tiny loopback web server and returned as a clickable http://127.0.0.1:<port>/<file> link that opens the rendered report in the browser (PDF opens in the viewer). The on-disk location is still surfaced too.

Changes

  • export.py
    • preview_url(path) — lazily starts a loopback (127.0.0.1, ephemeral port) static server rooted at the report's directory, on a daemon thread (one per directory), and returns an http://127.0.0.1/... URL that opens the rendered report on click. Loopback-only, serves just that directory, best-effort (returns None if a port can't be bound).
    • open_file(path) — OS default open (startfile/open/xdg-open), best-effort, no-op under PYTEST_CURRENT_TEST/CI/INVESTO_NO_OPEN.
  • models.pyExportedFile/ExportResult gain open_url; AnalysisReport gains html_report_open_url (alongside the existing file:// location fields).
  • server.pyanalyze_company and export_report populate the http open link.
  • cli.py--open opens the written report in the default app (a short-lived CLI can't host a persistent server); the output still prints the file location.

Verification

  • ruff check ., mypy, pytest -q — all green (288 tests; a new test fetches a report back over the loopback link and asserts 200).
  • End-to-end: preview_url() returned http://127.0.0.1:62056/…, and a GET returned the full rendered HTML (200). investo analyze "Sigachi Industries" --open wrote and opened the report in the browser.

Note

The clickable http://127.0.0.1 link works while the long-running MCP server is up (it hosts the preview server). After merging, restart the Investo MCP server so analyze_company/export_report return the new open_url / html_report_open_url.

…n chat)

A file:// link is blocked from opening in the Claude/VSCode chat sandbox, so
clicking the returned location did nothing. Serve each report over a tiny
loopback web server and hand back a clickable http://127.0.0.1 link that opens
the rendered report in the browser — while still surfacing the on-disk location.

- export.preview_url(path): lazily start a loopback (127.0.0.1, ephemeral port)
  static server rooted at the report's directory, on a daemon thread, one per
  directory; returns an http URL that opens the rendered report on click.
- export.open_file(path): OS default open (startfile/open/xdg-open), best-effort,
  no-op under tests/CI/INVESTO_NO_OPEN.
- models: ExportedFile/ExportResult gain open_url; AnalysisReport gains
  html_report_open_url, alongside the existing file:// location fields.
- server: analyze_company and export_report populate the http open link.
- cli: --open opens the written report in the default app (a short-lived CLI
  can't host a persistent server); the output still prints the file location.
@YashvantHange
YashvantHange merged commit df66724 into main Jul 18, 2026
6 checks passed
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