Edge Flow Manager MCP Server
# Edge Flow Manager MCP Server
A thin, **read-only** [Model Context Protocol](https://modelcontextprotocol.io) server that gives
LLMs and AI agents (Claude Code, Claude Desktop, LangChain, Agent Studio) live state from a
**Cloudera Edge Flow Manager (EFM / CEM)** instance — the control plane for MiNiFi agents at the edge.
| Surface | What it exposes | API |
|---|---|---|
| **Agent classes** | the groupings of MiNiFi agents that share a flow | `/efm/api/agent-classes` |
| **Agents** | enrolled agents + last-heartbeat (online/offline) | `/efm/api/agents` |
| **Manifests** | the processor / controller-service types a class can run | `/efm/api/agent-manifests` |
| **Designer flows** | the live edge flow document, read + validate | `/efm/api/designer/flows/...` |
| **Resources** | assets & extension bundles EFM syncs to agents | `/efm/api/resource-manager` |
Practitioner-grade MCP servers already ship for NiFi, Cloudera Manager, Iceberg, Trino, and Grafana
— but nothing shipped for the **edge**. This is that server. It is the companion to the
[Cloudera Manager MCP Server](https://github.com/cldr-steven-matison/cloudera-manager-mcp-server):
CM covers the datacenter, this covers everything MiNiFi runs at the edge.
**MiNiFi has no REST API of its own.** Its command-and-control state — which agents are alive, what
flow each is running, what it's allowed to run — all lives in EFM. So an MCP server over EFM *is* an
MCP server over the MiNiFi fleet.
Every tool is GET-only. There are no write, publish, or config-mutation paths in v1 (see
[Roadmap](#roadmap)).
---
## Tools
### Agent classes & agents (5)
| Tool | Purpose |
|---|---|
| `efm_list_agent_classes()` | All agent classes (name, description, bound manifest ids) |
| `efm_get_agent_class(agent_class)` | Detail for one class — resolves it to its manifest |
| `efm_list_agents(agent_class="")` | Enrolled agents + `state` + last-heartbeat (`lastSeen`); filter by class |
| `efm_get_agent(agent_id)` | Full record for one agent (class, host, manifest hash, status) |
| `efm_get_class_monitor(agent_class)` | Per-class health: flow version, online/missing counts, metrics |
### Manifests (2)
| Tool | Purpose |
|---|---|
| `efm_get_manifest(agent_class)` | The component types a class can run — is a flow deployable there? |
| `efm_get_manifest_by_id(manifest_id)` | One manifest by id, with full property descriptors |
### Designer flows (3)
| Tool | Purpose |
|---|---|
| `efm_list_flows()` | One summary per class: `identifier` (flowId), `agentClass`, root PG id |
| `efm_get_flow(flow_id)` | The full live edge flow document (PGs, processors, connections) |
| `efm_validate_flow(flow_id)` | Validation results — the check EFM runs before a publish |
### Resources (2)
| Tool | Purpose |
|---|---|
| `efm_list_resources()` | All assets / extension bundles in the resource manager |
| `efm_list_class_resources(agent_class)` | Resources assigned to one class |
---
## Prerequisites
1. **Git** — `brew install git`
2. **Node.js** — for `npx` / MCP Inspector: `brew install node`
3. **uv** — `curl -LsSf https://astral.sh/uv/install.sh | sh`
4. A reachable EFM / CEM instance. EFM's default HTTP port is **10090**; the REST base is
`http://<efm-host>:10090/efm/api`.
> On Kubernetes (the CSO / CFM operator), reach EFM with
> `kubectl port-forward service/efm 10090:10090 -n <namespace>` and point `EFM_BASE_URL` at
> `http://127.0.0.1:10090/efm/api`.
---
## Step 1 — Clone
```bash
git clone https://github.com/cldr-steven-matison/edge-flow-manager-mcp-server.git
cd edge-flow-manager-mcp-server
```
## Step 2 — Configure
```bash
cp .env.example .env
$EDITOR .env
set -a; source .env; set +a
```
Minimal `.env` (unauthenticated EFM — the default):
```bash
EFM_BASE_URL=http://efm-host:10090/efm/api
```
With HTTP Basic and a self-signed TLS cert:
```bash
EFM_BASE_URL=https://efm-host:10090/efm/api
EFM_USER=admin
EFM_PASSWORD=yourpassword
EFM_VERIFY_SSL=false
```
## Step 3 — Run with MCP Inspector
```bash
npx @modelcontextprotocol/inspector@0.14.0 uv run --directory . run-server
```
> **Pin the Inspector to the v1 line (`@0.14.0`).** This server pins `mcp<2` (the v1 FastMCP
> idiom, matching the sibling Cloudera MCP servers). The current `@latest` Inspector (2.x)
> completes `tools/list` but its Tools pane renders **empty** against a v1 server — the tool
> list simply doesn't show. `@0.14.0` (classic **Connect → List Tools** UI) lists all tools
> correctly. For an ad-hoc launch you may also need `DANGEROUSLY_OMIT_AUTH=true` to skip the
> proxy token locally.
The server prints (to stderr) whether EFM was wired up:
```
Starting Edge Flow Manager MCP Server via transport: stdio (EFM configured)
```
In the Inspector: **Connect** → **List Tools** → you should see all 12 tools.
## Step 4 — Smoke tests
| Call | Expect |
|---|---|
| `efm_list_agent_classes()` | your agent-class names |
| `efm_list_agents()` | enrolled agents + last-heartbeat |
| `efm_list_flows()` | one summary per class, each with a flowId |
| `efm_list_resources()` | assets / extension bundles (may be empty on a fresh EFM) |
A typical investigation chains them: `efm_list_agent_classes` → `efm_get_agent_class` →
`efm_get_manifest` → `efm_list_flows` → `efm_get_flow` → `efm_validate_flow`.
## Step 5 — Claude Desktop / Claude Code
Local clone:
```json
{
"mcpServers": {
"edge-flow-manager": {
"command": "uv",
"args": ["run", "--directory", "/abs/path/to/edge-flow-manager-mcp-server", "run-server"],
"env": {
"EFM_BASE_URL": "http://efm-host:10090/efm/api"
}
}
}
}
```
Straight from GitHub (no clone), via `uvx`:
```json
{
"mcpServers": {
"edge-flow-manager": {
"command": "uvx",
"args": ["--from", "git+https://github.com/cldr-steven-matison/edge-flow-manager-mcp-server@main", "run-server"],
"env": { "EFM_BASE_URL": "http://efm-host:10090/efm/api" }
}
}
}
```
---
## Agent-loop mapping
| Loop | Tool sequence |
|---|---|
| **Fleet health** | `efm_list_agent_classes` → `efm_get_class_monitor` → `efm_list_agents` (read each class's last-heartbeat) |
| **Flow inspection** | `efm_list_flows` → `efm_get_flow` → `efm_validate_flow` |
| **Deployability check** | `efm_get_agent_class` → `efm_get_manifest` → `efm_list_class_resources` |
Knowing *which* agents are alive is a different question than *what flow* they run, which is
different again from *what a class can run* — exposing all three lets an agent join them in one
investigation without leaving the conversation.
---
## Configuration reference
All settings are environment variables (see [`.env.example`](.env.example) for the annotated set):
`EFM_BASE_URL` (the only required one), `EFM_USER` / `EFM_PASSWORD` (only if EFM enforces Basic),
`EFM_VERIFY_SSL` (`true` | `false` | path to a CA bundle), plus globals `EFM_MCP_TIMEOUT` /
`EFM_MCP_RETRIES` / `EFM_MCP_RETRY_WAIT`, `MCP_TRANSPORT` (`stdio` | `sse`), and `EFM_READONLY`
(defaults `true`; v1 has no write paths — the flag is plumbed for the future write tools).
---
## Roadmap
v1 is read-only and REST-only. Two extensions are deliberately deferred:
- **Write tools, off by default.** `efm_add_processor`, `efm_add_connection`, and
`efm_publish_flow`, gated behind `EFM_READONLY=false`. A publish pushes the flow to **every
agent in the class** on its next heartbeat, so these land only once the read tools are in real
use. The EFM Flow Designer write API is one `POST` per processor and one per connection (no bulk
create, no whole-flow `PUT`), with a `GET .../validate` clean before `POST .../publish`.
- **Postgres-backed `efm_get_operations()`.** EFM's `operation` / `bulk_operation` tables in
Postgres are the durable truth for command history and reliable online/offline status; the REST
view can lag or, under a crash-looping agent that floods the `operation` table, hang entirely.
A read-only Postgres query is the robust source — added when operational history is needed.
---
## Related Cloudera MCP Servers
* [Cloudera Manager MCP Server](https://github.com/cldr-steven-matison/cloudera-manager-mcp-server) — CM / YARN / Ranger / Atlas
* [Cloudera NiFi MCP Server](https://github.com/cloudera/NiFi-MCP-Server)
* [Cloudera Iceberg MCP Server](https://github.com/cloudera/iceberg-mcp-server)
## License
Apache-2.0.
TDQS
Scored across 12 tools
Each tool targets a distinct resource or action: classes, agents, manifests, monitors, flows, resources. Even similar pairs (e.g. efm_get_manifest vs efm_get_manifest_by_id) are separated by query key, and efm_list_resources vs efm_list_class_resources differ by scope.
All tools follow a consistent efm_<verb>_<noun> snake_case pattern. List/get are used predictably, and compound nouns like class_monitor and class_resources are clear. Minor suffix variations (by_id) are still systematic.
12 tools is a well-scoped set for an edge flow manager: enough to cover the main entities (agent classes, agents, flows, manifests, resources) without bloat.
The read/query surface is thorough: classes, agents, manifests, flows, resources, health. Validation is included enough to test flows. However, there are no publish/update/delete operations, and resource assignment is only readable, so management actions are missing.