Skip to content
Arxo Arxo

Workflows

Arxo MCP tools are designed to chain together so an AI assistant can move from a quick health check to deep analysis to actionable refactoring suggestions — all within a single conversation. This page walks through practical workflows, explains when to use each one, and shows the expected inputs and outputs at every step.


When to use: Before committing or opening a pull request, run a fast cycle check to catch circular dependencies early.

Steps:

  1. The AI calls check_cycles:
check_cycles({ "project_path": "." })
  1. The server returns an SCC (Strongly Connected Components) summary:
{
"scc": {
"component_count": 175,
"cycle_count": 2,
"max_cycle_size": 5,
"total_nodes_in_cycles": 8
},
"violations_count": 1
}
  1. The AI interprets the result:
    • cycle_count — number of distinct circular dependency groups.
    • max_cycle_size — number of modules in the largest cycle. A value of 0 means no cycles.
    • total_nodes_in_cycles — total modules trapped in cycles.
    • If any cycles exist, the AI can warn the developer and suggest running a full analysis with analyze_architecture to identify which modules are involved.

What to do next: If max_cycle_size > 0, follow up with the hotspot and refactoring workflow to find specific edges to cut.


When to use: When the codebase makes calls to LLM providers (OpenAI, Anthropic, etc.) and you want to verify observability, security, and cost controls are in place.

Steps:

  1. The AI calls check_llm_integration:
check_llm_integration({ "project_path": "." })
  1. The server returns an integration health report:
{
"llm_integration": {
"health_score": 0.62,
"observability_gap": 3,
"pii_leakage_risk": 1,
"cost_tracking_gap": 2,
"prompt_hardcoding": 4,
"model_coupling": 1,
"fallback_absence": 2
},
"findings": [
{
"title": "Observability gap",
"severity": "warning",
"evidence_count": 3,
"description": "LLM calls without tracing or logging detected"
}
],
"violations_count": 2
}
  1. The AI interprets the result and suggests fixes:
    • Observability gap — Add tracing spans or structured logging around LLM calls.
    • PII leakage risk — Introduce PII redaction before sending user data to an LLM.
    • Cost tracking gap — Add token usage logging and budget alerts.
    • Prompt hardcoding — Move inline prompts to templates or a prompt registry.
    • Model coupling — Introduce an adapter layer so you can swap providers.
    • Fallback absence — Add timeout, retry, or fallback model configuration.

The health_score (0–1) gives an overall grade. A score below 0.5 warrants immediate attention.


When to use: Before modifying a core module, check its blast radius — how many other modules depend on it directly or transitively.

Steps:

  1. The AI calls analyze_file_impact with the files about to change:
analyze_file_impact({
"project_path": ".",
"file_paths": ["src/core/auth.ts", "src/core/session.ts"]
})
  1. The server returns metrics and affected context:
{
"results": [
{
"id": "scc",
"data": [
{ "key": "scc.cycle_count", "value": { "kind": "number", "v": 1 } },
{ "key": "scc.max_cycle_size", "value": { "kind": "number", "v": 3 } }
]
},
{
"id": "centrality",
"data": [
{ "key": "centrality.module.betweenness_max", "value": { "kind": "number", "v": 0.42 } }
]
}
],
"violations": [],
"changed_files_context": [
"src/core/auth.ts",
"src/core/session.ts"
]
}
  1. The AI interprets the result:
    • High centrality.module.betweenness_max means the file sits on many dependency paths — changes will ripple widely.
    • If cycles exist (scc.max_cycle_size > 0), the changed files may be inside a cycle, amplifying the blast radius.
    • The AI can recommend introducing a facade, extracting an interface, or breaking a dependency before making the change.

Tip: Run this workflow whenever you touch files in core/, shared/, or any module that appears frequently in import graphs.


When to use: To verify the codebase meets architectural standards defined in your arxo.yaml configuration, or to check an ad-hoc policy.

evaluate_policy({ "project_path": "." })

The server loads the policy.invariants section from your arxo.yaml and checks each invariant against the current metrics.

