marzban-mcp
This server is an MCP bridge to a Marzban VPN panel, letting AI agents manage users, subscriptions, nodes, and core Xray configuration through 21 tools and 3 prompts.
User management: create, get, list, update, activate, deactivate, put on hold, extend subscriptions, and view traffic usage for individual users
Subscriptions: inspect subscription status/usage/expiry via subscription token, and get user details including masked subscription URLs/links by default
Config & hosts: read Xray core config as a summary, a specific section, or raw JSON; list proxy hosts and flag unknown
{VARIABLE}template tokensNodes & system: list connected nodes with status, Xray version, and bandwidth usage over a period; get panel-wide system stats (CPU, memory, user counts, bandwidth, core status)
Inbounds: list configured inbound proxies grouped by protocol with tag, network, TLS, and port
Safety/automation features: profile-gated tools, confirmation flow for destructive actions, env-only credentials, and ready-made investigation prompts (
expiring_users_audit,node_diagnostics,traffic_report)
marzban-mcp
An MCP server that lets AI agents manage a Marzban panel — built on marzban-sdk.
Users, subscriptions, nodes, and the core config — through Claude, Cursor, or any MCP-compatible client.
Documentation · Client Setup · Tools
Point an AI agent at your panel and it can actually run it — not just read about it. No custom integration code, just an entry in your MCP config.
Install
npm install -g marzban-mcpYou don't usually need to install it yourself — your MCP client runs it via npx (see below). Prefer a container? A multi-arch image is published at ilmar7786/marzban-mcp:
docker pull ilmar7786/marzban-mcpRelated MCP server: io.github.antonio-mello-ai/mcp-pfsense
Quick start
Add it to your client's MCP config with your panel's URL and an admin login. Every client reads roughly the same shape:
{
"mcpServers": {
"marzban": {
"command": "npx",
"args": ["-y", "marzban-mcp"],
"env": {
"MARZBAN_BASE_URL": "https://panel.example.com",
"MARZBAN_USERNAME": "admin",
"MARZBAN_PASSWORD": "secret"
}
}
}
}Claude Desktop, Claude Code, Cursor and other MCP clients all read the same
mcpServers block — just from a different config file. Restart the client
and the tools below become available.
Features
🔒 Env-only credentials — the panel URL, username and password are never accepted as a tool argument, so a compromised or confused model can't redirect the server elsewhere.
🎯 Profile-gated tools — a tool outside the active profile never appears in
tools/listat all, not just hidden behind a hint.✅ Confirmation on every destructive call — the first call only describes the consequences and returns a one-time token; nothing runs until a human-approved second call repeats it, and confirming one call never authorizes a different target or a wider version of the same call.
🔁 A retried destructive call doesn't run twice — an identical repeat within 5 minutes returns the recorded result of the first one instead of restarting the core again; a call whose outcome was never observed says so plainly rather than guessing.
🙈 Credentials masked by default —
proxies,subscription_urlandlinksstay hidden unless you explicitly opt in.🧭 21 tools, 3 prompts — full user lifecycle, config, hosts, nodes, system stats and subscriptions, plus ready-made investigations that chain several tools together.
🛠️ Built on
marzban-sdk— the same auth, retry and reconnect behavior as the SDK itself, just exposed as MCP tools.
Configuration
Variable | Required | Description |
| Yes | Your panel's URL, e.g. |
| Yes | Admin username |
| Yes | Admin password — also used to silently re-authenticate on expiry |
Everything else — profile, output format, verbosity, tool allow/deny filters, log level, link masking — is optional and documented in Configuration.
Tools
21 tools, namespaced marzban_<area>_<action>: Users (11) · Config (5)
· System & nodes (3) · Subscription (2). Three prompts —
expiring_users_audit, node_diagnostics, traffic_report — chain those
tools into ready-made investigations. Full list at
Tools &
Prompts.
Safety model
A profile isn't a hint — a tool outside it never appears in tools/list, so a
model can't call what it can't see. readonly exposes only lists and
lookups; standard (default) adds full user CRUD, renewals and status
changes; full adds destructive tools — delete, reset traffic, rewrite
config, restart the core.
Destructive tools also gate on confirmation: the first call never runs
anything — it describes exactly what would happen and returns a one-time
token. Only a second call, with that token attached, executes. MARZBAN_MCP_CONFIRM
controls how often this is required: auto (default, once per tool and
exact arguments, for 5 minutes — a different target or a wider call always
needs its own confirmation), always (every call), or off (unattended
environments only — no safety net once set).
Confirmation decides whether a call may run; it doesn't decide whether it has already run. So each destructive call is also remembered for 5 minutes: an identical repeat — the kind a client sends after a timeout — returns the recorded result of the first one, with a note saying so, and never reaches the panel. When a request went out and no answer came back, the outcome is reported as unknown, with instructions to check the state with a read-only tool rather than retry. A fresh confirmation still runs the operation for real, and restarting the server clears the memory.
Documentation
Full setup guides and the complete tool/prompt reference live at ilmar7786.github.io/marzban-sdk:
Contributing
This package lives in the marzban-sdk
monorepo — see the root CONTRIBUTING.md
for how to submit a patch. Running the server locally in watch mode, poking
it with the MCP Inspector, or wiring a client to your own build? See
ARCHITECTURE.md § Local development & manual testing.
Found a bug or have an idea?
Open an issue.
License
Available Tools
15 toolsmarzban_config_getGet core configARead-only
Reads the Xray core configuration. Defaults to a structural summary (inbound/outbound tags, ports, protocols, routing rule count) — the full config can be tens of KB and this is usually all that's needed. Pass section (e.g. "inbounds") for one key's raw JSON, or section: "raw" for the entire config.
| Name | Required | Description | Default |
|---|---|---|---|
| section | No | Return this one top-level key's raw JSON instead of the summary (e.g. "inbounds", "routing"). Use "raw" for the entire config. Omit for a structural summary — prefer that over "raw" unless you specifically need the full JSON. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | |
| mode | Yes | |
| section | Yes | |
| summary | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds meaningful context beyond the annotations: the default response is a truncated structural summary due to the config's large size, and section/raw override that behavior. This goes beyond the schema's basic parameter semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences: default behavior, parameter option, and raw caveat. Front-loaded with the core purpose and immediately guides the agent to the best default call. Every sentence carries operational value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, optional-parameter tool with 100% schema coverage and an output schema, the description covers the default behavior, the override options, and the rationale. An agent can call this correctly without further documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already documents the section values including 'raw' and omission behavior. The description adds practical selection guidance (prefer summary over raw unless full JSON needed) and clarifies output scale, which enhances the schema without repeating it verbatim.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Reads) and resource (Xray core configuration), and distinguishes the default structural summary from full raw output. This clearly differentiates it from sibling tools that target hosts, nodes, subscriptions, inbounds, or users.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises when to omit the parameter vs pass a section, and explicitly cautions against using "raw" unless full JSON is truly needed. The schema description echoes this guidance, reinforcing the decision rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_hosts_getGet proxy hostsARead-only
Lists proxy host settings grouped by inbound tag. Flags host fields (remark/address/host/sni/path) that reference an unknown {VARIABLE} template token — almost always a typo, since Marzban leaves unknown tokens un-substituted rather than erroring.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| hosts | Yes | |
| warnings | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the operation as read-only and non-destructive. The description goes beyond this by explaining the grouping behavior and, importantly, that unknown template tokens are flagged rather than causing an error because Marzban leaves them un-substituted. This gives an agent useful insight into output semantics that annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences carry all the essential information without redundancy. The core listing behavior is front-loaded, and the secondary token-flagging behavior is added in a compact, useful second sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with an output schema available, the description is complete. It explains what is returned, how results are grouped, and what the notable edge-case behavior is. There are no outstanding gaps an agent would need filled to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and the schema coverage is 100%, so there are no parameter semantics to document. The baseline of 4 applies here: the description appropriately focuses on the returned data and behavior rather than inventing parameter guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Lists'), a concrete resource ('proxy host settings'), and a distinguishing organizing principle ('grouped by inbound tag'). It also adds a second specific behavior (flagging unknown `{VARIABLE}` tokens) that makes the tool's purpose unmistakable and separates it from generic config or inbound tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the tool's purpose clear, so an agent can infer it is the right choice for inspecting proxy host settings. However, it does not explicitly state when not to use it or which sibling tools should be preferred for related concerns such as general config, inbound management, or node status.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_nodes_listList nodesARead-only
Lists all connected nodes with their status and Xray version, plus bandwidth usage (uplink/downlink) over the given period. start/end (ISO datetimes) narrow the usage window; omit both for all-time.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ISO datetime. Omit for no upper bound. | |
| start | No | ISO datetime. Omit for no lower bound. |
Output Schema
| Name | Required | Description |
|---|---|---|
| nodes | Yes | |
| usage | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context by specifying that it lists only connected nodes, includes status and Xray version, and that bandwidth usage is scoped to the given period, defaulting to all-time when both parameters are omitted.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The main purpose and return contents are front-loaded, and the parameter semantics are stated compactly and clearly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list operation with zero required parameters and an existing output schema, the description covers the essential behavior, parameter semantics, and default period. Nothing critical is missing for an agent to select and invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, and the description goes further by explaining that start/end narrow the bandwidth usage window rather than filtering nodes, and explicitly stating that omitting both parameters gives all-time usage. This adds meaning beyond the schema's generic 'no lower/upper bound' phrasing.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Lists'), names the resource ('all connected nodes'), and enumerates exactly what is returned: status, Xray version, and bandwidth usage over a period. This clearly differentiates it from sibling tools like marzban_system_stats or marzban_hosts_get, which target different resources or aggregates.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear parameter usage guidance ('omit both for all-time') but does not explicitly state when to prefer this tool over sibling tools or mention any exclusions. The use case is implied rather than directly contrasted with alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_subscription_infoGet subscription infoARead-only
Reads subscription status/usage/expiry using the token from a subscription URL (the same public, unauthenticated endpoint client apps use) — for diagnosing a broken subscription link without needing the username. For an admin-side lookup by username, use marzban_users_get instead.
| Name | Required | Description | Default |
|---|---|---|---|
| subscriptionToken | Yes | The opaque token from a user's subscription URL (the path segment after "/sub/") — not an admin/session token. |
Output Schema
| Name | Required | Description |
|---|---|---|
| links | No | |
| expire | No | |
| status | Yes | |
| proxies | Yes | |
| username | Yes | |
| next_plan | No | |
| online_at | No | |
| created_at | Yes | |
| data_limit | No | data_limit can be 0 or greater |
| used_traffic | Yes | |
| sub_updated_at | No | |
| on_hold_timeout | No | |
| subscription_url | No | |
| sub_last_user_agent | No | |
| lifetime_used_traffic | No | |
| on_hold_expire_duration | No | |
| data_limit_reset_strategy | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint and destructiveHint, and the description adds meaningful behavioral context beyond that: it calls 'the same public, unauthenticated endpoint client apps use,' clarifying that no admin authentication is needed. It does not contradict the annotations, and the remaining details about invalid-token behavior are not essential given the output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loads the core purpose and scope, and then immediately provides the routing alternative. Every sentence earns its place with no redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read-only tool with full schema coverage and an output schema, the description is complete: it explains the use case, the required token source, the authentication context, and the alternative admin-side tool. Nothing needed for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description covers 100% of the parameter and already fully explains that subscriptionToken is the opaque token from the subscription URL path segment after '/sub/' and not an admin/session token. The tool description adds little new meaning beyond restating 'using the token from a subscription URL,' so the schema-carried baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it 'Reads subscription status/usage/expiry' using a subscription token. It clearly distinguishes this from admin-side user lookups by stating it works 'without needing the username' and directly names the sibling alternative marzban_users_get.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells when to use the tool: 'for diagnosing a broken subscription link without needing the username.' It also gives a direct alternative and route when that condition does not hold: 'For an admin-side lookup by username, use marzban_users_get instead.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_system_inboundsList inboundsARead-only
Lists configured inbound proxies grouped by protocol, with tag, network, TLS mode, and port for each. For the raw Xray inbound JSON (routing, stream settings, etc.) use marzban_config_get with section: "inbounds" instead.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the read-only safety profile is covered. The description adds scoping detail about what is included (configured inbound proxies, grouped by protocol) and that it is not raw JSON, but does not disclose additional behavioral traits such as response size or potential filtering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The primary purpose and returned fields are upfront, and the alternative tool is mentioned in the second sentence without distracting from the main definition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless read-only list operation with annotations, an output schema, and a clear sibling alternative, the description is fully sufficient. Nothing essential is missing for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the schema has no parameter semantics to document. The description instead clarifies the shape and scope of the returned data, which is useful context and matches the baseline for a parameterless tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the specific verb 'Lists' and a precise resource ('configured inbound proxies'), then details the returned fields (tag, network, TLS mode, port) and grouping by protocol. It also explicitly distinguishes itself from the raw Xray inbound JSON returned by marzban_config_get.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear when-to-use this tool versus the alternative: use this for a structured summary, use marzban_config_get with section 'inbounds' when raw Xray JSON is needed. This explicit routing removes ambiguity for the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_system_statsGet system statsARead-only
Reports panel-wide stats: CPU/memory usage, user counts by status, and bandwidth totals/speeds, plus the Xray core version and whether it is currently running.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| core | Yes | |
| system | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context by stating exactly what the tool reports, including live Xray running state, which goes beyond the basic annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence that front-loads the main purpose and then packs the key reportable items into a compact list. Every phrase adds information without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only stats endpoint with an output schema present, the description is fully sufficient. It tells the agent what category of data to expect, and the annotations cover the operational risk profile.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is no parameter semantics to document. The description correctly does not invent any parameters, and the schema's empty properties are consistent with that.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Reports panel-wide stats', then enumerates the concrete data categories covered (CPU/memory, user counts, bandwidth, Xray core status). This clearly distinguishes it from siblings like marzban_system_inbounds or marzban_users_list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for obtaining an overall panel health/statistics overview, but it does not explicitly state when to prefer it over alternatives or mention any exclusions. There is no direct comparison to sibling tools such as marzban_system_inbounds.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_users_activateActivate userA
Sets a user's status to active.
| Name | Required | Description | Default |
|---|---|---|---|
| username | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| admin | No | |
| links | No | |
| expire | No | |
| status | Yes | |
| proxies | Yes | |
| inbounds | No | |
| username | Yes | |
| next_plan | No | |
| online_at | No | |
| created_at | Yes | |
| data_limit | No | data_limit can be 0 or greater |
| used_traffic | Yes | |
| sub_updated_at | No | |
| on_hold_timeout | No | |
| subscription_url | No | |
| excluded_inbounds | No | |
| auto_delete_in_days | No | |
| sub_last_user_agent | No | |
| lifetime_used_traffic | No | |
| on_hold_expire_duration | No | |
| data_limit_reset_strategy | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is not read-only and not destructive. The description adds that the affected behavior is a status change to active, which is useful contextual detail, but it does not disclose edge cases such as idempotency, prerequisites, or effects on expired or held users.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single tightly-worded sentence with no filler. Every word contributes meaning, and the core action is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple single-parameter status mutation with annotations and an output schema, the description is mostly sufficient. The main gap is the absence of usage-routing context, but the operation itself is described completely enough to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description does not compensate: it never mentions the username parameter or explains that it identifies the target user. The schema's pattern and constraints partially cover meaning, but the description adds no parameter-level semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Sets') and resource ('a user's status') with a clear outcome ('to active'). This unambiguously distinguishes the operation from siblings like marzban_users_deactivate, since the semantic opposite is explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given on when to use this tool versus alternatives such as marzban_users_deactivate, marzban_users_hold, or marzban_users_update. The intended use is only implied by the wording, not stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_users_createCreate userA
Creates a new user. dataLimit accepts a human size ("10GB"), expire a relative duration ("30d") or absolute date — both default to unlimited when omitted. templateId fills dataLimit/inbounds/expire from a user template; any field also given explicitly overrides the template value.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | ||
| expire | No | e.g. "30d". Omit for no expiration. | |
| status | No | Defaults to active. | |
| proxies | No | Protocol name -> settings, e.g. {"vless": {"id": "<uuid>"}} or {"shadowsocks": {}} to auto-generate credentials. Omit to leave unchanged on update. On create there is no server default — omitting this (without templateId) errors; provide at least one protocol with a matching inbound configured on the panel. | |
| inbounds | No | Protocol name -> inbound tags to restrict this user to. Omit for all inbounds. | |
| username | Yes | ||
| dataLimit | No | e.g. "10GB". Omit or 0 for unlimited. | |
| templateId | No | Create from a user template instead of specifying proxies/inbounds by hand. | |
| onHoldExpireDuration | No | Seconds the user may stay on_hold before expiring, counted from their first connection. Only meaningful when status is on_hold. | |
| dataLimitResetStrategy | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| admin | No | |
| links | No | |
| expire | No | |
| status | Yes | |
| proxies | Yes | |
| inbounds | No | |
| username | Yes | |
| next_plan | No | |
| online_at | No | |
| created_at | Yes | |
| data_limit | No | data_limit can be 0 or greater |
| used_traffic | Yes | |
| sub_updated_at | No | |
| on_hold_timeout | No | |
| subscription_url | No | |
| excluded_inbounds | No | |
| auto_delete_in_days | No | |
| sub_last_user_agent | No | |
| lifetime_used_traffic | No | |
| on_hold_expire_duration | No | |
| data_limit_reset_strategy | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations only marking readOnlyHint=false and destructiveHint=false, the description adds meaningful behavioral context: default-unlimited behavior for dataLimit and expire, support for human-readable sizes and relative or absolute durations, and template override semantics. It does not contradict the annotations and goes beyond what the schema states.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no filler. It front-loads the core action, then packs the most important parameter semantics into compact, readable sentences. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (10 parameters, nested objects) and the presence of a rich schema and output schema, the description covers the key cross-cutting behaviors: defaults, value formats, and template override logic. It relies on the schema for per-parameter details like the proxies-on-create requirement, which is acceptable since the schema describes it explicitly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 70%, so the schema handles most parameters, but the description adds value by clarifying formats ('10GB', '30d', absolute date), the unlimited-by-default behavior, and how templateId merges with explicitly provided fields. This meaningfully supplements the schema rather than repeating it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Creates a new user.' It clearly identifies the action, but it does not explicitly differentiate from sibling tools like marzban_users_update or marzban_users_list, so the sibling-distinguishing bar for a 5 is not fully met.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage by saying 'Creates a new user,' and it gives useful context about templateId and explicit override behavior. However, it does not state when to prefer this tool over an alternative, such as using marzban_users_update for existing users, nor does it mention any exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_users_deactivateDeactivate userB
Sets a user's status to disabled, immediately blocking their access without deleting them.
| Name | Required | Description | Default |
|---|---|---|---|
| username | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| admin | No | |
| links | No | |
| expire | No | |
| status | Yes | |
| proxies | Yes | |
| inbounds | No | |
| username | Yes | |
| next_plan | No | |
| online_at | No | |
| created_at | Yes | |
| data_limit | No | data_limit can be 0 or greater |
| used_traffic | Yes | |
| sub_updated_at | No | |
| on_hold_timeout | No | |
| subscription_url | No | |
| excluded_inbounds | No | |
| auto_delete_in_days | No | |
| sub_last_user_agent | No | |
| lifetime_used_traffic | No | |
| on_hold_expire_duration | No | |
| data_limit_reset_strategy | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds that the action is immediate and non-destructive ('without deleting them'), which complements the annotations (readOnlyHint=false, destructiveHint=false). However, it does not mention reversibility, impact on active sessions, or any side effects, leaving some behavioral gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, focused sentence that front-loads the action and adds the key clarifying detail about deletion. No unnecessary words or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with an output schema, the description is mostly adequate but lacks usage guidance and any parameter clarification. The output schema covers return values, so that is not a gap, but the missing usage context prevents a higher score.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description does not reference the 'username' parameter, and the schema provides no description (0% coverage). While the parameter name is self-explanatory, the description fails to compensate for the schema's lack of explanation, such as format or purpose.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Sets a user's status to disabled'), identifies the resource ('user'), and explicitly clarifies it does not delete the user, distinguishing it from deletion-like operations. This also implicitly contrasts with the sibling 'activate' tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives such as 'activate' or 'hold'. It does not mention conditions for disabling a user or suggest re-enabling via the activate tool, leaving the agent to infer usage from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_users_extendExtend user subscriptionA
Renews a user: adds addDuration to their current expiration (or to now, if they have none or it already passed) and/or addData on top of their current data limit. If the user was expired or limited, status is moved back to active. Use this instead of marzban_users_update for renewals — it reads the current expire/limit first so the increment is relative, not an absolute overwrite.
| Name | Required | Description | Default |
|---|---|---|---|
| addData | No | Extra data allowance to add on top of the current limit, e.g. "10GB". | |
| username | Yes | ||
| addDuration | No | Relative duration to add to the current expiration, e.g. "30d". |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | Yes | |
| user | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only state readOnly=false and destructive=false; the description adds the important behavioral details: fallback to now when no expiration exists or it already passed, additive data increments, and reactivation of expired/limited users. This is meaningful context beyond what annotations provide, and it contradicts nothing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences front-load the core behavior, then give routing guidance. Every sentence earns its place, and there is no redundant restatement of the title or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values do not need to be explained. The description covers fallback behavior, relative increments, status side effects, and sibling routing. The main gap is that the schema only requires username, while the description does not explicitly state that at least one of addDuration or addData should normally be supplied for the call to be meaningful.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents addData and addDuration with examples, and the description adds crucial relational meaning: increments are relative to current values rather than absolute overwrites, and expiration falls back to now if absent/passed. The required username is left undescribed, but its pattern makes it self-evident.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (a user subscription), the action (renews/extend), and the exact semantics (adds relative duration and/or data). It also explicitly distinguishes the tool from marzban_users_update, so an agent can tell them apart without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit when-to-use rule: 'Use this instead of marzban_users_update for renewals,' and explains why — it reads current expiration/limit first so the increment is relative rather than an absolute overwrite. This clearly routes the agent away from the closest sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_users_getGet userARead-only
Fetches one user by username, with a computed summary: data left, days left, usage percent, and whether they are effectively expired (covers the case where status has not caught up with an already-past expire yet).
| Name | Required | Description | Default |
|---|---|---|---|
| username | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| user | Yes | |
| summary | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds meaningful behavioral context beyond that, including the computed summary fields and the nuance about 'effectively expired' covering status lag.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the core action and resource, followed by the key computed output details. There is no filler or redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple, has one well-constrained parameter, an output schema, and annotations covering read-only safety. The description adds the only extra context an agent might need, namely the computed summary semantics, making it complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description only restates that the user is fetched by username, which adds little beyond the input schema's property name. Since schema description coverage is 0%, the description was expected to compensate by explaining parameter meaning or matching behavior, but it does not.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Fetches'), a specific resource ('one user by username'), and adds the distinguishing computed summary details, which clearly sets it apart from sibling tools like marzban_users_list that handle multiple users. It is not a tautology of the title.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'one user by username' gives clear context that this tool is for single-user lookup rather than listing or mutating users. However, it does not explicitly name alternatives or state when not to use this tool, relying on the sibling-tool names to imply the distinction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_users_holdPut user on holdA
Sets a user's status to on_hold — inactive until their first connection, at which point the on-hold timer starts. Useful for provisioning an account ahead of time without starting its clock.
| Name | Required | Description | Default |
|---|---|---|---|
| username | Yes | ||
| onHoldExpireDuration | No | Seconds the user may stay on_hold before expiring, counted from their first connection. |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| admin | No | |
| links | No | |
| expire | No | |
| status | Yes | |
| proxies | Yes | |
| inbounds | No | |
| username | Yes | |
| next_plan | No | |
| online_at | No | |
| created_at | Yes | |
| data_limit | No | data_limit can be 0 or greater |
| used_traffic | Yes | |
| sub_updated_at | No | |
| on_hold_timeout | No | |
| subscription_url | No | |
| excluded_inbounds | No | |
| auto_delete_in_days | No | |
| sub_last_user_agent | No | |
| lifetime_used_traffic | No | |
| on_hold_expire_duration | No | |
| data_limit_reset_strategy | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral context beyond the annotations: it explains the on_hold state transition and the first-connection timer trigger. It doesn't cover reversibility or what happens when the timer expires, but the core behavior is transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two front-loaded sentences with no filler. The core state change comes first, followed by the use case.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the state change and use case, but leaves an important gap: onHoldExpireDuration is optional and the description does not state what happens when it is omitted (e.g., default hold behavior or no expiry). Output schema covers return values, so that is not a concern.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema already documents onHoldExpireDuration, and the description reinforces its timing semantics. Username has no schema description and is not elaborated, though its role is obvious from the tool name and 'a user's status'. Overall only marginal added meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Sets'), a resource ('a user's status'), and the precise semantic (on_hold, inactive until first connection, then timer starts). This clearly distinguishes it from sibling tools like activate/deactivate, which target different user states.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear use case: provisioning an account ahead of time without starting its clock. It does not explicitly name alternatives or when-not-to-use, so it stops short of a full routing rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_users_listList usersARead-only
Lists users, optionally filtered by status or a search term (matches username/note). Paginated — default 25, max 100 per call; prefer search over paging through everyone. For one known username, use marzban_users_get instead.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Default 25, max 100. | |
| offset | No | ||
| search | No | Matches username or note (server-side substring search). | |
| status | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | Yes | |
| total | Yes | |
| users | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnlyHint=true and destructiveHint=false. The description adds pagination defaults (25, max 100) and clarifies that search matches username/note, which is beyond the annotations. It does not detail the response envelope or error behavior, but the output schema exists, so a 4 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with zero filler: purpose, filter options, pagination limits, and routing to the sibling. The most critical information (what the tool lists and its filters) is front-loaded, and every clause contributes.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with an output schema, annotations covering safety, and clear sibling differentiation, the description supplies all needed operational context: filtering, pagination, and search guidance. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% (limit and search have descriptions). The description reinforces these and adds the pagination preference, but it adds little for offset (no semantics) and status (only says 'optionally filtered', enum is in schema). It partially compensates for the coverage gap but does not fully explain each parameter's role.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb+resource ('Lists users') and immediately specifies the filtering options (status, search term). It explicitly differentiates from the sibling marzban_users_get by noting the single-user alternative, so an agent can reliably pick the right tool without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete guidance on when to prefer search over paging ('prefer `search` over paging through everyone') and names the exact alternative for a known username ('use marzban_users_get instead'). This is explicit when-to-use and when-not-to-use guidance with a sibling reference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_users_updateUpdate userA
Partially updates a user — only fields you provide are changed, everything else is left as-is. For status changes prefer marzban_users_activate/deactivate/hold (clearer intent, no need to know the raw status enum). For renewing an expiring/expired user prefer marzban_users_extend.
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | ||
| expire | No | e.g. "30d" or an absolute date. 0 means unlimited. | |
| proxies | No | Protocol name -> settings, e.g. {"vless": {"id": "<uuid>"}} or {"shadowsocks": {}} to auto-generate credentials. Omit to leave unchanged on update. On create there is no server default — omitting this (without templateId) errors; provide at least one protocol with a matching inbound configured on the panel. | |
| inbounds | No | Protocol name -> inbound tags to restrict this user to. Omit for all inbounds. | |
| username | Yes | ||
| dataLimit | No | e.g. "10GB". 0 means unlimited. | |
| dataLimitResetStrategy | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| admin | No | |
| links | No | |
| expire | No | |
| status | Yes | |
| proxies | Yes | |
| inbounds | No | |
| username | Yes | |
| next_plan | No | |
| online_at | No | |
| created_at | Yes | |
| data_limit | No | data_limit can be 0 or greater |
| used_traffic | Yes | |
| sub_updated_at | No | |
| on_hold_timeout | No | |
| subscription_url | No | |
| excluded_inbounds | No | |
| auto_delete_in_days | No | |
| sub_last_user_agent | No | |
| lifetime_used_traffic | No | |
| on_hold_expire_duration | No | |
| data_limit_reset_strategy | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (readOnlyHint=false, destructiveHint=false), the description discloses that updates are partial and non-destructive to omitted fields. It also clarifies that status changes via this tool would require raw enum knowledge, which is useful behavioral context not present in annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: the first states the core behavior, the second and third route to siblings. No filler or repetition of schema details. The most important information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the critical usage nuance (partial update) and sibling routing for a complex nested-parameter tool. An output schema exists, so return values need no explanation. It does not discuss edge cases like proxy replacement semantics, but the schema's proxy description already covers some of that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 57%, with descriptions for expire, proxies, inbounds, and dataLimit. The description adds the crucial cross-cutting semantic that all parameters are optional and only provided ones change, but it does not individually clarify note or dataLimitResetStrategy beyond the schema. This is adequate but not fully compensating.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Partially updates a user'. It clearly defines the core behavior (only provided fields are changed) and distinguishes this tool from sibling tools by naming the specialized alternatives for status and renewal operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to prefer marzban_users_activate/deactivate/hold and marzban_users_extend, with reasons. This is direct routing guidance that leaves little to inference and prevents misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
marzban_users_usageGet user traffic usageARead-only
Reports how much data a user has used: total, lifetime total, their current limit, and a breakdown by node. start/end (ISO datetimes) narrow the per-node breakdown to a period; omit both for all-time.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ISO datetime. Omit for no upper bound. | |
| start | No | ISO datetime. Omit for no lower bound. | |
| username | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| byNode | Yes | |
| username | Yes | |
| dataLimit | Yes | |
| usedTraffic | Yes | |
| lifetimeUsedTraffic | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is established. The description adds meaningful behavioral context beyond the annotations: it discloses that the report includes per-node breakdowns and that the breakdown can be filtered by period, which helps the agent set expectations without needing to inspect output structure further.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly written sentences deliver all essential information with no filler. The main purpose is front-loaded, followed immediately by parameter usage guidance, and every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only usage query with an output schema already present, the description covers everything needed to invoke it correctly: what is reported, which parameters affect the report, and what happens when the optional parameters are omitted. No critical behavioral or invocation details are missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents start and end as optional ISO datetimes, covering 67% of parameters, and the description reinforces this with the specific rule 'omit both for all-time.' This adds semantic context about how the two time parameters interact, which is valuable beyond the individual schema descriptions. The username parameter is only constrained by schema pattern, but the description's focus on usage makes its role clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Reports') and names the resource ('data a user has used'), then enumerates exactly what is returned: total, lifetime total, current limit, and per-node breakdown. This makes the tool's purpose unmistakable and distinct from sibling tools like marzban_users_get or marzban_users_list, which focus on user configuration rather than traffic statistics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly explains how to use the optional start/end parameters and explicitly states the all-time behavior when both are omitted. It does not name alternative sibling tools or specify when not to use this tool, but the usage context is evident from the description and the readOnly annotation, so the guidance is adequate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v0.2.3- Changed
marzban_subscription_info5 fields changed- removed
Output schema / properties / created_at / formatRemoved value: -"date-time" - removed
Output schema / properties / created_at / patternRemoved value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$" - changed
Output schema / properties / on_hold_timeout / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / online_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / sub_updated_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +]
- Changed
marzban_users_activate5 fields changed- removed
Output schema / properties / created_at / formatRemoved value: -"date-time" - removed
Output schema / properties / created_at / patternRemoved value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$" - changed
Output schema / properties / on_hold_timeout / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / online_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / sub_updated_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +]
- Changed
marzban_users_create6 fields changed- changed
Input schema / properties / proxies / descriptionPrevious value: -"Protocol name -> settings, e.g. {\"vless\": {\"id\": \"<uuid>\"}}. Omit to leave unchanged (update) or use server defaults (create)."New value: +"Protocol name -> settings, e.g. {\"vless\": {\"id\": \"<uuid>\"}} or {\"shadowsocks\": {}} to auto-generate credentials. Omit to leave unchanged on update. On create there is no server default — omitting this (without templateId) errors; provide at least one protocol with a matching inbound configured on the panel." - removed
Output schema / properties / created_at / formatRemoved value: -"date-time" - removed
Output schema / properties / created_at / patternRemoved value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$" - changed
Output schema / properties / on_hold_timeout / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / online_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / sub_updated_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +]
- Changed
marzban_users_deactivate5 fields changed- removed
Output schema / properties / created_at / formatRemoved value: -"date-time" - removed
Output schema / properties / created_at / patternRemoved value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$" - changed
Output schema / properties / on_hold_timeout / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / online_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / sub_updated_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +]
- Changed
marzban_users_extend5 fields changed- removed
Output schema / properties / user / properties / created_at / formatRemoved value: -"date-time" - removed
Output schema / properties / user / properties / created_at / patternRemoved value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$" - changed
Output schema / properties / user / properties / on_hold_timeout / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / user / properties / online_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / user / properties / sub_updated_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +]
- Changed
marzban_users_get5 fields changed- removed
Output schema / properties / user / properties / created_at / formatRemoved value: -"date-time" - removed
Output schema / properties / user / properties / created_at / patternRemoved value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$" - changed
Output schema / properties / user / properties / on_hold_timeout / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / user / properties / online_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / user / properties / sub_updated_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +]
- Changed
marzban_users_hold5 fields changed- removed
Output schema / properties / created_at / formatRemoved value: -"date-time" - removed
Output schema / properties / created_at / patternRemoved value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$" - changed
Output schema / properties / on_hold_timeout / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / online_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / sub_updated_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +]
- Changed
marzban_users_list5 fields changed- removed
Output schema / properties / users / items / properties / created_at / formatRemoved value: -"date-time" - removed
Output schema / properties / users / items / properties / created_at / patternRemoved value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$" - changed
Output schema / properties / users / items / properties / on_hold_timeout / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / users / items / properties / online_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / users / items / properties / sub_updated_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +]
- Changed
marzban_users_update6 fields changed- changed
Input schema / properties / proxies / descriptionPrevious value: -"Protocol name -> settings, e.g. {\"vless\": {\"id\": \"<uuid>\"}}. Omit to leave unchanged (update) or use server defaults (create)."New value: +"Protocol name -> settings, e.g. {\"vless\": {\"id\": \"<uuid>\"}} or {\"shadowsocks\": {}} to auto-generate credentials. Omit to leave unchanged on update. On create there is no server default — omitting this (without templateId) errors; provide at least one protocol with a matching inbound configured on the panel." - removed
Output schema / properties / created_at / formatRemoved value: -"date-time" - removed
Output schema / properties / created_at / patternRemoved value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$" - changed
Output schema / properties / on_hold_timeout / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / online_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - changed
Output schema / properties / sub_updated_at / anyOfPrevious value: -[ - { - "anyOf": [ - { - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$", - "type": "string" - }, - { - "type": "null" - } - ] - }, - { - "type": "null" - } -]New value: +[ + { + "type": "string" + }, + { + "type": "null" + } +]
15 tool updates
v0.2.2- First observed
marzban_config_get - First observed
marzban_hosts_get - First observed
marzban_nodes_list - First observed
marzban_subscription_info - First observed
marzban_system_inbounds - First observed
marzban_system_stats - First observed
marzban_users_activate - First observed
marzban_users_create - First observed
marzban_users_deactivate - First observed
marzban_users_extend - First observed
marzban_users_get - First observed
marzban_users_hold - First observed
marzban_users_list - First observed
marzban_users_update - First observed
marzban_users_usage
TDQS
Scored across 15 tools
Most tools have clearly distinct purposes, especially across user actions and system views. The descriptions explicitly disambiguate users_get vs users_list vs subscription_info and config_get vs hosts_get vs system_inbounds, though hosts_get and system_inbounds could still cause mild confusion.
The dominant pattern is marzban_<resource>_<verb>, e.g. users_create, users_get, hosts_get, nodes_list. A few tools break this pattern—subscription_info, system_inbounds, system_stats, users_usage—but the naming remains predictable and readable overall.
At 15 tools, the set is at the upper end of the well-scoped range but still feels justified for a panel administration server. Each tool covers a meaningful operation, and the many user-management tools map to distinct lifecycle actions.
The set covers user creation, retrieval, update, status changes, renewal, usage, subscription diagnosis, nodes, config, inbounds, and system stats. However, there is no delete-user tool, and no obvious way to generate or reset a subscription URL, leaving clear lifecycle gaps.
Maintenance
Related MCP Connectors
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
A paid remote MCP for CLI tool MCP, built to return verdicts, receipts, usage logs, and audit-ready
MCP server for Pentest-Tools.com: run scans, manage findings and reports via your preffered LLM.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
Related MCP Servers
- AlicenseAqualityAmaintenanceProduction-grade MCP server for MikroTik RouterOS with secure AI-native network automation.122210 npm66MIT
- AlicenseAqualityBmaintenanceEnables AI assistants to manage pfSense firewalls using 17 tools for system status, firewall rules, DHCP, DNS, monitoring, and service management via the pfSense REST API.1730 PyPI6MIT
- FlicenseNot gradedqualityBmaintenanceLocal-first CLI + proxy that curates your MCP servers per client from one canonical config, cutting tool-schema tokens ~80% and resolving secret references instead of hardcoding keys.-
- AlicenseAqualityBmaintenanceMCP server for Proxmox VE and Proxmox Datacenter Manager, covering every API endpoint via six consolidated tools for list, describe, and call operations with a read-only safety gate.616 npm2AGPL 3.0