Skip to main content
Glama
J-MaFf

s2-netbox-mcp

by J-MaFf

s2-netbox-mcp

A local MCP server that exposes LenelS2 S2 NetBox NBAPI operations — persons/credentials, access levels, portals/readers/outputs, time specs, holidays, portal/reader groups, threat levels, events/activity, and partitions/UDF lists — as MCP tools usable from any MCP-compatible client (Claude, Gemini/Antigravity, etc.).

Not the open-source netboxlabs.com "NetBox" DCIM/IPAM tool. This targets LenelS2's S2 NetBox physical access-control appliance and its NBAPI (Web-Based API for S2 NetBox and S2 Global, LenelS2 doc #API-UG-14).

WARNING

This connects to a real physical security system. With the wrong configuration, an AI agent using this server could unlock doors or modify access-control data on a live building. It is read-only by default — writes and destructive operations (lock/unlock, add/modify/delete) each require their own explicit opt-in environment variable (see Write access below) — but you are responsible for what you enable and which MCP client/model you point at it. See SECURITY.md before deploying anything beyond read-only against a production controller.

Read-only by default. With no write-related environment variables set, this server registers only query/read NBAPI commands:

  • Login

  • Logout

  • GetAPIVersion

  • GetPerson

  • SearchPersonData

  • GetCardAccessDetails

  • GetCardFormats

  • GetAccessLevel(s)

  • GetAccessLevelGroup(s)

  • GetPortals

  • GetReader(s)

  • GetOutputs

  • GetTimeSpec(s)

  • GetTimeSpecGroup(s)

  • GetHoliday(s)

  • GetPortalGroup(s)

  • GetReaderGroup(s)

  • GetAccessLevelNames

  • GetPartitions

  • GetUDFLists

  • GetUDFListItems

  • GetElevators

  • GetFloors

  • PingApp

  • GetEventHistory

  • ListEvents

  • GetAccessHistory

By default, this server registers only the query/read commands listed above. It does not register any write, delete, or control operations against the controller until you explicitly opt in via the environment variables in Write access below. Among the read-only tools, two are composites, find_portals and get_unlock_window, which issue only read commands. Note there is no GetPortal (singular) command; only GetPortals (plural, paginated, no single-portal filter) exists on the real NBAPI.

