SmartMoney — 13F superinvestor tracker
MCP serverAI & models13flow lets your AI research SEC 13F filings, the public reports where large institutional investors disclose their stock holdings. Every finding is linked back to its source, and the AI can run quality checks, maintain watchlists, and keep an audit trail of its work. The result is investment research you can verify.
Use SmartMoney — 13F superinvestor tracker in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add SmartMoney — 13F superinvestor tracker and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use SmartMoney to get live status
No key or account is asked for. Not verified by us yet: Ahel has not run a call through it.
Details
Available today. Use it from your connected AI after setup.
No key or account is asked for. Not verified by us yet: Ahel has not run a call through it.
After adding 13flow, ask your AI to research an institutional investor or a company in SEC 13F filings, or set up a watchlist to follow them.
What your AI can do with it
- Research SEC 13F filings from institutional investors
- Link every finding back to its source filing
- Run quality checks on research results
- Build watchlists of investors or companies to follow
- Keep an audit trail of research steps and sources
Install SmartMoney — 13F superinvestor tracker
The server’s own address, for the clients that take one directly. Or connect Ahel once and every client you use reads it from one address, with the account kept on Ahel rather than in each client’s config.
Claude Code
claude mcp add --transport http --scope user smartmoney-13f-superinvestor-tra 'https://13flow.eu/api/mcp'Run it once in your project, then open /mcp to approve any sign-in the server asks for.
Claude Desktop
https://13flow.eu/api/mcpAdd a custom connector in Settings, paste this address, and approve the sign-in.
Cursor
cursor://anysphere.cursor-deeplink/mcp/install?name=smartmoney-13f-superinvestor-tra&config=eyJ1cmwiOiJodHRwczovLzEzZmxvdy5ldS9hcGkvbWNwIn0=Open the link and Cursor adds the server at that address.
ChatGPT
https://13flow.eu/api/mcpIn Settings, enable Developer mode, create an MCP app, and paste this address. Your plan and workspace must allow custom apps.
Codex
codex mcp add smartmoney-13f-superinvestor-tra --url 'https://13flow.eu/api/mcp'Run it once, then sign in with codex mcp login smartmoney-13f-superinvestor-tra if the server asks for an account.
From the project's README
As published by bluetouff/13flow in README.md.
Reconstructs hedge-fund / superinvestor portfolios straight from SEC EDGAR 13F-HR filings, and diffs quarter-over-quarter to surface new positions, exits, adds and trims. Data is U.S.-government public domain — free to use and redistribute.
Guides: TEST_LOCAL.md to run it on your machine in minutes ·
INSTALL_SERVER.md for production deployment · SECURITY.md
for the threat model and audit.
Setup
pip install -r requirements.txt # or: pip install requests defusedxml flask
export SEC_UA="SmartMoney/1.0 you@example.com" # SEC requires a contact email or 403s you
export OPENFIGI_APIKEY="..." # optional, free; lifts FIGI rate limits
python run.py --list # tracked funds
python run.py --verify # sanity-check seed CIKs against EDGAR
python run.py --fund "Berkshire Hathaway" --top 15 --enrich # --enrich adds tickers
Offline tests (no network):
pip install pytest
python -m pytest tests/ -q # offline suites: parsing, figi, db, valuation, alerts, resolver, security, Pro API
CUSIP resolution & the long tail
13F rows carry only CUSIPs. resolver.py runs a confidence-ranked chain so the tail that
OpenFIGI misses still gets resolved where possible, with provenance recorded:
manual override (1.0) → OpenFIGI (0.95) → CUSIP issuer-prefix (0.65–0.85)
→ SEC name match (0.60) → unresolved (0.0, issuer name kept)
The CUSIP-prefix step reuses a confident sibling's ticker for a different share class/unit of
the same issuer; the SEC step matches nameOfIssuer against SEC company_tickers.json. Misses
are cached with a timestamp and re-tried after a TTL (the tail shrinks as data improves), not
forever. --sync --enrich uses the full chain.
python run.py --coverage # % of 13F value resolved, per fund + the worst tail
python run.py --resolve-sweep # re-run the chain over unresolved CUSIPs, back-fill
Provenance + confidence are stored per holding, so the dashboard's reconcile dot and the
valuation reconcile ratio can flag weak mappings. Optional cusip_overrides.json ({"<cusip>":"TKR"})
hard-maps stubborn names at top confidence.
Dashboard (web UI)
A read-only Flask API exposes the store as JSON, and a single-file dashboard consumes it.
pip install flask
python -m smartmoney.api --db smartmoney.db # serves http://localhost:5000
python -m smartmoney.api --db smartmoney.db --value # also enable live valuation (stooq)
Open http://localhost:5000. The UI is branded 13FLOW (dark editorial theme — emerald =
institutions, amber = insiders, converging like the Confluence score) with five screens:
Consensus (who's buying / most owned), Funds (holdings, current weights, implied P&L,
conviction sparklines), Compare (overlap matrix across funds), Alerts (subscriptions +
the diff feed), and Confluence (13F accumulation × insider buying). A served FAQ page
(/faq) explains the product, linked from the sidebar. Demo data is available only when
explicitly requested (?demo=1 in the browser or SMARTMONEY_CONFLUENCE_DEMO=1 for the
Confluence API); production errors are shown instead of silently substituting samples. API endpoints:
/api/live-status, /api/funds, /api/fund/<cik>,
/api/consensus/{buys,holdings}, /api/compare,
/api/signals/confluence, /api/signals/confluence/history,
/api/methodology/confluence-v1, /api/data-quality, /api/agent-stats,
/api/openapi.json, and the
MCP Streamable HTTP endpoint /api/mcp. The Registry surface exposes only bounded, read-only
public tools. Optional Pro/x402 tools are disabled by default and are not advertised publicly.
The official Registry manifest is server.json. Static,
crawler-friendly pages are
served at /funds, /funds/<cik>, /stocks, /stocks/<ticker>, /signals, and
/signals/<ticker>, with SEC links where an accession or issuer search can be resolved.
/agents and /fr/agents publish 7/30-day MCP activity from durable UTC aggregates. They
make no unique-user claim and retain no IP address, User-Agent, client version, raw client
identifier, arguments, prompts, responses or keys.
The separate operator-only /stats/ surface is an optional password-protected GoAccess
report generated from Apache logs. It adds no browser tracking, strips query strings,
anonymizes report IPs at level 2 and keeps a 90-day reporting window. Its dedicated CSP is
scoped to the authenticated report so the public site's nonce policy remains unchanged.
Production also installs a first-in-order static 000-zen-default.conf vhost. Unknown Host
headers receive an inert ZEN page and a separate minimal access log instead of reaching
13FLOW or contaminating 13flow_access.log; named vhosts continue to route normally.
/api/live-status is the public,
machine-readable proof of live state: SHA, source (SEC EDGAR), latest quarter, row counts,
data-quality summary, and uses_synthetic_data=false. /api/product-status is the
machine-readable operational status surface: it states live data coverage, disabled
claims, and why full quantitative validation remains blocked until imported 2013-2026
adjusted-price and normalized Form 4 transaction artifacts are available. See the
Core V1 scope gate in docs/CORE_V1_BOUNDARY.md.
Current product and research boundaries are exposed at /status, /readiness,
/api/product-status and /api/research-readiness. /api/pro-offer remains a retired
compatibility endpoint and is not exposed as a canonical MCP tool.
No browser accounts or checkout
Core V1 deliberately has no browser account system, no public signup, no
self-serve checkout and no Stripe billing flow. Pro API access is operator
issued: create a scoped key, deliver the plaintext token once through an
approved secure channel, verify /api/pro/v1/status, and keep audit/rotation
in the Pro control plane.
Pro API
The Pro API is an explicit, versioned API-key surface for institutional and automated use.
It is off by default. Enable it with SMARTMONEY_PRO_API=1 and store keys, counters, and
audit events in a dedicated control-plane SQLite file via SMARTMONEY_PRO_DB.
Recommended production split:
# /etc/13flow/13flow-web.env, used by 13flow.service on 127.0.0.1:8000
SMARTMONEY_OPEN=1
SMARTMONEY_DB_READONLY=1
SMARTMONEY_DB=/var/lib/13flow/13flow.db
SMARTMONEY_ADMIN_PANEL_USER=admin@toonux.com
SMARTMONEY_ADMIN_SESSION_SECRET=<server-only-random-secret>
SMARTMONEY_ADMIN_PASSWORD_PBKDF2=<pbkdf2-sha256$...>
SMARTMONEY_ADMIN_SESSION_SECONDS=1800
SMARTMONEY_ADMIN_TOTP_SECRET=<base32-secret>
SMARTMONEY_ADMIN_TOTP_REQUIRED=1
# /etc/13flow/13flow-pro.env, used by 13flow-pro.service on 127.0.0.1:8001
SMARTMONEY_OPEN=1
SMARTMONEY_DB_READONLY=1
SMARTMONEY_DB=/var/lib/13flow/13flow.db
SMARTMONEY_PRO_API=1
SMARTMONEY_PRO_DB=/var/lib/13flow-pro/13flow-pro.db
SMARTMONEY_PRO_KEY_PEPPER=<server-only-random-secret>
SMARTMONEY_PRO_REQUIRE_KEY_PEPPER=1
SMARTMONEY_PRO_ACCEPT_LEGACY_SHA256_KEYS=0
Do not grant /var/lib/13flow-pro write access to the public 13flow.service. Apache
should route only /api/pro/ to 13flow-pro.service, while the public site and open JSON
endpoints stay on the read-only service.
Admin panel access at /pro/admin is protected by a server-side admin session. Generate
the session secret and password hash on the server; the Pro API key used inside the panel
is still separate and must carry admin:read,admin:write.
openssl rand -hex 32
/opt/13flow/.venv/bin/python /opt/13flow/run.py --hash-admin-password
/opt/13flow/.venv/bin/python -c 'import base64,secrets; print(base64.b32encode(secrets.token_bytes(20)).decode().rstrip("="))'
Create an API key offline as the operator. The plaintext token is shown exactly once. In
production, only an HMAC-SHA256 hash derived with the server-only
SMARTMONEY_PRO_KEY_PEPPER is stored, so tokens generated from a GitHub clone or another
instance cannot authenticate against 13flow.eu. With
SMARTMONEY_PRO_REQUIRE_KEY_PEPPER=1, legacy SHA-256 rows are rejected unless
SMARTMONEY_PRO_ACCEPT_LEGACY_SHA256_KEYS=1 is explicitly set for a short migration window.
sudo -u flowpro env SMARTMONEY_PRO_KEY_PEPPER="$SMARTMONEY_PRO_KEY_PEPPER" \
SMARTMONEY_PRO_REQUIRE_KEY_PEPPER=1 \
/opt/13flow/.venv/bin/python /opt/13flow/run.py \
--create-api-key "Acme Asset Management" \
--pro-db /var/lib/13flow-pro/13flow-pro.db \
--api-key-scopes funds:read,quality:read \
--api-key-rate-per-min 120 \
--api-key-rate-per-day 10000
python run.py --list-api-keys --pro-db /var/lib/13flow-pro/13flow-pro.db
python run.py --revoke-api-key <key_id> --pro-db /var/lib/13flow-pro/13flow-pro.db
python run.py --prune-pro-audit-days 180 --pro-db /var/lib/13flow-pro/13flow-pro.db
Use Authorization: Bearer <token> or X-13FLOW-Key: <token>.
curl -H "Authorization: Bearer $TOKEN" https://13flow.eu/api/pro/v1/status
curl -H "Authorization: Bearer $TOKEN" https://13flow.eu/api/pro/v1/funds
curl -H "Authorization: Bearer $TOKEN" https://13flow.eu/api/pro/v1/fund/0001067983
curl -H "Authorization: Bearer $TOKEN" \
"https://13flow.eu/api/pro/v1/fund/0001067983?include_holds=0&limit_positions=20&limit_moves=50"
curl -H "Authorization: Bearer $TOKEN" https://13flow.eu/api/pro/v1/data-quality
curl https://13flow.eu/api/pro/v1/openapi.json
curl https://13flow.eu/api/product-status
curl https://13flow.eu/api/research-readiness
Security properties: opaque high-entropy tokens, key hashes only at rest, scoped access
(funds:read, quality:read), persistent per-minute/per-day rate limits, and an audit row
for every Pro request including denied and rate-limited calls. Pro responses are explicitly
non-cacheable (private, no-store, max-age=0) and vary on both supported key headers so
reverse proxies cannot mix responses across credentials.
Operational baseline:
- one active key per institution or internal service;
- revoke unused QA/bootstrap keys immediately;
- rotate institutional keys on a fixed schedule and after personnel/vendor changes;
- keep Pro audit rows long enough for incident response, then prune with
--prune-pro-audit-days; - back up
SMARTMONEY_PRO_DBwith encrypted backups only. Seedeploy/PRO_API_SPLIT.mdanddeploy/backup-pro-db.sh.
Before issuing or renewing a Pro key, confirm
/api/pro/v1/admin/release-readiness returns go: true with no blockers.
GET /api/pro/v1/fund/<cik> is the institutional detail endpoint: it returns the selected
filing metadata, previous filing metadata, full holdings, share-count moves versus the
previous quarter, fund-scoped data-quality warnings, and the methodology block needed to
reproduce the interpretation. For production integrations, use include_holds=0,
limit_positions, and limit_moves to keep payloads bounded while retaining the same
calculation basis. Responses include positions_total/positions_returned and
changes_total/changes_returned so clients can detect truncation deterministically.
Alerts — real delivery
The Pro workspace report compares the last two saved snapshots. It now includes per-ticker explanations, before/after scores and the SEC filings referenced by the saved movements. The first snapshot establishes a baseline; filtered list entries and removals are not described as purchases or sales. Manual snapshots and the existing scheduled runner use the same comparison logic.
Saved workspace alerts automatically become resolved when their conditions
stop matching, or invalidated when data quality blocks them. A fresh qualifying
snapshot reactivates the alert. Acknowledgements and dismissals survive unchanged
signals; unavailable observations do not imply a resolution. These states are
visible through the existing workspace, reports and alert endpoints.
Subscribe to a fund and get the diff (not just "a filing appeared") delivered when a new 13F lands. Channels: console (default), webhook, email.
python run.py --subscribe "Berkshire Hathaway" # console, primed
python run.py --subscribe "Scion Asset Mgmt" --channel webhook --target https://hooks.you/x
python run.py --list-subs
python run.py --alerts-run # sync subscribed funds from EDGAR, then deliver new ones
python run.py --alerts-dispatch # deliver pending from already-stored filings (offline)
Email needs SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_FROM in the env.
Key properties: idempotent (a crash/restart never re-sends or drops — the deliveries table is
the boundary), new subscribers are primed so they only get future filings, failed sends are
recorded and retried next run, and subscribing is gated to the paid tier. Drive --alerts-run
from cron rather than the in-process poll() loop.
Observed 13F revisions
GET /api/events/filings?after=0&limit=100 exposes a public, read-only cursor
journal for tracked funds (optional cik filter, maximum page size 200).
Each event has a stable id, sequence, recorded_at, fund and quarter,
immutable before/after states, changed fields and SEC source links.
Raw declared totals stay separate from composed totals, which are unavailable
for incomplete amendment chains. An unchanged re-import emits no event.
The existing sync writer records changes in the same transaction as the filing.
On initialization, it records the latest two stored quarters per tracked fund as
baseline events with the actual observation time. To initialize without an
EDGAR request, run python run.py --db <market-db> --record-filing-events under
the existing writer account. Back up the database first using the normal release
procedure; this adds a table but does not rewrite existing market data. No new
service, timer or dependency is needed. Before initialization, the endpoint
returns not_initialized or empty without writing to the database.
Consumers follow next_cursor while has_more is true. Restart from zero if
stream_id changes or head falls below the stored cursor after a restore.
The journal begins at installation: baselines do not reconstruct prior knowledge,
filing dates have day precision and are not trade dates, and composition status
is not a fund quality rating. It excludes private watchlists and ranking changes.
It retains observed portfolio summaries and fingerprints, not historical
per-security holdings: it is not a complete point-in-time backtest dataset.
Confluence (13FLOW) — where 13F accumulation meets insider buying
A separate screen ranks tickers where superinvestor 13F accumulation and open-market
Form 4 insider buying coincide — a rare, hard-to-fake overlap. It reuses the existing EDGAR
etiquette (UA + rate limit), the defusedxml hardening, and the dashboard theme.
GET /api/signals/confluence?window=90&min_score=0
→ { "kpis": {...}, "signals": [ {ticker, score, quadrant, breakdown{...}, institutional{...}, insider{...}}, ... ] }
GET /api/methodology/confluence-v1
→ frozen score version, parameters, universe, split, parameter_hash
GET /api/signals/confluence/history?ticker=TSM&window=90
→ append-only signal revisions from confluence-history.jsonl
The 0–100 score is an ordinal exploratory ranking, not a probability, not a historical
frequency, and not an expected-return estimate. FeatureParams controls what the signal
measures (recency half-life, buy-size curve, cluster window, seniority) and remains a set of
judgement parameters until sensitivity tables are published. Weights controls how the
pillars combine (institutional breadth, insider conviction, recency-weighted dollars,
agreement bonus, minus trim/sell penalties). The default weights are heuristic; the
current live build must be treated as not calibrated on live historical outcomes and not
validated out-of-sample. Each signal exposes its per-pillar breakdown
and a quadrant label (Conviction / Institutional bid / Insider conviction / Distribution /
Divergent / Neutral), but the quadrant describes direction while the score describes heuristic
intensity, so they can diverge.
Data-scope boundary: 13F filings are delayed long-US-securities disclosures, not complete fund portfolios. They omit shorts, most non-US holdings, bonds, full derivative books, intra-quarter trading and confidential-treatment omissions. The live Confluence rail also uses a bounded Form 4 issuer universe driven by tracked 13F activity; insider-only and distribution quadrants are therefore not exhaustive. Current Form 4 parsing focuses on normalized Table I transactions; Table II derivatives, 10b5-1 plan flags, multi-owner attribution and weighted-average price footnotes remain explicit limitations until modeled.
The quantitative proof boundary is public: VALIDATION_PROTOCOL.md defines the required
point-in-time dataset, train/validation/test split, baselines, neutralization, costs,
confidence intervals, permutation tests, and version log before any score can be called
validated. Until then, the correct wording is: backtest harness available; default weights
are heuristic. The offline price export, dataset builder and publication gate are:
python run.py \
--build-validation-prices \
--validation-tickers /var/lib/13flow/validation_tickers_sample25.txt \
--validation-prices-out /var/lib/13flow/validation_prices_sample25.csv \
--validation-price-provider massive \
--validation-start 2013-01-01 \
--validation-end 2026-07-02 \
--validation-price-sleep-sec 15 \
--validation-price-retry-attempts 8 \
--validation-price-retry-base-sec 60 \
--validation-price-retry-max-sec 900 \
--validation-price-timeout-sec 10 \
--validation-json
python run.py --db /var/lib/13flow/13flow.db \
--build-validation-dataset /var/lib/13flow/confluence_features.csv \
--validation-prices /var/lib/13flow/validation_prices_sample25.csv \
--validation-form4 /var/lib/13flow/validation_form4_sample25.csv \
--validation-tickers /var/lib/13flow/validation_tickers_sample25.txt \
--validation-code-commit "$SHA" \
--validation-json
python run.py --validation-dataset /path/to/confluence_features.csv --validation-json
The price exporter writes a provider-neutral ticker,date,adj_close CSV and reuses
already exported ticker rows unless --validation-price-force is set. Massive requires
MASSIVE_API_KEY in the process environment; stooq is available as a free fallback for
operator smoke tests, and yahoo is a no-key research fallback when a vendor account cannot
serve enough history. Any non-Massive fallback must be disclosed in the validation artifact
as a research price source, not an institutional production feed. The exporter retries 429
and 5xx responses with exponential backoff, honors Retry-After, deduplicates resumed rows
and reports complete/partial history coverage per ticker. It checkpoints the CSV after each
ticker so interrupted runs remain resumable. Use --validation-price-max-tickers 1 for first
contact with any new or fallback provider. Passing the same
--validation-tickers file to the dataset builder filters the feature export to that priced
universe; omit it only when the price CSV covers the full validation universe. The dataset
gate returns the feature-table SHA256, split counts, schema gaps, version mismatches and rank
metrics for the score plus available baselines.
Imported vendor/bulk price files can be checked without touching any external API:
python run.py \
--validate-price-csv /var/lib/13flow/validation_prices_full.csv \
--validation-tickers /var/lib/13flow/validation_tickers_priceable.txt \
--validation-start 2013-01-01 \
--validation-end 2026-07-02 \
--validation-json
The validator reports required columns, positive-price failures, duplicate ticker/date rows, missing tickers, partial histories and major calendar gaps before the file is used in a validation dataset.
The Form 4 validation artifact can be produced from SEC EDGAR with a conservative, checkpointed exporter:
SEC_UA='13FLOW/1.0 contact@example.com' python run.py \
--build-validation-form4 \
--validation-tickers /var/lib/13flow/validation_tickers_sample25.txt \
--validation-form4-out /var/lib/13flow/validation_form4_sample25.csv \
--validation-start 2024-07-03 \
--validation-end 2026-07-02 \
--validation-form4-sleep-sec 2 \
--validation-form4-max-tickers 1 \
--validation-json
Increase --validation-form4-max-tickers only after the one-ticker smoke succeeds. The
exporter reuses existing ticker rows unless --validation-form4-force is set and caps each
ticker with --validation-form4-max-filings-per-ticker.
For the operator checklist after a long Form 4 export finishes, including the offline CSV
gate and deployment order, see docs/POST_RUN_FORM4_VALIDATION.md.
The dataset builder joins the reviewed local Form 4 transaction file with
--validation-form4. Accepted CSV/JSONL rows include ticker, accession,
filing_date, transaction_date, owner identity/role fields, transaction code,
acquired/disposed flag, shares, price and ownership-after fields. The join is point-in-time:
only Form 4 filings accepted by the dataset as_of date and transactions inside the trailing
window enter the row. Without that file the builder still exports
feature_scope=13f_only_no_form4; with it the scope becomes 13f_form4_joined. Neither scope
is a full validation claim until the imported price and Form 4 artifacts, coverage, costs and
no-lookahead controls are reviewed. Non-priceable/common equity suspects are excluded by
default; use --validation-include-non-priceable only for auditing noisy 13F rows.
Confluence v1 is frozen as a machine-readable research contract in
docs/confluence_v1.json and documented in docs/CONFLUENCE_V1.md. The append-only signal
history is written to confluence-history.jsonl in SMARTMONEY_CACHE_DIR; corrections are
new revisions, not in-place edits.
The production live provider also has an explicit effective universe: to keep the public tier
off abusive Form 4 fan-out, it scans insider filings only for tickers with at least
SMARTMONEY_CONFLUENCE_SCAN_MIN_FUNDS tracked funds opening or adding in the latest 13F
quarter (default 3). Trim/exits are computed more broadly, but insider-only, distribution,
and divergent categories are therefore not exhaustive in this production path. This is
exposed in /api/signals/confluence under metadata.effective_universe. Only symbols
matched to the SEC company index enter the score. Share-class delimiters such as BRK/B
or BRK.B resolve to BRK-B only when that symbol exists in the index. Unmatched
securities are listed in metadata.universe_coverage.excluded_tickers; their security
type is not inferred and no insider score is assigned to them. Raw 13F holdings remain
unchanged.
Shortened here. Read the whole README on GitHub.
Tools it offers (13)
What this server listed when Ahel dialed its public endpoint in Sep 2026, with no key and no account of yours. The names are the server’s own.
get_live_statusget_product_statusget_research_readinessget_agent_statslist_fundsget_fundget_stockpreview_watchlistdiscover_watchlistget_confluence_signalsget_signal_historyget_confluence_methodologyget_data_quality
Signals
- GitHub stars
- 4
- Last commit
- Oct 2026
Advanced
- Delivery
- 13flow MCP server → your Ahel connector (mcp.ahel.ai) → your AI.
- Item type
- mcp-server
- Key
io-github-bluetouff-13flow- Source
- github.com/bluetouff/13flow
- Hosted endpoint
https://13flow.eu/api/mcp
More in AI & models
MCP server · upstash
More in AI & modelsAdButler
MCP server · adbutler
More in AI & modelsatom-mcp-server
MCP server · a7om-ai
More in AI & modelsottasia
MCP server · aiweather-anurag
More in AI & modelsunphurl
MCP server · 123ergo
More in AI & modelsmicrosoft-learn-mcp
MCP server · microsoftdocs
More in AI & models