From 9ce7c2cba21eec46a56c0d140d0168e7df65639a Mon Sep 17 00:00:00 2001 From: Thomas Munzer Date: Wed, 10 Jun 2026 15:27:09 -0700 Subject: [PATCH 1/6] refactor: merge alarms into event search Consolidate mist_search_alarms into mist_search_events with search_type values for event, alarm, and suppressed_alarm. - Use site_id to select site-level alarm searches - Keep suppressed alarms as a separate search_type - Preserve all existing event and alarm endpoint coverage - Preserve acked=false alarm filtering Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 2 +- src/mistmcp/tool_helper.py | 2 +- src/mistmcp/tools/search_alarms.py | 224 ----------- src/mistmcp/tools/search_events.py | 605 ++++++++++++++++++----------- 4 files changed, 388 insertions(+), 445 deletions(-) delete mode 100644 src/mistmcp/tools/search_alarms.py diff --git a/README.md b/README.md index 8ebec3e..300d38d 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The server exposes a focused set of tools grouped by workflow. This is the quick | Device and client lookup | `mist_search_device`, `mist_search_client`, `mist_search_nac_user_macs` | Find devices, clients, guest authorizations, and NAC-related client entries by name, MAC, IP, serial, model, or other filters. | | Configuration read | `mist_get_configuration_objects`, `mist_get_configuration_object_schema`, `mist_search_device_config_history` | Inspect org or site configuration, discover valid schema fields, and review recent configuration history on devices. | | Configuration changes | `mist_update_configuration_objects`, `mist_change_configuration_objects` | Create, update, and delete supported configuration objects. These tools require `--enable-write-tools`. | -| Monitoring and events | `mist_search_events`, `mist_search_audit_logs`, `mist_search_alarms`, `mist_get_stats` | Investigate events, audit history, alarms, and operational statistics across organizations, sites, devices, clients, and ports. | +| Monitoring and events | `mist_search_events`, `mist_search_audit_logs`, `mist_get_stats` | Investigate events, audit history, alarms, and operational statistics across organizations, sites, devices, clients, and ports. | | Assurance and AI insights | `mist_get_sle`, `mist_get_insight_metrics`, `mist_get_site_rrm_info`, `mist_troubleshoot` | Explore SLEs, Mist AI insight metrics, radio resource management state, and Marvis troubleshooting output. | | Device operations | `mist_utilities`, `mist_list_upgrades` | Run device-side diagnostics and maintenance helpers or inspect upgrade information. Call `mist_utilities` with only `device_type` to list the supported platform-specific utilities. Some state-changing utility actions require write tools, and the disruptive ones also trigger elicitation. | | Inventory and security context | `mist_get_org_licenses`, `mist_list_rogue_devices` | Review organization license usage and detect or inspect rogue AP activity seen by a site. | diff --git a/src/mistmcp/tool_helper.py b/src/mistmcp/tool_helper.py index 70cbed4..ee7d717 100644 --- a/src/mistmcp/tool_helper.py +++ b/src/mistmcp/tool_helper.py @@ -58,7 +58,7 @@ class McpToolsCategory(Enum): }, "events": { "description": "Events related to the sites and organizations. It provides access to various events such as device events, client events, and more. These events can be used for monitoring and troubleshooting purposes.", - "tools": ["mist_search_events", "mist_search_audit_logs", "mist_search_alarms"], + "tools": ["mist_search_events", "mist_search_audit_logs"], }, "info": { "description": "Tools that provide information about the sites and organizations.", diff --git a/src/mistmcp/tools/search_alarms.py b/src/mistmcp/tools/search_alarms.py deleted file mode 100644 index 096738d..0000000 --- a/src/mistmcp/tools/search_alarms.py +++ /dev/null @@ -1,224 +0,0 @@ -""" --------------------------------------------------------------------------------- --------------------------------- Mist MCP SERVER ------------------------------- - - Written by: Thomas Munzer (tmunzer@juniper.net) - Github : https://github.com/tmunzer/mistmcp - - This package is licensed under the MIT License. - --------------------------------------------------------------------------------- -""" - -import mistapi -from fastmcp import Context -from fastmcp.exceptions import ToolError -from mistmcp.request_processor import get_apisession -from mistmcp.response_processor import process_response, handle_network_error -from mistmcp.response_formatter import format_response -from mistmcp.server import mcp -from mistmcp.logger import logger - -from pydantic import Field -from typing import Annotated -from uuid import UUID -from enum import Enum - - -class Scope(Enum): - ORG = "org" - SITE = "site" - SUPPRESSED = "suppressed" - - -@mcp.tool( - name="mist_search_alarms", - description="""Search for raised alarms in an organization or site with optional filtering. - -Scopes: -- `org`: Search all alarms across the organization -- `site`: Search alarms in a specific site (requires `site_id`) -- `suppressed`: View temporarily disabled alarms across the organization - -Alarm groups: `infrastructure` (network device/connectivity issues), `marvis` (AI-driven network detections), `security` (security events) - -Common Marvis alarm types: `bad_cable`, `bad_wan_uplink`, `dns_failure`, `arp_failure`, `auth_failure`, `dhcp_failure`, `missing_vlan`, `negotiation_mismatch`, `port_flap` - -For a complete list of alarm types, use `mist_get_constants` with `object_type=alarm_definitions`.""", - tags={"events"}, - annotations={ - "title": "Search alarms", - "readOnlyHint": True, - "destructiveHint": False, - "openWorldHint": True, - "idempotentHint": True, - }, -) -async def search_alarms( - org_id: Annotated[UUID, Field(description="""Organization ID""")], - scope: Annotated[ - Scope, - Field( - description="""Search scope: `org` (organization-wide), `site` (specific site, requires site_id), or `suppressed` (disabled alarms)""" - ), - ], - site_id: Annotated[UUID, Field(description="""Site ID""", default=None)], - group: Annotated[ - str, - Field( - description="""Only for org/site scope. Alarm group. enum: `infrastructure`, `marvis`, `security`. The `marvis` group is used to retrieve AI-driven network issue detections.""", - default=None, - ), - ], - severity: Annotated[ - str, - Field( - description="""Only for org/site scope.Severity of the alarm. enum: `critical`, `major`, `minor`, `warn`, `info`""", - default=None, - ), - ], - alarm_type: Annotated[ - str, - Field( - description="""Only for org/site scope. Comma separated list of types of the alarm (e.g., 'bad_cable,auth_failure'). IMPORTANT: use the `mist_get_constants` tool with `object_type=alarm_definitions`to get the list of possible alarm types""", - default=None, - ), - ], - acked: Annotated[ - bool, - Field( - description="""Only for org/site scope. Whether to filter for acknowledged (true) or unacknowledged (false) alarms""", - default=None, - ), - ], - start: Annotated[ - int, Field(description="""Start of time range (epoch seconds)""", default=None) - ], - end: Annotated[ - int, Field(description="""End of time range (epoch seconds)""", default=None) - ], - limit: Annotated[ - int, Field(description="""Max number of results per page""", default=20) - ] = 20, -) -> dict | list | str: - """Search for raised alarms in an organization or site with optional filtering. - - Scopes: - - `org`: Search all alarms across the organization - - `site`: Search alarms in a specific site (requires `site_id`) - - `suppressed`: View temporarily disabled alarms across the organization - - Alarm groups: `infrastructure` (network device/connectivity issues), `marvis` (AI-driven network detections), `security` (security events) - - Common Marvis alarm types: `bad_cable`, `bad_wan_uplink`, `dns_failure`, `arp_failure`, `auth_failure`, `dhcp_failure`, `missing_vlan`, `negotiation_mismatch`, `port_flap` - - For a complete list of alarm types, use `mist_get_constants` with `object_type=alarm_definitions`.""" - - logger.debug("Tool search_alarms called") - logger.debug( - "Input Parameters: org_id: %s, scope: %s, site_id: %s, group: %s, severity: %s, alarm_type: %s, acked: %s, start: %s, end: %s, limit: %s", - org_id, - scope, - site_id, - group, - severity, - alarm_type, - acked, - start, - end, - limit, - ) - - apisession, response_format = await get_apisession() - - try: - object_type = scope - - if object_type.value == "site": - if not site_id: - raise ToolError( - { - "status_code": 400, - "message": '`site_id` parameter is required when `scope` is "site".', - } - ) - - if group and scope.value not in ["org", "site"]: - raise ToolError( - { - "status_code": 400, - "message": '`group` parameter can only be used when `scope` is in "org", "site".', - } - ) - - if severity and scope.value not in ["org", "site"]: - raise ToolError( - { - "status_code": 400, - "message": '`severity` parameter can only be used when `scope` is in "org", "site".', - } - ) - - if alarm_type and scope.value not in ["org", "site"]: - raise ToolError( - { - "status_code": 400, - "message": '`alarm_type` parameter can only be used when `scope` is in "org", "site".', - } - ) - - if acked and scope.value not in ["org", "site"]: - raise ToolError( - { - "status_code": 400, - "message": '`acked` parameter can only be used when `scope` is in "org", "site".', - } - ) - - match object_type.value: - case "org": - response = mistapi.api.v1.orgs.alarms.searchOrgAlarms( - apisession, - org_id=str(org_id), - group=group if group else None, - severity=severity if severity else None, - type=alarm_type if alarm_type else None, - acked=acked if acked else None, - start=str(start) if start else None, - end=str(end) if end else None, - limit=limit, - ) - await process_response(response) - case "site": - response = mistapi.api.v1.sites.alarms.searchSiteAlarms( - apisession, - site_id=str(site_id), - group=group if group else None, - severity=severity if severity else None, - type=alarm_type if alarm_type else None, - acked=acked if acked else None, - start=str(start) if start else None, - end=str(end) if end else None, - limit=limit, - ) - await process_response(response) - case "suppressed": - response = mistapi.api.v1.orgs.alarmtemplates.listOrgSuppressedAlarms( - apisession, org_id=str(org_id) - ) - await process_response(response) - - case _: - raise ToolError( - { - "status_code": 400, - "message": f"Invalid object_type: {object_type.value}. Valid values are: {[e.value for e in Scope]}", - } - ) - - except ToolError: - raise - except Exception as _exc: - await handle_network_error(_exc) - - return format_response(response, response_format) diff --git a/src/mistmcp/tools/search_events.py b/src/mistmcp/tools/search_events.py index 4466290..2cc209f 100644 --- a/src/mistmcp/tools/search_events.py +++ b/src/mistmcp/tools/search_events.py @@ -11,7 +11,6 @@ """ import mistapi -from fastmcp import Context from fastmcp.exceptions import ToolError from mistmcp.request_processor import get_apisession from mistmcp.response_processor import process_response, handle_network_error @@ -25,7 +24,13 @@ from uuid import UUID -class Event_source(Enum): +class SearchType(Enum): + EVENT = "event" + ALARM = "alarm" + SUPPRESSED_ALARM = "suppressed_alarm" + + +class EventSource(Enum): DEVICE = "device" MXEDGE = "mxedge" WAN_CLIENT = "wan_client" @@ -37,18 +42,19 @@ class Event_source(Enum): @mcp.tool( name="mist_search_events", - description="""Search for events across an organization or site with flexible filtering options. + description="""Search for Mist events and alarms across an organization or site. -This tool queries events from various sources including devices, MX Edge instances, and clients. You can: -- Filter by time range using `start` and `end` (epoch seconds) -- Filter by event type (use `mist_get_constants` tool first to discover available event types) -- Apply source-specific filters (MAC address, text search, SSID, etc.) +Use `search_type=event` to search event streams from devices, MX Edge instances, clients, roaming, or rogue APs. +Use `search_type=alarm` to search raised alarms. If `site_id` is provided, site alarms are searched; otherwise org alarms are searched. +Use `search_type=suppressed_alarm` to list temporarily disabled alarms for the organization. -IMPORTANT: Always specify an `event_type` to limit results. Use `mist_get_constants` with: +For event types, use `mist_get_constants` with: - `object_type=device_events` for device events -- `object_type=mxedge_events` for MX Edge events +- `object_type=mxedge_events` for MX Edge events - `object_type=client_events` for WAN/wireless client events -- `object_type=nac_events` for NAC client events""", +- `object_type=nac_events` for NAC client events + +For alarm types, use `mist_get_constants` with `object_type=alarm_definitions`.""", tags={"events"}, annotations={ "title": "Search events", @@ -59,75 +65,122 @@ class Event_source(Enum): }, ) async def search_events( - event_source: Annotated[ - Event_source, + search_type: Annotated[ + SearchType, Field( - description="""Event source type: device, mxedge, wan_client, wireless_client, nac_client, roaming (requires site_id), or rogue (requires site_id)""" + description="""Type of event-like data to search: `event`, `alarm`, or `suppressed_alarm`""" ), ], org_id: Annotated[UUID, Field(description="""Organization ID""")], + event_source: Annotated[ + EventSource, + Field( + description="""Required when search_type is `event`. Event source type: device, mxedge, wan_client, wireless_client, nac_client, roaming (requires site_id), or rogue (requires site_id)""", + default=None, + ), + ], event_type: Annotated[ str, Field( - description="""Comma-separated event types to filter by. The list of possible event types can be obtained with the `mist_get_constants` tool with `object_type=device_events` when `event_source` is `device`, `object_type=mxedge_events` when `event_source` is `mxedge`, `object_type=client_events` when `event_source` is `wan_client` or `wireless_client`, `object_type=nac_events` when `event_source` is `nac_client`""", + description="""Only for search_type=event. Comma-separated event types to filter by. Use `mist_get_constants` to discover available values for the selected event_source""", + default=None, + ), + ], + site_id: Annotated[ + UUID, + Field( + description="""Site ID. For search_type=alarm, providing site_id searches site alarms; omitting it searches org alarms. Required for event_source=roaming or rogue. Optional for other event sources to narrow results to a site""", default=None, ), ], - site_id: Annotated[UUID, Field(description="""Site ID""", default=None)], mac: Annotated[ str, Field( - description="""MAC address to filter by (device/WAN client/NAC client/rogue events only)""", + description="""Only for search_type=event. MAC address filter for device, mxedge, WAN client, NAC client, or rogue events""", default=None, ), ], text: Annotated[ str, Field( - description="""Text search in event details (device/NAC client events only)""", + description="""Only for search_type=event with event_source=device or nac_client. Text search in event details""", default=None, ), ], ssid: Annotated[ str, Field( - description="""SSID filter (wireless_client/nac_client/rogue events only)""", + description="""Only for search_type=event with event_source=wireless_client, nac_client, or rogue. SSID filter""", + default=None, + ), + ], + group: Annotated[ + str, + Field( + description="""Only for search_type=alarm. Alarm group: `infrastructure`, `marvis`, or `security`""", + default=None, + ), + ], + severity: Annotated[ + str, + Field( + description="""Only for search_type=alarm. Alarm severity: `critical`, `major`, `minor`, `warn`, or `info`""", + default=None, + ), + ], + alarm_type: Annotated[ + str, + Field( + description="""Only for search_type=alarm. Comma-separated alarm types (e.g., `bad_cable,auth_failure`). Use `mist_get_constants` with `object_type=alarm_definitions` to discover available alarm types""", + default=None, + ), + ], + acked: Annotated[ + bool, + Field( + description="""Only for search_type=alarm. Filter acknowledged (true) or unacknowledged (false) alarms""", default=None, ), ], start: Annotated[ - int, Field(description="""Start of time range (epoch seconds)""", default=None) + int, + Field( + description="""Start of time range (epoch seconds). Used for search_type=event or alarm; ignored for suppressed_alarm""", + default=None, + ), ], end: Annotated[ - int, Field(description="""End of time range (epoch seconds)""", default=None) + int, + Field( + description="""End of time range (epoch seconds). Used for search_type=event or alarm; ignored for suppressed_alarm""", + default=None, + ), ], limit: Annotated[ - int, Field(description="""Max number of results per page""", default=20) + int, + Field( + description="""Max number of results per page. Used for search_type=event or alarm; ignored for suppressed_alarm""", + default=20, + ), ] = 20, ) -> dict | list | str: - """Search for events across an organization or site with flexible filtering options. - - This tool queries events from various sources including devices, MX Edge instances, and clients. You can: - - Filter by time range using `start` and `end` (epoch seconds) - - Filter by event type (use `mist_get_constants` tool first to discover available event types) - - Apply source-specific filters (MAC address, text search, SSID, etc.) - - IMPORTANT: Always specify an `event_type` to limit results. Use `mist_get_constants` with: - - `object_type=device_events` for device events - - `object_type=mxedge_events` for MX Edge events - - `object_type=client_events` for WAN/wireless client events - - `object_type=nac_events` for NAC client events""" + """Search for Mist events and alarms across an organization or site.""" logger.debug("Tool search_events called") logger.debug( - "Input Parameters: event_source: %s, org_id: %s, event_type: %s, site_id: %s, mac: %s, text: %s, ssid: %s, start: %s, end: %s, limit: %s", - event_source, + "Input Parameters: search_type: %s, org_id: %s, event_source: %s, event_type: %s, site_id: %s, mac: %s, text: %s, ssid: %s, group: %s, severity: %s, alarm_type: %s, acked: %s, start: %s, end: %s, limit: %s", + search_type, org_id, + event_source, event_type, site_id, mac, text, ssid, + group, + severity, + alarm_type, + acked, start, end, limit, @@ -136,214 +189,328 @@ async def search_events( apisession, response_format = await get_apisession() try: - object_type = event_source - - if object_type.value == "roaming": - if not site_id: - raise ToolError( - { - "status_code": 400, - "message": '`site_id` parameter is required when `event_source` is "roaming".', - } + match search_type: + case SearchType.EVENT: + response = await _search_event( + apisession=apisession, + org_id=org_id, + event_source=event_source, + event_type=event_type, + site_id=site_id, + mac=mac, + text=text, + ssid=ssid, + start=start, + end=end, + limit=limit, ) - - if object_type.value == "rogue": - if not site_id: + case SearchType.ALARM: + response = await _search_alarm( + apisession=apisession, + org_id=org_id, + site_id=site_id, + group=group, + severity=severity, + alarm_type=alarm_type, + acked=acked, + start=start, + end=end, + limit=limit, + ) + case SearchType.SUPPRESSED_ALARM: + _validate_event_params_not_used( + event_source=event_source, + event_type=event_type, + mac=mac, + text=text, + ssid=ssid, + ) + _validate_alarm_params_not_used( + group=group, + severity=severity, + alarm_type=alarm_type, + acked=acked, + ) + response = mistapi.api.v1.orgs.alarmtemplates.listOrgSuppressedAlarms( + apisession, org_id=str(org_id) + ) + await process_response(response) + case _: raise ToolError( { "status_code": 400, - "message": '`site_id` parameter is required when `event_source` is "rogue".', + "message": f"Invalid search_type: {search_type.value}. Valid values are: {[e.value for e in SearchType]}", } ) + except ToolError: + raise + except Exception as _exc: + await handle_network_error(_exc) - if text and event_source.value not in ["device", "nac_client"]: - raise ToolError( - { - "status_code": 400, - "message": '`text` parameter can only be used when `event_source` is in "device", "nac_client".', - } - ) + return format_response(response, response_format) - if ssid and event_source.value not in [ - "wireless_client", - "nac_client", - "rogue", - ]: - raise ToolError( - { - "status_code": 400, - "message": '`ssid` parameter can only be used when `event_source` is in "wireless_client", "nac_client", "rogue".', - } - ) - match object_type.value: - case "device": - if site_id: - response = mistapi.api.v1.sites.devices.searchSiteDeviceEvents( - apisession, - site_id=str(site_id), - start=str(start) if start else None, - end=str(end) if end else None, - type=str(event_type) if event_type else None, - mac=str(mac) if mac else None, - text=str(text) if text else None, - limit=limit, - ) - await process_response(response) - else: - response = mistapi.api.v1.orgs.devices.searchOrgDeviceEvents( - apisession, - org_id=str(org_id), - start=str(start) if start else None, - end=str(end) if end else None, - type=str(event_type) if event_type else None, - mac=str(mac) if mac else None, - text=str(text) if text else None, - limit=limit, - ) - await process_response(response) - case "mxedge": - if site_id: - response = mistapi.api.v1.sites.mxedges.searchSiteMistEdgeEvents( - apisession, - site_id=str(site_id), - start=str(start) if start else None, - end=str(end) if end else None, - type=str(event_type) if event_type else None, - mxedge_id=f"00000000-0000-0000-1000-{str(mac)}" - if mac - else None, - limit=limit, - ) - await process_response(response) - else: - response = mistapi.api.v1.orgs.mxedges.searchOrgMistEdgeEvents( - apisession, - org_id=str(org_id), - start=str(start) if start else None, - end=str(end) if end else None, - type=str(event_type) if event_type else None, - mxedge_id=f"00000000-0000-0000-1000-{str(mac)}" - if mac - else None, - limit=limit, - ) - await process_response(response) - case "wan_client": - if site_id: - response = ( - mistapi.api.v1.sites.wan_clients.searchSiteWanClientEvents( - apisession, - site_id=str(site_id), - start=str(start) if start else None, - end=str(end) if end else None, - type=str(event_type) if event_type else None, - mac=str(mac) if mac else None, - limit=limit, - ) - ) - await process_response(response) - else: - response = mistapi.api.v1.orgs.wan_clients.searchOrgWanClientEvents( - apisession, - org_id=str(org_id), - start=str(start) if start else None, - end=str(end) if end else None, - type=str(event_type) if event_type else None, - mac=str(mac) if mac else None, - limit=limit, - ) - await process_response(response) - case "wireless_client": - if site_id: - response = ( - mistapi.api.v1.sites.clients.searchSiteWirelessClientEvents( - apisession, - site_id=str(site_id), - start=str(start) if start else None, - end=str(end) if end else None, - type=str(event_type) if event_type else None, - ssid=str(ssid) if ssid else None, - limit=limit, - ) - ) - await process_response(response) - else: - response = ( - mistapi.api.v1.orgs.clients.searchOrgWirelessClientEvents( - apisession, - org_id=str(org_id), - start=str(start) if start else None, - end=str(end) if end else None, - type=str(event_type) if event_type else None, - ssid=str(ssid) if ssid else None, - limit=limit, - ) - ) - await process_response(response) - case "nac_client": - if site_id: - response = ( - mistapi.api.v1.sites.nac_clients.searchSiteNacClientEvents( - apisession, - site_id=str(site_id), - start=str(start) if start else None, - end=str(end) if end else None, - type=str(event_type) if event_type else None, - mac=str(mac) if mac else None, - text=str(text) if text else None, - ssid=str(ssid) if ssid else None, - limit=limit, - ) - ) - await process_response(response) - else: - response = mistapi.api.v1.orgs.nac_clients.searchOrgNacClientEvents( - apisession, - org_id=str(org_id), - start=str(start) if start else None, - end=str(end) if end else None, - type=str(event_type) if event_type else None, - mac=str(mac) if mac else None, - text=str(text) if text else None, - ssid=str(ssid) if ssid else None, - limit=limit, - ) - await process_response(response) - case "roaming": - response = mistapi.api.v1.sites.events.listSiteRoamingEvents( +async def _search_event( + apisession, + org_id: UUID, + event_source: EventSource, + event_type: str, + site_id: UUID, + mac: str, + text: str, + ssid: str, + start: int, + end: int, + limit: int, +): + if not event_source: + raise ToolError( + { + "status_code": 400, + "message": "`event_source` is required when `search_type` is `event`.", + } + ) + + if event_source in [EventSource.ROAMING, EventSource.ROGUE] and not site_id: + raise ToolError( + { + "status_code": 400, + "message": f"`site_id` parameter is required when `event_source` is `{event_source.value}`.", + } + ) + + if text and event_source not in [EventSource.DEVICE, EventSource.NAC_CLIENT]: + raise ToolError( + { + "status_code": 400, + "message": '`text` parameter can only be used when `event_source` is in "device", "nac_client".', + } + ) + + if ssid and event_source not in [ + EventSource.WIRELESS_CLIENT, + EventSource.NAC_CLIENT, + EventSource.ROGUE, + ]: + raise ToolError( + { + "status_code": 400, + "message": '`ssid` parameter can only be used when `event_source` is in "wireless_client", "nac_client", "rogue".', + } + ) + + match event_source: + case EventSource.DEVICE: + if site_id: + response = mistapi.api.v1.sites.devices.searchSiteDeviceEvents( apisession, site_id=str(site_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + text=str(text) if text else None, limit=limit, ) - await process_response(response) - case "rogue": - response = mistapi.api.v1.sites.rogues.searchSiteRogueEvents( + else: + response = mistapi.api.v1.orgs.devices.searchOrgDeviceEvents( + apisession, + org_id=str(org_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + text=str(text) if text else None, + limit=limit, + ) + case EventSource.MXEDGE: + mxedge_id = f"00000000-0000-0000-1000-{str(mac)}" if mac else None + if site_id: + response = mistapi.api.v1.sites.mxedges.searchSiteMistEdgeEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mxedge_id=mxedge_id, + limit=limit, + ) + else: + response = mistapi.api.v1.orgs.mxedges.searchOrgMistEdgeEvents( + apisession, + org_id=str(org_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mxedge_id=mxedge_id, + limit=limit, + ) + case EventSource.WAN_CLIENT: + if site_id: + response = mistapi.api.v1.sites.wan_clients.searchSiteWanClientEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + limit=limit, + ) + else: + response = mistapi.api.v1.orgs.wan_clients.searchOrgWanClientEvents( + apisession, + org_id=str(org_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + limit=limit, + ) + case EventSource.WIRELESS_CLIENT: + if site_id: + response = mistapi.api.v1.sites.clients.searchSiteWirelessClientEvents( apisession, site_id=str(site_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, ssid=str(ssid) if ssid else None, - ap_mac=str(mac) if mac else None, limit=limit, ) - await process_response(response) - - case _: - raise ToolError( - { - "status_code": 400, - "message": f"Invalid object_type: {object_type.value}. Valid values are: {[e.value for e in Event_source]}", - } + else: + response = mistapi.api.v1.orgs.clients.searchOrgWirelessClientEvents( + apisession, + org_id=str(org_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + ssid=str(ssid) if ssid else None, + limit=limit, + ) + case EventSource.NAC_CLIENT: + if site_id: + response = mistapi.api.v1.sites.nac_clients.searchSiteNacClientEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + text=str(text) if text else None, + ssid=str(ssid) if ssid else None, + limit=limit, ) + else: + response = mistapi.api.v1.orgs.nac_clients.searchOrgNacClientEvents( + apisession, + org_id=str(org_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + text=str(text) if text else None, + ssid=str(ssid) if ssid else None, + limit=limit, + ) + case EventSource.ROAMING: + response = mistapi.api.v1.sites.events.listSiteRoamingEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + limit=limit, + ) + case EventSource.ROGUE: + response = mistapi.api.v1.sites.rogues.searchSiteRogueEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + ssid=str(ssid) if ssid else None, + ap_mac=str(mac) if mac else None, + limit=limit, + ) + case _: + raise ToolError( + { + "status_code": 400, + "message": f"Invalid event_source: {event_source.value}. Valid values are: {[e.value for e in EventSource]}", + } + ) - except ToolError: - raise - except Exception as _exc: - await handle_network_error(_exc) + await process_response(response) + return response - return format_response(response, response_format) + +async def _search_alarm( + apisession, + org_id: UUID, + site_id: UUID, + group: str, + severity: str, + alarm_type: str, + acked: bool, + start: int, + end: int, + limit: int, +): + if site_id: + response = mistapi.api.v1.sites.alarms.searchSiteAlarms( + apisession, + site_id=str(site_id), + group=group if group else None, + severity=severity if severity else None, + type=alarm_type if alarm_type else None, + acked=acked if acked is not None else None, + start=str(start) if start else None, + end=str(end) if end else None, + limit=limit, + ) + else: + response = mistapi.api.v1.orgs.alarms.searchOrgAlarms( + apisession, + org_id=str(org_id), + group=group if group else None, + severity=severity if severity else None, + type=alarm_type if alarm_type else None, + acked=acked if acked is not None else None, + start=str(start) if start else None, + end=str(end) if end else None, + limit=limit, + ) + + await process_response(response) + return response + + +def _validate_event_params_not_used( + event_source: EventSource, + event_type: str, + mac: str, + text: str, + ssid: str, +) -> None: + if event_source or event_type or mac or text or ssid: + raise ToolError( + { + "status_code": 400, + "message": "`event_source`, `event_type`, `mac`, `text`, and `ssid` can only be used when `search_type` is `event`.", + } + ) + + +def _validate_alarm_params_not_used( + group: str, + severity: str, + alarm_type: str, + acked: bool, +) -> None: + if group or severity or alarm_type or acked is not None: + raise ToolError( + { + "status_code": 400, + "message": "`group`, `severity`, `alarm_type`, and `acked` can only be used when `search_type` is `alarm`.", + } + ) From f187133aed4b11292f6816a125c7f49939596ac7 Mon Sep 17 00:00:00 2001 From: Thomas Munzer Date: Wed, 10 Jun 2026 15:43:14 -0700 Subject: [PATCH 2/6] fix: validate merged event search parameters Reject cross-mode parameters instead of silently ignoring them in the unified event/alarm search tool, and validate MX Edge MAC filters before building the derived MX Edge UUID. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/mistmcp/tools/search_events.py | 33 +++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/mistmcp/tools/search_events.py b/src/mistmcp/tools/search_events.py index 2cc209f..0352788 100644 --- a/src/mistmcp/tools/search_events.py +++ b/src/mistmcp/tools/search_events.py @@ -191,6 +191,12 @@ async def search_events( try: match search_type: case SearchType.EVENT: + _validate_alarm_params_not_used( + group=group, + severity=severity, + alarm_type=alarm_type, + acked=acked, + ) response = await _search_event( apisession=apisession, org_id=org_id, @@ -205,6 +211,13 @@ async def search_events( limit=limit, ) case SearchType.ALARM: + _validate_event_params_not_used( + event_source=event_source, + event_type=event_type, + mac=mac, + text=text, + ssid=ssid, + ) response = await _search_alarm( apisession=apisession, org_id=org_id, @@ -324,7 +337,7 @@ async def _search_event( limit=limit, ) case EventSource.MXEDGE: - mxedge_id = f"00000000-0000-0000-1000-{str(mac)}" if mac else None + mxedge_id = _mxedge_id_from_mac(mac) if site_id: response = mistapi.api.v1.sites.mxedges.searchSiteMistEdgeEvents( apisession, @@ -444,6 +457,24 @@ async def _search_event( return response +def _mxedge_id_from_mac(mac: str) -> str | None: + if not mac: + return None + + normalized_mac = str(mac).replace(":", "").replace("-", "").replace(".", "").lower() + if len(normalized_mac) != 12 or not all( + char in "0123456789abcdef" for char in normalized_mac + ): + raise ToolError( + { + "status_code": 400, + "message": "`mac` must be a 12-character MAC address when `event_source` is `mxedge`.", + } + ) + + return f"00000000-0000-0000-1000-{normalized_mac}" + + async def _search_alarm( apisession, org_id: UUID, From de7ab19f28a1677eec75d2f6cee8726eb5b2f35f Mon Sep 17 00:00:00 2001 From: Thomas Munzer Date: Wed, 10 Jun 2026 15:55:28 -0700 Subject: [PATCH 3/6] fix: keep generated consolidated tools stable Wire the consolidated event/alarm and upgrade tools into make generate so regenerated output preserves mist_search_events, mist_get_sle, and mist_upgrades instead of recreating split tool files. Also align the search-client template with the checked-in generated behavior so make generate is idempotent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- mcp_generator/generate_from_openapi.py | 38 ++++++++++++++++++- mcp_generator/templates/tmpl_search_client.py | 35 ++++++----------- mcp_generator/tools_optimization.yaml | 2 + src/mistmcp/tool_helper.py | 2 +- src/mistmcp/tools/search_client.py | 14 ++++--- src/mistmcp/tools/upgrades.py | 3 +- 6 files changed, 61 insertions(+), 33 deletions(-) diff --git a/mcp_generator/generate_from_openapi.py b/mcp_generator/generate_from_openapi.py index c6a8e01..541fed5 100644 --- a/mcp_generator/generate_from_openapi.py +++ b/mcp_generator/generate_from_openapi.py @@ -68,7 +68,6 @@ from mcp_generator.templates.tmpl_tool_change_configuration_objects import ( CHANGE_CONFIGURATION_OBJECTS_OPERATION_IDS, CHANGE_CONFIGURATION_OBJECTS_TEMPLATE, - CHANGE_OPERATIONS, ) from mcp_generator.templates.tmpl_tool_read import TOOL_TEMPLATE_READ from mcp_generator.templates.tmpl_tool_search_device import ( @@ -77,6 +76,10 @@ from mcp_generator.templates.tmpl_tool_update_configuration_objects import ( UPDATE_CONFIGURATION_OBJECTS_TEMPLATE, ) + from mcp_generator.templates.tmpl_tool_upgrade import ( + TOOL_TEMPLATE_UPGRADE, + UPGRADE_OPERATIONS, + ) from mcp_generator.templates.tmpl_tool_utilities import UTILITIES_TEMPLATE from mcp_generator.templates.tmpl_tool_write import TOOL_TEMPLATE_WRITE from mcp_generator.templates.tmpl_tool_write_delete import ( @@ -102,7 +105,6 @@ from templates.tmpl_tool_change_configuration_objects import ( CHANGE_CONFIGURATION_OBJECTS_OPERATION_IDS, CHANGE_CONFIGURATION_OBJECTS_TEMPLATE, - CHANGE_OPERATIONS, ) from templates.tmpl_tool_read import TOOL_TEMPLATE_READ from templates.tmpl_tool_search_device import TOOL_TEMPLATE_SEARCH_DEVICE @@ -132,6 +134,26 @@ os.path.join( DIR_PATH, "../src/mistmcp/tools/schemas_data.py") ) +SEARCH_EVENTS_OPERATION_IDS = [ + "searchSiteDeviceEvents", + "searchOrgDeviceEvents", + "searchSiteMistEdgeEvents", + "searchOrgMistEdgeEvents", + "searchSiteWanClientEvents", + "searchOrgWanClientEvents", + "searchSiteWirelessClientEvents", + "searchOrgWirelessClientEvents", + "searchSiteNacClientEvents", + "searchOrgNacClientEvents", + "listSiteRoamingEvents", + "searchSiteRogueEvents", + "searchOrgAlarms", + "searchSiteAlarms", + "listOrgSuppressedAlarms", +] +SEARCH_EVENTS_TEMPLATE = Path( + os.path.join(DIR_PATH, "../src/mistmcp/tools/search_events.py") +).read_text(encoding="utf-8") # List of custom tools to generate (not directly from OpenAPI) CUSTOM_TOOLS = [ { @@ -188,6 +210,18 @@ "tag": "clients", "operation_ids": SEARCH_CLIENT_OPERATION_IDS, }, + { + "name": "search_events", + "template": SEARCH_EVENTS_TEMPLATE, + "tag": "events", + "operation_ids": SEARCH_EVENTS_OPERATION_IDS, + }, + { + "name": "upgrades", + "template": TOOL_TEMPLATE_UPGRADE, + "tag": "utilities_upgrade", + "operation_ids": UPGRADE_OPERATIONS, + }, ] # Global read-only hint for tool generation READ_ONLY_HINT = True diff --git a/mcp_generator/templates/tmpl_search_client.py b/mcp_generator/templates/tmpl_search_client.py index c0e8efa..331d193 100644 --- a/mcp_generator/templates/tmpl_search_client.py +++ b/mcp_generator/templates/tmpl_search_client.py @@ -74,7 +74,7 @@ async def search_client( ), ], org_id: Annotated[UUID, Field(description="""Organization ID""")], - site_id: Annotated[UUID, Field(description="""Site ID""", default=None)], + site_id: Annotated[UUID, Field(description="""Site ID. Required for site_guest, optional for other client types""", default=None)], device_mac: Annotated[ str, Field( @@ -99,7 +99,7 @@ async def search_client( hostname: Annotated[ str, Field( - description="""Partial / full Client hostname. Use `prefix*` for prefix search or `*substring*` for contains search (e.g. `everest*` and `*rest*` match `my-everest-client`). Suffix-only wildcards (e.g. `*everest`) are not supported. Not applicable for WAN or wired clients or Org/Site Guests""", + description="""Partial / full Client hostname. Use `prefix*` for prefix search or `*substring*` for contains search (e.g. `everest*` and `*rest*` match `my-everest-client`). Suffix-only wildcards (e.g. `*everest`) are not supported. Not applicable for wired clients or Org/Site Guests""", default=None, ), ], @@ -110,13 +110,6 @@ async def search_client( default=None, ), ], - wlan_id: Annotated[ - UUID, - Field( - description="""WLAN ID to filter by. Only applicable for wireless clients and Guests""", - default=None, - ), - ], ssid: Annotated[ str, Field( @@ -150,7 +143,7 @@ async def search_client( logger.debug("Tool search_client called") logger.debug( - "Input Parameters: client_type: %s, org_id: %s, site_id: %s, device_mac: %s, band: %s, mac: %s, hostname: %s, ip: %s, wlan_id: %s, ssid: %s, text: %s, start: %s, end: %s, limit: %s", + "Input Parameters: client_type: %s, org_id: %s, site_id: %s, device_mac: %s, band: %s, mac: %s, hostname: %s, ip: %s, ssid: %s, text: %s, start: %s, end: %s, limit: %s", client_type, org_id, site_id, @@ -159,7 +152,6 @@ async def search_client( mac, hostname, ip, - wlan_id, ssid, text, start, @@ -188,11 +180,11 @@ async def search_client( } ) - if hostname and client_type.value not in ["wireless", "nac"]: + if hostname and client_type.value not in ["wireless", "nac", "wan"]: raise ToolError( { "status_code": 400, - "message": '`hostname` parameter can only be used when `client_type` is in "wireless", "nac".', + "message": '`hostname` parameter can only be used when `client_type` is in "wireless", "nac", "wan".', } ) @@ -204,14 +196,6 @@ async def search_client( } ) - if wlan_id and client_type.value not in ["wireless", "org_guest", "site_guest"]: - raise ToolError( - { - "status_code": 400, - "message": '`wlan_id` parameter can only be used when `client_type` is in "wireless", "org_guest", "site_guest".', - } - ) - if ssid and client_type.value not in [ "wireless", "org_guest", @@ -303,13 +287,19 @@ async def search_client( apisession, org_id=str(org_id), ssid=str(ssid) if ssid else None, - wlan_id=str(wlan_id) if wlan_id else None, start=str(start) if start else None, end=str(end) if end else None, limit=limit, ) await process_response(response) case "site_guest": + if not site_id: + raise ToolError( + { + "status_code": 400, + "message": '`site_id` parameter is required when `client_type` is "site_guest".', + } + ) if mac: response = mistapi.api.v1.sites.guests.getSiteGuestAuthorization( apisession, site_id=str(site_id), guest_mac=str(mac) @@ -320,7 +310,6 @@ async def search_client( apisession, site_id=str(site_id), ssid=str(ssid) if ssid else None, - wlan_id=str(wlan_id) if wlan_id else None, start=str(start) if start else None, end=str(end) if end else None, limit=limit, diff --git a/mcp_generator/tools_optimization.yaml b/mcp_generator/tools_optimization.yaml index abde124..236ca56 100644 --- a/mcp_generator/tools_optimization.yaml +++ b/mcp_generator/tools_optimization.yaml @@ -787,6 +787,7 @@ getStats: function: mistapi.api.v1.sites.stats.searchSiteSwOrGwPorts(apisession, site_id=str(site_id), mac=str(object_id) if object_id else None, limit=limit) searchEvents: + skip: true type: tool_consolidation tags: [events] description: |- @@ -1436,6 +1437,7 @@ listRogueDevices: # function: mistapi.api.v1.sites.sle.listSiteSleMetricClassifiers(apisession, site_id=str(site_id), scope=scope.value, scope_id=scope_id, metric=metric) searchAlarms: + skip: true type: tool_consolidation tags: [events] description: |- diff --git a/src/mistmcp/tool_helper.py b/src/mistmcp/tool_helper.py index ee7d717..5f8823c 100644 --- a/src/mistmcp/tool_helper.py +++ b/src/mistmcp/tool_helper.py @@ -22,6 +22,7 @@ class McpToolsCategory(Enum): UTILITIES = "utilities" SLES = "sles" CLIENTS = "clients" + EVENTS = "events" UTILITIES_UPGRADE = "utilities_upgrade" SITES_INSIGHTS = "sites_insights" CONSTANTS = "constants" @@ -29,7 +30,6 @@ class McpToolsCategory(Enum): SITES_RRM = "sites_rrm" ORGS = "orgs" STATS = "stats" - EVENTS = "events" SITES_ROGUES = "sites_rogues" ORGS_NAC = "orgs_nac" MARVIS = "marvis" diff --git a/src/mistmcp/tools/search_client.py b/src/mistmcp/tools/search_client.py index 95d7c5b..15a8931 100644 --- a/src/mistmcp/tools/search_client.py +++ b/src/mistmcp/tools/search_client.py @@ -63,7 +63,13 @@ async def search_client( ), ], org_id: Annotated[UUID, Field(description="""Organization ID""")], - site_id: Annotated[UUID, Field(description="""Site ID. Required for site_guest, optional for other client types""", default=None)], + site_id: Annotated[ + UUID, + Field( + description="""Site ID. Required for site_guest, optional for other client types""", + default=None, + ), + ], device_mac: Annotated[ str, Field( @@ -114,12 +120,10 @@ async def search_client( ), ], start: Annotated[ - int, Field( - description="""Start of time range (epoch seconds)""", default=None) + int, Field(description="""Start of time range (epoch seconds)""", default=None) ], end: Annotated[ - int, Field( - description="""End of time range (epoch seconds)""", default=None) + int, Field(description="""End of time range (epoch seconds)""", default=None) ], limit: Annotated[ int, Field(description="""Max number of results per page""", default=20) diff --git a/src/mistmcp/tools/upgrades.py b/src/mistmcp/tools/upgrades.py index fd1eb22..abff48a 100644 --- a/src/mistmcp/tools/upgrades.py +++ b/src/mistmcp/tools/upgrades.py @@ -283,8 +283,7 @@ def _build_payload_description() -> str: for action in sorted(PAYLOAD_REQUIRED_ACTIONS, key=lambda value: value.value): contract = PAYLOAD_CONTRACTS[action] - required = ", ".join(contract["required"] - ) if contract["required"] else "none" + required = ", ".join(contract["required"]) if contract["required"] else "none" attributes = ", ".join(contract["attributes"]) attribute_descriptions = _format_attribute_descriptions(contract) example_text = json.dumps(contract["example"], ensure_ascii=True) From da2614a172c6d5f9993ed8ff25939657f84901aa Mon Sep 17 00:00:00 2001 From: Thomas Munzer Date: Wed, 10 Jun 2026 16:13:57 -0700 Subject: [PATCH 4/6] feat: add search events functionality with operation IDs and template --- mcp_generator/generate_from_openapi.py | 28 +- mcp_generator/templates/tmpl_search_events.py | 566 ++++++++++++++++++ 2 files changed, 574 insertions(+), 20 deletions(-) create mode 100644 mcp_generator/templates/tmpl_search_events.py diff --git a/mcp_generator/generate_from_openapi.py b/mcp_generator/generate_from_openapi.py index 541fed5..c48ff42 100644 --- a/mcp_generator/generate_from_openapi.py +++ b/mcp_generator/generate_from_openapi.py @@ -65,6 +65,10 @@ REQ_OPTIMIZED_TEMPLATE, REQ_TEMPLATE, ) + from mcp_generator.templates.tmpl_search_events import ( + SEARCH_EVENTS_OPERATION_IDS, + SEARCH_EVENTS_TEMPLATE, + ) from mcp_generator.templates.tmpl_tool_change_configuration_objects import ( CHANGE_CONFIGURATION_OBJECTS_OPERATION_IDS, CHANGE_CONFIGURATION_OBJECTS_TEMPLATE, @@ -102,6 +106,10 @@ SEARCH_CLIENT_OPERATION_IDS, SEARCH_CLIENT_TEMPLATE, ) + from templates.tmpl_search_events import ( + SEARCH_EVENTS_OPERATION_IDS, + SEARCH_EVENTS_TEMPLATE, + ) from templates.tmpl_tool_change_configuration_objects import ( CHANGE_CONFIGURATION_OBJECTS_OPERATION_IDS, CHANGE_CONFIGURATION_OBJECTS_TEMPLATE, @@ -134,26 +142,6 @@ os.path.join( DIR_PATH, "../src/mistmcp/tools/schemas_data.py") ) -SEARCH_EVENTS_OPERATION_IDS = [ - "searchSiteDeviceEvents", - "searchOrgDeviceEvents", - "searchSiteMistEdgeEvents", - "searchOrgMistEdgeEvents", - "searchSiteWanClientEvents", - "searchOrgWanClientEvents", - "searchSiteWirelessClientEvents", - "searchOrgWirelessClientEvents", - "searchSiteNacClientEvents", - "searchOrgNacClientEvents", - "listSiteRoamingEvents", - "searchSiteRogueEvents", - "searchOrgAlarms", - "searchSiteAlarms", - "listOrgSuppressedAlarms", -] -SEARCH_EVENTS_TEMPLATE = Path( - os.path.join(DIR_PATH, "../src/mistmcp/tools/search_events.py") -).read_text(encoding="utf-8") # List of custom tools to generate (not directly from OpenAPI) CUSTOM_TOOLS = [ { diff --git a/mcp_generator/templates/tmpl_search_events.py b/mcp_generator/templates/tmpl_search_events.py new file mode 100644 index 0000000..4567ddc --- /dev/null +++ b/mcp_generator/templates/tmpl_search_events.py @@ -0,0 +1,566 @@ +SEARCH_EVENTS_OPERATION_IDS = [ + "searchSiteDeviceEvents", + "searchOrgDeviceEvents", + "searchSiteMistEdgeEvents", + "searchOrgMistEdgeEvents", + "searchSiteWanClientEvents", + "searchOrgWanClientEvents", + "searchSiteWirelessClientEvents", + "searchOrgWirelessClientEvents", + "searchSiteNacClientEvents", + "searchOrgNacClientEvents", + "listSiteRoamingEvents", + "searchSiteRogueEvents", + "searchOrgAlarms", + "searchSiteAlarms", + "listOrgSuppressedAlarms", +] + +SEARCH_EVENTS_TEMPLATE = '''""" +-------------------------------------------------------------------------------- +-------------------------------- Mist MCP SERVER ------------------------------- + + Written by: Thomas Munzer (tmunzer@juniper.net) + Github : https://github.com/tmunzer/mistmcp + + This package is licensed under the MIT License. + +-------------------------------------------------------------------------------- +""" + +import mistapi +from fastmcp.exceptions import ToolError +from mistmcp.request_processor import get_apisession +from mistmcp.response_processor import process_response, handle_network_error +from mistmcp.response_formatter import format_response +from mistmcp.server import mcp +from mistmcp.logger import logger + +from pydantic import Field +from typing import Annotated +from enum import Enum +from uuid import UUID + + +class SearchType(Enum): + EVENT = "event" + ALARM = "alarm" + SUPPRESSED_ALARM = "suppressed_alarm" + + +class EventSource(Enum): + DEVICE = "device" + MXEDGE = "mxedge" + WAN_CLIENT = "wan_client" + WIRELESS_CLIENT = "wireless_client" + NAC_CLIENT = "nac_client" + ROAMING = "roaming" + ROGUE = "rogue" + + +@mcp.tool( + name="mist_search_events", + description="""Search for Mist events and alarms across an organization or site. + +Use `search_type=event` to search event streams from devices, MX Edge instances, clients, roaming, or rogue APs. +Use `search_type=alarm` to search raised alarms. If `site_id` is provided, site alarms are searched; otherwise org alarms are searched. +Use `search_type=suppressed_alarm` to list temporarily disabled alarms for the organization. + +For event types, use `mist_get_constants` with: +- `object_type=device_events` for device events +- `object_type=mxedge_events` for MX Edge events +- `object_type=client_events` for WAN/wireless client events +- `object_type=nac_events` for NAC client events + +For alarm types, use `mist_get_constants` with `object_type=alarm_definitions`.""", + tags={"events"}, + annotations={ + "title": "Search events", + "readOnlyHint": True, + "destructiveHint": False, + "openWorldHint": True, + "idempotentHint": True, + }, +) +async def search_events( + search_type: Annotated[ + SearchType, + Field( + description="""Type of event-like data to search: `event`, `alarm`, or `suppressed_alarm`""" + ), + ], + org_id: Annotated[UUID, Field(description="""Organization ID""")], + event_source: Annotated[ + EventSource, + Field( + description="""Required when search_type is `event`. Event source type: device, mxedge, wan_client, wireless_client, nac_client, roaming (requires site_id), or rogue (requires site_id)""", + default=None, + ), + ], + event_type: Annotated[ + str, + Field( + description="""Only for search_type=event. Comma-separated event types to filter by. Use `mist_get_constants` to discover available values for the selected event_source""", + default=None, + ), + ], + site_id: Annotated[ + UUID, + Field( + description="""Site ID. For search_type=alarm, providing site_id searches site alarms; omitting it searches org alarms. Required for event_source=roaming or rogue. Optional for other event sources to narrow results to a site""", + default=None, + ), + ], + mac: Annotated[ + str, + Field( + description="""Only for search_type=event. MAC address filter for device, mxedge, WAN client, NAC client, or rogue events""", + default=None, + ), + ], + text: Annotated[ + str, + Field( + description="""Only for search_type=event with event_source=device or nac_client. Text search in event details""", + default=None, + ), + ], + ssid: Annotated[ + str, + Field( + description="""Only for search_type=event with event_source=wireless_client, nac_client, or rogue. SSID filter""", + default=None, + ), + ], + group: Annotated[ + str, + Field( + description="""Only for search_type=alarm. Alarm group: `infrastructure`, `marvis`, or `security`""", + default=None, + ), + ], + severity: Annotated[ + str, + Field( + description="""Only for search_type=alarm. Alarm severity: `critical`, `major`, `minor`, `warn`, or `info`""", + default=None, + ), + ], + alarm_type: Annotated[ + str, + Field( + description="""Only for search_type=alarm. Comma-separated alarm types (e.g., `bad_cable,auth_failure`). Use `mist_get_constants` with `object_type=alarm_definitions` to discover available alarm types""", + default=None, + ), + ], + acked: Annotated[ + bool, + Field( + description="""Only for search_type=alarm. Filter acknowledged (true) or unacknowledged (false) alarms""", + default=None, + ), + ], + start: Annotated[ + int, + Field( + description="""Start of time range (epoch seconds). Used for search_type=event or alarm; ignored for suppressed_alarm""", + default=None, + ), + ], + end: Annotated[ + int, + Field( + description="""End of time range (epoch seconds). Used for search_type=event or alarm; ignored for suppressed_alarm""", + default=None, + ), + ], + limit: Annotated[ + int, + Field( + description="""Max number of results per page. Used for search_type=event or alarm; ignored for suppressed_alarm""", + default=20, + ), + ] = 20, +) -> dict | list | str: + """Search for Mist events and alarms across an organization or site.""" + + logger.debug("Tool search_events called") + logger.debug( + "Input Parameters: search_type: %s, org_id: %s, event_source: %s, event_type: %s, site_id: %s, mac: %s, text: %s, ssid: %s, group: %s, severity: %s, alarm_type: %s, acked: %s, start: %s, end: %s, limit: %s", + search_type, + org_id, + event_source, + event_type, + site_id, + mac, + text, + ssid, + group, + severity, + alarm_type, + acked, + start, + end, + limit, + ) + + apisession, response_format = await get_apisession() + + try: + match search_type: + case SearchType.EVENT: + _validate_alarm_params_not_used( + group=group, + severity=severity, + alarm_type=alarm_type, + acked=acked, + ) + response = await _search_event( + apisession=apisession, + org_id=org_id, + event_source=event_source, + event_type=event_type, + site_id=site_id, + mac=mac, + text=text, + ssid=ssid, + start=start, + end=end, + limit=limit, + ) + case SearchType.ALARM: + _validate_event_params_not_used( + event_source=event_source, + event_type=event_type, + mac=mac, + text=text, + ssid=ssid, + ) + response = await _search_alarm( + apisession=apisession, + org_id=org_id, + site_id=site_id, + group=group, + severity=severity, + alarm_type=alarm_type, + acked=acked, + start=start, + end=end, + limit=limit, + ) + case SearchType.SUPPRESSED_ALARM: + _validate_event_params_not_used( + event_source=event_source, + event_type=event_type, + mac=mac, + text=text, + ssid=ssid, + ) + _validate_alarm_params_not_used( + group=group, + severity=severity, + alarm_type=alarm_type, + acked=acked, + ) + response = mistapi.api.v1.orgs.alarmtemplates.listOrgSuppressedAlarms( + apisession, org_id=str(org_id) + ) + await process_response(response) + case _: + raise ToolError( + { + "status_code": 400, + "message": f"Invalid search_type: {search_type.value}. Valid values are: {[e.value for e in SearchType]}", + } + ) + except ToolError: + raise + except Exception as _exc: + await handle_network_error(_exc) + + return format_response(response, response_format) + + +async def _search_event( + apisession, + org_id: UUID, + event_source: EventSource, + event_type: str, + site_id: UUID, + mac: str, + text: str, + ssid: str, + start: int, + end: int, + limit: int, +): + if not event_source: + raise ToolError( + { + "status_code": 400, + "message": "`event_source` is required when `search_type` is `event`.", + } + ) + + if event_source in [EventSource.ROAMING, EventSource.ROGUE] and not site_id: + raise ToolError( + { + "status_code": 400, + "message": f"`site_id` parameter is required when `event_source` is `{event_source.value}`.", + } + ) + + if text and event_source not in [EventSource.DEVICE, EventSource.NAC_CLIENT]: + raise ToolError( + { + "status_code": 400, + "message": '`text` parameter can only be used when `event_source` is in "device", "nac_client".', + } + ) + + if ssid and event_source not in [ + EventSource.WIRELESS_CLIENT, + EventSource.NAC_CLIENT, + EventSource.ROGUE, + ]: + raise ToolError( + { + "status_code": 400, + "message": '`ssid` parameter can only be used when `event_source` is in "wireless_client", "nac_client", "rogue".', + } + ) + + match event_source: + case EventSource.DEVICE: + if site_id: + response = mistapi.api.v1.sites.devices.searchSiteDeviceEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + text=str(text) if text else None, + limit=limit, + ) + else: + response = mistapi.api.v1.orgs.devices.searchOrgDeviceEvents( + apisession, + org_id=str(org_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + text=str(text) if text else None, + limit=limit, + ) + case EventSource.MXEDGE: + mxedge_id = _mxedge_id_from_mac(mac) + if site_id: + response = mistapi.api.v1.sites.mxedges.searchSiteMistEdgeEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mxedge_id=mxedge_id, + limit=limit, + ) + else: + response = mistapi.api.v1.orgs.mxedges.searchOrgMistEdgeEvents( + apisession, + org_id=str(org_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mxedge_id=mxedge_id, + limit=limit, + ) + case EventSource.WAN_CLIENT: + if site_id: + response = mistapi.api.v1.sites.wan_clients.searchSiteWanClientEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + limit=limit, + ) + else: + response = mistapi.api.v1.orgs.wan_clients.searchOrgWanClientEvents( + apisession, + org_id=str(org_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + limit=limit, + ) + case EventSource.WIRELESS_CLIENT: + if site_id: + response = mistapi.api.v1.sites.clients.searchSiteWirelessClientEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + ssid=str(ssid) if ssid else None, + limit=limit, + ) + else: + response = mistapi.api.v1.orgs.clients.searchOrgWirelessClientEvents( + apisession, + org_id=str(org_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + ssid=str(ssid) if ssid else None, + limit=limit, + ) + case EventSource.NAC_CLIENT: + if site_id: + response = mistapi.api.v1.sites.nac_clients.searchSiteNacClientEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + text=str(text) if text else None, + ssid=str(ssid) if ssid else None, + limit=limit, + ) + else: + response = mistapi.api.v1.orgs.nac_clients.searchOrgNacClientEvents( + apisession, + org_id=str(org_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + mac=str(mac) if mac else None, + text=str(text) if text else None, + ssid=str(ssid) if ssid else None, + limit=limit, + ) + case EventSource.ROAMING: + response = mistapi.api.v1.sites.events.listSiteRoamingEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + limit=limit, + ) + case EventSource.ROGUE: + response = mistapi.api.v1.sites.rogues.searchSiteRogueEvents( + apisession, + site_id=str(site_id), + start=str(start) if start else None, + end=str(end) if end else None, + type=str(event_type) if event_type else None, + ssid=str(ssid) if ssid else None, + ap_mac=str(mac) if mac else None, + limit=limit, + ) + case _: + raise ToolError( + { + "status_code": 400, + "message": f"Invalid event_source: {event_source.value}. Valid values are: {[e.value for e in EventSource]}", + } + ) + + await process_response(response) + return response + + +def _mxedge_id_from_mac(mac: str) -> str | None: + if not mac: + return None + + normalized_mac = str(mac).replace(":", "").replace("-", "").replace(".", "").lower() + if len(normalized_mac) != 12 or not all( + char in "0123456789abcdef" for char in normalized_mac + ): + raise ToolError( + { + "status_code": 400, + "message": "`mac` must be a 12-character MAC address when `event_source` is `mxedge`.", + } + ) + + return f"00000000-0000-0000-1000-{normalized_mac}" + + +async def _search_alarm( + apisession, + org_id: UUID, + site_id: UUID, + group: str, + severity: str, + alarm_type: str, + acked: bool, + start: int, + end: int, + limit: int, +): + if site_id: + response = mistapi.api.v1.sites.alarms.searchSiteAlarms( + apisession, + site_id=str(site_id), + group=group if group else None, + severity=severity if severity else None, + type=alarm_type if alarm_type else None, + acked=acked if acked is not None else None, + start=str(start) if start else None, + end=str(end) if end else None, + limit=limit, + ) + else: + response = mistapi.api.v1.orgs.alarms.searchOrgAlarms( + apisession, + org_id=str(org_id), + group=group if group else None, + severity=severity if severity else None, + type=alarm_type if alarm_type else None, + acked=acked if acked is not None else None, + start=str(start) if start else None, + end=str(end) if end else None, + limit=limit, + ) + + await process_response(response) + return response + + +def _validate_event_params_not_used( + event_source: EventSource, + event_type: str, + mac: str, + text: str, + ssid: str, +) -> None: + if event_source or event_type or mac or text or ssid: + raise ToolError( + { + "status_code": 400, + "message": "`event_source`, `event_type`, `mac`, `text`, and `ssid` can only be used when `search_type` is `event`.", + } + ) + + +def _validate_alarm_params_not_used( + group: str, + severity: str, + alarm_type: str, + acked: bool, +) -> None: + if group or severity or alarm_type or acked is not None: + raise ToolError( + { + "status_code": 400, + "message": "`group`, `severity`, `alarm_type`, and `acked` can only be used when `search_type` is `alarm`.", + } + ) +''' From 6cafdc207a9f929832676531677935b20b49d422 Mon Sep 17 00:00:00 2001 From: Thomas Munzer Date: Wed, 10 Jun 2026 16:43:00 -0700 Subject: [PATCH 5/6] fix: mark event search optional params nullable Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- mcp_generator/templates/tmpl_search_events.py | 74 +++++++++---------- src/mistmcp/tools/search_events.py | 74 +++++++++---------- 2 files changed, 74 insertions(+), 74 deletions(-) diff --git a/mcp_generator/templates/tmpl_search_events.py b/mcp_generator/templates/tmpl_search_events.py index 4567ddc..f4c8491 100644 --- a/mcp_generator/templates/tmpl_search_events.py +++ b/mcp_generator/templates/tmpl_search_events.py @@ -91,84 +91,84 @@ async def search_events( ], org_id: Annotated[UUID, Field(description="""Organization ID""")], event_source: Annotated[ - EventSource, + EventSource | None, Field( description="""Required when search_type is `event`. Event source type: device, mxedge, wan_client, wireless_client, nac_client, roaming (requires site_id), or rogue (requires site_id)""", default=None, ), ], event_type: Annotated[ - str, + str | None, Field( description="""Only for search_type=event. Comma-separated event types to filter by. Use `mist_get_constants` to discover available values for the selected event_source""", default=None, ), ], site_id: Annotated[ - UUID, + UUID | None, Field( description="""Site ID. For search_type=alarm, providing site_id searches site alarms; omitting it searches org alarms. Required for event_source=roaming or rogue. Optional for other event sources to narrow results to a site""", default=None, ), ], mac: Annotated[ - str, + str | None, Field( description="""Only for search_type=event. MAC address filter for device, mxedge, WAN client, NAC client, or rogue events""", default=None, ), ], text: Annotated[ - str, + str | None, Field( description="""Only for search_type=event with event_source=device or nac_client. Text search in event details""", default=None, ), ], ssid: Annotated[ - str, + str | None, Field( description="""Only for search_type=event with event_source=wireless_client, nac_client, or rogue. SSID filter""", default=None, ), ], group: Annotated[ - str, + str | None, Field( description="""Only for search_type=alarm. Alarm group: `infrastructure`, `marvis`, or `security`""", default=None, ), ], severity: Annotated[ - str, + str | None, Field( description="""Only for search_type=alarm. Alarm severity: `critical`, `major`, `minor`, `warn`, or `info`""", default=None, ), ], alarm_type: Annotated[ - str, + str | None, Field( description="""Only for search_type=alarm. Comma-separated alarm types (e.g., `bad_cable,auth_failure`). Use `mist_get_constants` with `object_type=alarm_definitions` to discover available alarm types""", default=None, ), ], acked: Annotated[ - bool, + bool | None, Field( description="""Only for search_type=alarm. Filter acknowledged (true) or unacknowledged (false) alarms""", default=None, ), ], start: Annotated[ - int, + int | None, Field( description="""Start of time range (epoch seconds). Used for search_type=event or alarm; ignored for suppressed_alarm""", default=None, ), ], end: Annotated[ - int, + int | None, Field( description="""End of time range (epoch seconds). Used for search_type=event or alarm; ignored for suppressed_alarm""", default=None, @@ -284,14 +284,14 @@ async def search_events( async def _search_event( apisession, org_id: UUID, - event_source: EventSource, - event_type: str, - site_id: UUID, - mac: str, - text: str, - ssid: str, - start: int, - end: int, + event_source: EventSource | None, + event_type: str | None, + site_id: UUID | None, + mac: str | None, + text: str | None, + ssid: str | None, + start: int | None, + end: int | None, limit: int, ): if not event_source: @@ -475,7 +475,7 @@ async def _search_event( return response -def _mxedge_id_from_mac(mac: str) -> str | None: +def _mxedge_id_from_mac(mac: str | None) -> str | None: if not mac: return None @@ -496,13 +496,13 @@ def _mxedge_id_from_mac(mac: str) -> str | None: async def _search_alarm( apisession, org_id: UUID, - site_id: UUID, - group: str, - severity: str, - alarm_type: str, - acked: bool, - start: int, - end: int, + site_id: UUID | None, + group: str | None, + severity: str | None, + alarm_type: str | None, + acked: bool | None, + start: int | None, + end: int | None, limit: int, ): if site_id: @@ -535,11 +535,11 @@ async def _search_alarm( def _validate_event_params_not_used( - event_source: EventSource, - event_type: str, - mac: str, - text: str, - ssid: str, + event_source: EventSource | None, + event_type: str | None, + mac: str | None, + text: str | None, + ssid: str | None, ) -> None: if event_source or event_type or mac or text or ssid: raise ToolError( @@ -551,10 +551,10 @@ def _validate_event_params_not_used( def _validate_alarm_params_not_used( - group: str, - severity: str, - alarm_type: str, - acked: bool, + group: str | None, + severity: str | None, + alarm_type: str | None, + acked: bool | None, ) -> None: if group or severity or alarm_type or acked is not None: raise ToolError( diff --git a/src/mistmcp/tools/search_events.py b/src/mistmcp/tools/search_events.py index 0352788..294d945 100644 --- a/src/mistmcp/tools/search_events.py +++ b/src/mistmcp/tools/search_events.py @@ -73,84 +73,84 @@ async def search_events( ], org_id: Annotated[UUID, Field(description="""Organization ID""")], event_source: Annotated[ - EventSource, + EventSource | None, Field( description="""Required when search_type is `event`. Event source type: device, mxedge, wan_client, wireless_client, nac_client, roaming (requires site_id), or rogue (requires site_id)""", default=None, ), ], event_type: Annotated[ - str, + str | None, Field( description="""Only for search_type=event. Comma-separated event types to filter by. Use `mist_get_constants` to discover available values for the selected event_source""", default=None, ), ], site_id: Annotated[ - UUID, + UUID | None, Field( description="""Site ID. For search_type=alarm, providing site_id searches site alarms; omitting it searches org alarms. Required for event_source=roaming or rogue. Optional for other event sources to narrow results to a site""", default=None, ), ], mac: Annotated[ - str, + str | None, Field( description="""Only for search_type=event. MAC address filter for device, mxedge, WAN client, NAC client, or rogue events""", default=None, ), ], text: Annotated[ - str, + str | None, Field( description="""Only for search_type=event with event_source=device or nac_client. Text search in event details""", default=None, ), ], ssid: Annotated[ - str, + str | None, Field( description="""Only for search_type=event with event_source=wireless_client, nac_client, or rogue. SSID filter""", default=None, ), ], group: Annotated[ - str, + str | None, Field( description="""Only for search_type=alarm. Alarm group: `infrastructure`, `marvis`, or `security`""", default=None, ), ], severity: Annotated[ - str, + str | None, Field( description="""Only for search_type=alarm. Alarm severity: `critical`, `major`, `minor`, `warn`, or `info`""", default=None, ), ], alarm_type: Annotated[ - str, + str | None, Field( description="""Only for search_type=alarm. Comma-separated alarm types (e.g., `bad_cable,auth_failure`). Use `mist_get_constants` with `object_type=alarm_definitions` to discover available alarm types""", default=None, ), ], acked: Annotated[ - bool, + bool | None, Field( description="""Only for search_type=alarm. Filter acknowledged (true) or unacknowledged (false) alarms""", default=None, ), ], start: Annotated[ - int, + int | None, Field( description="""Start of time range (epoch seconds). Used for search_type=event or alarm; ignored for suppressed_alarm""", default=None, ), ], end: Annotated[ - int, + int | None, Field( description="""End of time range (epoch seconds). Used for search_type=event or alarm; ignored for suppressed_alarm""", default=None, @@ -266,14 +266,14 @@ async def search_events( async def _search_event( apisession, org_id: UUID, - event_source: EventSource, - event_type: str, - site_id: UUID, - mac: str, - text: str, - ssid: str, - start: int, - end: int, + event_source: EventSource | None, + event_type: str | None, + site_id: UUID | None, + mac: str | None, + text: str | None, + ssid: str | None, + start: int | None, + end: int | None, limit: int, ): if not event_source: @@ -457,7 +457,7 @@ async def _search_event( return response -def _mxedge_id_from_mac(mac: str) -> str | None: +def _mxedge_id_from_mac(mac: str | None) -> str | None: if not mac: return None @@ -478,13 +478,13 @@ def _mxedge_id_from_mac(mac: str) -> str | None: async def _search_alarm( apisession, org_id: UUID, - site_id: UUID, - group: str, - severity: str, - alarm_type: str, - acked: bool, - start: int, - end: int, + site_id: UUID | None, + group: str | None, + severity: str | None, + alarm_type: str | None, + acked: bool | None, + start: int | None, + end: int | None, limit: int, ): if site_id: @@ -517,11 +517,11 @@ async def _search_alarm( def _validate_event_params_not_used( - event_source: EventSource, - event_type: str, - mac: str, - text: str, - ssid: str, + event_source: EventSource | None, + event_type: str | None, + mac: str | None, + text: str | None, + ssid: str | None, ) -> None: if event_source or event_type or mac or text or ssid: raise ToolError( @@ -533,10 +533,10 @@ def _validate_event_params_not_used( def _validate_alarm_params_not_used( - group: str, - severity: str, - alarm_type: str, - acked: bool, + group: str | None, + severity: str | None, + alarm_type: str | None, + acked: bool | None, ) -> None: if group or severity or alarm_type or acked is not None: raise ToolError( From b8b85568427c8907d668c8030b8ed0283a95857a Mon Sep 17 00:00:00 2001 From: Thomas Munzer Date: Wed, 10 Jun 2026 16:48:17 -0700 Subject: [PATCH 6/6] cleanup the tool_optimization file --- mcp_generator/tools_optimization.yaml | 980 -------------------------- 1 file changed, 980 deletions(-) diff --git a/mcp_generator/tools_optimization.yaml b/mcp_generator/tools_optimization.yaml index 236ca56..e109ccb 100644 --- a/mcp_generator/tools_optimization.yaml +++ b/mcp_generator/tools_optimization.yaml @@ -20,141 +20,6 @@ listSiteRogueAPs: getSiteRogueAP: skip: true -# listUpgrades: -# type: tool_consolidation -# tags: [utilities_upgrade] -# description: Retrieve upgrade-related information for the organization. Use device types (ap, switch, srx, mxedge, ssr) to list or retrieve upgrade jobs. Use available_device_versions to list available firmware versions for AP/switch/gateway devices. Use available_ssr_versions to list available SSR firmware versions. -# read_only_hint: true -# destructive_hint: false -# match_name: device_type -# if_filter: upgrade_id -# parameters: -# - name: org_id -# schema: -# type: string -# format: uuid -# description: ID of the organization -# required: true -# - name: site_id -# schema: -# type: string -# format: uuid -# description: ID of the site. Required when device_type is site_mxedge -# required: false -# required_if: -# device_type: -# - site_mxedge -# - name: device_type -# schema: -# type: string -# enum: -# [ -# ap, -# switch, -# srx, -# org_mxedge, -# site_mxedge, -# ssr, -# available_device_versions, -# available_ssr_versions, -# ] -# required: true -# description: "Type of query: use ap/switch/srx/org_mxedge/site_mxedge/ssr to list upgrade jobs for that device type; use available_device_versions to list available firmware versions for AP/switch/gateway devices; use available_ssr_versions to list available SSR firmware versions" -# - name: upgrade_id -# schema: -# type: string -# format: uuid -# description: ID of a specific upgrade job to retrieve. Only applicable when device_type is ap, switch, srx, org_mxedge, site_mxedge, or ssr -# only_if: -# device_type: -# - ap -# - switch -# - srx -# - org_mxedge -# - site_mxedge -# - ssr -# - name: firmware_type -# schema: -# type: string -# enum: [ap, switch, gateway] -# description: Device model type to filter available firmware versions by. Only applicable when device_type is available_device_versions -# only_if: -# device_type: -# - available_device_versions -# - name: model -# schema: -# type: string -# description: Device model to filter available firmware versions by. Only applicable when device_type is available_device_versions -# only_if: -# device_type: -# - available_device_versions -# - name: channel -# schema: -# type: string -# enum: [alpha, beta, stable] -# description: SSR firmware release channel to filter by. Only applicable when device_type is available_ssr_versions. Defaults to stable -# only_if: -# device_type: -# - available_ssr_versions -# - name: mac -# schema: -# type: string -# description: MAC address (or comma-separated list) of SSR device(s) to retrieve available versions for. Only applicable when device_type is available_ssr_versions -# only_if: -# device_type: -# - available_ssr_versions -# requests: -# ap: -# list: -# operationId: listOrgDeviceUpgrades -# function: mistapi.api.v1.orgs.devices.listOrgDeviceUpgrades(apisession, org_id=str(org_id)) -# get: -# operationId: getOrgDeviceUpgrade -# function: mistapi.api.v1.orgs.devices.getOrgDeviceUpgrade(apisession, org_id=str(org_id), upgrade_id=str(upgrade_id)) -# switch: -# list: -# operationId: listOrgDeviceUpgrades -# function: mistapi.api.v1.orgs.devices.listOrgDeviceUpgrades(apisession, org_id=str(org_id)) -# get: -# operationId: getOrgDeviceUpgrade -# function: mistapi.api.v1.orgs.devices.getOrgDeviceUpgrade(apisession, org_id=str(org_id), upgrade_id=str(upgrade_id)) -# srx: -# list: -# operationId: listOrgDeviceUpgrades -# function: mistapi.api.v1.orgs.devices.listOrgDeviceUpgrades(apisession, org_id=str(org_id)) -# get: -# operationId: getOrgDeviceUpgrade -# function: mistapi.api.v1.orgs.devices.getOrgDeviceUpgrade(apisession, org_id=str(org_id), upgrade_id=str(upgrade_id)) -# org_mxedge: -# list: -# operationId: listOrgMxEdgeUpgrades -# function: mistapi.api.v1.orgs.mxedges.listOrgMxEdgeUpgrades(apisession, org_id=str(org_id)) -# get: -# operationId: getOrgMxEdgeUpgrade -# function: mistapi.api.v1.orgs.mxedges.getOrgMxEdgeUpgrade(apisession, org_id=str(org_id), upgrade_id=str(upgrade_id)) -# site_mxedge: -# list: -# operationId: listSiteMxEdgeUpgrades -# function: mistapi.api.v1.sites.mxedges.listSiteMxEdgeUpgrades(apisession, site_id=str(site_id)) -# get: -# operationId: getSiteMxEdgeUpgrade -# function: mistapi.api.v1.sites.mxedges.getSiteMxEdgeUpgrade(apisession, site_id=str(site_id), upgrade_id=str(upgrade_id)) -# ssr: -# list: -# operationId: listOrgSsrUpgrades -# function: mistapi.api.v1.orgs.ssr.listOrgSsrUpgrades(apisession, org_id=str(org_id)) -# get: -# operationId: getOrgSsrUpgrade -# function: mistapi.api.v1.orgs.ssr.getOrgSsrUpgrade(apisession, org_id=str(org_id), upgrade_id=str(upgrade_id)) -# available_device_versions: -# list: -# operationId: listOrgAvailableDeviceVersions -# function: mistapi.api.v1.orgs.devices.listOrgAvailableDeviceVersions(apisession, org_id=str(org_id), type=firmware_type.value if firmware_type else None, model=model if model else None) -# available_ssr_versions: -# list: -# operationId: listOrgAvailableSsrVersions -# function: mistapi.api.v1.orgs.ssr.listOrgAvailableSsrVersions(apisession, org_id=str(org_id), channel=channel.value if channel else "stable", mac=mac if mac else None) - getInsightMetrics: type: tool_consolidation tags: [sites_insights] @@ -320,136 +185,6 @@ getConstants: operationId: listNacEventsDefinitions function: mistapi.api.v1.const.nac_events.listNacEventsDefinitions(apisession) -# getSiteSle: -# type: tool_consolidation -# tags: [sles] -# description: Provides Information about the Service Level Expectations (SLEs) for a given site. The SLEs are derived from the insight metrics and can be used to monitor the network user experience of the site against the defined SLEs -# read_only_hint: true -# destructive_hint: false -# match_name: object_type -# parameters: -# - name: site_id -# schema: -# type: string -# format: uuid -# description: ID of the Mist Site -# required: true -# - name: scope -# schema: -# type: string -# enum: [client, ap, gateway, mxedge, switch, site] -# description: Scope of the SLEs to retrieve. Can be 'client', 'ap', 'gateway', 'mxedge', 'switch' or 'site' -# required: true -# - name: scope_id -# schema: -# type: string -# description: ID of the object to retrieve SLEs for. Required if scope is 'client', 'ap', 'gateway', 'mxedge' or 'switch'. Optional if scope is 'site' -# required: true -# - name: metric -# schema: -# type: string -# description: Name of the metric to retrieve SLEs for. Use the tool`mist_get_constants` with `object_type=insight_metrics` to see available metrics -# required: true -# - name: object_type -# schema: -# type: string -# description: Type of object to retrieve metrics for -# required: true -# - name: start -# schema: -# type: integer -# description: Start time (epoch timestamp in seconds) -# required: false -# - name: end -# schema: -# type: integer -# description: End time (epoch timestamp in seconds) -# required: false -# - name: classifier -# schema: -# type: string -# description: Classifier name. Required when object_type is 'classifier_summary_trend' -# required: false -# required_if: -# test: -# - classifier_summary_trend -# - name: duration -# schema: -# type: string -# description: Duration like 7d, 2w -# required: false - -# requests: -# summary: -# get: -# operationId: getSiteSleSummary -# function: mistapi.api.v1.sites.sle.getSiteSleSummary(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# impact_summary: -# get: -# operationId: getSiteSleImpactSummary -# function: mistapi.api.v1.sites.sle.getSiteSleImpactSummary(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# summary_trend: -# get: -# operationId: getSiteSleSummaryTrend -# function: mistapi.api.v1.sites.sle.getSiteSleSummaryTrend(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# impacted_applications: -# get: -# operationId: listSiteSleImpactedApplications -# function: mistapi.api.v1.sites.sle.listSiteSleImpactedApplications(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# impacted_aps: -# get: -# operationId: listSiteSleImpactedAps -# function: mistapi.api.v1.sites.sle.listSiteSleImpactedAps(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# impacted_gateways: -# get: -# operationId: listSiteSleImpactedGateways -# function: mistapi.api.v1.sites.sle.listSiteSleImpactedGateways(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# impacted_interfaces: -# get: -# operationId: listSiteSleImpactedInterfaces -# function: mistapi.api.v1.sites.sle.listSiteSleImpactedInterfaces(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# impacted_switches: -# get: -# operationId: listSiteSleImpactedSwitches -# function: mistapi.api.v1.sites.sle.listSiteSleImpactedSwitches(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# impacted_wireless_clients: -# get: -# operationId: listSiteSleImpactedWirelessClients -# function: mistapi.api.v1.sites.sle.listSiteSleImpactedWirelessClients(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# impacted_wired_clients: -# get: -# operationId: listSiteSleImpactedWiredClients -# function: mistapi.api.v1.sites.sle.listSiteSleImpactedWiredClients(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# impacted_chassis: -# get: -# operationId: listSiteSleImpactedChassis -# function: mistapi.api.v1.sites.sle.listSiteSleImpactedChassis(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# histogram: -# get: -# operationId: getSiteSleHistogram -# function: mistapi.api.v1.sites.sle.getSiteSleHistogram(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# classifier_summary_trend: -# get: -# operationId: getSiteSleClassifierSummaryTrend -# function: mistapi.api.v1.sites.sle.getSiteSleClassifierSummaryTrend(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,classifier=classifier,start=str(start) if start else None,end=str(end) if end else None,duration=duration if duration else None,) - -# threshold: -# get: -# operationId: getSiteSleThreshold -# function: mistapi.api.v1.sites.sle.getSiteSleThreshold(apisession,site_id=str(site_id),scope=scope.value,scope_id=scope_id,metric=metric,) - getSelf: type: tool_consolidation tags: [self_account] @@ -786,342 +521,6 @@ getStats: operationId: searchSiteSwOrGwPorts function: mistapi.api.v1.sites.stats.searchSiteSwOrGwPorts(apisession, site_id=str(site_id), mac=str(object_id) if object_id else None, limit=limit) -searchEvents: - skip: true - type: tool_consolidation - tags: [events] - description: |- - Search for events across an organization or site with flexible filtering options. - - This tool queries events from various sources including devices, MX Edge instances, and clients. You can: - - Filter by time range using `start` and `end` (epoch seconds) - - Filter by event type (use `mist_get_constants` tool first to discover available event types) - - Apply source-specific filters (MAC address, text search, SSID, etc.) - - IMPORTANT: Always specify an `event_type` to limit results. Use `mist_get_constants` with: - - `object_type=device_events` for device events - - `object_type=mxedge_events` for MX Edge events - - `object_type=client_events` for WAN/wireless client events - - `object_type=nac_events` for NAC client events - read_only_hint: true - destructive_hint: false - match_name: event_source - parameters: - - name: event_source - schema: - type: string - enum: - [ - device, - mxedge, - wan_client, - wireless_client, - nac_client, - roaming, - rogue, - ] - description: "Event source type: device, mxedge, wan_client, wireless_client, nac_client, roaming (requires site_id), or rogue (requires site_id)" - required: true - - name: org_id - schema: - type: string - format: uuid - description: ID of the organization to search for events in - required: true - - name: event_type - schema: - type: string - description: Comma-separated event types to filter by. The list of possible event types can be obtained with the `mist_get_constants` tool with `object_type=device_events` when `event_source` is `device`, `object_type=mxedge_events` when `event_source` is `mxedge`, `object_type=client_events` when `event_source` is `wan_client` or `wireless_client`, `object_type=nac_events` when `event_source` is `nac_client` - required: false - - name: site_id - schema: - type: string - format: uuid - description: Site ID (required for roaming/rogue events, optional for others) - required: false - required_if: - event_source: - - roaming - - rogue - - name: mac - schema: - type: string - description: MAC address to filter by (device/WAN client/NAC client/rogue events only) - required: false - - name: text - schema: - type: string - description: Text search in event details (device/NAC client events only) - required: false - only_if: - event_source: - - device - - nac_client - - name: ssid - schema: - type: string - description: SSID filter (wireless_client/nac_client/rogue events only) - required: false - only_if: - event_source: - - wireless_client - - nac_client - - rogue - - name: start - schema: - type: integer - description: Start time (epoch timestamp in seconds) - required: false - - name: end - schema: - type: integer - description: End time (epoch timestamp in seconds) - required: false - - name: limit - schema: - type: integer - default: 20 - description: Max number of results to return (max 1000) - required: false - requests: - device: - site_id: - operationId: searchSiteDeviceEvents - function: mistapi.api.v1.sites.devices.searchSiteDeviceEvents(apisession, site_id=str(site_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, mac=str(mac) if mac else None, text=str(text) if text else None, limit=limit) - org_id: - operationId: searchOrgDeviceEvents - function: mistapi.api.v1.orgs.devices.searchOrgDeviceEvents(apisession, org_id=str(org_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, mac=str(mac) if mac else None, text=str(text) if text else None, limit=limit) - mxedge: - site_id: - operationId: mxedges.searchSiteMistEdgeEvents - function: mistapi.api.v1.sites.mxedges.searchSiteMistEdgeEvents(apisession, site_id=str(site_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, mxedge_id=f"00000000-0000-0000-1000-{str(mac)}" if mac else None, limit=limit) - org_id: - operationId: searchOrgMistEdgeEvents - function: mistapi.api.v1.orgs.mxedges.searchOrgMistEdgeEvents(apisession, org_id=str(org_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, mxedge_id=f"00000000-0000-0000-1000-{str(mac)}" if mac else None, limit=limit) - wan_client: - site_id: - operationId: searchSiteWanClientEvents - function: mistapi.api.v1.sites.wan_clients.searchSiteWanClientEvents(apisession, site_id=str(site_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, mac=str(mac) if mac else None, limit=limit) - org_id: - operationId: searchOrgWanClientEvents - function: mistapi.api.v1.orgs.wan_clients.searchOrgWanClientEvents(apisession, org_id=str(org_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, mac=str(mac) if mac else None, limit=limit) - wireless_client: - site_id: - operationId: searchSiteWirelessClientEvents - function: mistapi.api.v1.sites.clients.searchSiteWirelessClientEvents(apisession, site_id=str(site_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, ssid=str(ssid) if ssid else None, limit=limit) - org_id: - operationId: searchOrgWirelessClientEvents - function: mistapi.api.v1.orgs.clients.searchOrgWirelessClientEvents(apisession, org_id=str(org_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, ssid=str(ssid) if ssid else None, limit=limit) - nac_client: - site_id: - operationId: searchSiteNacClientEvents - function: mistapi.api.v1.sites.nac_clients.searchSiteNacClientEvents(apisession, site_id=str(site_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, mac=str(mac) if mac else None, text=str(text) if text else None, ssid=str(ssid) if ssid else None, limit=limit) - org_id: - operationId: searchOrgNacClientEvents - function: mistapi.api.v1.orgs.nac_clients.searchOrgNacClientEvents(apisession, org_id=str(org_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, mac=str(mac) if mac else None, text=str(text) if text else None, ssid=str(ssid) if ssid else None, limit=limit) - roaming: - site_id: - operationId: listSiteRoamingEvents - function: mistapi.api.v1.sites.events.listSiteRoamingEvents(apisession, site_id=str(site_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, limit=limit) - rogue: - site_id: - operationId: searchSiteRogueEvents - function: mistapi.api.v1.sites.rogues.searchSiteRogueEvents(apisession, site_id=str(site_id), start=str(start) if start else None, end=str(end) if end else None, type=str(event_type) if event_type else None, ssid=str(ssid) if ssid else None, ap_mac=str(mac) if mac else None, limit=limit) - -# searchDevices: -# type: tool_consolidation -# tags: [devices] -# description: |- -# This tool can be used to search for devices in an organization or site. -# You can filter the search by device type, device name, or MAC address using the `device_type`, `name`, and `mac` parameters, respectively -# IMPORTANT: this tool only returns devices that are currently connected to Mist -# read_only_hint: true -# destructive_hint: false -# parameters: -# - name: scope -# schema: -# type: string -# enum: [org, site] -# description: Whether to search for devices in the entire organization or a specific site. If `site` is selected, the `site_id` parameter is required -# required: true -# - name: org_id -# schema: -# type: string -# format: uuid -# description: ID of the organization to search for devices in -# required: true -# - name: site_id -# schema: -# type: string -# format: uuid -# description: ID of the site to search for devices in -# required: false -# required_if: -# scope: -# - site -# - name: device_type -# schema: -# type: string -# enum: [ap, switch, gateway] -# description: Type of device to search for -# required: false -# - name: hostname -# schema: -# type: string -# description: Hostname of the device to search for. Supports partial matches -# required: false -# - name: mac -# schema: -# type: string -# description: MAC address of the device to search for -# required: false -# - name: model -# schema: -# type: string -# description: Model of the device to search for -# required: false -# - name: limit -# schema: -# type: integer -# default: 20 -# description: Max number of results to return (max 1000) -# required: false -# match_name: scope -# requests: -# org: -# list: -# operationId: searchOrgDevices -# function: mistapi.api.v1.orgs.devices.searchOrgDevices(apisession, org_id=str(org_id), type=str(device_type) if device_type else None, hostname=str(hostname) if hostname else None, mac=str(mac) if mac else None, model=str(model) if model else None, limit=limit ) -# site: -# list: -# operationId: searchSiteDevices -# function: mistapi.api.v1.sites.devices.searchSiteDevices(apisession, site_id=str(site_id), type=str(device_type) if device_type else None, hostname=str(hostname) if hostname else None, mac=str(mac) if mac else None, model=str(model) if model else None, limit=limit ) - -# searchGuestAuthorization: -# type: tool_consolidation -# tags: [clients] -# description: |- -# Search for guest authorization entries in an organization or site -# read_only_hint: true -# destructive_hint: false -# parameters: -# - name: scope -# schema: -# type: string -# enum: [org, site] -# description: Whether to search in the entire organization or a specific site. If `site` is selected, the `site_id` parameter is required -# required: true -# - name: org_id -# schema: -# type: string -# format: uuid -# description: ID of the organization to search for guest authorization entries in -# required: true -# - name: site_id -# schema: -# type: string -# format: uuid -# description: ID of the site to search for guest authorization entries in -# required: false -# required_if: -# scope: -# - site -# - name: guest_mac -# schema: -# type: string -# description: MAC address of the guest to search for in the authorization entries -# required: false -# - name: wlan_id -# schema: -# type: string -# format: uuid -# description: ID of the WLAN to filter guest authorization entries by -# required: false -# - name: auth_method -# schema: -# type: string -# description: Authentication method to filter guest authorization entries by -# required: false -# - name: ssid -# schema: -# type: string -# description: SSID to filter guest authorization entries by -# required: false -# - name: start -# schema: -# type: integer -# description: Start time (epoch timestamp in seconds) -# required: false -# - name: end -# schema: -# type: integer -# description: End time (epoch timestamp in seconds) -# required: false -# - name: limit -# schema: -# type: integer -# default: 20 -# description: Max number of results to return (max 1000) -# required: false -# match_name: scope -# if_filter: guest_mac -# requests: -# org: -# list: -# operationId: searchOrgGuestAuthorization -# function: mistapi.api.v1.orgs.guests.searchOrgGuestAuthorization(apisession,org_id=str(org_id),wlan_id=str(wlan_id) if wlan_id else None,auth_method=auth_method if auth_method else None,ssid=ssid if ssid else None,start=str(start) if start else None,end=str(end) if end else None, limit=limit ) -# get: -# operationId: getOrgGuestAuthorization -# function: mistapi.api.v1.orgs.guests.getOrgGuestAuthorization(apisession, org_id=str(org_id), guest_mac=str(guest_mac) ) -# site: -# list: -# operationId: searchSiteGuestAuthorization -# function: mistapi.api.v1.sites.guests.searchSiteGuestAuthorization(apisession, site_id=str(site_id), wlan_id=str(wlan_id) if wlan_id else None, auth_method=auth_method if auth_method else None, ssid=ssid if ssid else None, start=str(start) if start else None, end=str(end) if end else None, limit=limit ) -# get: -# operationId: getSiteGuestAuthorization -# function: mistapi.api.v1.sites.guests.getSiteGuestAuthorization(apisession, site_id=str(site_id), guest_mac=str(guest_mac) ) - -# getOrgOrSiteInfo: -# type: tool_consolidation -# tags: [info] -# description: |- -# Search information about the organizations or sites -# read_only_hint: true -# destructive_hint: false -# parameters: -# - name: info_type -# schema: -# type: string -# enum: [org, site] -# description: Type of information to search for. Possible values are `org` and `site` -# required: true -# - name: org_id -# schema: -# type: string -# format: uuid -# description: ID of the organization to search for information in -# required: true -# - name: site_id -# schema: -# type: string -# format: uuid -# description: ID of the site to search for information in -# required: false -# match_name: info_type -# if_filter: site_id -# requests: -# org: -# get: -# operationId: getOrg -# function: mistapi.api.v1.orgs.orgs.getOrg(apisession, org_id=str(org_id)) -# site: -# list: -# operationId: listOrgSites -# function: mistapi.api.v1.orgs.sites.listOrgSites(apisession, org_id=str(org_id)) -# get: -# operationId: getSiteInfo -# function: mistapi.api.v1.sites.sites.getSiteInfo(apisession, site_id=str(site_id) ) - searchAuditLogs: type: tool_consolidation tags: [events] @@ -1177,152 +576,6 @@ searchAuditLogs: operationId: listOrgAuditLogs function: mistapi.api.v1.orgs.logs.listOrgAuditLogs(apisession, org_id=str(org_id), start=str(start) if start else None, end=str(end) if end else None, message=str(message) if message else None, limit=limit ) -# searchClient: -# type: tool_consolidation -# tags: [clients] -# description: |- -# Search for clients across an organization or specific site. -# Supports searching by client type (WAN, wired, wireless, NAC), MAC address, hostname, IP address, and more. -# Use wildcards (*) for partial matches on MAC address, hostname, IP, and text fields. -# Different client types support different filter parameters - the tool will validate compatibility. -# read_only_hint: true -# destructive_hint: false -# match_name: client_type -# parameters: -# - name: client_type -# schema: -# type: string -# enum: [wired, wireless, wan, nac, org_guest, site_guest] -# description: "Type of client: WAN, wired, wireless, NAC, Org guest, or Site guest" -# required: true -# - name: org_id -# schema: -# type: string -# format: uuid -# description: ID of the organization to search for clients in -# required: true -# - name: site_id -# schema: -# type: string -# format: uuid -# description: Site ID for site-level search (optional) -# required: false -# - name: device_mac -# schema: -# type: string -# description: Partial / full MAC Address of the Access Point or the Switch. Use `prefix*` for prefix search or `*substring*` for contains search (e.g. `aabbcc*` and `*bbcc*` match `aabbccddeeff`). Suffix-only wildcards (e.g. `*bccddeeff`) are not supported. Not applicable for WAN clients or Org/Site Guests -# required: false -# only_if: -# client_type: -# - wireless -# - wired -# - name: band -# schema: -# type: string -# enum: ["24", "5", "6"] -# description: 802.11 band (24 or 5 or 6 GHz). Wireless clients only -# required: false -# only_if: -# client_type: -# - wireless -# - name: mac -# schema: -# type: string -# description: Partial / full Client MAC Address. Use `prefix*` for prefix search or `*substring*` for contains search (e.g. `aabbcc*` and `*bbcc*` match `aabbccddeeff`). Suffix-only wildcards (e.g. `*bccddeeff`) are not supported -# required: false -# - name: hostname -# schema: -# type: string -# description: Partial / full Client hostname. Use `prefix*` for prefix search or `*substring*` for contains search (e.g. `everest*` and `*rest*` match `my-everest-client`). Suffix-only wildcards (e.g. `*everest`) are not supported. Not applicable for WAN or wired clients or Org/Site Guests -# required: false -# only_if: -# client_type: -# - wireless -# - nac -# - name: ip -# schema: -# type: string -# description: Partial / full Client IP Address. Use `prefix*` for prefix search or `*substring*` for contains search (e.g. `10.100.10.*` and `*100.10.*` match `10.100.10.54`). Suffix-only wildcards (e.g. `*.54`) are not supported. Not applicable for NAC clients or Org/Site Guests -# required: false -# only_if: -# client_type: -# - wan -# - wired -# - wireless -# - name: wlan_id -# schema: -# type: string -# format: uuid -# description: WLAN ID to filter by. Only applicable for wireless clients and Guests -# required: false -# only_if: -# client_type: -# - wireless -# - org_guest -# - site_guest -# - name: ssid -# schema: -# type: string -# description: SSID name to filter by. Only applicable for wireless clients, Guests, and NAC clients -# required: false -# only_if: -# client_type: -# - wireless -# - org_guest -# - site_guest -# - nac -# - name: text -# schema: -# type: string -# description: Free text search in client details (supports * wildcard). Not applicable for WAN clients or Org/Site Guests -# required: false -# only_if: -# client_type: -# - wired -# - wireless -# - nac -# - name: start -# schema: -# type: integer -# description: Start time (epoch timestamp in seconds) -# required: false -# - name: end -# schema: -# type: integer -# description: End time (epoch timestamp in seconds) -# required: false -# - name: limit -# schema: -# type: integer -# default: 20 -# description: Max number of results to return (max 1000) -# required: false -# requests: -# wan: -# list: -# operationId: searchOrgWanClients -# function: mistapi.api.v1.orgs.wan_clients.searchOrgWanClients(apisession, org_id=str(org_id), site_id=str(site_id) if site_id else None, mac=str(mac) if mac else None, hostname=str(hostname) if hostname else None, ip=str(ip) if ip else None, start=str(start) if start else None, end=str(end) if end else None, limit=limit ) -# wired: -# list: -# operationId: searchOrgWiredClients -# function: mistapi.api.v1.orgs.wired_clients.searchOrgWiredClients(apisession, org_id=str(org_id), site_id=str(site_id) if site_id else None, device_mac=str(device_mac) if device_mac else None, mac=str(mac) if mac else None, ip=str(ip) if ip else None, text=str(text) if text else None, start=str(start) if start else None, end=str(end) if end else None, limit=limit ) -# wireless: -# list: -# operationId: searchOrgWirelessClients -# function: mistapi.api.v1.orgs.clients.searchOrgWirelessClients(apisession, org_id=str(org_id), site_id=str(site_id) if site_id else None, ap=str(device_mac) if device_mac else None, band=str(band) if band else None, ssid=str(ssid) if ssid else None, mac=str(mac) if mac else None, hostname=str(hostname) if hostname else None, ip=str(ip) if ip else None, text=str(text) if text else None, start=str(start) if start else None, end=str(end) if end else None, limit=limit ) -# nac: -# list: -# operationId: searchOrgNacClients -# function: mistapi.api.v1.orgs.nac_clients.searchOrgNacClients(apisession, org_id=str(org_id), site_id=str(site_id) if site_id else None, ssid=str(ssid) if ssid else None, mac=str(mac) if mac else None, hostname=str(hostname) if hostname else None, text=str(text) if text else None, start=str(start) if start else None, end=str(end) if end else None, limit=limit ) -# org_guest: -# list: -# operationId: searchOrgGuestAuthorization -# function: mistapi.api.v1.orgs.guests.searchOrgGuestAuthorization(apisession, org_id=str(org_id), ssid=str(ssid) if ssid else None, guest_mac=str(mac) if mac else None, wlan_id=str(wlan_id) if wlan_id else None, start=str(start) if start else None, end=str(end) if end else None, limit=limit ) -# site_guest: -# list: -# operationId: searchSiteGuestAuthorization -# function: mistapi.api.v1.sites.guests.searchSiteGuestAuthorization(apisession, site_id=str(site_id), ssid=str(ssid) if ssid else None, guest_mac=str(mac) if mac else None, wlan_id=str(wlan_id) if wlan_id else None, start=str(start) if start else None, end=str(end) if end else None, limit=limit ) - listRogueDevices: type: tool_consolidation tags: [sites_rogues] @@ -1387,159 +640,6 @@ listRogueDevices: operationId: listSiteRogueClients function: mistapi.api.v1.sites.insights.listSiteRogueClients(apisession, site_id=str(site_id), limit=limit, start=str(start) if start else None, end=str(end) if end else None ) -# listSiteSleInfo: -# type: tool_consolidation -# tags: [sles] -# description: List SLE metadata for a site scope. Use metrics to list available SLE metrics for a given scope, or classifiers to list the classifiers available for a specific metric. -# read_only_hint: true -# destructive_hint: false -# match_name: query_type -# parameters: -# - name: site_id -# schema: -# type: string -# format: uuid -# description: Site ID -# required: true -# - name: query_type -# schema: -# type: string -# enum: [metrics, classifiers] -# description: "Type of metadata to retrieve: metrics returns the list of available SLE metrics for the given scope; classifiers returns the list of classifiers for a specific metric (requires metric parameter)" -# required: true -# - name: scope -# schema: -# type: string -# enum: [ap, client, gateway, site, switch] -# description: "Scope of the SLE data: site, ap, client, gateway, or switch" -# required: true -# - name: scope_id -# schema: -# type: string -# description: "ID of the scoped object: `site_id` if `scope=site`; `device_id` if `scope=ap`, `switch`, or `gateway`; `MAC address` if `scope=client`" -# required: true -# - name: metric -# schema: -# type: string -# description: SLE metric name to retrieve classifiers for. Required when query_type is classifiers. Use query_type=metrics first to discover available metric names -# required: false -# required_if: -# test: -# - classifiers -# requests: -# metrics: -# list: -# operationId: listSiteSlesMetrics -# function: mistapi.api.v1.sites.sle.listSiteSlesMetrics(apisession, site_id=str(site_id), scope=scope.value, scope_id=scope_id) -# classifiers: -# list: -# operationId: listSiteSleMetricClassifiers -# function: mistapi.api.v1.sites.sle.listSiteSleMetricClassifiers(apisession, site_id=str(site_id), scope=scope.value, scope_id=scope_id, metric=metric) - -searchAlarms: - skip: true - type: tool_consolidation - tags: [events] - description: |- - Search for raised alarms in an organization or site with optional filtering. - - Scopes: - - `org`: Search all alarms across the organization - - `site`: Search alarms in a specific site (requires `site_id`) - - `suppressed`: View temporarily disabled alarms across the organization - - Alarm groups: `infrastructure` (network device/connectivity issues), `marvis` (AI-driven network detections), `security` (security events) - - Common Marvis alarm types: `bad_cable`, `bad_wan_uplink`, `dns_failure`, `arp_failure`, `auth_failure`, `dhcp_failure`, `missing_vlan`, `negotiation_mismatch`, `port_flap` - - For a complete list of alarm types, use `mist_get_constants` with `object_type=alarm_definitions`. - read_only_hint: true - destructive_hint: false - match_name: scope - parameters: - - name: org_id - schema: - type: string - format: uuid - description: Organization ID - required: true - - name: scope - schema: - type: string - enum: [org, site, suppressed] - description: "Search scope: `org` (organization-wide), `site` (specific site, requires site_id), or `suppressed` (disabled alarms)" - required: true - - name: site_id - schema: - type: string - format: uuid - description: Site ID. Can be used to filter alarms for a specific site. Required if `scope` is set to `site` - required: false - required_if: - scope: - - site - - name: group - schema: - type: string - description: "Only for org/site scope. Alarm group. enum: `infrastructure`, `marvis`, `security`. The `marvis` group is used to retrieve AI-driven network issue detections." - only_if: - scope: - - org - - site - - name: severity - schema: - type: string - description: "Only for org/site scope.Severity of the alarm. enum: `critical`, `major`, `minor`, `warn`, `info`" - only_if: - scope: - - org - - site - - name: alarm_type - schema: - type: string - description: "Only for org/site scope. Comma separated list of types of the alarm (e.g., 'bad_cable,auth_failure'). IMPORTANT: use the `mist_get_constants` tool with `object_type=alarm_definitions`to get the list of possible alarm types" - only_if: - scope: - - org - - site - - name: acked - schema: - type: boolean - description: Only for org/site scope. Whether to filter for acknowledged (true) or unacknowledged (false) alarms - only_if: - scope: - - org - - site - - name: start - schema: - type: integer - description: Only for org/site scope. Start time (epoch timestamp in seconds) - required: false - - name: end - schema: - type: integer - description: Only for org/site scope. End time (epoch timestamp in seconds) - required: false - - name: limit - schema: - type: integer - default: 20 - description: Only for org/site scope. Max number of results to return (max 1000) - required: false - requests: - org: - list: - operationId: searchOrgAlarms - function: mistapi.api.v1.orgs.alarms.searchOrgAlarms(apisession,org_id=str(org_id),group=group if group else None,severity=severity if severity else None,type=alarm_type if alarm_type else None,acked=acked if acked else None,start=str(start) if start else None,end=str(end) if end else None,limit=limit,) - site: - list: - operationId: searchSiteAlarms - function: mistapi.api.v1.sites.alarms.searchSiteAlarms(apisession,site_id=str(site_id),group=group if group else None,severity=severity if severity else None,type=alarm_type if alarm_type else None,acked=acked if acked else None,start=str(start) if start else None,end=str(end) if end else None,limit=limit,) - suppressed: - list: - operationId: listOrgSuppressedAlarms - function: mistapi.api.v1.orgs.alarmtemplates.listOrgSuppressedAlarms(apisession, org_id=str(org_id)) - searchDeviceConfigHistory: type: tool_consolidation tags: [configuration] @@ -1646,86 +746,6 @@ searchNacUserMacs: operationId: getOrgUserMac function: mistapi.api.v1.orgs.usermacs.getOrgUserMac(apisession, org_id=str(org_id), usermac_id=str(usermac_id) ) -# getOrgSle: -# type: tool_consolidation -# tags: [sles] -# description: Get Org SLEs (all/worst sites, Mx Edges, ...). Use the `mist_get_insight_metrics` tool to get the list of available SLE metrics -# read_only_hint: true -# destructive_hint: false -# parameters: -# - name: org_id -# schema: -# type: string -# format: uuid -# description: Organization ID -# required: true -# - name: metric -# schema: -# type: string -# description: Metric to look at. Use the `mist_get_insight_metrics` tool to get the list of available SLE metrics -# required: true -# - name: sle -# schema: -# type: string -# description: Type of SLE data to retrieve for the organization sites. Use the `mist_get_insight_metrics` tool to get the list of available SLE metrics -# required: false -# - name: start -# schema: -# type: integer -# description: Start time (epoch timestamp in seconds) -# required: false -# - name: end -# schema: -# type: integer -# description: End time (epoch timestamp in seconds) -# required: false -# requests: -# default: -# get: -# operationId: getOrgSle -# function: mistapi.api.v1.orgs.insights.getOrgSle(apisession, org_id=str(org_id), metric=str(metric), sle=str(sle) if sle else None, start=str(start) if start else None, end=str(end) if end else None) - -# getOrgSitesSle: -# type: tool_consolidation -# tags: [sles] -# description: Get SLE summary for the organization sites. -# read_only_hint: true -# destructive_hint: false -# parameters: -# - name: org_id -# schema: -# type: string -# format: uuid -# description: Organization ID -# required: true -# - name: sle -# schema: -# type: string -# enum: [wifi, wired, wan] -# description: Type of SLE data to retrieve for the sites. Possible values are `wifi`, `wired`, and `wan` -# required: true -# - name: start -# schema: -# type: integer -# description: Start time (epoch timestamp in seconds) -# required: false -# - name: end -# schema: -# type: integer -# description: End time (epoch timestamp in seconds) -# required: false -# - name: limit -# schema: -# type: integer -# default: 20 -# description: Max number of results to return (max 1000) -# required: false -# requests: -# default: -# get: -# operationId: getOrgSitesSle -# function: mistapi.api.v1.orgs.insights.getOrgSitesSle(apisession, org_id=str(org_id), sle=sle.value, start=str(start) if start else None, end=str(end) if end else None, limit=limit ) - troubleshoot: type: tool_consolidation tags: [marvis]