Files
glances/tests/HOW_TO_TEST_MCP.md
2026-02-21 21:18:27 +01:00

6.9 KiB

How to test the Glances MCP server

This guide covers both the automated test suite (tests/test_mcp.py) and manual verification of the MCP server that is now built into Glances.


Prerequisites

Install Glances with the mcp and web extras:

pip install 'glances[web,mcp]'

Or, inside the development virtual environment:

pip install -e '.[web,mcp]'

Automated test suite

# From the repository root
python -m pytest tests/test_mcp.py -v

# Or with the project venv
.venv/bin/python -m pytest tests/test_mcp.py -v

The suite automatically:

  1. Starts a Glances web server with --enable-mcp on port 61235
  2. Runs smoke tests (HTTP-level) and full MCP-client tests for every resource and prompt
  3. Shuts the server down

Tests are skipped automatically when the mcp package is not installed.


Manual testing

1. Start Glances with MCP enabled

glances -w --enable-mcp
Endpoint URL
SSE transport http://localhost:61208/mcp/sse
POST messages http://localhost:61208/mcp/messages/

2. Verify the SSE endpoint with curl

curl -N http://localhost:61208/mcp/sse

You should see a continuous text/event-stream response with an endpoint event pointing to the messages URL.

3. Explore resources and prompts with the Python client

import asyncio, json
from mcp.client.sse import sse_client
from mcp import ClientSession
from pydantic import AnyUrl

MCP_SSE = "http://localhost:61208/mcp/sse"

async def demo():
    async with sse_client(MCP_SSE) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()

            # List static resources
            res = await session.list_resources()
            print("Resources:", [str(r.uri) for r in res.resources])

            # List resource templates
            tmpl = await session.list_resource_templates()
            print("Templates:", [t.uriTemplate for t in tmpl.resourceTemplates])

            # Read all plugin names
            plugins = await session.read_resource(AnyUrl("glances://plugins"))
            print("Plugins:", json.loads(plugins.contents[0].text)[:5], "…")

            # Read CPU stats
            cpu = await session.read_resource(AnyUrl("glances://stats/cpu"))
            print("CPU:", json.loads(cpu.contents[0].text))

            # Read CPU alert thresholds
            limits = await session.read_resource(AnyUrl("glances://limits/cpu"))
            print("CPU limits:", json.loads(limits.contents[0].text))

            # List prompts
            prompts = await session.list_prompts()
            print("Prompts:", [p.name for p in prompts.prompts])

            # Run system health summary prompt
            health = await session.get_prompt("system_health_summary")
            print("Health prompt (first 200 chars):", health.messages[0].content.text[:200])

            # Run alert analysis with a severity filter
            alerts = await session.get_prompt("alert_analysis", arguments={"level": "critical"})
            print("Alerts:", alerts.messages[0].content.text[:200])

            # Top-5 processes report
            procs = await session.get_prompt("top_processes_report", arguments={"nb": "5"})
            print("Processes:", procs.messages[0].content.text[:200])

asyncio.run(demo())

4. Connect Claude CLI (Linux)

Add the Glances MCP server with:

claude mcp add --transport sse glances http://localhost:61208/mcp/sse

Then verify that the server is recognised:

claude mcp list
# glances: http://localhost:61208/mcp/sse

Once configured, start a Claude CLI session and try:

  • *"Is my system healthy ?"

It will return:

Here's your system health summary:

  CPU — Good

  - 6% total usage, load average 0.88 (on 16 cores) — very light

  Memory — Warning

  - RAM: 76.8% used (12.6 GB / 16.4 GB)
  - Swap: 95.9% used (3.9 GB / 4.0 GB) — critical, nearly exhausted

  Disk — Good

  - Root (/): 40.2% used, 530 GB free

  Temperatures — Good

  ┌────────────┬──────┐
  │   Sensor   │ Temp │
  ├────────────┼──────┤
  │ CPU        │ 54°C │
  ├────────────┼──────┤
  │ HDD        │ 40°C │
  ├────────────┼──────┤
  │ NVMe       │ 36°C │
  ├────────────┼──────┤
  │ RAM        │ 41°C │
  ├────────────┼──────┤
  │ GPU (i915) │ 49°C │
  └────────────┴──────┘

  - CPU Fan: 2992 RPM, Video Fan: 2822 RPM — both spinning normally

  Battery — Good

  - 96%, currently charging

  Alerts — None active

  ---
  Verdict: mostly healthy, but swap is nearly full. Your system is swapping heavily (12.7 GB
  swapped out), which suggests RAM pressure. You may want to check for memory-hungry processes
   and consider killing or restarting any you don't need.
  • "What is the current CPU usage on my machine ?"
  • "Are there any active alerts ?"
  • "Show me the top 5 processes by CPU."
  • "How is my disk space looking ?"

If Glances requires authentication, add a Bearer token or Basic Auth header via the headers key in settings.json (see the authentication section below).

5. Connect Claude Desktop

Add to claude_desktop_config.json (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows):

{
  "mcpServers": {
    "glances": {
      "url": "http://localhost:61208/mcp/sse"
    }
  }
}

Restart Claude Desktop, then try:

  • "What is the current CPU usage on my machine?"
  • "Are there any active alerts?"
  • "Show me the top 5 processes by CPU."
  • "How is my disk space looking?"

Testing authentication

Start Glances with a password:

glances -w --enable-mcp --username
# Follow the prompts to create a username/password pair

A request without credentials should return HTTP 401:

curl -I http://localhost:61208/mcp/sse
# HTTP/1.1 401 Unauthorized

Connect with Basic Auth:

import base64
creds = base64.b64encode(b"myuser:mypassword").decode()
headers = {"Authorization": f"Basic {creds}"}

async with sse_client(MCP_SSE, headers=headers) as (read, write):
    ...

Or with a JWT Bearer token (see the RESTful API docs for how to obtain one):

headers = {"Authorization": "Bearer <your_jwt_token>"}
async with sse_client(MCP_SSE, headers=headers) as (read, write):
    ...

The unit tests for the auth middleware live in tests/test_mcp.py (TestGlancesMcpAuthMiddleware) and do not require a running server.