Using MCP servers can make your AI agents intelligent and more rooted in the context of the task. This ensures that the LLM model gets right context about your task so that it can produce results specific to your goals.

In this comprehensive guide, we'll demonstrate AI agent development by building a practical example: a code review agent that integrates with Claude Desktop using the Model Context Protocol (MCP). Through this hands-on MCP development tutorial, you'll learn how to create AI agents for software development that can      automatically detect your project's programming language, load appropriate review checklists, and provide structured feedback.

By the end of this guide, you'll understand the fundamentals of building AI agents and have a fully functional code review tool that you can customize for your team's specific needs or adapt for entirely different use cases.

Explore more about MCP and its role in AI systems: Learn more about MCP and its role in AI systems here

What we will build:

  • A code review agent that works with Claude Desktop
  • Automatic technology detection for Python, JavaScript, Java, Go, Rust, and TypeScript
  • Customizable review checklists with security, quality, and performance checks
  • Pattern-based code analysis using regular expressions
  • Real-time progress tracking during reviews

Time required: 30-45 minutes

Skill level: Intermediate Python knowledge

Prerequisites:

  • Python 3.11 or higher installed
  • Claude Desktop application
  • Basic command line familiarity

Understanding AI Agent Development Through a Code Review Implementation

Before we dive in, let's clarify exactly how this code review system works:

How the Code Review Process Works in Our AI Agent

