Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
CNC_MCP_BASE_URLYesCNC UI/API URL with scheme, e.g. https://host:30603
CNC_MCP_PASSWORDNoCrosswork password for two-leg CAS SSO authentication
CNC_MCP_USERNAMENoCrosswork username for two-leg CAS SSO authentication
CNC_MCP_API_TOKENNoPre-issued JWT token alternative to username/password (cannot be refreshed)
CNC_MCP_VERIFY_TLSNoWhether to verify TLS certificates; set to false for self-signed lab certificatestrue
CNC_MCP_ENABLE_WRITESNoWrite tools are not registered until this is truefalse
CNC_MCP_TIMEOUT_SECONDSNoTimeout in seconds (see .env.example for additional timeout, retry, concurrency, and response-cap settings)

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
cnc_list_devicesA

List network devices (inventory nodes) with optional filters and paging.

Read-only. Use it to discover device uuids/host names before calling cnc_get_device, cnc_update_device or cnc_delete_device. Filters AND together. Unmanaged devices are hidden in the CNC UI's default table but are returned here.

Args: host_name, reachability, admin_state, credential_profile: exact-match filters (case-insensitive, '*' wildcard). Enum filters accept friendly or wire values. page_size, page: paging (page is 0-based). response_format: 'markdown' (default) or 'json'.

Returns: str: Markdown, one line per device: "host_name (uuid) ip=... reach=... oper=... admin=... profile=... dg=..." plus "More available: page=N." when another page exists. Or JSON: {"total": int|null, "count": int, "page": int, "page_size": int, "has_more": bool, "next_page": int|null, "collection_total": int|null, "items": []} 'total' is the number of matches for the filter (absent when zero matched); 'collection_total' is the size of the whole inventory. On failure: "Error: " (unknown enum value -> the accepted values are listed; 500 'NATS request failed' -> the platform could not parse the request).

cnc_get_deviceA

Get the full inventory record of one device by uuid or host name.

Read-only. Pass exactly one selector. Returns every field Crosswork holds for the node: uuid, host_name, node_ip, admin_state, reachability_state, operational_state, reachability_check, profile, connectivity_info, product_info, routing_info, tag_names, dg_name/dg_uuid, nso_state, errors, creation_time, last_upd_time, ...

Note the read/write asymmetry: node_ip.inet_af reads as a string ('ROBOT_INET_ADDR_TYPE_v4') but is the integer 0 in write bodies, so do not feed this object straight back into a write.

Returns: str: JSON object of the node, or "Error: ..." (not found -> no device matched the selector; ambiguous -> a wildcard host_name matched several devices, use the uuid).

cnc_get_device_collection_summaryA

Count devices by collection status across the whole inventory.

Read-only. This is the "Collection status" widget of the Network Devices page: how many devices are in progress, completed, warning, failed or in maintenance for inventory collection. Use it as a quick health check before drilling into individual devices with cnc_list_devices.

Returns: str: JSON with flat integer counts: {"inprogress": int, "warning": int, "failed": int, "completed": int, "maintenance": int} On failure: "Error: ...".

cnc_wait_for_device_reachableA

Poll a device until its reachability_state is CONN_STATE_REACHABLE.

Read-only convergence wait. Call it right after cnc_create_device (or after fixing credentials / admin state) instead of polling cnc_get_device in a loop. Pass exactly one of uuid / host_name. A new device typically moves UNKNOWN/CHECKING -> REACHABLE within a minute or two once it is attached to a Data Gateway.

Returns: str: On success: "Device () is reachable after Ns." plus a JSON summary (reachability_state, operational_state, dg_name, errors). On timeout (NOT an error): "Not reachable yet after Ns; current reachability_state=..., operational_state=..." plus the same summary — call again to keep waiting, or inspect 'errors' / dg_name. "Error: ..." only for API failures or when no device matches.

cnc_list_credential_profilesA

List credential profiles known to Crosswork, with optional name filter and paging.

Read-only. Use it to find the profile name to reference when adding devices or providers, or to check which protocols (SSH/HTTP/HTTPS/SNMPv2/...) a profile covers. For one profile's full record use cnc_get_credential_profile.

Secrets are masked by the API ("******"); usernames are returned in clear.

Args: profile: name filter (exact, case-insensitive, '*' wildcard; surrounding whitespace is stripped and a blank filter means no filter). page_size / page: filterData paging (0-based page). response_format: 'markdown' (default) or 'json'.

