Skip to main content

A simple wrapper library for FastMCP + Starlette

Project description

viyv_mcp

viyv_mcp is a production-ready Python wrapper around FastMCP and Starlette that simplifies creating MCP (Model Context Protocol) servers with minimal boilerplate.

PyPI version Python 3.10+ License: MIT Version

๐Ÿš€ Quick Start

# Install the package
pip install viyv_mcp

# Create a new MCP server project
create-viyv-mcp new my_mcp_server

# Navigate to the project and install dependencies
cd my_mcp_server
uv sync

# Run the server
uv run python main.py

Your MCP server is now running at http://localhost:8000 ๐ŸŽ‰

โœจ Key Features

๐Ÿ› ๏ธ Simple Tool Creation

from viyv_mcp import tool

@tool(description="Add two numbers")
def add(a: int, b: int) -> int:
    return a + b

๐ŸŒ‰ External MCP Server Bridge

// app/mcp_server_configs/filesystem.json
{
  "command": "npx",
  "args": ["@modelcontextprotocol/server-filesystem", "/workspace"],
  "env": {
    "API_KEY": "$API_KEY"  // Environment variable interpolation
  },
  "cwd": "/path/to/working/dir",  // Optional
  "tags": ["filesystem", "io"]     // Optional: for filtering
}

๐Ÿš€ Production-Ready Multi-Worker Support (New in v0.1.10)

# Enable stateless HTTP mode for multi-worker deployments
STATELESS_HTTP=true uv run python main.py

# Deploy with Gunicorn (recommended for production)
uv pip install gunicorn
STATELESS_HTTP=true uv run gunicorn main:app \
  -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000

๐Ÿ”’ JWT Authentication & Access Control

# Tools with security metadata
@tool(
    description="Query salary",
    namespace="hr",                 # Visible only to hr agents
    security_level="confidential",  # Requires confidential+ clearance
)
def query_salary(employee_id: str) -> str:
    return f"Salary: $100,000"
# Generate JWT for an agent
python -m viyv_mcp generate-jwt \
  --sub hr-agent --clearance confidential --namespace hr \
  --trust common --expires 24h --secret "$SECRET"
  • Namespace: Controls tool visibility (tools/list filtering)
  • Security Level: Controls tool executability (tools/call clearance check)
  • Modes: bypass (dev), authenticated (JWT), deny_all (default safe)
  • Both transports: Works for stdio (.mcp.json) and HTTP

๐Ÿ”— Built-in Integrations

  • Custom FastAPI Endpoints: Mount additional APIs with @entry

๐Ÿ“ฆ Installation

# Basic installation
pip install viyv_mcp

# With optional security config (YAML support)
pip install "viyv_mcp[security]"

๐Ÿ“ Project Structure

When you create a new project with create-viyv-mcp new my_project:

my_project/
โ”œโ”€โ”€ main.py                # Server entry point
โ”œโ”€โ”€ pyproject.toml         # Dependencies (managed by uv)
โ”œโ”€โ”€ Dockerfile             # Production-ready container
โ”œโ”€โ”€ .env                   # Environment variables
โ””โ”€โ”€ app/
    โ”œโ”€โ”€ config.py          # Configuration management
    โ”œโ”€โ”€ tools/             # MCP tools (@tool decorator)
    โ”œโ”€โ”€ resources/         # MCP resources (@resource decorator)
    โ”œโ”€โ”€ prompts/           # MCP prompts (@prompt decorator)
    โ”œโ”€โ”€ agents/            # AI agents (@agent decorator)
    โ”œโ”€โ”€ entries/           # Custom HTTP endpoints (@entry decorator)
    โ””โ”€โ”€ mcp_server_configs/ # External MCP server configurations

๐Ÿ’ป Advanced Usage Examples

Creating Resources with URI Templates

from viyv_mcp import resource

def register(mcp):
    @resource("database://{table}/{id}")
    def get_record(table: str, id: str) -> dict:
        """Fetch a database record by table and ID"""
        # Your database logic here
        return {"table": table, "id": id, "data": "..."}

Prompts with Parameters

from viyv_mcp import prompt
from typing import Annotated
from pydantic import Field

def register(mcp):
    @prompt("code_review")
    def code_review_prompt(
        language: Annotated[str, Field(description="Programming language")],
        code: Annotated[str, Field(description="Code to review")]
    ) -> str:
        return f"""
        Please review this {language} code:
        ```{language}
        {code}
        ```
        Focus on: performance, security, and best practices.
        """

๐Ÿ“‚ Tool Grouping (New in v0.1.13)

Organize tools into groups for better discoverability and UI presentation:

from viyv_mcp import tool

