Skip to main content
Glama
ahmad-act

Multiple MCP Servers Framework

by ahmad-act
README.md
# šŸš€ Multiple MCP Servers using FastAPI and Testing with Inspector

This project provides a framework for running multiple **Model Context Protocol (MCP)** servers using different transport mechanisms: FastAPI-based HTTP servers, standalone `streamable-http` servers, and `stdio`-based servers. 

āœ… **Supported MCP Transports:**
- stdio
- streamable-http
- FastAPI-mounted
   
It includes **three main scripts**:
- `mcp-server-with-stdio.py` āž”ļø A standalone MCP server using `stdio` transport.
- `mcp-server-with-streamable-http.py` āž”ļø A standalone MCP server using `streamable-http` transport.
- `mcp-server-fastapi.py` āž”ļø A FastAPI server hosting two MCP instances (`McpServer1` and `McpServer2`) with `streamable-http` transport.

Each server implements a simple **echo** tool for testing and demonstration, and the framework supports robust logging, environment configuration, and graceful shutdown handling. The servers are compatible with the **MCP Inspector** for interactive testing. šŸ•µļøā€ā™‚ļø

---

# šŸ“‘ Table of Contents

1. [šŸŽÆ Purpose](#-purpose)  
2. [šŸ—‚ļø Project Structure](#ļø-project-structure)  
3. [✨ Features](#-features)  
4. [šŸ› ļø Prerequisites](#ļø-prerequisites)  
5. [šŸ“¦ Required Packages](#-required-packages)  
6. [āš™ļø Installation](#ļø-installation)  
    - [Clone the Repository](#-clone-the-repository)  
    - [Set Up a Virtual Environment](#-set-up-a-virtual-environment)  
    - [Install Dependencies](#-install-dependencies)  
    - [Configure Environment Variables](#-configure-environment-variables)  
7. [šŸš€ Usage](#-usage)  
    - [1ļøāƒ£ Standalone Stdio MCP Server](#-1ļøāƒ£-standalone-stdio-mcp-server)  
        - [Starting the MCP Server](#-starting-the-mcp-server-stdio)  
        - [Starting the MCP Inspector](#-starting-the-mcp-inspector-stdio)  
        - [Opening the MCP Inspector](#-opening-the-mcp-inspector-stdio)  
        - [Using the MCP Inspector](#-using-the-mcp-inspector-stdio)  
    - [2ļøāƒ£ Standalone Streamable-HTTP MCP Server](#-2ļøāƒ£-standalone-streamable-http-mcp-server)  
        - [Starting the MCP Server](#-starting-the-mcp-server-streamable-http)  
        - [Starting the MCP Inspector](#-starting-the-mcp-inspector-streamable-http)  
        - [Opening the MCP Inspector](#-opening-the-mcp-inspector-streamable-http)  
        - [Using the MCP Inspector](#-using-the-mcp-inspector-streamable-http)  
    - [3ļøāƒ£ FastAPI-Based MCP Server](#-3ļøāƒ£-fastapi-based-mcp-server)  
        - [Starting the MCP Server](#-starting-the-mcp-server-fastapi)  
        - [Starting the MCP Inspector](#-starting-the-mcp-inspector-fastapi)  
        - [Opening the MCP Inspector](#-opening-the-mcp-inspector-fastapi)  
        - [Using the MCP Inspector](#-using-the-mcp-inspector-fastapi)  
8. [🧩 Workflow](#-workflow)  
9. [šŸ“ Logging](#-logging)  
10. [šŸ›‘ Graceful Shutdown](#-graceful-shutdown)  
11. [🧭 Notes](#-notes)  
12. [šŸ› ļø Troubleshooting](#ļø-troubleshooting)  

---

## šŸŽÆ Purpose

The MCP Server Framework is designed to:
- Demonstrate the flexibility of MCP servers using different transports (`streamable-http` and `stdio`).
- Provide a production-ready FastAPI server hosting multiple MCP instances under a single application.
- Support standalone MCP servers for simpler use cases or environments requiring `stdio` communication.
- Ensure robust logging, configuration management, and graceful shutdown for all server types.
- Enable easy integration with the MCP Inspector for testing and tool interaction.

---

## šŸ—‚ļø Project Structure

The project is organized as follows:

```
/
ā”œā”€ā”€ src/
│   ā”œā”€ā”€ mcp-server-fastapi.py                # FastAPI server hosting two MCP instances
│   ā”œā”€ā”€ mcp-server-with-streamable-http.py   # Standalone MCP server with streamable-http
│   ā”œā”€ā”€ mcp-server-with-stdio.py             # Standalone MCP server with stdio
│   ā”œā”€ā”€ fastapi_mcp_servers/                 # MCP server implementations for FastAPI
│   │   ā”œā”€ā”€ __init__.py
│   │   ā”œā”€ā”€ mcp_server_1.py                  # First MCP server with echo1 tool
│   │   └── mcp_server_2.py                  # Second MCP server with echo2 tool
│   ā”œā”€ā”€ config/                              # Configuration and logging utilities
│   │   ā”œā”€ā”€ __init__.py
│   │   ā”œā”€ā”€ app_settings.py                  # Environment variable and settings management
│   │   └── logging_config.py                # Logging setup with file rotation and cleanup
│   └── util/
│       └── mcp_server_shutdown_handler.py   # Graceful shutdown handler for MCP servers
ā”œā”€ā”€ .env                                     # Environment variables (e.g., PORT, LOG_DIR)
ā”œā”€ā”€ pyproject.toml                           # Project dependencies
└── README.md                                # Project documentation
```

---

## ✨ Features

- **Multiple MCP Servers**:
   - Standalone MCP server using `stdio` transport for direct stdin/stdout communication.
   - Standalone MCP server using `streamable-http` transport at `http://0.0.0.0:8001/mcp/`.
   - FastAPI server hosting two MCP instances at `/echo1/mcp/` and `/echo2/mcp/` with `streamable-http` transport.
- **Echo Tool**: A simple tool that echoes input messages, implemented across all servers for testing.
- **Transport Flexibility**: Supports `streamable-http` (recommended for HTTP-based communication) and `stdio` (for Inspector-driven communication).
- **Robust Logging**: Configurable logging with file rotation and console output, stored in a specified log directory.
- **Environment Configuration**: Loads settings from a `.env` file (e.g., `PORT`, `LOG_DIR`, `API_KEY`).
- **Graceful Shutdown**: Handles `SIGINT` and `SIGTERM` signals to ensure clean termination of MCP servers.
- **Lifespan Management (FastAPI)**: Manages startup and shutdown of MCP session managers in the FastAPI server.
- **MCP Inspector Compatibility**: All servers are compatible with the MCP Inspector for interactive tool testing.

---

## šŸ› ļø Prerequisites

To run the project, ensure you have the following installed:

- **Python**: Version 3.8 or higher
- **Node.js**: Required for running the MCP Inspector
- **uv**: A Python package manager for installing dependencies
- **npx**: For running the MCP Inspector
- **Operating System**: Compatible with Windows, macOS, or Linux
- **Recommended**: a modern terminal that supports UTF-8

---

## šŸ“¦ Required Packages

The project depends on the following Python packages:

- `mcp[cli]`: Provides the MCP server and CLI tools.
- `fastapi`: The FastAPI framework for the `mcp-server-fastapi.py` script.
- `uvicorn`: ASGI server implementation for running FastAPI.
- `python-dotenv`: For loading environment variables from a `.env` file.

---

## āš™ļø Installation

1. **Clone the Repository**:
   
   ```bash
   git clone https://github.com/ahmad-act/Multiple-MCP-Servers-Using-FastAPI-and-Testing-with-Inspector.git
   cd Multiple-MCP-Servers-Using-FastAPI-and-Testing-with-Inspector
   ```

2. **Set Up a Virtual Environment** (optional but recommended):
   ```bash
   uv venv
   source venv/bin/activate  # On Windows: venv\Scripts\activate
   ```

3. **Install Dependencies**:

   Install the required Python packages using `uv`:

   ```bash
   uv sync
   ```

   Alternatively,

   ```bash
   uv add mcp[cli] fastapi uvicorn python-dotenv
   ```

4. **Configure Environment Variables**:

   Create a `.env` file in the project root with the following content:

   ```env
   PORT=10000
   LOG_DIR=logs
   ```

---

## Usage

### 1ļøāƒ£ Standalone Stdio MCP Server (`mcp-server-with-stdio.py`)

#### Starting the MCP Server

You do not need to manually run the MCP server for stdio transport. MCP Inspector runs the MCP Server for stdio transport.

#### Starting the MCP Inspector

The `stdio` server is typically launched by the MCP Inspector, not manually. Run the Inspector with the following command, adjusting the `--directory` path to your `src/` directory:

```bash
npx @modelcontextprotocol/inspector uv --directory "<your-src-directory>" run mcp-server-with-stdio.py --debug
```

![MCP Inspector Run](doc/mcp-inspector-stdio-run-1.png)

The Inspector will manage the server lifecycle and communicate over `stdio`.

#### Opening the MCP Inspector

Open the link `http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=XXXXXXXXXXXXXXXXXX` with its token in your browser:

![MCP Inspector Use](doc/mcp-inspector-stdio-open-1.png)

#### Using the MCP Inspector

1. After running the above command, the Inspector will start and automatically connect to the `stdio`-based server.
2. In the Inspector UI (`http://127.0.0.1:6274`), inspect the available tools (e.g., `echo`).
3. Test the `echo` tool:
   - **Input**:

     ```json
     {
       "message": "test"
     }
     ```
   - **Expected Output**:

     ```json
     {
       "echo": "Echo from MCP Server with stdio: test"
     }
     ```
      
   ![MCP Inspector Use](doc/mcp-inspector-stdio-use-1.png)
   ![MCP Inspector Use](doc/mcp-inspector-stdio-use-2.png)
   ![MCP Inspector Use](doc/mcp-inspector-stdio-use-3.png)


### 2ļøāƒ£ Standalone Streamable-HTTP MCP Server (`mcp-server-with-streamable-http.py`)

#### Starting the MCP Server

Open new terminal and go to the project root folder:

```bash
cd "D:\My Study\AI\GitHub ahmad-act\Multiple-MCP-Servers-Using-FastAPI-and-Testing-with-Inspector"
```

Run the standalone MCP server:

```bash
uv run ./src/mcp-server-with-streamable-http.py
```

The server will start on `http://0.0.0.0:8001/mcp/`.

![MCP Server with streamable-http](doc/mcp-server-streamable-http-run-1.png)

#### Starting the MCP Inspector

Run the MCP Inspector:

Open new terminal and run the command:

```bash
npx @modelcontextprotocol/inspector
```

![MCP Inspector Run](doc/mcp-inspector-streamable-http-run-1.png)

#### Opening the MCP Inspector

Open the Inspector in your browser at `http://127.0.0.1:6274`.

```plaintext
http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

![MCP Inspector Open](doc/mcp-inspector-streamable-http-open-1.png)

#### Using the MCP Inspector

1. Configure the Inspector to connect to `http://0.0.0.0:8001/mcp/`.

   ![MCP Inspector Test](doc/mcp-inspector-streamable-http-test-1.png)
   ![MCP Inspector Test](doc/mcp-inspector-streamable-http-test-2.png)

2. Test the `echo` tool:
   
   - **Input**:
     ```json
     {
       "message": "test"
     }
     ```
   - **Expected Output**:
     ```json
     {
       "echo": "Echo from MCP Server with streamable-http: test"
     }
     ```

   ![MCP Inspector Test](doc/mcp-inspector-streamable-http-test-3.png)

### 3ļøāƒ£ FastAPI-Based MCP Server (`mcp-server-fastapi.py`)

#### Starting the MCP Server

Open new terminal and go to the project root folder:

```bash
cd "D:\My Study\AI\GitHub ahmad-act\Multiple-MCP-Servers-Using-FastAPI-and-Testing-with-Inspector"
```

Run the FastAPI server:

```bash
uv run ./src/mcp-server-fastapi.py
```

The server will start on `http://0.0.0.0:10000` (or the port specified in the `PORT` environment variable). The MCP endpoints will be available at:
- `http://0.0.0.0:10000/echo1/mcp/`
- `http://0.0.0.0:10000/echo2/mcp/`

   ![MCP Server with streamable-http](doc/mcp-server-fastapi-run-1.png)

#### Starting the MCP Inspector

Run the MCP Inspector:

Open new terminal and run the command:

```bash
npx @modelcontextprotocol/inspector
```

![MCP Inspector Run](doc/mcp-inspector-fastapi-run-1.png)

#### Opening the MCP Inspector

Open the Inspector in your browser at `http://127.0.0.1:6274`.

```plaintext
http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

![MCP Inspector Open](doc/mcp-inspector-fastapi-open-1.png)

#### Using the MCP Inspector

1. Configure the Inspector to connect to `http://0.0.0.0:10000/echo1/mcp/` for `McpServer1`.

   ![MCP Inspector Test](doc/mcp-inspector-fastapi-mcp-server1-test-1.png)
   ![MCP Inspector Test](doc/mcp-inspector-fastapi-mcp-server1-test-2.png)

2. Test the `echo` tool:
   - **Input**:
     ```json
     {
       "message": "test"
     }
     ```
   - **Expected Output**:
     ```json
     {
       "echo": "Echo from MCP Server 1 using FastAPI: test"
     }
     ```

   ![MCP Inspector Test](doc/mcp-inspector-fastapi-mcp-server1-test-3.png)

3. Configure the Inspector to connect to `http://0.0.0.0:10000/echo2/mcp/` for `McpServer2`.

   ![MCP Inspector Test](doc/mcp-inspector-fastapi-mcp-server2-test-1.png)
   ![MCP Inspector Test](doc/mcp-inspector-fastapi-mcp-server2-test-2.png)

4. Test the `echo` tool:
   - **Input**:
     ```json
     {
       "message": "test"
     }
     ```
   - **Expected Output**:
     ```json
     {
       "echo": "Echo from MCP Server 2 using FastAPI: test"
     }
     ```

   ![MCP Inspector Test](doc/mcp-inspector-fastapi-mcp-server2-test-3.png)

---

## 🧩 Workflow

1. **Choose the Server Type**:
   - Use `mcp-server-fastapi.py` for a multi-MCP HTTP server.
   - Use `mcp-server-with-streamable-http.py` for a standalone HTTP-based MCP server.
   - Use `mcp-server-with-stdio.py` for `stdio`-based communication, typically managed by the MCP Inspector.
2. **Start the Server**:
   - For FastAPI or streamable-http servers, run the respective script with `uv run`.
   - For the stdio server, use the MCP Inspector to launch the server.
3. **Interact with MCP Tools**: Use the MCP Inspector to connect to the server and test the `echo` tool.
4. **Monitor Logs**: Check logs in the `logs/` directory (or the directory specified in `LOG_DIR`) for debugging and monitoring.
5. **Graceful Shutdown**: Press `Ctrl+C` or send a `SIGTERM` signal to shut down HTTP-based servers gracefully. For the `stdio` server, shutting down the Inspector will terminate the server.

---

## šŸ“ Logging

- Logs are stored in the directory specified by the `LOG_DIR` environment variable (default: `logs/`).
- Log files are named in the format `YYYYMM.log` (e.g., `202507.log` for July 2025).
- Logs rotate when they reach 5 MB, with up to 5 backup files.
- Old log files can be cleaned up using the `cleanup_old_logs` function in `logging_config.py`.

Example log output:
```
2025-07-01 13:06:00,123 - __main__ - INFO - Starting FastMCP server with streamable-http transport...
2025-07-01 13:06:00,125 - __main__ - INFO - FastMCP server initialized successfully.
```

---

## šŸ›‘ Graceful Shutdown

All servers handle `SIGINT` (e.g., `Ctrl+C`) and `SIGTERM` signals to ensure graceful shutdown:
- MCP servers are shut down cleanly.
- Logs are updated with shutdown status.
- The process exits with a status code of `0`.

---

## 🧭 Notes

- **Transport Options**:
  - `streamable-http` is recommended for HTTP-based communication due to its efficiency.
  - `stdio` is suitable for environments where direct stdin/stdout communication is preferred, typically with the MCP Inspector.
- **Port Configuration**:
  - The FastAPI server uses port `10000` by default (configurable via `PORT`).
  - The streamable-http server uses port `8001` (hardcoded).
  - The stdio server does not use a network port.
- **MCP Inspector**: Required for testing all servers. Ensure it is running to interact with MCP tools.

---

## šŸ› ļø Troubleshooting

- **Server Fails to Start**:
  - Check logs in the `logs/` directory for errors.
  - Ensure the `PORT` environment variable is a valid integer for HTTP-based servers.
  - Verify that port `8001` (for streamable-http) or `10000` (for FastAPI) is not in use.
- **MCP Inspector Cannot Connect**:
  - For HTTP servers, verify the server is running and the endpoint URLs are correct.
  - For the stdio server, ensure the Inspector command includes the correct `--directory` path.
- **Log Files Not Created**: Ensure the `LOG_DIR` directory exists and is writable.
- **Dependency Issues**: Run `uv sync` to ensure all required packages are installed.

---

TDQS

C2.4/5.0

Scored across 1 tool

Disambiguation5/5

With only one tool, there is no possibility of confusion between tools.

Naming Consistency5/5

A single tool name 'echo' is self-consistent, so the naming pattern is coherent by default.

Tool Count1/5

The server is named 'Multiple MCP Servers Framework', yet provides only one trivial echo tool, which is a severe mismatch between name and functionality.

Completeness1/5

A single echo tool provides no meaningful coverage for any domain; the tool surface is severely incomplete for the implied purpose.

Maintenance

ActivityInactive
ResponsivenessNo issues