InvestJournal is a stock research workspace. This MCP server lets AI assistants (like Claude) query your tracked stocks, daily price history, financial ratios, DCF valuations, watchlists, and personal notes — all scoped to your authenticated account. Read-only by default; opt-in write tools let your assistant create and manage watchlists, save and annotate DCF valuations, write and edit comments, manage price alerts, and ask questions about uploaded company PDFs via Retrieval-Augmented Generation. Every write tool operates exclusively on data you own.
InvestJournal is not yet listed in Claude's built-in connector directory, so it won't appear when you browse the connector list — add it as a custom connector instead (available on every plan; the Free plan allows one). Open claude.ai/settings/connectors (or Settings > Connectors in the Claude Desktop app), click Add custom connector, and paste this URL:
https://mcp.investjournal.io/mcp
Connectors are tied to your Claude account — once added on the web or desktop, InvestJournal also works in the Claude mobile apps.
Add the server with one command:
claude mcp add --scope user --transport http investjournal https://mcp.investjournal.io/mcp
Then, inside Claude Code, run /mcp, select investjournal, and choose Authenticate.
On first connection Claude will open a browser tab to https://mcp.investjournal.io/authorize, which redirects to the InvestJournal login page. After you log in (using either the reviewer test account credentials or your own InvestJournal account), tokens are issued and your tools become available in chat.
Granting write access: connections are read-only by default. On the authorization screen, tick “modify your data” to also grant the stockgrade:write scope — this is what lets the write tools (create/edit watchlists, comments, price alerts, and DCF valuations) run. Leave it unticked to keep the connection read-only. Without the write scope, write tools are refused with a message asking you to reconnect and grant write access.
GET https://mcp.investjournal.io/authorize (PKCE S256 required)POST https://mcp.investjournal.io/tokenGET https://mcp.investjournal.io/.well-known/oauth-authorization-serverGET https://mcp.investjournal.io/.well-known/oauth-protected-resourcehttps://mcp.investjournal.io/sessionsAdmin-only tools (titled …(admin) below) are listed by tools/list only for admin accounts — a regular account's session simply doesn't see them, and they additionally refuse non-admin callers if invoked directly.
| Name | Title | What it does | Read-only | Destructive |
|---|---|---|---|---|
GetStockSummary | Stock Summary | Profile of a stock by ticker — name, shared ratio count, and your DCF count for it. Also when it next reports (a date the company announced, or a results release from the last 14 days) and the newest fiscal period InvestJournal holds ratios for. Both are absent when unknown — never a placeholder — so a company that has announced nothing simply has no date. | ✓ | — |
ListStocks | List Stocks | Paginated list of tracked stocks with profile counts (ratioCount is the shared catalog's; dcfValuationCount is yours). Returns total/hasMore/nextCursor and may be partial — page with cursor. Optional nameOrTickerPrefix and currency filters. | ✓ | — |
SearchStocks | Search Stocks | Substring search by name or ticker. | ✓ | — |
ScreenStocks | Screen Stocks | Filter and rank the whole tracked universe by GICS sector/industry/exchange/country and minimum ROE, ROA, FCF/sales and revenue-growth thresholds (decimal fractions — 0.15 is 15%). Returns total/hasMore/nextCursor and may be partial — page with cursor. Each row carries the four latest ratio values with their fiscal years, plus your own DCF upside and upsideBasis naming which kind of valuation produced it — a reverseDcf is fitted to a price, so its upside is the price move since that valuation rather than a discount to an independent estimate of worth. | ✓ | — |
GetPriceHistory | Price History | Daily closing-price history from the database (optional from/to range and daily/weekly/monthly granularity), plus the latest known price and its date. | ✓ | — |
GetLatestPrice | Latest Price | A stock's latest known daily closing price and its date. | ✓ | — |
AddStock | Add Stock (admin) | Admin-only: add a new stock to the tracked universe by its real Yahoo Finance ticker (revives a previously soft-deleted stock with the same ticker). | — | — |
AddStockListing | Add Stock Listing (admin) | Admin-only: register a secondary listing (e.g. a US OTC ticker) of an already-tracked company. The listing gets its own price series and is offered in the portfolio transaction picker only; elsewhere its ticker aliases to the primary company. | — | — |
EditStock | Edit Stock (admin) | Admin-only: rename/reticker an existing stock, fix its currency or metadata, or set its reporting cadence / fiscal year-end for the earnings calendar, preserving its price/news/comment/watchlist history. | — | ✓ |
DeleteStock | Delete Stock (admin) | Admin-only: soft-delete a stock so it no longer appears in the app; history is preserved and it can be revived later. | — | ✓ |
ListWatchlists | List Watchlists | The user's watchlists with stock counts. | ✓ | — |
GetWatchlistStocks | Get Watchlist Stocks | All stocks in a named watchlist, each with the date the company announced it will report (absent when it has announced nothing, which is the normal case). | ✓ | — |
GetWatchlistRatioRanking | Rank Watchlist by Ratio | Top N watchlist stocks ranked by a single ratio (ROE, ROA, FCFSales, etc.), each with the same announced report date as GetWatchlistStocks. | ✓ | — |
GetWatchlistStocksWithLatestRatios | Watchlist with Latest Ratios | All ratios for all watchlist stocks in one call. | ✓ | — |
AddStockToWatchlist | Add Stock to Watchlist | Add a stock to one of the user's watchlists. | — | — |
RemoveStockFromWatchlist | Remove Stock from Watchlist | Remove a stock from one of the user's watchlists. | — | ✓ |
CreateWatchlist | Create Watchlist | Create a new watchlist for the signed-in user. | — | — |
ArchiveWatchlist | Archive Watchlist | Archive (soft-delete) one of the user's watchlists by name. | — | ✓ |
RenameWatchlist | Rename Watchlist | Rename one of the user's watchlists. | — | — |
SetWatchlistFavorite | Set Watchlist Favorite | Mark a watchlist as a favorite or remove the flag. | — | — |
GetStockRatios | Get Stock Ratios | All financial ratios for a stock, plus the user's own custom metrics when they have any (returned separately, never mixed into the sourced ratios). | ✓ | — |
AddMyMetrics | Add My Metrics | Add or update the user's own custom metric for a stock — backlog, store count, anything the standard ratios don't cover. A whole series in one call. | — | — |
GetMyMetrics | Get My Metrics | The user's own custom metrics for a stock, with every period recorded. | ✓ | — |
DeleteMyMetric | Delete My Metric | Delete one of the user's own custom metrics — a single period, or the whole metric. | — | ✓ |
ListMyTasks | List My Tasks | The user's own Morning Desk checklist ("Your list"): open tasks with their optional ticker and due date, then recently checked-off ones — with the ids the other task tools take. | ✓ | — |
AddMyTask | Add My Task | Add a task to the user's own checklist, optionally attached to a stock and/or given a due date. | — | — |
CompleteMyTask | Complete My Task | Check a task off the user's checklist. With a stock attached (and the user's journal-line preference on) this also writes a private note on that stock — exactly what checking it off on the desk does. | — | — |
EditMyTask | Edit My Task | Change a task's text, the stock it is attached to, and/or its due date — each independently; clear flags remove an attachment or a date. | — | — |
ReorderMyTasks | Reorder My Tasks | Set the order of the user's open tasks. Says so when the list's sort is not "My order", where the new order would not show. | — | — |
DeleteMyTask | Delete My Task | Delete a task from the user's checklist, open or done. | — | ✓ |
AddFinancialRatio | Add Financial Ratio (admin) | Admin-only: add or update a financial ratio for a stock. | — | ✓ |
ListNews | List News | List news items (press releases), newest first, with optional ticker/date/source filters, free-text search across headline, company name and ticker, and pagination. Each item says whether it is an earnings release — one that put a row on the earnings calendar — and can be filtered to only those. | ✓ | — |
GetEarningsCalendar | Get Earnings Calendar | When the companies you follow report. Every row is a date the company itself made public — there are no estimates or predictions, so a company with no row has simply not announced or reported, which is the normal case. One row per company and fiscal period: Scheduled (the company announced this date; links the release) or Reported (the results release is out; links it, and flags when InvestJournal's ratios still predate it). Default window: 14 days back to 90 days ahead; scope watched / held / all. | ✓ | — |
AddNewsItem | Add News Item (admin) | Admin-only: manually add a news item (press release) to the Latest News feed and, when the ticker matches, a stock's page. Insert-only; duplicate URLs are rejected. | — | — |
EditNewsItem | Edit News Item (admin) | Admin-only: update an existing news item (matched by sourceUrl) — fix a wrong headline, date, source, body, or stock link. | — | ✓ |
DeleteNewsItem | Delete News Item (admin) | Admin-only: soft-delete a news item (matched by sourceUrl) so it no longer appears in the feeds. | — | ✓ |
ReportNewsDigest | Report News Review Digest (admin) | Admin-only: files one GitHub issue for a news-ingestion run — the leftovers a human must finish, and/or the run's own statistics. A clean run with statistics files a closed record; a clean run with neither files nothing. | — | — |
MarkEarningsEvent | Mark Earnings Event (admin) | Admin-only: records what a stored press release means for the earnings calendar — a results release marks the fiscal period reported, a date announcement marks it scheduled. One row per stock and period; a correction re-issue updates the same row, and a results release is never downgraded. An annual results release records the company's fiscal year-end month when none is known yet; if one is already recorded and the label disagrees, the stored month wins and the reply says so. | — | — |
ListRefreshDue | List Refresh Due (admin) | Admin-only: the Koyfin refresh queue — stocks whose latest results release is newer than the ratios we hold, held/watched first, each with its probe backoff state (due / waiting / parked) and, for the calling admin, valuations still running on pre-report inputs. Read-only; the importer is a local tool. | ✓ | — |
ReportRefreshQueue | Report Refresh Queue (admin) | Admin-only: rewrites the one rolling ratio-refresh GitHub issue from the refresh queue — created when the queue is non-empty, updated while it stays so, closed when it empties. Never one issue per stock. | — | — |
ListSuspectValuations | List Suspect Valuations (admin) | Admin-only: the calling admin's own DCF valuations that look wrong, loudest first — the stored fit price is more than 10% from the close we hold for the day it was fitted — 10% sits above the measured quote-vs-close noise floor, so a flagged row is a real currency or unit error rather than quote timing (never today's close: a fitted price is supposed to differ from today's), we have never priced that stock, or the company reported after the valuation was made. Judges only the chosen valuation per stock. Read-only; it repairs nothing. | ✓ | — |
GetDcfValuations | List DCF Valuations | Your most recent DCF valuations for a stock (up to 10, newest first) with intrinsic values. Valuations are private per user — this never returns anyone else's. | ✓ | — |
GetLatestDcf | Latest DCF | Most recent DCF valuation for a stock. | ✓ | — |
CalculateDcf | Calculate DCF | Compute a hypothetical DCF intrinsic value from raw inputs without persisting anything. | ✓ | — |
SaveDcfValuation | Save DCF Valuation | Create and persist a new DCF valuation for a stock (app-standard discount/terminal bands). | — | — |
DeleteDcfValuation | Delete DCF Valuation | Soft-delete one of the user's own DCF valuations by id. | — | ✓ |
SetDcfVerdict | Set DCF Verdict | Set the user's manual verdict (Undervalued / FairlyValued / Overvalued) on a DCF valuation. | — | — |
GetStockComments | Get Comments | The user's notes for a stock (privacy-filtered). | ✓ | — |
SearchComments | Search Comments | Substring search across the user's comments. | ✓ | — |
AddStockComment | Add Comment | Save a private note, or post a public comment, on a stock. | — | — |
DeleteStockComment | Delete Comment | Delete one of the user's own comments by id. | — | ✓ |
EditStockComment | Edit Comment | Edit (overwrite) the text of one of the user's own comments by id. | — | ✓ |
SetCommentPrivacy | Set Comment Privacy | Convert one of the user's own entries between a private note and a public comment, by id. | — | — |
GetThesis | Get Thesis | The user's investment thesis for a stock, with revision history. | ✓ | — |
UpsertThesis | Upsert Thesis | Create or update the user's thesis (every save records a revision). | — | ✓ |
ListAlerts | List Alerts | The user's price alerts. | ✓ | — |
CreateAlert | Create Alert | Create a price alert for a stock (requires an existing DCF valuation). | — | — |
UpdateAlert | Update Alert | Update an alert's threshold price and/or expiration date by id. | — | — |
SetAlertEnabled | Set Alert Enabled | Enable or disable one of the user's alerts by id. | — | — |
DeleteAlert | Delete Alert | Permanently delete one of the user's alerts by id. | — | ✓ |
ListPortfolios | List Portfolios | Every portfolio (of up to five) the user has — name, active account count, position count, writable and archived flags. Carries no monetary value: portfolios are never combined into one figure. Use it to learn the names to pass as portfolio to every tool below. | ✓ | — |
ListHoldings | List Holdings | What the user owns: positions with cost basis, unrealized P&L and allocation, grouped by currency (never FX-converted, so there is no combined total). Each currency's asserted cash balance, when set, is included and already folded into that group's subtotal. Optional account by name returns only that account's groups. Optional portfolio by name; omitted, resolves the caller's default and names it in the reply. | ✓ | — |
ListPortfolioTransactions | List Portfolio Transactions | The portfolio ledger, newest first — buys, sells, opening positions and adjustments. Optional filters by stock, type and year, applied over the whole ledger. Optional portfolio by name; omitted, resolves the caller's default and names it in the reply. | ✓ | — |
SharesHeldOn | Shares Held On | Shares of one stock held at the end of a given date — what a back-dated sell is validated against. Scoped to one account, like the sell guard itself: with 2+ accounts the account name is required. Optional portfolio by name; omitted, resolves the caller's default and names it in the reply. | ✓ | — |
AddPortfolioTransaction | Add Portfolio Transaction | Record a buy or sell, or assert a position with an opening/adjustment. Holdings recompute from the ledger. With 2+ active portfolios, the portfolio name is required — an unqualified write refuses and lists them rather than guessing. | — | — |
SetOpeningPositions | Set Opening Positions | Start tracking an existing portfolio: every position and its cash as of one date, saved as a single all-or-nothing batch. Optional tax treatment (Tax-free/Tax-deferred/Taxable) for the account it creates — only set from what the user actually said, never guessed from the account's name; omitted, an existing account keeps the treatment it has. With 2+ active portfolios, the portfolio name is required. | — | — |
SetCashBalance | Set Cash Balance | Assert one currency's cash balance — replaces the previous figure, never a deposit/withdrawal ledger entry. Every other currency is untouched. Omit amount to REMOVE the balance and stop tracking that currency (different from 0, which asserts none is held). The currency must be one the account holds. Optional backdated asOf; the app's own cash sheet always uses today. With 2+ active portfolios, the portfolio name is required. | — | — |
EditPortfolioTransaction | Edit Portfolio Transaction | Overwrite one ledger row by id (whole-row replace). Holdings re-fold from the ledger. With 2+ active portfolios, the portfolio name is required. | — | ✓ |
DeletePortfolioTransaction | Delete Portfolio Transaction | Remove one ledger row by id. Later average costs and the current position for that stock are recomputed. With 2+ active portfolios, the portfolio name is required. | — | ✓ |
ListAccounts | List Accounts | The portfolio's name and its accounts (wrappers) — name, currencies held, archived flag, and how the user says it's taxed (Tax-free/Tax-deferred/Taxable, or null if never said — never inferred from the name). Used to disambiguate before a write and to echo the user's own nouns back. Optional portfolio by name; omitted, resolves the caller's default and names it in the reply. | ✓ | — |
CreateAccount | Create Account | Create a new, empty account (wrapper) — e.g. "My RRSP" holding USD. Currency can widen to both later, never narrow once used. Optional tax treatment (Tax-free/Tax-deferred/Taxable) — only set from what the user actually said, never guessed from the account's name. With 2+ active portfolios, the portfolio name is required. | — | — |
RenameAccount | Rename Account | Rename an account by its current name (case- and article-insensitive) without touching its positions, and/or change which currencies it holds (CAD/USD/Both) and how it's taxed (Tax-free/Tax-deferred/Taxable, or None to clear it) — an omitted value leaves the stored one untouched, never guessed from the name. Currency widens freely; narrowing is refused while the dropped currency is still held. With 2+ active portfolios, the portfolio name is required. | — | — |
ArchiveAccount | Archive Account | Archive an EMPTY account (wrapper) — it leaves the portfolio page and accepts no new writes, while its journal history stays readable. Refuses an account holding open positions or cash: a card that can hide money must not be hideable. A fully exited history is fine. Nothing is deleted. With 2+ active portfolios, the portfolio name is required. | — | ✓ |
CreatePortfolio | Create Portfolio | Create a new, empty portfolio — its own accounts, transactions and cash, kept separate from the user's others. How many may be active is a plan limit (one free, five Pro); at the limit the tool is refused. Names must be unique per user, case-insensitively. | — | — |
RenamePortfolio | Rename Portfolio | Rename a portfolio (of up to five) — the container the accounts live in. Empty name is refused. With 2+ active portfolios, portfolio says which one by its current name. | — | — |
ListDocuments | List Documents | Uploaded PDFs for a stock with processing status. | ✓ | — |
AskDocument | Ask Question on Documents | RAG query on a stock's uploaded PDFs (uses Gemini API credits). | ✓ | — |
WhoAmI | Who Am I | Report which account the session is signed in as (email and user ID) and whether it has admin privileges. | ✓ | — |
LogoutFromMcp | Disconnect | End the session: revoke the user's MCP refresh tokens and invalidate the current access token immediately (rejected on the next request). Restart your MCP client to sign in as a different account. | — | ✓ |
ListStocks)ListStocks is paginated and may return a partial list. It accepts these optional parameters:
| Parameter | Default | Meaning |
|---|---|---|
limit | 50 | Max stocks per page; clamped to the range 1–200. |
cursor | — | Opaque token from the previous response's nextCursor. Omit for the first page; keep calling with it while hasMore is true. |
nameOrTickerPrefix | — | Case-insensitive prefix match on stock name or ticker. |
currency | — | Exact, case-insensitive currency filter (e.g. USD, CAD). |
The response is an object { stocks, total, limit, hasMore, nextCursor } — always check total and hasMore before concluding a stock is absent; it may simply be on a later page.
The server ships four named MCP prompts — they appear as clickable entries in the + menu of claude.ai and Claude Desktop once the connector is added. Each one walks Claude through a multi-tool workflow so you don't have to compose it yourself. (Prompts are available on the remote connector; local stdio mode exposes tools only.)
| Prompt | Title | What it does | Arguments |
|---|---|---|---|
show_me_around | Show me around | Guided tour: checks who you are, looks at your watchlists, and demonstrates one real insight with your own data. | — |
analyze_stock | Analyze a stock end-to-end | Full research brief on one stock: summary, ratios, reverse-DCF vs price, recent news, price history. | ticker |
weekly_portfolio_review | Weekly portfolio review | What changed this week: watchlist ranking, news, alerts, and valuation drift for the most interesting names. | — |
build_first_watchlist | Build my first watchlist | Starts from zero: finds companies you care about and saves them to a new watchlist (needs write access). | — |
The server also ships initialize-time instructions: if your first message is vague ("hi", "what can you do?"), Claude demonstrates with your real data instead of listing tools; a concrete request is simply fulfilled.
These prompts are designed for an Anthropic reviewer using the seeded test account. Each demonstrates a representative tool path.
"Show me a summary of every stock I'm tracking, ordered by my watchlist priority. For my top 3, include the latest DCF intrinsic value and ROE."
Expected behaviour: Claude calls ListWatchlists → GetWatchlistStocks → GetLatestDcf → GetStockRatios, composes a multi-stock summary.
"Add a comment to AAPL: 'Re-reviewed Q3 — services revenue growth holding at 13% y/y, watching for hardware refresh cycle.' Keep it as a private note."
Expected behaviour: Claude calls AddStockComment(ticker="AAPL", text="...", isPrivate=true). Per MCP conventions for readOnlyHint: false tools, Claude confirms with the user before invoking.
"For NVDA, what does the latest annual report say about competitive risks from custom silicon?"
Expected behaviour: Claude calls ListDocuments(ticker="NVDA") to find the annual report, then AskDocument(ticker="NVDA", question="...") which performs RAG over the PDF.
Read the full policy at /privacy. Summary: this server only accesses data the authenticated user owns; only the AskDocument tool sends data to a third party (Google Gemini) and only for RAG queries; all OAuth tokens are revocable.
For issues, account requests, or questions: [email protected].