Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gemini/skills/devcontainer-management/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: devcontainer-management
description: Guide for identifying, managing, and running commands within the NetAlertX development container. Use this when asked to run backend logic, setup scripts, or troubleshoot container issues.
description: Guide for identifying, managing, and running commands within the NetAlertX development container. Use this when asked to run commands, testing, setup scripts, or troubleshoot container issues.
---

# Devcontainer Management
Expand Down
52 changes: 52 additions & 0 deletions .gemini/skills/mcp-activation/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
name: mcp-activation
description: Enables live interaction with the NetAlertX runtime. This skill configures the Model Context Protocol (MCP) connection, granting full API access for debugging, troubleshooting, and real-time operations including database queries, network scans, and device management.
---

# MCP Activation Skill

This skill configures the NetAlertX development environment to expose the Model Context Protocol (MCP) server to AI agents.

## Why use this?

By default, agents only have access to the static codebase (files). To perform dynamic actions—such as:
- **Querying the database** (e.g., getting device lists, events)
- **Triggering actions** (e.g., network scans, Wake-on-LAN)
- **Validating runtime state** (e.g., checking if a fix actually works)

...you need access to the **MCP Server** running inside the container. This skill sets up the necessary authentication tokens and connection configs to bridge your agent to that live server.

## Prerequisites

1. **Devcontainer:** You must be connected to the NetAlertX devcontainer.
2. **Server Running:** The backend server must be running (to generate `app.conf` with the API token).

## Activation Steps

1. **Activate Devcontainer Skill:**
If you are not already inside the container, activate the management skill:
```text
activate_skill("devcontainer-management")
```

2. **Generate Configurations:**
Run the configuration generation script *inside* the container. This script extracts the API Token and creates the necessary settings files (`.gemini/settings.json` and `.vscode/mcp.json`).

```bash
# Run inside the container
/workspaces/NetAlertX/.devcontainer/scripts/generate-configs.sh
```

3. **Apply Changes:**

* **For Gemini CLI:**
The agent session must be **restarted** to load the new `.gemini/settings.json`.
> "I have generated the MCP configuration. Please **restart this session** to activate the `netalertx-devcontainer` tools."

* **For VS Code (GitHub Copilot / Cline):**
The VS Code window must be **reloaded** to pick up the new `.vscode/mcp.json`.
> "I have generated the MCP configuration. Please run **'Developer: Reload Window'** in VS Code to activate the MCP server."

## Verification

After restarting, you should see new tools available (e.g., `netalertx-devcontainer__get_devices`).
34 changes: 34 additions & 0 deletions .github/skills/mcp-activation/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: mcp-activation
description: Enables live interaction with the NetAlertX runtime. This skill configures the Model Context Protocol (MCP) connection, granting full API access for debugging, troubleshooting, and real-time operations including database queries, network scans, and device management.
---

# MCP Activation Skill

This skill configures the environment to expose the Model Context Protocol (MCP) server to AI agents running inside the devcontainer.

## Usage

This skill assumes you are already running within the NetAlertX devcontainer.

1. **Generate Configurations:**
Run the configuration generation script to extract the API Token and update the VS Code MCP settings.

```bash
/workspaces/NetAlertX/.devcontainer/scripts/generate-configs.sh
```

2. **Reload Window:**
Request the user to reload the VS Code window to activate the new tools.
> I have generated the MCP configuration. Please run the **'Developer: Reload Window'** command to activate the MCP server tools.
> In VS Code: open the Command Palette (Windows/Linux: Ctrl+Shift+P, macOS: Cmd+Shift+P), type Developer: Reload Window, press Enter — or click the Reload button if a notification appears. 🔁
> After you reload, tell me “Window reloaded” (or just “reloaded”) and I’ll continue.


## Why use this?

