Metadata-Version: 2.5
Name: flink-mcp-server
Version: 0.1.0
Summary: Platform-independent, read-only MCP server for monitoring Apache Flink clusters via the REST API
Project-URL: Homepage, https://github.com/hakkiburakalks/flink-mcp-server
Project-URL: Source, https://github.com/hakkiburakalks/flink-mcp-server
Project-URL: Issues, https://github.com/hakkiburakalks/flink-mcp-server/issues
Author: hakkiburakalks
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: apache-flink,flink,llm,mcp,model-context-protocol,monitoring,observability
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: mcp<2,>=1.2.0
Requires-Dist: pyyaml>=6
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# flink-mcp-server

Read-only MCP server for monitoring Apache Flink clusters. It only needs a reachable
JobManager REST endpoint, so it works the same on bare metal, Docker, Kubernetes or YARN.
Tool output is summarized for LLMs rather than returning raw REST JSON.

## Tools (V1)

| Tool | What it returns |
| --- | --- |
| `cluster_overview` | Flink version, slots, job counts |
| `list_jobs` | Jobs with state and duration |
| `job_details` | Per-vertex status and parallelism |
| `job_exceptions` | Root exception and recent history (stacktraces trimmed) |
| `checkpoint_stats` | Counts, failure rate, last completed/failed |
| `backpressure` | Per-vertex backpressured/busy/idle ms per second |
| `taskmanagers` | Slots and resources per TaskManager |
| `job_config` | Job execution config |
| `job_metrics` | Job metric values, or the catalogue of available metric ids (filterable) |
| `list_jars` | Uploaded JARs and their entry classes |
| `cluster_config` | JobManager configuration, filterable by key |
| `list_clusters` | Configured clusters (names and URLs only) |
| `fleet_overview` | Overview of all clusters in one call; unreachable ones report an error |
| `diagnose_job` | One-call verdict (`healthy`/`degraded`/`critical`) with ranked findings from state, tasks, exceptions, checkpoints and backpressure |

All per-cluster tools take an optional `cluster` argument; omit it for the default cluster.

## Configuration

| Variable | Default | |
| --- | --- | --- |
| `FLINK_REST_URL` | `http://localhost:8081` | JobManager REST endpoint |
| `FLINK_REST_TOKEN` | unset | Sent as `Authorization: Bearer ...` |
| `FLINK_MCP_TRANSPORT` | `stdio` | `stdio` or `streamable-http` |
| `FLINK_MCP_HOST` / `FLINK_MCP_PORT` | `127.0.0.1` / `8000` | HTTP bind address |
| `FLINK_MCP_AUTH_TOKEN` | unset | Bearer token required on every HTTP request |
| `FLINK_MCP_REQUIRE_AUTH` | `true` | `false` is the same as `--no-auth` |
| `FLINK_CLUSTERS_FILE` | unset | YAML with several clusters (overrides the two above) |

Multiple clusters: copy `clusters.example.yaml`, then set `FLINK_CLUSTERS_FILE`.
Per cluster: `url`, `token` or `token_env` (preferred, keeps secrets out of the file),
`ca_cert`, `insecure`, `timeout`.

## Install and run

One-line installers. They install [uv](https://docs.astral.sh/uv/) first if it is missing,
then the server. They download and run a script, so read it first if you prefer
([install.sh](https://github.com/hakkiburakalks/flink-mcp-server/blob/main/install.sh), [install.ps1](https://github.com/hakkiburakalks/flink-mcp-server/blob/main/install.ps1)).

macOS / Linux:

```
curl -LsSf https://raw.githubusercontent.com/hakkiburakalks/flink-mcp-server/main/install.sh | sh
```

Windows (PowerShell):

```
irm https://raw.githubusercontent.com/hakkiburakalks/flink-mcp-server/main/install.ps1 | iex
```

Options: register in Claude Code and point at your cluster, or remove everything.

```
curl -LsSf .../install.sh | sh -s -- --claude-code --url http://localhost:8081
& ([scriptblock]::Create((irm .../install.ps1))) -ClaudeCode -Url http://localhost:8081
```

Uninstall with `--uninstall` / `-Uninstall`. Set `FLINK_MCP_SOURCE` to install a specific tag or
a local checkout (e.g. `git+https://github.com/hakkiburakalks/flink-mcp-server@v0.1.0`).

Or skip installing and let uv run it on demand (Windows, macOS, Linux):

```
uvx --from git+https://github.com/hakkiburakalks/flink-mcp-server flink-mcp-server
```

Add it to an MCP client. Claude Code:

```
claude mcp add flink -e FLINK_REST_URL=http://localhost:8081 -- uvx --from git+https://github.com/hakkiburakalks/flink-mcp-server flink-mcp-server
```

Claude Desktop, Cursor and others (`mcpServers` in their JSON config):

```json
{
  "mcpServers": {
    "flink": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/hakkiburakalks/flink-mcp-server", "flink-mcp-server"],
      "env": { "FLINK_REST_URL": "http://localhost:8081" }
    }
  }
}
```

From a checkout: `uv sync --extra dev && uv run flink-mcp-server`.

## Remote access (Streamable HTTP)

```
FLINK_MCP_AUTH_TOKEN=change-me flink-mcp-server --transport streamable-http --host 0.0.0.0 --port 8000
```

The endpoint is `http://<host>:8000/mcp`. Clients send `Authorization: Bearer <token>`.

Authentication is on by default:

| Situation | Behaviour |
| --- | --- |
| `FLINK_MCP_AUTH_TOKEN` set | Token enforced (always, even with `--no-auth`) |
| Loopback bind, no token | Open; fine for local use |
| Non-loopback bind, no token | A random token is generated and printed to stderr at startup |
| Non-loopback bind, no token, `--no-auth` | Open, with a warning. Only do this on a trusted network |

The server speaks plain HTTP: put it behind a TLS-terminating proxy before exposing it.


## Test

```
uv run pytest                      # unit tests
docker compose -f tests/docker-compose.yml up -d
uv run pytest -m integration       # needs the local cluster (Docker)
```

## Roadmap

Done: V2 multi-cluster, token/TLS options, Streamable HTTP with bearer auth.
Next: Kubernetes discovery, V3 diagnostics (Prometheus, logs), V4 approval-gated operations and SQL Gateway.
