Skip to main content
Glama
tossinvest-openapi-mcp

tossinvest-openapi-mcp

by EthanKlocked

tossinvest-openapi-mcp

Safe-by-default local stdio MCP server for the official Toss Securities / 토스증권 Open API.

This package is an independent developer tool and is not affiliated with, endorsed by, or sponsored by Toss Securities.

This package is designed for developers who want read-only account, market, and order data in an MCP client, with optional order operations protected by multiple explicit safety gates.

Safety defaults

  • Uses only the official Toss Open API server: https://openapi.tossinvest.com

  • Starts without credentials; auth_status reports missing configuration instead of crashing.

  • Keeps OAuth access tokens in memory only.

  • On eligible GET 401 invalid-token or 401 token-revoked responses, replaces the affected cached token and retries once; concurrent issuance is shared within a client instance.

  • auth_status separates token issuance from data endpoint reachability and reports whether a default TOSS_ACCOUNT_SEQ is configured.

  • Redacts API keys, secrets, bearer tokens, account headers, and account numbers from tool output/errors.

  • Trading is disabled by default.

  • v0.2 workflow tools are safety-first and preview-based: portfolio_snapshot → pre_trade_check → order_preview → approval → order_execute → order_status_summary.

  • order_preview stores preview contracts in memory only and never calls Toss order POST endpoints.

  • order_execute is intentionally fast: it rechecks only preview/confirmation/hash/env/delegated-authority gates, submits at most one order POST, and reports timeout/network ambiguity as unknown_execution_state for reconciliation before any manual retry.

  • Order tools default to dryRun=true.

  • Real create/modify/cancel operations require ENABLE_TRADING=true plus the operation-specific gate.

  • Confirmation is required by default.

  • Default max order amounts are 0 KRW and 0 USD.

  • BLOCKED_SYMBOLS takes precedence over ALLOWED_SYMBOLS.

Related MCP server: tossinvest-mcp

Install and run

This repository is currently distributed from GitHub source only. It has not been published to npm under an EthanKlocked-owned package.

Important: the unscoped npm name tossinvest-openapi-mcp is already used by a different npm package, so do not install or run that package expecting this repository's code.

Clone this repository, then install and build locally:

git clone https://github.com/EthanKlocked/tossinvest-openapi-mcp.git
cd tossinvest-openapi-mcp
npm install
npm run build
npm test

Run locally:

TOSS_API_KEY=... TOSS_SECRET_KEY=... node dist/index.js

Do not put real secrets in committed files. Prefer passing env vars from your local shell or MCP client secret manager.

MCP client configuration example

Use the local cloned path:

{
  "mcpServers": {
    "tossinvest": {
      "command": "node",
      "args": ["/absolute/path/to/cloned/tossinvest-openapi-mcp/dist/index.js"],
      "env": {
        "TOSS_API_KEY": "${TOSS_API_KEY}",
        "TOSS_SECRET_KEY": "${TOSS_SECRET_KEY}",
        "TOSS_ACCOUNT_SEQ": "${TOSS_ACCOUNT_SEQ}"
      }
    }
  }
}

If this project is later published to npm, use a package name owned by the maintainer, such as @ethanklocked/tossinvest-openapi-mcp, rather than the already-taken unscoped name.

Environment variables

Name

Default

Purpose

TOSS_API_KEY

unset

Toss Open API client id / API key.

TOSS_SECRET_KEY

unset

Toss Open API client secret.

TOSS_ACCOUNT_SEQ

unset

Optional default account sequence for account-scoped tools.

ENABLE_TRADING

false

Global gate for any real order operation.

ENABLE_ORDER_CREATE

false

Gate for real order create.

ENABLE_ORDER_MODIFY

false

Gate for real order modify.

ENABLE_ORDER_CANCEL

false

Gate for real order cancel.

REQUIRE_CONFIRMATION

true

Requires exact confirmation text for real order operations.

MAX_ORDER_KRW

0