Requirements

  • Node.js >= 18.17 (tested on Node 24)

  • An S2 NetBox controller reachable from wherever this server runs, with the NBAPI enabled and configured for session-login authentication (not MAC authentication — see the spec for why that's out of scope for v1)

  • A NetBox operator account with API access and read permission on the resources you want to query

Related MCP server: UniFi Network MCP Server

Setup

Two ways to get the server:

Option A — npm (no clone needed):

npm install -g s2-netbox-mcp

This installs the s2-netbox-mcp binary; point your MCP client's command at s2-netbox-mcp directly (no node dist/index.js needed).

Option B — clone and build:

npm install
npm run build

Either way, copy .env.example to .env and fill in real values (or provide the same variables directly in your shell / in the Claude Code MCP server config's env block — see below). Never commit .env — it's already gitignored.

cp .env.example .env
# edit .env

Start the server directly to sanity-check it boots (it just waits on stdio for an MCP client — Ctrl+C to stop; this also sends Logout if a session was opened):

npm start

Environment variables

Variable

Required

Default

Description

NETBOX_BASE_URL

Yes

Base URL of the NetBox controller's web interface, e.g. https://netbox.example.internal. No trailing slash or path — the client appends NETBOX_API_PATH itself.

NETBOX_USERNAME

Yes

NBAPI session-login username.

NETBOX_PASSWORD

Yes

NBAPI session-login password. Never logged, never written to any tracked file.

NETBOX_ALLOW_INSECURE_TLS

No

false

Set to true/1/yes to accept a self-signed/on-prem TLS certificate. Explicit opt-in only — any other value (including unset) keeps normal certificate verification.

NETBOX_API_PATH

No

/nbws/goforms/nbapi

The NBAPI path appended to NETBOX_BASE_URL. The default is the verified path on NetBox 6.x controllers. Only set this to override the default — e.g. to the legacy, pre-6.x path /goforms/nbapi, which returns HTTP 410 Gone on 6.x controllers (see Controller prerequisites below). A value without a leading / has one added automatically.

NETBOX_ENABLE_WRITES

No

false

Set to true/1/yes to register the write tools (see Write access below). Unset (or any other value) leaves the server strictly read-only.

NETBOX_ENABLE_DESTRUCTIVE

No

false

Set to true/1/yes, together with NETBOX_ENABLE_WRITES, to additionally register the 11 destructive tools (see Write access below).

NETBOX_EVENT_API_PATH

No

tracks NETBOX_API_PATH

Request path used only for trigger_event. Unset/empty tracks whatever NETBOX_API_PATH resolves to; a non-empty override is used verbatim (leading / added if missing) — e.g. the doc's pre-6.x Event API path /appd/nbapi, if your controller serves it separately.

NETBOX_UNLOCK_HOLIDAY_GROUPS

No

8,7,6

The holiday groups reserved for the managed unlock window, in first,middle,last segment order — see Scheduled unlock windows below. Must be 1-3 distinct integers in 1..8, comma-separated; reserve groups nothing else on the controller uses.

NETBOX_UNLOCK_NAME_PREFIX

No

MCP Unlock Window

Name prefix of every object the managed unlock window creates: the portal group (<prefix>), the time spec group (<prefix> time specs), and the per-segment holidays/time specs (<prefix> first/middle/last). 1-40 characters so the longest name (<prefix> time specs) fits the 64-character NAME limit.

NETBOX_DAILY_UNLOCK_HOLIDAY_GROUP

No

5

The single holiday group reserved for the managed daily recurring unlock window — see Scheduled daily unlock windows below. Must be a single integer in 1..8, and must not be a member of NETBOX_UNLOCK_HOLIDAY_GROUPS (the two features' reserved groups can never collide).

NETBOX_DAILY_UNLOCK_NAME_PREFIX

No

MCP Daily Unlock Window

Name prefix of every object the managed daily unlock window creates: the portal group (<prefix>), the time spec group (<prefix> time specs), and the one holiday/time spec (<prefix> schedule). 1-40 characters so the longest name fits the 64-character NAME limit.

NETBOX_LIVE_TEST_PORTALKEY

No

The PORTALKEY of the one door you designate safe to physically unlock during npm run test:live:write/npm run test:live:write:daily. Read only by those scripts, never by the server itself.

If any of the three required variables is missing, the server prints a single actionable line to stderr and exits with a non-zero status — it never prints a stack trace on startup misconfiguration.

Write access

Write/control tools exist in this server but are not registered unless you explicitly opt in:

  • NETBOX_ENABLE_WRITES=true registers the write tools listed in the "Write tools" table below — the 45 pass-through tools (creating, modifying, locking/unlocking, activating, and triggering) plus the three composite write tools set_portals_state, schedule_unlock_window, and cancel_unlock_window. Left unset (the default), the server's tool surface is exactly the read tools below — byte-for-byte the same read-only posture as before this variable existed.

  • The two unlock-window composites delete only the holidays and time specs they themselves own (named <prefix> first|middle|last — see Scheduled unlock windows), and do so without NETBOX_ENABLE_DESTRUCTIVE because those objects are server-owned; they never delete anything else.

  • NETBOX_ENABLE_DESTRUCTIVE=true, set in addition to NETBOX_ENABLE_WRITES, registers the 11 destructive tools (each description is DESTRUCTIVE:-prefixed): delete_access_level, delete_access_level_group, delete_holiday, delete_portal_group, delete_reader_group, delete_time_spec, delete_time_spec_group, remove_credential, remove_person, remove_threat_level, remove_threat_level_group. Two ordinarily non-destructive write tools also independently refuse one specific destructive-shaped call when this flag is off, regardless of whether the tool itself is registered: modify_person refuses a call with DELETED="TRUE" or PERSONPURGE="TRUE", and modify_udf_list_items refuses a call where any list item has DELETE="1" — both name NETBOX_ENABLE_DESTRUCTIVE in the error and send nothing to the controller.

  • Every write tool's description starts with WRITE: (or DESTRUCTIVE: for the 11 above), and every successful write's result text contains the literal SUCCESS followed by the controller's response data as pretty JSON (which may be {} when the command returns no data), so you can always tell a write actually happened.

  • Client-side guards (e.g. "give either READERKEY or READERGROUPKEY, not both") reject malformed calls with a tool error before any NBAPI command is issued — no partial or guessed request ever reaches the controller.

Set these the same way as the other variables — in .env (see .env.example) or your MCP server config's env block.

Controller prerequisites

Before this server can talk to your controller, on the NetBox web UI go to Configuration → Site Settings → Network Controller → Data Integration and confirm all three of these are checked:

  • Enable V2

  • Use Authentication

  • Use login username/password for authentication (requires setup privilege)

The NBAPI user account also needs a role with NBAPI read access (see the NBAPI doc's "Setting Up User Roles for the API" section) — a login that succeeds but can't read the resources this server queries will surface as FAIL or APIERROR responses per tool call. If you set NETBOX_ENABLE_WRITES, that role needs Read-Write API privilege instead (Configuration → Site Settings → User Roles → API Privilege) — Read-Only suffices only for the read tools.

Troubleshooting

  • "Login succeeds but every other command returns APIERROR 5." This is the live-observed symptom of the Use login username/password for authentication (requires setup privilege) checkbox being unticked, which puts the controller in MAC-authentication mode instead of session-login mode (MAC auth is out of scope for this server — see the spec). Login still returns SUCCESS with a session ID, but every subsequent command — including Logout — fails with APIERROR 5. Fix: tick that checkbox on the Data Integration tab. This server's client detects this exact pattern (a successful re-login followed by another APIERROR 5) and surfaces a tool error naming the checkbox directly.

  • "HTTP 410 Gone." The configured NETBOX_API_PATH is not served by this controller. NetBox 6.x serves the NBAPI at /nbws/goforms/nbapi (the default this server uses); the 2020 doc's /goforms/nbapi path is deregistered on 6.x and returns 410 for every request. If you're on a pre-6.x controller, set NETBOX_API_PATH=/goforms/nbapi explicitly; if you're on 6.x and still see this, double-check NETBOX_API_PATH isn't set to something else by mistake.

Registering with Claude Code

Add this to your Claude Code MCP server configuration (e.g. via claude mcp add-json s2-netbox-mcp '<json>', or directly in your .mcp.json / claude_desktop_config.json-style config file under mcpServers):

{
  "mcpServers": {
    "s2-netbox-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/s2-netbox-mcp/dist/index.js"],
      "env": {
        "NETBOX_BASE_URL": "https://netbox.example.internal",
        "NETBOX_USERNAME": "svc-account",
        "NETBOX_PASSWORD": "REPLACE_ME",
        "NETBOX_ALLOW_INSECURE_TLS": "false"
      }
    }
  }
}

Replace the args path with the actual absolute path to dist/index.js on your machine, and replace the env values with your real controller details (or omit env entirely and rely on a .env file next to the project if you prefer — either works, since src/index.ts loads .env via dotenv before reading process.env). Run npm run build first so dist/index.js exists.

Tools exposed

Read tools (always registered)

Tool

Wraps NBAPI command

Required params

check_connection

GetAPIVersion

get_person

GetPerson

PERSONID

search_person_data

SearchPersonData

— (all filters optional)

get_card_access_details

GetCardAccessDetails

ENCODEDNUM, CARDFORMAT

get_card_formats

GetCardFormats

get_access_level

GetAccessLevel

ACCESSLEVELKEY

get_access_levels

GetAccessLevels

— (optional STARTFROMKEY/STARTFROMNAME/WANTKEY)

get_access_level_group

GetAccessLevelGroup

ACCESSLEVELGROUPKEY

get_access_level_groups

GetAccessLevelGroups

— (optional STARTFROMKEY)

get_access_level_names

GetAccessLevelNames

— (optional PARTITIONKEY/STARTFROMNAME)

get_portals

GetPortals

— (optional STARTFROMKEY; no single-portal filter — returns each portal with its nested readers)

get_reader

GetReader

READERKEY

get_readers

GetReaders

— (optional STARTFROMKEY; no portal-id filter)

get_outputs

GetOutputs

— (optional STARTFROMKEY)

find_portals

GetPortals + GetReaders (composite)

query (search terms)

get_event_history

GetEventHistory

— (optional EVENTNAME/STARTDTTM/ENDDTTM/NEXTKEY)

list_events

ListEvents

get_access_history

GetAccessHistory

— (optional STARTLOGID/AFTERLOGID/ORDER/MAXRECORDS/ENCODEDNUM/HOTSTAMP/CARDFORMAT/OLDESTDTTM/NEWESTDTTM)

get_time_spec

GetTimeSpec

TIMESPECKEY

get_time_specs

GetTimeSpecs

— (optional STARTFROMKEY)

get_time_spec_group

GetTimeSpecGroup

TIMESPECGROUPKEY

get_time_spec_groups

GetTimeSpecGroups

— (optional STARTFROMKEY)

get_holiday

GetHoliday

HOLIDAYKEY

get_holidays

GetHolidays

— (optional STARTFROMKEY)

get_portal_group

GetPortalGroup

PORTALGROUPKEY

get_portal_groups

GetPortalGroups

— (optional STARTFROMKEY)

get_reader_group

GetReaderGroup

READERGROUPKEY

get_reader_groups

GetReaderGroups

— (optional STARTFROMKEY)

get_partitions

GetPartitions

get_udf_lists

GetUDFLists

get_udf_list_items

GetUDFListItems

UDFLISTKEY

get_elevators

GetElevators

— (optional STARTFROMKEY)

get_floors

GetFloors

— (optional STARTFROMKEY)

ping_app

PingApp

get_unlock_window

GetPortalGroups + GetPortalGroup + GetTimeSpecGroups + GetTimeSpecs + GetHolidays + GetHoliday (composite)

get_daily_unlock_window

GetPortalGroups + GetPortalGroup + GetTimeSpecGroups + GetTimeSpecs + GetHolidays (composite)

There is deliberately no get_portal (singular) tool — no such NBAPI command exists; only GetPortals (plural) does. get_card_access_details and get_access_history identify a card by ENCODEDNUM/CARDFORMAT (and get_access_history optionally by HOTSTAMP), not by PERSONID — neither command has a PERSONID parameter.

Every read tool except find_portals returns a thin JSON pass-through of that NBAPI command's response fields — no reshaping. Each tool's input schema declares exactly the documented PARAMS fields for its command — no invented, renamed, or passthrough fields. All NBAPI parameter names above are copied verbatim from the NBAPI Command Reference (see specs/archive/s2-netbox-mcp-write.md and the archived specs/archive/s2-netbox-mcp.md) — none are invented or guessed.

Seven tools are composites — they combine several NBAPI commands and reshape the result instead of passing one command through: find_portals, get_unlock_window, and get_daily_unlock_window (read-only, always registered), and set_portals_state, schedule_unlock_window, cancel_unlock_window, schedule_daily_unlock_window, and cancel_daily_unlock_window (write, registered only with NETBOX_ENABLE_WRITES). Every composite reads list commands fully paginated (following NEXTKEY until -1) and issues only commands from the closed allowlist. set_portals_state locks, unlocks (Extended Unlock until locked again), or momentarily unlocks many portals in one call — the given portalKeys or every portal — issuing one command per portal sequentially and never stopping on a single failure; its result partitions the portals into succeeded, alreadyInState (the controller's "Portal state not changed"), and failed, and is an error only when failed is non-empty. The five unlock-window tools are described under Scheduled unlock windows and Scheduled daily unlock windows below.

find_portals is for finding a door when you only know where it is. Portal names are site codes (01OF05A), and the only human-readable location text on the controller is each reader's DESCRIPTION. GetPortals doesn't return it, and neither command takes a filter. So find_portals reads every page of GetPortals and GetReaders, joins them by READERKEY, and returns the portals where every term of query appears (case-insensitive) in the portal name, a reader name, or a reader description. For example, "maintenance office" matches a reader described as BREAKROOM TO MAINTENANCE OFFICE. Each match includes its readers' names and descriptions. The result also lists portalsWithoutDescriptions: portals none of whose readers has a description, which can only be found by name. It issues no commands beyond those two.

Write tools and Destructive tools

write (needs only NETBOX_ENABLE_WRITES) and destructive (needs NETBOX_ENABLE_WRITES and NETBOX_ENABLE_DESTRUCTIVE). Every write tool's input schema declares exactly the documented PARAMS fields for its command, matching required/optional as documented — see the "Write access" section above for the gating rules and the shared SUCCESS/WRITE:/ DESTRUCTIVE: conventions.

Tool

Wraps NBAPI command

Required params

Tier

lock_portal

LockPortal

PORTALKEY

write

unlock_portal

UnlockPortal

PORTALKEY

write

momentary_unlock_portal

MomentaryUnlockPortal

PORTALKEY

write

dog_on_next_exit_portal

DogOnNextExitPortal

PORTALKEY

write

activate_output

ActivateOutput

OUTPUTKEY

write

deactivate_output

DeactivateOutput

OUTPUTKEY

write

add_time_spec

AddTimeSpec

NAME

write

modify_time_spec

ModifyTimeSpec

TIMESPECKEY

write

add_time_spec_group

AddTimeSpecGroup

NAME

write

modify_time_spec_group

ModifyTimeSpecGroup

TIMESPECGROUPKEY

write

delete_time_spec

DeleteTimeSpec

TIMESPECKEY

destructive

delete_time_spec_group

DeleteTimeSpecGroup

TIMESPECGROUPKEY

destructive

add_holiday

AddHoliday

HOLIDAYNAME, STARTDATE, ENDDATE

write

modify_holiday

ModifyHoliday

HOLIDAYKEY

write

delete_holiday

DeleteHoliday

HOLIDAYKEY

destructive

add_portal_group

AddPortalGroup

NAME, PORTALKEYS

write

modify_portal_group

ModifyPortalGroup

PORTALGROUPKEY, PORTALKEYS

write

delete_portal_group

DeletePortalGroup

PORTALGROUPKEY

destructive

add_reader_group

AddReaderGroup

NAME, READERKEYS

write

modify_reader_group

ModifyReaderGroup

READERGROUPKEY, READERKEYS

write

delete_reader_group

DeleteReaderGroup

READERGROUPKEY

destructive

add_access_level

AddAccessLevel

ACCESSLEVELNAME, TIMESPECGROUPKEY

write

modify_access_level

ModifyAccessLevel

ACCESSLEVELKEY, TIMESPECGROUPKEY

write

delete_access_level

DeleteAccessLevel

ACCESSLEVELKEY

destructive

add_access_level_group

AddAccessLevelGroup

NAME

write

modify_access_level_group

ModifyAccessLevelGroup

ACCESSLEVELGROUPKEY

write

delete_access_level_group

DeleteAccessLevelGroup

ACCESSLEVELGROUPKEY

destructive

add_person

AddPerson

LASTNAME

write

modify_person

ModifyPerson

PERSONID

write

remove_person

RemovePerson

PERSONID

destructive

add_credential

AddCredential

PERSONID, CARDFORMAT (+ ENCODEDNUM or HOTSTAMP)

write

modify_credential

ModifyCredential

PERSONID

write

remove_credential

RemoveCredential

PERSONID (+ CREDENTIALID or ENCODEDNUM/HOTSTAMP)

destructive

set_threat_level

SetThreatLevel

LEVELNAME

write

add_threat_level

AddThreatLevel

LEVELNAME

write

modify_threat_level

ModifyThreatLevel

LEVELNAME, SEQNUM

write

remove_threat_level

RemoveThreatLevel

LEVELNAME

destructive

add_threat_level_group

AddThreatLevelGroup

LEVELGROUPNAME

write

modify_threat_level_group

ModifyThreatLevelGroup

LEVELGROUPNAME, LEVELNAMES

write

remove_threat_level_group

RemoveThreatLevelGroup

LEVELGROUPNAME

destructive

trigger_event

TriggerEvent

EVENTNAME, EVENTACTION

write

insert_activity

InsertActivity

ACTIVITYTYPE

write

add_partition

AddPartition

NAME, TIMEZONE

write

switch_partition

SwitchPartition

PARTITIONKEY

write

modify_udf_list_items

ModifyUDFListItems

UDFLISTKEY, LISTITEMS

write

set_portals_state

LockPortal / UnlockPortal / MomentaryUnlockPortal per portal, after GetPortals (composite)

action (portalKeys optional; omitted = every portal)

write

schedule_unlock_window

AddHoliday/ModifyHoliday, AddTimeSpec/ModifyTimeSpec, AddTimeSpecGroup/ModifyTimeSpecGroup, AddPortalGroup/ModifyPortalGroup, plus DeleteTimeSpec/DeleteHoliday of leftover managed segments, plus reads (composite)

start, end (portalKeys, acknowledgeSideEffects, dryRun optional)

write

cancel_unlock_window

ModifyPortalGroup, DeleteHoliday, ModifyTimeSpecGroup, DeleteTimeSpec — managed objects only — plus reads (composite)

write

schedule_daily_unlock_window

AddHoliday/ModifyHoliday, AddTimeSpec/ModifyTimeSpec, AddTimeSpecGroup/ModifyTimeSpecGroup, AddPortalGroup/ModifyPortalGroup, plus reads (composite)

startDate, endDate, dailyStartTime, dailyEndTime (portalKeys, acknowledgeSideEffects, dryRun optional)

write

cancel_daily_unlock_window

ModifyPortalGroup, DeleteHoliday, ModifyTimeSpecGroup, DeleteTimeSpec — managed objects only — plus reads (composite)

write

modify_portal_group and modify_reader_group always replace the group's membership with the PORTALKEYS/READERKEYS you send — on this controller (6.2.0, verified live) an omitted or unparsed list empties the group instead of leaving it unchanged, so both tools require the complete membership.

trigger_event is unverified live on 6.x; NETBOX_EVENT_API_PATH is available to override the request path if your controller serves the Event API separately from the main NBAPI path (see the environment variable table above).

switch_partition changes the partition for every later call made by this server process, not just the caller's own next request — the NBAPI session is cached and reused, and SwitchPartition has no per-call scope.

Person / credential tools and Active Directory

If this NetBox instance syncs person/access-level data from Active Directory, any write this server makes to a synced field is silently overwritten on the next AD sync — add_person and modify_person both carry this caution in their tool descriptions. Separately, modify_person's ACCESSLEVELS has two syntaxes: a plain list of access-level name strings replaces the person's entire set of access levels, while a list of { ACCESSLEVELNAME, DELETE?, ACTDATE?, EXPDATE?, AUTOREMOVE? } blocks is additive (adds/removes individual levels without touching the rest). Mixing the two syntaxes in one call is rejected client-side before any command is sent.

Scheduled unlock windows

"Unlock these doors from start to end" is one call — schedule_unlock_window — and the controller itself enforces the schedule: no process has to stay alive to relock the doors, so the MCP host can go away the moment the call returns.

How it works (the same objects an operator creates by hand). The window is realised as a Holiday covering the dates, a Time Spec with no weekdays and only one holiday group ticked, and a Portal Group whose Unlock Time Spec is that time spec's group. A time spec with no weekdays and holiday group G ticked is active only on dates covered by a holiday in group G, so the portals unlock exactly on the window's dates and clock range. A window that spans midnight is split into up to three segments — first (start time → 23:59 on the start date), middle (00:00 → 23:59 on every date strictly between, if any) and last (00:00 → end time on the end date) — each with its own holiday + time spec pair.

Managed objects and the single-window model. Everything the tool creates is named with NETBOX_UNLOCK_NAME_PREFIX (default MCP Unlock Window): the portal group is named exactly <prefix>, the time spec group <prefix> time specs (never <prefix> — group names are unique across group types on this controller, so a portal group and a time spec group cannot share a name), and the per-segment holidays and time specs <prefix> first, <prefix> middle, <prefix> last. Names are the identity. There is one managed window at a time: scheduling a new one rewrites those same objects (modifying what exists, adding what is missing, deleting leftover segments from the previous window), and calling it twice with the same arguments is idempotent (only Modify/Get commands, same keys). The composite tools never modify or delete any object whose name is not exactly one of those; a user-created object that happens to carry one of those names is treated as managed. The apply order is fixed — resolve portals, managed time spec group, per-segment holiday + time spec, group membership, delete leftovers, managed portal group — and every step is read back and compared to the plan before the tool reports verified: true; any mismatch is a tool error describing the field. If any apply step fails, the tool rolls back by deleting every managed holiday and time spec written so far (mirroring cancel_unlock_window's cleanup) before returning the error, so no partial window is left active; the error text names the failed step, the controller's message, and what the rollback removed.

Reserved holiday groups. NetBox has exactly eight holiday groups (1–8), shared by every time spec on the controller. NETBOX_UNLOCK_HOLIDAY_GROUPS (default 8,7,6) reserves one group per segment kind (first, middle, last, in that order). Reserve groups nothing else on the controller uses. With fewer than three groups configured, only windows needing that many segments can be scheduled (one group = same-day windows only); the tool never doubles up a group, because two segments sharing one would each unlock on the other's dates.

The side-effect check and acknowledgeSideEffects. A holiday in group G suppresses, on its dates, every time spec that does not tick G — an access level whose time spec ticks only groups 1–3, say, would lose access during a window that uses group 8. Before writing anything, schedule_unlock_window reads every time spec and holiday and reports suppressedTimeSpecs (time specs other than Never and its own that lack a group the plan uses) and overlappingHolidays (non-managed holidays whose dates intersect the window — reported, never touched). If any time spec would be suppressed, the call is refused with nothing written unless acknowledgeSideEffects=true. dryRun=true returns the plan and the report without writing anything, whether or not you acknowledged. The built-in Always time spec ticks all eight groups and is never affected.

Cancelling. cancel_unlock_window first, if the managed portal group exists, points it at the built-in Never time spec group (re-sending its current portals); then, regardless of whether that portal group exists, deletes the managed holidays and empties the managed time spec group and deletes the managed time specs. The last two are best-effort: if the controller refuses them, the tool still succeeds and lists what was left under leftBehind, because once the portal group (if any) is on Never and no managed holiday exists, nothing can unlock. The managed portal group and time spec group are kept (pointing at Never / empty) and reused by the next window. The tool reports there was nothing to cancel only when no managed object of any kind — portal group, time spec group, holiday, or time spec — exists. get_unlock_window (always registered, read-only) shows the current managed state — the portal group and whether it points at the managed time spec group, that group's members (read from GetTimeSpecGroups, because GetTimeSpecGroup returns FAIL/NOT FOUND on the verified 6.2.0 controller), the managed time specs and holidays — plus the window derived from them and activeNow on the host clock.

Limits and caveats.

  • A window must end in the future and be at most 31 days long. Holidays are capped at 30 per partition, so a window whose segments would push past that is refused. portalKeys are keys only (use get_portals or find_portals to map names); an unknown key is refused before anything is written.

  • End of day on the NBAPI is 23:59 (the built-in Always uses it), and ENDTIME is inclusive through the end of that minute, so there is no midnight gap between segments of a multi-day window. A window's door relocks up to 59 seconds after the stated end minute (observed live: a window ending 08:27 relocked at 08:27:59 controller time). An end of 00:00 means "up to 23:59 of the previous day".

  • Times are the controller's local time. The MCP host is assumed to share the controller's timezone; the host clock is used only to reject windows that have already elapsed and to compute activeNow.

  • The physical unlock is not observable through the NBAPI: no read command exposes portal state, and GetEventHistory carries no Unlock/Relock activity. The tool verifies its work by reading the configuration objects back and comparing them to the plan; confirm the door itself on Monitor → Portal Status or in person.

  • set_portals_state is the immediate alternative: its UNLOCK is an Extended Unlock that lasts until LOCK, with nothing scheduling the relock.

Session handling, retry-on-expired-session, and error mapping are all automatic and match the NBAPI documentation:

  • The first tool call triggers Login; the session ID is cached and reused for every later call in the same server run.

  • If a call fails with APIERROR 5 (auth failure / expired session), the client transparently re-logs-in once and retries the original command.

  • An <APIERROR> response surfaces as a tool error like "5: There was an authentication failure."

  • A <CODE>FAIL</CODE> response surfaces as a tool error including the controller's ERRMSG text verbatim.

  • A <CODE>NOT FOUND</CODE> response (e.g. an unknown PERSONID) is returned as a normal, non-error result stating "not found" — it is not thrown as an exception.

  • SIGINT/SIGTERM trigger Logout for any active session before the process exits.

Scheduled daily unlock windows

The companion to Scheduled unlock windows above: "unlock these doors from dailyStartTime to dailyEndTime, every day from startDate through endDate" — a single partial-day window that recurs daily across a date range, which schedule_unlock_window cannot express (it models one continuous span, so a multi-day request there keeps doors unlocked overnight on the days strictly between the first and last). schedule_daily_unlock_window relocks the doors every night outside the daily window.

How it works (reusing the same mechanism). This reuses the exact holiday + time spec + portal group mechanism described above: a Holiday spanning the whole date range, a Time Spec with no weekdays and only the one reserved daily holiday group ticked, and a Portal Group whose Unlock Time Spec is that time spec's group. Because a time spec with no weekdays and holiday group G ticked is active during its STARTTIME-ENDTIME on every date covered by a holiday in group G, one holiday (covering every date in the range) paired with one partial-day time spec already expresses "the same time-of-day window, every day in the range" — no first/middle/last segment-splitting is ever needed, unlike the continuous feature, whose planner has to split a multi-day span into up to three segments precisely because a middle day needs a full 00:00-23:59 grant. This feature's plan is always exactly one segment.

Environment variables and collision safety. NETBOX_DAILY_UNLOCK_HOLIDAY_GROUP (default 5) is the single holiday group this feature reserves, and NETBOX_DAILY_UNLOCK_NAME_PREFIX (default MCP Daily Unlock Window) names its managed objects — see the environment variable table above for both. NETBOX_DAILY_UNLOCK_HOLIDAY_GROUP is validated at startup to never be a member of NETBOX_UNLOCK_HOLIDAY_GROUPS, so this feature and the continuous one always use disjoint holiday groups, and — because each feature's managed portal group and time spec group are named after its own prefix — disjoint managed-object names as well. Consequently the two features can be active at the same time: a daily window and a continuous window may both be scheduled and unlocking doors concurrently, with no shared NBAPI object between them. This also means schedule_daily_unlock_window's side-effect check does not special-case a currently-active continuous window — if its dates happen to overlap the daily plan's dates, it is reported like any other foreign time spec/holiday, which is the correct, general behaviour rather than a special case.

Managed objects and the single-daily-window model. Everything this tool creates is named with NETBOX_DAILY_UNLOCK_NAME_PREFIX: the portal group is named exactly <prefix>, the time spec group <prefix> time specs (never <prefix> — group names are unique across group types on this controller, same as the continuous feature), and the one holiday and one time spec <prefix> schedule (same name, different object tables — no collision). Names are the identity. There is one managed daily window at a time: scheduling a new one rewrites those same objects (modifying what exists, adding what is missing), and calling it twice with the same arguments is idempotent (only Modify/Get commands, same keys). The tools never modify or delete any object whose name is not exactly one of those; a user-created object that happens to carry one of those names is treated as managed. The apply order is fixed — resolve portals, managed time spec group, managed holiday, managed time spec, group membership, managed portal group — and every step is read back and compared to the plan before the tool reports verified: true; any mismatch is a tool error describing the field. If any apply step fails, the tool rolls back by deleting the managed holiday and time spec written so far (mirroring cancel_daily_unlock_window's cleanup) before returning the error, so no partial window is left active; the error text names the failed step, the controller's message, and what the rollback removed.

The side-effect check and acknowledgeSideEffects. Exactly as for the continuous feature: a holiday in the reserved daily group suppresses, on its dates, every time spec that does not tick that group. Before writing anything, schedule_daily_unlock_window reads every time spec and holiday and reports suppressedTimeSpecs (time specs other than Never and its own that lack the reserved daily group) and overlappingHolidays (non-managed holidays whose dates intersect the window — reported, never touched). If any time spec would be suppressed, the call is refused with nothing written unless acknowledgeSideEffects=true. dryRun=true returns the plan and the report without writing anything, whether or not you acknowledged.

Cancelling. cancel_daily_unlock_window first, if the managed portal group exists, points it at the built-in Never time spec group (re-sending its current portals); then, regardless of whether that portal group exists, deletes the managed holiday if it exists, and empties the managed time spec group and deletes the managed time spec if either exists. The last two are best-effort: if the controller refuses them, the tool still succeeds and lists what was left under leftBehind, because once the portal group (if any) is on Never and no managed holiday exists, nothing can unlock. The managed portal group and time spec group are kept (pointing at Never / empty) and reused by the next daily window. The tool reports there was nothing to cancel only when no managed object of any kind — portal group, time spec group, holiday, or time spec — exists. get_daily_unlock_window (always registered, read-only) shows the current managed state — the portal group and whether it points at the managed time spec group, that group's members, the one managed time spec and holiday (singular, not arrays — this feature never has more than one of each) — plus the window derived from them and activeNow on the host clock.

Limits and caveats.

  • A window must end in the future and span at most 31 days (endDate - startDate). Holidays are capped at 30 per partition, so a window whose one holiday would push past that is refused. portalKeys are keys only (use get_portals/find_portals to map names); an unknown key is refused before anything is written.

  • An overnight-crossing daily window is not supported: dailyEndTime must be strictly later than dailyStartTime (same-day time-of-day only). A request like "10 PM to 5 AM, every night" is rejected — a future extension could express this as two segments, but it is out of scope here.

  • There is no per-weekday selectivity: the whole [startDate, endDate] range unlocks every day at the given time-of-day (no "weekdays only" filtering).

  • Dates are YYYY-MM-DD and times are HH:MM, both controller-local; the same midnight-relock and host/controller-clock-assumption caveats as the continuous feature above apply here too.

  • The physical unlock is not observable through the NBAPI — confirm the door on Monitor → Portal Status or in person, exactly as above.

Testing

npm test

Runs the full unit test suite against a hand-rolled, in-memory HTTP stub — no network access and no live controller are required or contacted.

Live smoke test (optional)

npm run test:live

This calls all read tools except get_unlock_window/get_daily_unlock_window (34 of the 36 — see Tools exposed below) against a real, configured controller and prints a PASS/FAIL line per tool plus a summary, exiting non-zero if anything failed. It only runs if NETBOX_BASE_URL, NETBOX_USERNAME, and NETBOX_PASSWORD are all set (loaded from .env if present); otherwise it prints one line saying live testing was skipped and exits 0. It never prints the value of NETBOX_PASSWORD, under any circumstance, and it never issues a write/control command regardless of NETBOX_ENABLE_WRITES. npm test never runs this script and never requires .env to exist.

Live write smoke test (optional, opt-in twice)

npm run test:live:write                        # CRUD round-trips only
npm run test:live:write -- --go                # ... plus the real 2-minute unlock window
npm run test:live:write -- --go --start 14:30  # pin the unlock time (1-60 min ahead)

PowerShell: on at least one PowerShell/npm combination this silently drops flags passed after -- (npm prints npm warn Unknown cli config "--go" and the flag never reaches the script — observed live, 2026-09-15). If --go doesn't trigger phase (c), call the script directly instead: npx tsx scripts/live-check-write.ts --go.

This skips with one line and exit 0 — making no network call — unless NETBOX_BASE_URL, NETBOX_USERNAME, NETBOX_PASSWORD, NETBOX_ENABLE_WRITES=true and NETBOX_LIVE_TEST_PORTALKEY are all set. Most of the round-trips below issue deletes/removes directly against the controller (independent of the MCP server's own NETBOX_ENABLE_DESTRUCTIVE gating, which this script bypasses by calling the NBAPI client directly), so set NETBOX_ENABLE_DESTRUCTIVE=true before running it.

Otherwise it round-trips add → get → modify → get → delete for a time spec, a time spec group, a holiday, a reader group, and a portal group under the distinct prefix MCP livecheck (the portal group's unlock time spec group is Never and the holiday is in 2099, so nothing can unlock), asserting each read-back. It then round-trips a person (AddPersonGetPersonModifyPersonGetPerson) plus a credential on that person (AddCredentialGetPerson with WANTCREDENTIALIDModifyCredential with DISABLED=1 → read-back → RemoveCredential → read-back) → RemovePerson, accepting either NOT FOUND or DELETED=TRUE on the final GetPerson (never sends PERSONPURGE); an access level (AddAccessLevel with TIMESPECGROUPKEY NeverGetAccessLevelModifyAccessLevel → read-back → DeleteAccessLevel → read-back gone) plus an access level group built from a second temporary access level (AddAccessLevelGroupGetAccessLevelGroupModifyAccessLevelGroup → read-back → DeleteAccessLevelGroup, tolerating the same FAIL/ERRMSG="NOT FOUND" quirk documented for GetTimeSpecGroup against an empty collection); a threat level plus a threat level group (AddThreatLevelAddThreatLevelGroupModifyThreatLevelModifyThreatLevelGroupRemoveThreatLevelGroupRemoveThreatLevel, proven gone by a second RemoveThreatLevel failing — there is no GetThreatLevel, and SetThreatLevel is never called); InsertActivity with a timestamped USERACTIVITY record; a UDF list item round-trip via ModifyUDFListItems (or a recorded SKIPPED pass if no UDF list is configured); and GetPartitionsSwitchPartition back to the session's own partition (AddPartition is never called). It cleans up any MCP livecheck leftovers — including persons, access levels/groups, and threat levels/groups — from an aborted run, both before and after the round trips.

It then estimates the controller's clock from the newest GetAccessHistory record and refuses to run the door phase — regardless of --go — when that estimate disagrees with the host clock by more than 2 minutes; window times passed to schedule_unlock_window are always controller-local, not host-local.

With --go — pass it only after notifying the user (push notification plus a chat message giving the exact unlock and relock clock times) and receiving a go-ahead, because they observe the door — it prints a HEADS-UP line, schedules a real 2-minute unlock of the designated portal through the real schedule_unlock_window executor (unlock at now + 2 min and relock at now + 4 min, or at --start HH:MM), prints OBSERVE: portal ... should unlock at HH:MM and relock at HH:MM — confirm on Monitor → Portal Status, polls get_unlock_window every 30 s until one minute after relock, then calls cancel_unlock_window and asserts the managed portal group is on Never with no managed holiday, time spec, or time spec group member left (leftBehind is tolerated but reported). It refuses that phase if a managed window already exists (so it never replaces a real one); apart from the supervised single actions below, it never touches outputs, TriggerEvent, or portal lock/unlock actions, never prints the password, exits non-zero on any failed assertion (still cancelling the window first), and npm test never runs it.

Supervised single actions

npm run test:live:write -- --action unlock_portal
npm run test:live:write -- --action set_threat_level --value High

--action <name> [--value <v>] runs exactly one write against the designated portal (or its strike output) instead of the full flow above — skipping phases (b), (b2), and (c) entirely. It still requires NETBOX_ENABLE_WRITES=true and the credential variables (same skip line as above), but not NETBOX_ENABLE_DESTRUCTIVE, since no deletes happen. It refuses to run — exit 2, no network call — if --action is combined with --go, if the action name is unknown, or if set_threat_level's required --value is missing. It prints the exact command and params sent (never credentials), the controller's CODE/DETAILS or ERRMSG, and an OBSERVE: ... line describing what to check at the door or on Monitor; a FAIL with ERRMSG "Portal state not changed" is reported as PASS-with-note rather than a failure. Exits 0 on success or already-in-state, 1 otherwise, and unknown/invalid arguments exit 2.

Every action is reversible:

Action

Effect

Reverse

unlock_portal

UnlockPortal (Extended Unlock)

lock_portal

lock_portal

LockPortal

momentary_unlock_portal

MomentaryUnlockPortal (relocks itself)

dog_on_next_exit_portal

DogOnNextExitPortal

lock_portal

activate_output

ActivateOutput on the portal's strike output

deactivate_output

deactivate_output

DeactivateOutput on the portal's strike output

set_portals_state_unlock

the real set_portals_state (setPortalsState) tool, action UNLOCK

set_portals_state_lock

set_portals_state_lock

set_portals_state, action LOCK

set_portals_state_momentary

set_portals_state, action MOMENTARY_UNLOCK (relocks itself)

set_threat_level

SetThreatLevel LEVELNAME=<--value>

set_threat_level --value Default

trigger_event_activate

TriggerEvent EVENTNAME=<--value> EVENTACTION=ACTIVATE PARTITIONID=1

trigger_event_deactivate

trigger_event_deactivate

TriggerEvent EVENTNAME=<--value> EVENTACTION=DEACTIVATE PARTITIONID=1

activate_output/deactivate_output resolve the strike output by finding the GetOutputs entry whose NAME starts with the designated portal's NAME (e.g. portal "02OF01A" → output "02OF01A EL"), failing clearly if none is found. AddPartition is never reachable through --action, same as the rest of this script.

trigger_event_activate/trigger_event_deactivate require --value <EVENTNAME> — the name of a NetBox event that must already exist (events cannot be created via the NBAPI; create it first in the NetBox UI). This is the only live verification path for trigger_event — the full CRUD flow above never calls TriggerEvent. Both actions go through the same NetboxClient.call as every other command, so NETBOX_EVENT_API_PATH routing still applies; the script prints which URL path it used.

Live write smoke test — daily unlock window (optional, opt-in twice)

npm run test:live:write:daily         # CRUD round-trips only
npm run test:live:write:daily -- --go # ... plus the real 2-minute daily unlock window

PowerShell: see the same-named caveat under "Live write smoke test" above — if --go is silently dropped, use npx tsx scripts/live-check-write-daily.ts --go instead (verified live, 2026-09-15, on portal 02OF01A: unlock/relock confirmed in person, 16/16 steps PASS).

A sibling script to npm run test:live:write above, covering schedule_daily_unlock_window/cancel_daily_unlock_window/ get_daily_unlock_window (kept as a separate npm script rather than chained onto test:live:write so -- --go keeps reaching the script it is meant for). It skips with one line and exit 0 — making no network call — under the same gating as npm run test:live:write. Otherwise it round-trips add → get → modify → get → delete for a time spec, a time spec group, a holiday, and a portal group under the distinct prefix MCP livecheck daily (the portal group's unlock time spec group is Never and the holiday is in 2099, so nothing can unlock), asserting each read-back, then runs the same controller-clock-skew guard as test:live:write (refusing the door phase above a 2-minute skew regardless of --go).

With --go — pass it only after notifying the user and receiving a go-ahead, same as above — it prints a HEADS-UP line, schedules a real 2-minute daily unlock covering only today's date (dailyStartTime = now

  • 2 min, dailyEndTime = now + 4 min) on the designated portal through the real schedule_daily_unlock_window executor, prints an OBSERVE: ... line, polls get_daily_unlock_window every 30 s until one minute after relock, then calls cancel_daily_unlock_window and asserts the managed portal group is on Never with no managed holiday or time spec left (leftBehind is tolerated but reported). It refuses that phase if a managed daily window already exists, never touches persons, credentials, access levels, threat levels, outputs, events, partitions, or UDF lists, never prints the password, exits non-zero on any failed assertion (still cancelling the window first), and npm test never runs it.

Out of scope

  • Photo ID handling (GetPicture and photo upload)

  • StreamEvents / the persistent /appdevent/nbapi/event push feed

  • MAC-based authentication (session-login only)

  • The S2 Global API variant

  • The deprecated NBAPI commands (EditPerson, EditThreatLevel, EditThreatLevelGroup, GetAccessDataLog, GetAccessCardDetails, LoginUserName, LoginUserPassword)

  • Multiple concurrent managed unlock windows, per-window naming, or any persistence on the MCP host (there is one managed window; names are its identity)

  • Resolving portals by name in the composite tools (keys only — get_portals/find_portals map names)

  • Automatically deleting the managed portal group or time spec group on cancel (they stay, pointing at Never / empty, and are reused)

  • Any scheduler on the host (Task Scheduler, in-process timers) — the controller is the only scheduler

  • Confirmation prompts inside the server — the MCP host's permission model and the environment gates are the controls

  • Any GUI/dashboard beyond the MCP tool surface

See specs/archive/s2-netbox-mcp-write.md for the full requirements the write-tool surface was built against, and specs/archive/s2-netbox-mcp.md for the original read-only v1 spec (archived — all its acceptance criteria passed, including live verification).

Contributing

Bug reports, feature requests, and PRs are welcome — see CONTRIBUTING.md for the workflow (issue first, branch naming, PR conventions) and the physical-safety note that applies to any change touching write/destructive tools.

Security

Found a vulnerability? See SECURITY.md for how to report it privately and what the physical-safety blast radius looks like at each configuration level.

Available Tools

36 tools
check_connectionA

Confirms the server can authenticate to the configured S2 NetBox controller and returns the NBAPI version string (wraps GetAPIVersion). No parameters required.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations provided, the description carries the burden of disclosing behavior. It clearly states that the tool performs an authentication check and returns a version string, and it names the wrapped API. This is transparent for a simple read/check operation, though it does not describe failure behavior.

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 sentences, no filler, with the core purpose front-loaded. Every phrase adds useful information: what it confirms, what it returns, and the wrapped API method.

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 zero-parameter connectivity check with no output schema, the description is complete: it states the action, the target system, the return value, and the underlying API. Nothing essential 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?

The tool has zero parameters, so there is little to document. The description explicitly states 'No parameters required,' which reinforces the empty schema and removes any ambiguity for the agent.

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 ('confirms'), a specific resource ('server can authenticate to the configured S2 NetBox controller'), and a concrete outcome ('returns the NBAPI version string'). It also names the wrapped API method (GetAPIVersion), which clearly distinguishes it from the many get/list sibling 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?

The description gives clear context for when to use the tool: to verify server authentication/connectivity to the S2 NetBox controller. It does not explicitly name alternatives or exclusions, but among siblings it is the only connection-checking tool, so the usage context is clear.

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

find_portalsA

Finds portals (doors) by location or name. Portal names are site codes (e.g. 01OF05A), so this also searches each portal's reader names and reader descriptions (e.g. 'WORKSHOP TO MAINTENANCE OFFICE'). Case-insensitive; a portal matches when every whitespace-separated term appears in its name, a reader name, or a reader description. Reads every page of GetPortals and GetReaders and joins them by READERKEY. The result also lists portals with no reader description, which can only match by name.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesRequired. Search terms, e.g. "maintenance office", "electrical closet", or "01OF05".

TDQS

A4.5/5.0
Behavior5/5

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

With no annotations, the description carries the full behavioral burden, and it does so thoroughly. It discloses case-insensitive matching, the all-terms-must-match rule, the fields searched, the full-page reads of GetPortals and GetReaders, the join key READERKEY, and the special case of portals with no reader description. This is far beyond what the minimal schema or annotations would provide.

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?

Every sentence is functional: the first states what it finds, the second clarifies name semantics and examples, the third defines exact matching behavior, and the fourth explains the no-reader-description edge case. There is no filler or repetition of the schema.

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?

Given the tool's low complexity (one required parameter), no annotations, and no output schema, the description provides enough detail for an agent to invoke it correctly and understand matching behavior. It does not describe the output shape or error cases, but those are less critical for a search-style tool when the matching and result inclusion behavior are already clearly specified.

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

Parameters5/5

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

Although the schema already describes the single query parameter with examples, the description adds substantial meaning beyond it: whitespace-separated terms are treated as separate search terms, matching is case-insensitive, and every term must appear for a match. These semantic rules materially affect how an agent should construct a query, so the description earns credit above the baseline.

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 uses the specific verb 'Finds' with a clearly defined resource, 'portals (doors)' and explains exactly what is searched: name, reader names, and reader descriptions. It effectively distinguishes this tool from sibling raw-listing tools like get_portals and get_readers by describing a joined, term-based search rather than a raw retrieval. The example site codes and human-readable names make the intent unmistakable.

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 description implies the main use case: searching for portals by location or name rather than listing all portals. However, it never explicitly says when to use this tool versus siblings like get_portals or get_readers, and it gives no exclusion criteria. The agent must infer the alternative from the sibling list and context.

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

get_access_historyA

Returns historical access (grant/deny) records for optional filters (wraps NBAPI GetAccessHistory). Identifies a person by ENCODEDNUM/HOTSTAMP, not PERSONID — GetAccessHistory has no PERSONID parameter.

ParametersJSON Schema
NameRequiredDescriptionDefault
ORDERNoOptional. Sort order for returned records.
HOTSTAMPNoOptional. Restrict results to this hot-stamp number.
AFTERLOGIDNoOptional. Return records strictly after this LOGID.
CARDFORMATNoOptional. Card format of ENCODEDNUM/HOTSTAMP.
ENCODEDNUMNoOptional. Restrict results to this encoded card number.
MAXRECORDSNoOptional. Maximum number of records to return.
NEWESTDTTMNoOptional. Newest date/time to include.
OLDESTDTTMNoOptional. Oldest date/time to include.
STARTLOGIDNoOptional. Begin returning records at this LOGID.

TDQS

A4.2/5.0
Behavior4/5

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

No annotations are present, so the description carries the full burden of conveying behavior. It clearly signals a read-only operation ('Returns...records' in the first sentence), discloses that records are 'grant/deny' entries, and highlights a behavioral quirk: identification uses ENCODEDNUM/HOTSTAMP rather than PERSONID. It could add pagination or auth details, but the core behavior is transparent enough for safe invocation.

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 sentences, no filler, and the most important behavior is front-loaded. The first sentence gives purpose and the second immediately clarifies the critical identifier limitation, earning its place without waste.

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 moderately complex tool with nine optional parameters and no output schema, the description is largely complete: it states the operation, the data kind, the filtering model, and the critical identification caveat. It leaves return-structure details unspecified, but the schema and the concise behavioral description give an agent enough to call the tool correctly.

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 nine optional parameters. The description adds meaningful semantic context beyond the schema by explaining that ENCODEDNUM/HOTSTAMP are the identification keys used by the underlying NBAPI and that PERSONID is intentionally unsupported, which helps the agent reason about which parameters to supply.

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 ('Returns historical access (grant/expiry) records') and a clear resource subject to filters. It also differentiates from siblings by noting this tool identifies via ENCODEDNUM/HOTSTAMP and never PERSONID, which distinguishes it from other history-returning tools like get_event_history.

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 description implies when to use it — when you need historical access grant/deny records with optional filters. It gives one important exclusion (do not pass PERSONID; GetAccessHistory has no PERSONID parameter), but it does not name alternative sibling tools or explicitly state when a different tool should be chosen.

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

get_access_levelA

Returns the details of a single access level for a given ACCESSLEVELKEY (wraps NBAPI GetAccessLevel).

ParametersJSON Schema
NameRequiredDescriptionDefault
ACCESSLEVELKEYYesRequired. The unique ACCESSLEVELKEY of the access level to retrieve.

TDQS

A3.5/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden. It only says the operation 'returns details'; it does not disclose error behavior, permissions, whether the key must be valid, or what the returned details look like.

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 a single front-loaded sentence that states the operation, target, and required input in one line. There is no padding, and the key information is immediately visible.

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

Completeness3/5

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

For a simple single-key retrieval tool, the description plus full parameter schema is minimally sufficient for an agent to attempt a call. However, with no output schema and no annotations, the lack of return structure or error behavior leaves some uncertainty about what 'details' will be returned.

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 ACCESSLEVELKEY parameter is already documented as required and unique. The tool description mostly restates the parameter name ('for a given ACCESSLEVELKEY') without adding meaningful semantic detail 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 clearly states the action ('Returns') and the resource ('details of a single access level'), and names the required ACCESSLEVELKEY. The word 'single' also helps distinguish it from plural siblings like get_access_levels and get_access_level_names.

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?

Usage context is implied: call this when you have an ACCESSLEVELKEY and need one access level's details. However, it gives no explicit guidance about when to prefer get_access_levels or get_access_level_group, leaving selection to inference.

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

get_access_level_groupA

Returns the details of a single access level group for a given ACCESSLEVELGROUPKEY (wraps NBAPI GetAccessLevelGroup).

ParametersJSON Schema
NameRequiredDescriptionDefault
ACCESSLEVELGROUPKEYYesRequired. The unique ACCESSLEVELGROUPKEY of the access level group to retrieve.

TDQS

A3.5/5.0
Behavior3/5

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

With no annotations, the description must carry the behavioral burden. 'Returns' and 'wraps NBAPI GetAccessLevelGroup' indicate a read operation and external API coupling, but there is no explicit statement about side effects, errors, permissions, or rate limits. Adequate for a simple read, but not comprehensive.

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 with no wasted words: function first, then key, then underlying API wrapper in a parenthetical. It is well-structured and easy to scan.

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

Completeness3/5

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

For a single-key lookup, the description and schema cover the basics. However, with no output schema and no annotation, the agent still doesn't know what 'details' includes or what happens for missing/invalid keys, leaving some uncertainty.

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 ACCESSLEVELGROUPKEY as the required unique key. The description only restates that the tool retrieves the group for that key, adding no extra format, constraints, or usage details beyond the schema.

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 action ('Returns the details') on a specific resource ('a single access level group') keyed by ACCESSLEVELGROUPKEY. The word 'single' helps differentiate it from plural siblings like get_access_level_groups, though it doesn't enumerate which details are returned.

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 description implies this tool is for retrieving one group when you have a specific key, but it never names alternatives such as get_access_level_groups or states when not to use it. Usage context is present only by implication.

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

get_access_level_groupsA

Lists access level groups configured on the NetBox system (wraps NBAPI GetAccessLevelGroups).

ParametersJSON Schema
NameRequiredDescriptionDefault
STARTFROMKEYNoOptional. Pagination cursor to continue listing from a previous call.

TDQS

A3.5/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It discloses that it lists groups and wraps an API, implying a read-only operation, but does not specify pagination behavior (though a pagination cursor parameter exists), rate limits, or whether the response is a list. It does not contradict annotations because none 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?

The description is a single sentence that states the purpose and the underlying wrapper, with no waste. The core purpose is front-loaded, and the parenthetical is a useful implementation note.

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

Completeness3/5

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

For a simple list tool with one optional parameter and no output schema, the description covers the essential purpose and the pagination hint. However, it could mention that the result is a paginated list and how to use the cursor, but this is partially implied. Given the simplicity, this is adequate but not rich.

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 only parameter, STARTFROMKEY, is fully described in the schema as an optional pagination cursor. The description adds minimal value beyond that, only implying pagination via the parameter name. With 100% schema coverage, baseline 3 is appropriate.

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?

The description states a specific verb ('Lists') and resource ('access level groups configured on the NetBox system'), clearly indicating what the tool does. It also mentions it wraps an underlying API call. It does not explicitly differentiate from siblings like 'get_access_level_group' (singular) or 'get_access_levels' (plural), but the resource name is distinct enough.

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 description implies it is for listing all access level groups, which is a typical use case. There is no explicit guidance on when to use this versus alternatives like 'get_access_level_groups' (singular) or 'get_access_level_groups' (all groups), but the plural form and the phrase 'configured on the NetBox system' imply a system-wide listing. No exclusions or alternatives are named.

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

get_access_level_namesB

Lists access level names configured on the NetBox system (wraps NBAPI GetAccessLevelNames).

ParametersJSON Schema
NameRequiredDescriptionDefault
PARTITIONKEYNoOptional. Per NBAPI GetAccessLevelNames — only "0" is documented as allowed.
STARTFROMNAMENoOptional. Pagination cursor (name) to continue listing from a previous call.

TDQS

B3.3/5.0
Behavior3/5

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

With no annotations, the description carries the behavioral burden. 'Lists' and 'wraps NBAPI GetAccessLevelNames' convey a read-only enumeration and tie the tool to a known API, but the description does not disclose return shape, pagination behavior, or any constraints beyond what the schema already documents.

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 a single, front-loaded sentence that states the action, resource, and backend wrapper with no filler. It is appropriately sized for a simple list tool.

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

Completeness3/5

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

The combination of the description and the fully documented schema is sufficient to invoke the tool, but the definition is thin for tool selection: it does not explain how the returned names relate to the sibling access-level tools or what the output looks like. Given no output schema and no annotations, a bit more context would make it 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 description coverage is 100%, and both optional parameters (PARTITIONKEY, STARTFROMNAME) have meaningful descriptions, so the description does not need to repeat them. The tool description adds no additional parameter-level context, so the schema baseline of 3 is appropriate.

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?

The description clearly identifies the operation ('Lists access level names') and the resource scope ('configured on the NetBox system'), and the wrapper reference adds endpoint precision. It does not explicitly differentiate itself from siblings like get_access_levels or get_access_level, though the word 'names' implies the distinction.

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?

There is no guidance about when to call this tool versus get_access_levels, get_access_level, or get_access_level_group(s). The description only states what it does; it never provides conditions, exclusions, or alternative suggestions.

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

get_access_levelsA

Lists access levels configured on the NetBox system (wraps NBAPI GetAccessLevels).

ParametersJSON Schema
NameRequiredDescriptionDefault
WANTKEYNoOptional. Per NBAPI GetAccessLevels.
STARTFROMKEYNoOptional. Pagination cursor (key) to continue listing from a previous call.
STARTFROMNAMENoOptional. Pagination cursor (name) to continue listing from a previous call.

TDQS

A3.8/5.0
Behavior3/5

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

No annotations are provided, so the description carries the behavioral disclosure burden. 'Lists' implies a non-mutating read operation and the NetBox system scope is stated, but pagination behavior, effect of WANTKEY, and response shape are not described. This is minimally adequate for a simple list tool but not rich.

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 that front-loads the action, resource, and system context with no redundant wording. Every word earns its place.

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 low-complexity list tool with all parameters documented in the schema and no required inputs, the description is reasonably complete. The absence of an output schema and explicit pagination detail is a minor gap, but an agent can safely invoke and understand this read-only listing operation.

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 baseline baseline is 3 and the schema already explains all three optional parameters. The tool description itself adds no parameter-level meaning beyond what the schema provides.

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?

Description uses a specific verb ('Lists') and resource ('access levels configured on the NetBox system'), and names the underlying API wrapper ('NBAPI GetAccessLevels'). This makes the plural list operation distinguishable from siblings like get_access_level or get_access_level_names.

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 description conveys a clear list operation but gives no explicit when-to-use guidance, exclusions, or alternatives. With many similar access-level siblings, an agent must infer selection from the resource name rather than being told how this tool differs.

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

get_card_access_detailsA

Returns card/credential access details for a given card (wraps NBAPI GetCardAccessDetails). Identifies the card by ENCODEDNUM + CARDFORMAT, not PERSONID — GetCardAccessDetails has no PERSONID parameter.

ParametersJSON Schema
NameRequiredDescriptionDefault
CARDFORMATYesRequired. The card format of ENCODEDNUM.
ENCODEDNUMYesRequired. The encoded card number whose access details should be retrieved.
MAXRECORDSNoOptional. Maximum number of access records to return.
OLDESTDTTMNoOptional. Oldest date/time to include in the returned access records.

TDQS

A3.9/5.0
Behavior3/5

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

With no annotations, the description carries the full behavioral burden. It discloses that this wraps NBAPI GetCardAccessDetails and clarifies the identification restriction, but it does not describe the returned detail structure, error behavior, or how MAXRECORDS and OLDESTDTTM affect results.

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 sentences with no filler. The core purpose is front-loaded, and the critical identification constraint is stated immediately after, making the definition easy to parse and act on.

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

Completeness3/5

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

The parameter surface is well covered by the schema, but there is no output schema and the description does not explain what the returned access details actually contain or how optional record limiting works. For a straightforward getter this is adequate, but an agent must infer some response semantics.

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 already documents all four parameters with 100% coverage, so the baseline is 3. The description adds the useful contextual point that PERSONID is not a valid lookup path, but it does not add new meaning for MAXRECORDS or OLDESTDTTM beyond their schema descriptions.

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 begins with a specific verb+resource pair: 'Returns card/credential access details for a given card.' It further distinguishes the tool from PERSONID-based access tools by explicitly stating that the card is identified by ENCODEDNUM + CARDFORMAT and that GetCardAccessDetails has no PERSONID parameter.

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 description clearly establishes when to use this tool: when you have ENCODEDNUM and CARDFORMAT but not PERSONID for the lookup. It does not name an alternative tool for PERSONID-based access, so the routing guidance stops short of being fully explicit.

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

get_card_formatsB

Returns the card formats configured on the NetBox system (wraps NBAPI GetCardFormats). No parameters required.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.1/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden. It states 'Returns' which implies a read operation, but it does not explicitly declare it as read-only, safe, or free of side effects. It also does not disclose authentication requirements, error behavior, or any limitations. The mention of wrapping NBAPI GetCardFormats adds implementation detail but not behavioral transparency.

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 two short sentences, front-loaded with the purpose and immediately noting the absence of parameters. Every word earns its place; there is no fluff or redundancy. The structure is efficient and easy to scan.

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

Completeness2/5

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

For a tool with no annotations, no output schema, and no parameters, the description is the only source of context. It fails to describe the return format, data shape, or potential failure modes. An agent calling this tool would know it returns card formats but not what the response looks like or how to interpret it. This is a significant gap for a tool that could return a list or object with various fields.

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?

The tool has zero parameters, and the schema confirms this with an empty properties object. The description explicitly says 'No parameters required', which is clear and sufficient. The baseline for 0 parameters is 4, and the description meets that baseline by reinforcing the absence of inputs.

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?

The description clearly states the verb 'Returns' and the resource 'card formats configured on the NetBox system', which is specific and unambiguous. It also mentions the underlying NBAPI call, adding implementation context. However, it does not explicitly differentiate from the many sibling get_* tools, though the resource name itself is distinctive.

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 provides no guidance on when to use this tool versus the many sibling getters. It only states that no parameters are required, which is about invocation, not selection. There is no mention of alternatives, prerequisites, or scenarios where this tool is preferred or discouraged.

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

get_daily_unlock_windowA

Reports the managed daily recurring unlock window, if any: the managed portal group "MCP Daily Unlock Window" (key, portals, its unlock time spec group and whether that is the managed time spec group "MCP Daily Unlock Window time specs"), that group and its members (read from paginated GetTimeSpecGroups), the one managed time spec and holiday, the window derived from them, and whether it is active right now on the host clock. Read-only: issues only Get commands. No parameters required.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior4/5

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

No annotations are provided, so the description carries the burden. It explicitly discloses that the tool issues only Get commands (read-only), reads from paginated GetTimeSpecGroups, derives a window, and checks whether it is active on the host clock. This goes beyond a simple 'reports the window' statement and gives useful behavioral context.

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?

The description is a single, information-dense sentence that front-loads the main purpose and then lists the included details. It is somewhat long but every clause adds meaningful detail about scope, source, and read-only behavior, so it earns its place.

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 zero-parameter read-only reporting tool, the description is quite complete: it names the managed group, the source commands, the derived window, and the active-now check. It does not describe the output format, but with no output schema and a complex report, a bit more detail on the return shape would help; still, the core calling context is fully covered.

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?

There are zero parameters, so the schema already fully defines the input surface. The description adds value by explaining what the tool reports and how it derives the result, which is more than the empty schema provides. Baseline 4 for zero params 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 states a specific verb ('Reports') and a precise resource ('managed daily recurring unlock window'), and enumerates exactly what is included. It distinguishes itself from the sibling get_unlock_window by specifying the managed 'MCP Daily Unlock Window' group and the derived window, so an agent can tell them apart.

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 description clearly implies this is a read-only reporting tool for the managed daily unlock window and notes it reads from paginated GetTimeSpecGroups. It does not explicitly name alternatives or when-not-to-use, but the detailed scope and read-only note give clear context for when to call it.

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

get_elevatorsA

Lists elevators configured on the NetBox system (wraps NBAPI GetElevators).

ParametersJSON Schema
NameRequiredDescriptionDefault
STARTFROMKEYNoOptional. Pagination cursor to continue listing from a previous call.

TDQS

A3.8/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It clearly signals a read-only listing operation ('Lists') and names the wrapped API, but it does not describe pagination behavior, output shape, or failure modes. This is adequate for a simple non-destructive list operation, but not detailed.

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 a single, front-loaded sentence that states the action and resource without filler. The parenthetical endpoint context is useful and non-redundant.

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 list tool with one optional pagination parameter and no output schema, the description plus schema are sufficient to call it correctly. It names the resource, the wrapped endpoint, and the only parameter; enumerating return fields would be helpful but is not necessary for 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?

The schema provides 100% coverage for the only parameter, STARTFROMKEY, with a clear description ('Optional. Pagination cursor to continue listing from a previous call.'). The tool description adds no parameter-specific meaning, 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 uses a specific verb ('Lists') and a specific resource ('elevators configured on the NetBox system'), and it identifies the wrapped endpoint ('NBAPI GetElevators'). This clearly distinguishes it from sibling 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 Guidelines3/5

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

The description implies usage by naming the resource and action, so an agent can infer it is the tool for listing elevators. However, it gives no explicit guidance on when to use this tool versus alternatives such as get_readers or get_floors.

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

get_event_historyB

Returns historical NetBox events for an optional event name/date range (wraps NBAPI GetEventHistory).

ParametersJSON Schema
NameRequiredDescriptionDefault
ENDDTTMNoOptional. End of the date/time range to query (NBAPI-documented format).
NEXTKEYNoOptional. Pagination continuation cursor from a previous call.
EVENTNAMENoOptional. Restrict results to this event name.
STARTDTTMNoOptional. Start of the date/time range to query (NBAPI-documented format).

TDQS

B3.2/5.0
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It only states that it 'wraps NBAPI GetEventHistory' and returns historical events, but does not mention that it is a read-only operation, how pagination works (NEXTKEY), or what the response format is. This is minimal transparency for a tool that could have side effects or require specific handling.

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 a single, focused sentence that immediately states the tool's purpose and wraps the underlying API. It is efficient with no filler, front-loading the core action and optional filters. This is exemplary conciseness.

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

Completeness2/5

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

Given that there is no output schema and no annotations, the description should explain the return format, pagination behavior, and any limitations. It only vaguely states that it returns historical events, without describing the structure of the results, how NEXTKEY is used, or whether the operation is read-only. For a tool with four optional parameters and no other structured documentation, this is incomplete and leaves the agent guessing about expected output.

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% (all four parameters have descriptions in the schema). The description adds little beyond what the schema already provides, merely restating that event name and date range are optional. The NEXTKEY pagination parameter is not mentioned in the description, but the schema documents it. Thus, the description provides marginal additional value, warranting a baseline 3.

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?

The description clearly states that the tool returns historical NetBox events and mentions the optional event name/date range filters. It also identifies the underlying API it wraps. While it distinguishes itself by focusing on historical events, it does not explicitly contrast with sibling tools like list_events, which might offer a different scope.

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 description implies usage for retrieving historical event data by stating 'Returns historical NetBox events' and mentions optional filters. However, it does not provide explicit guidance on when to use this tool over alternatives (e.g., list_events) or any exclusions, leaving the agent to infer the appropriate context.

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

get_floorsA

Lists floors configured on the NetBox system (wraps NBAPI GetFloors).

ParametersJSON Schema
NameRequiredDescriptionDefault
STARTFROMKEYNoOptional. Pagination cursor to continue listing from a previous call.

TDQS

A3.6/5.0
Behavior3/5

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

No annotations are provided, so the description carries the behavioral burden. 'Lists' clearly signals a read-only operation, and 'wraps NBAPI GetFloors' gives implementation context. However, it does not mention pagination behavior, return format, or potential performance concerns, though the STARTFROMKEY parameter in the schema partially addresses 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?

The description is a single focused sentence that front-loads the core action and resource. It contains no filler or redundant explanation, making it easy for an agent to parse quickly.

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 low-complexity list tool with one optional parameter and no output schema, the description plus the parameter schema is largely sufficient. It could mention pagination explicitly in the prose, but the schema already documents that behavior, so the main gap is minor.

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 fully describes the only parameter, STARTFROMKEY, as an optional pagination cursor, so the schema carries the semantic weight. The description adds no parameter-level detail, but with 100% schema coverage, the baseline of 3 is appropriate.

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?

The description uses a specific verb ('Lists') with a clear resource ('floors') and scope ('configured on the NetBox system'), so an agent can understand the tool's function immediately. It doesn't explicitly distinguish from sibling tools, but no sibling tool appears to target floors, so the differentiation need is low.

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 description implies the tool should be used when the agent needs to list floors, but it gives no explicit guidance about when to prefer this tool over alternatives or when not to use it. There are no exclusions or alternative tool references, but the purpose is straightforward enough that the usage is reasonably inferable.

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

get_holidayA

Returns the details of a single holiday for a given HOLIDAYKEY (wraps NBAPI GetHoliday).

ParametersJSON Schema
NameRequiredDescriptionDefault
HOLIDAYKEYYesRequired. The unique HOLIDAYKEY of the holiday to retrieve.

TDQS

A4/5.0
Behavior3/5

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

With no annotations, the description carries the burden of behavioral disclosure. It states the operation is a retrieval ('returns'), which implies a read, and notes it wraps NBAPI GetHoliday. However, it does not describe behavior for an invalid or missing HOLIDAYKEY or the response structure.

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 communicates the tool's purpose, scope, and key parameter without wasted words. The parenthetical wrapper note is short and adds context.

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 single-parameter getter, the description is sufficient for an agent to select and invoke it correctly. The only gaps are the lack of an explicit not-found behavior and return format, but neither blocks correct use for the common case.

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 both the schema and description convey that HOLIDAYKEY is required and unique. The description adds no additional format, source, or usage detail beyond the schema, so the baseline of 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, resource, and selection criterion: 'returns the details of a single holiday' for a HOLIDAYKEY. This clearly distinguishes it from the sibling get_holidays, which presumably returns multiple holidays.

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?

Makes clear this is the tool to use when you have a specific HOLIDAYKEY and need one holiday. It does not explicitly name get_holidays as the alternative for listing many holidays, so some inference is required.

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

get_holidaysA

Lists holiday keys configured on the NetBox system (wraps NBAPI GetHolidays). Returns a comma-separated key string, not a list of records — use get_holiday per key for details.

ParametersJSON Schema
NameRequiredDescriptionDefault
STARTFROMKEYNoOptional. Pagination cursor to continue listing from a previous call.

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations provided, the description carries the full disclosure burden. It usefully reveals a non-obvious behavior: the result is a comma-separated key string rather than a list of record objects. It does not mention pagination behavior, error cases, or response formatting beyond the key string, but the most important gotcha is disclosed.

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 sentences, no filler. The core purpose is front-loaded, and the critical return-format caveat is stated immediately after. Every clause earns its place.

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 read-style tool with one optional parameter and no output schema, the description covers purpose, return format, and the path to richer detail via get_holiday. It could still clarify how STARTFROMKEY affects the returned string, but the schema covers that parameter. Nothing essential for invoking the tool 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 the schema already documents STARTFROMKEY as an optional pagination cursor. The description adds no further parameter-level meaning beyond implying the tool returns keys; it neither clarifies cursor format nor explains continuation behavior. This matches the baseline for high schema coverage.

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 ('Lists'), a specific resource ('holiday keys'), and the system ('NetBox'), and distinguishes itself from get_holiday by clarifying it only returns keys. The parenthetical 'wraps NBAPI GetHolidays' adds a useful API mapping without ambiguity.

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 description explicitly routes the agent to get_holiday for per-key details, which is a clear alternative. It does not elaborate on when not to use the tool or contrast with other list-type siblings, but the main selection condition (need keys vs details) is present and actionable.

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

get_outputsB

Lists auxiliary outputs configured on the NetBox system (wraps NBAPI GetOutputs).

ParametersJSON Schema
NameRequiredDescriptionDefault
STARTFROMKEYNoOptional. Pagination cursor to continue listing from a previous call.

TDQS

B3.3/5.0
Behavior2/5

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

Annotations are absent, so the description carries full responsibility for behavioral disclosure. It only says 'lists auxiliary outputs', which is a read operation, but does not mention safety implications (e.g., read-only nature, no side effects), pagination behavior beyond the parameter, or any potential errors. For a list operation, this is a minor gap, but given the lack of annotations, the description should have at least indicated it is non-destructive and returns a list. The reference to 'wraps NBAPI GetOutputs' adds some context but does not fully disclose behavior.

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 a single, concise sentence that states the purpose and references the underlying API. It is appropriately sized and front-loaded with the core action. No wasted words.

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

Completeness3/5

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

Given the tool's simplicity (one optional parameter, no output schema, no nested objects), the description plus the schema is nearly complete. However, the lack of any behavioral transparency (e.g., that the operation is read-only and returns a list of outputs) and absence of usage guidance leave minor gaps. With annotations absent, a bit more context would be expected, but for a simple list tool, the current state is adequate.

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 description coverage is 100%, with the single parameter STARTFROMKEY fully described as a pagination cursor. The description does not add further meaning beyond that, so the baseline of 3 applies because the schema already provides sufficient semantics. The description's reference to 'auxiliary outputs' does not directly explain the parameter, but schema coverage meets the burden.

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?

The description clearly states the tool lists auxiliary outputs on the NetBox system, a specific verb-resource combination. It also references the wrapped NBAPI endpoint, which helps identify the underlying operation. However, it does not explicitly differentiate from siblings beyond indicating 'auxiliary outputs' as a distinct resource, which is sufficient given the naming.

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 description does not explicitly state when to use this tool versus alternatives, but the resource name 'auxiliary outputs' is specific enough that an agent can infer it is for that resource only. It does not mention any context like pagination handling, but the single parameter's schema covers that. No exclusions or alternatives are given, so it's adequate but not explicit.

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

get_partitionsA

Lists partitions configured on the NetBox system (wraps NBAPI GetPartitions). No parameters required.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4/5.0
Behavior3/5

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

With no annotations provided, the description carries the burden of behavioral disclosure. 'Lists' implies a read-only operation, and the wrapper reference adds context, but the description does not mention return format, pagination, error behavior, or access requirements. It is adequate but not rich.

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 a single concise sentence that leads with the core action and resource, then adds the wrapper context and parameter note. Every word earns its place.

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 no-argument list tool, the description is nearly complete: it states what is listed and that no parameters are needed. It does not describe the output shape, but the absence of an output schema and the low complexity make this a minor 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?

There are zero parameters, so the baseline is 4. The description explicitly states 'No parameters required,' which reinforces the empty input schema even though the schema already communicates this.

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 uses a specific verb ('Lists') and a clear resource ('partitions configured on the NetBox system'), and it also names the wrapped API ('NBAPI GetPartitions'). This makes the tool's purpose unambiguous and distinct from the sibling 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 Guidelines3/5

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

The description implies usage through its clear purpose, but it does not explicitly state when to use this tool versus alternatives or when not to use it. Mentioning that no parameters are required helps, but there is no explicit routing guidance.

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

get_personA

Returns the full person record for a given PERSONID (wraps NBAPI GetPerson).

ParametersJSON Schema
NameRequiredDescriptionDefault
PERSONIDYesRequired. The unique PERSONID of the person record to retrieve.
ALLPARTITIONSNoOptional. Per NBAPI GetPerson.
WANTCREDENTIALIDNoOptional. Include CREDENTIALID values on returned access cards.
ACCESSLEVELDETAILSNoOptional. Include full access level details in the response.

TDQS

A3.5/5.0
Behavior3/5

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

'Returns' makes the read-only nature reasonably clear, and 'wraps NBAPI GetPerson' adds a useful reference. However, with no annotations provided, the description carries the full behavioral burden and does not mention error behavior, authentication needs, or response format.

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 with no filler; the core behavior and API wrapper are stated upfront. It earns its place entirely.

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

Completeness3/5

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

For a get-by-ID tool with a complete parameter schema, this is adequate but minimal. It omits usage alternatives, return-shape expectations, and any edge cases, which matters more since there is no output schema and no annotations.

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 all four parameters are already documented in the schema. The description adds little beyond naming PERSONID and calling the result 'full,' which is acceptable but not additive.

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?

The description uses a specific verb ('Returns') and resource ('full person record') keyed by PERSONID, so an agent can tell this is a direct lookup tool. It does not explicitly differentiate it from sibling search_person_data, though the PERSONID-based lookup strongly implies it.

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 usage context is only implied: an agent would call this when it has a PERSONID and needs the full person record. It provides no explicit when-not guidance or comparison to alternatives like search_person_data.

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

get_portal_groupB

Returns the details of a single portal group for a given PORTALGROUPKEY (wraps NBAPI GetPortalGroup).

ParametersJSON Schema
NameRequiredDescriptionDefault
PORTALGROUPKEYYesRequired. The unique PORTALGROUPKEY of the portal group to retrieve.

TDQS

B3.1/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden. It states 'returns the details' but does not disclose whether this is a read-only operation, potential error conditions (e.g., invalid key), or what happens if the key does not exist. The parenthetical about wrapping NBAPI hints at an API call but adds no behavioral clarity. A simple getter still needs explicit assurance of non-mutation or side-effect-free behavior, which is absent.

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?

The description is a single, front-loaded sentence that gets to the point. However, the parenthetical '(wraps NBAPI GetPortalGroup)' is an implementation detail that does not help the agent decide when to call the tool and may add noise. Removing it would improve conciseness, but the overall structure is efficient.

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

Completeness2/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 leaves the return structure undefined. Saying 'details' is vague; an agent cannot anticipate what fields will be returned (e.g., group name, members, permissions). For a getter, the description should at least hint at the typical content of a portal group or indicate it returns the full object. Given the simplicity of the tool, the description is inadequate for an agent to reason about downstream usage.

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 the parameter is fully documented in the schema. The description's phrase 'for a given PORTALGROUPKEY' adds no additional meaning beyond the schema's 'The unique PORTALGROUPKEY of the portal group to retrieve.' The description neither clarifies format, constraints, nor relationship to other parameters (there are none). Baseline 3 is appropriate when the schema already explains the 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 clearly states the verb 'returns', the resource 'portal group', and the scope 'single' with a specific key. It differentiates from the plural sibling 'get_portal_groups' by emphasizing 'single' and 'given PORTALGROUPKEY'. The mention of wrapping NBAPI is implementation detail but does not obscure the purpose.

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?

There is no guidance on when to use this tool versus alternatives. The description does not mention conditions such as 'use this when you have a specific portal group key' or contrast with get_portal_groups or find_portals. The agent must infer from the name and the key requirement, which is insufficient for a tool set with many similar getters.

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

get_portal_groupsA

Lists portal groups configured on the NetBox system (wraps NBAPI GetPortalGroups).

ParametersJSON Schema
NameRequiredDescriptionDefault
STARTFROMKEYNoOptional. Pagination cursor to continue listing from a previous call.

TDQS

A3.5/5.0
Behavior2/5

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

No annotations are provided, so the description must disclose behavioral traits. It only states that it lists portal groups, but does not mention whether it is read-only, how pagination works (despite the STARTFROMKEY parameter), what the response structure is, or any error conditions. The cryptic 'wraps NBAPI GetPortalGroups' adds no behavioral clarity.

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 a single, focused sentence that front-loads the purpose. There is no extraneous content, and it earns its place by stating exactly what the tool does.

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

Completeness3/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 should convey what the response contains and any usage caveats. It says 'lists portal groups' which implies a list of portal group objects, but it does not mention the pagination mechanism or how to interpret the STARTFROMKEY parameter in practice. Given the simplicity of the tool (one optional param), this is minimally adequate but leaves some gaps.

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% for the single parameter STARTFROMKEY, and its description already explains it as a pagination cursor. The tool description adds no additional meaning beyond the schema, so a baseline score of 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 clearly states the action ('Lists') and the resource ('portal groups configured on the NetBox system'), and the plural form distinguishes it from the sibling tool get_portal_group (singular). The mention of wrapping NBAPI GetPortalGroups adds specificity without confusion.

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 purpose implies use when a list of portal groups is needed, but there is no explicit guidance on when to choose this over get_portal_group or other sibling tools like get_portals. No exclusions or alternative routing are provided.

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

get_portalsA

Lists portals (doors) configured on the NetBox system, each with its nested readers (wraps NBAPI GetPortals, paginated via STARTFROMKEY/NEXTKEY — there is no single-portal filter).

ParametersJSON Schema
NameRequiredDescriptionDefault
STARTFROMKEYNoOptional. Pagination cursor — the NEXTKEY from a previous call, to continue listing.

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral burden. It discloses the underlying NBAPI call, pagination via STARTFROMKEY/NEXTKEY, nested-reader inclusion, and the absence of single-portal filtering. It does not mention auth, rate limits, or response fields, but the core behavior is transparent.

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

Conciseness5/5

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

A single dense sentence conveys the resource, scope, nested structure, implementation wrapper, pagination mechanism, and a key limitation. There is no filler and the most important facts are front-loaded.

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 paginated list with no required parameters and no output schema, the description covers the scope, nested readers, pagination behavior, and the absence of a single-portal filter. Sibling tool names help fill the alternative-use context. Minor omissions like auth or exact return fields do not prevent 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?

The only parameter, STARTFROMKEY, is already fully documented in the schema (100% coverage). The description reinforces that pagination uses STARTFROMKEY/NEXTKEY but adds little beyond the schema. Baseline 3 is appropriate since the schema does the heavy lifting.

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 uses a specific verb-resource pair ('Lists portals configured on the NetBox system') and immediately adds distinguishing detail: each portal comes with nested readers, it wraps NBAPI GetPortals, and there is no single-portal filter. This clearly separates it from siblings like find_portals or get_portal_group.

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 clearly communicates that this is a paginated list operation and explicitly warns that there is no single-portal filter, so an agent knows not to use it to fetch a specific portal. It does not name an alternative tool directly, but the sibling list makes that inferable.

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

get_readerA

Returns the details of a single reader for a given READERKEY (wraps NBAPI GetReader).

ParametersJSON Schema
NameRequiredDescriptionDefault
READERKEYYesRequired. The unique READERKEY of the reader to retrieve.

TDQS

A3.8/5.0
Behavior3/5

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

There are no annotations, so the description carries the full behavioral disclosure burden. It does state the operation ('Returns the details') and identifies the underlying backend call ('wraps NBAPI GetReader'), which adds useful context, but it does not mention read-only behavior, error conditions, or output format.

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 a single well-structured sentence that front-loads the core action, target, and required input. There is no superfluous text or repetition of schema details.

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?

This is a simple one-parameter getter, and the description combined with the schema provides enough information to invoke the tool correctly. However, since there is no output schema, the description could be slightly more explicit about what fields or object shape are contained in the returned 'details'.

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 parameter READERKEY is already fully documented in the schema. The description repeats the parameter name but does not add any semantic detail beyond what the schema provides, keeping this at the baseline score of 3.

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 the specific action ('Returns the details') and the target resource ('a single reader') with the required identifier READERKEY. The singular 'single reader' clearly distinguishes this from the sibling get_readers tool without needing to inspect schemas.

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 description implies the usage context: you call this when you have a READERKEY and need one reader's details. However, it does not explicitly state when to prefer it over get_readers or any other sibling, nor does it mention alternative tools for reader-related queries.

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

get_reader_groupB

Returns the details of a single reader group for a given READERGROUPKEY (wraps NBAPI GetReaderGroup).

ParametersJSON Schema
NameRequiredDescriptionDefault
READERGROUPKEYYesRequired. The unique READERGROUPKEY of the reader group to retrieve.

TDQS

B3.4/5.0
Behavior2/5

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

With no annotations, the description carries the full burden. It only says 'returns the details' without specifying the nature of the operation (likely read-only), potential error conditions, or what 'details' encompass. It does mention wrapping NBAPI GetReaderGroup, but that adds no behavioral clarity. The description is too thin to disclose meaningful behavior.

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 a single, focused sentence with no extraneous content. The key fact (returns a single reader group by key) is front-loaded, and the parenthetical implementation detail is supplementary without adding bulk.

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

Completeness2/5

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

For a getter tool with no output schema and no annotations, the description leaves significant gaps: it does not define what 'details' are returned, does not indicate any error behavior, and does not clarify that the operation is read-only. Given the simple single-parameter interface, some of this is inferred, but the absence of return format and usage guidance makes it incomplete for an agent to call 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% for the single parameter READERGROUPKEY, so the schema fully documents the parameter. The description merely restates 'given READERGROUPKEY' without adding format, constraints, or examples beyond what the schema provides, meeting the baseline.

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 clearly states it returns details of a single reader group for a given READERGROUPKEY, and explicitly uses 'single' to distinguish from the plural sibling get_reader_groups. The verb 'returns' and resource 'reader group' are specific and unambiguous.

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?

Usage is implied by 'single' and 'given READERGROUPKEY', but the description does not explicitly state when to use this tool over alternatives like get_reader_groups or get_reader. No exclusions or conditions are provided, leaving selection to inference.

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

get_reader_groupsB

Lists reader groups configured on the NetBox system (wraps NBAPI GetReaderGroups).

ParametersJSON Schema
NameRequiredDescriptionDefault
STARTFROMKEYNoOptional. Pagination cursor to continue listing from a previous call.

TDQS

B3.3/5.0
Behavior2/5

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

No annotations are provided, so the description must carry the behavioral disclosure burden. It only says 'Lists...' which implies read-only, but does not explicitly state safety, pagination behavior, permissions, or side effects. The pagination cursor is mentioned only in the schema, not the description, leaving the agent without important behavioral context.

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?

The description is a single sentence that front-loads the main action. The parenthetical about wrapping NBAPI adds some implementation detail that may not be essential for an agent, but it does not bloat the description. Overall concise and well-structured.

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

Completeness2/5

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

With no output schema, no annotations, and only one optional parameter, the description still leaves gaps: it does not indicate what the response contains, whether pagination is required for large lists, or how this tool relates to the singular get_reader_group. The description is too minimal to be fully complete for an agent selecting and invoking the 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 description coverage is 100%: the sole parameter STARTFROMKEY has a clear description ('Optional. Pagination cursor to continue listing from a previous call.'). The tool description adds no additional semantic value beyond the schema, so the baseline score of 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 clearly states the action ('Lists'), the resource ('reader groups'), and the system ('NetBox'). It distinguishes itself from sibling tools like get_reader_group (singular) by the plural form, and the parenthetical identifies the underlying API. This is a specific and unambiguous purpose.

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 description implies usage through the plural 'reader groups' (listing all) but does not explicitly state when to use this instead of get_reader_group or related tools. No alternatives or exclusion criteria are mentioned, so the guidance is only implicit.

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

get_readersA

Lists readers configured on the NetBox system (wraps NBAPI GetReaders). There is no portal-id filter — use get_portals to see each reader nested under its portal.

ParametersJSON Schema
NameRequiredDescriptionDefault
STARTFROMKEYNoOptional. Pagination cursor to continue listing from a previous call.

TDQS

A4.2/5.0
Behavior3/5

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

With no annotations, the description must carry the behavioral burden. 'Lists' and the NBAPI wrapper make the read-only nature reasonably clear, and the 'no portal-id filter' constraint is useful. However, it does not describe pagination behavior or response format beyond what the schema already provides, so behavioral disclosure is adequate but not rich.

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 concise sentences with no wasted words. The core purpose is front-loaded, followed by the key limitation and the sibling alternative, making it highly scannable for an agent.

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 one-parameter, no-output-schema tool, the description covers what the tool does, its limitation, and the relevant alternative. The missing explicit statement about what the returned reader list contains is a minor gap, but the description is otherwise sufficient 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 coverage is 100% for the only parameter, STARTFROMKEY, whose description already explains it as a pagination cursor. The tool description adds no parameter-level meaning beyond that, so the baseline of 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 uses a specific verb ('Lists') and resource ('readers configured on the NetBox system'), making the purpose immediately clear. It also distinguishes itself from get_portals by explicitly noting the absence of a portal-id filter.

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?

The description directly tells the agent when to use this tool vs. an alternative: use get_readers for a flat reader list, and use get_portals to see readers nested under a portal. This is explicit routing with no ambiguity.

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

get_time_specA

Returns the details of a single time spec for a given TIMESPECKEY (wraps NBAPI GetTimeSpec).

ParametersJSON Schema
NameRequiredDescriptionDefault
TIMESPECKEYYesRequired. The unique TIMESPECKEY of the time spec to retrieve.

TDQS

A3.8/5.0
Behavior3/5

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

With no annotations provided, the description carries the full burden. It states the tool 'returns' details, implying a read operation, but does not disclose error behavior, return format, or any side effects. For a simple get operation, this is minimal but not misleading; it lacks depth but does not contradict anything.

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 a single, focused sentence that front-loads the purpose and input. It contains zero fluff and efficiently conveys the tool's function and the required key. This is a model of conciseness.

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 single-parameter retrieval tool with no output schema and no annotations, the description is adequate. It tells what it does and the input. It does not describe the returned fields or error cases, but given the simplicity and the sibling context, this is sufficient for an agent to use it correctly. The only gap is the vague 'details' without specifics.

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 parameter TIMESPECKEY is already documented in the schema. The tool description adds no extra semantics, format, or examples beyond what the schema provides. This meets the baseline of 3 for schema-covered parameters.

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 clearly states the verb 'Returns', the resource 'details of a single time spec', and the input key TIMESPECKEY. It distinguishes itself from siblings like get_time_specs (plural) and get_time_spec_group(s) by indicating it operates on a single time spec. The wrapper reference adds credibility without confusion.

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 usage is implied: call when you have a TIMESPECKEY to retrieve its details. However, the description does not explicitly mention when not to use it or point to alternatives like get_time_specs for listing. It provides no exclusions or routing guidance, falling into the 'implied usage' category.

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

get_time_spec_groupB

Returns the details of a single time spec group for a given TIMESPECGROUPKEY (wraps NBAPI GetTimeSpecGroup).

ParametersJSON Schema
NameRequiredDescriptionDefault
TIMESPECGROUPKEYYesRequired. The unique TIMESPECGROUPKEY of the time spec group to retrieve.

TDQS

B3.1/5.0
Behavior2/5

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

No annotations are provided, so the description bears full responsibility for behavioral disclosure. It only says 'returns the details' and wraps NBAPI GetTimeSpecGroup, but does not indicate whether the operation is read-only, what happens if the key is invalid, or the format of the returned details. This is a significant gap for a tool in a system with many similar retrieval tools.

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 a single, front-loaded sentence with no extraneous words. It states the action and the key input immediately, and the NBAPI reference adds context without bloating the text. This is ideal conciseness for a simple retrieval tool.

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

Completeness3/5

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

Given the simplicity (one parameter, no output schema) the description covers the basic call, but it lacks differentiation from the many similar sibling tools (e.g., get_time_spec_groups, get_time_specs) and does not mention error behavior or the contents of the returned details. It is adequate but not fully complete for an agent navigating a large toolset.

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 the TIMESPECGROUPKEY parameter fully. The description merely restates that it uses the key without adding any new meaning, such as accepted formats or constraints. Baseline 3 is appropriate since the schema carries the semantic load.

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?

The description clearly states it returns the details of a single time spec group for a given key, using a specific verb and resource. It does not explicitly differentiate from sibling tools like get_time_spec_groups (plural) or get_time_spec, but the word 'single' and the key parameter imply a distinct retrieval purpose.

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 guidance on when to use this tool versus alternatives. It only states the input requirement (TIMESPECGROUPKEY) but does not mention when to choose this over get_time_spec_groups for listing, or how it differs from get_time_spec. An agent must infer usage from the name alone.

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

get_time_spec_groupsA

Lists time spec groups configured on the NetBox system (wraps NBAPI GetTimeSpecGroups).

ParametersJSON Schema
NameRequiredDescriptionDefault
STARTFROMKEYNoOptional. Pagination cursor to continue listing from a previous call.

TDQS

A3.6/5.0
Behavior3/5

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

The description discloses it wraps NBAPI GetTimeSpecGroups and states the list scope, but does not mention pagination behavior, result shape, or any side effects. With no annotations, the description carries some burden, but for a read-only list operation this is minimally adequate.

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 one concise sentence with the key action front-loaded. The parenthetical wrapper context is relevant and does not add unnecessary clutter.

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?

Given the low complexity, one optional parameter fully documented in the schema, and no output schema, the description covers the main invocation context. It does not explicitly elaborate on return format, but 'Lists' plus the parameter description is likely sufficient for correct use.

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 has 100% coverage with a clear description for STARTFROMKEY, so the description does not need to compensate. The description adds no parameter-level meaning beyond what the schema already provides.

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 uses a specific verb 'Lists' with a clear resource 'time spec groups' and a scoping phrase 'configured on the NetBox system'. The plural form also distinguishes it from sibling get_time_spec_group, making the tool's purpose unambiguous.

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?

No when-to-use guidance is provided and no alternatives are mentioned, even though siblings like get_time_spec_group and get_time_specs exist. The agent must infer the appropriate selection solely from the tool name and basic description.

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

get_time_specsA

Lists time specs configured on the NetBox system (wraps NBAPI GetTimeSpecs).

ParametersJSON Schema
NameRequiredDescriptionDefault
STARTFROMKEYNoOptional. Pagination cursor to continue listing from a previous call.

TDQS

A3.7/5.0
Behavior3/5

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

There are no annotations, so the description carries the behavioral burden. 'Lists' and 'wraps NBAPI GetTimeSpecs' imply a read-only retrieval operation, but the description does not explicitly state safety, permissions, pagination behavior, or what the response contains. It provides useful context but leaves notable behavioral details unspecified.

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 communicates the resource, action, and underlying API wrapper with no filler. The essential information is front-loaded and every phrase earns its place.

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

Completeness3/5

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

This is a simple list operation with one optional, well-documented parameter, so it is not severely underserved. However, with no output schema and no annotation coverage, the description leaves return-value structure and the full pagination flow unspecified, making it adequate but not 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 description coverage is 100%: the only parameter, STARTFROMKEY, is already documented as an optional pagination cursor. The description does not add any parameter-level meaning beyond this, so the baseline score of 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 uses a specific verb ('Lists') and a clear resource ('time specs configured on the NetBox system'), and the plural 'time specs' plus the mention of the system scope distinguishes it from singular/group sibling tools like get_time_spec and get_time_spec_group. It also anchors the behavior to a concrete NBAPI operation.

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 description implies the tool is for listing all time specs configured in NetBox, so an agent can infer when to call it. However, it does not explicitly contrast it with sibling tools such as get_time_spec or get_time_spec_groups, nor does it state when to prefer one over the other.

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

get_udf_list_itemsA

Returns the items of a single UDF list for a given UDFLISTKEY (wraps NBAPI GetUDFListItems).

ParametersJSON Schema
NameRequiredDescriptionDefault
UDFLISTKEYYesRequired. The unique UDFLISTKEY of the UDF list to retrieve.

TDQS

A3.7/5.0
Behavior3/5

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

With no annotations, the description carries the behavioral burden. It does disclose that the call is a retrieval ('Returns') and that it wraps NBAPI GetUDFListItems, but it says nothing about error behavior, response shape, or whether any side effects 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?

A single sentence with no filler, front-loading the core action and resource before the NBAPI wrapper reference. Every clause earns its place.

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

Completeness3/5

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

For a one-parameter read tool with a fully documented schema, the description is mostly sufficient to invoke it. However, with no output schema, it leaves the shape of the returned items unspecified, and it lacks usage or error context.

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 UDFLISTKEY as required and unique. The description merely restates the parameter without adding format, source, or additional semantic detail, so it stays at the baseline.

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?

Description uses a specific verb ('Returns'), resource ('items of a single UDF list'), and required key (UDFLISTKEY). The word 'single' and 'items' clearly differentiate it from the sibling get_udf_lists, which retrieves the lists themselves.

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?

Usage is implied: an agent can infer it should call this tool when it has a UDFLISTKEY and wants that list's items. However, it never explicitly states when to prefer this over get_udf_lists or any alternative, and it gives no exclusions.

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

get_udf_listsB

Lists user-defined field (UDF) lists configured on the NetBox system (wraps NBAPI GetUDFLists). No parameters required.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.3/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It only states the action and that no parameters are required, but doesn't disclose return format, pagination, performance implications, or whether it's a read-only operation. For a list operation, an agent might need to know if the list is large or requires iteration, but the description offers no such context.

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?

The description is one sentence, front-loaded with the action and resource, and includes a useful parenthetical about the underlying NBAPI wrapper. The extra note 'No parameters required' is redundant given the empty schema, but harmless. It's concise and well-structured.

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

Completeness3/5

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

Given the tool has zero parameters and no output schema, the description covers the essential input side. However, it doesn't describe what the return value looks like (e.g., a list of UDF list objects with IDs and names), which an agent might need to know for downstream processing. The sibling 'get_udf_list_items' hints at a hierarchy, but the description doesn't clarify the relationship or what fields are returned. Still, for a simple no-param list operation, it's mostly complete.

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?

The tool has zero parameters, and the schema has no properties, so there's no parameter documentation needed. The description explicitly states 'No parameters required,' which is clear and accurate. With 0 parameters, the baseline is 4 as per the rubric, and the description meets it.

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?

The description clearly states it lists user-defined field (UDF) lists configured on the NetBox system, with a specific verb ('Lists') and resource ('UDF lists'). It distinguishes itself from the sibling 'get_udf_list_items' which likely lists the items within a UDF list, and other get_* tools. However, it doesn't explicitly differentiate itself from all siblings or mention the NBAPI wrapper context beyond a parenthetical.

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 description provides no explicit guidance on when to use this tool versus alternatives. The context implies it's for retrieving UDF lists, and the sibling 'get_udf_list_items' suggests a related tool, but no direct comparison or conditions are stated. With many sibling tools, a brief 'use this to fetch all UDF lists; for individual items use get_udf_list_items' would be helpful.

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

get_unlock_windowA

Reports the managed unlock window, if any: the managed portal group "MCP Unlock Window" (key, portals, its unlock time spec group and whether that is the managed time spec group "MCP Unlock Window time specs"), that group and its members (read from paginated GetTimeSpecGroups), the managed time specs and holidays, the window derived from them, and whether it is active right now on the host clock. Read-only: issues only Get commands. No parameters required.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations, the description carries the full behavioral burden and explicitly states 'Read-only: issues only Get commands' and 'No parameters required.' It also discloses that data is read from paginated GetTimeSpecGroups, making the safety and data-source behavior clear.

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?

The core purpose is front-loaded in the first clause, and there is no outright waste. However, the remainder is a long, nested enumeration with multiple parentheticals that is dense and somewhat difficult to scan; splitting it into clearer clauses would improve readability.

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 parameterless report tool with no output schema, the description is complete: it names the managed groups, the time specs and holidays, the derived window, the active status, and the read-only nature. An agent has enough information to invoke it correctly without further context.

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?

The input schema is empty and there are zero parameters, so the baseline is 4. The description reinforces this with 'No parameters required,' confirming to the agent that no arguments are needed.

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 uses a specific verb ('Reports') and a specific resource ('managed unlock window'), then precisely scopes it to the 'MCP Unlock Window' portal group, its time spec group, derived window, and active status. This is clearly differentiated from generic get_time_spec* siblings, even though get_daily_unlock_window is not explicitly named.

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 description gives clear context for when to use the tool: to report the managed unlock window, its constituent groups/specs, and whether it is currently active. It does not explicitly name alternatives or state when not to use it, 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_eventsA

Lists the event types/definitions known to the NetBox system (wraps NBAPI ListEvents). No parameters required.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions 'No parameters required' and that it wraps an API, but does not disclose the return format, pagination, potential errors, or whether it's read-only. For a simple list operation, this is minimal coverage.

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 no filler. The purpose is front-loaded, the wrapper note adds context, and the parameter note is useful. Every sentence earns its place.

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

Completeness3/5

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

For a simple no-parameter list tool, the description covers the essentials: what it lists and that no parameters are needed. However, it does not describe the response format (e.g., array of event definitions), and with no output schema, an agent might not know what to expect. This is a minor gap but not fatal for such a straightforward 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?

The tool has zero parameters and the schema is empty. The description explicitly states 'No parameters required', which confirms the parameter behavior. With 0 parameters, the baseline is 4, and the description adequately covers 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?

The description clearly states the verb 'Lists' and the resource 'event types/definitions known to the NetBox system', and even names the underlying API wrapper (NBAPI ListEvents). This is unambiguous and distinguishes it from sibling tools like get_event_history, which deal with history rather than definitions.

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 description implies usage (when you need to list event definitions) but does not explicitly state when not to use it or point to alternatives. Since there are siblings like get_event_history, the description could have clarified that this tool is for definitions, not history. However, the wording 'event types/definitions' is fairly clear, so it gets a mid score.

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

ping_appB

Pings the NetBox NBAPI application to confirm it is responsive (wraps NBAPI PingApp). No parameters required.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.3/5.0
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It states that it pings to confirm responsiveness, but does not disclose potential side effects, failure behavior, or what the response indicates. For a tool that likely only checks reachability, this is minimal but not contradictory.

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 a single, efficient sentence with no wasted words. It states the action, target, purpose, and parameter status clearly and front-loads the core functionality.

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, parameter-less health-check tool with no output schema, the description is sufficiently complete. It explains what the tool does and that no inputs are required. The only minor gap is not clarifying the return format or how to interpret the result, but this is not critical for a ping.

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?

The tool has zero parameters, and the description explicitly states 'No parameters required.' The schema coverage is 100% (since there are none), so the baseline for 0 parameters is 4, and the description appropriately confirms this.

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?

The description clearly states the action ('Pings') and the target ('NetBox NBAPI application') with a purpose ('to confirm it is responsive'). It also references the wrapped NBAPI PingApp. However, it does not explicitly differentiate from the sibling 'check_connection', which likely serves a similar health-check role.

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?

No guidance is provided on when to use this tool versus alternatives such as 'check_connection'. The description does not mention any conditions, prerequisites, or exclusions, leaving the agent to infer appropriate usage.

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

search_person_dataC

Searches for person records matching the given criteria (wraps NBAPI SearchPersonData). Every documented SearchPersonData filter field is modeled explicitly; omit all filters to return every record.

ParametersJSON Schema
NameRequiredDescriptionDefault
UDF1NoOptional. Search filter on user-defined field UDF1.
UDF2NoOptional. Search filter on user-defined field UDF2.
UDF3NoOptional. Search filter on user-defined field UDF3.
UDF4NoOptional. Search filter on user-defined field UDF4.
UDF5NoOptional. Search filter on user-defined field UDF5.
UDF6NoOptional. Search filter on user-defined field UDF6.
UDF7NoOptional. Search filter on user-defined field UDF7.
UDF8NoOptional. Search filter on user-defined field UDF8.
UDF9NoOptional. Search filter on user-defined field UDF9.
UDF10NoOptional. Search filter on user-defined field UDF10.
UDF11NoOptional. Search filter on user-defined field UDF11.
UDF12NoOptional. Search filter on user-defined field UDF12.
UDF13NoOptional. Search filter on user-defined field UDF13.
UDF14NoOptional. Search filter on user-defined field UDF14.
UDF15NoOptional. Search filter on user-defined field UDF15.
UDF16NoOptional. Search filter on user-defined field UDF16.
UDF17NoOptional. Search filter on user-defined field UDF17.
UDF18NoOptional. Search filter on user-defined field UDF18.
UDF19NoOptional. Search filter on user-defined field UDF19.
UDF20NoOptional. Search filter on user-defined field UDF20.
DELETEDNoOptional. Include/exclude deleted person records.
HOTSTAMPNoOptional. Match on a card hot-stamp number.
LASTNAMENoOptional. Match on the person's last name.
PERSONIDNoOptional. Match on a specific PERSONID.
FIRSTNAMENoOptional. Match on the person's first name.
MIDDLENAMENoOptional. Match on the person's middle name.
ACCESSLEVELNoOptional. Match persons assigned this access level.
ALLPARTITIONSNoOptional. Search across all partitions.
NEWESTLASTMODNoOptional. Only include records last modified on/before this date/time.
OLDESTLASTMODNoOptional. Only include records last modified on/after this date/time.
RAWCARDNUMBERNoOptional. Match on a raw (unformatted) card number.
WILDCARDSEARCHNoOptional. Treat text filters as wildcard patterns.
CASEINSENSITIVENoOptional. Perform a case-insensitive match.
WANTCREDENTIALIDNoOptional. Include CREDENTIALID values on returned access cards.
ACCESSLEVELDETAILSNoOptional. Include full access level details in the response.

TDQS

C2.9/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions wrapping NBAPI SearchPersonData and the omit-all-filters behavior, but does not disclose return format, pagination, result size limits, or deleted-record default handling, which are important for a search tool with no output schema.

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

Conciseness4/5

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

Two concise sentences with the core purpose front-loaded. The second sentence adds a useful operational note without waste, though it could be considered slightly redundant with the schema's optionality.

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

Completeness3/5

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

For a 35-parameter search tool with no output schema and no annotations, the description is adequate but thin. It confirms the filter surface and the empty-criteria behavior but does not describe the response shape, which the agent must infer. It is minimally viable but not rich.

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%, with all 35 parameters already described in the input schema. The description adds nothing beyond stating that every filter field is modeled explicitly, which merely restates the schema rather than enriching parameter meaning. 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 (searches) and resource (person records), and clarifies the search-by-criteria semantics. However, it does not differentiate itself from the sibling get_person, which is a direct single-record fetch — an agent must infer the distinction between search and direct retrieval.

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?

Provides only the operational note that omitting all filters returns every record. It gives no explicit guidance on when to use this tool versus get_person or other sibling read tools, and names no alternatives or exclusions.

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. 36 tool updatesv0.2.3
    • First observedcheck_connection
    • First observedfind_portals
    • First observedget_access_history
    • First observedget_access_level
    • First observedget_access_level_group
    • First observedget_access_level_groups
    • First observedget_access_level_names
    • First observedget_access_levels
    • First observedget_card_access_details
    • First observedget_card_formats
    • First observedget_daily_unlock_window
    • First observedget_elevators
    • First observedget_event_history
    • First observedget_floors
    • First observedget_holiday
    • First observedget_holidays
    • First observedget_outputs
    • First observedget_partitions
    • First observedget_person
    • First observedget_portal_group
    • First observedget_portal_groups
    • First observedget_portals
    • First observedget_reader
    • First observedget_reader_group
    • First observedget_reader_groups
    • First observedget_readers
    • First observedget_time_spec
    • First observedget_time_spec_group
    • First observedget_time_spec_groups
    • First observedget_time_specs
    • First observedget_udf_list_items
    • First observedget_udf_lists
    • First observedget_unlock_window
    • First observedlist_events
    • First observedping_app
    • First observedsearch_person_data

TDQS

A3.5/5.0

Scored across 36 tools

Disambiguation5/5

Each tool targets a distinct entity or operation (e.g., get_person vs search_person_data, get_portals vs find_portals, get_unlock_window vs get_daily_unlock_window). Descriptions clarify any potential overlap, such as get_readers vs get_portals. No two tools appear to serve the same purpose.

Naming Consistency4/5

The dominant pattern is get_<entity> for singular and get_<entity>s for plural, with a few exceptions like list_events, check_connection, ping_app, find_portals, and search_person_data. These deviations are minor and do not create confusion, but they break the otherwise uniform get_ convention.

Tool Count2/5

With 36 tools, the server exceeds the typical well-scoped range (3-15) by a wide margin. While the breadth of NetBox entities justifies many getters, the count feels heavy and could overwhelm an agent; a leaner surface with combined or parameterized tools would be more coherent.

Completeness4/5

The server provides comprehensive read-only coverage of NetBox entities: persons, time specs, groups, holidays, portals, readers, access levels, card formats, events, history, and more. Minor gaps exist (e.g., no single-portal getter, no individual event/access record retrieval), but the core read surface is complete for the apparent purpose.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers