Skip to main content

Code Property Graph MCP server for DayZ Enforce Script

Project description

enforce-cpg — Code Property Graph for Enforce Script

enforce-cpg

A Code Property Graph (CPG) MCP server for DayZ Enforce Script and BI config (config.cpp/config.bin, e.g. cfgVehicles, cfgWeapons).

It parses Enforce Script (.c) source and config documents across a vanilla/base layer and any number of mod layers, builds a graph of declarations, inheritance, overrides, and calls, and exposes that graph over the Model Context Protocol so an AI coding assistant (e.g. Claude Code) can answer real DayZ-modding questions: "what overrides Speak on Animal?", "who calls this method?", "what's the effective attachments[] on Plot after every mod's layered +=/=?", "what breaks if I change this field?" — across a real, multi-mod, load-order-dependent codebase, without ever crashing on a bad file, a corrupt PBO, or an unresolved reference.

Config ingestion. Both loose config.cpp (text) and config.bin (BI's rapified binary form) are discovered — as standalone files under a source root, or embedded inside any *.pbo, in either combination — and folded into the same graph as script declarations. A corrupt PBO, an unsupported/malformed rapified config.bin, or a syntactically broken config.cpp is recorded as a diagnostic and skipped; it never aborts the rest of the index run (see doctor below).

Install

pip install enforce-cpg        # or: uvx enforce-cpg --version

No compiler needed — the Enforce grammar ships as prebuilt wheels (tree-sitter-enforce).

Or, from a local checkout:

uv sync
uv run enforce-cpg --version

Configure

Point enforce-cpg at your vanilla scripts and mod source trees with an enforce-cpg.toml file (see enforce-cpg.example.toml):

[project]
name = "my-server"
db_path = ".enforce-cpg/index.db"

# ORDERED: earlier = loaded first = base precedence. This IS your -mod= order.
[[sources]]
name = "vanilla"
kind = "core"
path = "/path/to/vanilla_scripts"

[[sources]]
name = "MyMod"
kind = "mod"
path = "/path/to/MyMod/Scripts"

Load-order warning: the order of [[sources]] in this file is the override precedence used to resolve Animal.Speak-style method stacks — it must mirror your server's real -mod= load order. A source listed earlier is treated as the base that later sources override; get this wrong and resolve_method / get_inheritance will report the wrong override winner.

Build (or rebuild) the index:

uv run enforce-cpg index --config enforce-cpg.toml --full

Optional: pulling PBOs from a live game host over SFTP

pip install enforce-cpg[remote] (or uv sync --extra remote) pulls in paramiko and unlocks a kind = "sftp" source, e.g.:

[[sources]]
name = "live-server"
kind = "sftp"
path = "/mpmissions"
host = "game.example.com"
port = 22
username = "svc"
# either password or key_filename:
password = "..."
# key_filename = "/path/to/key"

enforce_cpg.remote gives sequential, single-retry list_pbos/fetch_pbo helpers built specifically for a live DayZ server's SFTP endpoint (never fanned out — a game server's SFTP side channel does not tolerate concurrent requests).

Honest gap: as of this release, kind="sftp" is not yet wired into indexingdiscover/discover_configs never consult a source's kind, so a configured sftp source currently contributes 0 files and 0 configs. doctor warns about this explicitly for any sftp source in your config, so it never fails silently. Actually pulling PBOs from the source over SFTP and indexing them still requires wiring enforce_cpg.remote into discovery — not done yet.

Tools

Once registered with an MCP client, enforce-cpg exposes 14 tools:

