Skip to main content
Glama
OxManifesto

ArchVanguard-MCP

by OxManifesto
README.md
<!--
GitHub topics: ai-agent llm-tools mcp langchain openai-function-calling pydantic
architecture static-analysis import-linter dependency-graph code-quality
-->

# ArchVanguard-MCP

Framework-agnostic architecture-rule enforcement for AI agents: analyze a Python codebase's import graph against a declarative ruleset and report layer, forbidden-import, and cycle violations with file and line.

[![CI](https://github.com/MrGuevara4/ArchVanguard-MCP/actions/workflows/ci.yml/badge.svg)](https://github.com/MrGuevara4/ArchVanguard-MCP/actions/workflows/ci.yml)
[![Coverage](https://img.shields.io/badge/coverage-95%25-brightgreen)](https://github.com/MrGuevara4/ArchVanguard-MCP)
[![PyPI](https://img.shields.io/pypi/v/archvanguard-mcp)](https://pypi.org/project/archvanguard-mcp/)
[![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
[![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000)](https://github.com/astral-sh/ruff)
[![Downloads](https://img.shields.io/pypi/dm/archvanguard-mcp)](https://pypi.org/project/archvanguard-mcp/)

## Abstract

Autonomous coding agents refactor, generate, and merge code faster than humans can review architecture. ArchVanguard-MCP gives an agent (or a CI job) one deterministic question: *does this codebase obey its declared architecture?* It parses a Python package's imports with the standard-library `ast` module — **never executing the target code** — builds the module dependency graph, and evaluates a declarative ruleset for layer-dependency violations, forbidden imports, and import cycles, returning each finding with a precise file and line. The core is a pure, framework-free Python library wrapped by thin optional adapters for OpenAI, Anthropic, LangChain, LlamaIndex, an MCP stdio server, and a CLI, so the same engine binds to any agent stack without conditionals.

## Feature matrix

| Framework | Status | Extra | Entry point |
|-----------|--------|-------|-------------|
| Core library (sync + async) | ✅ | *(none)* | `archvanguard_mcp.core.execute` |
| OpenAI function-calling | ✅ | `openai` | `adapters.openai_tool.tool_spec` / `run_tool_call` |
| Anthropic tool-use | ✅ | `anthropic` | `adapters.anthropic_tool.tool_spec` / `handle_tool_use` |
| LangChain | ✅ | `langchain` | `adapters.langchain_tool.build_tool` |
| LlamaIndex | ✅ | `llamaindex` | `adapters.llamaindex_tool.build_tool` |
| MCP (stdio, JSON-RPC 2.0) | ✅ | *(none; stdlib)* | `python -m archvanguard_mcp.adapters.mcp_server` |
| CLI | ✅ | *(none)* | `archvanguard` |

## Architecture

```mermaid
flowchart TD
    A[AI Agent / CI / Human] -->|tool call| S[Generated Tool Schema]
    S --> AD[Adapter layer<br/>openai · anthropic · langchain · llamaindex · mcp · cli]
    AD -->|typed args| V[Validation & sanitization<br/>paths · limits · rules]
    V -->|invalid| E[Structured error envelope<br/>stable code + details]
    V -->|valid| C[Core engine<br/>ast parse → graph → rule eval]
    C --> R[Response envelope<br/>violations + summary]
    C -->|failure| E
    E --> AD
    R --> AD
    AD --> A
```

The core (`archvanguard_mcp.core`) imports no AI framework. Framework code lives only in adapters, behind optional extras that fail with a clear, actionable error if not installed.

## Quickstart

```bash
# 1. Install
pip install archvanguard-mcp

# 2. Write a ruleset (rules.json)
cat > rules.json <<'JSON'
{
  "layers": [
    {"name": "core", "patterns": ["myapp.core", "myapp.core.*"]},
    {"name": "adapters", "patterns": ["myapp.adapters", "myapp.adapters.*"]}
  ],
  "allowed_dependencies": [{"from_layer": "adapters", "to_layer": "core"}],
  "forbidden_imports": [{"importer": "myapp.core.*", "forbidden": "langchain*"}],
  "allow_cycles": false
}
JSON

# 3. Enforce (exit code 1 if any violation — use it as a merge gate)
archvanguard --root ./src/myapp --rules rules.json
```

## Framework integration

### OpenAI (native function-calling)

```python
from openai import OpenAI
from archvanguard_mcp.adapters import openai_tool

client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Check ./src/myapp against rules.json"}],
    tools=[openai_tool.tool_spec()],
)
for call in response.choices[0].message.tool_calls or []:
    tool_message = openai_tool.run_tool_call(call)  # dispatches to the engine
    # append tool_message to your messages and continue the loop
```

### Anthropic (native tool-use)

```python
import anthropic
from archvanguard_mcp.adapters import anthropic_tool

client = anthropic.Anthropic()
message = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    tools=[anthropic_tool.tool_spec()],
    messages=[{"role": "user", "content": "Verify the layering of ./src/myapp"}],
)
for block in message.content:
    if block.type == "tool_use":
        tool_result = anthropic_tool.handle_tool_use(block)  # -> tool_result block
```

### LangChain

```python
from archvanguard_mcp.adapters import langchain_tool

tool = langchain_tool.build_tool()  # a StructuredTool with args_schema
# agent = create_react_agent(llm, [tool]) ; agent.invoke(...)
```

### LlamaIndex

```python
from archvanguard_mcp.adapters import llamaindex_tool

tool = llamaindex_tool.build_tool()  # a FunctionTool
# agent = ReActAgent.from_tools([tool], llm=llm) ; agent.chat(...)
```

### MCP server

Run `python -m archvanguard_mcp.adapters.mcp_server`, and register it in your MCP
client (`claude_desktop_config.json` or `mcp.json`):

```json
{
  "mcpServers": {
    "archvanguard": {
      "command": "python",
      "args": ["-m", "archvanguard_mcp.adapters.mcp_server"]
    }
  }
}
```

## API reference

Tool name: **`enforce_architecture`**. Full field tables are in
[`docs/SCHEMA.md`](docs/SCHEMA.md); the machine schemas are generated into
[`schemas/`](schemas/).

| Input field | Type | Required | Notes |
|-------------|------|----------|-------|
| `root_path` | string | yes | Existing directory to scan. |
| `language` | `"python"` | no | Only Python is supported. |
| `rules` | object | no | `layers`, `allowed_dependencies`, `forbidden_imports`, `allow_cycles`. |
| `include` / `exclude` | string[] | no | Module-name globs. |
| `strict_parse` | bool | no | Abort on first unparseable file. |
| `config` | object | no | Hard-bounded `max_files`, `max_file_bytes`, `wall_clock_ms`, `max_dir_depth`, `parallel`. |

The response contains `status`, `correlation_id`, `violations[]` (`rule_type`,
`file`, `line`, `from_module`, `to_module`, `message`), a `summary`, and an
`error` envelope when `status == "error"`.

## Error codes

| Code | Meaning | Retryable | Remediation |
|------|---------|-----------|-------------|
| `VALIDATION_ERROR` | Arguments failed schema/semantic validation | no | Fix the request per `details`. |
| `PATH_NOT_FOUND` | `root_path` does not exist | no | Provide an existing directory. |
| `PATH_NOT_ALLOWED` | Not a directory, or symlink/traversal escape | no | Point at a real directory inside the tree. |
| `LIMIT_EXCEEDED` | A hard cap (files, size, patterns, concurrency) was hit | no | Narrow scope or lower the workload. |
| `PARSE_ERROR` | A file failed to parse (only fatal with `strict_parse`) | no | Fix the file or disable `strict_parse`. |
| `TIMEOUT` | Wall-clock budget exceeded | yes | Raise `wall_clock_ms` (≤30000) or narrow scope. |
| `DEPENDENCY_MISSING` | An adapter extra is not installed | no | `pip install "archvanguard-mcp[<extra>]"`. |
| `INTERNAL_ERROR` | Unexpected fault (details redacted) | yes | Retry; report if persistent. |

## Performance

Measured on 16 cores, Linux, Python 3.13 (see [`docs/BENCHMARKS.md`](docs/BENCHMARKS.md);
reproduce with `python scripts/benchmark.py`):

| Modules | p50 | p95 |
|--------:|----:|----:|
| 250 | 18.5 ms | 19.6 ms |
| 1000 | 125 ms | 132 ms |
| 3000 | 374 ms | 390 ms |
| 4500 | 547 ms | 565 ms |

p95 stays under the 2000 ms budget across the full supported range (up to the
5000-file hard cap).

## Security

The analyzer never executes target code, rejects path traversal and symlink
escape, enforces hard resource caps, and accepts only `fnmatch` globs (no raw
regex, so no ReDoS surface). See [`docs/THREAT_MODEL.md`](docs/THREAT_MODEL.md).
Report vulnerabilities privately per [`SECURITY.md`](SECURITY.md) — acknowledgement
within 3 business days.

## Contributing

See [`CONTRIBUTING.md`](CONTRIBUTING.md). Dev setup:

```bash
pip install -e ".[all,dev]" && pre-commit install
make all   # lint + type + coverage(≥90%) + schema + security + build
```

Commits follow [Conventional Commits](https://www.conventionalcommits.org/). The
core must stay framework-free (INV-1); schemas are generated, never hand-edited.

## Roadmap

- [ ] Additional target languages (JavaScript/TypeScript, Go) behind the `language` enum.
- [ ] Allowlist for statically resolvable dynamic imports.
- [ ] Optional per-rule severity and baseline/ratchet mode for legacy repos.
- [ ] SARIF output for code-scanning integration.

## Citation

```bibtex
@software{fatih_archvanguard_mcp_2026,
  author  = {Farhang Fatih},
  title   = {ArchVanguard-MCP: Framework-agnostic architecture-rule enforcement for AI agents},
  year    = {2026},
  version = {0.1.0},
  license = {MIT},
  url     = {https://github.com/MrGuevara4/ArchVanguard-MCP}
}
```

## License

MIT © Farhang Fatih. See [`LICENSE`](LICENSE).

---

Author & Principal Architect: **Farhang Fatih**