# Pyramid MCP
[](https://badge.fury.io/py/pyramid-mcp)
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
[](https://github.com/your-org/pyramid-mcp/actions)
[](https://codecov.io/gh/your-org/pyramid-mcp)
## โ ๏ธ Development Status
**๐ง This project is currently under active development and is not yet ready for production use.**
- ๐งช **Experimental**: APIs and features may change without notice
- ๐ **Breaking Changes**: Expect breaking changes between releases
- ๐ **Not Production Ready**: Use at your own risk in production environments
- ๐ **Known Issues**: Some features may be incomplete or have bugs
**For Production Use**: Please wait for the 1.0.0 stable release or use the project for experimentation and development only.
---
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
- ๐ **Authentication Parameters**: Support for Bearer token and Basic auth as tool parameters (uses `mcp_security` parameter by default, configurable)
- ๐ก๏ธ **Security Filtering**: Automatic filtering of tools based on user permissions and ACL contexts (enabled by default)
- โ๏ธ **Settings-based Configuration**: Configure via Pyramid settings
- ๐ **Route Discovery**: Automatic discovery of Pyramid routes (configurable)
- ๐ก **Multiple Protocols**: Support for HTTP and SSE (Server-Sent Events)
- ๐๏ธ **Enable/Disable Control**: Easily enable or disable MCP endpoints via configuration (perfect for staging โ production workflows)
- ๐งช **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)
```bash
pip install pyramid-mcp
```
### From Source
```bash
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
```python
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
```python
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
```bash
# 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}
}
}'
```
## Security Parameter Name
**Key Concept**: The security parameter name is **`mcp_security`** by default, but can be configured to any name you prefer.
This allows you to:
- Use existing security parameters from your application (e.g., `pcm_security`, `api_security`)
- Avoid duplicating security configuration
- Maintain consistency across your application
```python
# Default: uses 'mcp_security' parameter
@view_config(route_name='secure', renderer='json', mcp_security='bearer')
# Configured: uses your existing parameter name
settings = {'mcp.security_parameter': 'pcm_security'}
# Now use: pcm_security='BearerAuth'
@view_config(route_name='secure', renderer='json', pcm_security='BearerAuth')
```
**See the [Configurable Security Parameter](#configurable-security-parameter) section for complete details.**
### Configuration
Configure pyramid_mcp using Pyramid settings:
```python
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 Configuration
'mcp.route_discovery.enabled': 'false', # Enable automatic route discovery
'mcp.route_discovery.include_patterns': 'api/*', # Routes to include as tools
'mcp.route_discovery.exclude_patterns': 'internal/*', # Routes to exclude from tools
}
config = Configurator(settings=settings)
config.include('pyramid_mcp')
```
### Accessing MCP in Views
```python
@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
```python
# Basic inclusion
config.include('pyramid_mcp')
# Access MCP instance
mcp = config.get_mcp() # From configurator
mcp = request.mcp # From request (in views)
```
### Tool Registration
```python
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}"
# With authentication parameters
from pyramid_mcp.security import BearerAuthSchema
@tool(
name="secure_tool",
description="Tool that requires authentication",
security=BearerAuthSchema()
)
def secure_tool(pyramid_request, data: str, auth_token: str) -> dict:
"""Tool with Bearer token authentication."""
# Access authentication headers from the standard request headers
auth_header = pyramid_request.headers.get("Authorization", "")
return {"data": data, "authenticated": bool(auth_header)}
```
### Manual Usage (Advanced)
```python
from pyramid_mcp import PyramidMCP, MCPConfiguration
from pyramid_mcp.security import BearerAuthSchema
# 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
# Register tool with authentication
@pyramid_mcp.tool(
name="secure_manual_tool",
description="Secure tool with authentication",
security=BearerAuthSchema()
)
def secure_manual_tool(pyramid_request, data: str, auth_token: str) -> dict:
auth_header = pyramid_request.headers.get("Authorization", "")
return {"data": data, "authenticated": bool(auth_header)}
# 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
```bash
# 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
```bash
ModuleNotFoundError: No module named 'pyramid_mcp'
```
**Solution**: Make sure pyramid-mcp is installed in your active Python environment:
```bash
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:
```python
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
- ๐ [Documentation](https://your-org.github.io/pyramid-mcp)
- ๐ [Report Issues](https://github.com/your-org/pyramid-mcp/issues)
- ๐ฌ [Discussions](https://github.com/your-org/pyramid-mcp/discussions)
- ๐ง [Contact the maintainers](https://github.com/your-org/pyramid-mcp/discussions)
## Examples
### Complete Examples
See the `examples/` directory for complete example applications:
- **[Basic Integration](examples/pyramid_app_example.py)**: Complete Pyramid application with MCP integration
- **Advanced Usage**: Multiple tools, schema validation, and SSE support
### Tool Examples
```python
# 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}
# Tool with Bearer token authentication
from pyramid_mcp.security import BearerAuthSchema
@tool(
name="secure_api_request",
description="Make authenticated API request",
security=BearerAuthSchema()
)
def secure_api_request(pyramid_request, endpoint: str, auth_token: str) -> dict:
# Auth headers are automatically created and available in request headers
auth_header = pyramid_request.headers.get("Authorization", "")
# auth_header = "Bearer <token>"
return {"endpoint": endpoint, "status": "authenticated"}
# Tool with Basic authentication
from pyramid_mcp.security import BasicAuthSchema
@tool(
name="database_query",
description="Query database with credentials",
security=BasicAuthSchema()
)
def database_query(pyramid_request, query: str, username: str, password: str) -> dict:
# Auth headers are automatically created and available in request headers
auth_header = pyramid_request.headers.get("Authorization", "")
# auth_header = "Basic <base64_encoded_credentials>"
return {"query": query, "status": "executed"}
# 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
```python
settings = {
# MCP Server Configuration
'mcp.server_name': 'my-api', # Server name (default: 'pyramid-mcp')
'mcp.server_version': '1.0.0', # Server version (default: '1.0.0')
'mcp.mount_path': '/mcp', # Mount path for MCP endpoints (default: '/mcp')
'mcp.enable': 'true', # Enable MCP endpoints (default: True)
# Security Configuration
'mcp.security_parameter': 'mcp_security', # Name of security parameter in views (default: 'mcp_security')
'mcp.add_security_predicate': 'true', # Register security view predicate (default: True)
'mcp.expose_auth_as_params': 'true', # Expose auth credentials as tool parameters (default: True)
# Protocol Configuration
'mcp.enable_sse': 'true', # Enable Server-Sent Events (default: True)
'mcp.enable_http': 'true', # Enable HTTP protocol (default: True)
# Route Discovery Configuration
'mcp.route_discovery.enabled': 'false', # Enable automatic route discovery (default: False)
'mcp.route_discovery.include_patterns': 'api/*', # Routes to include as tools
'mcp.route_discovery.exclude_patterns': 'internal/*', # Routes to exclude from tools
}
```
### Enable/Disable MCP Endpoints
The `mcp.enable` configuration allows you to control whether MCP endpoints are created when including the pyramid_mcp plugin. This is particularly useful for staging โ production workflows.
#### Basic Usage
```python
# Enable MCP endpoints (default behavior)
settings = {
'mcp.enable': 'true' # or True, 'yes', 'on', '1'
}
# Disable MCP endpoints
settings = {
'mcp.enable': 'false' # or False, 'no', 'off', '0'
}
```
#### When `mcp.enable=true` (default)
- โ
**Full MCP functionality**: HTTP endpoints, tool registration, route discovery
- โ
**Production ready**: All features available for client connections
- โ
**Backward compatible**: Default behavior, existing code continues to work
#### When `mcp.enable=false`
- โ
**View predicates only**: `mcp_description`, `llm_context_hint`, `mcp_security` predicates still registered
- โ **No HTTP endpoints**: `/mcp` endpoints are not created
- โ **No tool registration**: `@tool` decorators are not processed
- โ **No route discovery**: Automatic route discovery is skipped
#### Staging โ Production Workflow
This configuration enables a clean staging โ production deployment pattern:
```python
# staging.ini - Test views with predicates, no MCP endpoints exposed
[app:main]
mcp.enable = false
mcp.server_name = staging-api
# production.ini - Full MCP functionality
[app:main]
mcp.enable = true
mcp.server_name = production-api
```
**Staging Benefits:**
- Test that views work with MCP predicates (`mcp_description`, `llm_context_hint`, etc.)
- No accidental exposure of MCP endpoints in staging
- Validate configuration without enabling external access
**Production Benefits:**
- Clean activation of MCP functionality
- Same codebase, different configuration
- Zero downtime deployment when enabling MCP
### Authentication Parameters Feature
Pyramid MCP supports tools that require authentication credentials to be passed as parameters rather than HTTP headers. This is particularly useful for Claude AI clients that cannot pass HTTP headers.
#### Controlling Authentication Parameter Exposure
You can control whether authentication parameters are exposed in tool schemas using the `mcp.expose_auth_as_params` configuration:
```python
# Expose auth credentials as tool parameters (default)
settings = {
'mcp.expose_auth_as_params': 'true'
}
# Don't expose auth credentials as parameters (use HTTP headers instead)
settings = {
'mcp.expose_auth_as_params': 'false'
}
```
**When `expose_auth_as_params=true` (default):**
- Authentication parameters appear in the tool's input schema
- Clients (like Claude) can see and provide auth credentials as regular parameters
- Useful for clients that cannot send HTTP headers
**When `expose_auth_as_params=false`:**
- Authentication parameters are NOT included in the tool's input schema
- Tools rely on traditional HTTP header authentication
- Useful when you want to use standard HTTP authentication patterns
#### Bearer Token Authentication
```python
from pyramid_mcp import tool
from pyramid_mcp.security import BearerAuthSchema
@tool(
name="secure_api_call",
description="Call a secure API endpoint",
security=BearerAuthSchema()
)
def secure_api_call(pyramid_request, data: str, auth_token: str) -> dict:
"""Call a secure API with Bearer token authentication."""
# Authentication headers are automatically available in request headers
auth_header = pyramid_request.headers.get("Authorization", "")
# auth_header = "Bearer <token>"
# Make API call with authentication
return {"success": True, "data": data}
```
#### HTTP Basic Authentication
```python
from pyramid_mcp import tool
from pyramid_mcp.security import BasicAuthSchema
@tool(
name="secure_ftp_access",
description="Access FTP server with credentials",
security=BasicAuthSchema()
)
def secure_ftp_access(pyramid_request, path: str, username: str, password: str) -> dict:
"""Access FTP server with basic authentication."""
# Authentication headers are automatically available in request headers
auth_header = pyramid_request.headers.get("Authorization", "")
# auth_header = "Basic <base64_encoded_credentials>"
# Use credentials for FTP access
return {"path": path, "status": "connected"}
```
#### How It Works
1. **Schema Integration**: Authentication parameters are automatically merged into the tool's JSON schema
2. **Parameter Extraction**: Credentials are extracted from tool arguments during execution
3. **Header Generation**: Authentication headers are created and added to the subrequest headers
4. **Parameter Cleanup**: Authentication parameters are removed from the arguments passed to your handler function
5. **Validation**: Credentials are validated before tool execution
#### Example MCP Call with Authentication
```bash
# Call a tool with Bearer token authentication
curl -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"id": 1,
"params": {
"name": "secure_api_call",
"arguments": {
"data": "hello world",
"auth_token": "your-bearer-token-here"
}
}
}'
# Call a tool with Basic authentication
curl -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"id": 2,
"params": {
"name": "secure_ftp_access",
"arguments": {
"path": "/home/user",
"username": "myuser",
"password": "mypassword"
}
}
}'
```
#### Security Considerations
- **Credentials are passed as parameters**: Authentication data is sent in the request body, not HTTP headers
- **No credential logging**: Authentication parameters are removed from handler arguments before execution
- **Validation**: Credentials are validated before tool execution
- **Standard HTTP headers**: Credentials are converted to standard HTTP Authorization headers for your use
### Configurable Security Parameter
**Parameter Name**: The security parameter name is **`mcp_security`** by default, but can be configured to any name you prefer.
By default, pyramid-mcp looks for the `mcp_security` parameter in your view configurations to determine what authentication parameters to add to MCP tools. However, you can configure this to use any existing security parameter from your application, avoiding the need to duplicate security configuration.
```python
# Default usage with 'mcp_security' parameter
@view_config(route_name='secure', renderer='json', mcp_security='bearer')
def secure_view(request):
return {"data": "secure"}
# Or configure to use your existing parameter name
settings = {
'mcp.security_parameter': 'pcm_security', # Use existing parameter name
}
config = Configurator(settings=settings)
config.include('pyramid_mcp')
# Now use your existing parameter name
@view_config(route_name='secure', renderer='json', pcm_security='BearerAuth')
def secure_view(request):
return {"data": "secure"}
```
#### Using Existing Security Parameters
If your application already uses security parameters like `pcm_security`, `api_security`, or any other custom parameter name, you can configure pyramid-mcp to use them:
```python
# Configure pyramid-mcp to use your existing security parameter
settings = {
'mcp.security_parameter': 'pcm_security', # Use existing parameter name
'mcp.server_name': 'my-api',
'mcp.mount_path': '/mcp'
}
config = Configurator(settings=settings)
config.include('pyramid_mcp')
```
#### Example with Custom Security Parameter
```python
from pyramid.view import view_config
from pyramid.config import Configurator
# Configure to use 'api_auth' as the security parameter
settings = {
'mcp.security_parameter': 'api_auth',
'mcp.server_name': 'my-enterprise-api'
}
config = Configurator(settings=settings)
config.include('pyramid_mcp')
# Your existing views with custom security parameter
@view_config(
route_name='secure_endpoint',
renderer='json',
api_auth='bearer' # Uses your existing parameter name
)
def secure_endpoint_view(request):
return {"message": "secure data"}
@view_config(
route_name='admin_endpoint',
renderer='json',
api_auth='basic' # Uses your existing parameter name
)
def admin_endpoint_view(request):
return {"admin": "data"}
```
#### Benefits of Configurable Security Parameter
1. **No Duplication**: Reuse existing security configuration instead of adding new `mcp_security` parameters
2. **Consistency**: Use the same security parameter names across your entire application
3. **Integration**: Seamlessly integrate with existing security systems and middleware
4. **Flexibility**: Change security parameter names without modifying view code
#### Backward Compatibility
The default behavior remains unchanged. If you don't configure `mcp.security_parameter`, pyramid-mcp will continue to use `mcp_security` as the parameter name:
```python
# Default behavior (no configuration needed)
@view_config(route_name='secure', renderer='json', mcp_security='bearer')
def secure_view(request):
return {"data": "secure"}
```
#### Advanced Security Integration
You can integrate with complex security systems by using descriptive parameter names:
```python
# Configure for enterprise security system
settings = {
'mcp.security_parameter': 'enterprise_auth_level',
'mcp.server_name': 'enterprise-api'
}
@view_config(
route_name='financial_data',
renderer='json',
enterprise_auth_level='bearer' # Integrates with existing system
)
def financial_data_view(request):
return {"financial": "data"}
```
#### Disabling Security Predicate Registration
**Parameter**: `mcp.add_security_predicate`
**Type**: Boolean
**Default**: `true`
In some cases, you may want to disable pyramid-mcp's automatic registration of the security view predicate. This is useful when:
1. **Library Conflicts**: Another library (like pycornmarsh) already registers the same predicate name
2. **Manual Registration**: You want to register the predicate manually with custom behavior
3. **Testing**: You need to control predicate registration timing for testing
```python
# Disable automatic predicate registration
settings = {
'mcp.security_parameter': 'pcm_security',
'mcp.add_security_predicate': 'false', # Disable automatic registration
}
config = Configurator(settings=settings)
config.include('pyramid_mcp')
# The 'pcm_security' predicate won't be registered by pyramid-mcp
# Your application or another library must register it
```
**Use Cases**:
- **Cornice Integration**: When using Cornice with existing security predicates
- **Custom Predicates**: When you need predicates with custom validation logic
- **Conflict Resolution**: When multiple libraries try to register the same predicate
## Development
### Setup Development Environment
```bash
# 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
```bash
# 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
```bash
# 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](CONTRIBUTING.md) 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](CHANGELOG.md) for version history and changes.
## License
MIT License - see [LICENSE](LICENSE) file for details.
## Related Projects
- ๐ [Model Context Protocol (MCP)](https://github.com/modelcontextprotocol/python-sdk) - The official MCP Python SDK
- ๐ [FastAPI MCP](https://github.com/your-org/fastapi-mcp) - Similar integration for FastAPI
- ๐๏ธ [Pyramid](https://trypyramid.com/) - The Pyramid web framework
## Acknowledgments
- Thanks to the [Pyramid](https://trypyramid.com/) team for the excellent web framework
- Inspired by [FastAPI MCP](https://github.com/your-org/fastapi-mcp)
- Built with the [Model Context Protocol](https://github.com/modelcontextprotocol/python-sdk)
---
**โญ If you find this project useful, please consider giving it a star on GitHub! โญ**
Raw data
{
"_id": null,
"home_page": null,
"name": "pyramid-mcp",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": "pyramid, mcp, model-context-protocol, web, framework, ai, llm",
"author": "pyramid-mcp contributors",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/8b/c7/a4403bd6253b6ea6a228c2486d1658a004c3fe66701e73cb79fa25508529/pyramid_mcp-0.0.26.tar.gz",
"platform": null,
"description": "# Pyramid MCP\n\n[](https://badge.fury.io/py/pyramid-mcp)\n[](https://www.python.org/downloads/)\n[](https://opensource.org/licenses/MIT)\n[](https://github.com/your-org/pyramid-mcp/actions)\n[](https://codecov.io/gh/your-org/pyramid-mcp)\n\n## \u26a0\ufe0f Development Status\n\n**\ud83d\udea7 This project is currently under active development and is not yet ready for production use.**\n\n- \ud83e\uddea **Experimental**: APIs and features may change without notice\n- \ud83d\udd04 **Breaking Changes**: Expect breaking changes between releases\n- \ud83d\udccb **Not Production Ready**: Use at your own risk in production environments\n- \ud83d\udc1b **Known Issues**: Some features may be incomplete or have bugs\n\n**For Production Use**: Please wait for the 1.0.0 stable release or use the project for experimentation and development only.\n\n---\n\nPyramid 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.\n\n## Features\n\n- \ud83d\udd0c **Pyramid Plugin**: Easy integration with `config.include('pyramid_mcp')`\n- \ud83d\udee0\ufe0f **Tool Registration**: Simple `@tool` decorator for registering MCP tools\n- \ud83d\udd10 **Authentication Parameters**: Support for Bearer token and Basic auth as tool parameters (uses `mcp_security` parameter by default, configurable)\n- \ud83d\udee1\ufe0f **Security Filtering**: Automatic filtering of tools based on user permissions and ACL contexts (enabled by default)\n- \u2699\ufe0f **Settings-based Configuration**: Configure via Pyramid settings\n- \ud83d\udd0d **Route Discovery**: Automatic discovery of Pyramid routes (configurable)\n- \ud83d\udce1 **Multiple Protocols**: Support for HTTP and SSE (Server-Sent Events)\n- \ud83c\udf9b\ufe0f **Enable/Disable Control**: Easily enable or disable MCP endpoints via configuration (perfect for staging \u2192 production workflows)\n- \ud83e\uddea **Well Tested**: Comprehensive test suite with pytest\n- \ud83d\udcda **Type Hints**: Full type annotations for better IDE support\n- \ud83d\ude80 **Easy to Use**: Minimal setup required\n\n## Installation\n\n### From PyPI (Recommended)\n\n```bash\npip install pyramid-mcp\n```\n\n### From Source\n\n```bash\ngit clone https://github.com/your-org/pyramid-mcp\ncd pyramid-mcp\npip install -e .\n```\n\n### Requirements\n\n- Python 3.9+\n- Pyramid 2.0+\n- Marshmallow 3.22+ (for schema validation)\n\n## Quick Start\n\n### Basic Usage\n\n```python\nfrom pyramid.config import Configurator\nfrom pyramid.view import view_config\nfrom pyramid_mcp import tool\n\n# Include pyramid_mcp in your Pyramid application\ndef create_app():\n config = Configurator(settings={\n 'mcp.server_name': 'my-api',\n 'mcp.mount_path': '/mcp'\n })\n \n # Include the pyramid_mcp plugin\n config.include('pyramid_mcp')\n \n # Add your regular Pyramid routes\n config.add_route('home', '/')\n config.scan()\n \n return config.make_wsgi_app()\n\n# Register MCP tools using the decorator\n@tool(name=\"calculate\", description=\"Perform basic math operations\")\ndef calculate(operation: str, a: float, b: float) -> float:\n \"\"\"Perform basic math operations.\"\"\"\n if operation == \"add\":\n return a + b\n elif operation == \"subtract\":\n return a - b\n elif operation == \"multiply\":\n return a * b\n elif operation == \"divide\":\n if b == 0:\n raise ValueError(\"Cannot divide by zero\")\n return a / b\n else:\n raise ValueError(f\"Unknown operation: {operation}\")\n\n@view_config(route_name='home', renderer='json')\ndef home_view(request):\n return {\"message\": \"Hello World\", \"mcp_available\": True}\n```\n\n### Run Your Application\n\n```python\nif __name__ == '__main__':\n from wsgiref.simple_server import make_server\n \n app = create_app()\n server = make_server('0.0.0.0', 8080, app)\n print(\"Server started at http://localhost:8080\")\n print(\"MCP endpoint available at http://localhost:8080/mcp\")\n server.serve_forever()\n```\n\n### Test Your MCP Integration\n\n```bash\n# Initialize MCP connection\ncurl -X POST http://localhost:8080/mcp \\\n -H \"Content-Type: application/json\" \\\n -d '{\"jsonrpc\": \"2.0\", \"method\": \"initialize\", \"id\": 1}'\n\n# List available tools\ncurl -X POST http://localhost:8080/mcp \\\n -H \"Content-Type: application/json\" \\\n -d '{\"jsonrpc\": \"2.0\", \"method\": \"tools/list\", \"id\": 2}'\n\n# Call the calculate tool\ncurl -X POST http://localhost:8080/mcp \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"jsonrpc\": \"2.0\", \n \"method\": \"tools/call\", \n \"id\": 3,\n \"params\": {\n \"name\": \"calculate\",\n \"arguments\": {\"operation\": \"add\", \"a\": 5, \"b\": 3}\n }\n }'\n```\n\n## Security Parameter Name\n\n**Key Concept**: The security parameter name is **`mcp_security`** by default, but can be configured to any name you prefer.\n\nThis allows you to:\n- Use existing security parameters from your application (e.g., `pcm_security`, `api_security`)\n- Avoid duplicating security configuration\n- Maintain consistency across your application\n\n```python\n# Default: uses 'mcp_security' parameter\n@view_config(route_name='secure', renderer='json', mcp_security='bearer')\n\n# Configured: uses your existing parameter name\nsettings = {'mcp.security_parameter': 'pcm_security'}\n# Now use: pcm_security='BearerAuth'\n@view_config(route_name='secure', renderer='json', pcm_security='BearerAuth')\n```\n\n**See the [Configurable Security Parameter](#configurable-security-parameter) section for complete details.**\n\n### Configuration\n\nConfigure pyramid_mcp using Pyramid settings:\n\n```python\nsettings = {\n # MCP Server Configuration\n 'mcp.server_name': 'my-api', # Server name\n 'mcp.server_version': '1.0.0', # Server version\n 'mcp.mount_path': '/mcp', # Mount path for MCP endpoints\n \n # Protocol Configuration \n 'mcp.enable_sse': 'true', # Enable Server-Sent Events\n 'mcp.enable_http': 'true', # Enable HTTP protocol\n \n # Route Discovery Configuration\n 'mcp.route_discovery.enabled': 'false', # Enable automatic route discovery\n 'mcp.route_discovery.include_patterns': 'api/*', # Routes to include as tools\n 'mcp.route_discovery.exclude_patterns': 'internal/*', # Routes to exclude from tools\n}\n\nconfig = Configurator(settings=settings)\nconfig.include('pyramid_mcp')\n```\n\n### Accessing MCP in Views\n\n```python\n@view_config(route_name='mcp_info', renderer='json')\ndef mcp_info_view(request):\n # Access MCP instance through request\n mcp = request.mcp\n \n # Get available tools\n tools = list(mcp.protocol_handler.tools.keys())\n \n return {\n 'server_name': mcp.config.server_name,\n 'available_tools': tools,\n 'mount_path': mcp.config.mount_path\n }\n```\n\n## API Reference\n\n### Plugin Integration\n\n```python\n# Basic inclusion\nconfig.include('pyramid_mcp')\n\n# Access MCP instance\nmcp = config.get_mcp() # From configurator\nmcp = request.mcp # From request (in views)\n```\n\n### Tool Registration\n\n```python\nfrom pyramid_mcp import tool\n\n@tool(name=\"my_tool\", description=\"Tool description\")\ndef my_tool(param1: str, param2: int) -> str:\n \"\"\"Tool implementation.\"\"\"\n return f\"Result: {param1} * {param2}\"\n\n# With schema validation (optional)\nfrom marshmallow import Schema, fields\n\nclass MyToolSchema(Schema):\n param1 = fields.Str(required=True)\n param2 = fields.Int(required=True)\n\n@tool(name=\"validated_tool\", schema=MyToolSchema)\ndef validated_tool(param1: str, param2: int) -> str:\n return f\"Validated: {param1} + {param2}\"\n\n# With authentication parameters\nfrom pyramid_mcp.security import BearerAuthSchema\n\n@tool(\n name=\"secure_tool\", \n description=\"Tool that requires authentication\",\n security=BearerAuthSchema()\n)\ndef secure_tool(pyramid_request, data: str, auth_token: str) -> dict:\n \"\"\"Tool with Bearer token authentication.\"\"\"\n # Access authentication headers from the standard request headers\n auth_header = pyramid_request.headers.get(\"Authorization\", \"\")\n return {\"data\": data, \"authenticated\": bool(auth_header)}\n```\n\n### Manual Usage (Advanced)\n\n```python\nfrom pyramid_mcp import PyramidMCP, MCPConfiguration\nfrom pyramid_mcp.security import BearerAuthSchema\n\n# Manual configuration\nconfig = Configurator()\nmcp_config = MCPConfiguration(\n server_name=\"my-server\",\n mount_path=\"/mcp\"\n)\n\npyramid_mcp = PyramidMCP(config, config=mcp_config)\n\n# Register tools manually\n@pyramid_mcp.tool(\"manual_tool\")\ndef manual_tool(x: int) -> int:\n return x * 2\n\n# Register tool with authentication\n@pyramid_mcp.tool(\n name=\"secure_manual_tool\",\n description=\"Secure tool with authentication\",\n security=BearerAuthSchema()\n)\ndef secure_manual_tool(pyramid_request, data: str, auth_token: str) -> dict:\n auth_header = pyramid_request.headers.get(\"Authorization\", \"\")\n return {\"data\": data, \"authenticated\": bool(auth_header)}\n\n# Mount manually (with auto_commit=False for more control)\npyramid_mcp.mount(auto_commit=False)\nconfig.commit()\n```\n\n## MCP Protocol\n\nOnce configured, your Pyramid application will expose MCP endpoints:\n\n- **HTTP**: `POST /mcp` (or your configured mount path)\n- **SSE**: `GET /mcp/sse` (if enabled)\n\n### Example MCP Requests\n\n```bash\n# Initialize MCP connection\ncurl -X POST http://localhost:8080/mcp \\\n -H \"Content-Type: application/json\" \\\n -d '{\"jsonrpc\": \"2.0\", \"method\": \"initialize\", \"id\": 1}'\n\n# List available tools\ncurl -X POST http://localhost:8080/mcp \\\n -H \"Content-Type: application/json\" \\\n -d '{\"jsonrpc\": \"2.0\", \"method\": \"tools/list\", \"id\": 2}'\n\n# Call a tool\ncurl -X POST http://localhost:8080/mcp \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"jsonrpc\": \"2.0\", \n \"method\": \"tools/call\", \n \"id\": 3,\n \"params\": {\n \"name\": \"calculate\",\n \"arguments\": {\"operation\": \"add\", \"a\": 5, \"b\": 3}\n }\n }'\n```\n\n## Troubleshooting\n\n### Common Issues\n\n#### \"Module not found\" error\n```bash\nModuleNotFoundError: No module named 'pyramid_mcp'\n```\n**Solution**: Make sure pyramid-mcp is installed in your active Python environment:\n```bash\npip list | grep pyramid-mcp\npip install pyramid-mcp\n```\n\n#### MCP endpoints not accessible\n**Problem**: Getting 404 when accessing `/mcp` endpoint.\n\n**Solutions**:\n1. Ensure you've included the plugin: `config.include('pyramid_mcp')`\n2. Check your mount path setting: `'mcp.mount_path': '/mcp'`\n3. Verify the configurator is properly committed if using manual setup\n\n#### Tools not showing up in `/tools/list`\n**Problem**: Registered tools don't appear in MCP tools list.\n\n**Solutions**:\n1. Ensure tools are registered before mounting: `pyramid_mcp.mount()`\n2. Check that `config.scan()` is called to discover `@tool` decorators\n3. Verify the tool registration syntax\n\n#### Type validation errors\n**Problem**: Getting validation errors when calling tools.\n\n**Solutions**:\n1. Check parameter types match the function signature\n2. Use Marshmallow schemas for complex validation\n3. Review the MCP request format\n\n### Debug Mode\n\nEnable debug logging to troubleshoot issues:\n\n```python\nimport logging\nlogging.basicConfig(level=logging.DEBUG)\n\n# In your Pyramid settings\nsettings = {\n 'mcp.server_name': 'my-api',\n 'mcp.mount_path': '/mcp',\n # Add debug settings if needed\n}\n```\n\n### Getting Help\n\n- \ud83d\udcd6 [Documentation](https://your-org.github.io/pyramid-mcp)\n- \ud83d\udc1b [Report Issues](https://github.com/your-org/pyramid-mcp/issues)\n- \ud83d\udcac [Discussions](https://github.com/your-org/pyramid-mcp/discussions)\n- \ud83d\udce7 [Contact the maintainers](https://github.com/your-org/pyramid-mcp/discussions)\n\n## Examples\n\n### Complete Examples\n\nSee the `examples/` directory for complete example applications:\n\n- **[Basic Integration](examples/pyramid_app_example.py)**: Complete Pyramid application with MCP integration\n- **Advanced Usage**: Multiple tools, schema validation, and SSE support\n\n### Tool Examples\n\n```python\n# Simple tool\n@tool(name=\"greet\", description=\"Greet a user\")\ndef greet(name: str) -> str:\n return f\"Hello, {name}!\"\n\n# Tool with schema validation\nfrom marshmallow import Schema, fields\n\nclass UserSchema(Schema):\n name = fields.Str(required=True, validate=lambda x: len(x) > 0)\n age = fields.Int(required=True, validate=lambda x: x > 0)\n\n@tool(name=\"create_user\", description=\"Create a new user\", schema=UserSchema)\ndef create_user(name: str, age: int) -> dict:\n return {\"id\": 123, \"name\": name, \"age\": age, \"created\": True}\n\n# Tool with Bearer token authentication\nfrom pyramid_mcp.security import BearerAuthSchema\n\n@tool(\n name=\"secure_api_request\",\n description=\"Make authenticated API request\",\n security=BearerAuthSchema()\n)\ndef secure_api_request(pyramid_request, endpoint: str, auth_token: str) -> dict:\n # Auth headers are automatically created and available in request headers\n auth_header = pyramid_request.headers.get(\"Authorization\", \"\")\n # auth_header = \"Bearer <token>\"\n return {\"endpoint\": endpoint, \"status\": \"authenticated\"}\n\n# Tool with Basic authentication\nfrom pyramid_mcp.security import BasicAuthSchema\n\n@tool(\n name=\"database_query\",\n description=\"Query database with credentials\",\n security=BasicAuthSchema()\n)\ndef database_query(pyramid_request, query: str, username: str, password: str) -> dict:\n # Auth headers are automatically created and available in request headers\n auth_header = pyramid_request.headers.get(\"Authorization\", \"\")\n # auth_header = \"Basic <base64_encoded_credentials>\"\n return {\"query\": query, \"status\": \"executed\"}\n\n# Async tool (if using async views)\n@tool(name=\"async_tool\", description=\"Async operation\")\nasync def async_tool(data: str) -> str:\n # Simulate async work\n await asyncio.sleep(0.1)\n return f\"Processed: {data}\"\n```\n\n## Configuration\n\n### All Configuration Options\n\n```python\nsettings = {\n # MCP Server Configuration\n 'mcp.server_name': 'my-api', # Server name (default: 'pyramid-mcp')\n 'mcp.server_version': '1.0.0', # Server version (default: '1.0.0')\n 'mcp.mount_path': '/mcp', # Mount path for MCP endpoints (default: '/mcp')\n 'mcp.enable': 'true', # Enable MCP endpoints (default: True)\n \n # Security Configuration\n 'mcp.security_parameter': 'mcp_security', # Name of security parameter in views (default: 'mcp_security')\n 'mcp.add_security_predicate': 'true', # Register security view predicate (default: True)\n 'mcp.expose_auth_as_params': 'true', # Expose auth credentials as tool parameters (default: True)\n \n # Protocol Configuration \n 'mcp.enable_sse': 'true', # Enable Server-Sent Events (default: True)\n 'mcp.enable_http': 'true', # Enable HTTP protocol (default: True)\n \n # Route Discovery Configuration\n 'mcp.route_discovery.enabled': 'false', # Enable automatic route discovery (default: False)\n 'mcp.route_discovery.include_patterns': 'api/*', # Routes to include as tools\n 'mcp.route_discovery.exclude_patterns': 'internal/*', # Routes to exclude from tools\n}\n```\n\n### Enable/Disable MCP Endpoints\n\nThe `mcp.enable` configuration allows you to control whether MCP endpoints are created when including the pyramid_mcp plugin. This is particularly useful for staging \u2192 production workflows.\n\n#### Basic Usage\n\n```python\n# Enable MCP endpoints (default behavior)\nsettings = {\n 'mcp.enable': 'true' # or True, 'yes', 'on', '1'\n}\n\n# Disable MCP endpoints \nsettings = {\n 'mcp.enable': 'false' # or False, 'no', 'off', '0'\n}\n```\n\n#### When `mcp.enable=true` (default)\n\n- \u2705 **Full MCP functionality**: HTTP endpoints, tool registration, route discovery\n- \u2705 **Production ready**: All features available for client connections\n- \u2705 **Backward compatible**: Default behavior, existing code continues to work\n\n#### When `mcp.enable=false`\n\n- \u2705 **View predicates only**: `mcp_description`, `llm_context_hint`, `mcp_security` predicates still registered\n- \u274c **No HTTP endpoints**: `/mcp` endpoints are not created\n- \u274c **No tool registration**: `@tool` decorators are not processed\n- \u274c **No route discovery**: Automatic route discovery is skipped\n\n#### Staging \u2192 Production Workflow\n\nThis configuration enables a clean staging \u2192 production deployment pattern:\n\n```python\n# staging.ini - Test views with predicates, no MCP endpoints exposed\n[app:main]\nmcp.enable = false\nmcp.server_name = staging-api\n\n# production.ini - Full MCP functionality\n[app:main] \nmcp.enable = true\nmcp.server_name = production-api\n```\n\n**Staging Benefits:**\n- Test that views work with MCP predicates (`mcp_description`, `llm_context_hint`, etc.)\n- No accidental exposure of MCP endpoints in staging\n- Validate configuration without enabling external access\n\n**Production Benefits:**\n- Clean activation of MCP functionality\n- Same codebase, different configuration\n- Zero downtime deployment when enabling MCP\n\n### Authentication Parameters Feature\n\nPyramid MCP supports tools that require authentication credentials to be passed as parameters rather than HTTP headers. This is particularly useful for Claude AI clients that cannot pass HTTP headers.\n\n#### Controlling Authentication Parameter Exposure\n\nYou can control whether authentication parameters are exposed in tool schemas using the `mcp.expose_auth_as_params` configuration:\n\n```python\n# Expose auth credentials as tool parameters (default)\nsettings = {\n 'mcp.expose_auth_as_params': 'true'\n}\n\n# Don't expose auth credentials as parameters (use HTTP headers instead)\nsettings = {\n 'mcp.expose_auth_as_params': 'false'\n}\n```\n\n**When `expose_auth_as_params=true` (default):**\n- Authentication parameters appear in the tool's input schema\n- Clients (like Claude) can see and provide auth credentials as regular parameters\n- Useful for clients that cannot send HTTP headers\n\n**When `expose_auth_as_params=false`:**\n- Authentication parameters are NOT included in the tool's input schema\n- Tools rely on traditional HTTP header authentication\n- Useful when you want to use standard HTTP authentication patterns\n\n#### Bearer Token Authentication\n\n```python\nfrom pyramid_mcp import tool\nfrom pyramid_mcp.security import BearerAuthSchema\n\n@tool(\n name=\"secure_api_call\",\n description=\"Call a secure API endpoint\",\n security=BearerAuthSchema()\n)\ndef secure_api_call(pyramid_request, data: str, auth_token: str) -> dict:\n \"\"\"Call a secure API with Bearer token authentication.\"\"\"\n # Authentication headers are automatically available in request headers\n auth_header = pyramid_request.headers.get(\"Authorization\", \"\")\n # auth_header = \"Bearer <token>\"\n \n # Make API call with authentication\n return {\"success\": True, \"data\": data}\n```\n\n#### HTTP Basic Authentication\n\n```python\nfrom pyramid_mcp import tool\nfrom pyramid_mcp.security import BasicAuthSchema\n\n@tool(\n name=\"secure_ftp_access\",\n description=\"Access FTP server with credentials\",\n security=BasicAuthSchema()\n)\ndef secure_ftp_access(pyramid_request, path: str, username: str, password: str) -> dict:\n \"\"\"Access FTP server with basic authentication.\"\"\"\n # Authentication headers are automatically available in request headers\n auth_header = pyramid_request.headers.get(\"Authorization\", \"\")\n # auth_header = \"Basic <base64_encoded_credentials>\"\n \n # Use credentials for FTP access\n return {\"path\": path, \"status\": \"connected\"}\n```\n\n#### How It Works\n\n1. **Schema Integration**: Authentication parameters are automatically merged into the tool's JSON schema\n2. **Parameter Extraction**: Credentials are extracted from tool arguments during execution\n3. **Header Generation**: Authentication headers are created and added to the subrequest headers\n4. **Parameter Cleanup**: Authentication parameters are removed from the arguments passed to your handler function\n5. **Validation**: Credentials are validated before tool execution\n\n#### Example MCP Call with Authentication\n\n```bash\n# Call a tool with Bearer token authentication\ncurl -X POST http://localhost:8080/mcp \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"jsonrpc\": \"2.0\", \n \"method\": \"tools/call\", \n \"id\": 1,\n \"params\": {\n \"name\": \"secure_api_call\",\n \"arguments\": {\n \"data\": \"hello world\",\n \"auth_token\": \"your-bearer-token-here\"\n }\n }\n }'\n\n# Call a tool with Basic authentication\ncurl -X POST http://localhost:8080/mcp \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"jsonrpc\": \"2.0\", \n \"method\": \"tools/call\", \n \"id\": 2,\n \"params\": {\n \"name\": \"secure_ftp_access\",\n \"arguments\": {\n \"path\": \"/home/user\",\n \"username\": \"myuser\",\n \"password\": \"mypassword\"\n }\n }\n }'\n```\n\n#### Security Considerations\n\n- **Credentials are passed as parameters**: Authentication data is sent in the request body, not HTTP headers\n- **No credential logging**: Authentication parameters are removed from handler arguments before execution\n- **Validation**: Credentials are validated before tool execution\n- **Standard HTTP headers**: Credentials are converted to standard HTTP Authorization headers for your use\n\n### Configurable Security Parameter\n\n**Parameter Name**: The security parameter name is **`mcp_security`** by default, but can be configured to any name you prefer.\n\nBy default, pyramid-mcp looks for the `mcp_security` parameter in your view configurations to determine what authentication parameters to add to MCP tools. However, you can configure this to use any existing security parameter from your application, avoiding the need to duplicate security configuration.\n\n```python\n# Default usage with 'mcp_security' parameter\n@view_config(route_name='secure', renderer='json', mcp_security='bearer')\ndef secure_view(request):\n return {\"data\": \"secure\"}\n\n# Or configure to use your existing parameter name\nsettings = {\n 'mcp.security_parameter': 'pcm_security', # Use existing parameter name\n}\nconfig = Configurator(settings=settings)\nconfig.include('pyramid_mcp')\n\n# Now use your existing parameter name\n@view_config(route_name='secure', renderer='json', pcm_security='BearerAuth')\ndef secure_view(request):\n return {\"data\": \"secure\"}\n```\n\n#### Using Existing Security Parameters\n\nIf your application already uses security parameters like `pcm_security`, `api_security`, or any other custom parameter name, you can configure pyramid-mcp to use them:\n\n```python\n# Configure pyramid-mcp to use your existing security parameter\nsettings = {\n 'mcp.security_parameter': 'pcm_security', # Use existing parameter name\n 'mcp.server_name': 'my-api',\n 'mcp.mount_path': '/mcp'\n}\n\nconfig = Configurator(settings=settings)\nconfig.include('pyramid_mcp')\n```\n\n#### Example with Custom Security Parameter\n\n```python\nfrom pyramid.view import view_config\nfrom pyramid.config import Configurator\n\n# Configure to use 'api_auth' as the security parameter\nsettings = {\n 'mcp.security_parameter': 'api_auth',\n 'mcp.server_name': 'my-enterprise-api'\n}\n\nconfig = Configurator(settings=settings)\nconfig.include('pyramid_mcp')\n\n# Your existing views with custom security parameter\n@view_config(\n route_name='secure_endpoint',\n renderer='json',\n api_auth='bearer' # Uses your existing parameter name\n)\ndef secure_endpoint_view(request):\n return {\"message\": \"secure data\"}\n\n@view_config(\n route_name='admin_endpoint', \n renderer='json',\n api_auth='basic' # Uses your existing parameter name\n)\ndef admin_endpoint_view(request):\n return {\"admin\": \"data\"}\n```\n\n#### Benefits of Configurable Security Parameter\n\n1. **No Duplication**: Reuse existing security configuration instead of adding new `mcp_security` parameters\n2. **Consistency**: Use the same security parameter names across your entire application\n3. **Integration**: Seamlessly integrate with existing security systems and middleware\n4. **Flexibility**: Change security parameter names without modifying view code\n\n#### Backward Compatibility\n\nThe default behavior remains unchanged. If you don't configure `mcp.security_parameter`, pyramid-mcp will continue to use `mcp_security` as the parameter name:\n\n```python\n# Default behavior (no configuration needed)\n@view_config(route_name='secure', renderer='json', mcp_security='bearer')\ndef secure_view(request):\n return {\"data\": \"secure\"}\n```\n\n#### Advanced Security Integration\n\nYou can integrate with complex security systems by using descriptive parameter names:\n\n```python\n# Configure for enterprise security system\nsettings = {\n 'mcp.security_parameter': 'enterprise_auth_level',\n 'mcp.server_name': 'enterprise-api'\n}\n\n@view_config(\n route_name='financial_data',\n renderer='json', \n enterprise_auth_level='bearer' # Integrates with existing system\n)\ndef financial_data_view(request):\n return {\"financial\": \"data\"}\n```\n\n#### Disabling Security Predicate Registration\n\n**Parameter**: `mcp.add_security_predicate` \n**Type**: Boolean \n**Default**: `true`\n\nIn some cases, you may want to disable pyramid-mcp's automatic registration of the security view predicate. This is useful when:\n\n1. **Library Conflicts**: Another library (like pycornmarsh) already registers the same predicate name\n2. **Manual Registration**: You want to register the predicate manually with custom behavior\n3. **Testing**: You need to control predicate registration timing for testing\n\n```python\n# Disable automatic predicate registration\nsettings = {\n 'mcp.security_parameter': 'pcm_security',\n 'mcp.add_security_predicate': 'false', # Disable automatic registration\n}\n\nconfig = Configurator(settings=settings)\nconfig.include('pyramid_mcp')\n\n# The 'pcm_security' predicate won't be registered by pyramid-mcp\n# Your application or another library must register it\n```\n\n**Use Cases**:\n- **Cornice Integration**: When using Cornice with existing security predicates\n- **Custom Predicates**: When you need predicates with custom validation logic\n- **Conflict Resolution**: When multiple libraries try to register the same predicate\n\n## Development\n\n### Setup Development Environment\n\n```bash\n# Clone the repository\ngit clone https://github.com/your-org/pyramid-mcp\ncd pyramid-mcp\n\n# Install with development dependencies\nmake install\n\n# Or manually with poetry\npoetry install\npoetry shell\n```\n\n### Running Tests\n\n```bash\n# Run all tests\nmake test\n\n# Run with coverage\nmake test-coverage\n\n# Run specific test types\nmake test-unit # Unit tests only\nmake test-integration # Integration tests only\n\n# Run tests with pytest directly\npoetry run pytest -v\npoetry run pytest --cov=pyramid_mcp --cov-report=html\n```\n\n### Code Quality\n\n```bash\n# Run all quality checks\nmake check\n\n# Individual commands\nmake format # Format code with black\nmake lint # Lint with ruff\nmake type # Type check with mypy\n```\n\n### Making Changes\n\n1. Create a new branch: `git checkout -b feature/your-feature`\n2. Make your changes\n3. Add tests for new functionality\n4. Run the test suite: `make test`\n5. Check code quality: `make check`\n6. Commit your changes: `git commit -m \"Add your feature\"`\n7. Push and create a pull request\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.\n\n### Ways to Contribute\n\n- \ud83d\udc1b **Report bugs** by creating issues\n- \ud83d\udca1 **Suggest features** through discussions\n- \ud83d\udcd6 **Improve documentation** \n- \ud83e\uddea **Write tests** to improve coverage\n- \ud83d\udd27 **Fix bugs** and implement features\n- \ud83d\udcdd **Write examples** and tutorials\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for version history and changes.\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Related Projects\n\n- \ud83d\udd17 [Model Context Protocol (MCP)](https://github.com/modelcontextprotocol/python-sdk) - The official MCP Python SDK\n- \ud83d\ude80 [FastAPI MCP](https://github.com/your-org/fastapi-mcp) - Similar integration for FastAPI\n- \ud83c\udfd7\ufe0f [Pyramid](https://trypyramid.com/) - The Pyramid web framework\n\n## Acknowledgments\n\n- Thanks to the [Pyramid](https://trypyramid.com/) team for the excellent web framework\n- Inspired by [FastAPI MCP](https://github.com/your-org/fastapi-mcp)\n- Built with the [Model Context Protocol](https://github.com/modelcontextprotocol/python-sdk)\n\n---\n\n**\u2b50 If you find this project useful, please consider giving it a star on GitHub! \u2b50**\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Model Context Protocol (MCP) integration for Pyramid web framework",
"version": "0.0.26",
"project_urls": {
"Documentation": "https://github.com/cartaorobbin/pyramid-mcp",
"Homepage": "https://github.com/cartaorobbin/pyramid-mcp",
"Repository": "https://github.com/cartaorobbin/pyramid-mcp"
},
"split_keywords": [
"pyramid",
" mcp",
" model-context-protocol",
" web",
" framework",
" ai",
" llm"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "50bd4eee5d0ebc5fc989a8a9ed85fd40536c1d3cb2f145296b39a14849e77e2b",
"md5": "b804bc9cfa52380e3fce58a2379dc04e",
"sha256": "5968ce8fc277ce652d085ab8a949e554357796af6a8f2d4b4778490587faa078"
},
"downloads": -1,
"filename": "pyramid_mcp-0.0.26-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b804bc9cfa52380e3fce58a2379dc04e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 61305,
"upload_time": "2025-10-21T14:31:10",
"upload_time_iso_8601": "2025-10-21T14:31:10.948107Z",
"url": "https://files.pythonhosted.org/packages/50/bd/4eee5d0ebc5fc989a8a9ed85fd40536c1d3cb2f145296b39a14849e77e2b/pyramid_mcp-0.0.26-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "8bc7a4403bd6253b6ea6a228c2486d1658a004c3fe66701e73cb79fa25508529",
"md5": "8193db3b82ac170a2a59b73c1fa98535",
"sha256": "5cee54b0b9d30641462a397cba87149f5f166781bc7d0ef41ebfcd41009e7c32"
},
"downloads": -1,
"filename": "pyramid_mcp-0.0.26.tar.gz",
"has_sig": false,
"md5_digest": "8193db3b82ac170a2a59b73c1fa98535",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 58708,
"upload_time": "2025-10-21T14:31:12",
"upload_time_iso_8601": "2025-10-21T14:31:12.399269Z",
"url": "https://files.pythonhosted.org/packages/8b/c7/a4403bd6253b6ea6a228c2486d1658a004c3fe66701e73cb79fa25508529/pyramid_mcp-0.0.26.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-21 14:31:12",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "cartaorobbin",
"github_project": "pyramid-mcp",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "pyramid-mcp"
}