Backup automatico script del 2026-09-27 07:00
This commit is contained in:
1 parent
f347badf3b
commit
09dcbbdadb
24 files changed
+1164
-193
No files matched your search
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Conformità Streamable HTTP / lifecycle MCP: negoziazione versione, 202 per notifiche, header.
|
||||
|
||||
Uso (dentro il container):
|
||||
docker exec loogle-mcp python /srv/scripts/test_mcp_protocol.py
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import httpx
|
||||
|
||||
sys.path.insert(0, "/srv")
|
||||
from app.db import get_conn # noqa: E402
|
||||
from app.jwt_utils import create_access_token # noqa: E402
|
||||
|
||||
BASE = os.environ.get("TEST_BASE", "http://127.0.0.1:8700") + "/mcp"
|
||||
row = get_conn().execute("SELECT id, username FROM users WHERE username='daniele'").fetchone()
|
||||
token, _ = create_access_token(dict(row), "context:read", "protocol-test")
|
||||
AUTH = {"Authorization": f"Bearer {token}"}
|
||||
failures = 0
|
||||
|
||||
|
||||
def check(label: str, cond: bool, detail: str = "") -> None:
|
||||
global failures
|
||||
failures += 0 if cond else 1
|
||||
print(f"{'OK ' if cond else 'FAIL'} {label} {detail}")
|
||||
|
||||
|
||||
def init(version):
|
||||
params = {"protocolVersion": version, "capabilities": {}, "clientInfo": {"name": "protocol-test"}}
|
||||
r = httpx.post(BASE, json={"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": params})
|
||||
return r.json()["result"]["protocolVersion"]
|
||||
|
||||
|
||||
for requested, expected in [("2025-06-18", "2025-06-18"), ("2025-03-26", "2025-03-26"),
|
||||
("2024-11-05", "2024-11-05"), ("2099-01-01", "2025-06-18")]:
|
||||
got = init(requested)
|
||||
check(f"initialize {requested}", got == expected, f"-> {got}")
|
||||
|
||||
r = httpx.post(BASE, json={"jsonrpc": "2.0", "method": "notifications/initialized"})
|
||||
check("notifica non autenticata initialized -> 202", r.status_code == 202 and not r.content, str(r.status_code))
|
||||
r = httpx.post(BASE, headers=AUTH, json={"jsonrpc": "2.0", "method": "notifications/cancelled",
|
||||
"params": {"requestId": 5}})
|
||||
check("notifica cancelled -> 202", r.status_code == 202, str(r.status_code))
|
||||
r = httpx.post(BASE, json={"jsonrpc": "2.0", "method": "notifications/cancelled"})
|
||||
check("notifica non autenticata non ammessa -> 401", r.status_code == 401, str(r.status_code))
|
||||
r = httpx.post(BASE, headers=AUTH, json=[{"jsonrpc": "2.0", "method": "notifications/initialized"},
|
||||
{"jsonrpc": "2.0", "id": 7, "method": "ping"}])
|
||||
body = r.json()
|
||||
check("batch notifica+request -> solo 1 risposta", r.status_code == 200 and len(body) == 1 and body[0]["id"] == 7,
|
||||
str(body))
|
||||
r = httpx.post(BASE, headers={**AUTH, "MCP-Protocol-Version": "2025-06-18"},
|
||||
json={"jsonrpc": "2.0", "id": 2, "method": "tools/list"})
|
||||
check("header versione valida -> 200", r.status_code == 200 and "tools" in r.json()["result"], str(r.status_code))
|
||||
r = httpx.post(BASE, headers={**AUTH, "MCP-Protocol-Version": "1999-01-01"},
|
||||
json={"jsonrpc": "2.0", "id": 3, "method": "tools/list"})
|
||||
check("header versione non supportata -> 400", r.status_code == 400, str(r.status_code))
|
||||
r = httpx.post(BASE, json={"jsonrpc": "2.0", "id": 4, "method": "tools/list"})
|
||||
check("request senza token -> 401 + WWW-Authenticate",
|
||||
r.status_code == 401 and "resource_metadata" in r.headers.get("www-authenticate", ""), str(r.status_code))
|
||||
r = httpx.post(BASE, headers=AUTH, json=[])
|
||||
check("batch vuoto -> 400", r.status_code == 400, str(r.status_code))
|
||||
print(f"Errori: {failures}")
|
||||
sys.exit(1 if failures else 0)
|
||||