---
title: Mcpo: un proxy de serveur mcp
author: Frederic AOUSTIN
version: 1.O
---

# Mcpo: un proxy de serveur mcp

![category](developpement)
![tag](python)
![tag](ia)


Rapidement quand on travaille sur produire une plateforme IA, on ajoute plusieurs serveurs MCP.

Ces serveurs permettent à un LLM via un orchestrateur d'utiliser des outils. 
Ces outils peuvent permettre:

- de communiquer avec des APIs tiers
- d'échanger avec une base de donnée
- de créer des pipelines en indiquant à une IA ce qu'elle doit réaliser
- ...

Très rapidement on se retrouve avec plusieurs services qu'il faut pouvoir centraliser.
En effet j'utilise docker et si je veux rendre mes serveurs mcp accessible sur l'exterieur je vais démultiplier l'usage des ports ce qui n'est pas une bonne chose.

Il faut donc pouvoir mettre en place un proxy qui va centraliser l'ensemble des demandes 

Nous allons mettre en place l'architecture suivante

```mermaid
flowchart LR
    user["Utilisateur"]
    crawl4ai["Craw4AI"]
    mcpo["mcpo"]
    mcp1["Mcp Serveur 1"]
    mcp2["Mcp Serveur 2"]
    mcpo --> crawl4ai
    mcpo --> mcp1
    mcpo --> mcp2
    user --> mcpo
```

Chaque serveur mcp sera accessible via une url du type http://127.0.0.1:8000/<serveur-mcp/

**Mcpo** fait se travaille et va plus loin car il unifie aussi la methode d'accès. Ainsi l'ensemble des serveurs mcp qui lui sont connectés seront accessible en **openapi** (même si le service de base est en sse ou http-streamable)

Pour créer un docker mcpo rien de plus simple

```
  mcpo:
    image: ghcr.io/open-webui/mcpo:main
    container_name: mcpo
    restart: unless-stopped
    ports:
      - "8080:8000"
    volumes:
      - ./mcpo-config:/app/config:ro
    command: ["mcpo", "--host", "0.0.0.0", "--port", "8000",
              "--api-key", "${MCPO_API_KEY:-mcpo-secret}",
              "--config", "/app/config/config.json"]
    networks:
      - mcp-net
    depends_on:
      - crawl4ai
      - mcp1
      - mcp2
```

Il faut fournir un fichier de configuration *config.json* permettant à **mcpo** de savoir comment se connecter au serveur mcp

```json
{
  "mcpServers": {
    "crawl4ai": {
      "type": "sse",
      "url": "http://crawl4ai:11235/mcp/sse",
      "headers": {
        "Authorization": "Bearer mXH2NW7JRhHvyLU6xNlufKZg361on"
      }
    },
    "mcp1": {
      "type": "streamable-http",
      "url": "http://mcp1:8000/mcp",
      "headers": {
        "Authorization": "Bearer 1234567890123"
      }
    },
    "mcp2": {
      "type": "streamable-http",
      "url": "http://mcp2:8000/mcp",
      "headers": {
        "Authorization": "Bearer 1234567890123fdsfsdf"
      }
    }
  }
}
```

Il faut noter dans notre exemple

- que pour se connecter aux apis depuis l'exterieur il faudra utiliser *MCPO_API_KEY*
- que chaque serveur mcp possède son propre système d'authentification par Token

Par défaut **mcpo*** rend accessible une interface *swagger* pour la documentation des outils et le test de ces derniers.
Cette interfaces est accessible sur http://127.0.0.1:8000/docs

Pour rendre cette interface non ouverte, mais accessible uniquement par token il faut modifier notre docker de cette façon

```
  mcpo:
    image: ghcr.io/open-webui/mcpo:main
    container_name: mcpo
    restart: unless-stopped
    ports:
      - "8080:8000"
    volumes:
      - ./mcpo-config:/app/config:ro
    command: ["mcpo", "--host", "0.0.0.0", "--port", "8000",
              "--api-key", "${MCPO_API_KEY:-mcpo-secret}",
              "--strict-auth",
              "--config", "/app/config/config.json"]
    networks:
      - mcp-net
    depends_on:
      - crawl4ai
      - mcp1
      - mcp2
```

On peut bien sur interroger les apis directement en python

```python
import requests

MCPO_URL = "http://localhost:8080"
MCPO_API_KEY = "<YOUR-SECRET-MCPO-API-KEY>"


def url_to_markdown(url: str) -> str:
    response = requests.post(
        f"{MCPO_URL}/crawl4ai/md",
        headers={
            "Authorization": f"Bearer {MCPO_API_KEY}",
            "Content-Type": "application/json",
        },
        json={
            "url": url,
            "temperature": 0,
        },
        timeout=60,
    )
    response.raise_for_status()
    data = response.json()
    return data.get("markdown", "")

if __name__ == "__main__":
    md = url_to_markdown("https://fraoustin.fr")
    print(md)
```

J'ai modifié ma commande **mcp** afin qu'elle soit compatible *openapi* vous pouvez la trouver [ici](./upload/mcp)

Exemple d'utilisation qui retourne le même résultat

```bash
mcp --token <YOUR-TOKEN-MCP> list
mcp --token <YOUR-TOCKEN-MCP> call get_weather city=Paris
mcp --openapi --url http://127.0.0.1:8080/mcpgeography/ --token <YOUR-TOKEN-MCPO> list
mcp --openapi --url http://127.0.0.1:8080/mcpgeography --token <YOUT-TOKEN-MCPO> call tool_get_weather_post city=Paris
```
