Odigos
Get a demo
← all posts
Odigos

MCP Based Auto Remediation: Davis AI to Odigos MCP Server and Back Again

How we wired incident detection to Odigos MCP so instrumentation deepens on problem open and reverts on close.

MCP Based Auto Remediation: Davis AI to Odigos MCP Server and Back Again

Most of the time, you want to be as lean and efficient with your telemetry data as possible. Collecting payloads, code attributes, 100% of distributed traces and stacktraces on every request gets expensive very quickly. So teams keep the baseline light: enough to know that something failed, not enough to reconstruct why without another trip through the instrumentation config.

That works — until something breaks. Then the context you left out is exactly what you need, and someone is manually flipping rules in the middle of an incident.

We kept asking a simpler question: what if the system that already detected the problem could ask Odigos to deepen the instrumentation for you — and just as importantly, put it back when the problem closed?

That's what Odigos MCP is for. This post is how we stood that loop up end to end. We used Dynatrace, Davis AI and Workflows as the proof of concept, but the pattern isn't tied to Dynatrace specifically. Any backend that can detect an incident and call an HTTP endpoint can pull the same lever in Odigos.

Watch the demo video for the full walkthrough — Davis detecting a problem, workflows calling Odigos MCP, enriched traces landing in Dynatrace, and instrumentation reverting when the problem closes.

The Pattern (Backend-Agnostic)

The shape is deliberately simple here:

  1. Odigos instruments the app and exports OTLP into your observability backend.
  2. That backend detects a problem — failure rate, error spike, latency, whatever it already watches.
  3. On problem open, your incident automation calls a small remediation webhook with relevant incident context.
  4. That endpoint talks to the Odigos MCP server and creates temporary instrumentation rules (payloads, code attributes, and so on).
  5. New failing traces land in the same backend with the extra context.
  6. On problem close, a second call reverts — MCP deletes the temporary rules, baseline returns.
LayerJob
Your APM / observability backendDetect + orchestrate
Thin webhook / automationTranslate "incident" into MCP tool calls
Odigos MCPMutate what gets recorded
OTLP pipelineShow the richer data back where you already look

In our demo, Dynatrace filled the first row. Grafana Alerting, PagerDuty + webhook, custom ops bots, or another OpenTelemetry-aware platform could fill it just as well. Odigos doesn't need to know who called MCP — only that something asked for deeper capture, then asked to turn it off.

Why MCP Instead of Clicking Around in the UI

Odigos already lets you change instrumentation through the UI and Kubernetes CRDs. MCP sits on top of that as a tool interface agents and automation can call: enable write mode, create an instrumentation rule, delete it when you're done.

For this demo that mattered for two reasons:

  • Incidents don't wait for a human to find the right screen. Whoever gets paged needs a machine-callable API.
  • The change has to be reversible. Magnify during the fire, dial it back when it's out — same path in both directions.

We kept Odigos MCP in-cluster only (ui.odigos-system…/mcp, read-write). The observability backend never talks to MCP directly. It hits a thin webhook we control; the webhook is the only thing that calls MCP. That keeps write access inside the cluster, no matter which product sits upstream.

MCP ships with Odigos Enterprise; we run it in-cluster with read-write mode only for the remediation webhook.

What We Actually Built (Dynatrace as the Example)

1. Cluster + Odigos + destination

A GKE cluster running OdiMall (our multi-service demo app), Odigos with MCP enabled, and an OTLP destination so traces already flow into Dynatrace — the same place Davis watches.

Swap the destination, and the rest of the loop still applies with whatever backend you already have in use today.

2. A remediation webhook

A small HTTP service with two endpoints:

  • POST /remediate — create the temporary instrumentation rules via MCP
  • POST /revert — delete those rules

No LLM in the path for this version. The backend decides when; the webhook decides what to ask MCP for. That kept the demo honest and debuggable.

The rules we create on remediate:

  • HTTP payload collection — request/response bodies on the failing path
  • Messaging payload collection — when the path crosses Kafka
  • Code attributes — function, file, line, and stacktrace where the language/library supports it

