Skip to main content
Glama
abuzo

@alexbuzo/dzengi-mcp

by abuzo
README.md
# @alexbuzo/dzengi-mcp

Safe, local Model Context Protocol (MCP) access to Dzengi market, account,
order, and position data. Trading tools are separate, explicitly guarded
mutations; the server is read-only until its policy gates are enabled.

> **Financial-risk warning:** trading digital assets and leveraged products can
> lose money quickly, including more than the amount initially committed.
> This package is infrastructure, not investment advice or a trading strategy.
> Review every order, account, symbol, quantity, price, leverage, and stop
> value yourself. Start with demo and read-only API keys. Never give an agent
> more permission than you can afford to use.

## 1. Scope and safety boundary

The package runs a Node.js 20+ stdio MCP server against the official Dzengi
REST adapter. It exposes curated typed tools, not an arbitrary HTTP proxy.
Public market reads work without credentials; signed account reads and every
mutation require credentials at call time. `dzengi_list_instruments` reads the
public `exchangeInfo` catalog without credentials, but automatically uses the
account-scoped catalog when both `DZENGI_API_KEY` and `DZENGI_API_SECRET` are
configured. Supplying only one credential keeps this read fully public and
never sends a partial credential pair.

The server does not implement withdrawals, deposits, transfers, funding, or
account-management operations. It cannot move funds. An account response may
contain broker metadata such as `canWithdraw` or `canDeposit`, but those flags
do not add a funding tool to this server. It also does not run a trading
strategy, store credentials remotely, or maintain WebSocket subscriptions.

Stdout is reserved for MCP protocol frames. Startup and audit diagnostics go
to stderr, and secrets, signatures, authorization headers, and complete signed
URLs are redacted. Successful tool results are recursively sanitized and
bounded to 1 MiB of UTF-8 JSON; an oversized result is returned as a safe
validation error instead of a partial response.

Broker HTTP response bodies are separately bounded to 2 MiB of decompressed
bytes before JSON parsing. An oversized or malformed read is returned as a
safe HTTP error; a dispatched mutation is reported as having an unknown
outcome and is never retried.

The transport rejects redirects (`redirect: "error"`) for every broker
request, so an API key or signed query cannot be forwarded to another origin.
A read redirect is a safe HTTP failure; a redirect rejection after mutation
dispatch is an unknown outcome that requires reconciliation. Swagger's cancel
endpoints may return `204 No Content`, which is accepted as an empty success
result; other empty `2xx` responses remain malformed.

## 2. Install from npm or source

The npm package name is `@alexbuzo/dzengi-mcp` and its executable is
`dzengi-mcp`. Run the package from an environment that supplies configuration
through environment variables:

```bash
npx -y @alexbuzo/dzengi-mcp@0.1.0
```

Run this published-package command outside the source checkout. Inside a
checkout with the same package name and version, npm can select the local
package without installing its executable, producing `dzengi-mcp: command
not found`. Set the MCP launcher's working directory to a neutral directory,
or use the source-checkout commands below. After changing source code, rebuild
and launch `node /absolute/path/to/dzengi-mcp/dist/index.js` to use those changes;
an `npx` command pinned to a published version still runs that published version.

For a source checkout:

```bash
git clone https://github.com/abuzo/DzengiMcp.git dzengi-mcp
cd dzengi-mcp
npm ci
cp .env.example .env
npm run build
npm start
```

`.env` is for local development only and is ignored by Git. Do not commit it,
paste credentials into this README, or put secrets in a Codex TOML file.

The default environment is the official demo adapter at
`https://demo-api-adapter.dzengi.com` with API v1. Live uses
`https://api-adapter.dzengi.com`; demo API v2 is rejected by configuration.

## 3. Create a restricted Dzengi API key

Follow Dzengi's [API Get Started guide](https://dzengi.com/api-get-started):
sign in, open **Settings > API integrations > Generate new key**, enable 2FA,
set permissions, bind an IP address, and set an expiration date.

Use separate keys for demo and live. Begin with the smallest read-only
permissions needed for market/account inspection. Add trade permission only
after the demo workflow is understood. Disable withdrawal, deposit, transfer,
or other funding permissions if the Dzengi account UI offers them; this server
does not need them. Bind the key to the narrowest stable egress IP, enable 2FA
on the account, set a short expiration, and record the expiry owner and date.
Keep the API secret in an environment manager or OS keychain, never in source,
shell history, logs, screenshots, tool arguments, or a Codex configuration
value. Rotate and revoke keys on the schedule in section 10.

