
Volatility 3 plugin that carves MCP/JSON-RPC message candidates from Windows and Linux memory dumps, preserving raw bytes, addresses, and SHA-256 for verification.
MCPTrace is a Volatility 3 plugin for extracting MCP/JSON-RPC message candidates from Windows and Linux memory dumps. It examines process memory for requests, responses, notifications, tool names, and call arguments, then records the recovered content together with its location in memory.
The project focuses on evidence that an analyst can inspect and verify. Each artifact retains its original bytes, process ID, virtual address, encoding, length, and SHA-256 hash. Results can be exported as JSONL for further analysis or comparison with other logs. MCPTrace operates on an acquired memory image and does not require an LLM or an external AI API.
tools/call names and arguments.The current analysis targets are Windows x64 and Linux x86-64. The plugin name refers to the operating system in the memory image, independently of the OS used to run Volatility.
MCPTrace uses Volatility's process enumeration and address translation. On Windows, it walks process Virtual Address Descriptors (VADs); on Linux, it walks Virtual Memory Areas (VMAs). These mappings define which process address ranges are examined. The two adapters share the same message-carving, correlation, policy, and export code.
Within readable ranges, the scanner searches for literal JSON-RPC version markers and locates candidate JSON objects around them. It handles nested objects, escaped characters, braces inside strings, and messages spanning contiguous read chunks. JSON with duplicate keys or unsupported identifiers is rejected rather than silently reinterpreted. MCP relevance is determined from known method names, response shapes, and associated request IDs; it is not full MCP schema validation.
Missing memory is kept missing. The reader does not fill gaps with zeroes or join
bytes across separate VADs/VMAs. With --include-partial, unparsed fragments can be
shown separately, without inventing missing IDs or arguments. Large unmapped ranges
can be skipped using page-table information, and unreadable address ranges remain
visible in the scan statistics.
Correlation is deliberately conservative. A numeric ID such as 1 is distinct from
the string ID "1", and messages in different processes are not automatically linked.
Multiple distinct representations associated with an ID are marked as ambiguous.
Candidate relationships do not reconstruct a session, message direction, or execution
timeline on their own.
Requires Python 3.10+. Installation includes the pinned framework dependency,
volatility3==2.28.2. Keep the repository's plugins/ directory available: the Python
package is installed with pip, while -p plugins loads the Volatility adapters.
git clone https://github.com/Kowntaewook/MCPTrace.git
cd MCPTrace
python -m venv .venv
Activate the environment for your shell:
.\.venv\Scripts\Activate.ps1source .venv/bin/activateThen install MCPTrace:
python -m pip install .
Run the following examples from the repository root with the virtual environment active. Replace the image paths and PIDs with your evidence and target processes. MCP clients and servers may run in separate processes, so inspect both where relevant.
Windows
Check that Volatility can interpret the image and enumerate its processes before running MCPTrace. Windows symbol preparation may require network access.
vol -f windows.raw windows.info.Info
vol -f windows.raw windows.pslist.PsList
mkdir output-windows
vol -p plugins -f windows.raw -o output-windows windows.mcptrace.MCPTrace --pid 4242 5252 --dump
Linux
Place ISF symbols matching the dump's exact kernel build in symbols/linux/.
If linux.pslist.PsList cannot resolve its kernel or layer requirements, resolve
the image/symbol setup before interpreting MCPTrace output.
vol -s symbols -f linux.lime linux.pslist.PsList
mkdir output-linux
vol -p plugins -s symbols -f linux.lime -o output-linux linux.mcptrace.MCPTrace --pid 4242 --dump
--pid to scan all processes, or pass multiple PIDs: --pid 4242 5252.--dump exports per-process JSONL files to the directory specified by -o.vol -p plugins windows.mcptrace.MCPTrace -h (or the Linux equivalent) for all options.For a JSON rendering of the full result table, put the global -r json option before
the plugin name. This is separate from the per-process JSONL exports produced by --dump.
vol -p plugins -f windows.raw -r json windows.mcptrace.MCPTrace --pid 4242 > findings.json
| Option | Purpose |
|---|---|
--pid 4242 5252 | Select process IDs; omit to examine all processes enumerated by the adapter. |
--dump | Export displayed artifacts and scan summaries as JSONL using the global -o directory. |
--include-partial | Include raw, unparsed fragments without reconstructing missing fields. |
--include-rpc | Also display generic JSON-RPC candidates without confirmed MCP relevance. |
--policy PATH | Apply local rules to tool arguments; see the Windows and Linux examples. |
--suspicious-only | Show policy matches and summaries; requires a nonempty policy. |
--max-records N | Bound candidate records per process before filtering; default: 10000. |
--max-object-bytes N | Bound the size of one complete JSON object; default: 65536 bytes. |
--max-bytes N | Bound attempted address-range bytes per process; 0 means unlimited. |
Policy findings describe matches against the rules supplied by the analyst. A match does not establish malicious activity. Review the example paths, hosts, and tool names before applying them to a different case.
A file such as mcptrace.pid-4242.jsonl contains a metadata record, artifact records,
and a final scan summary. The metadata identifies the process, target OS, and address
space. Artifact records preserve both the parsed message and the exact recovered bytes.
| Fields | Meaning |
|---|---|
pid, virtual_address, region_start | Process and location of the evidence. Addresses are process virtual addresses, not image file offsets. |
message, method, tool, request_id | Parsed message content and selected fields, when available. |
raw_base64, byte_length, raw_sha256 | Original bytes, their length, and SHA-256 for verification. |
state, encoding | Whether the record is complete or a fragment, and how its bytes are encoded. |
relation, candidate_virtual_addresses | Candidate counterpart locations and whether the relationship is ambiguous. |
findings | Results of optional argument-policy checks. |
To verify an artifact, decode raw_base64, check its length and hash, and re-read
that range through the corresponding process memory layer. Reformatting message
as JSON may change whitespace or escaping, so use the preserved bytes for an exact
comparison. Different memory copies remain separate evidence records.