Access the live runtime API to perform operations that are not possible through static file analysis:
- **Query the database**
- **Trigger network scans**
- **Manage devices and events**
- **Troubleshoot real-time system state**
36 changes: 34 additions & 2 deletions server/api_server/api_server_start.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
DeviceInfo,
BaseResponse, DeviceTotalsResponse,
DeviceTotalsNamedResponse,
EventsTotalsNamedResponse,
DeleteDevicesRequest, DeviceImportRequest,
DeviceImportResponse, UpdateDeviceColumnRequest,
LockDeviceFieldRequest, UnlockDeviceFieldsRequest,
Expand Down Expand Up @@ -1509,8 +1510,8 @@ def api_delete_old_events(days: int, payload=None):
@app.route("/sessions/totals", methods=["GET"])
@validate_request(
operation_id="get_events_totals",
summary="Get Events Totals",
description="Retrieve event totals for a specified period.",
summary="Get Events Totals (Deprecated)",
description="Retrieve event totals for a specified period. Deprecated: use /sessions/totals/named instead.",
query_params=[{
"name": "period",
"description": "Time period (e.g., '7 days')",
Expand All @@ -1527,6 +1528,37 @@ def api_get_events_totals(payload=None):
return jsonify(totals)


@app.route("/sessions/totals/named", methods=["GET"])
@validate_request(
operation_id="get_events_totals_named",
summary="Get Named Event Totals",
description="Retrieve event/session totals with named fields for a specified period.",
query_params=[{
"name": "period",
"description": "Time period (e.g., '7 days')",
"required": False,
"schema": {"type": "string", "default": "7 days"}
}],
response_model=EventsTotalsNamedResponse,
tags=["events"],
auth_callable=is_authorized
)
def api_get_events_totals_named(payload=None):
period = request.args.get("period", "7 days")
event_handler = EventInstance()
totals = event_handler.getEventsTotals(period)
# totals order: [all_events, sessions, missing, voided, new, down]
totals_dict = {
"total": totals[0] if len(totals) > 0 else 0,
"sessions": totals[1] if len(totals) > 1 else 0,
"missing": totals[2] if len(totals) > 2 else 0,
"voided": totals[3] if len(totals) > 3 else 0,
"new": totals[4] if len(totals) > 4 else 0,
"down": totals[5] if len(totals) > 5 else 0
}
return jsonify({"success": True, "totals": totals_dict})


@app.route('/events/recent', methods=['GET', 'POST'])
@validate_request(
operation_id="get_recent_events",
Expand Down
21 changes: 20 additions & 1 deletion server/api_server/mcp_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -795,8 +795,17 @@ def get_log_dir() -> str:


def _list_resources() -> List[Dict[str, Any]]:
"""List available MCP resources (read-only data like logs)."""
"""List available MCP resources (read-only data like logs and API spec)."""
resources = []

# API Specification
resources.append({
"uri": "netalertx://api/openapi.json",
"name": "OpenAPI Specification",
"description": "The full OpenAPI 3.1 specification for the NetAlertX API and MCP tools",
"mimeType": "application/json"
})

log_dir = get_log_dir()
if not log_dir:
return resources
Expand Down Expand Up @@ -840,6 +849,16 @@ def _list_resources() -> List[Dict[str, Any]]:

def _read_resource(uri: str) -> List[Dict[str, Any]]:
"""Read a resource by URI."""
# Handle API Specification
if uri == "netalertx://api/openapi.json":
from flask import current_app
spec = get_openapi_spec(flask_app=current_app)
return [{
"uri": uri,
"mimeType": "application/json",
"text": json.dumps(spec, indent=2)
}]

log_dir = get_log_dir()
if not log_dir:
return [{"uri": uri, "text": "Error: NETALERTX_LOG directory not configured"}]
Expand Down
18 changes: 18 additions & 0 deletions server/api_server/openapi/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,24 @@ class DeviceTotalsNamedResponse(BaseResponse):
)


class EventsTotalsNamedResponse(BaseResponse):
"""Response with named event/session statistics."""
totals: Dict[str, int] = Field(
...,
description="Dictionary of counts: total, sessions, missing, voided, new, down",
json_schema_extra={
"examples": [{
"total": 100,
"sessions": 50,
"missing": 0,
"voided": 0,
"new": 5,
"down": 2
}]
}
)


class DeviceExportRequest(BaseModel):
"""Request for exporting devices."""
format: Literal["csv", "json"] = Field(
Expand Down