Skip to main content
Glama
Manuciao88

PA MCP Server

by Manuciao88
README.md
# PA MCP Server

Server MCP che espone il motore **Portfolio Advisor (PA)** come tool per agenti AI.
Il motore quantitativo è incluso in `pa_engine/src`, così il progetto è
autonomo e non dipende da cartelle o dati esterni alla distribuzione.

Documentazione prodotto e limiti: [`PRODUCT_OVERVIEW.md`](PRODUCT_OVERVIEW.md).
Template privacy da sottoporre a revisione professionale:
[`PRIVACY_NOTICE_TEMPLATE.md`](PRIVACY_NOTICE_TEMPLATE.md).
Esito audit pre-release: [`AUDIT_REPORT.md`](AUDIT_REPORT.md).

## Cosa espone

| Tool | Output |
|---|---|
| `avvia_percorso_portafoglio` | Entry point per richieste generiche su capitale, rischi e scenari |
| `informazioni_strumento` | Scopo, metodo, limiti, privacy e flusso corretto |
| `proponi_strumenti` | Shortlist illustrativa commentata per valuta, da confermare |
| `verifica_strumenti` | Verifica ticker, storico e valuta con motivazioni di rifiuto |
| `schema_input_pa` | Schema JSON completo con required, default, unità, enum ed esempio minimale |
| `valida_input_pa` | Validazione offline: missing, errors, warnings e config normalizzata |
| `prepara_simulazione` | Pannello MCP App per revisione e conferma dei parametri precompilati |
| `analisi_completa` | Report interattivo, eseguito solo con approvazione esplicita valida |

L'agente chiama prima `schema_input_pa`, raccoglie i dati e passa la
configurazione a `valida_input_pa`. Se `valid=true`, chiama
`prepara_simulazione`: il client mostra un pannello con i parametri compilati e
la simulazione resta ferma. L'utente può modificare i valori e deve confermare
esplicitamente. Il widget congela la configurazione e invia all'agente un
identificatore interno di approvazione; l'agente chiama quindi direttamente
`analisi_completa`, che include ottimizzazione, rendimenti attesi, Monte Carlo,
stress test e confronto benchmark. L'approvazione scade dopo 2 ore e viene
consumata quando il report completo termina con successo.

Se l'utente fornisce una lista di strumenti, l'agente la passa a
`verifica_strumenti` e spiega puntualmente ogni rifiuto. Se non ha una lista e
chiede suggerimenti, l'agente usa `proponi_strumenti`, presenta ticker, nome,
borsa, costo stimato e commento, quindi attende conferma esplicita prima della
verifica e della configurazione. Nessuna sostituzione avviene automaticamente.

`cost_annual_pct` è espresso in punti percentuali: `0.50` significa `0,50%`
annuo. I client senza supporto MCP Apps possono validare e mostrare la bozza,
ma non completano il percorso di approvazione interattiva.

## Setup

```bash
python3.13 -m venv .venv
./.venv/bin/python -m pip install .
```

Per modificare e ricostruire i widget servono inoltre Node.js 20+ e `npm ci`.

Il motore Portfolio Advisor è incluso nel progetto in `pa_engine/src`, quindi
il server è autonomo. Per sviluppo è possibile puntare un motore alternativo:

```bash
export PA_ENGINE_DIR="/percorso/del/motore"   # opzionale, solo sviluppo
```

## Avvio

Locale (stdio):

```bash
./.venv/bin/python -m pa_mcp.server
```

Streamable HTTP, per connector remoti e test MCP Apps:

```bash
PA_MCP_TRANSPORT=http PA_MCP_PORT=3000 \
  ./.venv/bin/python -m pa_mcp.server
```

Endpoint MCP: `http://127.0.0.1:3000/mcp`. Per i client web va esposto
temporaneamente tramite HTTPS oppure distribuito su un host remoto. L'avvio
HTTP locale non abilita autenticazione e non va pubblicato direttamente in
produzione.

Approvazioni, recensioni e cache sono persistenti e condivisibili (sopravvivono
al riavvio) attivando un percorso di stato scrivibile:

