decker
Deterministic market-state engine for trading agents — state, gate, coordinates, with receipts.
Sollte ich dies verwenden
Qualität und Sicherheit
Befunde (17)
- HIGH
- MEDIUMin decker.place_order
- LOWin decker.get_signals
- LOWin decker.get_assembly
- LOWin decker.get_reading
- LOWin decker.get_view
- LOWin decker.get_market_state
- LOWin decker.get_price_axis_state
- LOWin decker.get_state_timeline
- LOWin decker.get_trigger_history
Basierend auf einer automatisierten Analyse der Tool-Definitionen und der Einhaltung des Protokolls.
Kontextkosten
Dies ist die ungefähre Anzahl der Tokens, die jedes Mal verbraucht werden, wenn die Tools des Servers in den Kontext eines Modells geladen werden. Höhere Werte verringern die Aufmerksamkeit, die für andere Aufgaben verfügbar ist.
Installieren
Installation mit einem Klick
Fügen Sie dies Ihrer Datei `claude_desktop_config.json` hinzu:
{
"mcpServers": {
"decker": {
"url": "https://api.decker-ai.com/api/v1/mcp"
}
}
}Remote-Endpunkte
https://api.decker-ai.com/api/v1/mcpstreamable-httpWas es kann
Tool-Inventar
Tools (15)
🟢decker.get_signals(symbols, min_progress, action_gate, timeframe, limit)
Active trading signals for the current user (with Skill Overlay applied), in customer-facing shape: coordinates (entry/target/stop), decision (ENTER/WAIT/SKIP — is_actual_trigger=true only for ENTER; WAIT/SKIP are standing candidates, not executed triggers), action_gate posture (GO/WATCH/HOLD — a stance, not an order command), progress, MTF verdict, and a plain-language summary_ko line. risk_reward_ratio is computed on the DISPLAYED coordinates (after overlay). Signals are retained rather than cut when they age (turn-retention policy) — read freshness_state (open|aged) / age_bars / freshness_sec before treating an old PENDING row as current. Filtered by symbols / min_progress / action_gate — action_gate here filters the CURRENT-MOMENT representative state, it does not search history (almost always 0 rows unless a gate is GO right now); for past GO events with their entry/target/stop and realized performance use decker.get_trigger_history instead. object_context (W1-C1 standard object block, present when a recent trigger bar exists): my_anchor / opp_anchor (reversal destination) / judgment_ref / geometry / why (action_gate + trigger_kind only — internal reason codes are scrubbed on this customer surface, use decker.get_market_state for those) / reverse_branch context (object_context.reverse_direction_conflict is present only when a local reversal shows stage='confirmed' but the swing's confirmed direction still disagrees — read it before treating reverse_branch.stage='confirmed' as a swing-level reversal). null on non-trigger bars or symbols outside the narrative universe (e.g. individual KRX stocks). Before placing any order through any execution tool, check the intent with decker.validate_intent.
Eingabe-Schema
{
"type": "object",
"properties": {
"symbols": {
"type": "array",
"items": {
"type": "string"
},
"description": "Symbol filter (e.g. ['BTCUSDT','ETHUSDT']). Omit for all."
},
"min_progress": {
"type": "number",
"minimum": 0,
"maximum": 100,
"description": "Minimum progress_pct (0-100)."
},
"action_gate": {
"type": "string",
"enum": [
"GO",
"WATCH",
"HOLD"
],
"description": "Engine action gate filter (3-layer grammar: gate = transition posture, not an order command). Rows where the engine emitted no gate for this bar (effective_action_gate null, e.g. KRX daily) are excluded when this filter is set."
},
"timeframe": {
"type": "string",
"enum": [
"30m",
"1h",
"4h",
"8h",
"1d"
],
"description": "Signal horizon filter (30m=scalp, 1h=swing, 4h/8h/1d=position). The same symbol can hold OPPOSITE directions on different horizons — omit to get the latest active signal regardless of horizon (its timeframe field says which one you got; when a specific symbols[] was requested, a row's other_horizon_conflict field flags it if another horizon is ACTIVE with the opposite direction). Prefer decker.get_assembly for the composed cross-horizon judgment instead of guessing which horizon to pass here."
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 20
}
}
}🟢decker.get_assembly(symbol)
Multi-timeframe optimal-path assembly per symbol (STRATEGY_LAYER §8): one deterministic machine verdict combining all live timeframes — direction, grade (aligned | structure+pullback | exhaustion-reversal), entry (now vs wait, with source TF), stop (risk stop), target (upper-TF target), RR, and a conditional switch coordinate on mixed structure. Upper TF supplies the target (slower = higher success), lower TF supplies the entry. This is the single judgment authority — narrate or filter it, do not re-decide coordinates. Omit symbol for all 14 universe symbols. ⚠ grade='aligned' means no OPPOSING-direction row exists among the active timeframes — it does NOT mean every timeframe's gate is GO/actionable right now. Check matrix_summary[].gate per timeframe before treating 'aligned' as 'all timeframes tradeable now'. ⚠ entry.mode='지금'(now) is a pure price-geometry verdict (STRATEGY_LAYER §8 R3 — is current price within the exhaustion-reversal zone or the ±0.3% entry band), independent of any timeframe's trigger/gate state — it does NOT mean the engine has confirmed a break event on this bar. Check the entry TF's row in matrix_summary[].gate before treating entry.mode='지금' as 'a trigger just fired, act now'.
Eingabe-Schema
{
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Optional symbol or alias (BTC, 비트코인, GOLD, 테슬라...). Omit for the full universe."
}
}
}🟢decker.get_reading(symbol, tf, include_tfs)
AI-synthesized market reading for a symbol/timeframe, in customer-facing language: current state description, directional bias scores, bidirectional break targets, MTF verdict per timeframe, and an execution hint (stance + long/short setups). Engine-native raw fields are NOT exposed here — use the REST raw contract (GET /public/reading) or decker.get_market_state for those — except object_context (W1-C1 standard object block, explicit exception: my_anchor/opp_anchor/judgment_ref/geometry/reverse_branch + why limited to action_gate/trigger_kind (internal reason codes scrubbed on this customer surface), present when a recent trigger bar exists, null otherwise incl. individual KRX stocks). object_context.reverse_direction_conflict is present only when a local reversal shows stage='confirmed' but the swing's confirmed direction still disagrees — read it before treating reverse_branch.stage='confirmed' as a swing-level reversal. execution_hint.preferred_direction is derived from key_direction alone and is NOT guaranteed to have a matching long_setup/short_setup (they come from an independent break-target resolver) — check that the setup for the preferred side is non-null before treating preferred_direction as an actionable side.
Eingabe-Schema
{
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "e.g. BTCUSDT"
},
"tf": {
"type": "string",
"enum": [
"15m",
"30m",
"1h",
"4h",
"8h",
"1d",
"1w"
],
"default": "4h"
},
"include_tfs": {
"type": "string",
"description": "Comma-separated additional TFs (e.g. '1h,4h,1d')."
}
},
"required": [
"symbol"
]
}🟢decker.get_view(symbol, tf)
The engine's VIEW for a symbol — the same composed card the daily briefing sends (single composer, verbatim): overall verdict, big/main timeframe alignment, the current game narrative in plain language, coordinates (baseline ref_price / target / invalidation), 'at this price, this view', and recent self-scoring verdicts (receipts). layer=STATE_VIEW: a market-state reading, NOT a trade instruction. Prefer this over get_market_state when you want the interpreted view instead of raw engine fields. object_context (W1-C1 standard object block, present when a recent trigger bar exists): my_anchor/opp_anchor(reversal destination)/judgment_ref/geometry/why(action_gate+trigger_kind only, reason codes scrubbed on this customer surface)/reverse_branch context (object_context.reverse_direction_conflict is present only when a local reversal shows stage='confirmed' but the swing's confirmed direction still disagrees — read it before treating reverse_branch.stage='confirmed' as a swing-level reversal). null on non-trigger bars or symbols outside the narrative universe. Before placing any order through any execution tool, check the intent with decker.validate_intent.
Eingabe-Schema
{
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "e.g. BTCUSDT, XYZ_GOLDUSD (crypto + HL TradFi synthetics; KRX daily lineage not yet covered by view v1)"
},
"tf": {
"type": "string",
"enum": [
"30m",
"1h",
"4h",
"8h",
"1d"
],
"description": "Optional view timeframe — the grounded narrative is composed on this TF's bar (e.g. '1h' when the user asks about the 1-hour picture). Omit for the engine's default action TF (usually 4h, same as the daily briefing card)."
}
},
"required": [
"symbol"
]
}🟢decker.get_market_state(symbol, timeframe)
Market State v0 — current engine structural state for a symbol/timeframe (latest evaluated bar, persisted engine emit read as-is, zero recompute). DOMAIN FRAME (why this engine exists): the market is read as a TARGET GAME — every coordinate comes from a *verified anchor* (a past level where a triggered move actually succeeded). The `game` block tells you the context that matters: game.status = forming_target (new anchor set, awaiting test) | testing_target (price is testing whether the declared target holds) | direction_resolved (game decided, price traveling); game.target = WHO is being judged (anchor id/phase/band); game.progress_dest = where price goes if the move proceeds (the opposing verified anchor to conquer); game.reverse_dest = where it goes if the move fails (the opposite house — also the stop logic's home); game.why_gate = full gate derivation chain; game.zt_regime = output canonicality (restored = deterministic delta lineage). action_gate alone (GO/WATCH/HOLD) is only a posture — the game context is the information. RAW CONTRACT: fields are engine-native vocabulary (c_state, hold_reason, R_* risk enums …), NOT customer-facing prose — for a human-language view use decker.get_view (with tf) or decker.get_reading. layer=STATE: this is a market-state reading, NOT a trade instruction. Absent fields are null (engine did not emit that axis — no filling). IMPORTANT: top-level state.c_state/action_gate/trigger_kind reflect the TRIGGER SNAPSHOT (only populated on a bar that actually had a trigger event) — null on most bars is normal, not a data gap. For the always-present, every-bar-populated view of the same axes use game.phase.c_state / game.phase.action_gate instead (different freshness, same underlying engine state machine). Don't read a null top-level field as 'engine has no state' — check game.phase first. object_context (top-level, W1-C1 standard object block, present when a recent trigger bar exists): my_anchor/opp_anchor(reversal destination)/judgment_ref/geometry/why(engine reason_codes)/reverse_branch context (object_context.reverse_direction_conflict is present only when a local reversal shows stage='confirmed' but the swing's confirmed direction still disagrees — read it before treating reverse_branch.stage='confirmed' as a swing-level reversal). null on non-trigger bars or symbols outside the narrative universe (e.g. individual KRX stocks). current_price (top-level, 2026-09-03): {price, bar_ts} — the single latest completed-bar close for this symbol ACROSS ALL timeframes (not just the requested tf), useful when comparing multiple timeframes' target bands against one 'now' price. null for KRX individual-stock symbols. Before placing any order through any execution tool, check the intent with decker.validate_intent.
Eingabe-Schema
{
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "e.g. BTCUSDT"
},
"timeframe": {
"type": "string",
"enum": [
"30m",
"1h",
"4h",
"8h",
"1d"
]
}
},
"required": [
"symbol",
"timeframe"
]
}🟢decker.get_price_axis_state(symbol, timeframe)
Price-axis (close-based target selection) state, read from engine_bar_state as persisted (Store-Output-Read, no recomputation). One voice: `signal` is the current state — side (+ buy / - sell), the signal bar (judgment bar '2' sealed by S) with its low/high, entry candidates (target, close two bars before the signal, bar-2 open, bar-2 close), and the outcome stated as WHAT crossed WHAT: status 'confirmed' = a close beyond the signal-bar edge in the signal's direction (resolved_ts, resolved_close), 'failed' = beyond the opposite edge, 'inside' = 판정보류 (close still inside the signal bar). `prev`/`history` = earlier signals with the same fields. active_target = the target this unit is labeling from (price, touch_kind, touched_ts); label = this bar's labeler output (t1/t2/1/2/+S/-S); pending_targets/rolling_target/conn_stems = coordinates. goal = exit target measured from the entry (signal bar-2 open): nearest opposite confirmed-signal edge at least 2% away, plus `ladder` = nearest such level at >=2% / >=4% / >=8% from entry (empty tier = no structure there, never filled with a percentage); goal.price null + reason = no level >=2% from entry. event_flow = the persisted event history (oldest→newest, last 20): target_selected / signal / signal_resolved (signal bar confirmed/failed with the close that decided it) / conn_arrival — compare the current state against how the events flowed. Omit timeframe for the multi-timeframe view: one row per TF {readable, target, signal, close} — side by side, no cross-TF verdict (cross_tf_verdict stays null). IMPORTANT — action_gate is always null BY DESIGN: this axis is diagnostic-only and not wired to any gate or order path. For GO/WATCH/HOLD use decker.get_market_state (MAIN axis). null when the engine has not evaluated the symbol/TF.
Eingabe-Schema
{
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "e.g. BTCUSDT"
},
"timeframe": {
"type": "string",
"description": "OMIT for the multi-timeframe view (all TFs side by side) — that is the intended way to read this axis. Pass one TF only when you deliberately want a single horizon.",
"enum": [
"30m",
"1h",
"4h",
"8h",
"1d",
"1w"
]
}
},
"required": [
"symbol"
]
}🟢decker.get_state_timeline(symbol, timeframe, since, limit)
Market State v0 — per-bar state timeline for a symbol/timeframe (same schema as decker.get_market_state, except each item carries a SLIM `game` tag {status, target_id, zt_regime, provenance} instead of the full game block — read status transitions across bars to see how the target game unfolded (forming → testing → resolved/failed); ascending by bar_ts). Bars the engine did not emit are simply absent (honest gaps, no filling).
Eingabe-Schema
{
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "e.g. BTCUSDT"
},
"timeframe": {
"type": "string",
"enum": [
"30m",
"1h",
"4h",
"8h",
"1d"
]
},
"since": {
"type": "string",
"description": "ISO8601 lower bound on bar_ts (exclusive). Optional."
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 500,
"default": 100
}
},
"required": [
"symbol",
"timeframe"
]
}🟢decker.get_trigger_history(symbol, timeframe, since, limit)
ACTION axis — actual historical GO triggers (not standing WATCH/HOLD candidates) for a symbol, with entry/target/stop coordinates and realized performance (mfe_pct/mae_pct/exit_reason/exit_price from trigger_performance, null = still open). Distinct from decker.get_signals (which reflects only the current-moment state, not a searchable history — its action_gate filter answers 'what does symbol×tf look like right now', not 'when did this last fire'). Use this to answer 'what did the engine actually trigger recently and at what price' — decker.get_signals/get_market_state cannot answer that. direction is judgment_signals-native vocabulary ("long"/"short"), distinct from the "+"/"-" convention used by other tools — read as-is, no translation.
Eingabe-Schema
{
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "e.g. BTCUSDT"
},
"timeframe": {
"type": "string",
"enum": [
"30m",
"1h",
"4h",
"8h",
"1d"
],
"description": "Optional — omit for all timeframes."
},
"since": {
"type": "string",
"description": "ISO8601 lower bound on trigger time (exclusive). Optional."
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"default": 20
}
},
"required": [
"symbol"
]
}⚪decker.get_user_skills
Trading skill catalog + currently active overlay for this user. Returns 8 published skills (conservative_v0/standard_v0/aggressive_v0/default_v0/scalp_v0/tight_v0/wide_v0/swing_v0) and the user's selected one.
Eingabe-Schema
{
"type": "object",
"properties": {}
}🟡decker.set_skill_overlay(skill_id)
Change active trading skill overlay for this user. Immediately affects all subsequent get_signals calls and downstream channels.
Eingabe-Schema
{
"type": "object",
"properties": {
"skill_id": {
"type": "string",
"description": "trading_skills.id (e.g. 'aggressive_v0')."
}
},
"required": [
"skill_id"
]
}🟢decker.validate_intent(symbol, side, order_type, timeframe)
Pre-trade gate check for a proposed order intent. Call this BEFORE placing any order through any execution tool (e.g. a broker MCP's review→place flow). Checks the intent (symbol + side) against Decker's deterministic market state: engine action_gate (GO/WATCH/HOLD — a transition posture, not an order command), current structural state, and the active signal's direction / invalidation (stop) coordinates. Returns a stance reading, NOT an approval or rejection: the vocabulary is the engine gate as-is plus a mechanical side_alignment (aligned/opposed vs the active signal's direction). covered=false means the engine does not emit state for this symbol — treat as unknown, not as HOLD. top-level action_gate can be null even when covered=true — this is not a missing field, it means the current bar has no fresh trigger reading; check gate_null_reason ('no_gate_available' = neither the current bar nor the carried-forward signal had a gate at all, vs 'signal_stale' = a value existed but the underlying signal exceeded the staleness threshold and was deliberately suppressed rather than served as a confident-but-old answer). The order decision and responsibility remain with the calling agent/user. Every check is persisted to an auditable decision ledger (check_id). signal.object_context (W1-C1 standard object block, present when a recent trigger bar exists): my_anchor/opp_anchor(reversal destination)/judgment_ref/geometry/why(action_gate+trigger_kind only, reason codes scrubbed)/reverse_branch context (object_context.reverse_direction_conflict is present only when a local reversal shows stage='confirmed' but the swing's confirmed direction still disagrees — read it before treating reverse_branch.stage='confirmed' as a swing-level reversal) — null when there is no active signal or no trigger bar.
Eingabe-Schema
{
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "e.g. BTCUSDT, SILVER, 테슬라 — aliases resolve to the engine symbol (XYZ_SILVERUSD, XYZ_TSLAUSD, …)."
},
"side": {
"type": "string",
"enum": [
"buy",
"long",
"sell",
"short"
],
"description": "Proposed order direction (buy/long = +, sell/short = -)."
},
"order_type": {
"type": "string",
"description": "Optional, informational (market/limit/…) — recorded in the ledger, does not change the state verdict."
},
"timeframe": {
"type": "string",
"enum": [
"30m",
"1h",
"4h",
"8h",
"1d"
],
"description": "Gate horizon. Omit = your open position's entry TF if you hold one on this symbol, else decker.get_assembly's entry TF (the single judgment authority's current best-path TF), else the engine's default action TF (4h)."
}
},
"required": [
"symbol",
"side"
]
}🟢decker.get_positions
Axis③ (Order/Execution) — this user's actual exposure: real open futures positions (execution_mode=real, with live sl_price/tp_price), virtual (paper) open positions, and the last 10 closed round-trips per mode. This is what your money actually did, distinct from decker.get_signals (axis②, what the engine recommends) — use this before deciding whether to place another order (avoid duplicate/over-exposure) and to check current protective stop/target on a real position.
Eingabe-Schema
{
"type": "object",
"properties": {}
}🟢decker.place_order(symbol, side, notional_usd)
Axis③ (Order/Execution) — unlike every other tool here, this one moves money. It places a market order through DECKER'S OWN execution engine (same path as the decker-ai.com chat trading UI, source='mcp') — it does NOT hand off to your own broker connection or exchange account; Decker executes using whatever exchange credentials this user has separately linked to their Decker account on the website. execution_mode (virtual|real) is NOT chosen by the caller — it is resolved server-side from this user's account settings (user_settings.execution_mode) AND the platform's real-trading kill switch; a real-money order requires both an explicit user opt-in AND role/tier eligibility (PRO/ENTERPRISE or admin) AND passing the tier's hard notional/leverage/daily-count caps (checked here before dispatch — violation blocks the order, does not downgrade it to virtual). The response always states which mode actually executed — treat 'virtual' in the response as authoritative even if you expected real. Restricted to the crypto-6 universe (BTCUSDT/ETHUSDT/SOLUSDT/BNBUSDT/XRPUSDT/DOGEUSDT) for this MCP path — HL-synthetic and KRX symbols are read-only via other tools. Call decker.validate_intent first to read the engine's current stance; this tool does not check it for you. Positions are tracked as ONE net row per user+symbol+mode, not per order — if you already hold a position on this symbol, this order nets into it and the response's pre_existing_position field says so. A later close_position call closes the combined total, not just what this call added.
Eingabe-Schema
{
"type": "object",
"properties": {
"symbol": {
"type": "string",
"enum": [
"BTCUSDT",
"ETHUSDT",
"SOLUSDT",
"BNBUSDT",
"XRPUSDT",
"DOGEUSDT"
],
"description": "Crypto-6 only for this MCP write path."
},
"side": {
"type": "string",
"enum": [
"buy",
"long",
"sell",
"short"
],
"description": "Order direction (buy/long or sell/short)."
},
"notional_usd": {
"type": "number",
"exclusiveMinimum": 0,
"description": "Order size in USD (quantity = notional_usd / current price). This is the value checked against the account's tier notional cap."
}
},
"required": [
"symbol",
"side",
"notional_usd"
]
}⚪decker.close_position(symbol, close_fraction)
Axis③ (Order/Execution) — closes (or partially reduces) an existing position through DECKER'S OWN execution engine (see decker.place_order for what that means — same account-linkage requirement applies here for real positions). Unlike place_order, there is no crypto-6 restriction — this reduces risk, not adds it, so any symbol you actually hold (including HL-synthetic/KRX paper positions) can be closed. Mode is NOT chosen by the caller — this looks up whatever position(s) actually exist for the symbol (real via live exchange query, virtual via the paper ledger) and closes whichever are open; if both a real and a virtual position exist for the same symbol, both are closed and the response reports execution_mode as 'mixed'. No open position for the symbol = a clean not-found response, not an error — safe to call speculatively.
Eingabe-Schema
{
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "e.g. BTCUSDT, XYZ_GOLDUSD — whatever symbol you hold. Aliases resolve like other tools."
},
"close_fraction": {
"type": "number",
"exclusiveMinimum": 0,
"maximum": 1,
"default": 1,
"description": "Fraction of the current position to close, 0 < x <= 1. Default 1.0 = full close. E.g. 0.5 closes half."
}
},
"required": [
"symbol"
]
}🔴decker.update_protective_stops(symbol, sl_price, tp_price, mode)
Axis③ (Order/Execution) — modifies the stop-loss and/or take-profit on an EXISTING open position. There is no cancel_order tool because Decker only places market orders (there is no resting order to cancel) — the actual gap this fills is modifying protective stops on a position you already hold. real: cancels the old exchange stop/take-profit order(s) and places new ones at the given price(s) (new order placed first, old one canceled only after — no unprotected window). virtual: updates the paper position's stop_loss/take_profit columns directly (polled by the paper monitor). Provide at least one of sl_price/tp_price — the other side, if omitted, is left at its current value. If both a real and a virtual position are open for this symbol, pass mode explicitly or the call is rejected asking which one.
Eingabe-Schema
{
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "e.g. BTCUSDT — must be a symbol you currently hold."
},
"sl_price": {
"type": "number",
"exclusiveMinimum": 0,
"description": "New stop-loss price. Omit to leave the current stop unchanged."
},
"tp_price": {
"type": "number",
"exclusiveMinimum": 0,
"description": "New take-profit price. Omit to leave the current target unchanged."
},
"mode": {
"type": "string",
"enum": [
"real",
"virtual"
],
"description": "Only required when both a real and a virtual position are open for this symbol — says which one to modify."
}
},
"required": [
"symbol"
]
}Community
Nachweis