Maximum allowed calculated KRW order amount.

MAX_ORDER_USD

0

Maximum allowed calculated USD order amount.

ALLOWED_SYMBOLS

unset

Optional comma-separated allow list.

BLOCKED_SYMBOLS

unset

Optional comma-separated block list; always wins over allow list.

TOSS_REQUEST_TIMEOUT_MS

15000

Timeout for OAuth, read-only, and order requests. Set 0 only for local debugging to disable the timeout.

Confirmation text for real order operations:

I understand this may place a real Toss Securities order

Tools

Read-only tools:

  • auth_status

  • accounts

  • holdings

  • prices

  • orderbook

  • trades

  • price_limits

  • candles

  • stock_info

  • stock_warnings

  • exchange_rate

  • market_calendar

  • orders_open

  • orders_closed

  • order_detail

  • buying_power

  • sellable_quantity

  • commissions

Workflow tools:

  • portfolio_snapshot — reads holdings, KRW/USD buying power, open orders, calculable position weights, account/accountSeq state, warning flags, and partial failures. Position weights use a KRW-converted, cash-inclusive denominator (holdings + KRW/USD cash buying power); when cashStatus is partial, omitted cash currencies are listed in omittedCashCurrencies.

  • pre_trade_check — separate read/check layer for candidate orders; returns canProceedDryRun, realOrderBlockedByDefault, checks, warnings, blockers, missing, estimate, and dataFreshness.

  • order_preview — creates an in-memory preview contract; returns previewId, requestHash, ttlSeconds, expiresAt, exact confirmationText, estimated amount/fee/cash/quantity checks, gate status, risk flags, and calculability notes. It never calls order POST endpoints. Default TTL: 90 seconds; max accepted TTL: 300 seconds.

  • order_execute — fast preview-based submission; requires previewId, matching requestHash, exact confirmation (I approve this exact Toss order preview), unexpired preview, env gates, and optional delegated-authority bounds. It does not run pre_trade_check in the hot path and does not add automatic order POST retry.

  • order_status_summary — read-only reconciliation summary for open/recently closed orders, state counts, filled/partial/canceled/rejected/replace-related states when present, and caveats for disappeared/replaced orders.

Trading tools:

  • order_validate — checks local gates only and never calls Toss order POST endpoints.

  • order_create — defaults to dry-run; real execution requires all create gates.

  • order_modify — defaults to dry-run; real execution requires all modify gates.

  • order_cancel — defaults to dry-run; real execution requires all cancel gates. When ALLOWED_SYMBOLS or BLOCKED_SYMBOLS is configured, real cancellation also requires caller-supplied request.symbol so local symbol policy can be evaluated before the POST. The server does not fetch order details before cancel because this would add a second API dependency and the official detail payload shape should be confirmed by users with live credentials before relying on it for safety.

Auth status and account selection

auth_status intentionally separates OAuth token issuance from actual data API reachability:

  • configured: required credential environment variables are present.

  • tokenAvailable: POST /oauth2/token succeeded.

  • dataApiReachable: a real read-only data check against GET /api/v1/accounts succeeded.

  • authenticated: true only when both token issuance and the data endpoint check succeed.

  • accountSeqConfigured: true when TOSS_ACCOUNT_SEQ is set.

  • accountSeqRequiredForAccountTools: true; account-scoped tools need either a per-call accountSeq or TOSS_ACCOUNT_SEQ.

Most market-data tools such as prices, orderbook, trades, and stock_info do not require accountSeq. Account-scoped tools such as holdings, orders_open, orders_closed, order_detail, buying_power, sellable_quantity, commissions, and real/dry-run order tools require accountSeq via the tool arguments or TOSS_ACCOUNT_SEQ.

Token recovery and diagnostics

