@memoryprocess/mcp 0.0.1 → 0.0.3-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/server.mjs +80 -13
  2. package/package.json +2 -2
package/dist/server.mjs CHANGED
@@ -16,7 +16,7 @@ import { MemoryProcessError, Process } from "@memoryprocess/core";
16
16
  *
17
17
  * Wire format follows docs/json-conventions.md:
18
18
  * - every result is `{ok:true,data} | {ok:false,error:{code,message,win32code?}}`
19
- * - bigints (addresses, pointers, 64-bit values) -> '0x…' strings
19
+ * - bigints (addresses, pointers, 64-bit values) -> '0x...' strings
20
20
  * - Buffers -> lowercase hex strings
21
21
  * - errors carry the typed `.code` from @memoryprocess/core when available
22
22
  */
@@ -57,8 +57,8 @@ function errorEnvelope(e) {
57
57
  };
58
58
  }
59
59
  /**
60
- * Parse an address argument: `0x…` hex string, decimal string, or
61
- * `"module+rva"` (resolved against the session's module table — the rva is
60
+ * Parse an address argument: `0x...` hex string, decimal string, or
61
+ * `"module+rva"` (resolved against the session's module table -- the rva is
62
62
  * optional). Returns the absolute address as bigint.
63
63
  */
64
64
  function parseAddress(proc, v, name = "addr") {
@@ -117,9 +117,9 @@ function parseNumeric(v, wide, name = "value") {
117
117
  }
118
118
  /** Agent-facing type aliases -> core WriteValueType/ScanValueType. */
119
119
  const NUMERIC_TYPES = {
120
- i8: "uint8",
120
+ i8: "int8",
121
121
  u8: "uint8",
122
- i16: "uint16",
122
+ i16: "int16",
123
123
  u16: "uint16",
124
124
  i32: "int32",
125
125
  u32: "uint32",
@@ -345,7 +345,7 @@ function parseHits(raw, type) {
345
345
  });
346
346
  }
347
347
  const sessionArg = { session: z.string().describe("session handle from proc_open") };
348
- const addrArg = z.union([z.string(), z.number()]).describe("address: \"0x…\" hex, decimal, or \"module+rva\"");
348
+ const addrArg = z.union([z.string(), z.number()]).describe("address: \"0x...\" hex, decimal, or \"module+rva\"");
349
349
  const typeArg = z.string().describe("i8 u8 i16 u16 i32 u32 i64 u64 f32 f64 ptr str wstr bytes[:N]");