Tool Description
reindex Rebuild the code property graph index (script and config). full=true forces a from-scratch rebuild; otherwise only changed files are re-indexed (config documents are always re-processed).
find_symbol Find declarations of a symbol by name (optionally filtered by kind).
find_references Find references to a symbol by name (optionally filtered by kind; declaration sites excluded by default).
find_callers Find callers of a class method, transitively up to the given depth.
resolve_method Resolve a script method call to its override stack across the source layers (core -> mods), in resolution order, flagging cut chains.
get_inheritance Get the inheritance chain for a class, optionally scoped to a method.
impact_of_change Estimate the blast radius of changing a class member.
get_overview Get a structural overview of a file or a class.
audit_overrides Corpus-wide script method override audit: every modded layer that overrides without super, silently disabling earlier layers. Script only — says nothing about config; use audit_configs for that.
resolve_config Resolve a config class+property (e.g. a cfgVehicles/cfgWeapons entry) to its effective runtime value by folding every source layer in load order — config's analogue of resolve_method. Returns the fold chain, the final value, and class_found (false only if the class itself was never declared anywhere — distinguishes a typo'd class name from a property that's genuinely never set).
audit_configs Corpus-wide config clobber audit: every place a later layer's = silently discards one or more earlier layers of the same class's own property. Each finding is labeled discards_append (a discarded layer was a += — an array silently thrown away, the headline case) and value_changed (false = a verbatim redeclaration, i.e. layer noise, not damage). On a real corpus most findings are value_changed=false; prioritize discards_append=true / value_changed=true.
mod_surface Every method a given source overrides that another source also defines — the mod's footprint on the shared hierarchy.
doctor Setup + index-health report: sources resolved, per-source script and config parse coverage (cfg_cpp/cfg_bin/cfg_parse_ok/cfg_bin_skipped/pbos_opened), missing-vanilla warning, config-specific warnings (scripts present but 0 configs indexed; a config.bin skipped as unrapifiable/unsupported version, named; any PBO under a source that couldn't be opened, even if others in the same source opened fine; a kind="sftp" source, which isn't wired into indexing yet), diagnostics, unresolved hotspots.
ingest Register a source from an extracted directory (always) or a .pbo (de-rapified if a tool is available), copied under .enforce-cpg/sources/ with the [[sources]] entry added.

The CLI (enforce-cpg <subcommand>) covers only part of this surface — index/reindex, find-symbol, overview (get_overview), audit (audit_overrides only — script overrides, not audit_configs), mod-surface --source <name>, doctor, and ingest <path> --name <n> --kind core|mod. find_references, find_callers, resolve_method, get_inheritance, impact_of_change, resolve_config, and audit_configs — including both of this project's config-analysis tools — have no CLI command and are reachable only through an MCP client (e.g. Claude Code) or by importing enforce_cpg.query directly in Python.

Every tool degrades honestly instead of crashing: an unresolved symbol or a missing argument returns {"results": [], "note": "..."} rather than an exception, so a single bad query never takes down the server.

Register with Claude Code

claude mcp add enforce-cpg -- uvx --from enforce-cpg enforce-cpg-mcp

The server reads its config from the ENFORCE_CPG_CONFIG environment variable (defaults to enforce-cpg.toml in the working directory), so set that to your project's config path when registering.

License

enforce-cpg is licensed under the Attribution Assurance License (AAL), an OSI-approved open-source license. The full license text is in LICENSE; the required attribution notice is in NOTICE.

Attribution notice (must be displayed per the AAL's attribution clause):

enforce-cpg — © 2026 tommyz4 — https://github.com/tommyz4/enforce-cpg

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

enforce_cpg-0.3.0.tar.gz (329.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

enforce_cpg-0.3.0-py3-none-any.whl (70.0 kB view details)

Uploaded Python 3

File details

Details for the file enforce_cpg-0.3.0.tar.gz.

File metadata

  • Download URL: enforce_cpg-0.3.0.tar.gz
  • Upload date:
  • Size: 329.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for enforce_cpg-0.3.0.tar.gz
Algorithm Hash digest
SHA256 fc8a631f949eae6c2c9648af5b0e367003fb9baf80b648f240c941bd0019512f
MD5 4f27488e03f1cbe291e1d32780e6b253
BLAKE2b-256 2c7317d0d56eb558c75928008437ed9d2faee9d45bd292f43d50472a7c89c624

See more details on using hashes here.

File details

Details for the file enforce_cpg-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: enforce_cpg-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 70.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for enforce_cpg-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 51fb55539bae4c3a4536699e194a41e69f330399da805c15fe3d9e95d4fa15ce
MD5 a259e80d7a5acdc974d2fa781e2598d7
BLAKE2b-256 45ea805b9643d97fc2718237f7198237f7bfdf58791efc3ec619d5a7339bc3e1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page