TossInvest OpenAPI MCP について
TossInvest OpenAPI MCPは、Toss Securitiesの口座・市場データにアクセスする開発者向けローカルMCPサーバーです。読み取り専用ツールが既定で利用でき、実注文には明示的なゲート、確認、金額上限が必要です。
主な機能
- 01読み取り専用の市場・口座データ
- 02ポートフォリオと取引前チェック
- 03プレビューに基づく注文ワークフロー
- 04既定で無効の取引機能
- 05認証情報とトークンのマスキング
活用シーン
- 01保有資産と購買余力の確認
- 02市場価格と注文板の確認
- 03承認前の注文プレビュー
- 04最近の注文状況の照合
MCP 対応
ローカルstdioのMCPサーバーとして、Toss Securities Open APIのデータと安全策付き注文ツールをMCPクライアントに提供します。注文ツールはドライランが既定で、実行には安全ゲートの設定が必要です。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
tossinvest-openapi-mcp
公式の Toss Securities / 토스증권 Open API 向けの、安全性をデフォルトで重視したローカル stdio MCP サーバーです。
このパッケージは独立した開発者向けツールであり、Toss Securities と提携、承認、または後援を受けていません。
このパッケージは、MCP クライアントでアカウント、マーケット、注文のデータを読み取り専用で利用したい開発者向けに設計されています。また、複数の明示的な安全ゲートで保護された注文操作も任意で利用できます。
安全性のデフォルト設定
- 公式の Toss Open API サーバーのみを使用します:
https://openapi.tossinvest.com - 認証情報なしで起動し、設定が不足している場合もクラッシュせずに
auth_statusで報告します。 - OAuth アクセストークンはメモリ内にのみ保持します。
- 対象となる GET リクエストで
401 invalid-tokenまたは401 token-revokedが返された場合、該当するキャッシュ済みトークンを置き換えて1回再試行します。同じクライアントインスタンス内では、並行するトークン発行を共有します。 auth_statusはトークン発行とデータエンドポイントへの到達可能性を分けて報告し、デフォルトのTOSS_ACCOUNT_SEQが設定されているかどうかも報告します。- API キー、シークレット、Bearer トークン、アカウントヘッダー、口座番号をツールの出力やエラーから秘匿します。
- 取引はデフォルトで無効です。
- v0.2 のワークフローツールは、安全性を優先したプレビュー方式です:
portfolio_snapshot → pre_trade_check → order_preview → approval → order_execute → order_status_summary。 order_previewはプレビュー契約をメモリ内にのみ保存し、Toss の注文 POST エンドポイントを呼び出しません。order_executeは意図的に高速です。プレビュー/確認/ハッシュ/環境変数/委任権限の各ゲートのみを再確認して、注文 POST を最大1回送信します。タイムアウトやネットワークの結果が不明な場合はunknown_execution_stateとして報告し、手動で再試行する前に照合を促します。- 注文ツールのデフォルトは
dryRun=trueです。 - 実際の作成/変更/キャンセル操作には、
ENABLE_TRADING=trueと操作ごとのゲートが必要です。 - デフォルトで確認が必要です。
- 注文金額のデフォルト上限は
0KRW および0USD です。 BLOCKED_SYMBOLSはALLOWED_SYMBOLSより優先されます。
インストールと実行
このリポジトリは現在、GitHub のソースのみから配布されています。EthanKlocked 所有のパッケージとして npm には公開されていません。
重要:スコープなしの npm パッケージ名 tossinvest-openapi-mcp は、すでに別の npm パッケージで使用されています。そのため、このリポジトリのコードを期待して、そのパッケージをインストールまたは実行しないでください。
このリポジトリをクローンしてから、ローカルでインストールおよびビルドします:
git clone https://github.com/EthanKlocked/tossinvest-openapi-mcp.git
cd tossinvest-openapi-mcp
npm install
npm run build
npm test
ローカルで実行します:
TOSS_API_KEY=... TOSS_SECRET_KEY=... node dist/index.js
コミットするファイルに実際のシークレットを含めないでください。ローカルシェルまたは MCP クライアントのシークレットマネージャーから環境変数を渡す方法を推奨します。
MCP クライアント設定の例
ローカルのクローン先のパスを使用します:
{
"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}"
}
}
}
}
このプロジェクトが後日 npm に公開される場合は、すでに使用されているスコープなしの名前ではなく、@ethanklocked/tossinvest-openapi-mcp のようなメンテナー所有のパッケージ名を使用してください。
環境変数
| 名前 | デフォルト | 用途 |
|---|---|---|
TOSS_API_KEY | 未設定 | Toss Open API のクライアント ID/API キーです。 |
TOSS_SECRET_KEY | 未設定 | Toss Open API のクライアントシークレットです。 |
TOSS_ACCOUNT_SEQ | 未設定 | アカウント単位のツールで使用する任意のデフォルト口座シーケンスです。 |
ENABLE_TRADING | false | 実際の注文操作全般に対するグローバルゲートです。 |
ENABLE_ORDER_CREATE | false | 実際の注文作成に対するゲートです。 |
ENABLE_ORDER_MODIFY | false | 実際の注文変更に対するゲートです。 |
ENABLE_ORDER_CANCEL | false | 実際の注文キャンセルに対するゲートです。 |
REQUIRE_CONFIRMATION | true | 実際の注文操作には、完全一致する確認テキストが必要です。 |
MAX_ORDER_KRW | 0 | 計算された KRW 注文金額の最大許容額です。 |
MAX_ORDER_USD | 0 | 計算された USD 注文金額の最大許容額です。 |
ALLOWED_SYMBOLS | 未設定 | 任意のカンマ区切りの許可リストです。 |
BLOCKED_SYMBOLS | 未設定 | 任意のカンマ区切りのブロックリストです。許可リストより常に優先されます。 |
TOSS_REQUEST_TIMEOUT_MS | 15000 | OAuth、読み取り専用、注文リクエストのタイムアウトです。ローカルでのデバッグ時のみ 0 に設定してタイムアウトを無効にします。 |
実際の注文操作に必要な確認テキスト:
I understand this may place a real Toss Securities order
ツール
読み取り専用ツール:
auth_statusaccountsholdingspricesorderbooktradesprice_limitscandlesstock_infostock_warningsexchange_ratemarket_calendarorders_openorders_closedorder_detailbuying_powersellable_quantitycommissions
ワークフローツール:
portfolio_snapshot— 保有資産、KRW/USD の購買余力、未約定注文、算出可能なポジション比率、口座/accountSeq の状態、警告フラグ、および部分的な失敗を読み取ります。ポジション比率の分母には、KRW 換算した現金を含みます(保有資産 + KRW/USD の現金購買余力)。cashStatusがpartialの場合、省略された現金通貨はomittedCashCurrenciesに一覧表示されます。pre_trade_check— 注文候補に対する独立した読み取り/チェックレイヤーです。canProceedDryRun、realOrderBlockedByDefault、checks、warnings、blockers、missing、estimate、dataFreshnessを返します。order_preview— メモリ内のプレビュー契約を作成します。previewId、requestHash、ttlSeconds、expiresAt、正確なconfirmationText、金額/手数料/現金/数量の推定チェック、ゲートの状態、リスクフラグ、および算出可能性に関する注記を返します。注文 POST エンドポイントは呼び出しません。デフォルトの TTL は 90 秒、受け付ける TTL の最大値は 300 秒です。order_execute— プレビューに基づいて迅速に注文を送信します。previewId、一致するrequestHash、正確な確認文(I approve this exact Toss order preview)、有効期限内のプレビュー、環境ゲート、およびオプションの委任権限の上限が必要です。処理のホットパスではpre_trade_checkを実行せず、注文 POST の自動再試行も追加しません。order_status_summary— 未約定/最近決済された注文の読み取り専用の照合サマリーです。状態別件数、約定/一部約定/キャンセル/拒否/訂正関連の状態(存在する場合)、および消失/訂正された注文に関する注意事項を返します。
取引ツール:
order_validate— ローカルゲートのみをチェックし、Toss の注文 POST エンドポイントは呼び出しません。order_create— デフォルトではドライランです。実際の注文執行には、作成に関するすべてのゲートを満たす必要があります。order_modify— デフォルトではドライランです。実際の注文執行には、変更に関するすべてのゲートを満たす必要があります。order_cancel— デフォルトではドライランです。実際の注文執行には、キャンセルに関するすべてのゲートを満たす必要があります。ALLOWED_SYMBOLSまたはBLOCKED_SYMBOLSが設定されている場合、POST 前にローカルのシンボルポリシーを評価できるよう、実際のキャンセルには呼び出し元からrequest.symbolも指定する必要があります。キャンセル前にサーバーが注文詳細を取得することはありません。これは API への依存をもう一つ追加することになり、安全性の根拠として利用する前に、ライブ認証情報を持つユーザーが公式の詳細ペイロードの形式を確認する必要があるためです。
認証状態と口座の選択
auth_status は、OAuth トークンの発行と実際のデータ API の到達可能性を意図的に分けています。
configured:必要な認証情報の環境変数が設定されています。tokenAvailable:POST /oauth2/tokenが成功しました。dataApiReachable:GET /api/v1/accountsに対する実際の読み取り専用データチェックが成功しました。authenticated:トークンの発行とデータエンドポイントのチェックの両方が成功した場合にのみtrueになります。accountSeqConfigured:TOSS_ACCOUNT_SEQが設定されている場合にtrueになります。accountSeqRequiredForAccountTools:trueです。口座に紐づくツールでは、呼び出しごとのaccountSeqまたはTOSS_ACCOUNT_SEQが必要です。
prices、orderbook、trades、stock_info などのほとんどのマーケットデータツールでは、accountSeq は不要です。holdings、orders_open、orders_closed、order_detail、buying_power、sellable_quantity、commissions などの口座に紐づくツール、および実注文/ドライラン注文ツールでは、ツール引数または TOSS_ACCOUNT_SEQ を通じて accountSeq を指定する必要があります。
トークンの再取得と診断
トークンの再取得は、HTTP 401 の場合に限り、構造化された code または error.code の値が完全一致する場合(invalid-token、token-revoked)に行われます。error.code がある場合は、無関係な値や競合する値であっても、こちらが優先されます。トップレベルの code は、ネストされたコードがない場合にのみ使用されます(たとえば、message だけを含む error オブジェクト)。メッセージ、任意のネストされた文字列、無関係な 401 エラーによってトークンが発行されることはありません。GET リクエストでの認証リトライは最大 1 回です。2 回目に拒否された場合は API エラーとして返されます。既存の POST における invalid-token のリトライ動作は維持されますが、POST での token-revoked はリプレイされません。内部オプション retryInvalidToken: false を指定すると、両方の認証回復コードが無効になります。これには、すでに無効化する設定になっている注文実行パスも含まれます。注文の結果が不明確な場合は、引き続き自動リプレイではなく照合が必要です。
トークンは引き続きメモリ内のみで保持され、既存の 30 秒の有効期限マージンと、既存の最小有効期間 60 秒/デフォルト 3600 秒を適用して expires_in を使用します。同一クライアントインスタンス内では、コールドスタート時や更新時に並行して行われるトークン発行は、1 件の処理を共有します。キャッシュの世代はオブジェクトの同一性で判定されるため、プロバイダーが同じトークン文字列を返した場合でも、遅れて発生した拒否によって新しい世代が破棄されることはありません。別々のプロセスや外部クライアント間では調整されません。定期的なトークン発行やリフレッシュトークンのグラントはありません。
認証情報が設定されている場合、auth_status に tokenLifecycle が追加されます。これは最新のトークン発行試行のスナップショットであり、データ API に受け入れられたことを示すものではありません。既存のステータスフィールドは維持されます。データアクセスを確認するには、トークンの拒否が繰り返された場合も含めて、dataApiReachable/dataApiCheck を使用してください。
reason:cold-cache、expiry-margin、invalid-token、token-revokedのいずれかです。startedAt、completedAt、expiresAt:Unix エポックのミリ秒です。処理中または取得できない場合、完了時刻/有効期限はnullになります。durationMs:トークン発行にかかった時間(ミリ秒)です。処理中はnullになります。outcome:pending、succeeded、failedのいずれかです。
診断情報には、これらの固定カテゴリと時間情報のみが含まれます。トークン、認証情報、ヘッダー、プロバイダーのレスポンス本文、生のネットワークメッセージは含まれません。トークン発行に失敗した場合は、安全で対処方法が分かる設定/ネットワークエラーが返されます。その後のリクエストで再度トークン発行を試みることができます。新しい環境変数や必須のツール引数は追加されません。
ソースを更新した後、npm run build を実行し、新しいビルドを読み込むために MCP サブプロセスを再起動してください。利用環境へのデプロイと読み取り専用の検証は、運用担当者が別途行う手順です。ソースのテストだけでは、実行環境が更新されたことを確認できません。
エンドポイントマッピング
| ツール | メソッド/パス | 副作用 |
|---|---|---|
auth_status | POST /oauth2/token; トークンの発行に成功した場合は続けて GET /api/v1/accounts | トークン/データへの到達性チェックのみ |
accounts | GET /api/v1/accounts | 読み取り専用 |
holdings | GET /api/v1/holdings | 読み取り専用 |
prices | GET /api/v1/prices | 読み取り専用 |
orderbook | GET /api/v1/orderbook | 読み取り専用 |
trades | GET /api/v1/trades | 読み取り専用 |
price_limits | GET /api/v1/price-limits | 読み取り専用 |
candles | GET /api/v1/candles | 読み取り専用 |
stock_info | GET /api/v1/stocks | 読み取り専用 |
stock_warnings | GET /api/v1/stocks/{symbol}/warnings | 読み取り専用 |
exchange_rate | GET /api/v1/exchange-rate | 読み取り専用 |
market_calendar | GET /api/v1/market-calendar/KR または GET /api/v1/market-calendar/US | 読み取り専用 |
orders_open | GET /api/v1/orders?status=OPEN | 読み取り専用 |
orders_closed | GET /api/v1/orders?status=CLOSED | 読み取り専用 |
order_detail | GET /api/v1/orders/{orderId} | 読み取り専用 |
buying_power | GET /api/v1/buying-power | 読み取り専用 |
sellable_quantity | GET /api/v1/sellable-quantity | 読み取り専用 |
commissions | GET /api/v1/commissions | 読み取り専用 |
portfolio_snapshot | GET /api/v1/holdings、GET /api/v1/buying-power、GET /api/v1/orders?status=OPEN を組み合わせます | 読み取り専用のワークフロースナップショット |
pre_trade_check | マーケットカレンダー、警告、価格制限、買付余力/売却可能数量、手数料、未約定注文を組み合わせます | 読み取り/チェックのみ。注文 POST は行いません |
order_preview | ローカルのプレビュー契約と読み取り/チェック呼び出し | Toss の注文 POST は行いません。プレビューはメモリー内にのみ保存されます |
order_execute | プレビュー/確認/ハッシュ/環境のゲートを通過した場合に限り POST /api/v1/orders | 注文 POST は最大1回。注文 POST の自動再試行は行いません |
order_status_summary | GET /api/v1/orders?status=OPEN および GET /api/v1/orders?status=CLOSED | 読み取り専用の照合 |
order_validate | ローカルでゲートを評価するのみ | Toss の注文 POST は行いません |
order_create | POST /api/v1/orders | すべてのゲートを通過した場合に限り実注文を行います |
order_modify | POST /api/v1/orders/{orderId}/modify | すべてのゲートを通過した場合に限り実際の注文変更を行います |
order_cancel | POST /api/v1/orders/{orderId}/cancel | すべてのゲートを通過した場合に限り実際の注文取消を行います |
v0.2 ワークフローの例
安全性を優先する推奨フロー:
portfolio_snapshot → pre_trade_check → order_preview → user/delegated approval → order_execute → order_status_summary
マーケットカレンダーのチェックは、リクエストの市場に応じて振り分けられます。
currency=KRWまたは6桁の韓国株式シンボルの場合は、market_calendar(KR)を使用します。- 米国株のティッカー/
currency=USDの場合は、market_calendar(US)を使用します。 result.today.dayMarket、preMarket、regularMarket、afterMarketがすべてnullの場合、公式カレンダーの形式から米国の非営業日を検出します。result.today.integratedがnullの場合、韓国の非営業日を検出します。- その場合、
pre_trade_checkとorder_previewはmarket、date、nextBusinessDayを含むmarket_closed_non_business_dayブロッカーを返します。missingにmarket_open_unknownは報告しません。
portfolio_snapshot の例:
{
"accountSeq": 1,
"currencies": ["KRW", "USD"],
"limit": 50
}
pre_trade_check の例です。これは独立した読み取り/チェック用ツールであり、意図的に order_execute のホットパスには組み込まれていません。
{
"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 の例です。Toss の注文 POST エンドポイントは呼び出さず、previewId、requestHash、TTL、正確な確認テキストを返します。
{
"accountSeq": 1,
"ttlSeconds": 90,
"request": {
"symbol": "005930",
"side": "BUY",
"orderType": "LIMIT",
"quantity": "1",
"price": "70000",
"currency": "KRW"
}
}
order_execute の例です。プレビュー応答から previewId、requestHash、正確な confirmationText をコピーしてください。
{
"previewId": "preview_...",
"requestHash": "<sha256-from-preview>",
"confirmation": "I approve this exact Toss order preview"
}
注文 POST がタイムアウトするか、曖昧なネットワークエラーを返した場合、order_execute は status: "unknown_execution_state" を返します。手動で再試行する前に、order_status_summary/order_detail で照合するよう呼び出し元に指示します。サーバーは注文 POST を自動的に再試行しません。
order_status_summary の例:
{
"accountSeq": 1,
"symbol": "005930",
"limit": 50
}
取引の安全性に関する例
ドライラン検証:
{
"request": {
"symbol": "005930",
"side": "BUY",
"orderType": "LIMIT",
"quantity": "1",
"price": "70000",
"currency": "KRW"
}
}
実際に作成するには、以下のすべてが必要です:
ENABLE_TRADING=true
ENABLE_ORDER_CREATE=true
REQUIRE_CONFIRMATION=true
MAX_ORDER_KRW=100000
ALLOWED_SYMBOLS=005930
また、ツール呼び出しには以下を含める必要があります:
{
"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"
}
}
公式エンドポイントのマッピング
この実装は意図的に薄く作られており、ツールを Toss Open API の公式パスにマッピングします:
- OAuth:
POST /oauth2/token - 市場/口座/注文データ:
https://openapi.tossinvest.com/openapi-docs/latest/openapi.jsonに記載されている/api/v1/...パス - 注文の作成/変更/キャンセル:公式の
/api/v1/ordersPOST パスのみ。POST を試行する前にローカルでガードされます。
開発
npm install
npm test
npm run lint
npm run audit:prod
必須のテストスイートでは、Node 組み込みのテストランナーとモック化された fetch 呼び出しを使用します。実際の Toss 認証情報は不要で、実際の注文エンドポイントも呼び出しません。
オプトインの読み取り専用インテグレーションスモークテスト
お使いの Toss 認証情報をローカルで設定した後、安全な読み取り専用スモークテストを実行できます:
TOSS_API_KEY=... TOSS_SECRET_KEY=... npm run smoke:readonly
オプションの口座指定チェックでは TOSS_ACCOUNT_SEQ を使用できますが、デフォルトのスモークテストでは、注文の作成、変更、キャンセルを行わない読み取り専用ツール(auth_status、accounts、market_calendar)のみを呼び出します。TOSS_API_KEY または TOSS_SECRET_KEY が設定されていない場合、コマンドは SKIP メッセージを表示して正常終了し、Toss API リクエストは行いません。出力には、MCP サーバーと同じ秘匿化ヘルパーが適用されます。
タイムアウト/再試行ポリシー
このサーバーでは、OAuth、読み取り専用呼び出し、注文呼び出しに設定可能なリクエストタイムアウトを適用します。GET では回数を制限した一時的なエラーの再試行を行います。HTTP 429 の場合は最大 3 回、HTTP 502/503/504 の場合は最大 2 回で、再試行の遅延は 10 秒を上限とします。認証の復旧では、前述のとおり、別途 1 回に限り再試行します。POST では一時的なエラーの再試行も、新たな token-revoked 再実行も行いません。既存の invalid-token の動作と呼び出しごとのオプトアウト設定は変更されません。照合を行わずに、結果が不明な注文を再試行しないでください。
リリースチェックリスト
リリースを公開またはタグ付けする前に:
- パッケージの所有権と名前の利用可能性を確認してください。スコープなしの
tossinvest-openapi-mcpという名前は公開しないでください。 npm test、npm run lint、npm run audit:prod、npm pack --dry-runを実行してください。- ドライランの tarball に、実行時ファイル(ソースマップなしの
dist/内の JavaScript/宣言ファイル)、scripts/smoke-readonly.mjs、README.md、LICENSE、.env.example、パッケージメタデータのみが含まれていることを確認してください。 - ドキュメントを再確認し、シークレット、口座番号、ローカルパス、非公開のワークフローメモ、投資助言/自動化に関する主張がないことを確かめてください。
- メンテナーから明示的な承認を得てから公開してください。
公開時の衛生管理
.gitignoreでは、.env、.env.*、ログ、カバレッジ、node_modules、ビルド出力を除外します。.npmignoreでは、ローカルの環境ファイル、ログ、カバレッジ、内部引き継ぎ/QA メモ、ローカル実行時の成果物を除外します。package.jsonのfilesでは、dist、公開ドキュメント、.env.example、変更履歴/セキュリティ/ライセンス関連ファイルのみを公開します。
免責事項
このソフトウェアは投資助言ではなく、取引戦略、リバランス、最適化、自動取引ループを実装するものでもありません。注文ツールは、明示的に有効化され、有効な Toss 認証情報を使用した場合に限り、実際の金融注文を発注できます。ご自身の責任でご利用ください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。