You can also pass policy rules directly, useful for one-off checks or experimentation:

evaluate_policy({
"project_path": ".",
"policy_yaml": "policy:\n invariants:\n - metric: scc.max_cycle_size\n op: '<='\n value: 0\n message: 'No circular dependencies allowed'\n - metric: propagation_cost.system.ratio\n op: '<='\n value: 0.10\n message: 'System propagation cost must stay under 10%'"
})
{
"violations": [
{
"metric": "scc.max_cycle_size",
"expected": 0,
"actual": 5,
"operator": "<="
}
],
"violations_count": 1,
"metrics_summary": [
{
"id": "scc",
"data": [
{ "key": "scc.max_cycle_size", "value": { "kind": "number", "v": 5 } }
]
},
{
"id": "propagation_cost",
"data": [
{ "key": "propagation_cost.system.ratio", "value": { "kind": "number", "v": 0.07 } }
]
}
]
}

What to do next: If violations exist, use get_hotspots to identify the worst offenders, then suggest_refactors for actionable steps.


When to use: To find the modules most in need of refactoring — those with high coupling, high churn, or high centrality — and get prioritized suggestions.

Steps:

  1. Identify hotspots:
get_hotspots({ "project_path": "." })

Response:

{
"hotspots": [
{
"metric": "centrality",
"title": "Hub module detected",
"severity": "warning",
"evidence_count": 3
},
{
"metric": "scc",
"title": "Circular dependency",
"severity": "error",
"evidence_count": 2
}
],
"findings_count": 5,
"violations_count": 2
}
  1. Optionally filter by metric type:
get_hotspots({ "project_path": ".", "metric_type": "centrality" })
  1. Get refactoring suggestions:
suggest_refactors({ "project_path": "." })

The response includes prioritized recommendations such as:

  • Break circular dependencies — identifies the lowest-weight edges to cut (e.g., barrel imports, type-only imports).
  • Split hub modules — suggests splitting modules with high fan-in + fan-out into smaller, cohesive units.
  • Fix layer violations — recommends dependency inversion or adapter patterns for upward-reaching imports.
  • Move misplaced modules — identifies modules with more connections to a neighboring community than their own.
  • Fix unstable dependencies — suggests extracting interfaces when stable modules depend on unstable ones.
  • Refactor high-churn hotspots — highlights modules that change frequently and are tightly coupled.

Each recommendation includes a priority (Critical / High / Medium), effort estimate (Low / Medium / High), and evidence (specific metric values and affected files).


When to use: For a comprehensive assessment of the entire codebase. Best run periodically (e.g., weekly) or before major releases.

Steps:

  1. Discover available presets:
list_presets()

Response:

[
{ "name": "quick", "description": "SCC, L1 overview, centrality" },
{ "name": "ci", "description": "SCC, smells, layer violations, architecture budgeting" },
{ "name": "risk", "description": "Ricci curvature, MSR, hotspot score, ownership, truck factor" },
{ "name": "coupling", "description": "Propagation cost, MSR co-change, coupling analysis, decoupling level" },
{ "name": "security", "description": "Security, sensitive data flow, effect violations" },
{ "name": "runtime", "description": "Cloud cost, traffic hotspot, critical path, runtime metrics" },
{ "name": "ai", "description": "LLM integration, ML/RAG/agent architecture" },
{ "name": "rag", "description": "RAG-specific health (retrieval, grounding, embedding drift)" },
{ "name": "full", "description": "All metrics" }
]
  1. Run the analysis with a preset:
analyze_architecture({
"project_path": ".",
"preset": "ci"
})
  1. Or run a full analysis:
analyze_architecture({
"project_path": ".",
"preset": "full"
})
  1. The response includes all computed metrics and any policy violations:
{
"results": [
{ "id": "scc", "data": [{ "key": "scc.cycle_count", "value": { "kind": "number", "v": 2 } }, { "key": "scc.max_cycle_size", "value": { "kind": "number", "v": 5 } }], "findings_count": 2 },
{ "id": "centrality", "data": [{ "key": "centrality.module.betweenness_max", "value": { "kind": "number", "v": 0.42 } }], "findings_count": 3 },
{ "id": "smells", "data": [{ "key": "smells.hubs.count", "value": { "kind": "number", "v": 1 } }, { "key": "smells.god_components.count", "value": { "kind": "number", "v": 0 } }], "findings_count": 1 }
],
"violations": [],
"violations_count": 0
}

