mirror of
https://github.com/0xrsydn/idx-cli.git
synced 2026-11-07 09:45:36 +00:00
Merge pull request #73 from 0xrsydn/feat/stockbit
feat: login-free Stockbit intraday and quote provider
This commit is contained in:
commit
be9d17bb80
157 changed files with 14699 additions and 481 deletions
|
|
@ -31,7 +31,7 @@ export default defineConfig({
|
|||
},
|
||||
{
|
||||
label: 'CLI',
|
||||
items: ['cli/stocks', 'cli/ownership', 'cli/output', 'cli/reference'],
|
||||
items: ['cli/stocks', 'cli/stockbit', 'cli/ownership', 'cli/output', 'cli/reference'],
|
||||
},
|
||||
{
|
||||
label: 'MCP server',
|
||||
|
|
@ -56,7 +56,7 @@ export default defineConfig({
|
|||
projectName: 'idx-cli',
|
||||
details: [
|
||||
'- `idx` is a CLI; `idx-mcp` is an MCP server over the same library. Both read the same config, cache and ownership database.',
|
||||
'- Output is JSON whenever stdout is not a terminal. Errors are one JSON object on stderr; exit codes: 2 invalid input, 3 not found, 4 upstream unavailable, 5 unsupported, 1 other.',
|
||||
'- Output is JSON whenever stdout is not a terminal. Errors are one JSON object on stderr; exit codes: 2 invalid input, 3 not found, 4 upstream unavailable or blocked, 5 unsupported, 1 other.',
|
||||
'- Every page is also available as Markdown by appending `.md` to its path, for example `/agents/install.md`.',
|
||||
].join('\n'),
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ description: Every idx-mcp tool and its inputs, generated from the server's tool
|
|||
idx-mcp serves these tools. `ownership_sync` is listed only when the server
|
||||
starts with `--allow-sync`. Results that come from a live provider are wrapped
|
||||
as `{data, source, fetched_at, stale}`; failures return `{error, code,
|
||||
message}` with `isError` set.
|
||||
message}` with `isError` set. Either may carry `warnings`, what idx worked
|
||||
around (such as a history fallback or a stale cache entry), when there was
|
||||
any.
|
||||
|
||||
EOF
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,14 @@ What an agent needs to know:
|
|||
- On failure stdout is empty and stderr holds one JSON object,
|
||||
`{"error": true, "code": "...", "message": "..."}`.
|
||||
- Exit codes say what to do next: `2` fix the input, `3` not found (or no
|
||||
cached data offline), `4` provider unavailable, retry later, `5`
|
||||
cached data offline), `4` provider unavailable or blocked, retry later, `5`
|
||||
unsupported, `1` other.
|
||||
- Tickers are IDX codes (`BBCA`); `.JK` is optional. Several tickers can be
|
||||
passed at once to `stocks quote` and `stocks compare`.
|
||||
- `stocks intraday` and `--provider stockbit` read Stockbit's public page,
|
||||
paced to one request a second across idx processes. Ask for the symbols
|
||||
you need rather than looping over the market; on `UPSTREAMBLOCKED`, stop
|
||||
instead of retrying.
|
||||
- Ownership queries need `idx ownership sync` once; after that they run
|
||||
offline. `idx -o json ownership releases` shows which months exist.
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ stdout is not a terminal, and with `--no-color`.
|
|||
| `0` | success | |
|
||||
| `2` | invalid input or config | fix the command |
|
||||
| `3` | not found, no data, or no cached data offline | check the ticker or name; go online |
|
||||
| `4` | upstream unavailable | retry later |
|
||||
| `4` | upstream unavailable or blocked | retry later; for `UPSTREAMBLOCKED`, wait or change network |
|
||||
| `5` | unsupported | use another command or provider |
|
||||
| `1` | anything else | read the message |
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,34 @@ two releases. `ticker` also reports concentration: the top holder's share,
|
|||
the top three, the Herfindahl index (HHI) and the free float (shares held by
|
||||
holders below 1%).
|
||||
|
||||
## Insider and major holder movements
|
||||
|
||||
With your own Stockbit login (`idx stockbit login`, see [Stockbit](/cli/stockbit/)),
|
||||
`movements` lists reported changes in holders' stakes, newest first. It reads
|
||||
Stockbit live and needs no import:
|
||||
|
||||
```bash
|
||||
idx ownership movements BBCA # one stock, 50 rows
|
||||
idx ownership movements # the whole market
|
||||
idx ownership movements --action sell --source ksei --pages 3
|
||||
idx ownership movements --from 2026-10-01 --to 2026-10-31
|
||||
idx ownership movements --holder 1000004481 # one holder's history
|
||||
```
|
||||
|
||||
Two sources share the list. `IDX` rows are insider disclosures: directors,
|
||||
commissioners and other insiders, at any size, with the trade price. `KSEI`
|
||||
rows are changes of holders at 5% and above, which report no price; Stockbit
|
||||
estimates one, shown with `~`. `--holder` takes the number in the HOLDER ID
|
||||
column. Shares are exact. Stakes are as Stockbit rounds them, so a director's
|
||||
small holding reads `<0.01%`.
|
||||
|
||||
These are filings, not signals. Many insiders buying at one price on one day
|
||||
is usually a share plan, transfers are not trades, and a row appears days
|
||||
after the change. Each page is 50 rows and one request to Stockbit (`--pages`
|
||||
up to 10); a query's pages are read and cached together, for an hour. JSON's
|
||||
`more` says rows remain past them. If a later page fails, you get the rows
|
||||
read before it, with `incomplete` saying why, and nothing is cached.
|
||||
|
||||
## Import reports yourself
|
||||
|
||||
The snapshot covers most needs. To load a month it lacks, or older history,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
239
web/src/content/docs/cli/stockbit.md
Normal file
239
web/src/content/docs/cli/stockbit.md
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
---
|
||||
title: Stockbit
|
||||
description: Today's session by the minute and quotes with best bid/offer from Stockbit's public page, plus the order book and live quotes with your own Stockbit login. Both opt-in.
|
||||
---
|
||||
|
||||
[Stockbit](https://stockbit.com)'s public symbol page carries a quote, the
|
||||
best bid and offer, and today's price for every minute of the session. idx
|
||||
reads that page directly. It needs no Stockbit account, no login and no
|
||||
helper tools. With your own Stockbit account, idx can also read the order
|
||||
book and live quotes; see [With your Stockbit login](#with-your-stockbit-login).
|
||||
|
||||
```bash
|
||||
idx stocks intraday BBCA # today's session, by the minute
|
||||
idx stocks intraday ^JKSE # an index (or IHSG, LQ45)
|
||||
idx --provider stockbit stocks quote BBCA # quote with bid/offer
|
||||
idx -o json stocks intraday BBCA | jq '.points | length'
|
||||
```
|
||||
|
||||
## What you get
|
||||
|
||||
| | `stocks intraday` | `--provider stockbit stocks quote` |
|
||||
| --- | --- | --- |
|
||||
| Price, change, previous close, volume | yes | yes |
|
||||
| Best bid and offer | while the market is open | while the market is open |
|
||||
| Market status (`market_status`) | yes | yes |
|
||||
| Price per minute (`points`) | yes | no |
|
||||
| Market cap, 52-week range | no | no |
|
||||
|
||||
- **Delayed.** Stockbit's terms describe its market data as "a real-time
|
||||
snapshot, delayed at least 10 minutes". It is not a live feed.
|
||||
- **Bid and offer only while trading.** Outside the session, Stockbit still
|
||||
shows the book as it closed. idx leaves `bid` and `offer` out then, so the
|
||||
closing book never passes for a live one.
|
||||
- **Top of the book only.** One bid and one offer price, no depth. The full
|
||||
order book needs your [Stockbit login](#with-your-stockbit-login).
|
||||
- **Prices only.** The page has no per-minute volume or OHLC.
|
||||
- **Empty sessions are data.** A suspended or delisted stock answers with
|
||||
`points: []` and a `session_note` saying so (`Stockbit lists the stock as
|
||||
suspended`). An active stock with no volume says `no trades this session`,
|
||||
even when its chart is a flat line at the previous close. Neither is an
|
||||
error.
|
||||
|
||||
`--provider stockbit` (or `IDX_PROVIDER=stockbit`, or
|
||||
`idx config set general.provider stockbit`) changes only where quotes come
|
||||
from. Without a login, history still comes from Yahoo. Company data,
|
||||
fundamentals and screening answer `UNSUPPORTED` under it, so use MSN for
|
||||
those.
|
||||
|
||||
## How idx talks to Stockbit
|
||||
|
||||
- One request per symbol to `https://stockbit.com/symbol/<CODE>`, at least one
|
||||
second apart across all your idx processes (a shell loop of `idx` calls
|
||||
included), cached for 5 seconds.
|
||||
- An honest user agent, `idx-cli/<version> (+https://github.com/0xrsydn/idx-cli)`,
|
||||
not a browser disguise. Stockbit's CDN refuses some generic agents
|
||||
(`curl/…`) outright but lets this one through. No curl-impersonate
|
||||
needed.
|
||||
- No retries. If Stockbit's CDN refuses your machine, the command fails at
|
||||
once with `UPSTREAMBLOCKED` (exit `4`):
|
||||
|
||||
```json
|
||||
{"error":true,"code":"UPSTREAMBLOCKED","message":"upstream blocked: stockbit.com refused this client (HTTP 403 from its CDN); ..."}
|
||||
```
|
||||
|
||||
Wait, or try from another network. `--provider msn` serves quotes without
|
||||
Stockbit.
|
||||
|
||||
## With your Stockbit login
|
||||
|
||||
Opt-in, and only with your own account. idx then talks to Stockbit's own API
|
||||
(`exodus.stockbit.com`) with your session's tokens.
|
||||
|
||||
```bash
|
||||
idx stockbit login # paste the credentialStorage cookie
|
||||
idx stockbit status # logged in? when do the tokens expire?
|
||||
idx stocks orderbook BBCA # depth, queued orders, foreign flow
|
||||
idx stocks orderbook BBRI --depth 5
|
||||
idx stocks actions BBCA # dividends, splits, meetings, ...
|
||||
idx stocks calendar --kind dividend # cum dates in the next 30 days
|
||||
idx ownership movements BBCA # insider and major holder buys and sells
|
||||
idx --provider stockbit stocks quote BBCA # live, not delayed
|
||||
idx --provider stockbit stocks history BBCA --period 1y # Stockbit's daily candles
|
||||
idx stockbit logout
|
||||
```
|
||||
|
||||
**Logging in.** `idx stockbit login` opens Chrome (or Chromium, Edge, Brave,
|
||||
Helium) on Stockbit's own sign-in page, in a browser profile only idx uses. Sign in
|
||||
there as usual, including any one-time code: idx reads the
|
||||
session cookie over the DevTools protocol, checks it with one request, and
|
||||
closes the window. Your password never reaches idx. The profile sits beside
|
||||
`config.toml`; idx takes the session cookie out of it once the session is
|
||||
stored, so the profile keeps only Stockbit's device cookies. The profile
|
||||
stays with the browser that made it: idx opens the same one next time, unless
|
||||
`IDX_STOCKBIT_BROWSER` names another. Choose your browser that way on the
|
||||
first sign-in if you have several.
|
||||
|
||||
Use your Stockbit password in that window. Google can refuse to sign in there
|
||||
with "This browser or app may not be secure", most likely because idx starts
|
||||
the browser with remote debugging on. If you only sign in with Google, use the
|
||||
local page below: sign in from a private window, paste the cookie, then close
|
||||
that window.
|
||||
|
||||
Run `login` again while the session is still good and there is nothing to
|
||||
do: idx checks it with one request and exits without opening a browser. The
|
||||
window it does open waits 15 minutes, and closes at once if you close it
|
||||
yourself.
|
||||
|
||||
**How long a session lasts.** Stockbit's refresh token is good for about a
|
||||
week, and idx spends it on every refresh, which extends the session. Use idx
|
||||
at least once a week and you stay signed in. A longer gap, a `logout`, or
|
||||
another tool spending the same token means one more sign-in.
|
||||
|
||||
Over SSH, on a machine with no display, without such a browser, or with
|
||||
`--no-browser`, idx serves a small page on your own machine (127.0.0.1, port
|
||||
7878 when it is free) instead. With
|
||||
stockbit.com open and logged in, click the page's **Send my Stockbit
|
||||
session** bookmarklet: it reads Stockbit's `credentialStorage` cookie in your
|
||||
browser and hands it to the page, which checks it with one request and says
|
||||
"Connected". If bookmarklets are blocked, click **Paste from clipboard**
|
||||
after copying the cookie, or paste it into the box. `--port` picks another
|
||||
port. Piping the value in still works
|
||||
(`pbpaste | idx stockbit login`), as does a refresh token on its own. On a
|
||||
server, set `IDX_STOCKBIT_REFRESH_TOKEN`. Set `IDX_STOCKBIT_BROWSER` to use a
|
||||
browser idx does not find on its own.
|
||||
|
||||
The session lands in `~/.config/idx/stockbit-session.json`, readable only by
|
||||
you. On macOS without `XDG_CONFIG_HOME` that is
|
||||
`~/Library/Application Support/idx/` instead; idx finds a session in either
|
||||
one, so the CLI and an MCP client started from the Dock share it. Tokens never appear in output, logs or errors. The page takes only the
|
||||
session value, keeps it in memory, and closes when it is done (or after five
|
||||
minutes). A session Stockbit refuses leaves a previously stored one in place.
|
||||
|
||||
## Remote and headless
|
||||
|
||||
The page listens on this machine's loopback interface only, and the browser
|
||||
handoff needs a browser on this machine too. On a server, in a container, or
|
||||
in a WSL distro, `127.0.0.1` is a different machine and neither will load.
|
||||
Three ways around that, in order of how little they ask of you.
|
||||
|
||||
**Pipe the cookie over SSH.** No tunnel, one command. Copy the
|
||||
`credentialStorage` value on the machine with the browser (DevTools,
|
||||
Application, Cookies), then:
|
||||
|
||||
```bash
|
||||
pbpaste | ssh <host> "idx stockbit login"
|
||||
```
|
||||
|
||||
idx reads stdin, verifies the session, and stores it on the server. The value
|
||||
never reaches a shell history or a file.
|
||||
|
||||
**Forward the page.** Run the page on the server and forward its port from the
|
||||
machine with the browser:
|
||||
|
||||
```bash
|
||||
idx stockbit login # on the server: over SSH, it serves the page
|
||||
ssh -L 7878:127.0.0.1:7878 <host> # where the browser is, keep it open
|
||||
```
|
||||
|
||||
Then open the printed URL there and click the bookmarklet. Over SSH, idx
|
||||
notices `SSH_CONNECTION`, skips the browser, and prints the exact forward
|
||||
itself.
|
||||
|
||||
**Seed a token.** For anything unattended, keep the refresh token in a secret
|
||||
store and pass it at run time:
|
||||
|
||||
```bash
|
||||
op run --env-file=stockbit.env -- idx stocks orderbook BBCA
|
||||
```
|
||||
|
||||
where the file holds `IDX_STOCKBIT_REFRESH_TOKEN=op://Private/stockbit/refresh`.
|
||||
Only the refresh token is needed; idx mints its own access token.
|
||||
|
||||
**Agents.** Over MCP, an agent calls `stockbit_login`, which answers at once
|
||||
and does the same as `idx stockbit login`. Where idx-mcp runs on your desktop,
|
||||
a browser window opens on Stockbit's sign-in page (`"method": "browser"`) and
|
||||
you sign in there. Over SSH or without a display, the answer carries the page
|
||||
URL and its `ssh -L` forward (`"method": "page"`) for the agent to hand you.
|
||||
The agent then polls `stockbit_status` until `sign_in.state` is `signed_in`
|
||||
or `failed`. While it waits, `sign_in.warning` carries the latest problem, such
|
||||
as Stockbit refusing the session you signed in with, so the agent can tell you
|
||||
to sign in again. A session that already works answers `signed_in` without opening
|
||||
anything, a second call while one is waiting returns it again, and
|
||||
`{"method": "page"}` or `{"method": "browser"}` picks the way. If the server
|
||||
stops while the window waits, the window closes with it.
|
||||
|
||||
One rule for all three: only one machine may own a session. Stockbit retires
|
||||
the refresh token on every refresh, so a token copied to two machines signs the
|
||||
other one out. Two machines need two sign-ins.
|
||||
|
||||
**One refresher per session.** Stockbit replaces the refresh token every time
|
||||
it is used. Once idx refreshes your session, a browser holding the same
|
||||
session has to log in again, and two tools sharing one session log each
|
||||
other out. `idx stockbit login` keeps its own browser profile, so this only
|
||||
affects a browser you use yourself. idx processes on one machine take turns
|
||||
through a lock, so they never spend the token twice.
|
||||
|
||||
What the login adds:
|
||||
|
||||
| | Without a login | With your login |
|
||||
| --- | --- | --- |
|
||||
| `--provider stockbit` quotes | public page, delayed | Stockbit's API, live |
|
||||
| Bid and offer in quotes | best price, while open | best price, while open |
|
||||
| `market_status` in quotes | `open` or `close` | `open` or `close` |
|
||||
| `stocks orderbook` | `AUTHERROR` | every level with lots and queued orders, OHLC, value, trades; foreign buy/sell/net once Stockbit marks them current |
|
||||
| `stocks history` under `--provider stockbit` | Yahoo | Stockbit's daily candles for `5d` to `1y`; Yahoo for other windows |
|
||||
| `stocks intraday` | public page | public page |
|
||||
| `stocks actions`, `stocks calendar` | `AUTHERROR` | corporate actions: one stock's history, or the market's calendar |
|
||||
| `ownership movements` | `AUTHERROR` | insider and major holder buys and sells, as reported to IDX and KSEI |
|
||||
|
||||
The order book is what Stockbit's own app shows. Outside trading it is the
|
||||
book as the market left it, and the output says so. Foreign buy, sell and net
|
||||
appear only when Stockbit marks them current: during trading its figures are
|
||||
the previous session's, so idx leaves them out (`stocks flow` has foreign
|
||||
flow session by session). Sizes are lots in the
|
||||
table and shares in JSON. `--history-provider stockbit` asks for Stockbit's
|
||||
candles explicitly; windows it charts only weekly or hourly (`2y`, `5y`,
|
||||
`1wk`) answer `UNSUPPORTED`. If Stockbit refuses a stored session, `auto`
|
||||
history falls back to Yahoo with a warning; an explicit
|
||||
`--history-provider stockbit` fails with `AUTHERROR`.
|
||||
|
||||
`market_status` in quotes is `open` while the regular market trades and
|
||||
`close` otherwise, including the lunch break and auctions, with or without a
|
||||
login. `stocks orderbook` keeps Stockbit's state verbatim
|
||||
(`STATE_NAME_SESSION_2`, `STATE_NAME_BREAK`, ...).
|
||||
|
||||
## Terms
|
||||
|
||||
Stockbit's [terms](https://stockbit.com/terms) allow its content for personal,
|
||||
non-commercial use. They prohibit data mining, robots and redistribution
|
||||
without Stockbit's written consent, which includes serving the data to other
|
||||
people through `idx-mcp`. idx is not affiliated with or endorsed by
|
||||
Stockbit. Use this for looking at a stock now and then, not for crawling the
|
||||
market or republishing prices. With your login, automated use is tied to your
|
||||
account: keep it human-paced.
|
||||
|
||||
Over MCP, the same data comes from `get_intraday`, `get_orderbook`,
|
||||
`get_corporate_actions`, `get_corporate_calendar`, `get_shareholder_movements` and `stockbit_status`, and from `get_quotes` and `get_price_history` when the
|
||||
server runs with `IDX_PROVIDER=stockbit`. The server never logs in; run
|
||||
`idx stockbit login` in a terminal.
|
||||
|
|
@ -19,6 +19,61 @@ session, the table says so under it, and JSON sets `behind_session`: the
|
|||
provider may still show the previous close. `history` takes `--period` (`1d`
|
||||
to `5y`) and `--interval` (`1d`, `1wk`, `1mo`).
|
||||
|
||||
## Today by the minute
|
||||
|
||||
```bash
|
||||
idx stocks intraday BBCA
|
||||
idx stocks intraday ^JKSE
|
||||
idx -o json stocks intraday BBCA | jq '.points[-1]'
|
||||
```
|
||||
|
||||
`intraday` shows today's session from Stockbit's public page, without a
|
||||
login: the quote, the best bid and offer while the market is open, a
|
||||
sparkline and the last five minutes. JSON gives every minute in `points`. It
|
||||
is delayed at least 10 minutes. A chart from before the latest session is
|
||||
noted under the header and sets `quote.behind_session`, as with quotes. See [Stockbit](/cli/stockbit/) for what it
|
||||
covers and the terms it comes with.
|
||||
|
||||
## Order book (Stockbit login)
|
||||
|
||||
```bash
|
||||
idx stocks orderbook BBCA
|
||||
idx stocks orderbook BBRI --depth 5
|
||||
```
|
||||
|
||||
With your own Stockbit session (`idx stockbit login`), `orderbook` shows
|
||||
every bid and offer level with lots and queued orders, the session's OHLC,
|
||||
value and trades, and foreign buy, sell and net once Stockbit marks them
|
||||
current (not during trading, when they lag a day). Without one it answers
|
||||
`AUTHERROR`. See [Stockbit](/cli/stockbit/#with-your-stockbit-login).
|
||||
|
||||
## Corporate actions (Stockbit login)
|
||||
|
||||
```bash
|
||||
idx stocks actions BBCA # newest first
|
||||
idx stocks actions TLKM --kind dividend
|
||||
idx stocks calendar # today and the next 30 days
|
||||
idx stocks calendar --kind dividend,rights --to 2026-12-31
|
||||
```
|
||||
|
||||
`actions` lists one stock's cash and stock dividends, bonus shares, rights
|
||||
issues, warrants, splits and reverse splits, shareholders' meetings, public
|
||||
exposes and tender offers (`--kind ipo` adds its IPO). `calendar` lists them
|
||||
across the market between `--from` and `--to` (at most 366 days), including
|
||||
what is announced ahead, plus rights trading, tender offers and IPO offers
|
||||
still open in that range, so an offer that began earlier still shows while
|
||||
you can act on it. An action's date is its cum date for dividends,
|
||||
bonuses, rights and splits: buy by then to be entitled. For the others it is
|
||||
the event's first day. When Stockbit gives no cum date, the action sits on
|
||||
its ex date, marked `(ex)` in the table, and JSON leaves `cum_date` out.
|
||||
Dividends per share keep their decimals (`Rp 3.8`); one not paid in Rupiah
|
||||
carries `currency` (e.g. `USD`). JSON's `kind` is the name `--kind` takes.
|
||||
|
||||
Both need your Stockbit session and answer `AUTHERROR` without one. Stockbit
|
||||
serves one kind per request, 1 s apart, so a first call with every kind takes
|
||||
about ten seconds; answers are then cached for 6 hours. `--kind` asks for
|
||||
less.
|
||||
|
||||
## Company data
|
||||
|
||||
| Command | What it shows |
|
||||
|
|
@ -142,6 +197,10 @@ idx stocks screen --filter high-dividend | jq -r '.[].symbol' | idx stocks compa
|
|||
|
||||
MSN is the default for quotes, company data and screening; Yahoo serves
|
||||
price history. Indo Premier (IPOT) serves broker summaries and foreign flow
|
||||
(IDX's own site with `flow --source idx`), whichever provider is selected. Switch with `IDX_PROVIDER=msn|yahoo` and
|
||||
`IDX_HISTORY_PROVIDER=auto|yahoo|msn`, or the matching
|
||||
[config keys](/start/config/).
|
||||
(IDX's own site with `flow --source idx`), and Stockbit serves `intraday`
|
||||
and, with your login, `orderbook`, whichever provider is selected. Switch
|
||||
with `--provider msn|yahoo|stockbit` (or `IDX_PROVIDER`) and
|
||||
`IDX_HISTORY_PROVIDER=auto|yahoo|msn|stockbit`, or the matching
|
||||
[config keys](/start/config/). `--provider stockbit` serves quotes only, with
|
||||
the best bid/offer, live when you are logged in; see
|
||||
[Stockbit](/cli/stockbit/).
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ description: idx-mcp serves idx's stock and ownership data to AI agents over MCP
|
|||
|
||||
`idx-mcp` is a [Model Context Protocol](https://modelcontextprotocol.io)
|
||||
server over stdio. It gives an agent the same data as the `idx` CLI, as
|
||||
[14 tools](/mcp/tools/) (plus an opt-in `ownership_sync`): quotes, price history, screening, company data,
|
||||
analysis, comparison, broker summaries, bandarmology, foreign flow, and the KSEI
|
||||
ownership queries.
|
||||
[21 tools](/mcp/tools/) (plus an opt-in `ownership_sync`): quotes, today's
|
||||
session by the minute, the order book, corporate actions and insider movements (with a Stockbit
|
||||
login), price history, screening, company data, analysis, comparison, broker summaries,
|
||||
bandarmology, foreign flow, and the KSEI ownership queries.
|
||||
|
||||
It shares idx's [config, cache and ownership database](/start/config/#files-idx-keeps),
|
||||
so `idx ownership sync` in a terminal also feeds the server.
|
||||
|
|
@ -27,11 +28,26 @@ Tools that fetch live data return:
|
|||
}
|
||||
```
|
||||
|
||||
`source` is the provider (`msn` or `yahoo`). Results are cached on disk;
|
||||
`source` is the provider (`msn`, `yahoo`, `ipot`, `idx` or `stockbit`). Results are cached on disk;
|
||||
`stale` is true when an expired cache entry was served because a fresh fetch
|
||||
failed. Ownership tools return their data directly, from the local
|
||||
database.
|
||||
|
||||
What `idx` prints as a warning in a terminal comes back in `warnings`, on an
|
||||
answer or an error, when there was any. For example, history that fell back to
|
||||
Yahoo because Stockbit refused your session says so, and a stale answer names
|
||||
the failure behind it:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [{ "date": "2026-11-03", "close": 9875, "...": "..." }],
|
||||
"source": "yahoo",
|
||||
"fetched_at": "2026-11-04T03:20:11Z",
|
||||
"stale": false,
|
||||
"warnings": ["Stockbit rejected the session; run `idx stockbit login` again; history falls back to yahoo meanwhile"]
|
||||
}
|
||||
```
|
||||
|
||||
Errors come back as a tool result with `isError` set and the CLI's error
|
||||
body, so the agent can decide whether to retry:
|
||||
|
||||
|
|
@ -44,6 +60,8 @@ body, so the agent can decide whether to retry:
|
|||
| Input | Limit |
|
||||
| --- | --- |
|
||||
| tickers per call (`get_quotes`, `compare_stocks`) | 20, duplicates removed |
|
||||
| `get_intraday` `tail` | 400 minutes (default: the whole session) |
|
||||
| `get_orderbook` `depth` | 50 levels per side (default 10) |
|
||||
| `screen_stocks` `limit` | 200 |
|
||||
| `search_investors` `limit` | 100 |
|
||||
| `get_ownership_changes` `limit` | 300 per page (default 200); page with `offset` |
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ description: Every idx-mcp tool and its inputs, generated from the server's tool
|
|||
idx-mcp serves these tools. `ownership_sync` is listed only when the server
|
||||
starts with `--allow-sync`. Results that come from a live provider are wrapped
|
||||
as `{data, source, fetched_at, stale}`; failures return `{error, code,
|
||||
message}` with `isError` set.
|
||||
message}` with `isError` set. Either may carry `warnings`, what idx worked
|
||||
around (such as a history fallback or a stale cache entry), when there was
|
||||
any.
|
||||
|
||||
## `analyze_bandar`
|
||||
|
||||
|
|
@ -63,6 +65,25 @@ Company data for one IDX ticker: profile, financial statements, earnings, analys
|
|||
| `sections` | array of `profile` / `financials` / `earnings` / `sentiment` / `insights` / `news` | no | Sections to fetch (default: all). |
|
||||
| `symbol` | string | yes | IDX ticker, e.g. "BBCA". |
|
||||
|
||||
## `get_corporate_actions`
|
||||
|
||||
Corporate actions of one IDX stock from the user's own Stockbit session, newest first: `kind` (dividend, stock-dividend, bonus, rights, warrant, split, reverse-split, meeting, expose, ipo, tender), `date` (the cum date for dividends, bonuses, rights and splits, i.e. the last day to buy and be entitled, or the ex date when `cum_date` is absent; else the event's first day), `ex_date`, `record_date`, `pay_date`, and per kind `cash_per_share` (IDR, may have decimals; in `currency`, an ISO code, when that is present), `ratio` {old, new} (1:5 split = 1 share becomes 5; 655:104 rights = 104 rights per 655 held), `factor` (price adjustment), `price` (rights, warrant exercise, tender or IPO price, IDR), `period` and `exercise` {start, end}, `shares`, `percentage_bps`, `time`, `venue`. Absent fields are omitted. One Stockbit request per kind (about 1 s each on a cold cache, then cached 6 hours). AUTHERROR means there is no session: call stockbit_status, then stockbit_login.
|
||||
|
||||
| Input | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `kinds` | array of `dividend` / `stock-dividend` / `bonus` / `rights` / `warrant` / `split` / `reverse-split` / `meeting` / `expose` / `ipo` / `tender` | no | Kinds to list (default: every kind but "ipo"). Each kind is one request to Stockbit. |
|
||||
| `symbol` | string | yes | IDX ticker, e.g. "BBCA". |
|
||||
|
||||
## `get_corporate_calendar`
|
||||
|
||||
Corporate actions across IDX from the user's own Stockbit session, oldest first, dated from `from` to `to` (default today and the next 30 days), plus rights trading, tender offers and IPO offers still open in that range (their `period` overlaps it, though `date` may be earlier): upcoming cum dates, meetings, exposes, rights, warrants, IPOs and tender offers, and the past year. Each item has the same fields as get_corporate_actions, with `symbol`. One Stockbit request per kind (about 1 s each on a cold cache, then cached 6 hours); pass `kinds` to ask for less. AUTHERROR means there is no session: call stockbit_status, then stockbit_login.
|
||||
|
||||
| Input | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `from` | string | no | First day, YYYY-MM-DD (default today). |
|
||||
| `kinds` | array of `dividend` / `stock-dividend` / `bonus` / `rights` / `warrant` / `split` / `reverse-split` / `meeting` / `expose` / `ipo` / `tender` | no | Kinds to list (default: every kind). Each kind is one request to Stockbit. |
|
||||
| `to` | string | no | Last day, YYYY-MM-DD (default 30 days after `from`; at most 366 days). |
|
||||
|
||||
## `get_foreign_flow`
|
||||
|
||||
Foreign investors' buying and selling of one IDX ticker, session by session (oldest first), with range totals; end of day. With `source` "ipot" (default): `foreign_buy_value`, `foreign_sell_value` and `foreign_net_value` in IDR across all boards, `value` traded, and `foreign_share_bps` (foreign share of trading); share counts, close and `non_regular_bps` are null, and `rounded` = true means one decimal of precision. With "idx": exact foreign share counts on the regular board, values estimated at the session's average price, the close, `change_bps` and `non_regular_bps`.
|
||||
|
|
@ -75,6 +96,15 @@ Foreign investors' buying and selling of one IDX ticker, session by session (old
|
|||
| `symbol` | string | yes | IDX ticker, e.g. "BBCA". |
|
||||
| `to` | string | no | Last session of the range, YYYY-MM-DD (default today). |
|
||||
|
||||
## `get_intraday`
|
||||
|
||||
Today's session of one IDX stock or index from Stockbit's public page (no login), whichever provider the server uses: `quote` (price, change, volume, `market_status`, `bid`/`offer` only while the market is open, `session_note`) and `points`, the price per minute in WIB, oldest first. Delayed at least 10 minutes; no per-minute volume. Empty `points` means the stock did not trade this session (see `session_note`), not an error. `quote.behind_session` is true when the chart is from before the latest IDX session (a holiday, or Stockbit lagging), as in get_quotes. UPSTREAMBLOCKED means stockbit.com refused this machine (HTTP 403): do not retry at once.
|
||||
|
||||
| Input | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `symbol` | string | yes | IDX ticker, e.g. "BBCA"; indices as "^JKSE" or "IHSG". |
|
||||
| `tail` | integer | no | Only the latest N minutes (default: the whole session, at most 400). |
|
||||
|
||||
## `get_investor_holdings`
|
||||
|
||||
Every IDX holding (above 1%) of one investor, matched by name.
|
||||
|
|
@ -83,6 +113,15 @@ Every IDX holding (above 1%) of one investor, matched by name.
|
|||
| --- | --- | --- | --- |
|
||||
| `entity` | string | yes | Investor name or part of it, e.g. "DWIMURIA"; the closest match is used. |
|
||||
|
||||
## `get_orderbook`
|
||||
|
||||
Order book of one IDX stock from the user's own Stockbit session: `bids` and `offers` (best price first) of {price, shares, orders}, the session's OHLC, volume (shares), value and frequency, and foreign buy/sell/net in IDR (null while Stockbit marks them not current, as during trading; get_foreign_flow has them per session). `market_status` is Stockbit's state, verbatim: STATE_NAME_SESSION_1 or _2 is trading; in any other state the book is as the market left it. AUTHERROR means there is no session: call stockbit_status, then stockbit_login for a URL the user can open.
|
||||
|
||||
| Input | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `depth` | integer | no | Price levels per side (default 10, at most 50). |
|
||||
| `symbol` | string | yes | IDX ticker, e.g. "BBCA". |
|
||||
|
||||
## `get_ownership_changes`
|
||||
|
||||
Holder changes (new, exited, increased, decreased) between two KSEI release dates, optionally for one ticker. Rows come largest change first, one page at a time: `summary` covers all of them (counts by type, tickers with the most changes), and `next_offset` is the `offset` for the next page, or null after the last.
|
||||
|
|
@ -107,12 +146,26 @@ OHLCV price history for one IDX ticker.
|
|||
|
||||
## `get_quotes`
|
||||
|
||||
Latest quotes (price, change, volume, 52-week range, market cap) for one or more IDX tickers. `as_of` is the last trade in WIB; `behind_session` is true when that is before the latest IDX session, so the price is not that session's close: the provider lags, the stock did not trade, or the day was an exchange holiday.
|
||||
Latest quotes (price, change, volume, 52-week range, market cap) for one or more IDX tickers. `as_of` is the last trade in WIB; `behind_session` is true when that is before the latest IDX session, so the price is not that session's close: the provider lags, the stock did not trade, or the day was an exchange holiday. When the server runs with the stockbit provider, quotes also carry `market_status` ("open" while the regular market trades, else "close", with or without a login), `bid`/`offer` (best price, only while the market is open) and `session_note` (suspended, delisted, no trades); Stockbit data is delayed at least 10 minutes.
|
||||
|
||||
| Input | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `symbols` | array of string | yes | IDX tickers, e.g. ["BBCA", "BBRI"]; the `.JK` suffix is optional. At most 20. |
|
||||
|
||||
## `get_shareholder_movements`
|
||||
|
||||
Reported changes in insiders' and major holders' stakes in IDX stocks, from the user's own Stockbit session, newest first: IDX insider disclosures (directors, commissioners and other insiders, any size, with the trade price) and KSEI changes of holders at 5% and above (price estimated: `price_estimated`). One stock's, or the market's without `symbol`. Shares are exact and signed (`shares_change` < 0 is a sale); percentages are basis points as Stockbit rounds them, so a small insider can read 0. `more` is true when rows remain past `pages`; `incomplete`, when present, says a later page failed and the rows are those read before it (retry later for the rest). These are filings, not signals: many insiders buying at one price on one day is usually a share plan, and rows appear days after the change. AUTHERROR means there is no session: call stockbit_status, then stockbit_login.
|
||||
|
||||
| Input | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `action` | `buy` / `sell` / `transfer` / `cross` / `corporate-action` | no | Only this kind of movement; "corporate-action" covers rights issues, private placements and the like. |
|
||||
| `from` | string | no | First day, YYYY-MM-DD. |
|
||||
| `holder_id` | string | no | One holder's movements: the `holder_id` of a row. |
|
||||
| `pages` | integer | no | Pages of 50 rows (default 1, at most 10); each page is one request to Stockbit. |
|
||||
| `source` | `idx` / `ksei` | no | "idx" (insider disclosures, any size) or "ksei" (holders at 5% and above). |
|
||||
| `symbol` | string | no | IDX ticker, e.g. "BBCA"; omit for the whole market. |
|
||||
| `to` | string | no | Last day, YYYY-MM-DD. |
|
||||
|
||||
## `get_shareholders`
|
||||
|
||||
Shareholders above 1% of an IDX ticker from the latest KSEI release, with concentration metrics (top1, top3, HHI, free float).
|
||||
|
|
@ -153,3 +206,17 @@ Search investor names in the KSEI ownership database.
|
|||
| --- | --- | --- | --- |
|
||||
| `limit` | integer | no | Maximum results (default 20, at most 100). |
|
||||
| `query` | string | yes | Full-text query over investor names. |
|
||||
|
||||
## `stockbit_login`
|
||||
|
||||
Start a Stockbit sign-in and return at once; this call does not wait for it. With method auto (the default), idx-mcp opens a browser window on Stockbit's own sign-in page when its machine has a display and is not reached over SSH (`method: "browser"` in the answer): the user signs in there and the window closes by itself. Otherwise it serves a page on 127.0.0.1 (`method: "page"`, with `url` and an `ssh -L` `forward` for a browser on another machine) that takes stockbit.com's session cookie from the user's own browser. Never ask the user for their password, and never type it. Then poll stockbit_status until `sign_in.state` is signed_in or failed. A session that already works answers state signed_in without opening anything; a second call while one is waiting returns it again (`already_open`).
|
||||
|
||||
| Input | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `method` | `auto` / `browser` / `page` | no | "auto" (default): a browser window when idx-mcp's machine has a display and no SSH, else the local page; "browser" or "page" picks one. |
|
||||
|
||||
## `stockbit_status`
|
||||
|
||||
Whether a Stockbit session is stored (or seeded by IDX_STOCKBIT_REFRESH_TOKEN) and when its tokens expire; never the tokens. Without one, get_orderbook fails and stockbit-provider quotes use Stockbit's delayed public page; the user adds one with stockbit_login, or `idx stockbit login` in a terminal. After stockbit_login, `sign_in.state` says whether that sign-in is waiting, signed_in or failed (with `sign_in.error`). While it waits, `sign_in.warning` is the latest problem it hit, such as Stockbit refusing the session the user signed in with: pass it on, since the user may need to sign in again.
|
||||
|
||||
No inputs.
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ in scripts. Ask for JSON with `-o json`, `IDX_OUTPUT=json`, or
|
|||
|
||||
```toml
|
||||
[general]
|
||||
provider = "msn" # msn | yahoo
|
||||
history_provider = "auto" # auto | yahoo | msn
|
||||
provider = "msn" # msn | yahoo | stockbit
|
||||
history_provider = "auto" # auto | yahoo | msn | stockbit
|
||||
exchange = "JK"
|
||||
output = "auto" # auto | table | json | jsonl
|
||||
color = true
|
||||
|
|
@ -56,6 +56,8 @@ fundamental_ttl = 3600
|
|||
| `IDX_CACHE_FUNDAMENTAL_TTL` | `cache.fundamental_ttl` |
|
||||
| `IDX_OWNERSHIP_SNAPSHOT_MANIFEST` | `ownership.snapshot_manifest` |
|
||||
| `IDX_CURL_IMPERSONATE_BIN` | path to a `curl_chrome*` binary |
|
||||
| `IDX_STOCKBIT_REFRESH_TOKEN` | seeds a [Stockbit session](/cli/stockbit/#with-your-stockbit-login) when none is stored |
|
||||
| `IDX_STOCKBIT_ACCESS_TOKEN` | seeds the session's access token |
|
||||
|
||||
## Files idx keeps
|
||||
|
||||
|
|
@ -64,6 +66,7 @@ fundamental_ttl = 3600
|
|||
| Config | `~/.config/idx/config.toml` |
|
||||
| Cache | `~/.cache/idx/` (`idx cache info`, `idx cache clear`) |
|
||||
| Ownership database | `~/.local/share/idx/ownership.db` |
|
||||
| Stockbit session (after `idx stockbit login`) | `~/.config/idx/stockbit-session.json`, owner-only |
|
||||
|
||||
The MCP server reads the same config, cache and database.
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ Tickers are IDX codes; the `.JK` suffix is optional.
|
|||
idx stocks quote BBCA # one quote
|
||||
idx stocks quote BBCA BBRI BMRI # several (spaces or commas)
|
||||
idx stocks history BBCA --period 1y # daily OHLCV
|
||||
idx stocks intraday BBCA # today by the minute (Stockbit)
|
||||
idx stocks technical BBCA # trend, RSI, MACD, moving averages
|
||||
idx stocks fundamental BBCA # growth, valuation and risk together
|
||||
idx stocks compare BBCA BBRI BMRI # fundamentals side by side
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ TLKM.JK 2,250 <span class="up">+0.45%</span> 87,159,900
|
|||
<div>
|
||||
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M3 17l6-6 4 4 8-8"></path><path d="M15 7h6v6"></path></svg>
|
||||
<h2>Stocks</h2>
|
||||
<p>Quotes, OHLC history, financial statements and a screener. Technical, growth, valuation and risk analysis, and side-by-side compare.</p>
|
||||
<p>Quotes, today's session by the minute, OHLC history, financial statements and a screener. Technical, growth, valuation and risk analysis, and side-by-side compare.</p>
|
||||
<code>idx stocks fundamental BBRI</code>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -139,7 +139,7 @@ TLKM.JK 2,250 <span class="up">+0.45%</span> 87,159,900
|
|||
<div>
|
||||
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><rect x="4" y="7" width="16" height="12" rx="3"></rect><path d="M12 3v4M9 13h.01M15 13h.01"></path></svg>
|
||||
<h2>Agents</h2>
|
||||
<p>JSON whenever output is piped, errors as one JSON object, meaningful exit codes. Plus idx-mcp: 11 tools for any MCP client.</p>
|
||||
<p>JSON whenever output is piped, errors as one JSON object, meaningful exit codes. Plus idx-mcp: 17 tools for any MCP client.</p>
|
||||
<code>npx -y idx-mcp</code>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -219,7 +219,7 @@ TLKM.JK 2,250 <span class="up">+0.45%</span> 87,159,900
|
|||
<dl class="codes">
|
||||
<dt>2</dt><dd>invalid input or config</dd>
|
||||
<dt>3</dt><dd>not found, or no cached data offline</dd>
|
||||
<dt>4</dt><dd>upstream unavailable, retry later</dd>
|
||||
<dt>4</dt><dd>upstream unavailable or blocked, retry later</dd>
|
||||
<dt>5</dt><dd>unsupported</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue