---
title: "Setup"
url: "https://nsta1.github.io/Orleans.Lattice/docs/lattice.api.mcp.telemetry/setup.html"
source: "https://github.com/NSTA1/Orleans.Lattice/blob/release/9.9/docs/lattice.api.mcp.telemetry/setup.md"
package: "Orleans.Lattice.Api.Mcp.Telemetry"
version: "9.9.0"
documents: "Orleans.Lattice 9.9.0 (release line 9.9)"
built: "2026-10-04"
all-pages: "https://nsta1.github.io/Orleans.Lattice/llms.txt"
bundle: "https://nsta1.github.io/Orleans.Lattice/docs/lattice.api.mcp.telemetry/llms-full.txt"
---
# Setup

Part of the [Api.Mcp.Telemetry documentation](README.md).

Registering the `Orleans.Lattice.Api.Mcp.Telemetry` tool module on an MCP host, pointing it at a metrics backend, and configuring the credential, guardrails, and metric-access allow-list.

## Prerequisites

The telemetry tools plug into the `Orleans.Lattice.Api.Mcp` binding, so the host must:

- Have called `AddLatticeMcp(...)` (co-hosted) or `AddLatticeMcpRemote(...)` (remote) to register the MCP front door - see [MCP setup](../lattice.api.mcp/setup.md).
- Reach a read-only Prometheus / PromQL-compatible HTTP backend that scrapes the cluster's `orleans.lattice` metrics - see [Metrics](../lattice/metrics.md).

The telemetry tools call no `Orleans.Lattice.Api.*` facade and need no in-silo activation: they proxy the metrics backend directly, so the module can run co-hosted on a silo or on a remote head. Discovery still needs the caller's effective permissions, as for every group - the auth facade (`AddLatticeAuthApi()`) when co-hosted, or the `Auth` endpoint on a remote head (see [MCP setup](../lattice.api.mcp/setup.md#prerequisites)).

## Register the tool module

`AddTelemetryTools(...)` binds and validates `LatticeApiMcpTelemetryOptions`, registers the default HTTP-backed backend client (unless the host registered its own `IPrometheusQueryClient` first) and the metric-access policy (the policy is built once, with its wildcard patterns precompiled), registers the `TelemetryAccessAuthorizer` every tool consults at call time, and registers the telemetry tool group so its tools are advertised to a caller holding a cluster-wide `LatticeOperation.Telemetry` grant. It is idempotent: calling it twice registers exactly one tool group and one backend client.

```csharp verify
using Orleans.Lattice.Api.Mcp.Telemetry;

var services = new ServiceCollection();
services.AddLatticeMcp();

services.AddTelemetryTools(o =>
{
    o.BackendAddress = new Uri("https://prometheus.internal:9090/");
    o.RequestTimeout = TimeSpan.FromSeconds(30);
    o.MaxRange = TimeSpan.FromHours(24);
    o.MaxStep = TimeSpan.FromHours(1);
});
```

## Options

`LatticeApiMcpTelemetryOptions` (populated through the `AddTelemetryTools` delegate):

| Option | Type | Default | Purpose |
|---|---|---|---|
| `BackendAddress` | `Uri?` | none | The absolute base address of the read-only Prometheus / PromQL-compatible backend. A host that opts telemetry in must supply one. |
| `AuthMode` | `LatticeTelemetryBackendAuthMode` | `None` | How the proxy authenticates to the backend: `None`, `Bearer`, `Basic`, `MutualTls`, or `DynamicBearer`. The static modes require the matching `Credential` member; `DynamicBearer` instead requires a registered `ITelemetryBackendTokenProvider`. |
| `Credential` | `LatticeTelemetryBackendCredential?` | `null` | The backend credential secret, consulted per `AuthMode`. Carries the backend credential only - never the caller's Lattice credential. |
| `RequestTimeout` | `TimeSpan` | 30s | The per-request timeout for a backend call. Must be strictly positive and no longer than `int.MaxValue` milliseconds (about 24.8 days), the longest finite timeout `HttpClient` accepts. |
| `MaxRange` | `TimeSpan` | 24h | The largest window (`end - start`) a single range query may span. Must be strictly positive. |
| `MaxStep` | `TimeSpan` | 1h | The largest resolution step a single range query may request. Must be strictly positive. |
| `MetricAccess` | `LatticeTelemetryMetricAccessMode` | `ReadAll` | `ReadAll` exposes every backend metric; `DenyAllExceptAllowed` restricts the surface to `AllowedMetrics`. |
| `AllowedMetrics` | `IList<string>` | empty | Exact names and/or `*`-wildcard patterns permitted under `DenyAllExceptAllowed`. Ignored under `ReadAll`. |

The options are validated when they are first resolved - the binding registers no start-up validation, so a misconfiguration surfaces as an `OptionsValidationException` on first use rather than at host start: the backend address must be an absolute URI, the timeouts and range guardrails must be strictly positive (and the request timeout no longer than `HttpClient` accepts), each static non-`None` auth mode must carry its matching credential member (`DynamicBearer` carries no static credential and instead resolves a token provider at request time), and `DenyAllExceptAllowed` must list at least one allowed metric, with no null, empty, or whitespace entry.

## Backend authentication

Pick the mode that matches the backend and supply the matching `Credential` member:

```csharp verify
using Orleans.Lattice.Api.Mcp.Telemetry;

var services = new ServiceCollection();
services.AddLatticeMcp();

// HTTP basic authentication to the backend.
services.AddTelemetryTools(o =>
{
    o.BackendAddress = new Uri("https://prometheus.internal:9090/");
    o.AuthMode = LatticeTelemetryBackendAuthMode.Basic;
    o.Credential = new LatticeTelemetryBackendCredential
    {
        BasicUsername = "lattice-reader",
        BasicPassword = "backend-secret",
    };
});
```

- `Bearer` stamps `Authorization: Bearer <token>` from `Credential.BearerToken`.
- `Basic` stamps `Authorization: Basic <base64(user:password)>` from `Credential.BasicUsername` / `Credential.BasicPassword`.
- `MutualTls` presents `Credential.ClientCertificate` on the transport handler (no `Authorization` header).
- `None` sends no credential.
- `DynamicBearer` stamps a rotating `Authorization: Bearer` token fetched per request from a registered `ITelemetryBackendTokenProvider`, instead of a static `Credential`. Use it when the backend needs a short-lived token that rotates (for example an Entra token for Azure Monitor managed Prometheus). Register a provider that implements the seam - the [`Orleans.Lattice.Api.Mcp.Telemetry.Azure`](../lattice.api.mcp.telemetry.azure/README.md) companion supplies an Azure managed-identity one. The proxy fails closed if `DynamicBearer` is selected with no provider registered, or if the provider returns an empty token - it never sends an unauthenticated backend query.

## Restrict the metric surface

By default the proxy reads any metric the backend exposes. To limit it to an explicit allow-list, switch to `DenyAllExceptAllowed` and list the exact names and/or `*` patterns:

```csharp verify
using Orleans.Lattice.Api.Mcp.Telemetry;

var services = new ServiceCollection();
services.AddLatticeMcp();

services.AddTelemetryTools(o =>
{
    o.BackendAddress = new Uri("https://prometheus.internal:9090/");
    o.MetricAccess = LatticeTelemetryMetricAccessMode.DenyAllExceptAllowed;
    o.AllowedMetrics.Add("orleans_lattice_shard_writes_total"); // exact name
    o.AllowedMetrics.Add("orleans_lattice_wal_*");              // wildcard pattern
});
```

Wildcard patterns are precompiled once when the policy is built, so a per-call admission check never recompiles a pattern. See [Security](security.md) for how the allow-list is enforced across the four tools.

## Next

- [Tools](tools.md) - the four telemetry tools and their arguments and results.
- [Security](security.md) - the dual-credential trust boundary and the metric-access allow-list.
