loading…
Search for a command to run...
loading…
An MCP server that retrieves Japanese stock market data via J-Quants API v2.
An MCP server that retrieves Japanese stock market data via J-Quants API v2.
English | 日本語
An MCP (Model Context Protocol) server that retrieves Japanese stock market data via J-Quants API v2.
User-facing documentation site: https://shigechika.github.io/jquants-mcp/ (also available in 日本語) — start there if you want a gentler 5-minute introduction. This README is the technical reference (config schema, all 43 tools with parameter tables, deployment).
Release history and changelog: GitHub Releases.
Deployment shapes (stdio / Docker Compose / self-hosted HTTP / Cloud Run) and how to pick between them: see docs/deploy/.
24-second loop showing real output from the Claude iPhone app calling jquants-mcp tools:
get_sector_performanceget_top_turnover_valueget_candlestick_dataget_fins_summaryget_comparison_chart_dataIndividual frames are in docs/screenshots/.
# Using uv (recommended)
uv pip install jquants-mcp
# Using pip
pip install jquants-mcp
git clone https://github.com/shigechika/jquants-mcp.git
cd jquants-mcp
uv sync --dev
Settings are loaded with the following priority (later wins):
~/.jquants-api/jquants-api.toml — API key only (J-Quants official config)~/.config/jquants-mcp/config.ini (user global)./config.ini (current directory)If you already use jquants-api-client, your API key is automatically read from ~/.jquants-api/jquants-api.toml. No extra configuration needed.
jquants-mcp login
Opens a browser to J-Quants (AWS Cognito, PKCE flow), and on success writes the API key to ~/.config/jquants-mcp/config.ini (mode 0600). Same auth backend as the official jquants-cli. Use jquants-mcp logout to clear the saved key.
MCP-specific settings (cache, client behavior):
[jquants]
# cache_dir = ~/.cache/jquants-mcp
# base_url = https://api.jquants.com/v2
[client]
# max_retries = 5
# retry_base_delay = 1.0
# max_pages = 10
[server]
# ssl_certfile = /path/to/fullchain.pem
# ssl_keyfile = /path/to/privkey.pem
# bearer_token = <secret>
# encryption_key = <random-secret> # enables per-user API key storage (multi-user mode)
[oauth]
# github_client_id = <your-github-client-id>
# github_client_secret = <your-github-client-secret>
# base_url = https://mcp.example.com
# jwt_signing_key = <random-secret> # optional: auto-generated if blank
# require_consent = true
| Variable | Required | Default | Description |
|---|---|---|---|
JQUANTS_API_KEY |
No* | — | J-Quants API key |
JQUANTS_API_TOML_PATH |
No | ~/.jquants-api/jquants-api.toml |
Path to the J-Quants official config file. Override to avoid macOS 26+ launchd sandbox restrictions (see macOS launchd note below) |
JQUANTS_PLAN |
No | auto-detect | Plan: free / light / standard / premium (auto-detected from the API key at server startup; set this variable only to override) |
JQUANTS_CACHE_DIR |
No | ~/.cache/jquants-mcp |
Cache directory path |
JQUANTS_BASE_URL |
No | https://api.jquants.com/v2 |
API base URL |
MAX_RETRIES |
No | 5 |
Max retry attempts for failed requests |
RETRY_BASE_DELAY |
No | 1.0 |
Base delay (seconds) for exponential backoff |
MAX_PAGES |
No | 10 |
Max pages to fetch per paginated request |
SSL_CERTFILE |
No | — | Path to SSL certificate file (HTTP transport) |
SSL_KEYFILE |
No | — | Path to SSL private key file (HTTP transport) |
MCP_BEARER_TOKEN |
No | — | Bearer token for HTTP authentication |
GITHUB_CLIENT_ID |
No | — | GitHub OAuth App client ID (enables GitHub OAuth 2.1) |
GITHUB_CLIENT_SECRET |
No | — | GitHub OAuth App client secret |
GOOGLE_CLIENT_ID |
No | — | Google OAuth 2.0 client ID (enables Google OAuth 2.1) |
GOOGLE_CLIENT_SECRET |
No | — | Google OAuth 2.0 client secret |
OAUTH_PROVIDER |
No | github |
OAuth provider: github or google |
OAUTH_BASE_URL |
No | — | Public base URL of the server (e.g. https://mcp.example.com) |
OAUTH_JWT_SIGNING_KEY |
No | auto | Secret for JWT signing; auto-generated if blank |
OAUTH_REQUIRE_CONSENT |
No | true |
Show OAuth consent screen on every login (true/false) |
MCP_ENCRYPTION_KEY |
No | — | Passphrase for AES-256-GCM encryption of per-user API keys |
MCP_ENCRYPTION_KEY_PREVIOUS |
No | — | Previous encryption passphrase — enables dual-key decrypt during a rotation window. See secrets rotation runbook |
RATE_LIMIT_PER_MINUTE |
No | 60 |
Per-user request ceiling (multi-user mode). Applies per OAuth user |
RATE_LIMIT_BURST |
No | 20 |
Per-user burst allowance (token-bucket capacity) |
JQUANTS_ALLOWED_EMAILS |
No | — | Comma-separated allowlist of emails. Empty = allow any authenticated user (self-host default). Set this on public Cloud Run instances to restrict access; unauthorized users get a 403-style message pointing them to self-host |
* API key is auto-detected from ~/.jquants-api/jquants-api.toml. Set JQUANTS_API_KEY only to override.
Environment variables override both config.ini and jquants-api.toml. This allows MCP clients (Claude Desktop, Claude Code) to pass settings via their env block while keeping defaults elsewhere.
If you run jquants-mcp as a macOS LaunchAgent and the API key lives in ~/.jquants-api/jquants-api.toml, the server may silently hang during startup on macOS 26 or later. The TCC sandbox applied to launchd-spawned processes blocks open() on some dotfiles under $HOME (mode 600), and the process never reaches the port-bind step.
Workaround: copy the toml outside the sandboxed home hierarchy and point the server at it via JQUANTS_API_TOML_PATH:
sudo mkdir -p /usr/local/etc/jquants-mcp
sudo cp ~/.jquants-api/jquants-api.toml /usr/local/etc/jquants-mcp/jquants-api.toml
sudo chown "$USER":staff /usr/local/etc/jquants-mcp/jquants-api.toml
sudo chmod 600 /usr/local/etc/jquants-mcp/jquants-api.toml
Then add the following to your LaunchAgent plist's EnvironmentVariables dict:
<key>JQUANTS_API_TOML_PATH</key>
<string>/usr/local/etc/jquants-mcp/jquants-api.toml</string>
Alternatives: set JQUANTS_API_KEY directly in the plist (simpler but puts the key in a plist file that Time Machine / iCloud may back up), or put api_key = directly in ~/.config/jquants-mcp/config.ini (if that path is not sandbox-blocked on your macOS version).
Linux/systemd and other init systems are not affected.
jquants-mcp supports four authentication modes:
| Mode | When to use |
|---|---|
| None | Local stdio or trusted LAN (single user) |
| Bearer Token | Single-user remote access over HTTPS |
| GitHub OAuth 2.1 | Multi-user access / Claude Desktop Connectors |
| Google OAuth 2.1 | Multi-user access via Google account |
The mode is selected automatically at startup:
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and OAUTH_BASE_URL are all set, and OAUTH_PROVIDER=googleGITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, and OAUTH_BASE_URL are all setMCP_BEARER_TOKEN (or bearer_token in config.ini) is setThe server acts as an OAuth 2.1 authorization server using GitHub as the upstream identity provider (IdP). Clients are redirected to GitHub's login page; the server exchanges the authorization code for a signed JWT that identifies the user across requests.
jquants-mcp (or any name)https://mcp.example.com)https://mcp.example.com/oauth/callbackVia environment variables:
export GITHUB_CLIENT_ID=Ov23liXXXXXXXXXXXXXX
export GITHUB_CLIENT_SECRET=<your-client-secret>
export OAUTH_BASE_URL=https://mcp.example.com # must be publicly reachable
export OAUTH_JWT_SIGNING_KEY=<random-secret> # optional: auto-generated if blank
export MCP_ENCRYPTION_KEY=<random-secret> # required for per-user API key storage
Via config.ini:
[oauth]
github_client_id = Ov23liXXXXXXXXXXXXXX
github_client_secret = <your-client-secret>
base_url = https://mcp.example.com
# jwt_signing_key = <random-secret> # optional: auto-generated if blank
# require_consent = true # default: true
[server]
encryption_key = <random-secret> # required for per-user API key storage
jquants-mcp -t streamable-http --port 8080 \
--ssl-certfile /path/to/fullchain.pem \
--ssl-keyfile /path/to/privkey.pem \
--github-client-id <ID> \
--github-client-secret <SECRET> \
--oauth-base-url https://mcp.example.com
When all OAuth settings are configured via environment variables or config.ini, CLI flags are optional — OAuth is activated automatically on startup.
| CLI Option | Description |
|---|---|
--github-client-id |
GitHub OAuth App client ID |
--github-client-secret |
GitHub OAuth App client secret |
--oauth-base-url |
Public base URL of the server (used to build redirect URIs) |
The server supports Google as an alternative OAuth 2.1 identity provider. Users are redirected to Google's Sign-In page; the server exchanges the authorization code for a signed JWT.
https://mcp.example.comhttps://mcp.example.com/oauth/callbackVia environment variables:
export GOOGLE_CLIENT_ID=<your-client-id>
export GOOGLE_CLIENT_SECRET=<your-client-secret>
export OAUTH_PROVIDER=google
export OAUTH_BASE_URL=https://mcp.example.com
export MCP_ENCRYPTION_KEY=<random-secret> # required for per-user API key storage
Via config.ini:
[oauth]
google_client_id = <your-client-id>
google_client_secret = <your-client-secret>
provider = google
base_url = https://mcp.example.com
[server]
encryption_key = <random-secret>
When OAuth is enabled, the server provides a browser-based settings page at https://mcp.example.com/settings.
https://mcp.example.com/settings in a browserprovider = google in config.ini)This is equivalent to calling register_api_key via Claude, but accessible directly from any browser without an MCP client.
When serving jquants-mcp under a path prefix (e.g. https://mcp.example.com/jquants-mcp/mcp) via a reverse proxy, two things are required — no code changes needed:
1. Strip the prefix in the reverse proxy:
Caddy:
handle /jquants-mcp/* {
uri strip_prefix /jquants-mcp
reverse_proxy localhost:8080
}
nginx (named capture group avoids numbered-backreference vulnerabilities):
location /jquants-mcp/ {
rewrite ^/jquants-mcp(?<path>/.*)$ $path break;
proxy_pass http://localhost:8080;
}
2. Set OAUTH_BASE_URL to the full prefixed URL:
export OAUTH_BASE_URL=https://mcp.example.com/jquants-mcp
Or via config.ini:
[oauth]
base_url = https://mcp.example.com/jquants-mcp
FastMCP derives all OAuth endpoints (/oauth/callback, /settings, /.well-known/oauth-authorization-server) from OAUTH_BASE_URL, so setting it to the prefixed public URL ensures the OAuth flow and settings page work correctly after the proxy strips the prefix.
Google OAuth note: Add both
https://mcp.example.comto Authorized JavaScript origins andhttps://mcp.example.com/jquants-mcp/oauth/callbackto Authorized redirect URIs in the Google Cloud Console.
When GitHub OAuth 2.1 and MCP_ENCRYPTION_KEY are both configured, the server operates in multi-user mode: each authenticated user stores their own J-Quants API key on the server, and all data tools use that key automatically. All users share the read cache; each user gets an independent J-Quants client with isolated rate limiting.
sequenceDiagram
participant U as User
participant C as Claude
participant S as jquants-mcp
participant G as GitHub
participant J as J-Quants API
U->>C: Connect (Connectors UI / Claude Code)
C->>G: OAuth 2.1 Authorization
G-->>C: Access token (JWT)
U->>C: "Register my J-Quants API key: <key>"
C->>S: register_api_key(api_key="<key>")
S->>J: Probe plan-specific endpoints (auto-detect)
J-->>S: Detected plan
S->>S: Encrypt & store key + plan (AES-256-GCM)
S-->>C: {"status": "ok", "plan": "<detected>"}
U->>C: "Get TOPIX daily prices"
C->>S: get_indices_bars_daily_topix(...)
S->>J: API call with user's key
J-->>S: Data
S-->>C: Result
| Tool | Required | Description |
|---|---|---|
register_api_key |
OAuth 2.1 + MCP_ENCRYPTION_KEY |
Encrypt and store your J-Quants API key |
delete_api_key |
OAuth 2.1 + MCP_ENCRYPTION_KEY |
Remove your stored key |
Registering a key (tell Claude):
"Register my J-Quants API key:
<your-api-key>"
Claude calls register_api_key(api_key="..."). The server probes plan-specific endpoints with the key to auto-detect the plan (free / light / standard / premium) and stores it alongside the encrypted key — no manual selection needed. Subsequent tool calls use the detected plan for rate limiting and date-range restrictions.
MCP_ENCRYPTION_KEY| Configuration | Behavior |
|---|---|
No auth, no MCP_ENCRYPTION_KEY |
Single-user: global JQUANTS_API_KEY for all connections |
| Bearer token | Single-user: same as above, with HTTP authentication |
OAuth + no MCP_ENCRYPTION_KEY |
OAuth authentication, but all users share the global JQUANTS_API_KEY |
OAuth + MCP_ENCRYPTION_KEY |
Full multi-user: each user has an independent encrypted API key |
Register the MCP server with claude mcp add:
claude mcp add jquants-mcp -- jquants-mcp
Or if installed from source:
claude mcp add jquants-mcp \
-- /path/to/jquants-mcp/.venv/bin/jquants-mcp
The --scope (-s) option controls where the configuration is stored:
| Scope | Description | Config location |
|---|---|---|
local (default) |
Current project, current user only | .claude.json |
project |
Current project, shared with team | .mcp.json in project root |
user |
All projects, current user only | ~/.claude.json |
API key is auto-detected from ~/.jquants-api/jquants-api.toml. Set --env JQUANTS_API_KEY=... only to override.
Install the operational guidance Skill into your Claude Code project:
npx skills add shigechika/jquants-mcp
This adds skills/jquants-mcp-usage/SKILL.md to your project, giving Claude Code practical tips on cache tiers, plan-based date limits, screener patterns, and safe cache management — without touching the tool definitions.
Add to Claude Desktop config file:
| OS | Config file |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
{
"mcpServers": {
"jquants-mcp": {
"command": "/path/to/jquants-mcp/.venv/bin/jquants-mcp"
}
}
}
The server auto-detects the plan from your API key on startup — no need to set it manually. Add an env block only if you want to override the detection or point to a different API key.
Note: Claude Desktop has a limited
PATH(/usr/local/bin,/usr/bin, etc.), so you must specify the full path to the executable.
Restart Claude Desktop after editing.
jquants-mcp
Run the server over HTTP so that MCP clients on other machines can connect:
jquants-mcp --transport streamable-http --port 8080
This exposes the MCP endpoint at http://<host>:8080/mcp. Clients on the same LAN (or via SSH tunnel) can connect to the server.
Claude Code (remote):
claude mcp add jquants-mcp \
--transport http http://192.0.2.1:8080/mcp
| Option | Default | Description |
|---|---|---|
--transport, -t |
stdio |
Transport type: stdio or streamable-http |
--host |
127.0.0.1 |
Bind address |
--port, -p |
8080 |
Port number |
--ssl-certfile |
— | Path to SSL certificate file |
--ssl-keyfile |
— | Path to SSL private key file |
--bearer-token |
— | Bearer token for authentication |
For secure remote access over the internet (e.g., IPv6), enable TLS encryption and Bearer token authentication:
# Generate a bearer token
python3 -c "import secrets; print(secrets.token_hex(32))"
# Start with TLS and authentication
jquants-mcp -t streamable-http --port 8080 \
--ssl-certfile /path/to/fullchain.pem \
--ssl-keyfile /path/to/privkey.pem \
--bearer-token <TOKEN>
Or configure via config.ini (no CLI flags needed):
[server]
ssl_certfile = /path/to/fullchain.pem
ssl_keyfile = /path/to/privkey.pem
bearer_token = <TOKEN>
Claude Code (remote with TLS):
Note:
claude mcp add --transport http --header "Authorization: Bearer ..."does not send the header during health checks (claude-code#28293). Use mcp-stdio as a workaround:
pip install mcp-stdio # or: uvx mcp-stdio
claude mcp add jquants-mcp -- \
mcp-stdio https://192.0.2.1:8080/mcp --bearer-token <TOKEN>
Claude Desktop does not support Streamable HTTP transport directly. Use mcp-stdio to bridge stdio to a remote MCP server:
{
"mcpServers": {
"jquants-mcp": {
"command": "mcp-stdio",
"args": [
"http://192.0.2.1:8080/mcp"
]
}
}
}
To connect to a TLS-enabled server with Bearer token authentication:
{
"mcpServers": {
"jquants-mcp": {
"command": "mcp-stdio",
"args": [
"https://192.0.2.1:8080/mcp",
"--bearer-token", "<TOKEN>"
]
}
}
}
Restart Claude Desktop after editing.
Claude Desktop's Connectors feature provides a native OAuth 2.1 authentication flow. Users click Connect in the Connectors panel and are redirected to GitHub's login page automatically — no manual token management required.
Requirements:
- Server accessible over HTTPS (TLS certificate required)
- GitHub or Google OAuth 2.1 configured (see GitHub OAuth 2.1 / Google OAuth 2.1)
MCP_ENCRYPTION_KEYset on the server (for per-user API key storage)
Server-side startup:
jquants-mcp -t streamable-http --port 8080 \
--ssl-certfile /path/to/fullchain.pem \
--ssl-keyfile /path/to/privkey.pem \
--github-client-id <ID> \
--github-client-secret <SECRET> \
--oauth-base-url https://mcp.example.com
claude_desktop_config.json (Connectors UI):
{
"mcpServers": {
"jquants-mcp": {
"type": "http",
"url": "https://mcp.example.com/mcp"
}
}
}
On first use, Claude Desktop opens a browser window for GitHub OAuth. After authentication, the token is stored automatically and subsequent connections use it silently.
Note: Claude Desktop Connectors support (
"type": "http"with OAuth) is rolling out gradually. If it is not yet available in your version, use the stdio proxy method as a fallback.
| Tool | Endpoint | Plan | Description |
|---|---|---|---|
get_equities_master |
/equities/master |
Free+ | Listed issue information |
get_equities_bars_daily |
/equities/bars/daily |
Free+ | Daily stock prices (OHLC) |
get_equities_bars_minute |
/equities/bars/minute |
Light+ | Minute-level stock prices |
get_equities_bars_daily_am |
/equities/bars/daily/am |
Premium | Morning session prices |
get_equities_investor_types |
/equities/investor-types |
Light+ | Trading by investor type |
get_equities_earnings_calendar |
/equities/earnings-calendar |
Free+ | Earnings schedule |
search_equities |
(cache only) | Free+ | Reverse lookup by company name (e.g. "住友商事" → 8053) |
| Tool | Endpoint | Plan | Description |
|---|---|---|---|
get_fins_summary |
/fins/summary |
Free+ | Financial summary (quarterly) |
get_fins_details |
/fins/details |
Premium | Detailed statements (BS/PL/CF) |
get_fins_dividend |
/fins/dividend |
Premium | Cash dividend data |
| Tool | Endpoint | Plan | Description |
|---|---|---|---|
get_indices_bars_daily |
/indices/bars/daily |
Free+ | Index daily prices |
get_indices_bars_daily_topix |
/indices/bars/daily/topix |
Free+ | TOPIX daily prices |
| Tool | Endpoint | Plan | Description |
|---|---|---|---|
get_derivatives_bars_daily_futures |
/derivatives/bars/daily/futures |
Light+ | Futures daily prices |
get_derivatives_bars_daily_options |
/derivatives/bars/daily/options |
Light+ | Options daily prices |
get_derivatives_bars_daily_options_225 |
/derivatives/bars/daily/options/225 |
Light+ | Nikkei 225 options prices |
| Tool | Endpoint | Plan | Description |
|---|---|---|---|
get_markets_margin_interest |
/markets/margin-interest |
Standard+ | Margin trading data |
get_markets_margin_alert |
/markets/margin-alert |
Standard+ | Margin trading alerts |
get_markets_short_ratio |
/markets/short-ratio |
Standard+ | Short selling ratio |
get_markets_short_sale_report |
/markets/short-sale-report |
Standard+ | Short sale position report |
get_markets_breakdown |
/markets/breakdown |
Premium | Market breakdown by investor |
get_markets_calendar |
/markets/calendar |
Free+ | Trading calendar |
| Tool | Endpoint | Plan | Description |
|---|---|---|---|
get_bulk_list |
/bulk/list |
Light+ | List downloadable CSV files |
get_bulk_download_url |
/bulk/get |
Light+ | Get signed download URL |
Cross-sectional cache-only tools that scan all listed equities. No extra API calls, useful for "what's the overall market doing today?" and sector valuation queries.
| Tool | Description |
|---|---|
detect_price_change |
Daily advance/decline summary (値上がり/値下がり銘柄数) and advance-decline ratio. |
get_advance_decline_ratio |
Cumulative advance/decline ratio (騰落レシオ) over the last period trading days. Default 25 (overbought >120, oversold <70). |
get_top_movers |
Top gainers/losers ranked by percentage price change. Returns code + name + change_pct. |
get_top_volume |
Top stocks by trading volume (出来高ランキング, share count). Returns code + name + volume + turnover_value. |
get_top_turnover_value |
Top stocks by turnover value (売買代金ランキング, yen). Surfaces high-priced large-caps that dominate institutional flow, distinct from get_top_volume. |
get_sector_performance |
Sector-level average daily change (業種別騰落率) grouped by TSE 33 sectors (default) or 17 sectors (sector_type="s17"). |
get_sector_briefing |
Sector-level median PER, PBR, and ROE (業種別ブリーフィング) aggregated from the most recent FY financials. Split-adjusted. Sorted by PER ascending (cheapest first). |
get_dividend_yield_ranking |
High dividend yield stock ranking (高配当利回りランキング). Joins DivAnn from fins_summary with AdjC to compute yield_pct = DivAnn / AdjC × 100. Skips interim reports with empty DivAnn. |
get_market_briefing |
Composite daily briefing (相場ブリーフィング) — advance/decline + 25-day ADR + sector top/bottom + top movers + top turnover + screener highlights + TOPIX change in one call. |
Offline tools that compute signals directly from the SQLite cache. No extra API calls, pure Python, no numpy/pandas. Intended for Claude-assisted stock screening without hitting rate limits.
| Tool | Description |
|---|---|
detect_price_limit |
Find stocks that touched the daily upper/lower price limit (ストップ高/安) using the UL/LL flags. Optional close-at-limit refinement via C == H / C == L. |
compare_close_vs_vwap |
Compute the daily VWAP (Va / Vo) and compare to the close for a given code + date or date range. |
detect_52w_high_low |
New 52-week rolling high/low (Yahoo / Bloomberg / TradingView convention). Returns new_high / new_high_close / new_low / new_low_close plus conviction context: AdjO, close_vs_vwap ("above"/"below"), volume_ratio, volume_ratio_sessions. |
detect_52w_high_low_range |
Same as above but across a date range (date_from–date_to). Use this instead of repeated single-date calls. |
detect_ytd_high_low |
New year-to-date (年初来) high/low (Kabutan / JPX / Yahoo!ファイナンス convention). Same four signals against the YTD prior window plus AdjO, close_vs_vwap, volume_ratio, volume_ratio_sessions. |
detect_ytd_high_low_range |
Same as above but across a date range (date_from–date_to). Use this instead of repeated single-date calls. |
detect_volume_surge |
List stocks whose volume on date exceeds the trailing 20-day average by a configurable multiplier (default 2.0). |
detect_distribution_days |
Identify distribution days (機関投資家の売り圧力) using TOPIX as the market proxy and total market turnover (SUM(Va)) as the volume signal. A distribution day fires when TOPIX falls ≥ sigma_multiplier σ (default 2.0) below the 20-session rolling mean. Four or more within window_sessions (default 25) sessions is a warning that the uptrend may be failing (IBD — Investor's Business Daily — method adapted for TOPIX). Each entry includes volume_confirmed (whether total market Va exceeded the prior session). |
detect_follow_through_day |
Confirm a new uptrend (フォロースルーデイ). TOPIX must rise ≥ sigma_multiplier σ (default 2.0) above the 20-session rolling mean on session 4 or later from rally_start (the low/reversal day), with higher total market Va than the prior session. Provide the first day of the rally attempt as rally_start; check each subsequent date until the signal fires or distribution resumes. |
detect_consecutive_dividend_increase |
Screen for stocks with at least min_years (default 10) consecutive years of annual dividend increase (連続増配). Split-adjusted. Supports as_of_date for lookahead-free back-testing. Results sorted by consecutive years descending; each entry includes code, name, consecutive_years, latest_div_ann, latest_fy_end, and a history list of recent fiscal years. All plans (cache-only). |
Cache-only tool that assembles a one-page snapshot for a single stock from cached data. No extra API calls.
| Tool | Description |
|---|---|
get_stock_briefing |
One-page briefing for a single stock (株式ブリーフィング): latest price (close, change_pct, volume, OHLC), most recent FY financials (revenue, operating profit, net income), and valuation ratios (PER, PBR, ROE, EPS, BPS, dividend yield). All figures are split-adjusted. PER and ROE are null when EPS ≤ 0 (net-loss period). Dividend yield uses the most recent DivAnn disclosed within the past 18 months. |
Pure-Python SMA / Bollinger Bands / RSI computation over the cached daily bars. No extra API call for codes already in cache; falls back to the J-Quants API on a cache miss and stores the result.
| Tool | Description |
|---|---|
get_technical_indicators |
Compute SMA (5/25/75), Bollinger Bands (bb20, ±2σ sample std), and RSI (rsi14, Wilder smoothing) for a single code over a date or date range. Returns numeric values — useful for "is close above SMA25?" or "is RSI overbought?" without rendering a chart. All values use split-adjusted close (AdjC). Indicators not yet warmed up are returned as null. |
RSI in charts: RSI sub-panel is not yet available. Use
get_technical_indicatorsfor numeric RSI values.
Both tools return JSON for React artifact / Plotly rendering (no optional dependencies).
| Tool | Description |
|---|---|
get_candlestick_data |
OHLCV + indicator data as JSON parallel arrays for a single code. Returns dates, ohlcv, indicators (SMA / Bollinger), lock_days, earnings_dates. Default: 91-day range, sma5 + sma25 overlays. |
get_comparison_chart_data |
Multi-stock time-series data as JSON wide-format records (up to 10 codes). Default mode="return_pct" normalises each series to 0% at its first bar; mode="price" plots adjusted close. |
Indicator options for get_candlestick_data:
volume, sma5, sma20, sma25, sma60, sma75, sma200, bb20 (20-day Bollinger band; expands to bb20_upper / bb20_mid / bb20_lower)adjusted=True); set False for raw OHLC| Tool | Auth required | Description |
|---|---|---|
health_check |
— | Server health and API key status |
cache_status |
— | Cache statistics |
cache_clear |
— | Clear cached data |
register_api_key |
OAuth 2.1 | Store your J-Quants API key (multi-user mode) |
delete_api_key |
OAuth 2.1 | Remove your stored J-Quants API key |
The server uses a two-tier SQLite cache:
equities_bars_daily, equities_master, fins_summary, indices_bars_daily_topix, investor_types, markets_margin_interest, markets_margin_alert, markets_short_ratio, markets_breakdown, markets_calendarCache is stored at ~/.cache/jquants-mcp/cache.db by default.
Expected disk usage after a full historical fetch (approximate; varies by market data availability):
| Plan | Retention | Approx. size |
|---|---|---|
| Free | 2 years | ~500 MB |
| Light | 5 years | ~2.9 GB |
| Standard | 10 years | ~3.5 GB |
| Premium | All available | ~4 GB+ |
The scripts/bulk_fetch_all.py script downloads all available bulk CSV data from the J-Quants Bulk API and imports it into the SQLite cache. This is the fastest way to populate the local cache with historical data.
# Fetch all available data for your plan
uv run python scripts/bulk_fetch_all.py
# Fetch specific endpoints only
uv run python scripts/bulk_fetch_all.py --endpoints fins_summary topix margin_interest
# Dry run — show file list and sizes without downloading
uv run python scripts/bulk_fetch_all.py --dry-run
The script respects the plan-based rate limit (e.g. 60 req/min for Light) and retries on 429 errors. A full historical fetch takes roughly 1 hour; use health_check to monitor progress.
The CSV sideload script (import_csv_to_cache.py) is maintained by the publisher pipeline that feeds this cache. If you are building your own pipeline, implement sideloading by inserting directly into the equities_bars_daily / equities_master tables following the schema defined in src/jquants_mcp/cache/schema.py.
scripts/daily_fetch.py fetches additional J-Quants data via jquantsapi.ClientV2 and inserts it directly into the SQLite cache. Designed to be called from an external daily pipeline (e.g. a cron job or shell script).
The script reads the plan from ~/.config/jquants-mcp/config.ini (or JQUANTS_PLAN env var) and automatically determines which endpoints to fetch:
| Plan | Endpoints |
|---|---|
| Free | fins_summary, earnings_cal |
| Light | + topix, investor_types |
| Standard | + short_ratio, margin_interest, margin_alert, short_sale_report |
| Premium | + breakdown |
# Fetch all endpoints available for your plan
python3 scripts/daily_fetch.py
# Fetch specific endpoints only
python3 scripts/daily_fetch.py --topix --investor-types
# Fetch trading calendar
python3 scripts/daily_fetch.py --calendar
# Backfill historical Markets data (past N days)
python3 scripts/daily_fetch.py --backfill 90
# Use a custom cache DB path
python3 scripts/daily_fetch.py --db /path/to/cache.db
Permission errors (403) are handled gracefully — the script logs the error and continues to the next endpoint without crashing.
scripts/verify_cache_completeness.py audits the local cache and reports which tables are up-to-date, stale, or missing for the current plan.
# Quick freshness check (text output)
uv run python scripts/verify_cache_completeness.py
# Machine-readable JSON (for CI / monitoring)
uv run python scripts/verify_cache_completeness.py --output json
# Detect date-level gaps (days where only a fraction of stocks were fetched)
uv run python scripts/verify_cache_completeness.py --check-gaps
# Show what --auto-fix would repair, without making API calls
uv run python scripts/verify_cache_completeness.py --check-gaps --auto-fix --dry-run
# Re-fetch gap days automatically
uv run python scripts/verify_cache_completeness.py --check-gaps --auto-fix
Exit codes: 0 = all tables healthy, 1 = stale or missing tables, 2 = fatal (DB unreadable).
The plan is auto-detected from your API key (same probe as daily_fetch.py); pass --plan <plan> or set JQUANTS_PLAN to override (skips the probe).
Useful before a plan downgrade to confirm all currently-covered data has been fetched, and as a periodic check to catch silent fetch failures early.
This server can be deployed to Google Cloud Run. The deployment splits state across two managed stores:
cache.db — published to a GCS bucket by the self-hosted server and downloaded to /tmp (tmpfs) on every cold start. Cloud Run reads it but never writes back.users / oauth_state — stored in Firestore (Native mode). Strongly consistent and multi-writer safe, so Cloud Run can scale horizontally without SQLite write conflicts.Details: see GCS and Firestore integration below.
For a fork-and-deploy walkthrough (WIF, OAuth clients, custom domain, Claude mobile setup, allowlist), see docs/deploy/gcp.md. The sections below summarise the moving parts; the deploy guide is the canonical step-by-step.
cache.db (updated out-of-band by the self-hosted server)roles/storage.objectViewer on the GCS bucket (read-only access to cache.db)roles/datastore.user on the project (Firestore read/write)roles/secretmanager.secretAccessor if using Secret Manager for API keysgcloud storage buckets create gs://YOUR_BUCKET \
--location asia-northeast1
gcloud firestore databases create \
--location=us-west1 \
--type=firestore-native
The recommended path is to fork the repository and rely on the GitHub Actions CD workflow at .github/workflows/cd.yml, which calls gcloud run deploy --source . with the correct flags (memory, CPU, env vars, secrets). That workflow is the single source of truth for production deployment — do not run ad-hoc gcloud run services update commands, as they will be overwritten on the next CD run.
For a one-off manual deploy (e.g. testing a fork), run the same command locally:
gcloud run deploy jquants-mcp \
--project "${PROJECT_ID}" \
--region "${REGION}" \
--source . \
--execution-environment gen2 \
--memory 6Gi \
--cpu 2 \
--no-cpu-throttling \
--cpu-boost \
--set-env-vars "GCS_BUCKET=YOUR_BUCKET,JQUANTS_CACHE_DIR=/tmp" \
--set-secrets "JQUANTS_API_KEY=jquants-api-key:latest"
Memory sizing notes are in Memory requirements below.
| Variable | Required | Default | Description |
|---|---|---|---|
GCS_BUCKET |
Yes | — | GCS bucket holding the cache.db snapshot |
GCS_PREFIX |
No | jquants-mcp/ |
Object key prefix in the bucket |
JQUANTS_CACHE_DIR |
No | /tmp |
Local directory where cache.db is materialized (tmpfs on Cloud Run) |
PORT |
No | 8000 |
HTTP port (set by Cloud Run) |
JQUANTS_API_KEY |
Yes | — | J-Quants API key (use Secret Manager) |
JQUANTS_PLAN |
No | auto-detect | Plan: free / light / standard / premium (auto-detected from the API key unless overridden) |
MCP_BEARER_TOKEN |
No | — | Bearer token for HTTP authentication (single-user mode only) |
PUBSUB_INVOKER_SA |
No | — | Service account email for Pub/Sub push authentication. When set, /internal/reload verifies the Google-signed OIDC token. Required if using Pub/Sub auto-reload; leave unset otherwise. |
PUBSUB_AUDIENCE |
No | request URL | OIDC audience to verify against (defaults to the incoming request URL) |
GOOGLE_CLOUD_PROJECT |
Yes | — | GCP project ID. Required for Firestore (user DB) and Secret Manager access. Set via vars.GCP_PROJECT in the CD workflow |
OAUTH_PROVIDER, OAUTH_BASE_URL, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, … |
No | — | OAuth configuration for multi-user mode |
Firestore uses Application Default Credentials from the Cloud Run service account.
Cloud Run deployments depend on two managed stores, not an in-container SQLite set:
| Data | Where it lives | Access mode |
|---|---|---|
cache.db (market data) |
GCS object, materialized to /tmp/cache.db on startup |
Read-only from Cloud Run |
users (per-user encrypted J-Quants API keys) |
Firestore users collection |
Read/write |
oauth_state (OAuth sessions, PKCE verifiers, dynamic client registrations) |
Firestore oauth_state collection |
Read/write |
cache.db is owned by a self-hosted publisher (a cron / scheduled task running scripts/daily_fetch.py or scripts/bulk_fetch_all.py + scripts/gcs_export_cache.py) that pushes a fresh snapshot to GCS on each run. Cloud Run never writes back to GCS.
sequenceDiagram
participant E as entrypoint.sh
participant M as MCP server
participant D as cache.db downloader
participant G as GCS
E->>M: start (no cache.db yet)
activate M
Note right of M: serve requests via<br/>J-Quants API fallback
E->>D: spawn background job
activate D
D->>G: gcloud storage cp cache.db /tmp
G-->>D: ~2.9 GiB (1-2 min)
D->>M: SIGHUP
deactivate D
Note right of M: reload cache.db,<br/>switch to Tier 1 cache
deactivate M
Notes:
cache.db is ~2.9 GiB and takes 1–2 minutes to download. Requests during that window hit the live J-Quants API, so they work but are slower and count against rate limits.cache_status returns a minimal payload (db_path + plan only). A full payload with row counts and db_size_mb indicates the cache is loaded.maxScale: 1 restriction — scale as needed.After startup, cache.db is refreshed daily by the publisher. The mechanism differs by deployment target.
Cloud Run — Pub/Sub push
SIGHUP cannot reliably target a specific process across Cloud Run's multi-instance model. Instead, the publisher triggers a reload via a Pub/Sub push to the /internal/reload endpoint, which re-downloads cache.db from GCS in the background.
sequenceDiagram
participant P as Publisher (daily_fetch.py<br/>+ gcs_export_cache.py)
participant G as GCS
participant PS as Pub/Sub
participant CR as Cloud Run<br/>(/internal/reload)
participant C as CacheStore
P->>G: upload new cache.db snapshot
G->>PS: GCS object notification
PS->>CR: POST /internal/reload<br/>(Google-signed OIDC token)
CR->>CR: verify OIDC token<br/>(PUBSUB_INVOKER_SA)
CR-->>PS: 200 OK (immediate ACK)
CR->>G: download new cache.db to /tmp
G-->>CR: ~2.9 GiB
CR->>C: request_reload()<br/>(lazy reconnect on next query)
PUBSUB_INVOKER_SA must be the service account email that Pub/Sub uses to sign the OIDC token. PUBSUB_AUDIENCE defaults to the incoming request URL and normally does not need to be set.
Docker Compose — direct file update
When GCS_BUCKET is not set, cache.db lives on the local filesystem (bind-mounted into the container). daily_fetch.py appends rows directly to the same file; SQLite's normal concurrent-access handling means the server picks up new data on the next query with no explicit signal required.
sequenceDiagram
participant P as Publisher (daily_fetch.py)
participant D as cache.db (bind mount)
participant M as MCP server
P->>D: append new rows (daily_fetch.py)
Note right of D: same file, visible<br/>to the server immediately
M->>D: reads new rows on next query
Local process (launchd / systemd) — SIGHUP
When running the MCP server as a local service (e.g. launchd on macOS), SIGHUP triggers a lazy reconnect — useful after replacing cache.db wholesale (e.g. via bulk_fetch_all.py):
# macOS launchd
launchctl kill SIGHUP system/<YOUR_LAUNCHD_LABEL>
# or directly
kill -HUP <MCP_PID>
Permission error on startup (403 Forbidden or storage.objects.get denied):
gcloud storage buckets get-iam-policy gs://YOUR_BUCKET \
--format="table(bindings.role, bindings.members)"
The service account needs roles/storage.objectViewer on the bucket — see IAM setup.
Firestore permission errors:
gcloud projects get-iam-policy "${PROJECT_ID}" \
--flatten="bindings[].members" \
--filter="bindings.members:serviceAccount:jquants-mcp@*"
The service account needs roles/datastore.user on the project.
cache_status returns only db_path and plan (no row counts):
The cache.db background download has not finished yet. Normal during the first 1–2 minutes after a cold start. Check the logs for cache.db download complete; signaling MCP server to reload.
cache.db not found in GCS on first deploy:
There is no "empty cache" fallback mode beyond API fallback — the server will keep serving requests directly from the J-Quants API. Upload a cache.db snapshot from your self-hosted server to GCS to enable Tier 1 caching (see Initial cache.db upload).
SA="jquants-mcp@${PROJECT_ID}.iam.gserviceaccount.com"
# Create service account
gcloud iam service-accounts create jquants-mcp \
--display-name "jquants-mcp Cloud Run SA"
# Read-only access to the cache.db snapshot in GCS
gcloud storage buckets add-iam-policy-binding gs://YOUR_BUCKET \
--member "serviceAccount:${SA}" \
--role "roles/storage.objectViewer"
# Firestore access for users / oauth_state collections
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member "serviceAccount:${SA}" \
--role "roles/datastore.user"
# Secret Manager access (if using Secret Manager for JQUANTS_API_KEY etc.)
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member "serviceAccount:${SA}" \
--role "roles/secretmanager.secretAccessor"
Note: if the self-hosted server that publishes cache.db uses a different service account, only that account needs write access to the bucket. The Cloud Run service account remains viewer-only.
Cloud Run reads cache.db as a read-only snapshot. Publish a snapshot from your self-hosted server (which has been warming the cache) before the first deploy:
gcloud storage cp ~/.cache/jquants-mcp/cache.db \
gs://YOUR_BUCKET/jquants-mcp/cache.db \
--no-gzip-in-flight
Important: disable parallel composite uploads (the default for large files). They corrupt SQLite files because the reassembled object contains byte ranges that do not form a valid database page layout. On the publishing host, set:
gcloud config set storage/parallel_composite_upload_enabled False
No manual Firestore setup is required — the server creates the users and oauth_state collections on first write.
Cloud Run materializes cache.db into /tmp (a tmpfs, i.e. RAM). The memory limit therefore must cover:
cache.db size (currently ~2.9 GiB)Current production sizing (see .github/workflows/cd.yml) is --memory 6Gi --cpu 2 --no-cpu-throttling, which leaves ~2.8 GiB headroom over the baseline. Cloud Run gen2 is required for memory allocations above 4 Gi.
If cache.db grows beyond ~4 GiB, bump the memory limit accordingly — the tmpfs ceiling is roughly the instance memory, so you need cache.db + ~2 GiB at a minimum.
For production incidents on the Cloud Run deployment, see the runbooks:
Alert policies that trigger these are in ops/alerts/; each policy's documentation links back to the matching runbook.
The disaster recovery posture documents the current single-region deployment, RTO/RPO expectations, and the (undrilled) standby-region procedure.
Service-level objectives — availability and latency targets with an error-budget policy — are in docs/slo.md.
# Install dev dependencies
uv sync --dev
# Run tests
uv run pytest -v
# Lint
uv run ruff check src/ tests/
# Format
uv run ruff format src/ tests/
This software (jquants-mcp) is a technical tool for retrieving Japanese stock data from the J-Quants API v2 for use with Claude and other MCP clients. It is intended to provide reference information for your own investment research, and:
Выполни в терминале:
claude mcp add jquants-mcp -- npx Безопасность
Низкий рискАвтоматическая эвристика по публичным данным — не гарантия безопасности.