# mcp_gateway

## Co robi

Pojedynczy serwer MCP, który dla klienta (np. Claude'a) wygląda jak jeden backend, a pod spodem agreguje N realnych serwerów MCP i przekierowuje do nich wywołania. Pośredniczy zarówno w narzędziach (`tools/list`, `tools/call`), jak i w zasobach (`resources/list`, `resources/read`, `resources/subscribe`/`unsubscribe`), a także propaguje notyfikacje z backendów do klientów (`tools/list_changed`, `resources/list_changed`, `resources/updated`). Utrzymuje cykl życia połączeń do backendów: łączy się przy starcie i przy `add_mcp_server`, sprawdza żywotność pingiem, a przy zerwaniu uruchamia pętlę reconnect i odtwarza narzędzia oraz zasoby. Sam wystawia wbudowane narzędzia `management__*` (dodanie/usunięcie/odświeżenie backendu w runtime) oraz alternatywne REST API dla klientów nie-MCP. Każda kolizja nazwy narzędzia czy URI zasobu skutkuje twardym błędem, żeby niespójności wychodziły natychmiast, a nie kumulowały się jako ciche nadpisania.

## Możliwy podział na 3 moduły

1. **`mcp_gateway_core`** — silnik backendowy bez ekspozycji na świat: `models`, `registry`, `connection_pool`, `executor`, `orchestrator`. Reużywalna biblioteka „mam N serwerów MCP, zarządzaj nimi", niezależna od tego kto i jak korzysta z wyniku.
2. **`mcp_gateway_server`** — warstwa protokołu MCP wystawiona klientom: `gateway` (handlery MCP, broadcast notyfikacji do sesji) plus integracja z `streamable_http`. Zależy od `core`, niczego doń nie wnosi poza front-endem.
3. **`mcp_gateway_admin`** — control plane: `management` + `management_server` (wbudowane narzędzia administracyjne wystawione jako lokalny backend MCP), `rest_api` (alternatywny interfejs dla nie-MCP) oraz utrwalanie konfiguracji (`config.json`, `save_config` z `main.py`). Zależy od `core`, niezależny od `server`.

## config.json

```json
{
  "host": "127.0.0.1",
  "port": 8000,
  "management_port": 8999,
  "backends": [
    {
      "id": "nostr_admin",
      "url": "http://127.0.0.1:8100/mcp/",
      "enabled": true,
      "autostart": true,
      "sh_path": "../mcp_nostr_db/admin/mcp/mcp_admin.sh"
    }
  ]
}
```

Pola backendu:

| Pole | Opis |
|------|------|
| `id` | Stabilny identyfikator; tooly z tego backendu są eksponowane jako `<id>__<nazwa>` |
| `url` | Streamable-http URL backendu MCP |
| `enabled` | `false` = wpis czytany ale nie podłączany |
| `autostart` | `true` = gateway spawnuje `sh_path` przy starcie i SIGTERM-uje przy shutdownie |
| `sh_path` | Ścieżka do skryptu odpalającego backend (relatywna od katalogu `config.json` lub absolutna; musi być wykonywalna) |

Autostart spawnuje proces w osobnej grupie procesów (`start_new_session=True`),
czeka do 15s aż URL zacznie odpowiadać, a przy shutdownie wysyła SIGTERM →
(po 5s) SIGKILL. Stdout/stderr backendu dziedziczy gateway. `save_config`
zachowuje `autostart` i `sh_path` przy zapisie po dynamicznym `add_mcp_server`.