Those are the same levers you'd toggle by hand in the Odigos UI. MCP just does it on demand.

To keep things simple for this demonstration, we removed all but basic logic from the webhook/automation layer. This is where agentic AI or your own custom business logic would live — controlling what levers to pull in Odigos' MCP server and when.

For clarity, we only turned on three rule types in this demo. MCP exposes many more configuration options than we needed to prove the loop.

3. Incident automation (Davis + Workflows in our case)

This part is product-specific, but the job is universal: fire on open, fire on close, don't double-fire.

In Dynatrace, Davis often opened the problem on api-gateway even when the interesting work was downstream. Filters that assumed a specific root-cause service never fired. The fix: trigger on problem state — active for remediate, closed for revert — and condition the HTTP tasks so both workflows don't run on every event.

Once that was clean, the UI matched the architecture: problem opens → successful remediate → rules appear in Odigos → enriched spans in the backend → problem closes → successful revert → rules gone.

If you wire this to another stack, you're implementing the same two hooks: "incident started" and "incident ended."

What Changes in the Trace

Before MCP

Same failing waterfall: gateway → order-service → inventory conflict → upstream 5XX error. You know it failed. You don't have the body that was sent, or much code-level signal on the span.

After MCP

Same failing request. New attributes on those spans — payloads and code context — without restarting pods. That's the point: the incident path gets deeper instrumentation while it's still the incident path.

On the Kafka leg (e.g. order → notification), spans can include messaging.message.payload so you see the event body, not just that a consumer failed.

When the problem closes, the second call tears the rules down. You're not permanently paying for verbose capture on every request. All of this happens as soon as an issue is opened and is reversed as soon as it closes, with the ability to add in any amount of logic around why/when the MCP server is invoked.

The Broader Point

This is the same idea we keep coming back to: the model or the APM isn't the bottleneck — the data that reaches it is. Lean by default. Deeper when error rates spike. Instrumentation that preserves the anomaly instead of hoping a fixed sample rate caught it.

Odigos MCP makes that depth a callable control plane. Dynatrace was our proof point because that's how a lot of teams already run ops — but the principle is simple: detect anywhere, adjust the data plane in Odigos, put it away when you're done.

Watch the demo video to see the full loop in action.

Odigos MCP Tools Reference

Odigos MCP exposes 83 tools for reading cluster state and mutating instrumentation, sampling, destinations, and more. Tools are grouped below by area. Write operations require enable_write_mode first; check with get_access_mode.

Access & safety

ToolWhat it does
get_access_modeReport whether the server is in read-only or read-write mode
enable_write_modeEnable cluster-mutating tools (requires confirmation)
disable_write_modeSwitch back to read-only mode

Cluster health & overview

ToolWhat it does
describe_odigosCluster-wide health: version, tier, gateway/odiglet status
get_gateway_infoGateway deployment rollout, replicas, resources
get_odiglet_infoOdiglet DaemonSet status per node
get_overview_metricsPer-source and per-destination bytes sent and throughput
get_service_mapService-call topology with request counts
get_peer_sourcesInbound and outbound peers for one service
collect_diagnose_bundleDiagnostic bundle for support (logs, CRDs, profiles, metrics)
pause_odigosPause all reconciliation by scaling instrumentor and odiglet to zero

Sources (instrumentation)

ToolWhat it does
list_sourcesList all instrumented workloads
describe_sourceFull status for one workload
list_workloads_in_namespaceList all workloads in a namespace
instrument_sourceInstrument a workload (creates Source CRD; may restart pods)
instrument_namespaceBulk-instrument an entire namespace
uninstrument_sourceRemove instrumentation from a workload
uninstrument_namespaceRemove namespace-level instrumentation
uninstrument_clusterRemove all instrumentation cluster-wide
update_sourceOverride service name or distro for a container
get_source_conditionsAggregated error/stuck conditions across Sources
get_runtime_detectionDetected language, runtime version, and libc per container
get_instrumentation_healthPer-pod SDK/eBPF health (tracer, sampler, exporter)
recover_from_rollbackLift auto-rollback after agent-caused crash
restart_workloadsRolling restart after config changes
restart_podDelete a single pod so its controller recreates it

Instrumentation rules

ToolWhat it does
list_instrumentation_rulesList all instrumentation rules
get_instrumentation_ruleReturn one rule's full spec
create_instrumentation_ruleCreate a rule (headers, payload, code attributes, and more)
update_instrumentation_ruleModify an existing rule
delete_instrumentation_ruleDelete a rule by resource name
add_custom_instrumentationAdd an eBPF probe for a specific function or method

Sampling

ToolWhat it does
get_samplingList Sampling CRs with per-group rule counts
get_sampling_groupReturn one sampling group's full spec
create_sampling_groupCreate an empty sampling group
delete_sampling_groupDelete a group and all its rules
create_highly_relevant_operation_ruleAlways keep traces you care about (errors, slow paths)
update_highly_relevant_operation_ruleModify a highly-relevant rule
delete_highly_relevant_operation_ruleRemove a highly-relevant rule
create_noisy_operation_ruleDrop high-volume, low-value traces
update_noisy_operation_ruleModify a noisy-operation rule
delete_noisy_operation_ruleRemove a noisy-operation rule
create_cost_reduction_ruleDown-sample high-volume operations to cut spend
update_cost_reduction_ruleModify a cost-reduction rule
delete_cost_reduction_ruleRemove a cost-reduction rule

Destinations (telemetry backends)

ToolWhat it does
list_destinationsList all configured destinations
get_destinationReturn one destination's full spec
list_destination_typesList supported types (Datadog, Jaeger, and others)
get_destination_schemaRequired, optional, and secret fields for a destination type
list_potential_destinationsAuto-discovered destinations from cluster annotations
create_destinationCreate a new destination
update_destinationUpdate an existing destination
delete_destinationDelete a destination and stop telemetry flow

Actions (collector pipeline processing)

ToolWhat it does
list_actionsList all Actions (PII masking, attribute edits, and more)
get_actionReturn one Action's full spec
create_actionCreate an Action (K8sAttributesResolver, AddClusterInfo, and more)
update_actionUpdate an existing Action
delete_actionDelete an Action

Profiling

ToolWhat it does
enable_source_profilingOpen an on-demand profiling slot for a workload
disable_source_profilingClose a profiling slot and free buffered data
clear_source_profiling_bufferDrop buffered samples but keep the slot active
get_source_profileReturn a full flamebearer profile (large response)
get_source_hot_functionsTop hot functions ranked by self time
list_profiling_slotsList active profiling slots and memory stats

Data streams

ToolWhat it does
list_data_streamsList data stream names with per-stream counts
update_data_streamRename a stream (cascades to Sources and Destinations)
delete_data_streamDelete a stream and remove labels

Distributions & profiles

ToolWhat it does
list_distrosList available OTel distributions by language
get_distroReturn full spec for one distribution
set_distroSelect a distribution for a container
list_profilesList curated profile presets
apply_profileApply a profile to OdigosConfiguration

Configuration

ToolWhat it does
get_effective_configReturn merged effective OdigosConfiguration
get_config_yamlsUI form schema for all config fields
update_local_ui_configWrite local UI overrides
reset_local_ui_configReset local UI config to defaults
update_remote_configWrite central-managed RemoteConfig
set_component_log_levelSet log level for autoscaler, scheduler, instrumentor, odiglet, and others

Kubernetes introspection

ToolWhat it does
get_k8s_manifestRaw YAML for any K8s resource Odigos knows about
get_pod_detailsFull pod details (containers, lifecycle, resources)
get_collector_podGateway or odiglet pod manifest and lifecycle state
list_gateway_podsList gateway collector pods
list_odiglet_podsPer-node odiglet pods with live throughput metrics
The Production Context Platform

Stop guessing. Ask production.

One agent. One service. See how Odigos helps answer a production question.

MCP Based Auto Remediation: Davis AI to Odigos MCP Server and Back Again | Odigos Blog