## 4. Start with demo, read-only

The safe baseline is:

```dotenv
DZENGI_ENV=demo
DZENGI_API_VERSION=1
DZENGI_ALLOW_TRADE=false
DZENGI_ALLOW_LIVE_TRADING=false
DZENGI_REQUIRE_CONFIRMATION=true
DZENGI_MAX_LEVERAGE=1
```

Credentials are not needed for public reads. After building from source, check
the executable and protocol boundary without contacting a trading endpoint:

```bash
npm run build
npm run verify:stdio
```

Use `dzengi_get_runtime_status`, `dzengi_get_server_time`,
`dzengi_list_instruments`, and `dzengi_get_ticker` first. Signed account reads
will return `AUTH_REQUIRED` until both credential variables are supplied. With
the baseline gates, all six mutation tools remain denied even if a client asks
for `confirm: true`.

## 5. Configure Codex without embedding values

Codex forwards the names below from the environment in which it starts the
server. The TOML contains names, not API keys or secrets:

```toml
[mcp_servers.dzengi]
command = "npx"
args = ["-y", "@alexbuzo/dzengi-mcp@0.1.0"]
env_vars = [
  "DZENGI_ENV",
  "DZENGI_API_KEY",
  "DZENGI_API_SECRET",
  "DZENGI_ALLOW_TRADE",
  "DZENGI_ALLOW_LIVE_TRADING",
  "DZENGI_MAX_ORDER_NOTIONAL",
  "DZENGI_MAX_LEVERAGE",
  "DZENGI_ALLOWED_SYMBOLS"
]
default_tools_approval_mode = "writes"
```

