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

๐Ÿค– Agent Support with OpenAI Integration

from viyv_mcp import agent
from viyv_mcp.openai_bridge import build_function_tools

@agent(name="calculator", use_tools=["add", "subtract"])
async def calculator_agent(query: str) -> str:
    tools = build_function_tools(use_tools=["add", "subtract"])
    # Agent implementation using OpenAI SDK
    return f"Result: {result}"

๐ŸŒ‰ 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

๐Ÿ”— Built-in Integrations

  • Slack: Full event handling, file management, thread context
  • OpenAI Agents SDK: Seamless function calling bridge
  • ChatGPT: Compatible with required search/fetch tools
  • Custom FastAPI Endpoints: Mount additional APIs with @entry

๐Ÿ“ฆ Installation

# Basic installation
pip install viyv_mcp

# With all optional dependencies
pip install "viyv_mcp[slack,openai]"

๐Ÿ“ 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

Tools with Runtime Context (Slack Integration)

from viyv_mcp import tool
from viyv_mcp.run_context import RunContext
from agents import RunContextWrapper

def register(mcp):
    @tool(description="Get user info from context")
    def get_user_info(
        wrapper: RunContextWrapper[RunContext],
        user_id: str
    ) -> dict:
        """Get user information from Slack context"""
        context = wrapper.context
        if context and hasattr(context, 'slack_event'):
            # Access Slack event data
            return {"user": context.slack_event.get("user"), "channel": context.channel}
        return {"user": user_id, "source": "direct"}

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.
        """

Slack Bot with File Handling

from viyv_mcp import entry
from viyv_mcp.app.adapters.slack_adapter import SlackAdapter
from viyv_mcp.run_context import RunContext

@entry("/slack")
def create_slack_app():
    adapter = SlackAdapter(
        bot_token=os.getenv("SLACK_BOT_TOKEN"),
        signing_secret=os.getenv("SLACK_SIGNING_SECRET"),
        context_cls=RunContext,
        handle_files=True,  # Enable file upload/download
        build_thread_history=True,  # Include thread context
    )
    return adapter.as_fastapi_app()

ChatGPT-Compatible Tools

from viyv_mcp import tool

def register(mcp):
    # Required for ChatGPT integration
    @tool(description="Search for information")
    def search(query: str) -> list:
        """Search tool required by ChatGPT"""
        results = perform_search(query)
        return [{"resource_link": f"resource://{r.id}", "title": r.title} for r in results]

    @tool(description="Fetch resource by ID")
    def fetch(id: str) -> dict:
        """Fetch tool required by ChatGPT (note: 'id' not 'uri')"""
        return get_resource_by_id(id)

๐Ÿ“‚ 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

# Integration Keys (optional)
SLACK_BOT_TOKEN=xoxb-...        # Slack bot token
SLACK_SIGNING_SECRET=...        # Slack signing secret
OPENAI_API_KEY=sk-...           # OpenAI API key

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

RunContextWrapper Pattern

  • Signature manipulation for dual compatibility
  • Works with both FastMCP and OpenAI Agents SDK
  • Provides access to runtime context (Slack events, user info)

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
    • Slack integration
    • OpenAI Agents
    • 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
  • Verify Slack and OpenAI integrations
  • 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
  • ๐Ÿ“ RunContextWrapper pattern for dual compatibility

v0.1.8

  • ๐Ÿค– OpenAI Agents SDK integration
  • ๐Ÿ’ฌ Slack adapter with file handling
  • ๐ŸŽฏ ChatGPT-compatible tool requirements

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-0.1.17.tar.gz (48.2 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-0.1.17-py3-none-any.whl (54.2 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for viyv_mcp-0.1.17.tar.gz
Algorithm Hash digest
SHA256 cf2a16e38005ed6ed19c13c453b50cab1ca36b246b1f9d8746716f0b89a1c1b1
MD5 e2d033d6507b43e7a42e676ff6ae2676
BLAKE2b-256 381afd70b15d22d1351e422496d81417d3e627460d01e64b9246b8f6eec6ea04

See more details on using hashes here.

File details

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

File metadata

  • Download URL: viyv_mcp-0.1.17-py3-none-any.whl
  • Upload date:
  • Size: 54.2 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-0.1.17-py3-none-any.whl
Algorithm Hash digest
SHA256 5e6b00b1ccedc7dffbea56f87715df891f1883176983715ee0d4c45b17a8d754
MD5 f06f0ff953374622e7e4179d321e0406
BLAKE2b-256 fd87dd777255fab94d5a4cd1053fbbc9c059d35fa4370f9446d9477f7a763f47

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