Token recovery matches exact structured code or error.code values (invalid-token, token-revoked) on HTTP 401 only. When present, error.code takes precedence even if unrelated or conflicting; the top-level code is used only when the nested code is absent (for example, an error object containing only message). Messages, arbitrary nested strings, and unrelated 401 errors do not trigger issuance. GET requests permit at most one authentication retry; a second rejection is returned as an API error. Existing POST invalid-token retry behavior is preserved, but POST token-revoked is never replayed. The internal retryInvalidToken: false option disables both authentication recovery codes, including order execution paths that already opt out. Ambiguous order outcomes still require reconciliation, not automatic replay.

Tokens remain memory-only, using expires_in with the existing 30-second expiry margin (and existing 60-second minimum lifetime / 3600-second default). Concurrent cold starts and refreshes share one in-flight issuance per client instance. Cache generations use object identity, so a late rejection cannot discard a newer generation even if the provider returns the same token string. This does not coordinate separate processes or external clients. There is no periodic issuance or refresh-token grant.

auth_status adds tokenLifecycle when credentials are configured: a snapshot of the latest issuance attempt, not proof of data API acceptance. Existing status fields remain; use dataApiReachable / dataApiCheck to check data access, including repeated token rejection.

  • reason: cold-cache, expiry-margin, invalid-token, or token-revoked.

  • startedAt, completedAt, expiresAt: Unix epoch milliseconds; completion/expiry can be null while pending or when unavailable.

  • durationMs: elapsed issuance milliseconds, or null while pending.

  • outcome: pending, succeeded, or failed.

Diagnostics contain only these fixed categories and timing values, never tokens, credentials, headers, provider bodies, or raw network messages. Issuance failures return a safe actionable configuration/network error; a later request can try issuance again. No new environment variables or required tool arguments are introduced.

After updating source, run npm run build and restart the MCP subprocess to load the new build. Deployment and read-only verification in the consuming environment are separate operator steps; source tests do not prove that runtime has been upgraded.

Endpoint mapping

Tool

Method/path

Side effect

auth_status

POST /oauth2/token; then GET /api/v1/accounts when token issuance succeeds

Token/data reachability check only

accounts

GET /api/v1/accounts

Read-only

holdings

GET /api/v1/holdings

Read-only

prices

GET /api/v1/prices

Read-only

orderbook

GET /api/v1/orderbook

Read-only

trades

GET /api/v1/trades

Read-only

price_limits

GET /api/v1/price-limits

Read-only

candles

GET /api/v1/candles

Read-only

stock_info

GET /api/v1/stocks

Read-only

stock_warnings

GET /api/v1/stocks/{symbol}/warnings

Read-only

exchange_rate

GET /api/v1/exchange-rate

Read-only

market_calendar

GET /api/v1/market-calendar/KR or GET /api/v1/market-calendar/US

Read-only

orders_open

GET /api/v1/orders?status=OPEN

Read-only

orders_closed

GET /api/v1/orders?status=CLOSED

Read-only

order_detail

GET /api/v1/orders/{orderId}

Read-only

buying_power

GET /api/v1/buying-power

Read-only

sellable_quantity

GET /api/v1/sellable-quantity

Read-only

commissions

GET /api/v1/commissions

Read-only

portfolio_snapshot

Composes GET /api/v1/holdings, GET /api/v1/buying-power, and GET /api/v1/orders?status=OPEN

Read-only workflow snapshot

pre_trade_check

Composes market calendar, warnings, price limits, buying power/sellable quantity, commissions, and open orders

Read/check only; no order POST

order_preview

Local preview contract plus read/check calls

No Toss order POST; memory-only preview storage

order_execute

POST /api/v1/orders only after preview/confirmation/hash/env gates pass

At most one order POST; no automatic order POST retry

order_status_summary

GET /api/v1/orders?status=OPEN and GET /api/v1/orders?status=CLOSED

Read-only reconciliation

order_validate

Local gate evaluation only

No Toss order POST

order_create

POST /api/v1/orders

Real order only after all gates pass

order_modify

POST /api/v1/orders/{orderId}/modify

Real order modification only after all gates pass

