Skip to main content

Model Context Protocol (MCP) integration for Pyramid web framework

Project description

Pyramid MCP

PyPI version Python 3.9+ License: MIT Tests Coverage

Pyramid MCP is a library that exposes Pyramid web application endpoints as Model Context Protocol (MCP) tools. It's inspired by fastapi_mcp but designed specifically for the Pyramid web framework.

Features

  • 🔌 Pyramid Plugin: Easy integration with config.include('pyramid_mcp')
  • 🛠️ Tool Registration: Simple @tool decorator for registering MCP tools
  • ⚙️ Settings-based Configuration: Configure via Pyramid settings
  • 🔍 Route Discovery: Automatic discovery of Pyramid routes (planned)
  • 📡 Multiple Protocols: Support for HTTP and SSE (Server-Sent Events)
  • 🧪 Well Tested: Comprehensive test suite with pytest
  • 📚 Type Hints: Full type annotations for better IDE support
  • 🚀 Easy to Use: Minimal setup required

Installation

From PyPI (Recommended)

pip install pyramid-mcp

From Source

git clone https://github.com/your-org/pyramid-mcp
cd pyramid-mcp
pip install -e .

Requirements

  • Python 3.9+
  • Pyramid 2.0+
  • Marshmallow 3.22+ (for schema validation)

Quick Start

Basic Usage

from pyramid.config import Configurator
from pyramid.view import view_config
from pyramid_mcp import tool

# Include pyramid_mcp in your Pyramid application
def create_app():
    config = Configurator(settings={
        'mcp.server_name': 'my-api',
        'mcp.mount_path': '/mcp'
    })
    
    # Include the pyramid_mcp plugin
    config.include('pyramid_mcp')
    
    # Add your regular Pyramid routes
    config.add_route('home', '/')
    config.scan()
    
    return config.make_wsgi_app()

# Register MCP tools using the decorator
@tool(name="calculate", description="Perform basic math operations")
def calculate(operation: str, a: float, b: float) -> float:
    """Perform basic math operations."""
    if operation == "add":
        return a + b
    elif operation == "subtract":
        return a - b
    elif operation == "multiply":
        return a * b
    elif operation == "divide":
        if b == 0:
            raise ValueError("Cannot divide by zero")
        return a / b
    else:
        raise ValueError(f"Unknown operation: {operation}")

@view_config(route_name='home', renderer='json')
def home_view(request):
    return {"message": "Hello World", "mcp_available": True}

Run Your Application

if __name__ == '__main__':
    from wsgiref.simple_server import make_server
    
    app = create_app()
    server = make_server('0.0.0.0', 8080, app)
    print("Server started at http://localhost:8080")
    print("MCP endpoint available at http://localhost:8080/mcp")
    server.serve_forever()

Test Your MCP Integration

# Initialize MCP connection
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "method": "initialize", "id": 1}'

# List available tools
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "method": "tools/list", "id": 2}'

# Call the calculate tool
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0", 
    "method": "tools/call", 
    "id": 3,
    "params": {
      "name": "calculate",
      "arguments": {"operation": "add", "a": 5, "b": 3}
    }
  }'

Configuration

Configure pyramid_mcp using Pyramid settings:

settings = {
    # MCP Server Configuration
    'mcp.server_name': 'my-api',           # Server name
    'mcp.server_version': '1.0.0',        # Server version
    'mcp.mount_path': '/mcp',              # Mount path for MCP endpoints
    
    # Protocol Configuration  
    'mcp.enable_sse': 'true',              # Enable Server-Sent Events
    'mcp.enable_http': 'true',             # Enable HTTP protocol
    
    # Route Discovery (planned)
    'mcp.include_patterns': 'api/*, users/*',  # Routes to include
    'mcp.exclude_patterns': 'internal/*',      # Routes to exclude
}

config = Configurator(settings=settings)
config.include('pyramid_mcp')

Accessing MCP in Views

@view_config(route_name='mcp_info', renderer='json')
def mcp_info_view(request):
    # Access MCP instance through request
    mcp = request.mcp
    
    # Get available tools
    tools = list(mcp.protocol_handler.tools.keys())
    
    return {
        'server_name': mcp.config.server_name,
        'available_tools': tools,
        'mount_path': mcp.config.mount_path
    }

API Reference

Plugin Integration

# Basic inclusion
config.include('pyramid_mcp')

# Access MCP instance
mcp = config.get_mcp()           # From configurator
mcp = request.mcp                # From request (in views)

Tool Registration

from pyramid_mcp import tool

@tool(name="my_tool", description="Tool description")
def my_tool(param1: str, param2: int) -> str:
    """Tool implementation."""
    return f"Result: {param1} * {param2}"

# With schema validation (optional)
from marshmallow import Schema, fields

class MyToolSchema(Schema):
    param1 = fields.Str(required=True)
    param2 = fields.Int(required=True)

@tool(name="validated_tool", schema=MyToolSchema)
def validated_tool(param1: str, param2: int) -> str:
    return f"Validated: {param1} + {param2}"

Manual Usage (Advanced)

from pyramid_mcp import PyramidMCP, MCPConfiguration

# Manual configuration
config = Configurator()
mcp_config = MCPConfiguration(
    server_name="my-server",
    mount_path="/mcp"
)

pyramid_mcp = PyramidMCP(config, config=mcp_config)

# Register tools manually
@pyramid_mcp.tool("manual_tool")
def manual_tool(x: int) -> int:
    return x * 2

# Mount manually (with auto_commit=False for more control)
pyramid_mcp.mount(auto_commit=False)
config.commit()

MCP Protocol

Once configured, your Pyramid application will expose MCP endpoints:

  • HTTP: POST /mcp (or your configured mount path)
  • SSE: GET /mcp/sse (if enabled)

Example MCP Requests

# Initialize MCP connection
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "method": "initialize", "id": 1}'

# List available tools
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "method": "tools/list", "id": 2}'

# Call a tool
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0", 
    "method": "tools/call", 
    "id": 3,
    "params": {
      "name": "calculate",
      "arguments": {"operation": "add", "a": 5, "b": 3}
    }
  }'

Troubleshooting

Common Issues

"Module not found" error

ModuleNotFoundError: No module named 'pyramid_mcp'

Solution: Make sure pyramid-mcp is installed in your active Python environment:

pip list | grep pyramid-mcp
pip install pyramid-mcp

MCP endpoints not accessible

Problem: Getting 404 when accessing /mcp endpoint.

Solutions:

  1. Ensure you've included the plugin: config.include('pyramid_mcp')
  2. Check your mount path setting: 'mcp.mount_path': '/mcp'
  3. Verify the configurator is properly committed if using manual setup

Tools not showing up in /tools/list

Problem: Registered tools don't appear in MCP tools list.

Solutions:

  1. Ensure tools are registered before mounting: pyramid_mcp.mount()
  2. Check that config.scan() is called to discover @tool decorators
  3. Verify the tool registration syntax

Type validation errors

Problem: Getting validation errors when calling tools.

Solutions:

  1. Check parameter types match the function signature
  2. Use Marshmallow schemas for complex validation
  3. Review the MCP request format

Debug Mode

Enable debug logging to troubleshoot issues:

import logging
logging.basicConfig(level=logging.DEBUG)

# In your Pyramid settings
settings = {
    'mcp.server_name': 'my-api',
    'mcp.mount_path': '/mcp',
    # Add debug settings if needed
}

Getting Help

Examples

Complete Examples

See the examples/ directory for complete example applications:

  • Basic Integration: Complete Pyramid application with MCP integration
  • Advanced Usage: Multiple tools, schema validation, and SSE support

Tool Examples

# Simple tool
@tool(name="greet", description="Greet a user")
def greet(name: str) -> str:
    return f"Hello, {name}!"

# Tool with schema validation
from marshmallow import Schema, fields

class UserSchema(Schema):
    name = fields.Str(required=True, validate=lambda x: len(x) > 0)
    age = fields.Int(required=True, validate=lambda x: x > 0)

@tool(name="create_user", description="Create a new user", schema=UserSchema)
def create_user(name: str, age: int) -> dict:
    return {"id": 123, "name": name, "age": age, "created": True}

# Async tool (if using async views)
@tool(name="async_tool", description="Async operation")
async def async_tool(data: str) -> str:
    # Simulate async work
    await asyncio.sleep(0.1)
    return f"Processed: {data}"

Configuration

All Configuration Options

settings = {
    # MCP Server Configuration
    'mcp.server_name': 'my-api',           # Server name (default: 'pyramid-mcp-server')
    'mcp.server_version': '1.0.0',        # Server version (default: '1.0.0')
    'mcp.mount_path': '/mcp',              # Mount path for MCP endpoints (default: '/mcp')
    
    # Protocol Configuration  
    'mcp.enable_sse': 'true',              # Enable Server-Sent Events (default: True)
    'mcp.enable_http': 'true',             # Enable HTTP protocol (default: True)
    
    # Route Discovery (planned feature)
    'mcp.include_patterns': 'api/*, users/*',  # Routes to include as tools
    'mcp.exclude_patterns': 'internal/*',      # Routes to exclude from tools
    
    # Advanced Options
    'mcp.auto_commit': 'true',             # Auto-commit configuration (default: True)
    'mcp.strict_mode': 'false',            # Strict mode for validation (default: False)
}

Development

Setup Development Environment

# Clone the repository
git clone https://github.com/your-org/pyramid-mcp
cd pyramid-mcp

# Install with development dependencies
make install

# Or manually with poetry
poetry install
poetry shell

Running Tests

# Run all tests
make test

# Run with coverage
make test-coverage

# Run specific test types
make test-unit         # Unit tests only
make test-integration  # Integration tests only

# Run tests with pytest directly
poetry run pytest -v
poetry run pytest --cov=pyramid_mcp --cov-report=html

Code Quality

# Run all quality checks
make check

# Individual commands
make format    # Format code with black
make lint      # Lint with ruff
make type      # Type check with mypy

Making Changes

  1. Create a new branch: git checkout -b feature/your-feature
  2. Make your changes
  3. Add tests for new functionality
  4. Run the test suite: make test
  5. Check code quality: make check
  6. Commit your changes: git commit -m "Add your feature"
  7. Push and create a pull request

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Ways to Contribute

  • 🐛 Report bugs by creating issues
  • 💡 Suggest features through discussions
  • 📖 Improve documentation
  • 🧪 Write tests to improve coverage
  • 🔧 Fix bugs and implement features
  • 📝 Write examples and tutorials

Changelog

See CHANGELOG.md for version history and changes.

License

MIT License - see LICENSE file for details.

Related Projects

Acknowledgments


⭐ If you find this project useful, please consider giving it a star on GitHub! ⭐

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyramid_mcp-0.0.4.tar.gz (33.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyramid_mcp-0.0.4-py3-none-any.whl (33.5 kB view details)

Uploaded Python 3

File details

Details for the file pyramid_mcp-0.0.4.tar.gz.

File metadata

  • Download URL: pyramid_mcp-0.0.4.tar.gz
  • Upload date:
  • Size: 33.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for pyramid_mcp-0.0.4.tar.gz
Algorithm Hash digest
SHA256 63762e572749a93545f5c04ffbe5d8664e9ccb48d1cadbac496e06cb3810f00e
MD5 682471e3118a31de1014b13b0c5d90dc
BLAKE2b-256 a20305e6e03bd6e5853ea0934601d03c7c6b557003a8650950d650728e0e2439

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyramid_mcp-0.0.4.tar.gz:

Publisher: on-release-pypi.yml on cartaorobbin/pyramid-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyramid_mcp-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: pyramid_mcp-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 33.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for pyramid_mcp-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 c3cda34f80cddab62f95111a0a5b1e2feba1af7c404b8f51766e23a3c4cc76e0
MD5 d49009e0fceb51e415c48a7979262f66
BLAKE2b-256 e485e920944782ec90de2a1a9e8206db989413a59598c6fd9dc112f968c04416

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyramid_mcp-0.0.4-py3-none-any.whl:

Publisher: on-release-pypi.yml on cartaorobbin/pyramid-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page