{
  "markdown": "# Constraint Registry\n\n<!-- mcp-name: io.github.SureshKhemka/constraints-registry -->\n\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\n[![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)](pyproject.toml)\n[![CI](https://github.com/SureshKhemka/constraints-registry/actions/workflows/ci.yml/badge.svg)](https://github.com/SureshKhemka/constraints-registry/actions/workflows/ci.yml)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)\n\n> **Policy-as-code guardrails for AI-generated code.** An **MCP server** that\n> serves engineering constraints to coding agents (Claude Code, Cursor, Codex) at\n> generation time and validates artifacts with **OPA, Conftest, Checkov, and\n> Semgrep**.\n\nA single, queryable source of engineering **constraints** (infrastructure,\norganizational, architectural) that coding agents (Claude Code, Cursor, Codex, …)\nconsult at code-generation time, exposed over an **MCP server**. It does **not**\nenforce constraints itself — it provides guidance to agents and delegates\ndeterministic validation to existing enforcement engines (**OPA**, **Conftest**,\n**Checkov**, **Semgrep**).\n\nConstraints are authored in source repos, aggregated into an immutable, versioned\n**bundle**, and served over MCP so an agent can:\n\n1. `describe_scope` — discover the valid selector vocabulary,\n2. `get_constraints` — fetch the rules relevant to what it's building, and\n3. `validate` — check a candidate artifact against the bound enforcement engines.\n\n> Authoritative requirements: `constraint-registry-v0-spec.md`.\n> Requirement → component → test mapping: `TRACEABILITY.md`.\n\n---\n\n## Contents\n- [Features](#features)\n- [Prerequisites](#prerequisites)\n- [Quick start](#quick-start)\n- [Running the MCP server](#running-the-mcp-server)\n- [Integrating with coding agents](#integrating-with-coding-agents)\n- [Authoring constraints](#authoring-constraints)\n- [Hot reload](#hot-reload-no-restart-on-constraint-changes)\n- [Validation harness](#validation-harness)\n- [Adding an enforcement engine](#adding-an-enforcement-engine)\n- [Repository layout](#repository-layout)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## Features\n\n- **Three constraint categories** — infrastructure, organizational, architectural,\n  including **relationship-style** selectors (e.g. \"no synchronous calls across\n  domain boundaries\") and **advisory** (no-enforcement) constraints.\n- **Multi-source aggregation** — import from many source repos; ids are namespaced\n  per source; deterministic, content-hashed, immutable **versioned bundles**.\n- **Precedence & anti-drift** — a configurable default policy (hard outranks\n  weaker; a downstream source may not relax a higher-precedence rule on the same\n  scope); fixture cross-checks keep guidance and enforcement from drifting.\n- **Pluggable engines** — a stable adapter interface with four real adapters:\n  **OPA** and **Conftest** (Rego policies), **Checkov** (IaC scanning), and\n  **Semgrep** (application source code). SARIF-emitting engines share one\n  normalization seam (`adapters/sarif/`), so adding a new SARIF engine is mostly\n  wiring. Adding an engine = one adapter + one config line (see\n  [Adding an enforcement engine](#adding-an-enforcement-engine)).\n- **Catalog importers** — Checkov and Semgrep ship importers that turn an engine's\n  rule catalog/ruleset into draft constraint **stubs** (with license/source\n  provenance) for a human to enrich — a fast path to bootstrapping a source.\n- **MCP server** — three tools (`describe_scope`, `get_constraints`, `validate`)\n  over **stdio** or a shared **HTTP** endpoint. `get_constraints` **fails open**\n  so an agent is never blocked.\n- **Hot reload** — the server can periodically re-import so constraint changes are\n  picked up **without a restart**.\n- **Validation harness** — proves the registry and constraint set are internally\n  consistent; machine-readable JSON, non-zero exit on failure.\n\n---\n\n## Prerequisites\n\n| Tool | Required? | Notes |\n|---|---|---|\n| **Python ≥ 3.11** | yes | the package targets 3.11+ |\n| **[uv](https://docs.astral.sh/uv/)** | yes | manages the venv and runs entry points |\n| **[OPA](https://www.openpolicyagent.org/docs/latest/#running-opa)** (`opa`) | for Rego `validate` / fixture cross-checks | the reference enforcement engine |\n| **[Conftest](https://www.conftest.dev/install/)** (`conftest`) | optional | second Rego engine; its checks SKIP if absent |\n| **[Checkov](https://www.checkov.io/2.Basics/Installing%20Checkov.html)** (`checkov`) | optional | IaC scanning engine; its checks SKIP if absent |\n| **[Semgrep](https://semgrep.dev/docs/getting-started/)** (`semgrep`) | bundled | source-code engine; installed automatically by `uv sync` |\n\nInstall the external engines on macOS:\n```bash\nbrew install opa conftest checkov   # semgrep is installed by `uv sync`\n```\nEach engine is **optional** and independent: any test or harness check whose\nengine binary is not on `PATH` is **skipped**, not failed. The registry and the\n`get_constraints`/`describe_scope` guidance work without any engine at all — an\nengine is only needed to run `validate` and the fixture cross-checks for\nconstraints bound to it.\n\n---\n\n## Quick start\n\n```bash\ngit clone https://github.com/SureshKhemka/constraints-registry.git\ncd constraints-registry\n\nuv sync                      # create the venv + install deps (incl. semgrep)\n\nuv run cregistry-harness     # run the validation harness against the bundled samples\n```\n\nThe harness emits machine-readable JSON and **exits non-zero on any failure**. A\ngreen run looks like:\n\n```json\n{ \"passed\": true, \"summary\": { \"pass\": 21, \"fail\": 0, \"skip\": 0, \"total\": 21 }, \"checks\": [ ... ] }\n```\n\n(`skip` is used only when an optional engine like `conftest` is not installed.)\n\n---\n\n## Running the MCP server\n\nTwo transports — pick based on how you want tools to connect.\n\n```bash\n# stdio (default): each tool launches its own copy; nothing to manage\nuv run cregistry-mcp\n\n# one shared HTTP server every tool connects to (recommended for multiple tools)\nuv run cregistry-mcp --http --port 8765 --reload-interval 60\n```\n\nFlags: `--transport {stdio,http,sse}`, `--http` (shorthand), `--host`\n(default `127.0.0.1`), `--port` (default `8765`), `--config`\n(or `$CREGISTRY_CONFIG`), `--reload-interval SECONDS` (`0` = off).\n\nManage the shared HTTP server:\n```bash\nlsof -ti tcp:8765 | xargs kill     # stop\n# restart = stop + start\n```\n\nFull operational guide (stop/restart, macOS launchd auto-start, the\nrepo-sync/decoupling pattern): **`docs/RUNNING.md`**.\nTool input/output contracts: **`docs/MCP_CONTRACT.md`**.\n\n---\n\n## Integrating with coding agents\n\nThe server exposes three tools: `describe_scope`, `get_constraints`, `validate`.\n\n### Claude Code\n\n```bash\n# shared HTTP server (start it first, see above), available in every project:\nclaude mcp add --scope user --transport http constraint-registry http://127.0.0.1:8765/mcp\n\n# OR stdio (no separate server to run; Claude launches it):\nclaude mcp add constraint-registry -- uv run --directory \"$(pwd)\" cregistry-mcp\n\nclaude mcp list   # should show: constraint-registry ... ✔ Connected\n```\n\n### Cursor (`~/.cursor/mcp.json`)\n\n```json\n{ \"mcpServers\": { \"constraint-registry\": { \"url\": \"http://127.0.0.1:8765/mcp\" } } }\n```\n\n### Codex / other stdio-only tools\n\nConfigure an MCP server with `command: uv`, `args: [\"run\",\"--directory\",\"/abs/path/to/repo\",\"cregistry-mcp\"]`.\n\n### Make the agent actually consult it\n\nAgents auto-discover the tools, but to get them to consult the registry *before*\ngenerating code, add an instruction to your project (or `~/.claude/CLAUDE.md`):\n\n> Before writing AWS/infra code, call the constraint-registry MCP: `describe_scope`\n> to learn valid selector values, then `get_constraints` with the right scope, and\n> comply with every `hard` constraint as a non-negotiable downstream gate.\n> Optionally `validate` the result.\n\n---\n\n## Authoring constraints\n\nA **source** is a directory with `constraints/*.yaml` (one constraint per file)\nand, optionally, `policies/` (engine policies) and `fixtures/` (sample artifacts).\nRegister sources and engines in `registry.config.yaml`:\n\n```yaml\nsources:\n  - { name: platform-security, path: sources/platform-security, precedence: 100 }\n  - { name: data-platform,     path: sources/data-platform,     precedence: 50  }\nengines:\n  - { name: opa,      adapter: \"cregistry.engine.adapters.opa:OpaAdapter\" }\n  - { name: conftest, adapter: \"cregistry.engine.adapters.conftest:ConftestAdapter\" }\n  - { name: checkov,  adapter: \"cregistry.engine.adapters.checkov:CheckovAdapter\", options: { min_level: warning } }\n  - { name: semgrep,  adapter: \"cregistry.engine.adapters.semgrep:SemgrepAdapter\", options: { min_level: warning } }\nprecedence_policy: default\n```\n\nA constraint (see `sources/platform-security/constraints/aws-s3-no-public-access.yaml`):\n\n```yaml\nid: aws.s3.no-public-access\ntitle: \"S3 buckets must not be publicly accessible\"\nintent: \"Public buckets are the top source of data-exposure incidents.\"\ncategory: infrastructure          # infrastructure | organizational | architectural\nscope:\n  providers: [aws]\n  resource_types: [aws_s3_bucket] # Terraform resource ids (NOT \"s3_bucket\")\n  environments: [all]\n  repos: [\"tag:data-plane\"]\nseverity: hard                    # hard | soft | advisory\nenforcement:                      # omit for an advisory (guidance-only) constraint\n  - { engine: opa, policy: policies/s3_public.rego }\nguidance:\n  do:   [\"Attach an aws_s3_bucket_public_access_block with all four flags true\"]\n  dont: [\"Never set acl = 'public-read' or 'public-read-write'\"]\n  example_compliant: |\n    {\"resources\": {\"aws_s3_bucket\": {\"data\": {\"acl\": \"private\", \"public_access_block\": true}}}}\nowner: platform-security\nversion: 1.0.0\nfixtures:                         # optional; cross-checked against the engine\n  pass: fixtures/s3_private.json\n  fail: fixtures/s3_public.json\n```\n\nScoping notes (matters when agents query):\n- `resource_types` use the target tooling's identifiers (Terraform: `aws_s3_bucket`).\n  Call `describe_scope` to discover the exact vocabulary present.\n- A query that **omits** a dimension matches broadly; a value that **contradicts**\n  a constraint's selector excludes it. Relationship-scoped constraints are only\n  returned for queries that supply a matching relationship.\n- After authoring, run `uv run cregistry-harness` to validate schema, precedence,\n  and fixtures.\n\n---\n\n## Hot reload (no restart on constraint changes)\n\nRun the server with `--reload-interval N` and it re-imports from disk every `N`\nseconds, publishing a new immutable bundle when content changes:\n\n```bash\nuv run cregistry-mcp --http --port 8765 --reload-interval 60\n```\n\n- No-op when nothing changed; previous bundle versions stay pinnable by id.\n- A failed re-import (e.g. an unresolvable precedence conflict) **keeps the\n  last-good bundle serving** and logs the reason — the server never goes dark.\n- The server reads from the configured source paths, so wire your teams'\n  constraint repos to sync/pull into those paths (a separate ops job, e.g. a cron\n  `git pull` or CI publish). Code/dependency changes still need a restart.\n\n---\n\n## Validation harness\n\n`uv run cregistry-harness` runs end-to-end against the bundled, self-contained\nsample sources and proves: schema conformance, deterministic import, malformed-\nconstraint isolation, namespacing & precedence, versioning & deprecation, engine-\ninterface conformance (incl. a reusable suite any adapter can be run against),\nfixture cross-checks / broken-binding detection, the MCP contract / scoping /\nfail-open, and hot-reload behavior. It prints structured JSON and returns a\nnon-zero exit on any failure — suitable for CI.\n\n```bash\nuv run cregistry-harness            # human-readable JSON to stdout, exit 0/1\nuv run cregistry-harness --config path/to/registry.config.yaml\n```\n\n---\n\n## Adding an enforcement engine\n\nImplement the `EngineAdapter` interface in a new module under\n`src/cregistry/engine/adapters/`, add one line under `engines:` in\n`registry.config.yaml`, and validate it against the existing conformance suite —\nno changes to the schema, importer, MCP server, or harness. Full walkthrough:\n**`docs/ADDING_AN_ENGINE.md`**.\n\n---\n\n## Repository layout\n\n```\nsrc/cregistry/\n  model.py            constraint schema (Pydantic)\n  loader.py           load + per-field schema validation\n  config.py           registry config (sources, engines)\n  importer.py         import → aggregate → bundle\n  precedence.py       namespacing precedence / conflict resolution\n  scope.py            scope matching (query + conflict)\n  bundle.py store.py  immutable versioned bundles + store\n  query.py validate.py  scoped queries + artifact validation\n  integrity.py        fixture cross-check / anti-drift\n  service.py          transport-independent service (+ hot reload)\n  mcp_server.py       MCP server (stdio / http) + CLI\n  engine/             stable engine interface, registry, and adapters:\n    adapters/opa, adapters/conftest, adapters/checkov, adapters/semgrep\n    adapters/sarif    shared SARIF normalization seam (used by checkov + semgrep)\n  harness/            the validation harness (checks/*)\nsources/              bundled sample source repos (constraints, policies, fixtures)\nscenarios/            self-contained fixtures for harness edge cases\ntests/                pytest suite: adapter conformance, fixtures, import, e2e\ndocs/                 RUNNING.md, MCP_CONTRACT.md, ADDING_AN_ENGINE.md\ndeploy/               launchd template for auto-starting the HTTP server\nCONTRACTS.md          the frozen engine-adapter seam new adapters code against\n```\n\nRun the adapter test suite directly with `uv run pytest`.\n\n---\n\n## Contributing\n\nContributions are very welcome — bug reports, new **engine adapters**, constraint\nsources, and docs. Adding an engine is intentionally small: one adapter module\nplus one config line, with no changes to the schema, importer, MCP server, or\nharness.\n\n- Read **[CONTRIBUTING.md](CONTRIBUTING.md)** for dev setup, conventions, and the\n  engine-adapter checklist.\n- Be a good neighbor — see the **[Code of Conduct](CODE_OF_CONDUCT.md)**.\n- Found a vulnerability? Report it privately per **[SECURITY.md](SECURITY.md)**.\n\nBefore opening a PR, make sure `uv run pytest` and `uv run cregistry-harness` are\ngreen; CI runs both on every pull request.\n\n---\n\n## License\n\nLicensed under the **[Apache License 2.0](LICENSE)**. See [NOTICE](NOTICE) for\nattribution and the licenses of the external engines this project integrates with.\n",
  "bytes": 14614,
  "sha": "940bb291ed89a2099811828fb27c30638784cd602767cf7bf28ae3da0efe4c7d",
  "repo_slug": "sureshkhemka/constraints-registry",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_sureshkhemka_constraints_regis_f8096e62/readme"
}