order_cancel

POST /api/v1/orders/{orderId}/cancel

Real order cancellation only after all gates pass

v0.2 workflow examples

Recommended safety-first flow:

portfolio_snapshot → pre_trade_check → order_preview → user/delegated approval → order_execute → order_status_summary

Market calendar checks are routed by request market:

  • currency=KRW or a six-digit Korean stock symbol uses market_calendar(KR).

  • US tickers / currency=USD use market_calendar(US).

  • US non-business days are detected from the official calendar shape when result.today.dayMarket, preMarket, regularMarket, and afterMarket are all null.

  • KR non-business days are detected when result.today.integrated is null.

  • In those cases pre_trade_check and order_preview return a market_closed_non_business_day blocker with market, date, and nextBusinessDay; they do not report market_open_unknown in missing.

portfolio_snapshot example:

{
  "accountSeq": 1,
  "currencies": ["KRW", "USD"],
  "limit": 50
}

pre_trade_check example. This is a separate read/check tool and is intentionally not forced into order_execute's hot path:

{
  "accountSeq": 1,
  "request": {
    "symbol": "005930",
    "side": "BUY",
    "orderType": "LIMIT",
    "quantity": "1",
    "price": "70000",
    "currency": "KRW"
  },
  "delegatedAuthority": {
    "remainingAmount": 100000,
    "expiresAt": "2026-07-05T15:00:00.000Z"
  }
}

order_preview example. It never calls Toss order POST endpoints and returns previewId, requestHash, TTL, and exact confirmation text:

{
  "accountSeq": 1,
  "ttlSeconds": 90,
  "request": {
    "symbol": "005930",
    "side": "BUY",
    "orderType": "LIMIT",
    "quantity": "1",
    "price": "70000",
    "currency": "KRW"
  }
}

order_execute example. Copy the previewId, requestHash, and exact confirmationText from the preview response:

{
  "previewId": "preview_...",
  "requestHash": "<sha256-from-preview>",
  "confirmation": "I approve this exact Toss order preview"
}

If an order POST times out or returns an ambiguous network failure, order_execute returns status: "unknown_execution_state" and directs callers to reconcile with order_status_summary/order_detail before any manual retry. The server does not automatically retry order POSTs.

order_status_summary example:

{
  "accountSeq": 1,
  "symbol": "005930",
  "limit": 50
}

Trading safety examples

Dry-run validation:

{
  "request": {
    "symbol": "005930",
    "side": "BUY",
    "orderType": "LIMIT",
    "quantity": "1",
    "price": "70000",
    "currency": "KRW"
  }
}

Real create requires all of the following:

ENABLE_TRADING=true
ENABLE_ORDER_CREATE=true
REQUIRE_CONFIRMATION=true
MAX_ORDER_KRW=100000
ALLOWED_SYMBOLS=005930

And the tool call must include:

{
  "dryRun": false,
  "confirmation": "I understand this may place a real Toss Securities order",
  "request": {
    "symbol": "005930",
    "side": "BUY",
    "orderType": "LIMIT",
    "quantity": "1",
    "price": "70000",
    "currency": "KRW"
  }
}

Official endpoint mapping

The implementation is intentionally thin and maps tools to official Toss Open API paths:

  • OAuth: POST /oauth2/token

  • Market/account/order data: /api/v1/... paths from https://openapi.tossinvest.com/openapi-docs/latest/openapi.json

  • Order create/modify/cancel: official /api/v1/orders POST paths only, guarded locally before any POST is attempted.

Development

npm install
npm test
npm run lint
npm run audit:prod

The required test suite uses Node's built-in test runner and mocked fetch calls. It does not require real Toss credentials and does not call live order endpoints.

Opt-in read-only integration smoke test

After configuring your own Toss credentials locally, you can run a safe read-only smoke test:

TOSS_API_KEY=... TOSS_SECRET_KEY=... npm run smoke:readonly