```bash
PA_STATE_PATH=/var/lib/pa_mcp/state.db PA_MCP_TRANSPORT=http PA_MCP_PORT=3000 \
  ./.venv/bin/python -m pa_mcp.server
```

Senza `PA_STATE_PATH` lo stato resta in memoria (comportamento usuale per
sviluppo locale e test).

### OAuth (HTTP, prima di esporre l'endpoint)

OAuth 2.1 (scope `pa.read`) è disponibile via FastMCP `OAuthProvider`:

```bash
PA_OAUTH=1 PA_PUBLIC_BASE_URL=https://pa.example.com \
  PA_MCP_TRANSPORT=http PA_MCP_PORT=3000 ./.venv/bin/python -m pa_mcp.server
```

Con `PA_OAUTH` non impostato il server HTTP resta senza autenticazione (adatto
a sviluppo e test). In produzione i token OAuth andrebbero persistiti nello
store condiviso e configurare autorizzazione per-tenant.

### Protezione infrastruttura (HTTP)

- `PA_RATE_LIMIT_PER_MIN` — token-bucket per IP (HTTP 429).
- `PA_MAX_BODY_BYTES` — limite body richieste (HTTP 413).
- `PA_ANALYSIS_TIMEOUT_SECONDS` — deadline hard per analisi (di default 60s;
  rilascia slot e approvazione).
- `PA_ANALYSIS_QUOTA_PER_HOUR` — quota oraria di analisi per tenant
  (0 = illimitata); chiave tenant via `PA_TENANT` (default `anonymous`).

### Osservabilità (HTTP)

- `GET /health/live` — liveness.
- `GET /health/ready` — readiness (503 se non pronto; stato dello store).
- `GET /metrics` — contatori operativi (senza dati personali).

### Deploy e documenti

Per pubblicare il connettore servirà un endpoint stabile (non il tunnel):
segli `DEPLOY_GUIDE.md` (include `Dockerfile`). Bozza di informativa e termini
in `PRIVACY_NOTICE_DRAFT.md` e `TERMS_OF_USE_DRAFT.md` (da revisionare).

Per i client i nuovi moduli `pa_mcp/auth.py`, `pa_mcp/limits.py`,
`pa_mcp/state.py`, `pa_mcp/oauth_provider.py`, `pa_mcp/quotas.py` sono inclusi
nella wheel.

Il server parla su stdio: qualsiasi client MCP può collegarlo. Esempio di
config per un client generico:

```json
{
  "mcpServers": {
    "pa-engine": {
      "command": "/percorso/pa-mcp-server/.venv/bin/python",
      "args": ["/percorso/pa-mcp-server/server_script.py"],
      "cwd": "/percorso/pa-mcp-server"
    }
  }
}
```

## Test dei tool

Test offline del contratto e del flusso di approvazione:

```bash
./.venv/bin/python -m unittest discover -s tests -p 'test_*.py'
node scripts/test_config_widget_render.js
node scripts/test_widget_render.js
```

Self-check completo con dati di mercato:

```bash
./.venv/bin/python -m pa_mcp.selfcheck
```

Esegue tutti i tool contro una config di test con dati reali (serve rete verso
Yahoo Finance) e stampa le chiavi di ogni output.

## Nota sul motore

Il wrapper riusa `pa/src` del motore PA. Non ricalcola nulla: delega la
pipeline completa al motore e serializza il report JSON prodotto da
`export_report_json`. Se il motore cambia interfaccia, aggiornare
`pa_mcp/engine.py`.

### Bug fix applicato al motore (numpy 2.x)

`pa/src/core/stress_test.py`: `weights.to_numpy(dtype=float)` con numpy 2.x
restituisce un array read-only e `target /= target.sum()` falliva con
`ValueError: output array is read-only`. Corretto con
`np.array(weights.to_numpy(dtype=float))`. In via di upstream nel motore.

## Roadmap

1. Revisione professionale finanziaria, fiscale, privacy e licenze dati.
2. Deploy remoto con OAuth 2.1, isolamento tenant, quote e osservabilità.
3. Pubblicazione sui registry supportati dopo security review indipendente.

La checklist bloccante è in [`GO_LIVE_CHECKLIST.md`](GO_LIVE_CHECKLIST.md).