def register(mcp):
    @tool(
        description="Add two numbers",
        group="่จˆ็ฎ—ใƒ„ใƒผใƒซ",  # Group name
        title="ๅŠ ็ฎ—"         # UI display name (optional)
    )
    def add(a: int, b: int) -> int:
        return a + b

    @tool(
        description="Subtract two numbers",
        group="่จˆ็ฎ—ใƒ„ใƒผใƒซ"  # Same group
    )
    def subtract(a: int, b: int) -> int:
        return a - b

    @tool(
        description="Delete a file",
        group="ใƒ•ใ‚กใ‚คใƒซใ‚ทใ‚นใƒ†ใƒ ",
        destructive=True  # Destructive operation hint
    )
    def delete_file(path: str) -> bool:
        import os
        os.remove(path)
        return True

External MCP Server Grouping:

// app/mcp_server_configs/filesystem.json
{
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"],
  "group": "ใƒ•ใ‚กใ‚คใƒซใ‚ทใ‚นใƒ†ใƒ ",  // Apply to all tools
  "group_map": {                 // Override per tool (optional)
    "read_file": "ใƒ•ใ‚กใ‚คใƒซๆ“ไฝœ/่ชญใฟ่พผใฟ",
    "write_file": "ใƒ•ใ‚กใ‚คใƒซๆ“ไฝœ/ๆ›ธใ่พผใฟ"
  }
}

How it works:

  • Group information is stored in _meta.viyv.group (vendor namespace)
  • MCP clients can use groups for organized display
  • Backward compatible: tools without groups work normally

๐Ÿ”ง Configuration

Environment Variables

# Server Configuration
HOST=0.0.0.0                    # Server host (default: 127.0.0.1)
PORT=8000                        # Server port (default: 8000)
STATELESS_HTTP=true              # Enable stateless mode for multi-worker

# Directory Configuration
BRIDGE_CONFIG_DIR=app/mcp_server_configs  # External MCP configs
STATIC_DIR=static/images                  # Static file serving

Configuration Class

# app/config.py
from viyv_mcp.app.config import Config

class MyConfig(Config):
    # Inherit base configuration

    @staticmethod
    def get_stateless_http():
        """Get stateless HTTP setting from environment"""
        env_val = os.getenv("STATELESS_HTTP", "").lower()
        if env_val in ("true", "1", "yes", "on"):
            return True
        elif env_val in ("false", "0", "no", "off"):
            return False
        return None  # Use FastMCP default

๐Ÿ—๏ธ Architecture & Advanced Features

ASGI-Level Routing (SSE Streaming Fix)

viyv_mcp implements custom ASGI routing to fix SSE streaming issues:

  • Direct /mcp path routing bypasses Starlette middleware
  • Ensures proper Server-Sent Events handling
  • Compatible with FastMCP's streaming protocol

Dynamic Tool Injection

  • Tools are refreshed on every request
  • Agents always have access to the latest tools
  • Supports runtime tool filtering with tags

External MCP Server Management

  • Child process management with stdio communication
  • Automatic tool/resource/prompt registration
  • Environment variable interpolation in configs
  • Tag-based filtering for selective tool inclusion

Production Deployment Features

Stateless HTTP Mode

  • No session ID requirements
  • Perfect for load-balanced environments
  • Enable with STATELESS_HTTP=true

Multi-Worker Deployment

# test_app.py - Create a module for Gunicorn
from viyv_mcp import ViyvMCP
from app.config import Config

stateless_http = Config.get_stateless_http()
app = ViyvMCP("Production Server", stateless_http=stateless_http).get_app()
# Run with Gunicorn
gunicorn test_app:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000

Docker Deployment

