Skip to main content
Glama
README.md
# MOF Tools MCP Server

A **production-ready**, professional MCP server for Metal-Organic Framework (MOF) research. This server uses the **Streamable HTTP** transport to provide scientific tools over HTTP with comprehensive **Pydantic validation** and a **formal tool registry system**.

## โœจ Key Features

- **๐Ÿ”’ Input/Output Validation**: All tool inputs and outputs are validated using Pydantic models
- **๐Ÿ“‹ Formal Tool Registry**: Centralized tool management with metadata, categories, and tags
- **๐Ÿ›ก๏ธ Production-Ready**: Industry-standard code with comprehensive error handling
- **๐Ÿ“Š Type Safety**: Full type hints throughout the codebase
- **โœ… Tested**: Comprehensive test suite with over 35 tests

## ๐Ÿ“ Repository Structure

- `main.py`: Server entrypoint with tool registration and initialization
- `tools.py`: Core scientific tools with Pydantic validation models
- `tool_registry.py`: Formal tool registration system with metadata management
- `tool_definitions.yaml`: YAML configuration file defining all available tools and their metadata
- `tests/test_tools.py`: Comprehensive test suite for tools and validation
- `tests/test_tools_load.py`: Load and consistency tests for tool definitions
- `pyproject.toml`: Dependency and package management

## ๐Ÿš€ Installation

```bash
# Install dependencies
pip install mcp[server] ase pydantic pyyaml bohr-agent-sdk
```

## ๐Ÿƒ Running the Server

To run as the modern HTTP server (Streamable HTTP):
```bash
python main.py
```

The server will start on `http://0.0.0.0:50001` and display registered tools information:

```
=== MOF Tools Server ===
Registered 3 tools:
  - search_mofs (search)
  - calculate_energy (calculation)
  - optimize_structure (optimization)

Tools by category:
  search: 1 tool(s)
  calculation: 1 tool(s)
  optimization: 1 tool(s)
  analysis: 0 tool(s)
```

## ๐Ÿงช Testing

Run the comprehensive test suite:

```bash
# Run all tests
PYTHONPATH=. pytest tests/ -v

# Run specific test file
PYTHONPATH=. pytest tests/test_tools.py -v
PYTHONPATH=. pytest tests/test_tools_load.py -v
```

## ๐Ÿงช Testing the Server

### Method 1: MCP Inspector
```bash
# Connect inspector to your running HTTP server
npx @modelcontextprotocol/inspector http://localhost:50001/mcp
```

### Method 2: Manual HTTP Check
Since the server runs on HTTP, you can verify it's up with a simple `curl`:

```bash
curl http://localhost:50001/mcp
```

## ๐Ÿ› ๏ธ Available Tools

All tools return validated JSON responses with comprehensive error handling.

Bohr Agent SDK integration also provides asynchronous job management tools:
- `submit_`: Submit a calculation job
- `query_job_status`: Check job progress
- `get_job_results`: Retrieve completed job data

### search_mofs

**Category**: Search  
**Description**: Search for Metal-Organic Frameworks by name or formula in the database

**Input**:
```json
{
  "query": "MOF-5"
}
```

**Output**:
```json
{
  "success": true,
  "results": [
    {
      "name": "MOF-5",
      "formula": "Zn4O(BDC)3",
      "surface_area": 3800.0
    }
  ],
  "count": 1,
  "message": "Found 1 MOF(s)"
}
```

### calculate_energy

**Category**: Calculation  
**Description**: Calculate the potential energy of a structure from CIF file content or path using ASE

**Input**:
```json
{
  "data": "<CIF file content or path>"
}
```

**Output**:
```json
{
  "success": true,
  "energy": -123.4567,
  "error": null,
  "message": "Energy: -123.4567 eV"
}
```

### optimize_structure

**Category**: Optimization  
**Description**: Perform structure optimization for a named MOF structure (placeholder implementation)

**Input**:
```json
{
  "name": "HKUST-1"
}
```

**Output**:
```json
{
  "success": true,
  "structure_name": "HKUST-1",
  "message": "Successfully initiated optimization for HKUST-1"
}
```

## ๐Ÿ”Œ Integration

To connect your agent to this server, use the Streamable HTTP endpoint:

**URL**: `http://localhost:50001/mcp`

## ๐Ÿ—๏ธ Architecture

### Pydantic Validation

All tools use Pydantic models for comprehensive input/output validation:

- **Input Models**: Validate and sanitize user inputs
- **Output Models**: Ensure consistent response structure
- **Field Validators**: Custom validation logic (e.g., trimming whitespace, checking ranges)
- **Error Handling**: Graceful error messages returned as validated JSON

### Tool Registry System

The formal tool registry provides:

- **Metadata Management**: Description, category, version, tags for each tool
- **Categorization**: Tools organized by category (search, calculation, optimization, analysis)
- **Tag-based Discovery**: Find tools by tags (e.g., "mof", "energy", "database")

### Production-Ready Features

- โœ… Full type hints throughout
- โœ… Comprehensive error handling
- โœ… Input sanitization and validation
- โœ… Consistent JSON output format
- โœ… Detailed documentation
- โœ… Test coverage (38 tests)
- โœ… Modular, maintainable code structure

## ๐Ÿ“š Development

### Tool Configuration

Tool definitions are stored in `tool_definitions.yaml` for easy configuration and management. This separates tool metadata from code logic.

**Example tool definition:**
```yaml
tools:
  - name: my_tool
    description: Tool description
    category: CALCULATION
    function_name: my_tool  # Function name in tools.py
    tags:
      - tag1
      - tag2
    version: "1.0.0"
```

### Adding a New Tool

1. **Define Pydantic models** in `tools.py`:
```python
class MyToolInput(BaseModel):
    param: str = Field(..., description="Parameter description")

class MyToolOutput(BaseModel):
    success: bool
    result: str
```

2. **Implement the tool function** in `tools.py`:
```python
def my_tool(param: str) -> str:
    try:
        validated_input = MyToolInput(param=param)
        # ... tool logic ...
        output = MyToolOutput(success=True, result="...")
        return output.model_dump_json(indent=2)
    except ValidationError as e:
        # ... error handling ...
```

3. **Add the tool definition** to `tool_definitions.yaml`:
```yaml
  - name: my_tool
    description: Tool description
    category: CALCULATION
    function_name: my_tool
    tags:
      - tag1
      - tag2
    version: "1.0.0"
```

The tool will be automatically registered when the server starts.

4. **Add tests** in `test_tools.py`:
```python
def test_my_tool():
    result = tools.my_tool("test")
    parsed = json.loads(result)
    assert parsed["success"] is True
```

## ๐Ÿ“ License

See LICENSE file for details.