Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions extensions/fastapi-mcp-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# fastapi-mcp-client

A FastAPI extension for composing MCP tools and skills in AI applications.

## Overview

This extension provides a client for the Model Context Protocol (MCP) that can be composed with FastAPI applications to leverage external tools and capabilities.

## Features

- **MCP client configuration**: Manage MCP servers and tool registration
- **Tool registry**: Typed service for discovering and using MCP tools
- **Integration points**: Easy composition with FastAPI AI apps
- **Environment-based configuration**: Support for `mcp_servers.yaml` or env-driven setup

## Usage

Add the extension to your FastAPI application:

```python
from fastapi import FastAPI
from fastapi_mcp_client import MCPClient

app = FastAPI()

# Initialize MCP client
mcp_client = MCPClient.from_env()

@app.get("/tools")
async def list_tools():
return {"tools": await mcp_client.list_tools()}

@app.post("/tool/{tool_name}")
async def execute_tool(tool_name: str, parameters: dict):
return await mcp_client.execute_tool(tool_name, parameters)
```

## Configuration

### Environment Variables

```env
MCP_SERVERS_FILE=/path/to/mcp_servers.yaml
MCP_CLIENT_ENABLED=true
```

### mcp_servers.yaml Example

```yaml
servers:
- name: "weather-api"
type: "stdio"
command: "python"
args: ["weather_server.py"]
env:
API_KEY: "${WEATHER_API_KEY}"
```

## Testing

Run the test suite:

```bash
pytest extensions/fastapi-mcp-client/tests/test_mcp_client.py -v
```

## License

MIT
26 changes: 26 additions & 0 deletions extensions/fastapi-mcp-client/README.md.append
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## MCP Client Extension

This template includes the `fastapi-mcp-client` extension for composing MCP tools.

### Configuration

Configure MCP servers via environment variables or `mcp_servers.yaml`:

```bash
MCP_SERVERS_FILE=mcp_servers.yaml
MCP_CLIENT_ENABLED=true
```

### Usage

```python
from fastapi import FastAPI
from fastapi_mcp_client import MCPClient

app = FastAPI()
mcp = MCPClient.from_env()

@app.get("/tools")
async def list_tools():
return await mcp.list_tools()
```
17 changes: 17 additions & 0 deletions extensions/fastapi-mcp-client/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[project]
name = "fastapi-mcp-client"
version = "0.1.0"
description = "FastAPI AI extension with MCP client for composing tools and skills"
readme = "README.md"
license = "MIT"
requires-python = ">=3.10"

[project.optional-dependencies]
dev = [
"pytest>=7.0",
"pytest-cov>=4.0",
]

[build-system]
requires = ["setuptools>=65.0"]
build-backend = "setuptools.build_meta"
2 changes: 2 additions & 0 deletions extensions/fastapi-mcp-client/template/.env.example.append
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
MCP_SERVERS_FILE=mcp_servers.yaml
MCP_CLIENT_ENABLED=true
5 changes: 5 additions & 0 deletions extensions/fastapi-mcp-client/template/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# FastAPI MCP client extension
.env
*.pyc
__pycache__/
mcp_servers.yaml
2 changes: 2 additions & 0 deletions extensions/fastapi-mcp-client/template/app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"""FastAPI MCP client extension."""
from fastapi_mcp_client import MCPClient
63 changes: 63 additions & 0 deletions extensions/fastapi-mcp-client/template/app/core/mcp_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""
FastAPI MCP client module.
Provides typed client for Model Context Protocol integration.
"""

import os
from typing import Any, Dict, List, Optional

class MCPClient:
"""Client for Model Context Protocol (MCP).

