Skip to main content
Glama
pwn2dav
by pwn2dav
README.md
# kuna_mcp

`kuna_mcp` is a Python MCP server for targeted binary analysis with
[Kuna](https://github.com/Noelo-Lab/kuna). It exposes Kuna through MCP's
Streamable HTTP transport, so MCP clients communicate with it using JSON-RPC at
`http://127.0.0.1:8000/mcp` by default.

The project and Python package are named `kuna_mcp`; the installed shell command
uses the conventional executable spelling `kuna-mcp`.

Whole-binary decompilation is deliberately **not** exposed. Large binaries can
take a long time and produce far more context than an AI can use safely.

## MCP tools

- `list_functions` — list functions as structured JSON, with pagination when
  Kuna returns a JSON list.
- `decompile_function` — decompile one function by name or hexadecimal VMA.
- `decompile_functions` — decompile a bounded list concurrently and return one
  response. Individual failures are preserved alongside successful results.

The server does not expose `decompile-all` or `decompile-project`.

## Release status

The current release is `0.1.0`: the first usable version of `kuna_mcp`. The
server, installer, real Kuna integration, and HTTP transport are functional,
but the public MCP tool schemas may still evolve before the `1.0.0`
compatibility milestone.

## Install

Requirements are Python 3.10+, a Rust toolchain, `make`, and `git`.

```bash
./install.sh
```

The installer initializes the Kuna submodule, runs `make binaries` and
`make specs`, creates `.venv`, and installs this package. Kuna's executable is
expected at `kuna/decompiler/target/release/kuna` and its specifications at
`kuna/specs`.

For Python-only development (using an existing Kuna installation):

```bash
python3 -m venv .venv
.venv/bin/pip install -e '.[dev]'
```

## Run over HTTP

```bash
.venv/bin/kuna-mcp
```

Options and their environment equivalents:

```text
--host  KUNA_MCP_HOST  default: 127.0.0.1
--port  KUNA_MCP_PORT  default: 8000
--path  KUNA_MCP_PATH  default: /mcp
```

Example:

```bash
.venv/bin/kuna-mcp --host 0.0.0.0 --port 8080
```

The default loopback binding is intentional. If you bind to a public or shared
interface, put the server behind authentication and TLS; every authenticated
client can request reads of binaries allowed by `KUNA_ALLOWED_BINARY_ROOTS`.

Connect an MCP client to `http://127.0.0.1:8000/mcp`. The server uses stateless
Streamable HTTP with JSON responses; the MCP SDK performs initialization,
JSON-RPC validation, tool discovery, input-schema validation, and response
framing.

## Use with an MCP client

Start `kuna-mcp`, then register the following Streamable HTTP endpoint in your
MCP client:

```text
http://127.0.0.1:8000/mcp
```

For clients that accept JSON server configuration, the entry normally has this
shape (the surrounding configuration filename varies by client):

```json
{
  "mcpServers": {
    "kuna": {
      "type": "http",
      "url": "http://127.0.0.1:8000/mcp"
    }
  }
}
```

Once connected, ask the client to list functions before requesting targeted
decompilation. For example:

```text
List the first 50 functions in /bin/ls with Kuna.
Decompile function sub_187d0 from /bin/ls.
Decompile addresses 0x187d0 and 0x18940 from /bin/ls in one request.
```

The same flow can be exercised with the MCP Python client:

```python
import asyncio
from mcp import Client


async def main():
    async with Client("http://127.0.0.1:8000/mcp") as client:
        functions = await client.call_tool(
            "list_functions",
            {"binary_path": "/bin/ls", "offset": 0, "limit": 10},
        )
        print(functions.structured_content)


asyncio.run(main())
```

### MCP Inspector

With Node.js available, start the server and connect the MCP Inspector to the
URL above:

```bash
npx -y @modelcontextprotocol/inspector
```

## Configuration and limits

All values are read when the server starts.

| Variable | Default | Purpose |
| --- | --- | --- |
| `KUNA_BINARY` | `./kuna/decompiler/target/release/kuna` | Kuna executable |
| `KUNA_SLEIGH_PATH` | `./kuna/specs` | Compiled SLEIGH specifications |
| `KUNA_ALLOWED_BINARY_ROOTS` | project root, `/bin`, `/usr/bin` | Allowed input roots, separated by `:` on Unix |
| `KUNA_TIMEOUT_SECONDS` | `120` | Timeout for each Kuna process |
| `KUNA_MAX_BATCH_SIZE` | `20` | Maximum functions in one batch |
| `KUNA_MAX_CONCURRENCY` | `4` | Maximum simultaneous Kuna processes |
| `KUNA_MAX_OUTPUT_BYTES` | `8388608` | Maximum stdout bytes per Kuna call |

Set the allow-list to every directory containing binaries the MCP may inspect:

```bash
KUNA_ALLOWED_BINARY_ROOTS=/samples:/opt/firmware .venv/bin/kuna-mcp
```

Resolved paths must remain below one of those roots, so symlinks cannot escape
the allow-list. Kuna is always launched without a shell.

## Example tool arguments

List functions:

```json
{
  "binary_path": "/bin/ls",
  "mode": "auto",
  "offset": 0,
  "limit": 500
}
```

Decompile by name:

```json
{
  "binary_path": "/bin/ls",
  "function": "sub_187d0"
}
```

Decompile several addresses in one request:

```json
{
  "binary_path": "/bin/ls",
  "functions": ["0x187d0", "0x18940"],
  "by_address": true,
  "mode": "reliable"
}
```

## Test

Install the development dependencies and run the fast test suite:

```bash
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest -q
```

These tests use a controlled fake Kuna executable and an in-memory MCP client,
so they validate command construction, pagination, validation, partial batch
failures, structured MCP results, and exposed tool names without requiring a
Kuna rebuild.

To test the relevant Kuna CLI surface itself:

```bash
source "$HOME/.cargo/env"
cargo test --manifest-path kuna/decompiler/Cargo.toml \
  -p kuna-cli --test decompile_all_cli
```

### End-to-end HTTP test

Terminal 1:

```bash
.venv/bin/kuna-mcp
```

Terminal 2:

```bash
.venv/bin/python scripts/http_smoke_test.py \
  --url http://127.0.0.1:8000/mcp \
  --binary /bin/ls
```

The smoke test connects through HTTP, initializes MCP/JSON-RPC, discovers the
tools, lists functions with the real Kuna executable, and decompiles the first
non-header function by address. A successful run exits with status zero.

Only analyze binaries you are legally authorized to inspect.


https://github.com/user-attachments/assets/47458d03-e454-43ab-acc8-2a4e57a201de