# MCP Server Request Flow and Architecture in flux159/mcp-server-kubernetes

> Discover the MCP server request flow and architecture in flux159/mcp-server-kubernetes. Learn how it routes requests via STDIO, SSE, or HTTP to a central core for validation, filtering, and dispatch to KubernetesManager tools.

- Repository: [Suyog Sonwalkar/mcp-server-kubernetes](https://github.com/flux159/mcp-server-kubernetes)
- Tags: architecture
- Published: 2026-03-02

---

**The MCP Kubernetes server uses a modular, request-driven architecture that routes client requests through STDIO, SSE, or HTTP transports to a central Server core, which validates, filters, and dispatches calls to KubernetesManager-backed tools while wrapping every operation in telemetry middleware.**

The `flux159/mcp-server-kubernetes` repository implements a Model Context Protocol (MCP) server that bridges AI clients with Kubernetes clusters. Understanding its request flow reveals how it safely exposes cluster operations through a clean separation between transport concerns, request routing, and domain-specific Kubernetes logic.

## Transport Layer and Server Startup

The entry point at [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts) initializes the server and selects the transport protocol based on environment variables. The implementation uses the official MCP SDK to create a `Server` instance configured via `serverConfig` from [`src/config/server-config.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/config/server-config.ts).

```typescript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { startSSEServer } from "./utils/sse.js";
import { startStreamableHTTPServer } from "./utils/streamable-http.js";

if (process.env.ENABLE_UNSAFE_SSE_TRANSPORT) {
  startSSEServer(server);
} else if (process.env.ENABLE_UNSAFE_STREAMABLE_HTTP_TRANSPORT) {
  startStreamableHTTPServer(server);
} else {
  const transport = new StdioServerTransport();
  server.connect(transport);
}

```

The server supports three transport mechanisms:

- **STDIO** (default) – Used by CLI clients; reads JSON-RPC messages from stdin and writes to stdout
- **SSE** – Server-Sent Events for streaming responses; enabled via `ENABLE_UNSAFE_SSE_TRANSPORT`
- **Streamable HTTP** – Custom HTTP transport; enabled via `ENABLE_UNSAFE_STREAMABLE_HTTP_TRANSPORT`

Each transport forwards raw JSON-RPC payloads to the server core without processing the message content.

## Server Core and Request Routing

The server core registers request handlers for four primary MCP methods in [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts). Each handler maps to a specific schema defined by the MCP SDK:

```typescript
server.setRequestHandler(ListResourcesRequestSchema, resourceHandlers.listResources);
server.setRequestHandler(ReadResourceRequestSchema, resourceHandlers.readResource);
server.setRequestHandler(ListToolsRequestSchema, async () => { ... });
server.setRequestHandler(CallToolRequestSchema, withTelemetry(async request => { ... }));

```

**`ListResources`** and **`ReadResource`** dispatch to the resource handlers in [`src/resources/handlers.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/resources/handlers.ts). **`ListTools`** returns the available tool schemas after applying environment-based filtering. **`CallTool`** serves as the primary execution entry point, receiving tool names and arguments before routing to the appropriate implementation.

Every `CallTool` request passes through **`withTelemetry`** middleware defined in [`src/middleware/telemetry-middleware.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/middleware/telemetry-middleware.ts), which captures timing metrics, success states, and error details before the request reaches domain logic.

## Environment-Driven Tool Filtering

Before exposing tools to clients, the server applies security filtering based on three environment variables defined in [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts):

- **`ALLOW_ONLY_READONLY_TOOLS`** – Exposes only safe, read-only operations (e.g., `kubectl_get`, `list_resources`)
- **`ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS`** – Excludes explicitly destructive operations while permitting state-changing but non-destructive actions
- **`ALLOWED_TOOLS`** – Comma-separated whitelist specifying exactly which tools to expose

The filtering logic compares requested tools against hardcoded arrays `readonlyTools` and `destructiveTools`:

```typescript
if (allowedToolsEnv) { 
  // Parse comma-separated list
}
else if (allowOnlyReadonlyTools) { 
  tools = readonlyTools; 
}
else if (nonDestructiveTools) { 
  tools = allTools.filter(t => !destructiveTools.includes(t)); 
}

```

This mechanism prevents accidental cluster modifications when running in restricted environments.

## Domain Logic and KubernetesManager

Once a tool call passes filtering, the server dispatches to type-guarded function implementations. The **`k8sManager`** instance from [`src/utils/kubernetes-manager.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/utils/kubernetes-manager.ts) injects into every tool, providing authenticated access to the cluster:

```typescript
if (name === "kubectl_get") {
  return await kubectlGet(k8sManager, input as KubectlGetArgs);
}
switch (name) {
  case "install_helm_chart": return await installHelmChart(input);
  case "port_forward":      return await startPortForward(k8sManager, input);
}

```

**`KubernetesManager`** handles critical responsibilities:

- **Configuration loading** – Supports YAML, JSON, minimal token+server pairs, in-cluster config, or default `~/.kube/config` via the constructor
- **API client exposure** – Provides typed clients via `getCoreApi()` (CoreV1Api), `getAppsApi()` (AppsV1Api), and `getBatchApi()` (BatchV1Api)
- **Resource lifecycle tracking** – `trackResource()` and `cleanup()` manage temporary resources
- **Network operations** – `trackPortForward()` and `trackWatch()` manage long-lived connections

Tools like `kubectl_get` ([`src/tools/kubectl-get.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/tools/kubectl-get.ts)) and `port_forward` ([`src/tools/port_forward.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/tools/port_forward.ts)) use these clients to execute cluster operations without managing authentication or connection state themselves.

## Resource Handlers

The [`src/resources/handlers.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/resources/handlers.ts) file implements the resource discovery protocol, allowing clients to browse available cluster data without prior knowledge of the Kubernetes API structure:

- **`listResources`** – Returns a static catalog of URI templates (e.g., `k8s://default/pods`, `k8s://namespaces`) that clients can query
- **`readResource`** – Parses incoming URIs to determine whether the request targets a cluster-scoped resource (nodes, namespaces) or namespaced resource (pods, deployments), then calls the appropriate `KubernetesManager` method (`listNamespacedPod`, `listNamespacedDeployment`, etc.)

This design decouples the client's data discovery from the underlying API implementation details.

## Response Flow and Error Handling

After domain logic execution completes, the server core serializes the result or an `McpError` back through the same transport layer that received the request. For streaming transports (SSE and streamable HTTP), the response may be chunked, but the logical flow remains consistent:

1. Tool or handler returns data
2. Server wraps the payload in MCP response format
3. Transport serializes to JSON-RPC or SSE events
4. Client receives the formatted response

The telemetry middleware captures final status codes and timing metrics before the response leaves the server boundary, ensuring complete observability of the request lifecycle.

## Summary

- **Modular transport layer** supports STDIO, SSE, and HTTP transports selected via environment variables in [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts)
- **Request routing** occurs through schema-specific handlers (`ListResources`, `ReadResource`, `ListTools`, `CallTool`) registered on the MCP Server instance
- **Security filtering** happens at startup via `ALLOW_ONLY_READONLY_TOOLS`, `ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS`, or `ALLOWED_TOOLS` environment variables
- **Domain isolation** keeps Kubernetes API interactions contained within `KubernetesManager` ([`src/utils/kubernetes-manager.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/utils/kubernetes-manager.ts)), which handles authentication, client initialization, and resource cleanup
- **Telemetry coverage** wraps every `CallTool` request via `withTelemetry` middleware in [`src/middleware/telemetry-middleware.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/middleware/telemetry-middleware.ts)

## Frequently Asked Questions

### How does the MCP server handle different transport protocols?

The server selects transports based on environment variables at startup. By default, it uses `StdioServerTransport` for CLI communication. When `ENABLE_UNSAFE_SSE_TRANSPORT` is set, it initializes `startSSEServer` from [`src/utils/sse.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/utils/sse.ts) for Server-Sent Events. When `ENABLE_UNSAFE_STREAMABLE_HTTP_TRANSPORT` is set, it uses `startStreamableHTTPServer` from [`src/utils/streamable-http.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/utils/streamable-http.ts). All transports forward raw JSON-RPC to the same request handlers, ensuring consistent behavior regardless of the connection method.

### What security mechanisms control tool access?

The server implements three environment-driven filtering strategies in [`src/index.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/index.ts). `ALLOW_ONLY_READONLY_TOOLS` restricts the server to read operations like `kubectl_get`. `ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS` filters out explicitly destructive tools while allowing state changes. `ALLOWED_TOOLS` accepts a comma-separated whitelist. These filters apply at server initialization, modifying the tool list returned by `ListTools` and preventing filtered tools from executing even if requested.

### How does KubernetesManager handle cluster authentication?

`KubernetesManager` ([`src/utils/kubernetes-manager.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/utils/kubernetes-manager.ts)) loads kubeconfig data through a priority-based constructor that handles multiple credential sources: explicit YAML/JSON files, minimal token and server pairs, in-cluster service account tokens, or the default `~/.kube/config`. It exposes typed API clients (`CoreV1Api`, `AppsV1Api`, `BatchV1Api`) that tools consume, abstracting authentication and connection management from individual tool implementations.

### What happens when a tool call fails?

Failures propagate through the `withTelemetry` middleware in [`src/middleware/telemetry-middleware.ts`](https://github.com/flux159/mcp-server-kubernetes/blob/main/src/middleware/telemetry-middleware.ts), which captures error details and timing before the server returns an `McpError` to the client. The telemetry system records the failure state for observability, while the transport layer serializes the error according to MCP protocol specifications, ensuring clients receive structured error information regardless of whether they connect via STDIO, SSE, or HTTP.