Provides tool discovery and execution through MCP servers.
"""

def __init__(self, servers: Optional[List[Dict[str, Any]]] = None):
self.config = {"servers": servers or []}
self._tools: Dict[str, Any] = {}

@classmethod
def from_env(cls) -> "MCPClient":
"""Create client from environment variables."""
servers_file = os.environ.get("MCP_SERVERS_FILE", "mcp_servers.yaml")
enabled = os.environ.get("MCP_CLIENT_ENABLED", "true").lower() == "true"

if not enabled or not os.path.exists(servers_file):
return cls()

try:
import yaml
with open(servers_file) as f:
config = yaml.safe_load(f) or {}
return cls(config.get("servers", []))
except ImportError:
return cls()

@classmethod
def from_yaml(cls, path: str) -> "MCPClient":
"""Create client from YAML config file."""
try:
import yaml
with open(path) as f:
config = yaml.safe_load(f) or {}
return cls(config.get("servers", []))
except ImportError:
return cls()

async def list_tools(self) -> List[Dict[str, Any]]:
"""List available MCP tools."""
return [
{"name": s.get("name", "unknown"), "type": s.get("type", "unknown")}
for s in self.config["servers"]
]

async def execute_tool(self, tool_name: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
"""Execute an MCP tool."""
for server in self.config["servers"]:
if server.get("name") == tool_name:
return {
"success": True,
"server": tool_name,
"result": parameters
}
return {"success": False, "error": f"Tool not found: {tool_name}"}
45 changes: 45 additions & 0 deletions extensions/fastapi-mcp-client/template/docs/MCP_CLIENT_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# MCP Client Guide

Guide for using the MCP client extension with FastAPI.

## Overview

The MCP (Model Context Protocol) client extension provides a way to integrate external tools and services into your FastAPI AI application.

## Configuration

### Environment Variables

```env
MCP_SERVERS_FILE=mcp_servers.yaml
MCP_CLIENT_ENABLED=true
```

### mcp_servers.yaml

```yaml
servers:
- name: "weather-api"
type: "stdio"
command: "python"
args: ["weather_server.py"]
```

## Usage

```python
from fastapi import FastAPI
from fastapi_mcp_client import MCPClient

app = FastAPI()

mcp = MCPClient.from_env()

@app.get("/tools")
async def list_tools():
return await mcp.list_tools()
```

## Adding Tools

Define MCP tools in your `mcp_servers.yaml` and they'll be automatically discovered and made available through the client.
19 changes: 19 additions & 0 deletions extensions/fastapi-mcp-client/template/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# fastapi-mcp-client

MCP client integration for FastAPI AI applications.

## Overview

This template provides MCP client configuration and tool registry for FastAPI applications.

## Features

- MCP server configuration
- Tool discovery and execution
- Type-safe tool registry

## Installation

```bash
pip install -e .[dev]
```
1 change: 1 addition & 0 deletions extensions/fastapi-mcp-client/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests for fastapi-mcp-client extension."""
68 changes: 68 additions & 0 deletions extensions/fastapi-mcp-client/tests/test_mcp_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"""Tests for FastAPI MCP Client extension."""
import pytest
from fastapi_mcp_client import MCPClient
from fastapi.testclient import TestClient
from fastapi import FastAPI


def test_mcp_client_initialization():
"""Test MCPClient initialization."""
client = MCPClient()
assert client is not None
assert hasattr(client, 'list_tools')
assert hasattr(client, 'execute_tool')


def test_mcp_client_from_env():
"""Test MCPClient initialization from environment."""
client = MCPClient.from_env()
assert client is not None


def test_mcp_client_yaml_config():
"""Test MCPClient initialization from YAML config."""
import tempfile
import yaml

config = {
'servers': [
{
'name': 'test-server',
'type': 'stdio',
'command': 'echo',
'args': ['test']
}
]
}

with tempfile.NamedTemporaryFile(mode='w', suffix='.yaml', delete=False) as f:
yaml.dump(config, f)
config_path = f.name

try:
client = MCPClient.from_yaml(config_path)
assert client is not None
assert hasattr(client, 'config')
finally:
import os
os.unlink(config_path)


def test_fastapi_integration():
"""Test FastAPI integration with MCP client."""
app = FastAPI()

@app.get("/mcp-tools")
async def list_tools(mcp: MCPClient = None):
if mcp:
return {"tools": await mcp.list_tools()}
return {"tools": []}

client = TestClient(app)
response = client.get("/mcp-tools")
assert response.status_code == 200
assert "tools" in response.json()


if __name__ == "__main__":
pytest.main([__file__, "-v"])
Loading