viyv-mcp


Nameviyv-mcp JSON
Version 0.1.14 PyPI version JSON
download
home_pageNone
SummaryA simple wrapper library for FastMCP + Starlette
upload_time2025-10-11 09:14:05
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseMIT
keywords mcp fastmcp starlette uvicorn
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # viyv_mcp

**viyv_mcp** is a production-ready Python wrapper around [FastMCP](https://github.com/jlowin/fastmcp) and [Starlette](https://www.starlette.io/) that simplifies creating MCP (Model Context Protocol) servers with minimal boilerplate.

[![PyPI version](https://badge.fury.io/py/viyv_mcp.svg)](https://badge.fury.io/py/viyv_mcp)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Version](https://img.shields.io/badge/version-0.1.10-green.svg)](https://pypi.org/project/viyv_mcp/)

## ๐Ÿš€ Quick Start

```bash
# 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
```python
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
```python
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
```json
// 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)
```bash
# 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

```bash
# 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)

```python
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

```python
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

```python
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

```python
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

```python
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:

```python
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:**

```json
// 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

```bash
# 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

```python
# 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
```python
# 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()
```

```bash
# Run with Gunicorn
gunicorn test_app:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000
```

#### Docker Deployment
```dockerfile
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
```bash
# 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
```bash
# 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](CONTRIBUTING.md).

### Development Setup

```bash
# 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](LICENSE) file for details.

## ๐Ÿ‘ฅ Authors

- **Hiroki Takezawa** - [BrainFiber](https://github.com/BrainFiber)

## ๐Ÿ™ Acknowledgments

- Built on [FastMCP](https://github.com/jlowin/fastmcp) by jlowin
- Powered by [Starlette](https://www.starlette.io/) ASGI framework
- Implements [Model Context Protocol](https://modelcontextprotocol.io/) specification
- Slack integration via [Slack Bolt](https://slack.dev/bolt-python/)
- OpenAI integration via [OpenAI Agents SDK](https://github.com/openai/agents-sdk)

## ๐Ÿ“ฎ Support

- ๐Ÿ“ง Email: hiroki.takezawa@brainfiber.net
- ๐Ÿ› Issues: [GitHub Issues](https://github.com/BrainFiber/viyv_mcp/issues)
- ๐Ÿ’ฌ Discussions: [GitHub Discussions](https://github.com/BrainFiber/viyv_mcp/discussions)
- ๐Ÿ“– Documentation: [Wiki](https://github.com/BrainFiber/viyv_mcp/wiki)

## ๐Ÿšฆ 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.13 (Latest)
- ๐Ÿ“‚ **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

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "viyv-mcp",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "mcp, fastmcp, starlette, uvicorn",
    "author": null,
    "author_email": "hiroki takezawa <hiroki.takezawa@brainfiber.net>",
    "download_url": "https://files.pythonhosted.org/packages/3a/e7/85bde5d3a40953cc9d9e92b3f421d8a376afa34acef0dd38a7e1aa73c070/viyv_mcp-0.1.14.tar.gz",
    "platform": null,
    "description": "# viyv_mcp\n\n**viyv_mcp** is a production-ready Python wrapper around [FastMCP](https://github.com/jlowin/fastmcp) and [Starlette](https://www.starlette.io/) that simplifies creating MCP (Model Context Protocol) servers with minimal boilerplate.\n\n[![PyPI version](https://badge.fury.io/py/viyv_mcp.svg)](https://badge.fury.io/py/viyv_mcp)\n[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Version](https://img.shields.io/badge/version-0.1.10-green.svg)](https://pypi.org/project/viyv_mcp/)\n\n## \ud83d\ude80 Quick Start\n\n```bash\n# Install the package\npip install viyv_mcp\n\n# Create a new MCP server project\ncreate-viyv-mcp new my_mcp_server\n\n# Navigate to the project and install dependencies\ncd my_mcp_server\nuv sync\n\n# Run the server\nuv run python main.py\n```\n\nYour MCP server is now running at `http://localhost:8000` \ud83c\udf89\n\n## \u2728 Key Features\n\n### \ud83d\udee0\ufe0f Simple Tool Creation\n```python\nfrom viyv_mcp import tool\n\n@tool(description=\"Add two numbers\")\ndef add(a: int, b: int) -> int:\n    return a + b\n```\n\n### \ud83e\udd16 Agent Support with OpenAI Integration\n```python\nfrom viyv_mcp import agent\nfrom viyv_mcp.openai_bridge import build_function_tools\n\n@agent(name=\"calculator\", use_tools=[\"add\", \"subtract\"])\nasync def calculator_agent(query: str) -> str:\n    tools = build_function_tools(use_tools=[\"add\", \"subtract\"])\n    # Agent implementation using OpenAI SDK\n    return f\"Result: {result}\"\n```\n\n### \ud83c\udf09 External MCP Server Bridge\n```json\n// app/mcp_server_configs/filesystem.json\n{\n  \"command\": \"npx\",\n  \"args\": [\"@modelcontextprotocol/server-filesystem\", \"/workspace\"],\n  \"env\": {\n    \"API_KEY\": \"$API_KEY\"  // Environment variable interpolation\n  },\n  \"cwd\": \"/path/to/working/dir\",  // Optional\n  \"tags\": [\"filesystem\", \"io\"]     // Optional: for filtering\n}\n```\n\n### \ud83d\ude80 Production-Ready Multi-Worker Support (New in v0.1.10)\n```bash\n# Enable stateless HTTP mode for multi-worker deployments\nSTATELESS_HTTP=true uv run python main.py\n\n# Deploy with Gunicorn (recommended for production)\nuv pip install gunicorn\nSTATELESS_HTTP=true uv run gunicorn main:app \\\n  -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000\n```\n\n### \ud83d\udd17 Built-in Integrations\n- **Slack**: Full event handling, file management, thread context\n- **OpenAI Agents SDK**: Seamless function calling bridge\n- **ChatGPT**: Compatible with required `search`/`fetch` tools\n- **Custom FastAPI Endpoints**: Mount additional APIs with `@entry`\n\n## \ud83d\udce6 Installation\n\n```bash\n# Basic installation\npip install viyv_mcp\n\n# With all optional dependencies\npip install \"viyv_mcp[slack,openai]\"\n```\n\n## \ud83d\udcc1 Project Structure\n\nWhen you create a new project with `create-viyv-mcp new my_project`:\n\n```\nmy_project/\n\u251c\u2500\u2500 main.py                # Server entry point\n\u251c\u2500\u2500 pyproject.toml         # Dependencies (managed by uv)\n\u251c\u2500\u2500 Dockerfile             # Production-ready container\n\u251c\u2500\u2500 .env                   # Environment variables\n\u2514\u2500\u2500 app/\n    \u251c\u2500\u2500 config.py          # Configuration management\n    \u251c\u2500\u2500 tools/             # MCP tools (@tool decorator)\n    \u251c\u2500\u2500 resources/         # MCP resources (@resource decorator)\n    \u251c\u2500\u2500 prompts/           # MCP prompts (@prompt decorator)\n    \u251c\u2500\u2500 agents/            # AI agents (@agent decorator)\n    \u251c\u2500\u2500 entries/           # Custom HTTP endpoints (@entry decorator)\n    \u2514\u2500\u2500 mcp_server_configs/ # External MCP server configurations\n```\n\n## \ud83d\udcbb Advanced Usage Examples\n\n### Tools with Runtime Context (Slack Integration)\n\n```python\nfrom viyv_mcp import tool\nfrom viyv_mcp.run_context import RunContext\nfrom agents import RunContextWrapper\n\ndef register(mcp):\n    @tool(description=\"Get user info from context\")\n    def get_user_info(\n        wrapper: RunContextWrapper[RunContext],\n        user_id: str\n    ) -> dict:\n        \"\"\"Get user information from Slack context\"\"\"\n        context = wrapper.context\n        if context and hasattr(context, 'slack_event'):\n            # Access Slack event data\n            return {\"user\": context.slack_event.get(\"user\"), \"channel\": context.channel}\n        return {\"user\": user_id, \"source\": \"direct\"}\n```\n\n### Creating Resources with URI Templates\n\n```python\nfrom viyv_mcp import resource\n\ndef register(mcp):\n    @resource(\"database://{table}/{id}\")\n    def get_record(table: str, id: str) -> dict:\n        \"\"\"Fetch a database record by table and ID\"\"\"\n        # Your database logic here\n        return {\"table\": table, \"id\": id, \"data\": \"...\"}\n```\n\n### Prompts with Parameters\n\n```python\nfrom viyv_mcp import prompt\nfrom typing import Annotated\nfrom pydantic import Field\n\ndef register(mcp):\n    @prompt(\"code_review\")\n    def code_review_prompt(\n        language: Annotated[str, Field(description=\"Programming language\")],\n        code: Annotated[str, Field(description=\"Code to review\")]\n    ) -> str:\n        return f\"\"\"\n        Please review this {language} code:\n        ```{language}\n        {code}\n        ```\n        Focus on: performance, security, and best practices.\n        \"\"\"\n```\n\n### Slack Bot with File Handling\n\n```python\nfrom viyv_mcp import entry\nfrom viyv_mcp.app.adapters.slack_adapter import SlackAdapter\nfrom viyv_mcp.run_context import RunContext\n\n@entry(\"/slack\")\ndef create_slack_app():\n    adapter = SlackAdapter(\n        bot_token=os.getenv(\"SLACK_BOT_TOKEN\"),\n        signing_secret=os.getenv(\"SLACK_SIGNING_SECRET\"),\n        context_cls=RunContext,\n        handle_files=True,  # Enable file upload/download\n        build_thread_history=True,  # Include thread context\n    )\n    return adapter.as_fastapi_app()\n```\n\n### ChatGPT-Compatible Tools\n\n```python\nfrom viyv_mcp import tool\n\ndef register(mcp):\n    # Required for ChatGPT integration\n    @tool(description=\"Search for information\")\n    def search(query: str) -> list:\n        \"\"\"Search tool required by ChatGPT\"\"\"\n        results = perform_search(query)\n        return [{\"resource_link\": f\"resource://{r.id}\", \"title\": r.title} for r in results]\n\n    @tool(description=\"Fetch resource by ID\")\n    def fetch(id: str) -> dict:\n        \"\"\"Fetch tool required by ChatGPT (note: 'id' not 'uri')\"\"\"\n        return get_resource_by_id(id)\n```\n\n### \ud83d\udcc2 Tool Grouping (New in v0.1.13)\n\nOrganize tools into groups for better discoverability and UI presentation:\n\n```python\nfrom viyv_mcp import tool\n\ndef register(mcp):\n    @tool(\n        description=\"Add two numbers\",\n        group=\"\u8a08\u7b97\u30c4\u30fc\u30eb\",  # Group name\n        title=\"\u52a0\u7b97\"         # UI display name (optional)\n    )\n    def add(a: int, b: int) -> int:\n        return a + b\n\n    @tool(\n        description=\"Subtract two numbers\",\n        group=\"\u8a08\u7b97\u30c4\u30fc\u30eb\"  # Same group\n    )\n    def subtract(a: int, b: int) -> int:\n        return a - b\n\n    @tool(\n        description=\"Delete a file\",\n        group=\"\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\",\n        destructive=True  # Destructive operation hint\n    )\n    def delete_file(path: str) -> bool:\n        import os\n        os.remove(path)\n        return True\n```\n\n**External MCP Server Grouping:**\n\n```json\n// app/mcp_server_configs/filesystem.json\n{\n  \"command\": \"npx\",\n  \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/workspace\"],\n  \"group\": \"\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\",  // Apply to all tools\n  \"group_map\": {                 // Override per tool (optional)\n    \"read_file\": \"\u30d5\u30a1\u30a4\u30eb\u64cd\u4f5c/\u8aad\u307f\u8fbc\u307f\",\n    \"write_file\": \"\u30d5\u30a1\u30a4\u30eb\u64cd\u4f5c/\u66f8\u304d\u8fbc\u307f\"\n  }\n}\n```\n\n**How it works:**\n- Group information is stored in `_meta.viyv.group` (vendor namespace)\n- MCP clients can use groups for organized display\n- Backward compatible: tools without groups work normally\n\n## \ud83d\udd27 Configuration\n\n### Environment Variables\n\n```bash\n# Server Configuration\nHOST=0.0.0.0                    # Server host (default: 127.0.0.1)\nPORT=8000                        # Server port (default: 8000)\nSTATELESS_HTTP=true              # Enable stateless mode for multi-worker\n\n# Directory Configuration\nBRIDGE_CONFIG_DIR=app/mcp_server_configs  # External MCP configs\nSTATIC_DIR=static/images                  # Static file serving\n\n# Integration Keys (optional)\nSLACK_BOT_TOKEN=xoxb-...        # Slack bot token\nSLACK_SIGNING_SECRET=...        # Slack signing secret\nOPENAI_API_KEY=sk-...           # OpenAI API key\n```\n\n### Configuration Class\n\n```python\n# app/config.py\nfrom viyv_mcp.app.config import Config\n\nclass MyConfig(Config):\n    # Inherit base configuration\n\n    @staticmethod\n    def get_stateless_http():\n        \"\"\"Get stateless HTTP setting from environment\"\"\"\n        env_val = os.getenv(\"STATELESS_HTTP\", \"\").lower()\n        if env_val in (\"true\", \"1\", \"yes\", \"on\"):\n            return True\n        elif env_val in (\"false\", \"0\", \"no\", \"off\"):\n            return False\n        return None  # Use FastMCP default\n```\n\n## \ud83c\udfd7\ufe0f Architecture & Advanced Features\n\n### ASGI-Level Routing (SSE Streaming Fix)\nviyv_mcp implements custom ASGI routing to fix SSE streaming issues:\n- Direct `/mcp` path routing bypasses Starlette middleware\n- Ensures proper Server-Sent Events handling\n- Compatible with FastMCP's streaming protocol\n\n### Dynamic Tool Injection\n- Tools are refreshed on every request\n- Agents always have access to the latest tools\n- Supports runtime tool filtering with tags\n\n### RunContextWrapper Pattern\n- Signature manipulation for dual compatibility\n- Works with both FastMCP and OpenAI Agents SDK\n- Provides access to runtime context (Slack events, user info)\n\n### External MCP Server Management\n- Child process management with stdio communication\n- Automatic tool/resource/prompt registration\n- Environment variable interpolation in configs\n- Tag-based filtering for selective tool inclusion\n\n### Production Deployment Features\n\n#### Stateless HTTP Mode\n- No session ID requirements\n- Perfect for load-balanced environments\n- Enable with `STATELESS_HTTP=true`\n\n#### Multi-Worker Deployment\n```python\n# test_app.py - Create a module for Gunicorn\nfrom viyv_mcp import ViyvMCP\nfrom app.config import Config\n\nstateless_http = Config.get_stateless_http()\napp = ViyvMCP(\"Production Server\", stateless_http=stateless_http).get_app()\n```\n\n```bash\n# Run with Gunicorn\ngunicorn test_app:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000\n```\n\n#### Docker Deployment\n```dockerfile\nFROM python:3.10-slim\nWORKDIR /app\nCOPY . .\nRUN pip install uv && uv sync\nCMD [\"uv\", \"run\", \"gunicorn\", \"main:app\", \"-w\", \"4\", \"-k\", \"uvicorn.workers.UvicornWorker\", \"-b\", \"0.0.0.0:8000\"]\n```\n\n## \ud83d\udcca Performance Optimization\n\n### Caching Strategies\n- Tools are cached per request\n- External MCP connections are persistent\n- Static file serving with efficient caching headers\n\n### Resource Management\n- Automatic cleanup of external MCP processes\n- Connection pooling for external services\n- Graceful shutdown handling\n\n### Monitoring & Debugging\n```bash\n# Enable debug logging\nLOG_LEVEL=DEBUG uv run python main.py\n\n# Health check endpoint\ncurl http://localhost:8000/health\n```\n\n## \ud83d\udd0d Troubleshooting\n\n### Common Issues\n\n#### SSE Streaming Not Working\n- Ensure no middleware interferes with `/mcp` path\n- Check ASGI routing configuration\n- Verify FastMCP version >= 2.12.3\n\n#### Multi-Worker Startup Failures\n- Enable `STATELESS_HTTP=true` for multi-worker mode\n- Use Gunicorn instead of uvicorn's `--workers` flag\n- Check for asyncio event loop conflicts\n\n#### External MCP Server Issues\n```bash\n# Check external server logs\ntail -f logs/external_mcp.log\n\n# Verify command exists\nwhich npx\n\n# Test configuration\ncat app/mcp_server_configs/test.json | jq .\n```\n\n#### Protocol Compatibility\n- Use MCP protocol version 2024-11-05\n- Pydantic v2 compatibility is patched automatically\n- Check `mcp_initialize_fix.py` for validation patches\n\n## \ud83d\udcda Examples\n\nComplete working examples in the `example/` directory:\n\n- **`claude_code_mcp`**: Claude Code CLI integration\n- **`test`**: Comprehensive example with all features\n  - Slack integration\n  - OpenAI Agents\n  - External MCP servers\n  - Custom endpoints\n\n## \ud83e\udd1d Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md).\n\n### Development Setup\n\n```bash\n# Clone the repository\ngit clone https://github.com/BrainFiber/viyv_mcp\ncd viyv_mcp\n\n# Install in development mode\npip install -e .\n\n# Run tests\npytest\n\n# Build package\npython -m build\n\n# Run example project\ncd example/test\nuv sync\nSTATELESS_HTTP=true uv run python main.py\n```\n\n### Testing Guidelines\n- Add sample implementations in `test/` directory\n- Test with both session and stateless modes\n- Verify Slack and OpenAI integrations\n- Check external MCP server bridging\n\n## \ud83d\udcc4 License\n\nMIT License - see the [LICENSE](LICENSE) file for details.\n\n## \ud83d\udc65 Authors\n\n- **Hiroki Takezawa** - [BrainFiber](https://github.com/BrainFiber)\n\n## \ud83d\ude4f Acknowledgments\n\n- Built on [FastMCP](https://github.com/jlowin/fastmcp) by jlowin\n- Powered by [Starlette](https://www.starlette.io/) ASGI framework\n- Implements [Model Context Protocol](https://modelcontextprotocol.io/) specification\n- Slack integration via [Slack Bolt](https://slack.dev/bolt-python/)\n- OpenAI integration via [OpenAI Agents SDK](https://github.com/openai/agents-sdk)\n\n## \ud83d\udcee Support\n\n- \ud83d\udce7 Email: hiroki.takezawa@brainfiber.net\n- \ud83d\udc1b Issues: [GitHub Issues](https://github.com/BrainFiber/viyv_mcp/issues)\n- \ud83d\udcac Discussions: [GitHub Discussions](https://github.com/BrainFiber/viyv_mcp/discussions)\n- \ud83d\udcd6 Documentation: [Wiki](https://github.com/BrainFiber/viyv_mcp/wiki)\n\n## \ud83d\udea6 Roadmap\n\n- [ ] WebSocket support for real-time communication\n- [ ] Built-in authentication/authorization\n- [ ] Tool versioning and migration support\n- [ ] Performance profiling dashboard\n- [ ] Plugin system for custom integrations\n- [ ] GraphQL endpoint support\n\n## \ud83d\udcc8 Changelog\n\n### v0.1.13 (Latest)\n- \ud83d\udcc2 **Tool Grouping**: Organize tools with `group` parameter in `@tool` and `@agent` decorators\n- \ud83c\udff7\ufe0f **Vendor Namespace**: Uses `_meta.viyv.group` for MCP spec compliance\n- \ud83c\udf09 **External MCP Grouping**: Support `group` and `group_map` in `mcp_server_configs/*.json`\n- \u2728 **Optional Parameters**: Added `title` and `destructive` hints\n- \ud83d\udd04 **Backward Compatible**: Tools without groups work normally\n- \ud83d\udcda Enhanced templates and documentation with grouping examples\n\n### v0.1.10\n- \u2728 Added stateless HTTP support for multi-worker deployments\n- \ud83d\udd27 Improved ASGI-level routing for SSE streaming\n- \ud83d\udce6 Updated FastMCP to 2.12.3 for better compatibility\n- \ud83d\udc1b Fixed Pydantic v2 validation issues\n- \ud83d\udcda Enhanced documentation and examples\n\n### v0.1.9\n- \ud83c\udf09 External MCP server bridging with tags and filtering\n- \ud83d\udd04 Dynamic tool refresh on every request\n- \ud83d\udcdd RunContextWrapper pattern for dual compatibility\n\n### v0.1.8\n- \ud83e\udd16 OpenAI Agents SDK integration\n- \ud83d\udcac Slack adapter with file handling\n- \ud83c\udfaf ChatGPT-compatible tool requirements\n\n---\n\nMade with \u2764\ufe0f by the viyv_mcp community\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A simple wrapper library for FastMCP + Starlette",
    "version": "0.1.14",
    "project_urls": {
        "Homepage": "https://github.com/BrainFiber/viyv_mcp",
        "Repository": "https://github.com/BrainFiber/viyv_mcp"
    },
    "split_keywords": [
        "mcp",
        " fastmcp",
        " starlette",
        " uvicorn"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "1af84333620ff6c0b51c4fdaa8d521ec734c71898f750d844ced1cd712c39c1b",
                "md5": "3375b8474c1d1fbf1ade20beafe67b64",
                "sha256": "88cfd05fa63eccc12cd244ae659a30f8ddc6d605c32a9cfb25ea6e6dabc74b4f"
            },
            "downloads": -1,
            "filename": "viyv_mcp-0.1.14-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "3375b8474c1d1fbf1ade20beafe67b64",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 53396,
            "upload_time": "2025-10-11T09:14:03",
            "upload_time_iso_8601": "2025-10-11T09:14:03.709174Z",
            "url": "https://files.pythonhosted.org/packages/1a/f8/4333620ff6c0b51c4fdaa8d521ec734c71898f750d844ced1cd712c39c1b/viyv_mcp-0.1.14-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "3ae785bde5d3a40953cc9d9e92b3f421d8a376afa34acef0dd38a7e1aa73c070",
                "md5": "0a888be3b98790471269262538867a0c",
                "sha256": "1a7245073ec1ad9586eebacd3cb564486d43df0366c80cf77bb166963d679185"
            },
            "downloads": -1,
            "filename": "viyv_mcp-0.1.14.tar.gz",
            "has_sig": false,
            "md5_digest": "0a888be3b98790471269262538867a0c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 47216,
            "upload_time": "2025-10-11T09:14:05",
            "upload_time_iso_8601": "2025-10-11T09:14:05.199500Z",
            "url": "https://files.pythonhosted.org/packages/3a/e7/85bde5d3a40953cc9d9e92b3f421d8a376afa34acef0dd38a7e1aa73c070/viyv_mcp-0.1.14.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-11 09:14:05",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "BrainFiber",
    "github_project": "viyv_mcp",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "viyv-mcp"
}
        
Elapsed time: 0.99097s