FROM python:3.10-slim
WORKDIR /app
COPY . .
RUN pip install uv && uv sync
CMD ["uv", "run", "gunicorn", "main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "-b", "0.0.0.0:8000"]

๐Ÿ“Š Performance Optimization

Caching Strategies

  • Tools are cached per request
  • External MCP connections are persistent
  • Static file serving with efficient caching headers

Resource Management

  • Automatic cleanup of external MCP processes
  • Connection pooling for external services
  • Graceful shutdown handling

Monitoring & Debugging

# Enable debug logging
LOG_LEVEL=DEBUG uv run python main.py

# Health check endpoint
curl http://localhost:8000/health

๐Ÿ” Troubleshooting

Common Issues

SSE Streaming Not Working

  • Ensure no middleware interferes with /mcp path
  • Check ASGI routing configuration
  • Verify FastMCP version >= 2.12.3

Multi-Worker Startup Failures

  • Enable STATELESS_HTTP=true for multi-worker mode
  • Use Gunicorn instead of uvicorn's --workers flag
  • Check for asyncio event loop conflicts

External MCP Server Issues

# Check external server logs
tail -f logs/external_mcp.log

# Verify command exists
which npx

# Test configuration
cat app/mcp_server_configs/test.json | jq .

Protocol Compatibility

  • Use MCP protocol version 2024-11-05
  • Pydantic v2 compatibility is patched automatically
  • Check mcp_initialize_fix.py for validation patches

๐Ÿ“š Examples

Complete working examples in the example/ directory:

  • claude_code_mcp: Claude Code CLI integration
  • test: Comprehensive example with all features
    • External MCP servers
    • Custom endpoints

๐Ÿค Contributing

We welcome contributions! Please see our Contributing Guide.

Development Setup

# Clone the repository
git clone https://github.com/BrainFiber/viyv_mcp
cd viyv_mcp

# Install in development mode
pip install -e .

# Run tests
pytest

# Build package
python -m build

# Run example project
cd example/test
uv sync
STATELESS_HTTP=true uv run python main.py

Testing Guidelines

  • Add sample implementations in test/ directory
  • Test with both session and stateless modes
  • Check external MCP server bridging

๐Ÿ“„ License

MIT License - see the LICENSE file for details.

๐Ÿ‘ฅ Authors

๐Ÿ™ Acknowledgments

๐Ÿ“ฎ Support

๐Ÿšฆ Roadmap

  • WebSocket support for real-time communication
  • Built-in authentication/authorization
  • Tool versioning and migration support
  • Performance profiling dashboard
  • Plugin system for custom integrations
  • GraphQL endpoint support

๐Ÿ“ˆ Changelog

v0.1.14 (Latest - 2025-10-13)

  • ๐Ÿ“š Implementation Examples: Added comprehensive tool grouping examples in example/test
    • 9 internal tools with group organization (Math, Statistics, Web Search, Image Tools)
    • Real-world Playwright MCP server configuration (20 browser automation tools)
  • ๐Ÿ“– Enhanced Documentation:
    • GROUPING_IMPLEMENTATION.md - detailed implementation report
    • app/mcp_server_configs/README.md - external MCP server grouping guide
    • Sample configuration files for learning
  • โœ… Verified Implementation: All examples tested and working with MCP Inspector
  • ๐ŸŽฏ Makes tool grouping feature (v0.1.13) immediately usable with practical examples

v0.1.13

  • ๐Ÿ“‚ Tool Grouping: Organize tools with group parameter in @tool and @agent decorators
  • ๐Ÿท๏ธ Vendor Namespace: Uses _meta.viyv.group for MCP spec compliance
  • ๐ŸŒ‰ External MCP Grouping: Support group and group_map in mcp_server_configs/*.json
  • โœจ Optional Parameters: Added title and destructive hints
  • ๐Ÿ”„ Backward Compatible: Tools without groups work normally
  • ๐Ÿ“š Enhanced templates and documentation with grouping examples

v0.1.10

  • โœจ Added stateless HTTP support for multi-worker deployments
  • ๐Ÿ”ง Improved ASGI-level routing for SSE streaming
  • ๐Ÿ“ฆ Updated FastMCP to 2.12.3 for better compatibility
  • ๐Ÿ› Fixed Pydantic v2 validation issues
  • ๐Ÿ“š Enhanced documentation and examples

v0.1.9

  • ๐ŸŒ‰ External MCP server bridging with tags and filtering
  • ๐Ÿ”„ Dynamic tool refresh on every request

Made with โค๏ธ by the viyv_mcp community

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

viyv_mcp-1.0.1.tar.gz (63.7 kB view details)

Uploaded Source

Built Distribution

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

viyv_mcp-1.0.1-py3-none-any.whl (64.3 kB view details)

Uploaded Python 3

File details

Details for the file viyv_mcp-1.0.1.tar.gz.

File metadata

  • Download URL: viyv_mcp-1.0.1.tar.gz
  • Upload date:
  • Size: 63.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.7

File hashes

Hashes for viyv_mcp-1.0.1.tar.gz
Algorithm Hash digest
SHA256 ff3bc505b60efb0087ae93cf860b6e109201f68589d0d99f19b957d26184db2a
MD5 259d0fc95929f8309318d44e518a7508
BLAKE2b-256 5fb2d701f372274d2b91c7cfe6d685993d08a27fcbb04c88ed8e3b459fa2a820

See more details on using hashes here.

File details

Details for the file viyv_mcp-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: viyv_mcp-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 64.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.7

File hashes

Hashes for viyv_mcp-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c7332ecdc1328d96c526fd35e092b0bbae837594bdb29d4091a486fd6df2761e
MD5 518302af3876c19d298aea585a1d5855
BLAKE2b-256 5753fa50eed08d294b8fa48d8a8d3738cbcd9ffb0dfd6e7b1d20fccc2f804a82

See more details on using hashes here.

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