Returns: str: Markdown "- profile — types: SSH (user), HTTP (user), SNMPv2" lines, or JSON: {"total": int|null, "count": int, "page": int, "page_size": int, "items": [{"profile": str, "user_pass": [{"user_name": str, "password": "", "type": "ROBOT_USERPASS_SSH|HTTP|HTTPS|..."}], "v2_info": {"read_community": "", ...}?}, ...], "has_more": bool, "next_page": int|null, "collection_total": int|null} "total" is the number of profiles matching the filter (null when the platform omits it, i.e. zero matches); "collection_total" is the size of the whole collection regardless of filter. On failure: "Error: " (500 "NATS request failed" -> the query body was rejected; 403 -> token rejected or missing privilege).

cnc_get_credential_profileA

Get the full record of one credential profile by name.

Read-only. Profiles have no UUID: the name is the identifier everywhere (devices and providers reference it in their "profile" field). Find names with cnc_list_credential_profiles.

Args: profile: exact profile name (case-insensitive; surrounding whitespace is stripped). A '*' wildcard is accepted by the platform but this tool needs a single exact match.

Returns: str: JSON object {"profile": str, "user_pass": [{"user_name", "password": "******", "type": "ROBOT_USERPASS_SSH|HTTP|HTTPS|...", ...}], "v2_info": {...}?, "v3_info": {...}?}. Secrets are masked by the API. On failure: "Error: Credential profile '' not found ..." when nothing matches, "Error: ... matches several profiles ..." when a wildcard was used, "Error: profile must not be empty ..." for a blank name, or "Error: ".

cnc_list_providersA

List the providers configured in Crosswork (SR-PCE, NSO, WAE, ...).

Read-only. Providers are the external systems CNC integrates with; the SR-PCE provider is what feeds the L3/SR-TE topology (via BGP-LS), and the NSO provider is used for service provisioning. Use this to discover provider UUIDs and check their reachability before touching devices, topology, or services; use cnc_get_provider for the full record.

Filters AND together. Only name and family are supported filters on this endpoint. Page with page/page_size (0-based).

Args: name: exact/wildcard name filter (case-insensitive). family: friendly family name (sr_pce, nso, wae, syslog_storage, alert, proxy, onc, accedian_proxy) or wire value. page_size, page: paging; has_more/next_page say whether to fetch another page. response_format: markdown (one line per provider: name, uuid, family, reachability, endpoints, credential profile) or json.

Returns: str: Markdown listing, or JSON: {"total": int|null, "count": int, "page": int, "page_size": int, "items": [{"uuid", "name", "family", "profile", "reachability_state", "connectivity_info": [...], "properties": {...}, ...}], "has_more": bool, "next_page": int|null, "collection_total": int|null, "offset": int, "next_offset": int|null} total is the number of providers matching the filter (absent / null when Crosswork omits it, which it does for zero matches); collection_total is the size of the whole provider collection. On failure: "Error: " (unknown family value -> the list of accepted values; 500 "NATS request failed" -> malformed request rather than an outage).

cnc_get_providerA

Get the full record of one provider, by UUID or by exact name.

Read-only. Exactly one of uuid / name must be given. Use it to inspect a provider's endpoints (connectivity_info), credential profile (profile), family, reachability and properties (for SR-PCE: auto-onboard, outgoing-interface, device-profile, preferred-stack) — for example before cnc_update_provider or cnc_delete_provider. A uuid lookup scans the (small) provider collection and matches client-side, since uuid is not a verified filter field on providers/query.