This follows the [Codex MCP configuration guide](https://developers.openai.com/codex/mcp).
Set the forwarded values in the local process environment or your approved
secret manager. Codex approvals are a client-side safety layer; the server's
trade flags, confirmation requirement, allowlist, notional limit, leverage
limit, and live dual gate remain authoritative. A stricter per-tool approval
policy is encouraged for new deployments.

### Configuration reference

All names below are read by `loadConfig`; blank optional values are omitted.

| Variable | Default / accepted values | Purpose |
| --- | --- | --- |
| `DZENGI_ENV` | `demo` or `live` (default `demo`) | Selects the official adapter host. |
| `DZENGI_API_VERSION` | `1` or `2`; defaults to `1` for demo and `2` for live | Demo v2 is rejected. |
| `DZENGI_API_KEY` | blank | Signed-request key; public reads do not need it. |
| `DZENGI_API_SECRET` | blank | HMAC secret; never returned in status or errors. |
| `DZENGI_ALLOW_TRADE` | `false` (strict `true`/`false`) | Master mutation gate. |
| `DZENGI_ALLOW_LIVE_TRADING` | `false` (strict `true`/`false`) | Required in addition to the master gate for live. |
| `DZENGI_REQUIRE_CONFIRMATION` | `true` (strict `true`/`false`) | Requires `confirm: true` on every mutation; live trading enforces `true` at startup. |
| `DZENGI_MAX_ORDER_NOTIONAL` | blank or positive plain decimal | Maximum order notional; mandatory when live trading is enabled. |
| `DZENGI_MAX_LEVERAGE` | `1`, up to `1000` | Maximum requested leverage. |
| `DZENGI_ALLOWED_SYMBOLS` | blank or comma-separated symbols | Optional trimmed, case-sensitive allowlist; copy symbols exactly from `dzengi_list_instruments`, including case and punctuation. |
| `DZENGI_RECV_WINDOW_MS` | `5000`, integer `1..60000` | Signed request timing window. |
| `DZENGI_TIMEOUT_MS` | `10000`, integer `100..120000` | HTTP timeout. |
| `DZENGI_READ_RETRIES` | `2`, integer `0..5` | Bounded retries for transient reads only. |
| `DZENGI_BASE_URL` | blank (derived from `DZENGI_ENV`) | Official host override; custom hosts require the next flag. Signed reads and mutations send the API key and HMAC signature to the configured host. |
| `DZENGI_ALLOW_CUSTOM_BASE_URL` | `false` (strict `true`/`false`) | Explicitly permits a non-official, fully trusted host. Custom non-loopback hosts must use HTTPS. |
| `DZENGI_AUDIT_LOG_PATH` | blank | Optional append-only JSONL mutation audit path; it must resolve to a regular file (stdout/stderr descriptor aliases and special files are rejected), and newly created files use mode `600`. |
| `DZENGI_LOG_LEVEL` | `info`; `debug`, `info`, `warn`, or `error` | Secret-free stderr verbosity. |

`DZENGI_LOG_LEVEL` controls lifecycle information only: `debug` and `info` show
startup information, while `warn` and `error` suppress it. Startup and
shutdown errors always remain on stderr. Mutation audit events are independent
of this filter and continue to be emitted to stderr and the configured audit
file when enabled. Runtime status reports only whether audit logging is enabled;
it never returns the configured local audit path. Its `baseUrl` status is the
configured endpoint origin only; endpoint paths are not returned.

Only set `DZENGI_BASE_URL` to an endpoint you fully trust: signed reads and every
mutation send `X-MBX-APIKEY` and a query HMAC `signature` to that host. Keep the
default official host unless a trusted test or gateway endpoint is required.

Changing any environment value, especially either trade flag, takes effect
only after the MCP process is restarted because configuration is loaded once.

## 6. Tool catalog

There are exactly 22 curated tools. Read tools have read-only MCP annotations;
mutations have destructive/write annotations and always require a caller-owned
`clientRequestId` plus a boolean `confirm` field.

### Read-only market and runtime tools

| Tool | What it does |
| --- | --- |
| `dzengi_get_runtime_status` | Reports environment, API version, configured endpoint origin, gates, limits, credential-presence booleans, and the audit-enabled flag; it never exposes endpoint paths or the local audit path. |
| `dzengi_get_server_time` | Reads server time and refreshes the local clock offset. |
| `dzengi_list_instruments` | Reads account-scoped `exchangeInfo` when both credentials are configured, otherwise public `exchangeInfo`, with bounded local pagination (`offset`, `limit`). |
| `dzengi_get_ticker` | Reads an optional-symbol 24-hour ticker. |
| `dzengi_get_order_book` | Reads bounded depth for a required `symbol` and optional `limit`. |
| `dzengi_get_candles` | Reads bounded candles for `symbol`, `interval`, and optional time/price filters. |
| `dzengi_get_trading_fees` | Reads optional-symbol fee information. |
| `dzengi_get_trading_limits` | Reads optional-symbol broker limits. |
| `dzengi_get_leverage_settings` | Reads signed leverage settings for an exact `symbol` whose `marketType` is `LEVERAGE`. A rejected request for a known `SPOT` instrument returns a descriptive validation error; symbols are never converted. |

### Read-only account and lifecycle tools

| Tool | What it does |
| --- | --- |
| `dzengi_get_account` | Reads signed account permissions and balances; optional `showZeroBalance`. |
| `dzengi_list_open_orders` | Reads open orders, optionally filtered by `symbol`. |
| `dzengi_get_order` | Reads a signed order by required `symbol` and `orderId`. |
| `dzengi_list_positions` | Reads current leverage positions. |
| `dzengi_list_trades` | Reads bounded signed trades for required `symbol` and optional time/limit filters. |
| `dzengi_list_position_history` | Reads bounded position history with optional `symbol`, `from`, `to`, and `limit`. |
| `dzengi_preflight_order` | Validates a proposed order against current metadata and policy without placing it. |

### Guarded mutation tools

| Tool | Financial operation and additional fields |
| --- | --- |
| `dzengi_place_order` | Places a `MARKET`, `LIMIT`, or `STOP` order. Required: `symbol`, `type`, `side`, `quantity`; optional: `price`, `accountId`, `leverage`, `expireTimestamp`, `newOrderRespType`, `stopLoss`, `takeProfit`, `stopDistance`, `profitDistance`, `trailingStopLoss`, `guaranteedStopLoss`. |
| `dzengi_cancel_order` | Cancels by required `symbol` and `orderId`; it never assumes `USD`. |
| `dzengi_edit_order` | Edits an exchange order by required safety-only `symbol` and `orderId`; provide `price` and/or `expireTimestamp`. |
| `dzengi_update_order` | Updates a leverage order by required safety-only `symbol` and `orderId`; provide at least one of `newPrice`, `expireTimestamp`, `stopLoss`, `takeProfit`, `stopDistance`, `profitDistance`, `trailingStopLoss`, or `guaranteedStopLoss`. |
| `dzengi_close_position` | Closes a leverage position by required safety-only `symbol` and `positionId`. |
| `dzengi_update_position` | Updates position protection by required safety-only `symbol` and `positionId`; provide at least one stop/protection field. |

Every mutation is sent at most once by the transport. An ID must never be
reused: while an entry remains in the bounded in-memory cache (up to 24 hours
and 1,024 completed entries), an identical request replays and a different
financial payload is rejected. Restart, TTL expiry, or capacity eviction
removes that local protection, so callers must reconcile before any new
request.

Lifecycle mutations use `symbol` for allowlist and signed ownership checks, then
omit it from the broker mutation payload. The signed order lookup is already
scoped by the exact `{symbol, orderId}` query, so a single matching order record
may omit `symbol`; explicit mismatches and ambiguous records still fail closed.
Position records must include the exact symbol. Order edits with a replacement
price also re-check the associated quantity against the configured notional cap.
Use the exact canonical symbol, including case and punctuation, returned by
`dzengi_list_instruments` for all symbol-bearing tools.

## 7. Enable demo mutations deliberately

Only do this with a demo account after the read-only checks pass. Replace every
`REPLACE_WITH_...` value; these are intentionally fake placeholders, not
credentials or live symbols:

```bash
export DZENGI_ENV=demo
export DZENGI_API_VERSION=1
export DZENGI_API_KEY=REPLACE_WITH_DEMO_API_KEY
export DZENGI_API_SECRET=REPLACE_WITH_DEMO_API_SECRET
export DZENGI_ALLOW_TRADE=true
export DZENGI_ALLOW_LIVE_TRADING=false
export DZENGI_REQUIRE_CONFIRMATION=true
export DZENGI_MAX_ORDER_NOTIONAL=10
export DZENGI_MAX_LEVERAGE=1
export DZENGI_ALLOWED_SYMBOLS=REPLACE_WITH_DEMO_SYMBOL
npm run build
npm start
```

The server still requires `confirm: true` on each mutation and a new
`clientRequestId`. Keep the notional and allowlist as small as practical. A
demo key should have no funding permission and should be bound and expired like
a live key.

## 8. Enable live mutations only with all gates

Live trading requires every item below at startup:

1. `DZENGI_ENV=live` and a live API key/secret;
2. `DZENGI_ALLOW_TRADE=true`;
3. `DZENGI_ALLOW_LIVE_TRADING=true`;
4. a positive `DZENGI_MAX_ORDER_NOTIONAL`;
5. a deliberate `DZENGI_MAX_LEVERAGE` and, preferably, a narrow
   `DZENGI_ALLOWED_SYMBOLS` list;
6. `DZENGI_REQUIRE_CONFIRMATION=true` (enforced at startup) and `confirm: true`
   per mutation; and
7. Codex write approval enabled for the client session.

Example shape, with deliberately fake credential placeholders:

```bash
export DZENGI_ENV=live
export DZENGI_API_VERSION=2
export DZENGI_API_KEY=REPLACE_WITH_LIVE_API_KEY
export DZENGI_API_SECRET=REPLACE_WITH_LIVE_API_SECRET
export DZENGI_ALLOW_TRADE=true
export DZENGI_ALLOW_LIVE_TRADING=true
export DZENGI_REQUIRE_CONFIRMATION=true
export DZENGI_MAX_ORDER_NOTIONAL=10
export DZENGI_MAX_LEVERAGE=1
export DZENGI_ALLOWED_SYMBOLS=REPLACE_WITH_LIVE_SYMBOL
npm run build
npm start
```

The example limit is not a recommendation; choose a limit appropriate to the
account and risk policy. Configuration rejects live trading without
`DZENGI_MAX_ORDER_NOTIONAL`. Restart after every gate or credential change,
then inspect `dzengi_get_runtime_status` before considering a write.

`DZENGI_MAX_ORDER_NOTIONAL` is measured in quote currency as quantity × limit or
stop price (or the current market reference price for a market order). It is a
pre-dispatch cap, not a guarantee against execution price or slippage.

## 9. Preflight, place, and reconcile

Dzengi's native `exchangeInfo` reports the price increment in top-level
`tickSize` and may omit `minPrice`/`maxPrice` entirely. Preflight checks this
increment without treating absent optional price bounds as an API error.
Declared but incomplete price filters and malformed explicit bounds still
produce warnings. Quantity filters, broker minimum notional, configured caps,
and confirmation requirements continue to apply independently.

Use an obviously fake symbol in documentation examples and replace it only
with a symbol returned by `dzengi_list_instruments`:

```json
{
  "tool": "dzengi_preflight_order",
  "arguments": {
    "symbol": "REPLACE_WITH_DEMO_SYMBOL",
    "type": "LIMIT",
    "side": "BUY",
    "quantity": "0.01",
    "price": "1.00",
    "confirm": true
  }
}
```

Placement must consume a fresh report with `allowed: true`. The mutation adds
the explicit confirmation and a new request ID; it is not a shell command and
must be issued through the MCP client:

```json
{
  "tool": "dzengi_place_order",
  "arguments": {
    "clientRequestId": "REPLACE_WITH_NEW_UUID",
    "confirm": true,
    "symbol": "REPLACE_WITH_DEMO_SYMBOL",
    "type": "LIMIT",
    "side": "BUY",
    "quantity": "0.01",
    "price": "1.00"
  }
}
```

An order mutation can cross the broker boundary before a timeout, network
failure, malformed response, or HTTP 5xx is observed. The server then returns
`MUTATION_OUTCOME_UNKNOWN` with reconciliation guidance. Do **not** retry the
mutation. Inspect, in order as applicable:

- `dzengi_list_open_orders` for the symbol;
- `dzengi_get_order` with the known `symbol` and `orderId`;
- `dzengi_list_trades` for fills; and
- `dzengi_list_positions` for position state.

On the same running process, repeating the identical `clientRequestId` returns
the cached unknown result without dispatching again. A different financial
payload under that ID is rejected. The local guard is memory-only: it does not
survive a process restart and is not a broker idempotency guarantee. Never
reuse a mutation ID after restart; reconcile broker state first and choose a
new ID only for a deliberately new action.

## 10. Emergency disablement and credential rotation

The emergency kill switch is to set **both** trade gates false and restart the
process:

```bash
export DZENGI_ALLOW_TRADE=false
export DZENGI_ALLOW_LIVE_TRADING=false
npm start
```

Stop the existing process first (`Ctrl-C` for a foreground process). Changing
the variables without restarting does not change the active policy. Verify
`dzengi_get_runtime_status` shows both gates disabled. If a key may have been
exposed, revoke it in Dzengi immediately; do not rely on the process restart
alone.

For rotation, generate a new key with the same least-privilege permissions,
IP binding, 2FA, and expiry policy; update the external secret store or local
environment; restart; run a public read and (if appropriate) a signed read;
then revoke the old key. Never print either value while checking the change.

### Audit file operations

`DZENGI_AUDIT_LOG_PATH` is optional. When set, the server appends one
secret-free JSONL start/terminal pair per mutation attempt; it does not persist
ordinary read responses or unrestricted broker payloads. Treat the file as
sensitive operational data even though credentials and signatures are redacted.
Create an owner-only directory and file before starting the server:

```bash
umask 077
install -d -m 700 /var/lib/dzengi-mcp/audit
touch /var/lib/dzengi-mcp/audit/mutations.jsonl
chmod 600 /var/lib/dzengi-mcp/audit/mutations.jsonl
export DZENGI_AUDIT_LOG_PATH=/var/lib/dzengi-mcp/audit/mutations.jsonl
```

The writer is append-only at the application level. The configured path is
read once at startup, while each event opens the configured path for an append;
the process does not automatically follow a renamed rotation target. To rotate
safely, stop the server (and let any in-flight write finish), move the old file
to an owner-only archive, create a new `600` file, update
`DZENGI_AUDIT_LOG_PATH`, and restart. Verify the new process's runtime status
and that a deliberately chosen test mutation/readiness check writes to the new
path; never use a live trade as a logging test. Set an operator-owned retention
period, protect backups, and use the organization's approved secure-deletion
procedure when records expire. Audit files are local state and must never be
committed, included in an npm tarball, or shipped to a support ticket without
redaction.

### Rollback to a known-good release

Select a previously verified package version and pin it instead of relying on
`latest`. For example, the Codex entry can temporarily use an owner-approved
version tag:

```toml
[mcp_servers.dzengi]
command = "npx"
args = ["-y", "@alexbuzo/dzengi-mcp@0.1.0"]
```

Stop the existing MCP process or supervisor unit, restore the known-good
environment file and safety gates (start with both trade gates `false`), and
restart the pinned version. Verify `dzengi_get_runtime_status`, then a public
read such as `dzengi_get_server_time`; perform `dzengi_get_account` only when a
signed read is appropriate and credentials have been checked independently.
Do not use a mutation to validate a rollback. If compromise is possible,
revoke the affected key, issue a replacement with the same least-privilege/IP/
2FA/expiry policy, update the secret store, and restart again. npm publication
and version promotion remain manual owner actions.

## 11. Errors and unknown outcomes

MCP failures are structured and set `isError: true`; the text and structured
representations contain the same safe error projection. The stable codes are:

| Code | Meaning |
| --- | --- |
| `CONFIG_ERROR` | Invalid environment, unsupported API version, unsafe host, or missing live limit. |
| `VALIDATION_ERROR` | Tool input, precision, required-field, account-selection, or preflight validation failed. |
| `POLICY_DENIED` | Trade gate, live gate, confirmation, symbol allowlist, notional, or leverage policy denied the mutation. |
| `AUTH_REQUIRED` | A signed read or mutation was requested without both credentials. |
| `RATE_LIMITED` | Broker or local pacing rejected the request; read retries remain bounded. |
| `DZENGI_HTTP_ERROR` | A non-success HTTP response or transport failure was classified as an HTTP error. |
| `DZENGI_API_ERROR` | Dzengi returned a non-success API envelope or malformed success payload. |
| `MUTATION_OUTCOME_UNKNOWN` | A dispatched mutation may have succeeded; reconcile before any new action. |

Only idempotent reads retry bounded transient statuses (`408`, `429`, `500`,
`502`, `503`, `504`). Writes are never automatically retried, including after
timestamp, timeout, network, malformed-response, or 5xx failures. The shared
limiter stays below Dzengi's documented 10 requests/second limit and applies a
separate margin for `openOrders`.

## 12. Development, tests, and owner release commands

Requirements: Node.js 20 or newer and npm. The offline development gate is:

```bash
npm ci
npm test
npm run typecheck
npm run lint
npm run build
npm run verify:stdio
npm run verify:pack
```

`npm run verify` runs the test, type, lint, build, stdio, and package gates in
one command. `npm run dev` runs the TypeScript entry point for local work;
`npm run clean` removes `dist`. `npm run update:openapi` refreshes the checked-
in official Swagger snapshot and `npm run check:openapi` checks for drift; both
are maintainer commands that need network access and their source snapshots are
not shipped in the npm payload. `npm run format` formats the repository.

Before an owner release, inspect the dry-run package and then use the existing
owner npm commands:

```bash
npm pack --dry-run
npm publish --access public
```

This repository's Task 11 verification does **not** publish. The package's
`prepack` build and `prepublishOnly` test/type/lint/build hooks provide an
additional release guard; `npm run verify:pack` invokes dry-run packing with
`--ignore-scripts` so the verifier cannot recursively invoke those hooks.

## 13. Official documentation

- [Dzengi API landing page](https://dzengi.com/api)
- [Dzengi Swagger UI](https://apitradedoc.dzengi.com/swagger-ui.html)
- [Dzengi public Swagger JSON](https://apitradedoc.dzengi.com/v2/api-docs?group=public-api)
- [Dzengi General REST API Information](https://dzengi.com/general-rest-api-information)
- [Dzengi API Get Started](https://dzengi.com/api-get-started)
- [Dzengi API Changelog](https://dzengi.com/api-changelog)
- [OpenAI Codex MCP configuration](https://developers.openai.com/codex/mcp)

When broker behavior and this README differ, verify the official Dzengi
documentation and the checked-in Swagger snapshot before changing a limit or
endpoint. The package intentionally favors a fail-closed result over guessing.

TDQS

A3.7/5.0

Scored across 22 tools

Disambiguation4/5

Most tools are clearly separated by resource and action (e.g., get_order vs list_open_orders vs place_order). The only potential confusion is between dzengi_edit_order and dzengi_update_order, which both target orders but have different meanings (exchange order edit vs leverage-order protection update), and between dzengi_close_position and dzengi_update_position, which are distinct but could be misread.

Naming Consistency5/5

All tools follow a consistent dzengi_<verb>_<noun> pattern with clear verbs like list, get, place, cancel, edit, update, close. The naming convention is uniform and predictable across the entire set.

Tool Count4/5

22 tools is on the higher end but appropriate for a trading exchange server covering public market data, account data, order lifecycle, and position management. It is slightly heavy but each tool maps to a distinct exchange operation.

Completeness4/5

The surface covers the core trading lifecycle: market data, account info, order placement/cancellation/editing, position management, and preflight validation. Minor gaps include no explicit deposit/withdrawal or historical order archive, but the main workflows are complete.

Maintenance

ActivityMaintained
ResponsivenessNo issues