Skip to content
SZ-MCP
Get Support

Finding the right endpoint

Discovery on both namespaces follows the same three steps: list the tags, search or browse within them, then read the endpoint’s schema before calling it.

Before any of that, Claude checks the task helpers listed in the code_mode description (wifi.list_all, wifi.overview, switches.port_lookup and many more): if one covers the task, it does the joins, pagination and known quirks for you and no endpoint needs finding. For how a SmartZone feature works, wifi.search_docs({ query }) searches the SmartZone 7.2.0 guides, and wifi.get_reference({ topic }) holds recipes (query-api, pagination, alarms-events, switch-config, data-sources).

list_tags() takes no arguments and returns every tag on the surface with the number of operations under it. Tags are the top of the hierarchy: there is no tag-group level above them.

CallReturns
wifi.list_tags()All 117 WSG tags with operation counts
switches.list_tags()All 42 SwitchM tags with operation counts

Earlier versions of SZ-MCP also had a list_tag_groups primitive and a group argument on list_tags. Both were removed: the SmartZone specs define no tag groups, so they could only ever return an empty list. If an older conversation or saved prompt still calls list_tag_groups, replace that step with a bare list_tags().

search_endpoints({ query }) scores every operation on the surface and returns the best matches, up to 20 by default.

Scoring is additive per query token. A token must appear in the search blob to score at all:

MatchScore
Token appears in the search blob+1
Token appears in operationId+2
Token appears in a tag name+1
Token appears in the path+1
Token is a whole path segment+1
A multi-word query matches every token+ the number of tokens

Ties go to the shorter path, which is usually the collection you mean.

The search blob is built from operationId, tags, summary, path, method and the request and response field names. In practice that means operationId, summary and field names are what you are searching, because the vendored specs populate no operation descriptions at all — 0 of 1,102 on WSG and 0 of 238 on SwitchM — and no tag descriptions either.

Queries are tokenised on whitespace and matched case-insensitively as substrings, so query: 'wlan' hits getWlan, WLAN and /rkszones/{id}/wlans alike. A query shorter than two characters is rejected.

You can narrow a search with tag or method:

await wifi.search_endpoints({ query: 'profile', tag: 'WLAN', method: 'POST' });

When you know the tag, list_endpoints_by_tag({ tag }) returns everything under it — 50 at a time by default, with offset for the rest. Its count field is the full total, not the page size, so it tells you whether to page again.

Unlike search_endpoints, this is an exact tag match. Tag names come from list_tags() and must be passed verbatim, including spaces and capitalisation — 'Switch VLAN Setting', not 'switch-vlan-setting'.

Every search and browse hit already carries access ('read' or 'write'), paginationStyle, requiredParams, requestBodyHint (the body’s field names) and responseHint. Often that is enough to call the endpoint. A hit with caveats carries quirks verified on a live controller; they override the spec.

When you need the full body schema, enum values or parameter descriptions, get_endpoint_details({ method, path }) returns the operation’s definition with $refs inlined (up to four references along any one path) and allOf merged, plus any caveats and the endpoint notes your organisation saved.

The vendored specs are Swagger 2.0, not OpenAPI 3, which declares a request body as a parameter with in: "body". get_endpoint_details moves it out of parameters into requestBody:

  • requestBody is { required, contentType, schema } (for a form upload, fields instead of schema), or null when the operation takes no body.
  • hasBody on each index entry is true when the operation takes a body.

serviceTicket, which the spec lists as a required query parameter on nearly every operation, is removed from parameters. SZ-MCP attaches it server-side.

Putting it together, as a single program:

async () => {
// 1. What areas exist on this surface?
const { tags } = await switches.list_tags();
// 2. Find candidates
const hits = await switches.search_endpoints({ query: 'vlan', limit: 5 });
// 3. Read the schema of the best one
const top = hits.results[0];
const details = await switches.get_endpoint_details({
method: top.method,
path: top.path,
});
// 4. The body schema is in requestBody
const body = details.requestBody?.schema;
return { tagCount: tags.length, top, body };
}