Skip to main content
Glama
vmware-skills

vmware-vdi

VMware VDI (Horizon)

AI-powered intelligent operations for VMware / Omnissa Horizon VDI — manage desktop pools, RDS farms, published apps, user sessions, desktop machines, entitlements, instant-clone images, and Horizon events/health/statistics through the Horizon 8 Connection Server REST API. Ships as both an MCP server (for AI agents) and a CLI (for help-desk and scripting). Part of the VMware skill family.

Disclaimer: Community-maintained open-source project, not affiliated with, endorsed by, or sponsored by VMware, Inc., Broadcom Inc., or Omnissa, LLC. "VMware", "Horizon", and "Omnissa" are trademarks of their respective owners. Source is publicly auditable under the MIT license.

Status: v1.0.0 (beta). REST endpoints are verified against the official Horizon Server API; GET-response field projections are defensive and pending validation against a live Connection Server (a field-name mismatch yields empty results, not a crash — see the beta note).

Upgrading to 2.0

2.0 renames all 27 MCP tools so every name starts with a verb (e.g. ad_user_search → search_ad_users, app_pool_list → list_app_pools, entitlement_add → add_entitlement). The full old → new table is in RELEASE_NOTES.md. Nothing else changes: same tools, parameters, safety gates and CLI commands. If an agent prompt, script or ~/.vmware/rules.yaml names a tool, update it — though deny rules written with the old names keep working with vmware-policy ≥ 1.18 (vmware-audit policy lists any rule the renames widened), and vmware-pilot ≥ 1.13 translates old names in saved workflows. If an install older than 2.0 shares that rules.yaml, give it vmware-policy ≥ 1.18.2 too: it matches each rule against both the old and the new name, so one file serves both.

Related MCP server: vSphere MCP Server

Why vmware-vdi

Every other VMware family skill stops at the vСenter VM. A Horizon desktop pool sits on those VMs — so vmware-aiops can reset the backing VM, but it cannot see a user session, log a user off, disable a pool, or push a golden image. vmware-vdi fills exactly that day-2 VDI gap — "who is stuck on a broken desktop", "log this user off so their profile unlocks", "why is this pool not provisioning", "push the patched image to Finance tonight" — with the family's governed-ops harness: every write is audited, previews its blast radius, and is authorized by the Horizon account's own RBAC role.

Capabilities — 27 MCP tools (16 read / 11 write)

Category

Tools

Monitoring

health summary · session list/get · machine list/get · event list

Statistics

session concurrency stats · per-pool utilization

Management

pool list/get · farm list · app-pool list · entitlement list · image list · AD search · pool enable/disable · entitlement add/remove

Ops actions

session logoff / disconnect / message · machine reset / maintenance / remove

Tasks

task status · image push · task cancel

Reads are strictly non-destructive. Writes preview their blast radius, double-confirm at the CLI, and are audit-logged to ~/.vmware/audit.db. push_desktop_pool_image recreates every desktop in a pool — the highest single-call blast radius in the family — and its preview states affected-desktop and in-session counts before any confirm, together with occupancy: determined when those counts can be believed, unknown when sessions exist that cannot be attributed to any pool or farm. An unknown occupancy refuses the confirm rather than reporting an unverified zero; overriding it needs --acknowledge-unknown-occupancy and is recorded in the audit row. A machine that names no desktop pool also makes the desktop count a lower bound ("at least N"); that refuses the confirm with no override.

On MCP, every gated write takes confirm (default false). A call without it returns blast_radius — the object's identity, counts, identifiers up to 20, blockers and unmeasured — and changes nothing; the acting response carries the same dict. An agent should show it to the user and pass confirm=true only after they agree. When something the blast radius depends on could not be read — a machine's state, a session's user, a task's type or state, a pool's enabled flag, a pool's current entitlements — confirm=true is refused with a message naming what to check.

Quick start

uv tool install vmware-vdi
vmware-vdi init      # friendly wizard: connect to a Connection Server + discover your pools
vmware-vdi doctor    # verify config / credentials / connectivity
vmware-vdi health    # one-glance VDI health

vmware-vdi init prompts for the Connection Server host, admin username, AD domain, and password; writes ~/.vmware-vdi/config.yaml + a 0600 .env (password obfuscated); tests the login; and on success discovers your pools, machines, and sessions with the next commands to try.

Example workflows

Help-desk — a user's desktop is stuck

vmware-vdi session list --user alice
vmware-vdi machine list --state AGENT_UNREACHABLE
vmware-vdi session logoff --user alice --dry-run   # preview which sessions
vmware-vdi session logoff --user alice             # double-confirm, then logs off + audits

Patch night — push a new golden image

vmware-vdi image list
vmware-vdi pool push-image --id pool-fin --dry-run  # BLAST RADIUS: N desktops, M logged-in users
vmware-vdi pool push-image --id pool-fin            # double-confirm; returns a task
vmware-vdi task status --pool pool-fin              # track progress

MCP server

{
  "mcpServers": {
    "vmware-vdi": {
      "command": "vmware-vdi",
      "args": ["mcp"],
      "env": { "VMWARE_VDI_CONFIG": "~/.vmware-vdi/config.yaml" }
    }
  }
}

Using the installed vmware-vdi mcp console script (not uvx) avoids a PyPI re-resolve on every launch — important behind enterprise TLS proxies.

Supported versions

  • VMware Horizon 8.x (primary) — Connection Server REST API /rest/v1.

  • Latest Omnissa Horizon (2406 / 2412+) — same /rest/v1 lineage.

Security

  • Authorization = Horizon RBAC. The skill does not gate read vs write; point a target at a read-only Horizon admin role and every write is refused at the Connection Server, un-bypassably.

  • Credentials live only in ~/.vmware-vdi/.env (0600, obfuscated b64: at rest); config files hold host/username/domain only. Inject VMWARE_VDI_<TARGET>_PASSWORD from a secret manager for real secrecy.

  • TLS verification on by default. All Connection-Server text is sanitize()d against prompt injection.

  • No outbound calls except to the configured Connection Server — no webhooks, no telemetry.

See SECURITY.md and skills/vmware-vdi/references/setup-guide.md.

Beta note

REST endpoints are verified against the official Horizon Server API operation index. GET-response field names (and a few write bodies) are defensive (.get() with fallbacks) and pending validation against a live Connection Server. On a field-name mismatch a list reads empty rather than crashing. First real-Horizon use should run vmware-vdi init and confirm the session/machine/pool projections; please file an issue with raw *_get output if a projection looks empty. Quality: 32 regression tests, ruff clean, bandit 0, tool endpoints pinned to a verified spec.

Companion skills

Part of the VMware skill family — install the modules you need:

Remote access (HTTPS) and limiting tools

By default vmware-vdi mcp speaks stdio to one local client and offers every tool. Two options change that (vmware-policy ≥ 1.21.0).

Serve over HTTPS so clients on other machines can connect. Every caller needs a bearer token:

vmware-audit token create alice          # prints the token once; give it to alice
vmware-audit token list                  # names only
vmware-audit token revoke alice          # refused from its next request, no restart
vmware-vdi mcp --transport https --host 0.0.0.0 --port 8443 \
    --cert /etc/vmware-mcp/server.pem --key /etc/vmware-mcp/server-key.pem \
    --public-name mcp.example.com

Connect a client (Claude Code shown; any MCP client that supports streamable HTTP and custom headers works):

claude mcp add --transport http vmware-vdi https://mcp.example.com:8443/mcp \
    --header "Authorization: Bearer $VMWARE_MCP_TOKEN"
{
  "mcpServers": {
    "vmware-vdi": {
      "type": "http",
      "url": "https://mcp.example.com:8443/mcp",
      "headers": { "Authorization": "Bearer ${VMWARE_MCP_TOKEN}" }
    }
  }
}
  • The server will not start without a token, refuses Host/Origin values outside --public-name, and checks before it binds that unauthenticated requests get 401. Use a certificate your clients trust for those names.

  • Behind a TLS-terminating reverse proxy on the same machine use --transport http --host 127.0.0.1 --public-name mcp.example.com and pass the Authorization header through.

  • Behind a load balancer or gateway on another machine, keep --transport https (a self-signed certificate is fine), list in --public-name the host name the balancer sends as Host, and have it forward Authorization. Its health probe can use GET /healthz, which needs no token and returns only {"status": "ok"} (vmware-policy ≥ 1.23.0).

  • Send traceparent or X-Request-ID with each request to have it stored on the audit row; vmware-audit log --correlation-id ID then finds the calls behind one platform request.

  • The audit log records each caller as token:<name>. Calls run side by side, with or without a target: each target keeps up to VMWARE_MCP_POOL_SIZE sessions (default 2), and each session is a login on the target. A call that finds them all busy waits at most 300 s for one.

  • Everyone who can reach the endpoint acts with this server's account. Tokens identify callers; they grant nothing on the platform. Run one endpoint per privilege level.

  • Several people or roles on one endpoint: run vmware-audit roles enable once, then give each token a role (vmware-audit token create NAME --role reader, or a role in roles.yaml naming tools and targets; vmware-policy ≥ 1.24.0). A role limits what the token may call on this endpoint; it cannot grant more than the account has. See vmware-policy's README, "Roles for network callers".

Offer only read tools, plus the writes you choose:

vmware-vdi mcp --expose read --allow-write add_entitlement
# or: VMWARE_VDI_MCP_EXPOSE=read VMWARE_VDI_MCP_ALLOW_WRITE=add_entitlement vmware-vdi mcp

Tools not offered do not appear in the client's tool list. A bad value or an unknown write tool stops the server (exit 2). This limits what clients are offered; it is not authorization, so the account itself should be least-privilege.

Details: skills/vmware-vdi/references/setup-guide.md ("Serving MCP over HTTPS", "Limiting which tools are offered").

License

MIT — see LICENSE.

Available Tools

27 tools
add_entitlementA
Idempotent

[WRITE] Grant desktop-pool access to AD user/group SID(s).

Get SIDs from search_ad_users. A bare call returns blast_radius (pool identity, which principals are already entitled and which are new) and grants nothing; confirm=True grants. Refused when the pool's current entitlements cannot be read. Show blast_radius to the user and wait for their decision. Do not set confirm=True on your own because the user asked for this earlier: they have not seen the blast radius yet. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
confirmNoFalse (default) returns the blast radius and changes nothing. True grants.
pool_idYesThe desktop-pool id (from list_desktop_pools).
ad_user_or_group_idsYesAD SIDs to entitle (from search_ad_users).

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnly=false, destructive=false, idempotent=true, openWorld=true), and the description adds substantial context beyond them: the no-op default call, the exact blast_radius contents, the refusal condition when entitlements can't be read, and that actions are audited. Nothing contradicts the idempotentHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with tag, purpose, workflow, then guardrail; most sentences earn their place. The 'do not set confirm=True on your own' sentence is slightly redundant with the following clause, but the emphasis is warranted for a destructive-adjacent workflow.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description still explains what the default call returns (blast_radius: pool identity, existing vs new principals), the failure mode, and the audit trail. An agent has everything needed to invoke it safely and interpret the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all four parameters are already documented, setting the baseline at 3. The description adds meaning to confirm by framing it as the deliberate second step in a reviewed workflow, which is more than the schema's terse 'True grants'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a bracketed [WRITE] tag plus a specific verb and resource ('Grant desktop-pool access to AD user/group SID(s)'), immediately distinguishing it from remove_entitlement and the read-only list_* siblings. An agent knows exactly what the tool does 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to search_ad_users for SIDs and to the two-phase workflow (bare call = blast radius, confirm=True = grant). It also names a when-not condition ('do not set confirm=True on your own... they have not seen the blast radius yet') and the refusal case, which is unusually complete guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cancel_vdi_taskA
Destructive

[WRITE] Cancel a running pool task (e.g. an in-progress image push).

A bare call reads the task and returns blast_radius (task type, state, progress) and cancels nothing; confirm=True cancels. A task whose type or state cannot be read is refused. Work already applied is not rolled back. Show blast_radius to the user and wait for their decision. Do not set confirm=True on your own because the user asked for this earlier: they have not seen the blast radius yet. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
confirmNoFalse (default) returns the blast radius and changes nothing. True cancels.
pool_idYesThe desktop-pool id.
task_idYesThe task id (from get_vdi_task_status).

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructive/write, but the description adds substantially more: the two-phase dry-run default, the exact contents of blast_radius (task type, state, progress), the refusal on unreadable task type/state, that applied work is not rolled back, and that the action is audited. This is rich behavioral context beyond the annotation set.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the write marker and the core action, then the dry-run/confirm split, then safety constraints. Every sentence earns its place, though the closing instruction about the user's prior request restates the blast-radius point already made.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description carries the return burden and does so by enumerating blast_radius fields. For a destructive, non-idempotent, open-world tool, it covers the prerequisites, refusal behavior, irreversibility, and audit trail an agent needs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents confirm and the other parameters, making 3 the baseline. The description still adds operational meaning beyond the terse schema text: what a bare call actually returns, that the default path mutates nothing, and the refusal condition tied to task_id resolvability.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Cancel a running pool task"), gives a concrete example (in-progress image push), and immediately distinguishes the dry-run read path from the actual cancel path. An agent can tell it apart from the sibling get_vdi_task_status, which only reads.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to cancel (confirm=True) versus when to stop at the blast radius, and names the alternative behavior. It even addresses the trap case of a user requesting the cancel before seeing the preview, telling the agent not to set confirm=True on that basis. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

disconnect_vdi_sessionA
Destructive

[WRITE] Disconnect Horizon session(s) — state preserved, the user can reconnect.

Less disruptive than logoff. Identify by session_ids OR user. A bare call returns blast_radius (session ids, count, affected users) and changes nothing; confirm=True disconnects. A session whose user cannot be read is refused. Show blast_radius to the user and wait for their decision. Do not set confirm=True on your own because the user asked for this earlier: they have not seen the blast radius yet. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
userNoDisconnect all sessions of this AD user (substring match).
targetNoHorizon target from config.yaml; omit to use the default.
confirmNoFalse (default) returns the blast radius and changes nothing. True disconnects.
session_idsNoSession ids to disconnect.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations mark it non-read-only and destructive, but the description adds what those hints cannot: a two-phase dry-run/confirm protocol, that state is preserved (softening the destructive read), that unreadable-user sessions are refused, that the call is audited, and the contents of the blast_radius payload. It does not contradict destructiveHint=true — it clarifies the degree of disruption.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the write marker and the core verb, then broken into short lines for targeting, dry-run behavior, and the safety instruction. Every sentence carries operational weight; nothing is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description explains exactly what a bare call returns (session ids, count, affected users) and how to proceed, which is what an agent needs for a zero-required-parameter, safety-gated mutation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds the OR relationship between session_ids and user and reinforces confirm's default semantics beyond the field-level text. It doesn't add syntax detail for the user substring match, but the choice logic is meaningful extra.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Disconnect Horizon session(s)') plus the key semantic that distinguishes it from siblings: state is preserved and the user can reconnect, explicitly contrasting with logoff_vdi_session. An agent can pick between the two session-terminating tools without reading further.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit selection rules (by session_ids OR user), the dry-run default, and the confirm=True gate, plus an operational instruction to show blast_radius and wait for the user's decision before confirming. It even names a specific misuse pattern to avoid ('do not set confirm=True because the user asked earlier').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_desktop_poolA
Read-onlyIdempotent

[READ] One desktop pool by id (teaching 404 on a wrong id).

Same projection as one list_desktop_pools row — id, name, type, enabled, provisioning_enabled, assignment — fetched with a single GET instead of listing every pool. Use it to re-check one pool after a write, or when you already hold an id.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
pool_idYesHorizon desktop-pool id (the opaque 'id' of a list_desktop_pools row, not the pool's display name). A wrong id returns a 404 whose hint tells you to re-run list_desktop_pools for exact ids.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, openWorld, non-destructive, so the bar is lower. The description adds genuinely new behavior: a wrong id returns a 404 whose hint tells you to re-run list_desktop_pools, and the returned projection matches a single list row. It does not cover auth/permission requirements, but the added error and projection behavior is substantive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with the read-only tag and scope front-loaded, followed by the projection and the when-to-use clause. No filler, no repetition of annotation data.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, yet the description enumerates the returned projection (id, name, type, enabled, provisioning_enabled, assignment), which is exactly the return-value context the agent needs. Combined with the error behavior and selection guidance, nothing material is missing for a two-parameter read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both parameters are already documented, including the opaque-id warning and the 404 hint. The description largely restates the pool_id semantics rather than adding format, syntax, or edge-case detail beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('[READ] One desktop pool by id'), and immediately contrasts with the sibling list_desktop_pools by saying it fetches a single GET instead of listing every pool. An agent can distinguish it from list/task siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the two conditions that select this tool: 're-check one pool after a write' and 'when you already hold an id'. It also names the alternative (list_desktop_pools) and the reason to prefer it when ids are unknown (the 404 hint routes back to list_desktop_pools).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_desktop_pool_utilizationA
Read-onlyIdempotent

[READ] Per-pool capacity: total / available / in-use / error machines and utilization %.

The "am I running out of desktops?" view, sorted by utilization. Drill in with list_vdi_machines --pool.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the "[READ]" tag adds nothing; the real value is disclosing that results are sorted by utilization and enumerating the returned counters. No auth, rate-limit, or pagination behavior is described, but for a small read-only aggregate there is little else to disclose.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short lines with zero filler: the returned metrics are front-loaded in line one and the routing hint is second. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by naming the exact fields returned and their ordering, which is precisely what an agent needs to interpret the response. Nothing required for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema carries 100% description coverage for the single optional `target` parameter (config.yaml target, omit for default), so the schema does the heavy lifting and a baseline 3 applies. The description adds no parameter-level detail beyond the incidental --pool drill-down hint.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource (desktop pool) and precise scope (per-pool capacity: total/available/in-use/error machines and utilization %), which cleanly separates it from list_desktop_pools and get_desktop_pool. The framing as the "am I running out of desktops?" view makes the output semantics immediately legible.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear triggering intent ("am I running out of desktops?") and explicitly routes the agent to the drill-down alternative (list_vdi_machines --pool). It stops short of stating when to prefer this over adjacent summary tools such as get_vdi_health_summary or list_desktop_pools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_vdi_health_summaryA
Read-onlyIdempotent

[READ] One-glance Horizon VDI health: session totals by state, problem machines, pool availability.

The first thing to call for "how is VDI right now?". Aggregates sessions, machines, and pools into a compact status. Drill into problems with list_vdi_machines --state or list_vdi_sessions.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, and openWorld, so the safety profile is covered. The description adds value by sketching the aggregate output (session totals by state, problem machines, pool availability), which matters since no output schema exists; it stops short of detailing freshness or scoping.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences plus a drill-down hint, all front-loaded: the 'what' first, then the positioning, then the alternatives. Nothing is padding, though the [READ] prefix mildly duplicates readOnlyHint.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden and does sketch the aggregate contents, but only at a high level—no mention of how fresh the data is or what the compact status actually contains field-by-field. Adequate for a single-optional-param read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single 'target' parameter is fully documented in the schema (default, omission behavior). The description adds nothing about the parameter, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (aggregate VDI health) and enumerates the facets returned: session totals by state, problem machines, pool availability. This clearly separates it from the many sibling list_* tools, which enumerate individual entities rather than summarizing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly declares itself the first call for 'how is VDI right now?' and names the follow-up alternatives (list_vdi_machines --state, list_vdi_sessions) with the condition that selects them. Both when-to-use and when-to-drill-down are covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_vdi_machineA
Read-onlyIdempotent

[READ] One Horizon desktop machine by id (teaching 404 on a wrong id).

Same projection as one list_vdi_machines row — id, name, pool_id, state, assigned user, agent_version, base_image — fetched with a single GET instead of scanning the estate. Use it to re-check one machine after a write, or when you already hold an id.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
machine_idYesHorizon machine id (the opaque 'id' of a list_vdi_machines row, not the desktop's display name and not the vCenter VM name). A wrong id returns a 404 whose hint tells you to re-run list_vdi_machines for exact ids.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover readOnly/idempotent/openWorld/non-destructive, so the bar is lower, but the description still adds real value: the exact field projection returned, the single-GET behavior, and the 404-with-remediation-hint failure mode on a bad id. It stops short of pagination/latency or auth details, which are minor here.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with a [READ] tag and the core purpose, then the projection, then the usage condition. Every clause earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by enumerating the returned fields (id, name, pool_id, state, assigned user, agent_version, base_image). Combined with the 404 behavior note and usage condition, nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so machine_id and target are fully documented in the schema, including the disambiguation from display name and vCenter VM name. The description adds nothing beyond that baseline, so 3 is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource+scope: 'One Horizon desktop machine by id', and frames it against the sibling list_vdi_machines row projection. An agent can immediately tell this fetches a single machine rather than scanning the estate.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names when to use it ('re-check one machine after a write, or when you already hold an id') and implicitly contrasts it with the alternative of scanning the estate via list_vdi_machines. The condition selecting this tool over the list sibling is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_vdi_sessionA
Read-onlyIdempotent

[READ] Full detail for one Horizon session by id.

A wrong id returns a teaching error ("run list_vdi_sessions for current ids"), not a traceback. Use list_vdi_sessions to discover ids.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
session_idYesThe session id (from list_vdi_sessions).

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds non-obvious behavior: a wrong id yields a teaching error rather than a traceback. It stops short of describing the returned detail fields, but for a read tool that is minor.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the read scope front-loaded and the fallback/alternative guidance second. No filler or restated title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-record read whose annotations carry the safety profile and whose schema fully documents parameters, the description covers the remaining critical needs: discovery routing and error behavior. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the schema already documents both 'target' and 'session_id' (including the 'from list_vdi_sessions' hint). The description adds no syntax or format detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Full detail'), resource ('Horizon session'), and scope ('one ... by id'), which clearly separates it from list_vdi_sessions. An agent can tell exactly what this tool returns 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternative ('Use list_vdi_sessions to discover ids') and the discovery condition, routing the agent correctly. It also clarifies what happens on a bad id, removing a common invocation pitfall.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_vdi_session_statsA
Read-onlyIdempotent

[READ] Session statistics: concurrency by state / protocol, current concurrent, busiest pools.

The reporting counterpart to list_vdi_sessions — aggregate numbers, not per-session rows.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, and openWorld, so the safety profile is fully covered by structured data. The description adds the '[READ]' marker and clarifies that results are aggregates rather than rows, but provides no behavioral details such as scope of aggregation, freshness, or failure modes. With annotations carrying the safety burden, a 3 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences, front-loaded with what it returns and followed by the disambiguation from its sibling. Every sentence earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description usefully enumerates the aggregate categories returned (by state/protocol, current concurrent, busiest pools), which is enough for an agent to know what to expect. It stops short of any detail on granularity, time window, or shaping of the response, so it is not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single 'target' parameter is documented in the schema as the Horizon target from config.yaml. The description adds no syntax, default, or selection detail beyond that, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource ('Session statistics') and enumerates exactly what it reports: concurrency by state/protocol, current concurrent count, and busiest pools. It explicitly differentiates itself from list_vdi_sessions as the aggregate reporting counterpart, so an agent can pick it 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.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It names the alternative (list_vdi_sessions) and the condition that selects this tool — wanting aggregate numbers rather than per-session rows. That is clear routing guidance, though there is no explicit when-not or prerequisite/permission guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_vdi_task_statusA
Read-onlyIdempotent

[READ] Status of a pool's long task (image push / provisioning), or all tasks for the pool.

Horizon tasks are pool-scoped. Give task_id (from push_desktop_pool_image or a prior get_vdi_task_status) for one task; omit it to list all tasks for the pool.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
pool_idYesThe desktop-pool id.
task_idNoA specific task id; omit to list all tasks for the pool.

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the '[READ]' tag adds nothing. The description does add one real behavioral constraint — Horizon tasks are pool-scoped — plus task_id provenance, but says nothing about permissions, task expiry, or result shape.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the '[READ]' marker and purpose in the first clause, then the task_id semantics. Two tight paragraphs with no filler, though the 'omit it to list all tasks for the pool' clause duplicates the task_id schema description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only, three-parameter, no-output-schema tool whose annotations fully cover the safety profile, the description supplies the essentials: what it returns, the pool-scoping constraint, and both usage modes. It stops short of characterizing what a task status looks like, which is the only real gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all three parameters and the baseline is 3. The description goes slightly beyond it by explaining the provenance of task_id (from push_desktop_pool_image or a prior status call), though it never mentions the 'target' parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource ('Status of a pool's long task'), scopes it (image push / provisioning), and covers the list-variant. It is clearly distinguishable from siblings like cancel_vdi_task or push_desktop_pool_image without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the two operating modes explicitly (supply task_id for one task, omit it to list all tasks for the pool) and even names where a task_id comes from (push_desktop_pool_image or a prior call). There is no explicit 'when not to use' or named alternative, which keeps it from a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_app_poolsA
Read-onlyIdempotent

[READ] List published application pools: id, name, farm, enabled, executable path. Paginated.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoPage size (default 50).
offsetNoPage offset.
targetNoHorizon target from config.yaml; omit to use the default.

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds the pagination behavior and the returned field set, which is useful, but says nothing further about permissions, limits, or errors.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence: the [READ] tag and core action come first, followed by returned fields and pagination. Nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only paginated list tool with full schema descriptions and rich annotations, the description covers what it is, what it returns, and that results are paged. Only explicit sibling routing is missing, which is minor here.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and all three parameters (limit, offset, target) are documented in the schema. The description only echoes pagination via "Paginated" and adds no meaning beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (list application pools) and enumerates returned fields (id, name, farm, enabled, executable path), which distinguishes it from sibling list_desktop_pools. It never explicitly names that sibling as the alternative, keeping it just short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The word "published" implies scope and the read tag implies a read-only listing, so usage is implied. However, there is no explicit when-to-use, when-not-to-use, or routing to list_desktop_pools for non-application pools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_desktop_poolsA
Read-onlyIdempotent

[READ] List Horizon desktop pools: id, name, type (AUTOMATED/MANUAL/RDS), enabled, assignment.

The verify pair for set_desktop_pool_enabled and push_desktop_pool_image. Paginated envelope.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoPage size (default 50).
offsetNoPage offset.
targetNoHorizon target from config.yaml; omit to use the default.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, destructive=false, openWorld), so the bar is lower. The description adds meaningful behavioral context by disclosing the 'Paginated envelope' return shape, which the annotations do not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight lines: purpose + fields, then usage, then return shape, all front-loaded with no waste. The '[READ]' tag is redundant with readOnlyHint but negligible.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully lists returned fields and notes pagination, and annotations cover the safety profile, so an agent has enough to call it correctly. Slightly more detail on pagination mechanics or default scoping would round it out.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so limit, offset, and target are already documented in the schema. The description adds no additional parameter meaning beyond what the schema provides, which is the baseline 3 for fully-covered schemas.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') and resource ('Horizon desktop pools') and enumerates the returned fields (id, name, type, enabled, assignment). It is clearly distinguishable from siblings like list_app_pools and list_vdi_images without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly identifies its role as 'the verify pair for set_desktop_pool_enabled and push_desktop_pool_image', giving concrete when-to-use context tied to specific sibling mutations. It stops short of naming when NOT to use it versus the other list_* siblings, so it is short of a full 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_entitlementsA
Read-onlyIdempotent

[READ] List the AD users/groups entitled to a desktop pool (who can access it). Paginated.

A wrong pool id returns a teaching 404. Use list_desktop_pools for pool ids.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoPage size (default 50).
offsetNoPage offset.
targetNoHorizon target from config.yaml; omit to use the default.
pool_idYesThe desktop-pool id (from list_desktop_pools).

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered; the description adds that results are paginated and that an invalid pool id produces a teaching 404. That is genuine behavioral context beyond the annotations, though it says nothing about result volume or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with the [READ] tag and the core purpose front-loaded, then pagination and error/routing notes. Every sentence earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter read tool with no output schema, the description covers the essential call mechanics: what it returns (AD users/groups with access), pagination, and how to source the required pool id. It does not describe the shape of returned entitlement entries, but that is a minor omission given the absence of an output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so limit, offset, target and pool_id are all documented in the schema itself. The description adds only that pool_id comes from list_desktop_pools, which is useful but marginal; baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and resource (AD users/groups entitled to a desktop pool), with the clarifying gloss 'who can access it'. This cleanly separates it from siblings add_entitlement/remove_entitlement and from pool-listing tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to list_desktop_pools for obtaining pool ids, and warns that a wrong pool id yields a teaching 404, which is actionable guidance. It lacks an explicit 'when not to use' or a note on when add/remove_entitlement would be the right call instead, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_farmsA
Read-onlyIdempotent

[READ] List Horizon RDS farms: id, name, type, enabled, RDS server count. Paginated.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoPage size (default 50).
offsetNoPage offset.
targetNoHorizon target from config.yaml; omit to use the default.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover safety (readOnlyHint, idempotentHint, destructiveHint=false), but the description adds that results are paginated and identifies the returned fields. It does not mention permission requirements or rate limits, but for a read-only list tool those are minor gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence plus the '[READ]' tag and a final 'Paginated.' clause; it is front-loaded with the action and resource and wastes no words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only list tool with fully documented parameters and rich annotations, the description supplies the missing return-field enumeration and pagination note. No output schema exists, so that returned-field list is the right level of detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so limit, offset, and target are fully documented in the schema. The description only implies pagination via the word 'Paginated'; it adds no syntax or constraints beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List Horizon RDS farms') and enumerates the returned fields, so an agent can distinguish it from the VDI-pool and image-listing siblings even without a title. No ambiguity about what is listed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no when-to-use guidance, no alternatives, and no exclusions. It never distinguishes listing RDS farms from the sibling tools that list desktop pools, app pools, images, or sessions, so the agent must infer the scope 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.

list_vdi_eventsA
Read-onlyIdempotent

[READ] List Horizon audit events (newest first), optionally filtered by severity. Paginated.

Each item: time, severity, type, module, user, machine, message. Use for "what went wrong recently".

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoPage size (default 50).
offsetNoPage offset.
targetNoHorizon target from config.yaml; omit to use the default.
severityNoFilter by severity (e.g. ERROR, WARNING, AUDIT_FAIL).

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is covered. The description adds useful behavior beyond annotations: newest-first ordering, pagination, severity filtering, and the fields returned per event.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: READ status, resource, ordering, filtering, pagination, returned fields, and usage are all stated without wasted text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although there is no output schema, the description lists the returned event fields and explains ordering, filtering, and pagination. Combined with annotations and a fully documented input schema, it gives the agent enough context to call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents limit, offset, target, and severity. The description adds context for severity filtering and pagination, but does not explain the target parameter or add meaningful semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: list Horizon audit events. It also specifies ordering (newest first), optional severity filtering, and pagination, which makes the tool’s behavior easy to distinguish from sibling list/get tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear usage cue: use for "what went wrong recently." It does not explicitly name alternatives or when not to use it, but the context is sufficient for an agent to select it confidently.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_vdi_imagesA
Read-onlyIdempotent

[READ] List instant-clone base VMs and snapshots (the golden-image catalog for push_desktop_pool_image).

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
base_vm_idNoOptionally scope snapshots to one base VM.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is fully covered structurally. The '[READ]' prefix merely restates that, and the description adds only the nature of the returned catalog — it says nothing about openWorldHint behavior, result size, or pagination.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence, front-loaded with the verb and resource, with the qualifying context tucked into a parenthetical rather than padding the prose. Nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple, zero-required-parameter list tool with no output schema, the description conveys what is returned and why it matters. Only minor details (pagination, result size, whether snapshots require base_vm_id) are left unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both optional parameters (target, base_vm_id) are documented there, including the default-target behavior and the snapshot-scoping effect. The description adds no parameter detail, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('List') and resource ('instant-clone base VMs and snapshots'), then defines the resource in domain terms ('golden-image catalog') so an agent understands what 'images' actually means. It also ties itself to the sibling that consumes the output (push_desktop_pool_image), which no other sibling does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The parenthetical 'catalog for push_desktop_pool_image' gives clear context for when this tool is relevant — browsing available base VMs/snapshots before pushing an image. It stops short of explicit when-not or alternative-tool guidance, but the usage context is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_vdi_machinesA
Read-onlyIdempotent

[READ] List Horizon desktop machines, filtered by pool id / state. Paginated.

Each item: id, name, pool_id, state (AVAILABLE/CONNECTED/AGENT_UNREACHABLE/PROVISIONING/ ERROR/MAINTENANCE/…), assigned user, agent_version, base_image. Verify pair for the machine write tools.

ParametersJSON Schema
NameRequiredDescriptionDefault
poolNoFilter to one desktop-pool id.
limitNoPage size (default 50).
stateNoFilter by machine state (e.g. AGENT_UNREACHABLE, ERROR).
offsetNoPage offset.
targetNoHorizon target from config.yaml; omit to use the default.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/destructive=false, so the safety profile is covered; the description adds pagination behavior and enumerates returned item fields plus the full state value set, which is real value beyond the annotations. It stops short of detailing default page ordering or pagination termination, so not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences; the READ marker and the core verb/resource are front-loaded, and the return-shape line earns its place by compensating for the absent output schema. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully enumerates the return fields and state enum values, so an agent knows what it gets back. Minor gaps remain (ordering, when pagination ends), but nothing essential to calling it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and all five parameters are documented in-schema (pool, state, limit, offset, target). The description only restates the pool/state filtering, adding no format or syntax detail, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (list Horizon desktop machines) with scope (filtered by pool id / state), and the '[READ]' prefix plus the field enumeration distinguish it from siblings like get_vdi_machine (single) and list_vdi_sessions. An agent can route to it 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.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear usage context ('Verify pair for the machine write tools'), telling the agent it is the read-side companion to reset/set_maintenance/remove_vdi_machine. It does not, however, explicitly contrast against get_vdi_machine or list_vdi_sessions, nor state exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_vdi_sessionsA
Read-onlyIdempotent

[READ] List Horizon VDI sessions, filtered by user / pool id / state. Paginated.

Returns a {items, returned, limit, total, truncated, hint} envelope; each item has id, user, type (DESKTOP/APPLICATION), state (CONNECTED/DISCONNECTED/PENDING), protocol (BLAST/PCOIP/RDP), pool_id, machine_id, start_time. This is the verify pair for logoff/disconnect — get a session id or confirm a user's sessions here first.

ParametersJSON Schema
NameRequiredDescriptionDefault
poolNoExact desktop-pool / farm id.
userNoSubstring-match the AD user name.
limitNoPage size (default 50).
stateNoCONNECTED, DISCONNECTED, or PENDING.
offsetNoPage offset.
targetNoHorizon target from config.yaml; omit to use the default.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered; the description adds genuinely new context by disclosing the return envelope ({items, returned, limit, total, truncated, hint}), the per-item fields, and the pagination/truncation behavior. It does not discuss rate limits or auth requirements, but for a read-only list tool this is solid added value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the [READ] marker, scope, and filter axes before the return shape and the workflow hint. Every sentence carries information an agent needs; nothing is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by spelling out the return envelope, item fields, and truncation/hint semantics, and it covers filters, pagination, and the logoff/disconnect verification workflow. Nothing material is missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and each parameter already documents itself (exact pool id, substring user match, page size/offset, target). The description names the same filter dimensions without adding syntax or format detail beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List Horizon VDI sessions') plus the three filter axes (user / pool id / state) and notes pagination. The plural 'sessions' plus filter scoping clearly separates it from the singular get_vdi_session sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'This is the verify pair for logoff/disconnect — get a session id or confirm a user's sessions here first.' That names the downstream tools and the reason to call this one first. It stops short of saying when NOT to use it (e.g., use get_vdi_session when the id is already known).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

logoff_vdi_sessionA
Destructive

[WRITE] Force-logoff Horizon session(s) — kicks the user, triggers profile write-back.

Identify targets by explicit session_ids OR by user (all of that user's sessions). A bare call returns blast_radius — session ids, count and affected users — and logs off nothing; confirm=True logs off. A session whose user cannot be read is refused. Show blast_radius to the user and wait for their decision. Do not set confirm=True on your own because the user asked for this earlier: they have not seen the blast radius yet. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
userNoLog off all sessions of this AD user (substring match); refuses if none match.
targetNoHorizon target from config.yaml; omit to use the default.
confirmNoFalse (default) returns the blast radius and changes nothing. True logs off.
session_idsNoSession ids to log off (from list_vdi_sessions).

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and non-idempotency, but the description adds real behavioral context beyond them: the two-phase dry-run/confirm flow, the side effect of profile write-back, the refusal when a user cannot be read, and the fact that calls are audited.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the write/destructive marker and the core action, then the targeting options, then the safety protocol. Every sentence carries information an agent needs; nothing is padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, yet the description explains what a non-confirming call returns (session ids, count, affected users), what confirmation does, and the failure case, which is exactly the information an agent needs for a destructive, non-idempotent operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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, but the description adds the alternative-selection relationship between session_ids and user that the schema states only in isolation, plus the meaning of a bare call in terms of the confirm parameter's effect on returned blast_radius.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource ('Force-logoff Horizon session(s)') with the destructive nature flagged up front via the [WRITE] tag. It also implicitly distinguishes itself from the read-only siblings and from disconnect_vdi_session by stating it 'kicks the user' and triggers profile write-back, so an agent can tell it apart from the other session tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit targeting rules (session_ids OR user), an explicit default dry-run path, and an explicit escalation rule: show blast_radius to the user, wait for their decision, and never set confirm=True on your own. It even pre-empts a likely agent failure mode (acting on a stale earlier instruction).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

push_desktop_pool_imageA
Destructive

[WRITE] Apply the pending image to an instant-clone pool — RECREATES EVERY DESKTOP in it.

Highest blast radius in the family: the preview states affected-desktop and in-session counts before you confirm, plus blast_radius.occupancy — "determined" when those counts can be believed, "unknown" when sessions exist that cannot be attributed to any pool or farm. confirm=True schedules the apply. Show blast_radius to the user and wait for their decision. Do not set confirm=True on your own because the user asked for this earlier: they have not seen the blast radius yet. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
confirmNoFalse (default) returns the blast radius and changes nothing. True schedules the push.
pool_idYesThe pool id (from list_desktop_pools).
logoff_policyNoWAIT_FOR_LOGOFF (default) or FORCE_LOGOFF.WAIT_FOR_LOGOFF
stop_on_errorNoHalt the rolling push on the first machine error (default True).
acknowledge_unknown_occupancyNoOnly consulted when the preview reports blast_radius.occupancy == "unknown", where in_session_count is a lower bound rather than a count and confirm=True is refused. Setting it True pushes on an unverified occupancy — check list_vdi_sessions first; the acknowledgement is recorded in the audit row. Ignored when occupancy is "determined".

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and non-idempotency, but the description adds substantial behavioral detail the annotations cannot: the preview-before-confirm flow, what blast_radius.occupancy 'determined' vs 'unknown' means, that confirm=True is refused under unknown occupancy, and that actions are audited. This is genuinely additive, though it does not detail rollout timing or partial-failure recovery beyond stop_on_error.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the highest-blast-radius fact, and each sentence carries weight (scope, occupancy semantics, the confirm warning, audit). Slightly dense and parenthetical-heavy, but nothing is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a high-risk write tool with no output schema, the description explains what the preview returns (affected-desktop and in-session counts, blast_radius.occupancy), the confirm gate, and the audit trail—enough for an agent to call it safely without guessing at return shape.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter semantics the schema states only in isolation: the confirm/acknowledge_unknown_occupancy interaction and the consequence of pushing on unverified occupancy. Marginal but real added value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource (apply the pending image to an instant-clone pool) and immediately quantifies the scope with 'RECREATES EVERY DESKTOP in it.' The [WRITE] tag and destructive scope distinguish it from the read/list siblings such as get_desktop_pool or list_vdi_images.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when/when-not guidance: show blast_radius to the user and wait, do not set confirm=True autonomously even if previously requested, and check list_vdi_sessions first before acknowledging unknown occupancy. These are actionable selection and sequencing rules, not vague context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_entitlementA
DestructiveIdempotent

[WRITE] Revoke desktop-pool access from AD user/group SID(s).

Get SIDs from list_entitlements. A bare call returns blast_radius (pool identity, which principals lose access and which were not entitled) and revokes nothing; confirm=True revokes. Refused when the pool's current entitlements cannot be read. Show blast_radius to the user and wait for their decision. Do not set confirm=True on your own because the user asked for this earlier: they have not seen the blast radius yet. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
confirmNoFalse (default) returns the blast radius and changes nothing. True revokes.
pool_idYesThe desktop-pool id (from list_desktop_pools).
ad_user_or_group_idsYesAD SIDs to remove (from list_entitlements).

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, readOnlyHint=false and idempotentHint=true, but the description adds the critical two-phase semantics: a bare call computes blast_radius and revokes nothing while confirm=True performs the revocation, plus the pre-condition failure mode and the auditing behavior. It also names the blast-radius contents (pool identity, principals losing access, principals not entitled), which no annotation conveys.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the operation class and core action, then layered with sourcing, dry-run semantics, and the human-confirmation guardrail; every sentence carries operational weight. Some redundancy with the schema (SID sourcing, confirm semantics) slightly dilutes it.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although there is no output schema, the description compensates by describing the blast_radius payload and the no-op default, and it covers safety gating and failure conditions for a destructive tool. An agent has everything needed to call it correctly and safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

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 confirm's two-phase behavior and the SID/pool_id sources, so the description largely restates structured data. It adds only marginal param-level meaning, such as the blast-radius field contents, which is return information rather than parameter guidance. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Revoke desktop-pool access from AD user/group SID(s)') and prefixes the [WRITE] class, which immediately separates it from the read-side siblings list_entitlements and add_entitlement. An agent can identify the operation 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says where to get inputs (list_entitlements for SIDs, list_desktop_pools for pool_id), describes the dry-run-first workflow, states the refusal condition ('Refused when the pool's current entitlements cannot be read'), and instructs the agent not to self-confirm without showing the user the blast radius. This is a full when/when-not protocol.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_vdi_machineA
Destructive

[WRITE] Remove machine(s) from their pool — for instant clones this DELETES the backing VM.

A bare call returns blast_radius (machine ids, names, states, assigned users) and removes nothing; confirm=True removes. A machine whose state cannot be read is refused. Show blast_radius to the user and wait for their decision. Do not set confirm=True on your own because the user asked for this earlier: they have not seen the blast radius yet. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
confirmNoFalse (default) returns the blast radius and changes nothing. True removes.
machine_idsYesMachine ids to remove (from list_vdi_machines).

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true and readOnlyHint=false, but the description goes well beyond them: dry-run blast_radius contents (ids, names, states, assigned users), refusal when machine state is unreadable, the fact that the operation is Audited, and the required human-in-the-loop confirmation sequence.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The [WRITE] tag and the destructive consequence are front-loaded, followed by the flow and safety instructions. Every sentence carries operational weight — no filler, no restatement of the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description enumerates what blast_radius returns and fully covers the destructive, audited, two-phase behavior an agent must understand before calling this. 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.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema documents target, confirm, and machine_ids. The description reinforces the confirm semantics and adds workflow meaning (blast radius returned before removal, machine_ids sourced from list_vdi_machines), but most parameter meaning is already in the schema, so the added value is incremental rather than substantial.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Remove machine(s) from their pool') and adds a crucial scope detail that no sibling carries: for instant clones this DELETES the backing VM. This distinguishes it cleanly from reset_vdi_machine, get_vdi_machine, and list_vdi_machines.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly defines the two-phase flow: a bare call returns blast_radius and changes nothing, confirm=True removes. It further instructs the agent to show the blast radius, wait for the user's decision, and NOT set confirm=True on its own even if the user previously asked — a precise when/when-not rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

reset_vdi_machineA
Destructive

[WRITE] Hard-reset desktop machine(s) — the user loses unsaved state.

A bare call returns blast_radius (machine ids, names, states, assigned users) and resets nothing; confirm=True resets. A machine whose state cannot be read is refused. Show blast_radius to the user and wait for their decision. Do not set confirm=True on your own because the user asked for this earlier: they have not seen the blast radius yet. For a graceful in-guest reboot use vmware-aiops (the vCenter VM). Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
confirmNoFalse (default) returns the blast radius and changes nothing. True resets.
machine_idsYesMachine ids to reset (from list_vdi_machines).

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, but the description goes well beyond them: it discloses that users lose unsaved state, that machines whose state cannot be read are refused, that the operation is audited, and that there is a mandatory human-in-the-loop confirmation gate. This is exactly the extra context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the write marker and the destructive consequence, then the confirmation protocol, then the alternative. Dense but every sentence carries weight; the instruction about the user's earlier request is slightly wordy but is a genuinely necessary guardrail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by explaining what a bare call returns (blast_radius contents: machine ids, names, states, assigned users). Combined with the refusal rule, audit note, and alternative path, an agent has everything needed to invoke this safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, and the description reinforces the semantics of confirm (bare call = dry run, True = reset) and machine_ids (sourced from list_vdi_machines). It adds little beyond the schema for target, but the confirm/blast_radius framing gives the parameters operational meaning rather than just types.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Hard-reset desktop machine(s)') and immediately marks it as a [WRITE] operation. It also distinguishes itself from the graceful in-guest reboot path (vmware-aiops), so an agent can separate it from siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly describes the two-phase contract: a bare call returns blast_radius and resets nothing, confirm=True resets, and the agent must show blast_radius and wait for the user's decision. It even names the anti-pattern ('Do not set confirm=True on your own because the user asked for this earlier') and points to the alternative for a graceful reboot.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_ad_usersA
Read-onlyIdempotent

[READ] Resolve AD users/groups by name to their SIDs — needed to entitle a pool (add_entitlement).

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesName substring to search for.
limitNoMax principals to return (default 25).
targetNoHorizon target from config.yaml; omit to use the default.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnlyHint, idempotentHint, openWorldHint, destructiveHint=false), so the '[READ]' tag is largely redundant. The description does add the workflow context that this feeds add_entitlement, but says nothing about matching semantics, truncated results when limit is hit, or AD lookup latency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence with the read-only marker front-loaded, the action next, and the workflow purpose last. Nothing wasted and nothing buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully discloses what comes back (SIDs) and why the call matters. Minor gap: it doesn't note that results may be truncated by limit, which an agent should know before feeding SIDs into add_entitlement.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% – name, limit and target are each documented in the schema, including the default of 25 and the config.yaml origin of target. The description's 'by name' merely restates the required parameter, adding no syntax or matching detail beyond it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Resolve AD users/groups by name') and the output form ('to their SIDs'), which no sibling tool provides. An agent can distinguish this from list_entitlements or add_entitlement 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.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It names the downstream consumer explicitly ('needed to entitle a pool (add_entitlement)'), so the agent knows this is a prerequisite step rather than a standalone listing. It stops short of stating when-not to use it (e.g., if you already have a SID), so no full 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_vdi_session_messageA

[WRITE] Send a message to Horizon session(s) — e.g. "save your work, maintenance in 10 min".

Low blast radius (informational only, no session disruption), so no confirm gate. Identify by session_ids OR user. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
userNoMessage all sessions of this AD user (substring match).
targetNoHorizon target from config.yaml; omit to use the default.
messageYesThe text to display to the user(s).
session_idsNoSession ids to message.
message_typeNoINFO, WARNING, or ERROR.INFO

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes beyond the annotations by disclosing blast radius ('low', 'informational only, no session disruption'), the absence of a confirmation gate, and that calls are audited. These are real behavioral traits an agent cannot infer from destructiveHint=false/readOnlyHint=false alone. It does not describe failure behavior or what happens if no matching sessions exist.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short, front-loaded sentences led by a [WRITE] marker and an example. No filler; each clause conveys distinct information (purpose, safety, targeting, audit).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter, single-required-field write tool with no output schema, the description covers purpose, targeting, safety profile, and audit trail. Remaining details (message_type values, target config resolution) are already documented in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is already 100%, so the baseline is 3. The description adds value by clarifying the alternative targeting semantics ('session_ids OR user'), which the per-parameter schema text does not express as an either/or choice.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (send a message to Horizon sessions) and reinforces it with a concrete example ('save your work, maintenance in 10 min'). It is clearly distinguishable from destructive siblings like logoff_vdi_session or disconnect_vdi_session.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear targeting guidance ('Identify by session_ids OR user') and explains there is no confirm gate because the action is informational. It does not explicitly state when to prefer this over alternatives such as logoff, but the usage context is clear enough to act on.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_desktop_pool_enabledA
Idempotent

[WRITE] Enable or disable a desktop pool — disabling stops NEW sessions (existing keep running).

Idempotent (matching state returns a noop). A bare call returns blast_radius (pool identity, current and new enabled state) and changes nothing; confirm=True applies. A pool whose current enabled state cannot be read is refused. Show blast_radius to the user and wait for their decision. Do not set confirm=True on your own because the user asked for this earlier: they have not seen the blast radius yet. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
confirmNoFalse (default) returns the blast radius and changes nothing. True applies it.
enabledYesTrue enables; False disables.
pool_idYesThe pool id (from list_desktop_pools).

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover idempotency, read-only, open-world, and destructive flags, but the description adds materially: the partial effect (new sessions blocked, existing unaffected), the noop-on-match behavior, the blast_radius return, the refusal when state is unreadable, and that the operation is audited. That is exactly the beyond-annotations context expected, and it does not conflict with destructiveHint=false since re-enabling is possible and existing sessions continue.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the [WRITE] tag and core action, then layers idempotency, blast_radius, workflow guidance, and auditing in a logical order. Dense but nearly every sentence carries operational weight, with only mild restatement of the confirm semantics already in the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description explains what the bare call returns (pool identity, current and new enabled state), what the refusal condition is, and how the audited two-phase flow behaves. An agent has everything needed to invoke this mutation safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the schema already documents target, confirm, enabled, and pool_id in detail, including the blast-radius semantics of confirm. The description reinforces the confirm behavior for a safety-critical reason but adds little syntactic meaning the schema does not already provide, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Starts with a [WRITE] tag and names a specific verb pair (enable/disable) plus the resource (desktop pool), then adds the scope nuance that disabling stops new sessions while existing ones keep running. The pool_id reference to list_desktop_pools orients the agent relative to a sibling listing tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States exactly when to call bare (returns blast_radius, changes nothing) versus with confirm=True, prescribes the workflow (show blast_radius to the user and wait), and explicitly forbids auto-confirming. It even guards against a specific failure mode (the user asked earlier but has not seen the blast radius).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_vdi_machine_maintenanceA
Idempotent

[WRITE] Enter (enabled=True) or exit (False) maintenance mode for machine(s).

Maintenance drains the machine (no new sessions). A bare call returns blast_radius (machine ids, states, assigned users) and changes nothing; confirm=True applies. A machine whose state cannot be read is refused. Show blast_radius to the user and wait for their decision. Do not set confirm=True on your own because the user asked for this earlier: they have not seen the blast radius yet. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoHorizon target from config.yaml; omit to use the default.
confirmNoFalse (default) returns the blast radius and changes nothing. True applies it.
enabledYesTrue enters maintenance; False exits.
machine_idsYesMachine ids (from list_vdi_machines).

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false and idempotentHint=true, but the description adds material context the annotations cannot convey: maintenance drains the machine (no new sessions), the default call is a non-mutating preview, an unreadable machine state causes a refusal, and the action is audited. It does not mention whether exiting maintenance restores sessions or how partial multi-machine failures are handled, so not quite a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the [WRITE] tag and the enter/exit semantics, then the drain behavior, then the preview/confirm protocol. The final two sentences overlap somewhat ('wait for their decision' vs 'do not set confirm=True on your own'), but the redundancy is deliberate safety emphasis rather than filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive-capable, four-parameter write tool with no output schema, the description covers the mutation semantics, the non-mutating preview path, the contents of the returned blast_radius (machine ids, states, assigned users), the refusal condition, and the audit trail. Nothing an agent needs before calling it is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents target, confirm, enabled and machine_ids; the baseline is 3. The description largely restates the enabled and confirm semantics rather than adding syntax or format guidance, so it earns the baseline but no more.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+mode ('Enter (enabled=True) or exit (False) maintenance mode for machine(s)'), including the boolean that selects the direction. It is trivially distinguishable from siblings like reset_vdi_machine, remove_vdi_machine, or set_desktop_pool_enabled.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states the two-step protocol: a bare call returns blast_radius and changes nothing, confirm=True applies it, and the agent must show blast_radius to the user and wait rather than self-confirming. It even pre-empts the failure mode of confirming because the user asked earlier, which is exactly the when/when-not guidance the dimension asks for.

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.

  1. 54 tool updatesv2.4.1
    • Removedad_user_search
    • Addedadd_entitlement
    • Removedapp_pool_list
    • Addedcancel_vdi_task
    • Addeddisconnect_vdi_session
    • Removedentitlement_add
    • Removedentitlement_list
    • Removedentitlement_remove
    • Removedevent_list
    • Removedfarm_list
    • Addedget_desktop_pool
    • Addedget_desktop_pool_utilization
    • Addedget_vdi_health_summary
    • Addedget_vdi_machine
    • Addedget_vdi_session
    • Addedget_vdi_session_stats
    • Addedget_vdi_task_status
    • Removedhealth_summary
    • Removedimage_list
    • Addedlist_app_pools
    • Addedlist_desktop_pools
    • Addedlist_entitlements
    • Addedlist_farms
    • Addedlist_vdi_events
    • Addedlist_vdi_images
    • Addedlist_vdi_machines
    • Addedlist_vdi_sessions
    • Addedlogoff_vdi_session
    • Removedmachine_get
    • Removedmachine_list
    • Removedmachine_maintenance
    • Removedmachine_remove
    • Removedmachine_reset
    • Removedpool_get
    • Removedpool_list
    • Removedpool_push_image
    • Removedpool_set_enabled
    • Removedpool_utilization
    • Addedpush_desktop_pool_image
    • Addedremove_entitlement
    • Addedremove_vdi_machine
    • Addedreset_vdi_machine
    • Addedsearch_ad_users
    • Addedsend_vdi_session_message
    • Removedsession_disconnect
    • Removedsession_get
    • Removedsession_list
    • Removedsession_logoff
    • Removedsession_send_message
    • Removedsession_stats
    • Addedset_desktop_pool_enabled
    • Addedset_vdi_machine_maintenance
    • Removedtask_cancel
    • Removedtask_status
  2. 10 tool updatesv1.2.0
    • Changedentitlement_add1 field changed
      • changedInput schema / properties / confirm / description
        Previous value: -"False previews; True grants."New value: +"False (default) returns the blast radius and changes nothing. True grants."
    • Changedentitlement_remove1 field changed
      • changedInput schema / properties / confirm / description
        Previous value: -"False previews; True revokes."New value: +"False (default) returns the blast radius and changes nothing. True revokes."
    • Changedmachine_maintenance1 field changed
      • changedInput schema / properties / confirm / description
        Previous value: -"False previews; True applies."New value: +"False (default) returns the blast radius and changes nothing. True applies it."
    • Changedmachine_remove1 field changed
      • changedInput schema / properties / confirm / description
        Previous value: -"False previews; True removes."New value: +"False (default) returns the blast radius and changes nothing. True removes."
    • Changedmachine_reset1 field changed
      • changedInput schema / properties / confirm / description
        Previous value: -"False previews; True resets."New value: +"False (default) returns the blast radius and changes nothing. True resets."
    • Changedpool_push_image1 field changed
      • changedInput schema / properties / confirm / description
        Previous value: -"False previews the blast radius; True schedules the push."New value: +"False (default) returns the blast radius and changes nothing. True schedules the push."
    • Changedpool_set_enabled1 field changed
      • changedInput schema / properties / confirm / description
        Previous value: -"False previews; True applies."New value: +"False (default) returns the blast radius and changes nothing. True applies it."
    • Changedsession_disconnect1 field changed
      • changedInput schema / properties / confirm / description
        Previous value: -"False previews; True disconnects."New value: +"False (default) returns the blast radius and changes nothing. True disconnects."
    • Changedsession_logoff1 field changed
      • changedInput schema / properties / confirm / description
        Previous value: -"False previews; True logs off."New value: +"False (default) returns the blast radius and changes nothing. True logs off."
    • Changedtask_cancel1 field changed
      • changedInput schema / properties / confirm / description
        Previous value: -"False previews; True cancels."New value: +"False (default) returns the blast radius and changes nothing. True cancels."
  3. 27 tool updatesv1.1.1
    • Changedad_user_search4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit / description
        Added value: +"Max principals to return (default 25)."
      • addedInput schema / properties / name / description
        Added value: +"Name substring to search for."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedapp_pool_list4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit / description
        Added value: +"Page size (default 50)."
      • addedInput schema / properties / offset / description
        Added value: +"Page offset."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedentitlement_add5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / ad_user_or_group_ids / description
        Added value: +"AD SIDs to entitle (from ad_user_search)."
      • addedInput schema / properties / confirm / description
        Added value: +"False previews; True grants."
      • addedInput schema / properties / pool_id / description
        Added value: +"The desktop-pool id (from pool_list)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedentitlement_list5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit / description
        Added value: +"Page size (default 50)."
      • addedInput schema / properties / offset / description
        Added value: +"Page offset."
      • addedInput schema / properties / pool_id / description
        Added value: +"The desktop-pool id (from pool_list)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedentitlement_remove5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / ad_user_or_group_ids / description
        Added value: +"AD SIDs to remove (from entitlement_list)."
      • addedInput schema / properties / confirm / description
        Added value: +"False previews; True revokes."
      • addedInput schema / properties / pool_id / description
        Added value: +"The desktop-pool id (from pool_list)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedevent_list5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit / description
        Added value: +"Page size (default 50)."
      • addedInput schema / properties / offset / description
        Added value: +"Page offset."
      • addedInput schema / properties / severity / description
        Added value: +"Filter by severity (e.g. ERROR, WARNING, AUDIT_FAIL)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedfarm_list4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit / description
        Added value: +"Page size (default 50)."
      • addedInput schema / properties / offset / description
        Added value: +"Page offset."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedhealth_summary2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedimage_list3 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / base_vm_id / description
        Added value: +"Optionally scope snapshots to one base VM."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedmachine_get3 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / machine_id / description
        Added value: +"Horizon machine id (the opaque 'id' of a machine_list row, not the desktop's display name and not the vCenter VM name). A wrong id returns a 404 whose hint tells you to re-run machine_list for exact ids."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedmachine_list6 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit / description
        Added value: +"Page size (default 50)."
      • addedInput schema / properties / offset / description
        Added value: +"Page offset."
      • addedInput schema / properties / pool / description
        Added value: +"Filter to one desktop-pool id."
      • addedInput schema / properties / state / description
        Added value: +"Filter by machine state (e.g. AGENT_UNREACHABLE, ERROR)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedmachine_maintenance5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / confirm / description
        Added value: +"False previews; True applies."
      • addedInput schema / properties / enabled / description
        Added value: +"True enters maintenance; False exits."
      • addedInput schema / properties / machine_ids / description
        Added value: +"Machine ids (from machine_list)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedmachine_remove4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / confirm / description
        Added value: +"False previews; True removes."
      • addedInput schema / properties / machine_ids / description
        Added value: +"Machine ids to remove (from machine_list)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedmachine_reset4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / confirm / description
        Added value: +"False previews; True resets."
      • addedInput schema / properties / machine_ids / description
        Added value: +"Machine ids to reset (from machine_list)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedpool_get3 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / pool_id / description
        Added value: +"Horizon desktop-pool id (the opaque 'id' of a pool_list row, not the pool's display name). A wrong id returns a 404 whose hint tells you to re-run pool_list for exact ids."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedpool_list4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit / description
        Added value: +"Page size (default 50)."
      • addedInput schema / properties / offset / description
        Added value: +"Page offset."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedpool_push_image7 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / acknowledge_unknown_occupancy
        Added value: +{
        +  "default": false,
        +  "description": "Only consulted when the preview reports blast_radius.occupancy == \"unknown\", where in_session_count is a lower bound rather than a count and confirm=True is refused. Setting it True pushes on an unverified occupancy — check session_list first; the acknowledgement is recorded in the audit row. Ignored when occupancy is \"determined\".",
        +  "title": "Acknowledge Unknown Occupancy",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / confirm / description
        Added value: +"False previews the blast radius; True schedules the push."
      • addedInput schema / properties / logoff_policy / description
        Added value: +"WAIT_FOR_LOGOFF (default) or FORCE_LOGOFF."
      • addedInput schema / properties / pool_id / description
        Added value: +"The pool id (from pool_list)."
      • addedInput schema / properties / stop_on_error / description
        Added value: +"Halt the rolling push on the first machine error (default True)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedpool_set_enabled5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / confirm / description
        Added value: +"False previews; True applies."
      • addedInput schema / properties / enabled / description
        Added value: +"True enables; False disables."
      • addedInput schema / properties / pool_id / description
        Added value: +"The pool id (from pool_list)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedpool_utilization2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedsession_disconnect5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / confirm / description
        Added value: +"False previews; True disconnects."
      • addedInput schema / properties / session_ids / description
        Added value: +"Session ids to disconnect."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
      • addedInput schema / properties / user / description
        Added value: +"Disconnect all sessions of this AD user (substring match)."
    • Changedsession_get3 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / session_id / description
        Added value: +"The session id (from session_list)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedsession_list7 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit / description
        Added value: +"Page size (default 50)."
      • addedInput schema / properties / offset / description
        Added value: +"Page offset."
      • addedInput schema / properties / pool / description
        Added value: +"Exact desktop-pool / farm id."
      • addedInput schema / properties / state / description
        Added value: +"CONNECTED, DISCONNECTED, or PENDING."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
      • addedInput schema / properties / user / description
        Added value: +"Substring-match the AD user name."
    • Changedsession_logoff5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / confirm / description
        Added value: +"False previews; True logs off."
      • addedInput schema / properties / session_ids / description
        Added value: +"Session ids to log off (from session_list)."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
      • addedInput schema / properties / user / description
        Added value: +"Log off all sessions of this AD user (substring match); refuses if none match."
    • Changedsession_send_message6 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / message / description
        Added value: +"The text to display to the user(s)."
      • addedInput schema / properties / message_type / description
        Added value: +"INFO, WARNING, or ERROR."
      • addedInput schema / properties / session_ids / description
        Added value: +"Session ids to message."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
      • addedInput schema / properties / user / description
        Added value: +"Message all sessions of this AD user (substring match)."
    • Changedsession_stats2 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
    • Changedtask_cancel5 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / confirm / description
        Added value: +"False previews; True cancels."
      • addedInput schema / properties / pool_id / description
        Added value: +"The desktop-pool id."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
      • addedInput schema / properties / task_id / description
        Added value: +"The task id (from task_status)."
    • Changedtask_status4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / pool_id / description
        Added value: +"The desktop-pool id."
      • addedInput schema / properties / target / description
        Added value: +"Horizon target from config.yaml; omit to use the default."
      • addedInput schema / properties / task_id / description
        Added value: +"A specific task id; omit to list all tasks for the pool."
  4. 27 tool updatesv1.0.1
    • First observedad_user_search
    • First observedapp_pool_list
    • First observedentitlement_add
    • First observedentitlement_list
    • First observedentitlement_remove
    • First observedevent_list
    • First observedfarm_list
    • First observedhealth_summary
    • First observedimage_list
    • First observedmachine_get
    • First observedmachine_list
    • First observedmachine_maintenance
    • First observedmachine_remove
    • First observedmachine_reset
    • First observedpool_get
    • First observedpool_list
    • First observedpool_push_image
    • First observedpool_set_enabled
    • First observedpool_utilization
    • First observedsession_disconnect
    • First observedsession_get
    • First observedsession_list
    • First observedsession_logoff
    • First observedsession_send_message
    • First observedsession_stats
    • First observedtask_cancel
    • First observedtask_status

TDQS

A4.2/5.0

Scored across 27 tools

Disambiguation5/5

Each tool targets a distinct resource and action: lists vs single-gets are paired (list_desktop_pools/get_desktop_pool, list_vdi_machines/get_vdi_machine, list_vdi_sessions/get_vdi_session), write operations are unique verbs (reset, maintenance, remove, enable, push, logoff, disconnect, message), and the three reporting tools (health_summary, session_stats, utilization) are explicitly differentiated as aggregate vs per-row views. Descriptions even cross-reference ('the reporting counterpart to list_vdi_sessions'), leaving little room for misselection.

Naming Consistency4/5

Names follow a predictable snake_case verb_noun pattern (list_*, get_*, set_*, remove_*, add_*, cancel_*, search_*). Minor deviation: the 'vdi' domain token appears inconsistently (list_vdi_machines, list_vdi_sessions) while other resources drop it (list_desktop_pools, list_app_pools, list_farms).

Tool Count4/5

27 tools is on the heavy side, but each covers a genuinely distinct object (pools, farms, images, machines, sessions, entitlements, tasks, events) with no redundant duplicates. Slightly over the ideal band but justified by the broad VDI management surface.

Completeness4/5

Strong lifecycle coverage: pools (list/get/enable/push image), machines (list/get/reset/maintenance/remove), sessions (list/get/logoff/disconnect/message), entitlements (list/add/remove), plus tasks, events, and health/stats reporting. Gaps exist in provisioning (no desktop pool/farm creation or deletion, farms are read-only), which is acceptable for an operations-focused server but leaves some lifecycle dead ends.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for VMware vSphere/vCenter operations, enabling natural language control of VMs, hosts, and infrastructure.
    Apache 2.0
  • F
    license
    Not graded
    quality
    D
    maintenance
    A comprehensive MCP server for VMware vSphere management, enabling AI agents to perform VM operations, monitoring, snapshots, and reporting through a secure, Dockerized environment.
    23
    -
  • A
    license
    A
    quality
    D
    maintenance
    MCP server for Nutanix Prism Central v4 REST API, enabling AI agents to list and inspect VMs, control VM power state, list clusters, read alerts, and list subnets.
    8
    MIT