Optional account-scoped checks can use TOSS_ACCOUNT_SEQ, but the default smoke path only calls read-only tools that do not create, modify, or cancel orders: auth_status, accounts, and market_calendar. If TOSS_API_KEY or TOSS_SECRET_KEY is missing, the command exits successfully with a SKIP message and makes no Toss API request. Output is passed through the same redaction helpers used by the MCP server.

Timeout/retry policy

This server applies a configurable request timeout to OAuth, read-only calls, and order calls. GETs retain bounded transient retries: up to three for HTTP 429 and two for HTTP 502/503/504, with retry delays capped at 10 seconds. Authentication recovery is separately bounded to one retry as described above. POSTs do not receive transient retries or new token-revoked replay; existing invalid-token behavior and per-call opt-outs are unchanged. Never retry an ambiguous order outcome without reconciliation.

Release checklist

Before publishing or tagging a release:

  1. Verify package ownership and name availability; do not publish the unscoped tossinvest-openapi-mcp name.

  2. Run npm test, npm run lint, npm run audit:prod, and npm pack --dry-run.

  3. Confirm the dry-run tarball includes only runtime files (dist/ JavaScript/declarations without source maps), scripts/smoke-readonly.mjs, README.md, LICENSE, .env.example, and package metadata.

  4. Re-scan docs for secrets, account numbers, local paths, private workflow notes, or investment advice/automation claims.

  5. Publish only after explicit maintainer approval.

Publication hygiene

  • .gitignore excludes .env, .env.*, logs, coverage, node_modules, and build output.

  • .npmignore excludes local env files, logs, coverage, internal handoff/QA notes, and local run artifacts.

  • package.json files only publishes dist, public docs, .env.example, and changelog/security/license files.

Disclaimer

This software is not investment advice and does not implement trading strategy, rebalancing, optimization, or automated trading loops. Order tools can place real financial orders only when explicitly enabled and used with valid Toss credentials; use at your own risk.

Available Tools

27 tools
accountsA

List Toss Securities accounts. Account numbers are masked.

Inputs: no named parameters.

auth_statusA

Check Toss API credential configuration and token status without returning secrets.

Inputs: no named parameters.

buying_powerC

Read buying power for an account and currency.

Inputs: currency (required), accountSeq.

candlesD

Read candles for a symbol.

Inputs: symbol (required), interval (required), count, before, +1 more.

commissionsC

Read official Toss account commission rates.

Inputs: accountSeq.

exchange_rateC

Read exchange rate from official Toss API.

Inputs: baseCurrency (required), quoteCurrency (required), dateTime.

holdingsC

Read holdings for an account using X-Tossinvest-Account.

Inputs: symbol, accountSeq.

market_calendarC

Read KR or US market calendar.

Inputs: date, market.

orderbookC

Read orderbook for a symbol.

Inputs: symbol (required).

order_cancelA

Cancel an order. Default dry-run; real execution requires ENABLE_TRADING, ENABLE_ORDER_CANCEL, dryRun=false, confirmation, and caller-supplied request.symbol when symbol allow/block policy is configured.

Inputs: orderId (required), dryRun, request, accountSeq, +1 more.

order_createA

Create an order. Default dry-run; real execution requires ENABLE_TRADING, ENABLE_ORDER_CREATE, dryRun=false, confirmation, amount, and symbol gates.

Inputs: request (required), dryRun, accountSeq, confirmation.

order_detailC

Read one order detail for an account.

Inputs: orderId (required), accountSeq.

order_executeB

Fast preview-based order execution. Requires valid unexpired previewId, matching requestHash, exact confirmation, and passing env/delegated-authority gates. No automatic order POST retry.

Inputs: previewId (required), requestHash (required), confirmation (required), delegatedAuthority.

order_modifyA

Modify an order. Default dry-run; real execution requires ENABLE_TRADING, ENABLE_ORDER_MODIFY, dryRun=false, confirmation, and applicable gates.

Inputs: orderId (required), request (required), dryRun, accountSeq, +1 more.

