Skip to main content
Glama
chaitanyaiscoding

MCP Database Tools Server

README.md
# MCP Database Tools Server

## πŸ“‹ Table of Contents
- [Overview](#overview)
- [Architecture](#architecture)
- [Project Structure](#project-structure)
- [Component Flow](#component-flow)
- [Installation & Setup](#installation--setup)
- [Usage](#usage)
- [Configuration](#configuration)
- [Troubleshooting](#troubleshooting)

---

## 🎯 Overview

This project is a **Model Context Protocol (MCP) Server** that automates Django database setup and management tasks. It provides tools to:
- Create PostgreSQL databases
- Enable PostgreSQL extensions (hstore)
- Update Django .env configuration files
- Execute Django management commands

The server integrates with VS Code Copilot and can be accessed via:
- VS Code MCP integration
- Automated workflow scripts

---

## πŸ—οΈ Architecture

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        MCP Client Layer                          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                           β”‚
β”‚  β”‚  VS Code     β”‚  β”‚   Workflow   β”‚                           β”‚
β”‚  β”‚  Copilot     β”‚  β”‚   Scripts    β”‚                           β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚                  β”‚                  β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   MCP Server    β”‚
                    β”‚   (server.py)   β”‚
                    β”‚                 β”‚
                    β”‚  - list_tools() β”‚
                    β”‚  - call_tool()  β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚                  β”‚                  β”‚
    β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”
    β”‚PostgreSQL β”‚     β”‚  Django   β”‚     β”‚   .env    β”‚
    β”‚ Database  β”‚     β”‚  Backend  β”‚     β”‚   File    β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

---

## πŸ“ Project Structure

```
MCP_project/
β”‚
β”œβ”€β”€ server.py                  # Main MCP server implementation
β”œβ”€β”€ mcp.json                   # MCP server metadata
β”œβ”€β”€ requirements.txt           # Python dependencies
β”‚
* Web and CLI clients removed: The project no longer includes web_client.py or test_client.py files.
β”œβ”€β”€ run_workflow.py           # Automated workflow executor
β”‚
β”œβ”€β”€ tools/                    # Utility modules (legacy/reference)
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ db_tools.py          # PostgreSQL database operations
β”‚   β”œβ”€β”€ env_tools.py         # Environment file management
β”‚   └── django_tools.py      # Django command execution
β”‚
β”œβ”€β”€ templates/               # Web UI templates
β”‚   └── index.html          # Main web interface
β”‚
└── venv/                   # Python virtual environment
```

---

## πŸ”„ Component Flow

### 1. **Core Server (server.py)**

The heart of the system, implementing the MCP protocol:

```python
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    server.py                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                          β”‚
β”‚  Configuration:                                          β”‚
β”‚  β”œβ”€ PG_USER, PG_PASSWORD, PG_HOST                       β”‚
β”‚  β”œβ”€ DB_NAME (default: sample_project_db)                β”‚
β”‚  β”œβ”€ ENV_PATH (Django .env location)                     β”‚
β”‚  β”œβ”€ MANAGE_PY (Django manage.py location)               β”‚
β”‚  └─ PYTHON_EXEC (Virtual environment Python)            β”‚
β”‚                                                          β”‚
β”‚  MCP Server Decorators:                                 β”‚
β”‚  β”œβ”€ @server.list_tools() β†’ Returns available tools      β”‚
β”‚  └─ @server.call_tool() β†’ Executes tool operations      β”‚
β”‚                                                          β”‚
β”‚  Tools Implemented:                                      β”‚
β”‚  β”œβ”€ create_database(db_name)                            β”‚
β”‚  β”œβ”€ enable_hstore(db_name)                              β”‚
β”‚  β”œβ”€ update_env(db_name)                                 β”‚
β”‚  └─ django(cmd)                                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

**Key Features:**
- **Async/await architecture** for MCP protocol compliance
- **stdio communication** (not HTTP) for MCP client integration
- **Automatic lowercase conversion** for PostgreSQL database names
- **Environment variable loading** from .env files for Django commands
- **Virtual environment Python** execution to ensure dependencies

---

### 2. **Tool: create_database**

```
Input: { db_name: "mydb" }
β”‚
β”œβ”€ Converts db_name to lowercase ("mydb")
β”‚
β”œβ”€ Connects to PostgreSQL server (postgres database)
β”‚  └─ Uses: PG_USER, PG_PASSWORD, PG_HOST
β”‚
β”œβ”€ Executes: CREATE DATABASE mydb;
β”‚
└─ Returns: "Database mydb created."
```

**PostgreSQL Connection:**
```python
psycopg2.connect(
    dbname="postgres",
    user=PG_USER, 
    password=PG_PASSWORD,
    host=PG_HOST
)
```

---

### 3. **Tool: enable_hstore**

```
Input: { db_name: "mydb" }
β”‚
β”œβ”€ Converts db_name to lowercase
β”‚
β”œβ”€ Connects to the specified database
β”‚
β”œβ”€ Executes: CREATE EXTENSION IF NOT EXISTS hstore;
β”‚
└─ Returns: "hstore extension enabled in mydb."
```

**Purpose:** Enables PostgreSQL's hstore extension for key-value pair storage.

---

### 4. **Tool: update_env**

```
Input: { db_name: "mydb" }
β”‚
β”œβ”€ Converts db_name to lowercase
β”‚
β”œβ”€ Reads ENV_PATH file
β”‚
β”œβ”€ Finds line: POSTGRES_DB_NAME=old_value
β”‚  └─ Skips commented lines (#)
β”‚
β”œβ”€ Replaces with: POSTGRES_DB_NAME=mydb
β”‚
└─ Returns: ".env updated: POSTGRES_DB_NAME=mydb"
```

**File Operations:**
- Preserves all other .env content
- Only updates non-commented POSTGRES_DB_NAME lines
- Maintains file structure and formatting

---

### 5. **Tool: django**

```
Input: { cmd: "migrate" }
β”‚
β”œβ”€ Loads environment from ENV_PATH using dotenv
β”‚  └─ Merges with os.environ
β”‚
β”œβ”€ Executes: PYTHON_EXEC MANAGE_PY migrate
β”‚  └─ In working directory: dirname(MANAGE_PY)
β”‚  └─ With loaded environment variables
β”‚
β”œβ”€ Captures stdout and stderr
β”‚
└─ Returns: Command output with exit code
```

**Execution Flow:**
```python
subprocess.run(
    [PYTHON_EXEC, MANAGE_PY] + cmd.split(),
    cwd=workdir,
    env=env,  # Loaded from .env
    capture_output=True,
    text=True
)
```

**Why Virtual Environment Python?**
- Django and dependencies installed in virtual environment
- System Python lacks required packages
- Ensures consistent execution environment

---

## Client Interfaces

Access to the server is primarily via VS Code MCP integration and the automated workflow script.

### C. **Workflow Automation (run_workflow.py)**

```
Complete Database Setup Workflow
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Step 1: Create database                 β”‚
β”‚  Step 2: Enable hstore extension         β”‚
β”‚  Step 3: Update .env file                β”‚
β”‚  Step 4: Run create_text_search_config   β”‚
β”‚  Step 5: Run migrations                  β”‚
β”‚  Step 6: Run update_fixtures             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

**Usage:**
```bash
python run_workflow.py mydb
```

**What It Does:**
1. Creates PostgreSQL database "mydb"
2. Enables hstore extension
3. Updates .env with POSTGRES_DB_NAME=mydb
4. Runs Django setup commands in sequence
5. Reports success/failure for each step

---

## πŸ› οΈ Installation & Setup

### Prerequisites
- Python 3.12+
- PostgreSQL server running
- Django project (optional, for Django commands)

### Step 1: Clone/Setup Project
```bash
cd /home/chaitanyaphani/MCP_project
```

### Step 2: Create Virtual Environment
```bash
python3 -m venv venv
source venv/bin/activate  # Linux/Mac
# or
venv\Scripts\activate  # Windows
```

### Step 3: Install Dependencies
```bash
pip install -r requirements.txt
```

**Dependencies:**
- `mcp` - Model Context Protocol SDK
- `Flask` - Web UI framework
- `psycopg2-binary` - PostgreSQL adapter
- `python-dotenv` - Environment file support

### Step 4: Configure PostgreSQL
Edit `server.py`:
```python
PG_USER = "postgres"
PG_PASSWORD = "your_password"  # Update this!
PG_HOST = "localhost"
```

### Step 5: Configure Django Paths
Edit `server.py`:
```python
ENV_PATH = "/path/to/your/django/.env"
MANAGE_PY = "/path/to/your/django/manage.py"
PYTHON_EXEC = "/path/to/your/django/venv/bin/python"
```

### Step 6: Configure VS Code (Optional)
Edit VS Code settings (`settings.json`):
```json
{
  "mcpServers": {
    "dbtools": {
      "command": "python",
      "args": ["server.py"],
      "cwd": "/home/chaitanyaphani/MCP_project"
    }
  }
}
```

---

## πŸš€ Usage

### Method 1: Automated Workflow
```bash
python run_workflow.py database_name
```

### Method 2: VS Code Copilot
Once configured, simply ask:
Once configured, simply ask:
```
"Create a database named myproject, enable hstore, 
update the .env file, and run migrations"
```

---

## βš™οΈ Configuration

### Environment Variables
The server uses these configuration constants:

| Variable | Purpose | Default |
|----------|---------|---------|
| `PG_USER` | PostgreSQL username | `postgres` |
| `PG_PASSWORD` | PostgreSQL password | `root` |
| `PG_HOST` | PostgreSQL host | `localhost` |
| `PG_PORT` | PostgreSQL port | `5432` |
| `DB_NAME` | Default database name | `sample_project_db` |
| `ENV_PATH` | Django .env file path | `/path/to/.env` |
| `MANAGE_PY` | Django manage.py path | `/path/to/manage.py` |
| `PYTHON_EXEC` | Virtual env Python | `/path/to/venv/bin/python` |

### Django .env File Format
Expected format:
```env
POSTGRES_DB_HOST=localhost
POSTGRES_DB_PORT=5432
POSTGRES_DB_NAME=mydb
POSTGRES_DB_USER=postgres
POSTGRES_DB_PASSWORD=password
```

---

## πŸ” Troubleshooting

### Issue 1: "AttributeError: 'Server' object has no attribute 'define_tool'"
**Cause:** Using incorrect MCP decorator syntax.  
**Solution:** Use `@server.list_tools()` and `@server.call_tool()` instead of `@server.define_tool`.

### Issue 2: "password authentication failed for user 'postgres'"
**Cause:** Incorrect PostgreSQL password.  
**Solution:** Update `PG_PASSWORD` in `server.py` with your actual PostgreSQL password.

### Issue 3: "ModuleNotFoundError: No module named 'django'"
**Cause:** Using system Python instead of virtual environment Python.  
**Solution:** Ensure `PYTHON_EXEC` points to your Django project's virtual environment Python.

### Issue 4: "database 'XX' does not exist" (uppercase names)
**Cause:** PostgreSQL converts unquoted identifiers to lowercase.  
**Solution:** Server now automatically converts database names to lowercase.

### Issue 5: ".env updated but database name not changed"
**Cause:** Looking for wrong variable name in .env file.  
**Solution:** Ensure your .env uses `POSTGRES_DB_NAME=` (not `POSTGRES_DB=`).

### Issue 6: "Tables not created after migrate"
**Cause:** Environment variables not loaded, or wrong Python executable.  
**Solutions:**
- Verify `PYTHON_EXEC` points to correct virtual environment
- Check `.env` file is loaded and contains correct database name
- Run migrate manually to see detailed errors

---

## πŸ“Š Data Flow Diagram

### Complete Workflow Example

```
User Request: "Create database 'myapp'"
β”‚
β”œβ”€ VS Code Copilot/Web UI/CLI
β”‚  └─ Sends MCP request to server.py
β”‚
β”œβ”€ server.py receives call_tool("create_database", {"db_name": "myapp"})
β”‚  β”‚
β”‚  β”œβ”€ Step 1: create_database
β”‚  β”‚  β”œβ”€ Convert "myapp" β†’ "myapp" (lowercase)
β”‚  β”‚  β”œβ”€ Connect to PostgreSQL
β”‚  β”‚  β”œβ”€ Execute: CREATE DATABASE myapp;
β”‚  β”‚  └─ Return: "Database myapp created."
β”‚  β”‚
β”‚  β”œβ”€ Step 2: enable_hstore
β”‚  β”‚  β”œβ”€ Connect to "myapp" database
β”‚  β”‚  β”œβ”€ Execute: CREATE EXTENSION IF NOT EXISTS hstore;
β”‚  β”‚  └─ Return: "hstore extension enabled in myapp."
β”‚  β”‚
β”‚  β”œβ”€ Step 3: update_env
β”‚  β”‚  β”œβ”€ Read /path/to/.env
β”‚  β”‚  β”œβ”€ Find: POSTGRES_DB_NAME=olddb
β”‚  β”‚  β”œβ”€ Replace with: POSTGRES_DB_NAME=myapp
β”‚  β”‚  β”œβ”€ Write back to file
β”‚  β”‚  └─ Return: ".env updated: POSTGRES_DB_NAME=myapp"
β”‚  β”‚
β”‚  └─ Step 4: django("migrate")
β”‚     β”œβ”€ Load .env into environment
β”‚     β”œβ”€ Execute: /venv/bin/python manage.py migrate
β”‚     β”‚  └─ Django reads POSTGRES_DB_NAME=myapp from env
β”‚     β”‚  └─ Connects to "myapp" database
β”‚     β”‚  └─ Applies migrations
β”‚     └─ Return: Migration output
β”‚
└─ Result returned to user
```

---

## πŸŽ“ Key Concepts

### Model Context Protocol (MCP)
- **Protocol** for AI assistants to interact with tools
- **stdio-based** communication (not HTTP)
- **Async/await** pattern required
- **Tool registration** via `list_tools()`
- **Tool execution** via `call_tool()`

### Why This Architecture?
1. **Separation of Concerns**: Server logic separate from client interfaces
2. **Multiple Interfaces**: Same server, different access methods
3. **Type Safety**: MCP protocol with schema validation
4. **Error Handling**: Comprehensive error reporting
5. **Environment Isolation**: Uses virtual environment Python

### PostgreSQL Naming Rules
- Unquoted identifiers converted to lowercase
- `CREATE DATABASE MyDB` creates `mydb`
- Server automatically handles this conversion

---

## πŸ“ Tool Reference

### create_database
```json
{
  "name": "create_database",
  "arguments": {
    "db_name": "string (optional, default: sample_project_db)"
  },
  "returns": "Database {db_name} created."
}
```

### enable_hstore
```json
{
  "name": "enable_hstore",
  "arguments": {
    "db_name": "string (optional, default: sample_project_db)"
  },
  "returns": "hstore extension enabled in {db_name}."
}
```

### update_env
```json
{
  "name": "update_env",
  "arguments": {
    "db_name": "string (optional, default: sample_project_db)"
  },
  "returns": ".env updated: POSTGRES_DB_NAME={db_name}"
}
```

### django
```json
{
  "name": "django",
  "arguments": {
    "cmd": "string (required) - Django management command"
  },
  "returns": "Command output (stdout/stderr)"
}
```

**Common Django Commands:**
- `migrate` - Apply database migrations
- `makemigrations` - Create new migrations
- `create_text_search_config` - Custom command
- `update_fixtures` - Custom fixture management
- `runserver` - Start development server

---

## 🀝 Contributing

To extend this server with new tools:

1. Add tool definition in `list_tools()`:
```python
Tool(
    name="my_new_tool",
    description="What it does",
    inputSchema={
        "type": "object",
        "properties": {
            "param1": {"type": "string", "description": "..."}
        },
        "required": ["param1"]
    }
)
```

2. Add tool implementation in `call_tool()`:
```python
elif name == "my_new_tool":
    param1 = arguments.get("param1")
    # Your logic here
    return [TextContent(type="text", text="Result")]
```

---

## πŸ“ž Support

For issues or questions:
1. Check the Troubleshooting section
2. Verify configuration in `server.py`
3. Test with `run_workflow.py` for debugging/automation
4. Check PostgreSQL logs for database issues
5. Check Django logs for Django command issues

---

## πŸ“„ License

This project is part of the Altiushub backend infrastructure.

---

**Last Updated:** December 12, 2025  
**Version:** 1.0.0  
**MCP Protocol Version:** Compatible with MCP SDK latest