Tip: Start with the quick preset for fast feedback (a few seconds), then escalate to ci, coupling, or full when deeper analysis is needed.


When to use: To compare current metrics against a previous state (e.g., main branch or a prior commit) and detect regressions.

analyze_with_baseline({
"project_path": ".",
"baseline_ref": "main"
})

The response shows the delta for each metric, making it easy to spot regressions:

{
"diff": [
{ "metric": "scc.max_cycle_size", "baseline": 3, "current": 5, "delta": 2 },
{ "metric": "propagation_cost.system.ratio", "baseline": 0.08, "current": 0.07, "delta": -0.01 }
],
"baseline_violations_count": 2,
"current_violations_count": 3
}

A positive delta in scc.max_cycle_size means cycles grew; a negative delta in propagation_cost.system.ratio means propagation cost improved.


A common production workflow chains several tools together to act as a CI quality gate:

1. check_cycles → fail if max_cycle_size > 0
2. evaluate_policy → fail if any violations exist
3. analyze_file_impact → warn if changed files have high centrality
4. get_hotspots → attach hotspot summary to the PR comment

The AI assistant can run these steps sequentially and produce a single summary report. For example:

Architecture Check — PASSED

  • Cycles: 0 (no circular dependencies)
  • Policy violations: 0
  • Changed files: src/api/handler.ts (betweenness: 0.12, low risk)
  • Hotspots: 2 findings (1 hub module, 1 high-churn file)

Or if the check fails:

Architecture Check — FAILED

  • Cycles: 2 groups detected (max size 5) — blocking
  • Policy violation: scc.max_cycle_size <= 0 not met
  • Recommendation: Run suggest_refactors to find edges to cut

MCP resources provide read-only access to cached analysis results. They are useful when an AI assistant wants to fetch metrics without triggering a new analysis run.

Resource URIUse case
metrics://current/<path>Retrieve the latest computed metrics without re-running analysis.
policy://violations/<path>Check current violation count for a quick pass/fail signal.
llm://risks/<path>Fetch LLM integration findings from the last analysis.
budget://status/<path>Read architecture budget health.

Resources return cached data from the most recent tool invocation. If no analysis has been run yet, the resource triggers one using the appropriate preset.


ScenarioRecommended presetSpeed
Pre-commit or quick sanity checkquickFast (seconds)
CI/CD pipeline gateciModerate
Evaluating refactoring riskriskModerate
Deep coupling auditcouplingSlower
Security and data flow reviewsecurityModerate
Runtime performance & cost analysisruntimeModerate
Auditing LLM/AI integrationsaiModerate
RAG-specific health checksragModerate
Full architecture reviewfullSlowest (all metrics)

Use list_presets to see the current preset definitions and the metrics each one includes.


  • Caching — Results are cached in memory with a configurable TTL (default 5 minutes) and a max entry limit. Repeated calls for the same project, preset, and config return cached results instantly. Use --cache-ttl and --max-cache-entries in Configuration to tune cache behavior.
  • Presets — Presets limit which metrics run. Use quick or check_cycles for sub-second feedback; use ci or coupling for targeted analysis; reserve full for periodic deep dives.
  • Incremental analysis — When file paths are provided (e.g., via analyze_file_impact), the engine only recomputes metrics affected by those files, further reducing analysis time.

The --log-level argument controls the MCP server log verbosity (e.g., --log-level debug). You can also set the RUST_LOG environment variable for fine-grained control (e.g., RUST_LOG=arxo_mcp=debug).

Logs are written to stderr so they never interfere with the JSON-RPC stream on stdout. In Cursor, open the MCP server logs panel and select the Arxo server to inspect tool execution, cache hits, and any errors.