Returns: str: JSON object with every provider field as Crosswork returns it (note connectivity_info[].ipaddrs[].inet_af reads as 'ROBOT_INET_ADDR_TYPE_v4'; write bodies use 0 — don't round-trip a read object into a write). "Error: ..." when neither or both selectors are given, when no provider matches (verify with cnc_list_providers), or on an API failure.

cnc_get_topology_summaryA

Summarize the CNC topology: node/link totals and state breakdowns.

Read-only. Combines three topology-service calls (init, nodes/summary, edges/summary) into one answer. Use it first to learn whether the topology is populated at all (an empty topology with a populated inventory usually means no reachable SR-PCE provider), then drill in with cnc_get_topology, cnc_list_topology_nodes or cnc_list_topology_links.

Returns: str: JSON: {"total_nodes": int, "unmapped_nodes": int, "max_logical_nodes": int, "reachability": {"CONN_STATE_REACHABLE": 5, ...}, "link_state": {"Up": 1, "Degraded": 0, "Down": 0}, "node_breakdowns": {: {: }, ...}, "link_breakdowns": {: {: }, ...}} unmapped_nodes counts nodes with no geographic location (they render on the logical map only). node_breakdowns carries every section the platform returned (e.g. device family) keyed by type. Counts are null and breakdowns empty when the platform returns an empty body (fresh, unpopulated topology). On failure: "Error: ". An HTTP 500 "Internal Server Error" from /v1/topology-service/... means the service rejected the request body (mapType/viewId/params) — deterministic, do NOT retry. (It is not the inventory's "NATS request failed" signal.)

cnc_get_topologyA

Get the topology graph: one page of nodes plus one page of links (edges).

Read-only. Crosswork returns the whole graph (up to maxLogicalNodes, 5000 on the lab instance) in one response with no server-side paging, so this tool re-downloads the graph on every call and pages BOTH lists client-side: page/page_size window the links, node_page/ node_page_size window the nodes. Each link carries both endpoints resolved (node UUID, node name, interface), so a links page is self-contained — you do not need the nodes page to read adjacency. Use it for node-to-node adjacency (e.g. "what is PE1 connected to?"); for tabular attributes (IPs, reachability, link status/utilisation) prefer cnc_list_topology_nodes / cnc_list_topology_links. Keep page sizes modest: the response is capped at the configured size limit.

Args: map_type: 'logical' only ('geo' is rejected with an explanation). page_size: links per page (1-500). page: 0-based page of links. node_page_size: nodes per page (1-1000). node_page: 0-based page of nodes. response_format: markdown (default) or json.

Returns: str: Markdown listing nodes then "A:ifA <-> B:ifB" per link, or JSON: {"map_type": "LOGICAL", "attributes": {"totalNodes": int, ...}, "nodes": {"total": int, "count": int, "page": int, "page_size": int, "items": [{"uuid": str, "name": str}], "has_more": bool, "next_page": int|null, ...}, "links": {"total": int, "count": int, "page": int, "page_size": int, "items": [{"uuid": str, "name": "-", "source": {"node_uuid": str, "node_name": str, "interface": str}, "target": {"node_uuid": str, "node_name": str, "interface": str}}], "has_more": bool, "next_page": int|null, ...}} Node icon/checksum attributes and edge decoration attributes (the only attributes the platform returns on /data) are dropped. On failure: "Error: ". An HTTP 500 "Internal Server Error" from /v1/topology-service/... means the service rejected the request body (mapType/viewId/params) — deterministic, do NOT retry. (It is not the inventory's "NATS request failed" signal.)

cnc_list_topology_nodesA

List the nodes on the topology map as a sorted, paged table.

Read-only. Topology nodes are the devices CNC has placed on the map (fed by inventory + SR-PCE); their UUIDs match the inventory node UUIDs. Use this for per-node attributes (management IP, TE router-id, reachability, family); use cnc_get_topology for adjacency.

Paging is a row window: startRow = page * page_size, endRow = startRow + page_size. Past the end the platform returns totalCount with no rows (reported as an empty page, not an error). No filtering is available on this endpoint — filter client-side or use the inventory tools. The platform silently accepts an unknown sort column (undefined order), so sort_by is validated here first.

Args: page_size: rows per page (1-500). page: 0-based page number. sort_by: column to sort on (see the parameter description). sort_ascending: sort direction. response_format: markdown (default) or json.

Returns: str: Markdown listing, or JSON: {"total": int, "count": int, "page": int, "page_size": int, "items": [{"uuid": str, "name": str, "nodeIp": str, "teRouterId": str, "reachabilityState": "CONN_STATE_REACHABLE"|..., "productType": str, "deviceFamily": str, "lastUpdateTime": str, ...}], "has_more": bool, "next_page": int|null, ...} Each item is the element's uuid merged with its attributes. On failure: "Error: " (unknown sort column -> "Error: Unknown sort column ..."). An HTTP 500 "Internal Server Error" from /v1/topology-service/... means the service rejected the request body (viewId/params) — deterministic, do NOT retry. (It is not the inventory's "NATS request failed" signal.)

cnc_list_topology_linksA

List the links (edges) on the topology map with status and utilisation.

Read-only. Each link carries its type (display name, e.g. "L2 Ethernet" for LT_L2_ETHERNET, "L3 ISIS IPv4 L1", "L3 OSPF IPv4", "L3 BGP EPE IPv4"), status (Up/Degraded/Down), both endpoint node names/UUIDs and interface names, and per-direction utilisation labels such as "0.00015% (1.5Kbps/1Gbps)" with a HEALTHY/... severity. L2 links come from LLDP collection; L3 links need an SR-PCE provider (BGP-LS).

Paging is a row window: startRow = page * page_size, endRow = startRow + page_size. Past the end the platform returns totalCount with no rows (reported as an empty page, not an error). No filtering is available.

Args: page_size: rows per page (1-500). page: 0-based page number. response_format: markdown (default) or json.

Returns: str: Markdown "status linkType: srcNode:srcIf <-> dstNode:dstIf (util)" per link, or JSON: {"total": int, "count": int, "page": int, "page_size": int, "items": [{"uuid": str, "name": str, "linkType": "L2 Ethernet", "status": "Up", "sourceNode-name": str, "sourceNode-uuid": str, "sourceConnector-name": str, "targetNode-name": str, "targetNode-uuid": str, "targetConnector-name": str, "targetConnector-uto-label": str, "targetConnector-uto-severity": "HEALTHY", ...}], "has_more": bool, "next_page": int|null, ...} Each item is the element's uuid merged with its attributes. On failure: "Error: ". An HTTP 500 "Internal Server Error" from /v1/topology-service/... means the service rejected the request body (viewId/params) — deterministic, do NOT retry. (It is not the inventory's "NATS request failed" signal.)

cnc_list_tagsA

List the tags defined on Crosswork (system tags such as 'mdt' plus any user-defined ones), with optional name/category filtering and paging.

Read-only. Use it to learn the exact tag names before filtering devices by tag or attaching tags to devices. The tool sends an empty body and applies the name/category filters and the paging itself after the fetch. Whether tags/query honours a filter body or pages server-side is not verified; if the response carries result_count/total_count larger than the rows returned, the collection was truncated by the server and the output says so. 'total' is the number of fetched tags that matched the filters; 'collection_total' is the number of tags on the platform (from the server's counts when present, else the number fetched).

Args: name: case-insensitive substring of the tag name. category: exact category (case-insensitive), e.g. 'default'. page_size / page: client-side paging over the filtered tags.

Returns: str: Markdown listing, or JSON: {"total": int, "count": int, "page": int, "page_size": int, "items": [{"name": str, "category": str, "created_by": str, "creation_time": str, "tag_type": str}, ...], "has_more": bool, "next_page": int|null, "collection_total": int} On failure: "Error: ".

cnc_list_usersA

List the Crosswork user accounts with their role, status and device access groups.

Read-only. Use it to confirm an account exists (Crosswork answers the same 'Invalid credentials' for an unknown username and a wrong password) and to see which role (PolicyId, e.g. 'admin') and device access groups (e.g. 'ALL-ACCESS') an account carries. The platform returns a dict keyed by username with PascalCase fields; this tool flattens it to a list and never returns the Password field.

Returns: str: Markdown listing, or JSON: {"count": int, "items": [{"username": str, "role": str, "first_name": str, "last_name": str, "status": str, "device_access_groups": [str, ...]}, ...]} On failure: "Error: " (403 -> the configured account lacks the user-administration privilege).

cnc_list_applicationsA

List the applications installed on the Crosswork platform with their versions (e.g. Crosswork Optimization Engine, Service Health, ...).

Read-only. Use it to check what is installed and at which version before assuming a feature (topology, SR-TE, VPN services) is available on this instance.

Returns: str: Markdown "name (application_id) version — description" lines, or JSON: {"count": int, "items": [{"application_id": str, "application_data": {"version": str, "summary": {"name": str, "description": str}, "category": str, "build_information": {"date_time": str, "publisher": str}}}, ...]} On failure: "Error: ".

cnc_list_alarmsA

List Crosswork platform alarms (device reachability, collection, application health, ...), newest first as the platform orders them.

Read-only. Use it to find out why something is unhealthy before digging into devices or providers. Alarms are paged with a SQL-like criteria string ('select * from alarm limit N page M'); no other filtering is exposed. The platform reports no total, so 'has_more' means the page came back full — request the next page to check.

Args: open_only: True for open alarms only (default), False for all. limit / page: page size and 0-based page number.

Returns: str: Markdown with one line per alarm (category, description, created time, id, acknowledged flag, event count; the Events detail is omitted), or JSON: {"total": null, "count": int, "page": int, "page_size": int, "items": [{"AlarmId": str, "AlarmCategory": str, "Description": str, "Created": str, "Updated": str, "Acknowledge": bool, "object_id": str, "origin_app_id": str, "events_count": int, "Events": [...]}, ...], "has_more": bool, "next_page": int|null} On failure: "Error: ".

cnc_list_inventory_jobsA

List inventory jobs — the audit trail of every device, credential, provider and tag write on Crosswork (each write returns one job).

Read-only. Use it to review recent changes or to find the job_id of a write whose result was lost, then inspect one with cnc_get_inventory_job or wait for it with cnc_wait_for_inventory_job. Paged with the inventory filterData.PageSize/PageNum grammar (assumed for this endpoint; 'total' is null when the platform reports no result_count, and 'has_more' then means the page came back full).

Args: page_size / page: page size and 0-based page number.

Returns: str: Markdown listing, or JSON: {"total": int|null, "count": int, "page": int, "page_size": int, "items": [{"job_id": str, "state": str, "type": str, "creation_time": str, "completion_time": str, "created_by": str, "impacted": [str, ...], "error": str}, ...], "has_more": bool, "next_page": int|null, "collection_total": int|null} States: JOB_COMPLETED and JOB_COMPLETED_WITH_WARNING (a success with an advisory in "error", e.g. a no-op or partially applied write), JOB_FAILED / JOB_CANCELLED / JOB_ABORTED (unsuccessful), JOB_RUNNING and other in-progress states. On failure: "Error: ".

cnc_get_inventory_jobA

Get one inventory job by id: its state, type, timestamps, the objects it touched and the error text when it failed.

Read-only. Use it to check the outcome of a device/credential/provider write. For a job that may still be running prefer cnc_wait_for_inventory_job, which polls until it finishes. The lookup scans the newest few hundred jobs (newest first), so a very old job may not be found even though cnc_list_inventory_jobs can still page to it.

Returns: str: JSON of the job: {"job_id", "state", "type", "creation_time", "completion_time", "created_by", "impacted": [" []"], "impacted_objects": [{"uuid", "name", "ip"}], "error"}. A state of JOB_COMPLETED_WITH_WARNING is a success whose advisory is in "error". "Error: No inventory job with id ..." when the id matches nothing; other failures: "Error: ".

cnc_wait_for_inventory_jobA

Poll an inventory job until it reaches a terminal state or the timeout elapses.

Read-only. Use it right after a write that came back JOB_RUNNING instead of calling cnc_get_inventory_job in a loop. Terminal states are the verified ones: JOB_COMPLETED and JOB_COMPLETED_WITH_WARNING (both successes; the latter carries an advisory, e.g. a no-op or partially applied write), and JOB_FAILED / JOB_CANCELLED / JOB_ABORTED (failures). Any other state (JOB_RUNNING or an in-progress state not seen before) keeps the tool polling until the timeout.

Returns: str: "Inventory job completed after s." followed by the job JSON (with "impacted_objects" parsed from "impacted") on success; for JOB_COMPLETED_WITH_WARNING the line also carries "Warning: " and the JSON gains a "warning" key. A timeout is NOT an error: "Inventory job not finished after s; current state: JOB_RUNNING. ..." followed by the job JSON — call again to keep waiting. "Error: Inventory job failed (job , state JOB_FAILED): " when the job ended unsuccessfully; "Error: No inventory job with id ..." when the id matches nothing; other API failures: "Error: ...".

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

A4.3/5.0

Scored across 19 tools

Disambiguation4/5

Each tool targets a distinct resource and action, and descriptions explicitly partition the topology tools (cnc_get_topology for adjacency vs cnc_list_topology_nodes/cnc_list_topology_links for tabular attributes). The only mild overlap is between the general topology getter and the two specialized topology listers, but the descriptions give clear guidance on when to use each.

Naming Consistency5/5

Every tool follows the same cnc_<verb>_<noun> convention (list_*, get_*, wait_for_*), with no camelCase or mixed-style deviations. The pattern is fully predictable across all 19 tools.

Tool Count4/5

19 tools is on the heavier side but each covers a genuinely distinct domain (devices, credentials, providers, topology, tags, users, applications, alarms, jobs) with read variants plus helpful summary/wait helpers. It feels slightly large but well-scoped rather than padded.

Completeness4/5

Read coverage is broad and coherent: devices, credentials, providers, topology, tags, users, applications, alarms and inventory jobs all have list/get surfaces, plus convergence-wait helpers. The notable gap is the complete absence of write operations (create/update/delete) even though descriptions reference them, but the surface appears intentionally read-only.

Maintenance

ActivityMaintained
ResponsivenessNo issues