Live demo — data resets daily at 03:00 UTC. Nothing you enter is saved. Server UI →

product: maestro audience: test-developer, operator, ai-assistant authority: normative

MCP Server — Live Events & Log Search

This document covers the Phase 3 MCP tools:

  • connect_live_events / poll_test_progress — real-time test progress via SignalR
  • search_execution_logs — full-text search over indexed execution log chunks

Live Events

How it works

The Maestro API exposes a SignalR hub at /testExecutionHub. The MCP server maintains a persistent connection to this hub and buffers incoming events in memory. Because MCP uses a request-response transport (stdio), the AI polls for events rather than receiving push notifications.

AI assistant                  McpServer                   API hub
      │                           │                           │
      │  connect_live_events       │  HubConnection.StartAsync │
      │──────────────────────────▶│──────────────────────────▶│
      │                           │         Connected          │
      │                           │◀──────────────────────────│
      │                           │                           │
      │                           │◀── TestStatusChangedEvent ─│  (broadcast)
      │                           │◀── StepProgressEvent ──────│  (broadcast)
      │  poll_test_progress        │                           │
      │──────────────────────────▶│  drains buffered events   │
      │◀── { statusEvents, stepEvents } ──────────────────────│

Tools

connect_live_events

Opens the SignalR connection. Safe to call multiple times — reconnects only if not already active.

Parameter Type Required Description
(none)

Returns:

{
  "station": "ST-01",
  "connected": true,
  "message": "Connected to station hub. Use poll_test_progress to receive events."
}

poll_test_progress

Drains and returns all events buffered since the last call. Returns immediately with empty arrays if no new events have arrived. Call at 1–5 second intervals while a test is running.

Parameter Type Required Description
(none)

Returns:

{
  "station": "ST-01",
  "connected": true,
  "statusEvents": [
    { "executionId": "…", "status": "RUNNING", "verdict": null },
    { "executionId": "…", "status": "COMPLETED", "verdict": "PASS" }
  ],
  "stepEvents": [
    { "executionId": "…", "stepExecutionId": "…", "stepName": "Calibrate",
      "currentStep": 1, "totalSteps": 5 }
  ]
}

Event types:

Array Trigger Key fields
statusEvents Test lifecycle changes (PENDING → RUNNING → COMPLETED / ABORTED) status, verdict (non-null when COMPLETED)
stepEvents Each step begins execution stepName, currentStep, totalSteps

Typical polling workflow

1. start_test(yamlFilePath=..., serialNumber=..., unattendedMode=true)
   → returns { executionId: "abc-123" }

2. connect_live_events()
   → connected: true

3. Loop until statusEvents contains status == "COMPLETED" or "ABORTED":
     poll_test_progress()
     → inspect stepEvents for progress, statusEvents for completion
     wait 2 seconds

4. get_test_status(executionId="abc-123")
   → final verdict and step summary

Buffer limits

The MCP server buffers up to 100 events per type. If the AI does not poll frequently enough and more than 100 events arrive, the oldest events are dropped. For tests with more than 100 steps poll every 1–2 seconds.


How it works

After a test execution completes, EmbeddingBackgroundService in Orchestra indexes the execution's log lines into the log_embeddings table. Each step's logs are chunked into segments of up to 2 000 characters with 200-character overlap to prevent long error messages from being split at a chunk boundary.

The search_execution_logs MCP tool calls GET /api/statistics/logs which runs a PostgreSQL full-text search (plainto_tsquery) over the indexed chunks.

Test execution completes
        │
        ▼ (within 65 seconds)
EmbeddingBackgroundService (Orchestra)
        │ groups logs by step, chunks to 2000 chars
        ▼
log_embeddings table (PostgreSQL)

AI: search_execution_logs(query="timeout error")
        │
        ▼
McpServer ──HTTP──▶ GET /api/statistics/logs?query=timeout+error
                         │  plainto_tsquery('english', ...)
                         ▼
                    log_embeddings (full-text search)
                         │
                         ▼
                    ranked hits → AI assistant

Indexing delay: Logs are indexed 5 minutes after execution completion (safety delay to avoid racing with in-flight persistence writes), then within the next 60-second poll cycle. Typical indexing latency: 5–65 seconds.


Tool: search_execution_logs

Parameter Type Required Default Description
query string Search phrase. Plain text recommended; supports PostgreSQL tsquery operators & (AND), \| (OR), ! (NOT).
testExecutionId UUID null Restrict search to a single execution.
stepName string null Restrict search to a specific step name.
limit int 20 Max hits per page (1–100).
page int 1 1-based page number.

Returns:

{
  "station": "ST-01",
  "results": {
    "query": "timeout",
    "testExecutionId": null,
    "stepName": null,
    "totalHits": 3,
    "page": 1,
    "pageSize": 20,
    "hits": [
      {
        "logEmbeddingId": "…",
        "testExecutionId": "…",
        "stepExecutionId": "…",
        "stepName": "CommunicationCheck",
        "chunkIndex": 0,
        "textSnippet": "connection timeout error while waiting for device…",
        "embeddedAt": "2025-06-01T14:32:11Z",
        "rank": 0.0
      }
    ]
  }
}

Note: rank is always 0.0 in Phase 3a. Relevance ranking using ts_rank will be added when pgvector semantic search is introduced in Phase 3b.


Example prompts

"Search the logs for test execution <id> for any timeout errors"
→ search_execution_logs(query="timeout error", testExecutionId="<id>")

"Did any steps mention a calibration failure?"
→ search_execution_logs(query="calibration failure")

"Find all log chunks from the 'RF Calibration' step that mention drift"
→ search_execution_logs(query="drift", stepName="RF Calibration")

"Show me the second page of results for 'voltage out of range'"
→ search_execution_logs(query="voltage out of range", page=2)

Troubleshooting

Symptom Likely cause Fix
totalHits: 0 for a recent test Logs not yet indexed (< 65 s since completion) Wait and retry
totalHits: 0 for a test from yesterday Orchestra was not running Restart Orchestra; it will index on next poll
connected: false from poll_test_progress Hub disconnected Call connect_live_events again
No statusEvents during a test connect_live_events was not called first Call it before starting the test
An unhandled error has occurred. Reload 🗙

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.