.exe, .dll or .sys file
and answers the agent’s questions about it. It lists headers,
sections, imports, exports, strings, TLS callbacks and resources. It
disassembles x86 and x64 code, finds every instruction that refers to an
address, and tests byte signatures against the file. Every answer is
compact JSON, paged, and never larger than 24 KB, because it lands in a
model’s context window. It never opens a process, attaches a
debugger or writes a byte. It is the static half of
Pointer Lab’s MCP server: Pointer Lab
works on the running program, and pe-mcp reads the file first.
pe-mcp.exe in an x64 or x86 zip. Nothing else to install
A small scripted MCP client spoke to pe-mcp.exe over stdio,
the way Claude Code does, and asked three questions about a local build of
the tutorial that ships with Pointer Lab. This is real
output. The client printed one row per line, and the rows are as the
server sent them.
# server pe-mcp 1.0.0, 17 tools
> strings {"filter":"Health: %.3f"}
{
"total": 1,
"items": [
{"rva":"0x1B518","enc":"utf16","text":"Health: %.3f Ammo: %.4f"}
],
"next": null
}
> xrefs_to {"rva":"0x1B518"}
{
"target": "0x1B518",
"note": "L\"Health: %.3f Ammo: %.4f\"",
"total": 1,
"items": [
{"rva":"0x1B4B","kind":"rip","text":"lea r8, [0x14001B518]","function":"0x1B40"}
],
"next": null
}
> disassemble {"rva":"0x1B4B","function":true}
{
"function": {"begin":"0x1B40","end":"0x1B79"},
"items": [
{"rva":"0x1B40","bytes":"4883EC38","text":"sub rsp, 0x38"},
{"rva":"0x1B44","bytes":"488B057DC00200","text":"mov rax, [0x14002DBC8]","ref":"0x2DBC8"},
{"rva":"0x1B4B","bytes":"4C8D05C6990100","text":"lea r8, [0x14001B518]","ref":"0x1B518","note":"L\"Health: %.3f Ammo: %.4f\""},
{"rva":"0x1B52","bytes":"F30F1000","text":"movss xmm0, dword ptr [rax]"},
{"rva":"0x1B56","bytes":"488B0573C00200","text":"mov rax, [0x14002DBD0]","ref":"0x2DBD0"},
{"rva":"0x1B5D","bytes":"0F5AD8","text":"cvtps2pd xmm3, xmm0"},
{"rva":"0x1B60","bytes":"F20F1008","text":"movsd xmm1, qword ptr [rax]"},
{"rva":"0x1B64","bytes":"66490F7ED9","text":"movq r9, xmm3"},
{"rva":"0x1B69","bytes":"F20F114C2420","text":"movsd [rsp+0x20], xmm1"},
{"rva":"0x1B6F","bytes":"E83C1F0000","text":"call 0x140003AB0","ref":"0x3AB0"},
{"rva":"0x1B74","bytes":"4883C438","text":"add rsp, 0x38"},
{"rva":"0x1B78","bytes":"C3","text":"ret"}
],
"next": null
}
The string led to the one instruction that uses it, and that instruction named its function. The function reads the float health and the double ammo through the two globals in orange.
tools/list. For a running program, use Pointer Lab’s MCP server.total, items and next. Pass next back as cursor for the next page. No result is larger than 24 KB of JSON, whatever the limit.function: true uses .pdata to disassemble the whole function around an address.find_pattern is sigscan, so it reads x64dbg, IDA, code and mask, C++ array and aobscanmodule forms. It returns every match and the total, so a Signature Lab signature can be checked before the program runs.isError set and a sentence saying what was wrong. A misspelled argument name is refused with the names the tool takes. A corrupt file is refused with the reason, or read in part with warnings.pe-mcp-v1.0.0-windows-x64.zip and pe-mcp-v1.0.0-windows-x86.zip, each with pe-mcp.execlaude mcp addIntended use. pe-mcp is for studying software you own or are authorized to analyze: your own programs, single-player games, CTF binaries, and the lab targets from The Game Hacker’s Handbook. It reads files and changes nothing, but what you do with what it finds is your decision. Modifying software you do not have permission to modify may be illegal where you live. This is a research tool.
What it does not read. It does not load PDB symbols,
parse .NET metadata or disassemble ARM64 code, though the headers and
tables of an ARM64 file still read. Function bounds come from
.pdata, so they exist only on x64. Files are read whole into
memory, up to 1 GiB each and 16 at once.
Cross-references come from a linear sweep. Data inside a code section can hide the instruction after it. A call through a register or a computed address is not a reference it can see.
The binary is unsigned. pe-mcp only reads files, but build it from source if you would rather not take a binary on trust.