Metadata-Version: 2.4
Name: mcp-template
Version: 0.1.0
Summary: Add your description here
Requires-Python: >=3.13
Description-Content-Type: text/markdown
Requires-Dist: mcp[cli]>=1.14.0
Requires-Dist: nest-asyncio>=1.6.0
Requires-Dist: openai>=1.107.1
Requires-Dist: psutil

# MCP Template Server & LLM Client

A comprehensive Python implementation of the **Model Context Protocol (MCP)** with multi-provider LLM support, featuring modular tools, prompts, and resources. This project provides a production-ready MCP server and flexible client that supports OpenAI, Claude, and Grok models.

## Table of Contents

- [Quick Start](#quick-start)
- [Introduction](#introduction)
- [Architecture & Code Structure](#architecture--code-structure)
- [Tools](#tools)
- [Prompts](#prompts)
- [Resources](#resources)
- [Test Cases](#test-cases)
- [Configuration](#configuration)
- [Running the System](#running-the-system)
- [Development](#development)
- [API Reference](#api-reference)
- [Contributing](#contributing)

## Quick Start

### Basic Usage (5 minutes)

```bash
# 1. Install dependencies
pip install -r requirements.txt

# 2. Set your API key (choose your provider)
export OPENAI_API_KEY="your-openai-key"
# OR
export ANTHROPIC_API_KEY="your-claude-key"
# OR
export GROK_API_KEY="your-grok-key"

# 3. Start the MCP server
python run_mcp_server.py --transport sse

# 4. Run the client (in another terminal)
python mcp_llm_client.py --provider openai --query "Calculate 25 squared"
```

### Output
```
Connected to MCP server using SSE transport
Processing query: 'Calculate 25 squared'
Calling openai/gpt-4o with 24 available tools...
Assistant wants to use 1 tool(s)
  1. Calling tool: power
     Arguments: {'kwargs': '{"base": 25, "exponent": 2}'}
     Result: 625
Getting final response from openai/gpt-4o...
Final answer: 25 squared is 625.
```

## Introduction

### What is MCP?

**MCP (Model Context Protocol)** is an open standard for connecting AI applications to external systems and data sources. It enables AI models to:

- **Execute tools** (calculations, API calls, system commands)
- **Access resources** (files, databases, configurations)
- **Use prompts** (reusable conversation templates)

### Getting Started with MCP

For a basic introduction to MCP concepts, see the [`intro_test/`](./intro_test/) directory, which contains:

- **[Complete MCP Guide](./intro_test/INTRO_README.md)** - Comprehensive introduction to MCP concepts
- **Basic Server & Client Examples** - Simple implementations using FastMCP
- **Transport Protocol Examples** - SSE and STDIO transport implementations
- **OpenAI Integration** - Basic MCP-OpenAI client example

> **New to MCP?** Start with [`intro_test/INTRO_README.md`](./intro_test/INTRO_README.md) for a complete beginner's guide.

## Architecture & Code Structure

```
mcp_template/
├── src/mcp_template/
│   ├── core/                 # Core MCP types and interfaces
│   ├── llm_client/          # Multi-provider LLM client factory
│   │   ├── base_client.py   # Abstract base client
│   │   ├── openai_client.py # OpenAI implementation
│   │   ├── claude_client.py # Claude implementation
│   │   ├── grok_client.py   # Grok implementation
│   │   └── client_factory.py # Factory for creating clients
│   ├── server/
│   │   ├── modular_server.py # Main MCP server
│   │   ├── tools/           # Tool registration system
│   │   ├── prompts/         # Prompt management
│   │   └── resources/       # Resource management
│   └── tools/               # Tool implementations
│       ├── math_tools.py    # Mathematical operations
│       ├── text_tools.py    # Text processing
│       ├── system_tools.py  # System utilities
│       └── web_tools.py     # Web utilities
├── intro_test/              # Basic MCP examples
├── mcp_llm_client.py        # Multi-provider MCP client
├── run_mcp_server.py       # Server launcher
└── config.py               # Configuration management
```

### Key Components

- **`modular_server.py`** - Main MCP server with auto-discovery
- **`mcp_llm_client.py`** - Client supporting multiple AI providers
- **`client_factory.py`** - Factory pattern for LLM client creation
- **Tool Registry** - Automatic tool discovery and registration
- **Transport Layer** - SSE and STDIO transport implementations

## Tools

Tools are executable functions that AI models can invoke to perform actions. The system includes **24 built-in tools** across multiple categories.

### Available Tool Categories

#### Mathematical Tools (`math_tools.py`)
```python
# Available functions: add, subtract, multiply, divide, power, square_root, calculate_bmi
result = await add(a=10, b=5)  # Returns: 15
result = await power(base=5, exponent=3)  # Returns: 125
result = await square_root(number=144)  # Returns: 12.0
```

#### Text Processing Tools (`text_tools.py`)
```python
# Available functions: count_words, search_text, replace_text, to_uppercase, to_lowercase, text_length
word_count = await count_words(text="Hello world")  # Returns: 2
uppercase = await to_uppercase(text="hello")  # Returns: "HELLO"
```

#### System Tools (`system_tools.py`)
```python
# Available functions: get_system_info, get_current_time, list_directory, get_file_info, get_environment_variable
sys_info = await get_system_info()  # Returns system information
current_time = await get_current_time()  # Returns: "2024-01-15 14:30:25"
```

#### Web Tools (`web_tools.py`)
```python
# Available functions: url_encode, url_decode, parse_url, validate_email, extract_domain
encoded = await url_encode(text="hello world")  # Returns: "hello%20world"
is_valid = await validate_email(email="user@example.com")  # Returns: True
```

### Creating Custom Tools

#### Method 1: Using MCPTool Class
```python
from mcp_template.core.types import MCPTool

async def custom_calculator(x: float, operation: str) -> float:
    """Perform custom calculation"""
    if operation == "double":
        return x * 2
    elif operation == "half":
        return x / 2
    return x

tool = MCPTool(
    name="custom_calculator",
    description="Perform custom calculations",
    input_schema={
        "type": "object",
        "properties": {
            "x": {"type": "number", "description": "Input number"},
            "operation": {
                "type": "string",
                "enum": ["double", "half"],
                "description": "Operation to perform"
            }
        },
        "required": ["x", "operation"]
    },
    handler=custom_calculator
)
```

#### Method 2: Using Tool Classes
```python
from mcp_template.tools.tool_registry import ServerToolRegistry

class CustomTools:
    @staticmethod
    def get_tools():
        return [
            CustomTools._create_custom_tool(),
        ]

    @staticmethod
    def _create_custom_tool():
        async def my_tool(param1: str, param2: int = 0) -> str:
            """Description of my tool"""
            return f"Processed {param1} with {param2}"

        return MCPTool(
            name="my_custom_tool",
            description="Custom tool description",
            input_schema={
                "type": "object",
                "properties": {
                    "param1": {"type": "string", "description": "First parameter"},
                    "param2": {"type": "integer", "description": "Second parameter", "default": 0}
                },
                "required": ["param1"]
            },
            handler=my_tool
        )
```

#### Method 3: FastMCP Integration
```python
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("MyServer")

@mcp.tool()
async def my_fastmcp_tool(input: str) -> str:
    """FastMCP tool with automatic schema generation"""
    return f"Processed: {input}"

# Tool is automatically registered with proper schema
```

### Tool Registration

Tools are automatically discovered and registered:

```python
# Automatic registration (recommended)
from mcp_template.server.modular_server import create_default_server

server = create_default_server()
await server.initialize()  # Automatically discovers and registers all tools

# Manual registration
from mcp_template.server.tools.tool_registry import ServerToolRegistry

registry = ServerToolRegistry()
registry.register_tools(your_custom_tools)
```

## Prompts

Prompts are reusable conversation templates that help AI models perform specific tasks.

### Available Prompts

#### Greeting Prompt
```python
from mcp_template.server.prompts.greeting_prompt import GreetingPrompt

prompt = GreetingPrompt()
result = await prompt.generate(
    name="Alice",
    style="friendly",
    tone="warm",
    element="compliment"
)
# Returns: Template with substituted variables
```

### Creating Custom Prompts

```python
from mcp_template.server.prompts.base_prompt import BaseServerPrompt

class CodeReviewPrompt(BaseServerPrompt):
    def __init__(self):
        super().__init__(
            name="code_review",
            description="Generate code review feedback",
            template="""
            Please review the following {language} code for:
            - Code quality and best practices
            - Potential bugs or security issues
            - Performance optimizations
            - Readability improvements

            Code to review:
            {code}

            Focus on: {focus_areas}
            """,
            arguments={
                "language": {
                    "type": "string",
                    "enum": ["python", "javascript", "java", "cpp"],
                    "description": "Programming language"
                },
                "focus_areas": {
                    "type": "string",
                    "description": "Areas to focus the review on"
                }
            }
        )

    async def generate(self, code: str, language: str, focus_areas: str = "all") -> str:
        return self._substitute_template(
            code=code,
            language=language,
            focus_areas=focus_areas
        )
```

## Resources

Resources represent data sources that AI models can access and read.

### Available Resources

#### Configuration Resource
```python
# URI: config://settings
# Returns: Server configuration in JSON format
{
  "server_name": "MCP Template Server",
  "version": "1.0.0",
  "features": ["tools", "prompts", "resources"],
  "transport": {"supported": ["stdio", "sse"], "default": "stdio"},
  "tools_count": 24,
  "prompts_count": 1,
  "resources_count": 2
}
```

#### Dynamic Greeting Resource
```python
# URI: dynamic://greeting
# Returns: Personalized greeting with current timestamp
```

### Creating Custom Resources

```python
from mcp_template.server.resources.base_resource import BaseServerResource

class DatabaseResource(BaseServerResource):
    def __init__(self, db_path: str):
        super().__init__(
            uri=f"db://{db_path}",
            name="Database Connection",
            description=f"Access to database: {db_path}",
            mime_type="application/json"
        )
        self.db_path = db_path

    async def read(self, query: str = None, **kwargs) -> str:
        """Execute database query and return results"""
        # Implement database logic here
        import json

        if query:
            # Execute specific query
            result = {"query": query, "result": "mock_data"}
        else:
            # Return database info
            result = {"database": self.db_path, "status": "connected"}

        return json.dumps(result, indent=2)
```

## Test Cases

Test cases should be written for each tool category to ensure proper functionality:

### Mathematical Tools Tests
Should test basic arithmetic, power functions, square root calculations, and BMI calculations.

### Text Tools Tests
Should test word counting, case conversion, text search, and text replacement functionality.

### System Tools Tests
Should test system information retrieval, current time, and environment variable access.

### Web Tools Tests
Should test URL encoding/decoding, email validation, and domain extraction.

## Configuration

### Environment Variables

Create a `.env` file in the project root:

```bash
# OpenAI (default provider)
OPENAI_API_KEY=sk-your-openai-key-here

# Claude (alternative provider)
ANTHROPIC_API_KEY=sk-ant-your-claude-key-here

# Grok (alternative provider)
GROK_API_KEY=xai-your-grok-key-here
```

### Server Configuration

The server automatically discovers and registers:
- **Tools**: All classes in `src/mcp_template/tools/`
- **Prompts**: All classes in `src/mcp_template/server/prompts/`
- **Resources**: All classes in `src/mcp_template/server/resources/`

## Running the System

### Transport Methods

#### 1. Server-Sent Events (SSE) - Recommended

**Start Server:**
```bash
python run_mcp_server.py --transport sse --port 8050
```

**Run Client:**
```bash
# Interactive mode
python mcp_llm_client.py --provider openai --model gpt-4o

# Single query
python mcp_llm_client.py --provider openai --query "Calculate 25 + 30"

# With custom parameters
python mcp_llm_client.py --provider openai --model gpt-4o --temperature 0.7 --max-tokens 1000
```

#### 2. Standard Input/Output (STDIO)

**Note:** STDIO transport doesn't require starting a separate server. The client automatically launches the server process.

```bash
# The client will automatically start the server
python mcp_llm_client.py --transport stdio --provider openai --query "Calculate 10 * 5"
```

### Advanced Usage

#### Multiple Providers
```bash
# OpenAI (default)
python mcp_llm_client.py --provider openai --model gpt-4o

# Claude
python mcp_llm_client.py --provider claude --model claude-3-opus-20240229

# Grok
python mcp_llm_client.py --provider grok --model grok-1
```

#### Custom Parameters
```bash
python mcp_llm_client.py \
  --provider openai \
  --model gpt-4o \
  --temperature 0.01 \
  --max-tokens 500 \
  --top-p 0.9 \
  --query "Explain quantum computing"
```

#### Interactive Mode
```bash
python mcp_llm_client.py --provider openai --temperature 0.7

# Now you can have natural conversations:
# Your query: Calculate 15 + 27
# Response: 15 + 27 equals 42.
#
# Your query: What's the square root of 144?
# Response: The square root of 144 is 12.
#
# Your query: Count words in "Hello beautiful world"
# Response: The text contains 3 words.
```

### Docker Usage (Future)

```bash
# Build the image
docker build -t mcp-template .

# Run with environment variables
docker run -e OPENAI_API_KEY=your-key -p 8050:8050 mcp-template
```

## Development

### Adding New Tools

1. **Create tool file** in `src/mcp_template/tools/`
2. **Implement tool class** with `get_tools()` method
3. **Return MCPTool objects** with proper schemas
4. **Tools are auto-discovered** - no registration needed

### Adding New Prompts

1. **Create prompt class** in `src/mcp_template/server/prompts/`
2. **Extend BaseServerPrompt**
3. **Implement template and arguments**
4. **Prompts are auto-discovered**

### Adding New Resources

1. **Create resource class** in `src/mcp_template/server/resources/`
2. **Extend BaseServerResource**
3. **Implement read() method**
4. **Resources are auto-discovered**

### Testing

```bash
# Run all tests
python -m pytest tests/

# Run specific test file
python -m pytest tests/unit/test_tools.py

# Run with coverage
python -m pytest --cov=src tests/
```

## API Reference

### MCPAIClient

```python
class MCPAIClient:
    def __init__(
        self,
        model: str = "gpt-4o",
        transport: TransportType = TransportType.SSE,
        provider: str = "openai",
        temperature: float = 0.7,
        max_tokens: int = 1000,
        **kwargs
    )

    async def process_query(self, query: str) -> str
    async def get_mcp_tools(self) -> List[Dict[str, Any]]
    async def interactive_session(self)
```

### AIClientFactory

```python
class AIClientFactory:
    @staticmethod
    def create_client(provider: str, model_name: str, **kwargs) -> BaseAIClient

    @staticmethod
    def create_openai_client(model_name: str = "gpt-4o", **kwargs) -> OpenAIClient

    @staticmethod
    def create_claude_client(model_name: str = "claude-3-opus-20240229", **kwargs) -> ClaudeClient

    @staticmethod
    def create_grok_client(model_name: str = "grok-1", **kwargs) -> GrokClient
```

## Contributing

1. **Fork the repository**
2. **Create feature branch**: `git checkout -b feature/your-feature`
3. **Add tests** for new functionality
4. **Ensure tests pass**: `python -m pytest`
5. **Submit pull request**

### Code Standards

- Use type hints for all function parameters and return values
- Follow PEP 8 style guidelines
- Add docstrings to all classes and methods
- Include unit tests for new features
- Update documentation for API changes

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Support

- **Documentation**: See [`intro_test/INTRO_README.md`](./intro_test/INTRO_README.md) for MCP basics
- **Issues**: Report bugs on GitHub Issues
- **Discussions**: Join discussions on GitHub Discussions
- **Email**: Contact maintainers for support

---

**Built with using the Model Context Protocol (MCP)**

*Transforming AI applications with standardized tool integration*