350
350
  const toolDefs = {
351
351
  proc_list: {
@@ -401,7 +401,7 @@ const toolDefs = {
401
401
  }
402
402
  },
403
403
  mem_write: {
404
- description: "Write a typed value (journaled — reversible via mem_undo). dryRun:true returns {addr,current,would,bytes} WITHOUT writing.",
404
+ description: "Write a typed value (journaled -- reversible via mem_undo). dryRun:true returns {addr,current,would,bytes} WITHOUT writing.",
405
405
  schema: {
406
406
  ...sessionArg,
407
407
  addr: addrArg,
@@ -521,6 +521,62 @@ const toolDefs = {
521
521
  };
522
522
  }
523
523
  },
524
+ mem_scan_pattern: {
525
+ description: "AOB signature scan: find all matches of a byte pattern like \"48 8B ?? 10\" (\"??\" wildcards). Returns {hits:[hexaddr],count,truncated}.",
526
+ schema: {
527
+ ...sessionArg,
528
+ pattern: z.string().describe("byte pattern, hex bytes separated by spaces, \"??\" wildcards"),
529
+ module: z.string().optional().describe("restrict to a module"),
530
+ section: z.string().optional().describe("restrict to a PE section of `module` (e.g. \".text\")"),
531
+ start: addrArg.optional().describe("range start"),
532
+ end: addrArg.optional().describe("range end"),
533
+ onlyReadable: z.boolean().optional().describe("only scan readable regions (default true)"),
534
+ limit: z.number().int().positive().optional().describe("max hits returned (default 1000)")
535
+ },
536
+ handler: async (s, a) => {
537
+ const proc = s.get(a.session);
538
+ if (typeof a.pattern !== "string" || !a.pattern.trim()) throw fail("INVALID_ARGS", "mem_scan_pattern needs a pattern string");
539
+ const hits = await proc.scan(a.pattern, {
540
+ module: a.module,
541
+ section: a.section,
542
+ start: a.start !== void 0 ? parseAddress(proc, a.start, "start") : void 0,
543
+ end: a.end !== void 0 ? parseAddress(proc, a.end, "end") : void 0,
544
+ onlyReadable: a.onlyReadable
545
+ });
546
+ const limit = a.limit ?? 1e3;
547
+ return {
548
+ count: hits.length,
549
+ truncated: hits.length > limit,
550
+ hits: hits.slice(0, limit).map((h) => hex(h))
551
+ };
552
+ }
553
+ },
554
+ mem_regions: {
555
+ description: "VirtualQueryEx map of the target's memory regions: [{base,size,protect,state,type}] -- base/size are hex, protect/state/type are hex flag values. writableOnly/executableOnly filter on protection.",
556
+ schema: {
557
+ ...sessionArg,
558
+ writableOnly: z.boolean().optional().describe("only regions whose protection allows writes"),
559
+ executableOnly: z.boolean().optional().describe("only regions whose protection allows execution")
560
+ },
561
+ handler: (s, a) => {
562
+ const proc = s.get(a.session);
563
+ const WRITABLE = 204;
564
+ const EXECUTABLE = 240;
565
+ let regions = proc.regions();
566
+ if (a.writableOnly === true) regions = regions.filter((r) => (r.protection & WRITABLE) !== 0);
567
+ if (a.executableOnly === true) regions = regions.filter((r) => (r.protection & EXECUTABLE) !== 0);
568
+ return {
569
+ count: regions.length,
570
+ regions: regions.map((r) => ({
571
+ base: hex(r.baseAddress),
572
+ size: hex(r.size),
573
+ protect: hex(r.protection),
574
+ state: hex(4096),
575
+ type: hex(r.type)
576
+ }))
577
+ };
578
+ }
579
+ },
524
580
  mem_pointer_resolve: {
525
581
  description: "Resolve module+rva plus a pointer chain: base = module base + rva, then dereference each offset (CE \"module.exe+RVA, offsets\" style).",
526
582
  schema: {
@@ -609,8 +665,19 @@ const toolDefs = {
609
665
  const addr = parseAddress(proc, a.addr);
610
666
  const type = normType(a.type);
611
667
  if (type === "str" || type === "wstr" || type === "bytes") throw fail("INVALID_ARGS", `freeze needs a numeric type, got "${a.type}"`);
612
- const coreType = type === "int8" || type === "int16" ? type === "int8" ? "uint8" : "uint16" : type;
613
- const stop = proc.freeze(addr, coreType, parseNumeric(a.value, WIDE_TYPES.has(type)), a.ms ?? 50);
668
+ const ms = a.ms ?? 50;
669
+ let stop;
670
+ if (type === "int8" || type === "uint8" || type === "int16" || type === "uint16") {
671
+ const v = Number(parseNumeric(a.value, false));
672
+ const write = type === "int8" || type === "uint8" ? () => proc.writeUInt8(addr, v & 255) : () => proc.writeUInt16(addr, v & 65535);
673
+ const timer = setInterval(() => {
674
+ try {
675
+ write();
676
+ } catch {}
677
+ }, ms);
678
+ if (typeof timer.unref === "function") timer.unref();
679
+ stop = () => clearInterval(timer);
680
+ } else stop = proc.freeze(addr, type, parseNumeric(a.value, WIDE_TYPES.has(type)), ms);
614
681
  return { freezeId: s.addFreeze(a.session, stop) };
615
682
  }
616
683
  },
@@ -623,7 +690,7 @@ const toolDefs = {
623
690
  }
624
691
  },
625
692
  mem_undo: {
626
- description: "Revert the last n journaled writes (default 1), most-recent first — the self-correction primitive.",
693
+ description: "Revert the last n journaled writes (default 1), most-recent first -- the self-correction primitive.",
627
694
  schema: {
628
695
  ...sessionArg,
629
696
  n: z.number().int().positive().optional()
@@ -634,12 +701,12 @@ const toolDefs = {
634
701
  }
635
702
  },
636
703
  mem_journal: {
637
- description: "Snapshot of the write journal for this session: [{index,addr,bytes|null}] — bytes is the pre-write hex that undo() restores.",
704
+ description: "Snapshot of the write journal for this session: [{index,addr,bytes|null}] -- bytes is the pre-write hex that undo() restores.",
638
705
  schema: sessionArg,
639
706
  handler: (s, a) => s.get(a.session).writeLog
640
707
  },
641
708
  eval_js: {
642
- description: "Escape hatch: run JS with the bound Process in scope as `proc`. Code is wrapped in an async body — use `return` for a result, `await` is allowed.",
709
+ description: "Escape hatch: run JS with the bound Process in scope as `proc`. Code is wrapped in an async body -- use `return` for a result, `await` is allowed.",
643
710
  schema: {
644
711
  ...sessionArg,
645
712
  code: z.string().describe("JS body; `proc` is the open Process")
@@ -683,7 +750,7 @@ async function callTool(sessions, name, args, opts = {}) {
683
750
  }
684
751
  // src/server.ts
685
752
  /**
686
- * @memoryprocess/mcp — MCP server exposing the memoryprocess toolkit to
753
+ * @memoryprocess/mcp -- MCP server exposing the memoryprocess toolkit to
687
754
  * LLM agents over stdio (the primary agentic surface).
688
755
  *
689
756
  * Usage:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memoryprocess/mcp",
3
- "version": "0.0.1",
3
+ "version": "0.0.3-beta.1",
4
4
  "description": "MCP server exposing the memoryprocess toolkit to LLM agents — the primary agentic surface.",
5
5
  "type": "module",
6
6
  "packageManager": "bun@1.4.4",
@@ -45,7 +45,7 @@
45
45
  "agent"
46
46
  ],
47
47
  "dependencies": {
48
- "@memoryprocess/core": "0.0.1",
48
+ "@memoryprocess/core": "workspace:*",
49
49
  "@modelcontextprotocol/sdk": "^1.32.2",
50
50
  "zod": "^4.6.7"
51
51
  },