Skip to content

dart mcp

Juwon1405 edited this page Jun 15, 2026 · 8 revisions

dart-mcp — the typed surface

dart-mcp is the security boundary of the project. Everything else is convenience.

What it is

A custom MCP (Model Context Protocol) server, implemented in Python, that exposes the typed forensic function surface (native + SIFT Workstation adapters) to the agent. It runs over stdio and speaks JSON-RPC 2.0.

What it is NOT

It is not a wrapper that translates LLM intent into shell commands. There is no execute_shell. There is no query_evidence(sql). There is no escape hatch.

The the typed MCP surface

Grouped by category:

Windows execution & traces (4)

  • get_amcache(hive_path) — AmCache.hve enumeration
  • parse_prefetch(prefetch_path) — Prefetch artifact parser
  • parse_shimcache(system_hive) — Application Compatibility cache
  • get_process_tree(process_csv) — process tree from snapshot

Windows user activity (3)

  • analyze_usb_history(system_hive, setupapi_log)
  • parse_shellbags(ntuser_hive) — shellbags reader
  • extract_mft_timeline(mft_path, start, end) — MFT $SI vs $FN

Windows system state (3)

  • list_scheduled_tasks()
  • detect_persistence() — registry/service/scheduled-task aggregation
  • analyze_event_logs(events_json)

macOS (3)

  • parse_unified_log(unifiedlog_json)
  • parse_knowledgec(knowledgec_db) — KnowledgeC.db reader
  • parse_fsevents(fsevents_csv) — FSEvents CSV reader

Browser & exfiltration (4)

  • parse_browser_history(history_db)
  • analyze_downloads(downloads_source) — MOTW handling
  • correlate_download_to_execution(downloads, executions)
  • detect_exfiltration()

Authentication & lateral movement (5)

  • analyze_windows_logons(security_events_json)
  • detect_lateral_movement() — PsExec, WMIExec
  • analyze_kerberos_events(security_events_json) — Kerberoasting / AS-REP roasting
  • analyze_unix_auth(auth_log_path)
  • detect_privilege_escalation()

Web/WAS + RDP brute (3)

  • analyze_web_access_log(access_log) — 16 attack patterns
  • detect_webshell(webroot) — 3 high-confidence indicators, 0 FP target
  • detect_brute_force_rdp(security_events_json) — credential stuffing vs spray vs single-account

MITRE gap fillers (4)

  • detect_credential_access() — T1003 (Mimikatz, SAM, NTDS, comsvcs.dll LOLBin)
  • detect_ransomware_behavior() — T1486/T1489/T1490
  • detect_defense_evasion() — T1070 (event log clearing, timestomp, MFT $SI vs $FN)
  • detect_discovery() — T1033/T1057/T1082/T1016/T1018/T1049/T1069/T1087/T1482

Cross-artifact (2)

  • correlate_events(hypothesis_id) — delegate to dart-corr
  • correlate_timeline(events) — DuckDB join

The schema

Every function has a JSON schema declared in dart_mcp/src/dart_mcp/__init__.py. The schema is enforced at the MCP layer:

  • Required arguments are required. Missing them raises InvalidArguments.
  • Argument types are validated. Passing a string where the schema requires an integer raises before the handler is called.
  • Path arguments go through _safe_resolve, which:
    • Refuses ..
    • Refuses absolute paths outside EVIDENCE_ROOT
    • Refuses paths containing NUL bytes
    • Returns the resolved absolute path inside EVIDENCE_ROOT if and only if the resolution stayed inside the read-only mount

The bypass tests

tests/test_mcp_bypass.py asserts that:

Attack Expected result
Call an unregistered function (execute_shell, eval, etc.) ToolNotFound
Pass .. in a path argument rejected by _safe_resolve
Pass an absolute path outside EVIDENCE_ROOT rejected
Pass a NUL-byte-truncated path rejected
Surface drift — function appears that wasn't declared test fails
Handler attempts to write outside EVIDENCE_ROOT filesystem refuses (read-only mount)

All 6 tests pass on main. Any change that breaks one is a release blocker.

Pagination

Every function returns cursor-paginated JSON. There is no "return everything" mode. This is for context-window safety: a 5M-row MFT export does not fit in any current LLM context window. The agent receives a page, decides if it needs more, and explicitly requests the next page.

Audit side-tap

Every call into dart-mcp is side-tapped into dart-audit. There is no path to call the MCP layer that does not produce an audit entry. This is enforced by the dispatch table itself, not by convention.

Adding a function

The contribution checklist for adding a new function is in Contributing. The short version:

  1. Read-only by construction (no write paths in the implementation)
  2. Use _safe_resolve for any path argument
  3. Pydantic / JSON schema declared
  4. Cursor-paginated output
  5. Bypass test added (call an unregistered variant — must ToolNotFound)
  6. Test evidence added under each case's evidence_root/
  7. README and accuracy-report updated

PRs that miss any of these will be sent back.


← Back to Home

Agentic-DART

Concepts

The 5 packages

Reference

Running it

Case studies

Project


Project links

Clone this wiki locally