Skip to content

Programmatic access (API · MCP · CLI)

Beyond the Windows review app and the Fabric dashboard, the curated triple is reachable from any tool, interface, or harness through three headless surfaces — all built on one shared client.

flowchart TD
    subgraph clients [Any consumer]
        web[Web / Power BI / Excel / curl]
        ai[AI agents & harnesses<br/>Claude · Copilot · Cursor]
        sh[Scripts · pipelines · terminals]
        win[WinForms review app]
    end
    web --> api[FdaObservability.Api<br/>REST + OpenAPI]
    ai --> mcp[FdaObservability.Mcp<br/>MCP stdio server]
    sh --> cli[FdaObservability.Cli<br/>fda-obs]
    win --> core
    api --> core[(FdaObservability.Core<br/>FdaKustoClient)]
    mcp --> core
    cli --> core
    core --> eh[(Eventhouse · FdaInteractions<br/>stored KQL functions)]

All four projects live under src/. Every read goes through the same stored functions (SearchFdaInteractions, GetFdaInteraction, FdaTuningSummary, FdaFailures, FdaTopQuestions) plus an inline KPI summarize — so the API, MCP, CLI, and desktop app return identical data.

Shared core — FdaObservability.Core

A cross-platform (net8.0) library holding the models, the FdaKustoClient, and a pluggable IKustoTokenProvider. Authentication is injected, so the same client serves:

Host Token provider
Desktop review app interactive MSAL (the reviewer's identity)
API / MCP / CLI DefaultAzureCredentialTokenProvider

DefaultAzureCredential resolves — in order — an environment service principal, managed/workload identity, Azure CLI, Azure PowerShell, and Visual Studio. That single chain runs unchanged in Azure, containers, CI, and on a dev box. The caller (or its host) needs Viewer on the observability KQL database.

Common configuration

All headless surfaces read the same settings — Eventhouse Query URI and database — from environment variables or config. See the configuration reference.


REST API — FdaObservability.Api

An ASP.NET Core minimal API with OpenAPI/Swagger. Consumable by web UIs, Power BI, Excel, Postman, curl, or any language.

Endpoints

Method & path Description
GET /health Connectivity + schema probe
GET /api/interactions Search — term, from, to, agent, user, status, onlyMatched, maxRows
GET /api/interactions/{id} One interaction by id (404 if absent)
GET /api/kpis KPI roll-up — from, to
GET /api/tuning-summary Per-agent × day tuning KPIs — from, to
GET /api/failures Interactions needing attention — from, to
GET /api/top-questions Top question patterns — from, to, topN

Interactive docs at /swagger; the OpenAPI document at /swagger/v1/swagger.json lets any client generate a typed SDK.

Run

export FdaObservability__EventhouseQueryUri=https://<cluster>.<region>.kusto.fabric.microsoft.com
export FdaObservability__Database=FDA_Observability_EH
dotnet run --project src/FdaObservability.Api      # http://localhost:5080/swagger
docker build -t fda-observability-api -f src/FdaObservability.Api/Dockerfile .
docker run -p 8080:8080 \
  -e FdaObservability__EventhouseQueryUri=https://<cluster>.<region>.kusto.fabric.microsoft.com \
  -e FdaObservability__Database=FDA_Observability_EH \
  -e AZURE_TENANT_ID=... -e AZURE_CLIENT_ID=... -e AZURE_CLIENT_SECRET=... \
  fda-observability-api
curl "http://localhost:8080/api/interactions?term=revenue&status=Error&maxRows=20"
curl "http://localhost:8080/api/kpis?from=2026-06-01&to=2026-06-20"

Securing it

Set Api:ApiKey (config or Api__ApiKey env). When present, every route except /health and /swagger requires a matching X-Api-Key header. When not set, the API logs a warning and stays open — front it with a gateway / APIM / Entra-auth proxy, or set the key, before exposing it externally. CORS is open by default for browser clients; tighten it for production.


MCP server — FdaObservability.Mcp

A Model Context Protocol stdio server (protocol 2024-11-05) exposing each query as a tool, so AI agents and harnesses (Claude Desktop/Code, Copilot, Cursor, …) can query interactions natively. It is dependency-light — hand-rolled JSON-RPC, no preview packages — and logs only to stderr so the protocol stream stays clean.

Tools

search_interactions · get_interaction · kpis · tuning_summary · failures · top_questions

Register (Claude Desktop / Code example)

{
  "mcpServers": {
    "fda-observability": {
      "command": "dotnet",
      "args": ["C:/path/to/FdaObservability.Mcp.dll"],
      "env": {
        "FDA_EVENTHOUSE_URI": "https://<cluster>.<region>.kusto.fabric.microsoft.com",
        "FDA_DATABASE": "FDA_Observability_EH"
      }
    }
  }
}

Then ask the agent things like "top failing FDA questions this week" or "show the executed DAX for interaction <id>" and it calls the tools directly.


CLI — FdaObservability.Cli (fda-obs)

A cross-platform dotnet tool for scripts, pipelines, and terminals. JSON output by default (pipe to jq); --table gives a human view for search/failures.

# install (after packing / from a feed)
dotnet tool install -g FdaObservability.Cli

export FDA_EVENTHOUSE_URI=https://<cluster>.<region>.kusto.fabric.microsoft.com

fda-obs ping
fda-obs search --term revenue --status Error --table
fda-obs kpis --from 2026-06-01 --to 2026-06-20
fda-obs failures --from 2026-06-13 --table
fda-obs top-questions --top 25 | jq '.[].Example'
Command Purpose
ping Connectivity + schema probe
search Search interactions (--term --from --to --agent --user --status --matched --max --table)
get <id> One interaction by id
kpis KPI roll-up (--from --to)
tuning Per-agent × day tuning KPIs (--from --to)
failures Interactions needing attention (--from --to --table)
top-questions Top question patterns (--from --to --top)

Connection comes from --cluster/--database flags or FDA_EVENTHOUSE_URI/FDA_DATABASE.


Governance

These surfaces expose prompt/answer text and DAX, which may be sensitive. The same rules as the review app apply: authenticate callers, scope KQL-database Viewer to authorized identities, and prefer the API's key/gateway or per-user (on-behalf-of) auth when surfacing data to a broad audience. RLS on the Eventhouse, if configured, applies to whichever identity the token represents.