Our implementation uses static code analysis, not AI-based code review. Here's what happens:

  1. Pattern Matching: Devs create a YAML checklist containing regex patterns based on specific requirements. The system used this checklist to check flag errors line by line (e.g., eval(, hardcoded passwords, console.log).
  2. File Validation: Checks if required files exist (e.g., requirements.txt, package.json)
  3. Static Analysis: No actual code execution - just text pattern matching

Discover more about AI solutions for businesses: Check out our AI services for businesses to explore custom AI solutions.

The AI Agent's Role: How Claude Orchestrates MCP Tools

Claude's role is limited to:

  • Natural Language Interface: You can ask "review my Python code" instead of calling command-line tools
  • Tool Orchestration: Claude decides which MCP server development tools to call based on your request
  • Result Presentation: Claude formats and explains the findings in conversational language
Seamlessly connect artificial intelligence agents to your systems using custom MCP development

What This Means for AI Agent Development

  • Regex patterns do the actual code review you define in YAML files
  • Not AI-based: Claude doesn't analyze your code semantically or understand logic
  • Pattern-based: You define what to look for (like "find all eval() calls")
  • Customizable: You control exactly what gets checked by editing YAML checklists
  • Deterministic: Same code always produces the same results (no AI variability)

Why Building AI Agents with MCP This Way Is Effective ?

This hybrid approach gives you:

  • Control: You define the exact rules via YAML checklists
  • Speed: Pattern matching is fast, no AI inference needed for scanning
  • Consistency: Deterministic results every time
  • Extensibility: Easy to add new checks without AI training
  • Convenience: Natural language interface via Claude Desktop

Think of it as linting rules + Claude's conversational interface. You're essentially building an AI agent with MCP that runs as a customizable linter through natural conversation.

Learn how consulting can optimize AI agent workflows: AI Strategy Consulting Services

Table of Contents

  1. Understanding the Model Context Protocol
  2. Project Architecture
  3. Setting Up the Project
  4. Building the Technology Detector
  5. Building the Validation System
  6. Building the Progress Tracker
  7. Building the Checklist Engine
  8. Creating YAML Checklists

Continue to Part 2 for MCP server development, testing, and deployment.

Understanding the Model Context Protocol

Architecture diagram of AI Agent Development and MCP Server integration for software automation

Before we dive into AI Agent Development, let's understand what MCP is and why it matters.

What is MCP?

The Model Context Protocol is an open standard developed by Anthropic. It is used for smoothly connecting artificial intelligence agents with external data sources. In simple terms, it’s a bridge that lets your AI talk to external tools or data sources.

Why does MCP matter?

Without MCP, every integration between AI Agents and your development tools would need custom code. MCP provides

  • A standard way to expose tools to artificial intelligence agents
  • Secure, local execution of code analysis
  • Bidirectional communication between Claude and your tools
  • Extensibility for custom integrations

For advanced AI agent examples, see: Custom AI Agent Development

How it works

MCP Server Development interaction process with artificial intelligence agents for efficient automation

The flow is straightforward:

  1. You interact with the Claude Desktop
  2. Claude identifies when it needs to use your MCP tools
  3. Claude sends a request to your MCP server
  4. Your MCP server executes the code review
  5. Results are sent back to Claude
  6. Claude presents the findings in natural language

Project Architecture

Our code review agent consists of several components that work together:

mcp-code-reviewer/
├── main.py                      # MCP server with tool definitions
├── technology_detector.py       # Detects project programming language
├── checklist_engine.py          # Orchestrates the review process
├── validators/
│   ├── __init__.py
│   ├── base_validator.py        # Base class for all validators
│   ├── pattern_validator.py     # Regex-based code scanning
│   └── file_validator.py        # File existence checks
├── reporters/
│   ├── __init__.py
│   └── progress_tracker.py      # Tracks review progress
├── checklists/
│   ├── python.yaml              # Python review rules
│   ├── javascript.yaml          # JavaScript review rules
│   └── java.yaml                # Java review rules
└── pyproject.toml              # Project metadata and dependencies

Component Overview:

  • Technology Detector identifies what programming language your project uses
  • Checklist Engine loads the appropriate YAML checklist and coordinates execution
  • Validators run the actual checks against your code
  • Progress Tracker monitors execution and collects results
  • MCP Server exposes everything as tools that Claude can use

For AI analytics integration, see: Conversational Analytics with SQL

Setting Up Your MCP Development Project

Building AI Agent for software development with MCP Server for automated code review

Firstly, we need to create the project structure and install the required dependencies.

Step 1: Create the project directory

Open your terminal and run these commands:

# Create main project folder
mkdir mcp-code-reviewer
cd mcp-code-reviewer


# Create subdirectories for different components
mkdir checklists validators reporters


# Create __init__.py files for Python packages
touch validators/__init__.py
touch reporters/__init__.py

Step 2: Define project dependencies

Create a file called pyproject.toml in the project root:

[project]
name = "mcp-code-reviewer"
version = "0.1.0"
description = "MCP server for automated code review"
requires-python = ">=3.11"
dependencies = [
    "mcp[cli]>=1.16.0",
    "pyyaml>=6.0",
    "pathspec>=0.11.0",
]


[project.scripts]
mcp-code-reviewer = "main:mcp.run"


[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

Dependency Explanation:

  • mcp[cli]: The official MCP SDK from Anthropic, including CLI tools for MCP development
  • pyyaml: Parses YAML files where we store our review checklists
  • pathspec: Handles file pattern matching (similar to .gitignore patterns)

Important: The entry point mcp-code-reviewer = "main:mcp.run" tells Python to call the run() method on the MCP server object in main.py. This is crucial for the  MCP server to work correctly.

Step 3: Install dependencies

We will use uv, a fast Python package manager. If you don't have it installed:

pip install uv

Now install the project dependencies:

uv sync

This creates a virtual environment and installs all required packages automatically.

Building the Technology Detector

The technology detector is the first component we need. It automatically identifies what programming language a project uses by looking for indicator files and counting source code files.

What it does:

The technology detector automatically identifies your project's programming language by analyzing indicator files and source code files.

How it works:

  1. Defines indicator files for each technology (e.g., package.json for JavaScript, pyproject.toml for Python)
  2. Scores each technology based on indicator files found (2 points per indicator)
  3. Counts source code files by extension and adds to the score.
  4. Returns the highest-scoring technology with confidence level.

Key implementation concept:

# Define technology indicators
TECH_INDICATORS = {
    "python": {
        "files": ["requirements.txt", "setup.py", "pyproject.toml"],
        "extensions": [".py"],
        "frameworks": {"django": ["manage.py"], "flask": ["app.py"]}
    },
    "javascript": {
        "files": ["package.json", "yarn.lock"],
        "extensions": [".js", ".jsx"]
    }
}

# Scoring logic - indicator files get 2 points, source files add to score
for tech, indicators in TECH_INDICATORS.items():
    for file in indicators["files"]:
        if self._file_exists(file):
            score += 2

    # Count source code files
    ext_count = self._count_extensions(indicators["extensions"])
    if ext_count > 0:
        score += min(ext_count / 10, 3)  # Cap at 3 points

Create the file:

Create technology_detector.py in your project root with the complete implementation, including the TechnologyDetector class with methods for:

  • detect(): Main detection method
  • _file_exists(): Checks for indicator files
  • _count_extensions(): Counts source files
  • _detect_frameworks(): Identifies frameworks by reading config files

Note: Full implementation available in the GitHub repository.

Building the Validation System

The validation system is the heart of our code review agent. We have three validator classes: a base class and two implementations.

Create a validators package

First, create validators/__init__.py:

from .base_validator import BaseValidator, ValidationResult
from .pattern_validator import PatternValidator
from .file_validator import FileValidator


__all__ = ['BaseValidator', 'ValidationResult', 'PatternValidator', 'FileValidator']

Base Validator

What it does:

Provides an abstract base class and a result container for all validators.

How it works:

  1. The ValidationResult class stores check outcomes (pass/fail, message, file location, line number)
  2. BaseValidator defines the abstract validate() method all validators must implement
  3. Provides helper method get_files_to_check() for scanning source files

Key implementation concept:

class ValidationResult:
    """Represents the result of a single validation check."""
    def __init__(self, check_id: str, passed: bool, message: str = "",
                 file_path: str = "", line_number: int = 0, severity: str = "info"):
        self.check_id = check_id
        self.passed = passed
        self.message = message
        self.file_path = file_path
        self.line_number = line_number
        self.severity = severity

class BaseValidator(ABC):
    @abstractmethod
    def validate(self, check: Dict[str, Any]) -> List[ValidationResult]:
        """Must be implemented by subclasses."""
        pass

Create the file:

Create validators/base_validator.py with the complete ValidationResult and BaseValidator classes.

Note: Full implementation available in the GitHub repository.

Pattern Validator

What it does:

Scans source code files line-by-line for regex pattern matches (security issues, code smells, etc.).

How it works:

  • Receives check definition with regex patterns from YAML
  • Gets appropriate source files based on file extensions
  • Compiles regex patterns and scans each line
  • Records failures with file path and line number when patterns match

Key implementation concept:

# Core pattern matching logic
for file_path in files:
    content = file_path.read_text(encoding='utf-8', errors='ignore')
    lines = content.split('\n')

    for pattern_str in patterns:
        pattern = re.compile(pattern_str, re.IGNORECASE | re.MULTILINE)

        for line_num, line in enumerate(lines, start=1):
            if pattern.search(line):
                results.append(ValidationResult(
                    check_id=check['id'],
                    passed=False,
                    message=f"Pattern match: {check['description']}",
                    file_path=str(file_path),
                    line_number=line_num,
                    severity=check.get('severity', 'info')
                ))

Create the file:

Create validators/pattern_validator.py with the PatternValidator class, including a helper method _get_extensions() to map technology names to file extensions.

Note: Full implementation available in the GitHub repository.

File Validator

What it does:

Checks if required project files exist (like requirements.txt, package.json, test files).

How it works:

  • Receives a check definition with a list of required files or glob patterns
  • Checks if any of the specified files exist in the project
  • Returns pass if found, fail with a missing file list if not
  • Supports glob patterns for finding test files or other patterns

Key implementation concept:

# Core file existence check
files_to_check = check.get('files', [])
found = False

for filename in files_to_check:
    file_path = self.project_path / filename
    if file_path.exists():
        found = True
        break

if found:
    results.append(ValidationResult(check_id=check['id'], passed=True, ...))
else:
    results.append(ValidationResult(
        check_id=check['id'],
        passed=False,
        message=f"Missing required files: {', '.join(files_to_check)}",
        ...
    ))

Create the file:

Create validators/file_validator.py with the FileValidator class, including helper method _check_pattern_files() for glob pattern matching.

Note: Full implementation available in the GitHub repository.

Building the Progress Tracker

The progress tracker monitors review execution and collects results.First, create reporters/__init__.py:

from .progress_tracker import ProgressTracker


__all__ = ['ProgressTracker']

What it does:

Tracks real-time progress of code review execution, counting passed/failed/skipped checks and recording failure details.

How it works:

  • Initializes counters for total, passed, failed, and skipped checks
  • Updates the current check being processed
  • Records each check outcome (pass/fail/skip)
  • Collects detailed failure information (file, line, message, severity)
  • Calculates percentage completion and formats reports

Key implementation concept:

class ProgressTracker:
    def __init__(self):
        self.total_checks = 0
        self.passed = 0
        self.failed = 0
        self.skipped = 0
        self.current_check = None
        self.failures = []
        self.start_time = None
        self.end_time = None

    def record_pass(self):
        """Record a passed check."""
        self.passed += 1
        self.in_progress = 0

    def record_fail(self, failure_info: Dict[str, Any]):
        """Record a failed check."""
        self.failed += 1
        self.failures.append(failure_info)

Create the file:

Create reporters/progress_tracker.py with the complete ProgressTracker class, including methods for:

  • start(), update_check(), complete()
  • record_pass(), record_fail(), record_skip()
  • get_progress(), get_summary()
  • format_progress_bar(), format_status(), format_failures()

Note: Full implementation available in the GitHub repository.

Building the Checklist Engines

The checklist engine coordinates everything, loading YAML checklists and orchestrating validator execution.

What it does:

Manages the complete code review process by running YAML checklists, validator checks, and monitoring progress.

How it works:

  • Loads technology-specific YAML checklist from the checklists directory
  • Counts total checks and initializes progress tracking
  • Iterates through each category and checks the item
  • Determines the appropriate validator (PatternValidator or FileValidator) based on the check definition
  • Executes validator and records results (pass/fail)
  • Provides progress callbacks for real-time updates
  • Returns a comprehensive summary with failures, duration, and statistics

Key implementation concept:

def review_code(self, technology: str, progress_callback=None) -> Dict[str, Any]:
    # Load checklist
    checklist = self.load_checklist(technology)

    # Start tracking
    total_checks = sum(len(category['items']) for category in checklist['categories'])
    self.progress_tracker.start(total_checks)

    # Execute checks
    for category in checklist['categories']:
        for check in category['items']:
            # Update progress
            self.progress_tracker.update_check(check['id'], check['description'])

            # Execute validation (choose appropriate validator)
            results = self._execute_check(check, technology)

            # Record results
            passed = all(r.passed for r in results)
            if passed:
                self.progress_tracker.record_pass()
            else:
                for result in results:
                    if not result.passed:
                        self.progress_tracker.record_fail({...})

    return self.progress_tracker.get_summary()

Create the file:

Create checklist_engine.py with the complete ChecklistEngine class, including:

  • load_checklist(): Loads YAML files
  • review_code(): Main orchestration method
  • _execute_check(): Chooses and runs the appropriate validator
  • get_progress(), get_summary(), format_report(): Result retrieval

Note: Full implementation available in the GitHub repository.

Creating YAML Checklists

Checklists define what to check for each programming language. Let's create a Python checklist as an example.

Create checklists/python.yaml:

technology: python
description: Code review checklist for Python projects


categories:
  - name: Security
    items:
      - id: SEC-001
        description: No hardcoded credentials or API keys
        validator: check_hardcoded_secrets
        severity: critical
        patterns:
          - "password\\s*=\\s*[\"'][^\"']+[\"']"
          - "api_key\\s*=\\s*[\"'][^\"']+[\"']"
          - "secret\\s*=\\s*[\"'][^\"']+[\"']"
          - "token\\s*=\\s*[\"'][^\"']+[\"']"


      - id: SEC-002
        description: SQL injection prevention (use parameterized queries)
        validator: check_sql_injection
        severity: critical
        patterns:
          - "execute\\([^)]*%[^)]*\\)"
          - "execute\\([^)]*\\+[^)]*\\)"


      - id: SEC-003
        description: No eval() or exec() usage
        validator: check_dangerous_functions
        severity: critical
        patterns:
          - "\\beval\\("
          - "\\bexec\\("


  - name: Code Quality
    items:
      - id: QA-001
        description: Functions should be under 50 lines
        validator: check_function_length
        severity: warning
        threshold: 50


      - id: QA-002
        description: No commented-out code blocks
        validator: check_commented_code
        severity: info
        patterns:
          - "^\\s*#.*\\b(def|class|if|for|while)\\b"


      - id: QA-003
        description: Proper exception handling (no bare except)
        validator: check_exception_handling
        severity: warning
        patterns:
          - "except\\s*:"


  - name: Best Practices
    items:
      - id: BP-001
        description: Use context managers for file operations
        validator: check_context_managers
        severity: warning
        patterns:
          - "open\\([^)]+\\)(?!\\s*as\\s+)"


      - id: BP-002
        description: Requirements file exists
        validator: check_requirements_file
        severity: info
        files: ['requirements.txt', 'pyproject.toml', 'Pipfile']


  - name: Testing
    items:
      - id: TEST-001
        description: Test files exist
        validator: check_test_files
        severity: info
        patterns:
          - 'test_*.py'
          - '*_test.py'


      - id: TEST-002
        description: No print statements (use logging)
        validator: check_print_statements
        severity: info
        patterns:
          - "\\bprint\\("

Important YAML Syntax Notes:

  • In YAML files, backslashes in regex patterns must be double-escaped
  • For example, \b becomes \\b in the YAML file
  • Always use double quotes for strings containing special characters
  • If you see parsing errors, check your escaping and quote usage

Similarly, create checklists/javascript.yaml:

technology: javascript
description: Code review checklist for JavaScript/TypeScript projects


categories:
  - name: Security
    items:
      - id: SEC-001
        description: No hardcoded credentials or API keys
        validator: check_hardcoded_secrets
        severity: critical
        patterns:
          - "password\\s*[:=]\\s*[\"'][^\"']+[\"']"
          - "apiKey\\s*[:=]\\s*[\"'][^\"']+[\"']"


      - id: SEC-002
        description: No eval() usage
        validator: check_dangerous_functions
        severity: critical
        patterns:
          - "\\beval\\("


      - id: SEC-003
        description: Avoid innerHTML (XSS vulnerability)
        validator: check_xss_vulnerabilities
        severity: critical
        patterns:
          - "\\.innerHTML\\s*="


  - name: Code Quality
    items:
      - id: QA-001
        description: Use const/let instead of var
        validator: check_var_usage
        severity: warning
        patterns:
          - "\\bvar\\s+"


      - id: QA-002
        description: No console.log in production code
        validator: check_console_statements
        severity: info
        patterns:
          - "console\\.log\\("
          - "console\\.debug\\("


  - name: Best Practices
    items:
      - id: BP-001
        description: Package.json exists
        validator: check_package_json
        severity: critical
        files: ["package.json"]


      - id: BP-002
        description: ESLint configuration exists
        validator: check_eslint_config
        severity: info
        files: [".eslintrc", ".eslintrc.js", ".eslintrc.json"]

What's Next?

Congratulations! You've completed Part 1 and built all the core components of your AI agent using MCP development:

  • Technology detector for automatic language identification 
  • Validation system with pattern and file validators 
  • Progress tracking for real-time feedback
  • Checklist engine for orchestrating reviews 
  • YAML checklists for Python and JavaScript

In Part 2, we'll cover:

  • Building the MCP server to expose these components as tools
  • Configuring Claude Desktop to use your MCP server
  • Testing with both MCP Inspector and Claude Desktop
  • Troubleshooting common issues
  • Extending the agent with additional features

Continue to Part 2: Integration, Testing & Deployment to complete your  AI agent with MCP server development!

You can explore the complete source code and follow along with the project on GitHub. Check out the repository here: GitHub Repository Link

Questions or Feedback?

If you have any queries regarding this guide or wish to share improvements:

  • Go to the GitHub repository, open a new issue
  • Share your feedback on social media platforms
  • Suggest refinements in the project

Happy coding and enjoy building AI agents!

AI Agent for Software Development powering next-generation business innovation

Shubham Agarwal

Shubham Agarwal

Principal Software Engineer

Read more expand

Shubham Agarwal is a Principal Software Engineer at Mobisoft Infotech with nearly a decade of experience in building high-performance web applications and designing scalable software architectures. While he specializes in Python, Node.js, and React, his expertise spans a wide range of technologies across the full stack. Over the years, Shubham has led the end-to-end development of several successful products translating complex ideas into clean, maintainable, and future-ready solutions. He brings a strong product mindset, a deep understanding of systems design, and a passion for writing code that solves real-world problems.