order_previewB

Create an in-memory preview contract for an order. Never calls Toss order POST endpoints. order_execute confirmation text: I approve this exact Toss order preview

Inputs: request (required), date, accountSeq, ttlSeconds, +1 more.

orders_closedB

Read closed orders for an account if supported by Toss API.

Inputs: to, from, limit, cursor, +2 more.

orders_openC

Read open orders for an account.

Inputs: limit, symbol, accountSeq.

order_status_summaryC

Read-only order reconciliation summary for open and recently closed orders, state counts, and replace/modify caveats.

Inputs: to, from, limit, cursor, +2 more.

order_validateC

Validate order safety gates only. Never calls Toss order POST endpoints. Confirmation text: I understand this may place a real Toss Securities order

Inputs: request (required), dryRun, operation, confirmation.

portfolio_snapshotA

Read a structured account snapshot: holdings, KRW/USD buying power, open orders, calculable position weights, warning flags, and partial failures. Position weights use a KRW-converted, cash-inclusive denominator (holdings + KRW/USD cash buying power); when cashStatus is 'partial', omitted cash currencies are listed in omittedCashCurrencies. If status is 'partial', do not trust holdings.count as a complete account position count; retry or use a fallback read path.

Inputs: limit, accountSeq, currencies.

pre_trade_checkB

Run separate pre-execution safety/reality checks for a candidate order. Read/check only; not required in order_execute hot path.

Inputs: request (required), date, accountSeq, delegatedAuthority.

price_limitsB

Read upper/lower price limits for a symbol.

Inputs: symbol (required).

pricesA

Read current prices for comma-separated symbols.

Inputs: symbols (required).

sellable_quantityC

Read sellable quantity for an account and symbol.

Inputs: symbol (required), accountSeq.

stock_infoC

Read basic stock info for comma-separated symbols.

Inputs: symbols (required).

stock_warningsC

Read buy-warning information for a stock.

Inputs: symbol (required).

tradesC

Read recent trades for a symbol.

Inputs: symbol (required), count.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.7/5.0

    Scored across 27 tools

    Disambiguation3/5

    Many tools related to orders (e.g., orders_open, orders_closed, order_detail, order_validate, order_preview, order_execute, order_create, order_modify, order_cancel) have similar purposes but descriptions help distinguish them. Some overlap exists, such as between order_validate and order_preview, but they are not identical.

    Naming Consistency4/5

    All tool names use lowercase with underscores, but they are not strictly verb_noun; many are noun phrases (e.g., stock_info, exchange_rate, portfolio_snapshot) or adjective_noun (e.g., orders_open, orders_closed). The pattern is consistent in structure, though not perfectly verb_noun.

    Tool Count3/5

    With 27 tools, the server is on the upper end of a reasonable range. While a trading platform may require many tools, some could be combined (e.g., orders_open and orders_closed into one with a parameter) to reduce count without loss of functionality.

    Completeness4/5

    The tool surface covers market data, account information, order management, and safety checks comprehensively. Minor gaps exist, such as no explicit tool for deposit/withdrawal history, but core trading workflows are well-supported.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      C
      maintenance
      MCP server wrapping Toss Securities Open API, enabling stock price queries and trading for Korean and US stocks via natural language.
      36
      265 npm
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Toss Securities (토스증권) Open API MCP server for the Korean stock market. Supports real-time quotes, orderbook, candles, account holdings, buying power, and order management (create/modify/cancel) with a built-in safety gate requiring explicit confirmation before any real order is placed.
      36
      259 npm
      4
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      A local MCP server that automatically generates tools from Toss Securities' official OpenAPI spec, enabling real API calls with multi-layered order safety and OAuth 2.0 authentication.
      36
      1
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      MCP server for Toss Securities Open API that exposes Korean (KRX) and US market data, portfolio holdings, order management, and conditional orders through 28 tools, with read-only and authenticated remote modes.
      28
      MIT