QNX MCP Server
by ChHaEoN
README.md
# QNX MCP Server
A read-only MCP server for diagnosing a QNX 8.0 target from a Linux development
host. The local demo reproduces a real synchronous IPC deadlock in two original
C programs and shows the wait cycle from structured QNX evidence.
## Why QNX
On QNX, a thread that sends a message can wait for a receiver (**SEND**) or for a
reply after the receiver accepted the message (**REPLY**). A thread in
**RECEIVE** can simply be an idle server. A generic process list cannot tell you
which IPC peer or channel is involved. This server reports those details from
`pidin` and leaves unknown fields empty, so an assistant can distinguish an idle
receiver from a real dependency cycle. [QNX message passing](https://www.qnx.com/developers/docs/8.0/com.qnx.doc.neutrino.lib_ref/topic/m/msgsend.html)
```text
MCP client ── stdio ── Linux / WSL2 qnx-mcp ── verified SSH/SFTP ── QNX 8.0
```
The supported MVP target is **QEMU x86_64**. The tested host uses
**Ubuntu 24.04 WSL2**, **Python 3.12**, and the Linux **QNX SDP 8.0 series with
8.0.5 components**. The guest reports `QNX 8.0.0 x86pc` through `uname`.
The original demo uses `qcc -Vgcc_ntox86_64`. The MCP process itself needs no
SDK, compiler, AWS credentials, or application-side LLM key.
## Install and connect
1. Obtain your own [QNX Everywhere SDK and license](https://www.qnx.com/products/everywhere/).
Build and boot a private guest using [the QEMU setup](docs/qemu.md).
2. Inside Linux, install project dependencies with [uv](https://docs.astral.sh/uv/getting-started/installation/):
```sh
uv sync --locked
```
Alternatively, use `python3 -m venv .venv` and
`.venv/bin/python -m pip install -e .` if your Linux Python provides pip.
3. Copy [targets/qemu.yaml](targets/qemu.yaml) to a **private file outside
the repo**. Set its SSH key, verified `known_hosts` and narrow `read_roots`.
Relative host file paths are resolved against the profile's directory.
4. Configure your client using [Claude Desktop / VS Code instructions](docs/clients.md).
The launcher command for Linux is:
```sh
/bin/sh /absolute/repo/scripts/launch-mcp.sh --profile /absolute/private/qemu.local.yaml
```
The server waits for MCP on stdin. It does not listen on a network port. With no
`--profile`, it uses the loopback QEMU defaults shown in the sample YAML. An
owner-selected YAML can point at another QNX 8.0 guest without code changes;
only the local x86_64 setup has been validated for this release.
## Tools
| Tool | Inputs | Evidence |
| --- | --- | --- |
| `system_info` | None | QNX release/machine, CPU and approximate memory from `uname` and `pidin info`; observed SFTP availability. |
| `list_processes` | Optional `pid`, executable substring `name`, thread `limit` | PID/TID, scheduling state, priority, and observed IPC peer/channel IDs. |
| `read_system_log` | Optional `buffer_set`, `pid`, `severity_max`, `since_epoch_ms`, `until_epoch_ms`, `limit` | Bounded `slog2info -f -s -t` snapshot, filtered locally. Lower severity numbers are more urgent. |
| `read_file` | Absolute `path`, optional byte `offset` and `max_bytes` | Bounded UTF-8 text from a regular file under an approved root. Follow `next_offset` for subsequent pages. |
Every successful response includes a target ID, observation time, status,
warnings and a truncation flag. `partial` means some evidence is unavailable or
clipped; a QNX query can return exit code zero and still have permission denials.
The parser uses the real-target-verified `%80B` width and does not invent a peer
TID when `pidin` gives only a PID. Cross-UID visibility is restricted, and the
process list is not an atomic or system-wide snapshot. [QNX pidin reference](https://www.qnx.com/developers/docs/8.0/com.qnx.doc.neutrino.utilities/topic/p/pidin.html)
## Reproduce the diagnosis
Follow the [deadlock demo](examples/deadlock_demo/README.md) to build and stage
the two programs manually. Read-only MCP calls show **A REPLY → B** and
**B SEND → A**, plus a normal RECEIVE thread on an unrelated channel. The
assistant can connect those observations to the callback-before-reply line in
the source. The developer reruns in `--fixed` mode to demonstrate that
reply-before-callback completes the request.
[Manual verification](docs/manual-testing.md) describes the tested QEMU path
and the separate SDK-free checks. [Demo storyboard](docs/demo.md) is a recording
script; no demo video is bundled.
## Safety
The server binds one trusted profile at startup. It accepts no arbitrary host,
shell command, target write, execution, delete or cloud action. It verifies SSH
host keys, uses a non-root account, bounds reads, checks path components and
writes a private audit log. Configure the client to ask before every call:
Claude Desktop needs **Manual** permission mode and VS Code needs the workspace
policy in [client setup](docs/clients.md). Annotations describe intent and do
not enforce consent. Target text can contain
prompt injection and must be treated as data. See [SECURITY.md](SECURITY.md) for
the trust boundary, path race limitation and planned hardening.
## Development
```sh
uv sync --locked
uv run --frozen ruff check .
uv run --frozen ruff format --check .
uv run --frozen pytest
uv build --wheel --no-sources
```
Public CI uses Linux and hand-written synthetic fixtures with a fake SSH/SFTP
backend. It does not use QNX, credentials or target captures. Real target
validation is a separate opt-in check. [PLAN.md](PLAN.md) tracks the later cloud
scenario; it is outside this release.
Original code is [MIT licensed](LICENSE). QNX software, images, SDK files,
vendor samples and target captures are not distributed. Obtain vendor
components under their own terms. The demo presents functional behavior.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo recent community issues