mirror of
https://github.com/mcloh/codex-chatgpt-mcp-proxy.git
synced 2026-11-05 21:34:11 +00:00
103 lines
4.3 KiB
Python
103 lines
4.3 KiB
Python
from fastapi.testclient import TestClient
|
|
from mcp.client.streamable_http import streamable_http_client
|
|
from codex_chatgpt_mcp_proxy.server import create_app
|
|
|
|
|
|
def test_api_auth_host_origin_and_isolation(config):
|
|
with TestClient(create_app(config), base_url=config.public_url) as c:
|
|
assert c.get("/healthz").json() == {"ok": True}
|
|
assert c.get("/healthz", headers={"host": "evil.example"}).status_code == 403
|
|
assert c.get("/healthz", headers={"origin": "https://evil.example"}).status_code == 403
|
|
for token in (None, "invalid", config.dev_mcp_token):
|
|
h = {"Authorization": "Bearer " + token} if token else {}
|
|
assert c.post("/api/worker/claim", headers=h).status_code == 401
|
|
assert (
|
|
c.post("/mcp", headers={"Authorization": "Bearer " + config.worker_token}).status_code
|
|
== 401
|
|
)
|
|
h = {"Authorization": "Bearer " + config.worker_token}
|
|
assert (
|
|
c.post(
|
|
"/api/worker/register",
|
|
headers=h,
|
|
json={
|
|
"worker_id": "home",
|
|
"protocol": "1",
|
|
"version": "test",
|
|
"workspaces": ["demo"],
|
|
},
|
|
).status_code
|
|
== 200
|
|
)
|
|
assert c.post("/api/worker/claim", headers=h).json() == {"task": None}
|
|
assert (
|
|
c.post(
|
|
"/api/worker/register",
|
|
headers=h,
|
|
json={
|
|
"worker_id": "home",
|
|
"protocol": "1",
|
|
"version": "test",
|
|
"workspaces": ["/tmp"],
|
|
},
|
|
).status_code
|
|
== 400
|
|
)
|
|
assert c.post("/api/worker/claim", headers=h, content="x" * 140000).status_code == 413
|
|
|
|
|
|
async def test_real_mcp_transport_initialize_discover_and_validation(config):
|
|
import httpx2
|
|
|
|
app = create_app(config)
|
|
async with app.router.lifespan_context(app):
|
|
async with httpx2.AsyncClient(
|
|
transport=httpx2.ASGITransport(app=app),
|
|
headers={"Authorization": "Bearer " + config.dev_mcp_token},
|
|
) as http:
|
|
async with streamable_http_client(config.public_url + "/mcp", http_client=http) as (
|
|
read,
|
|
write,
|
|
):
|
|
from mcp import ClientSession
|
|
|
|
async with ClientSession(read, write) as session:
|
|
initialization = await session.initialize()
|
|
assert initialization.server_info.name == "codex-chatgpt-mcp-proxy"
|
|
tools = await session.list_tools()
|
|
names = {t.name for t in tools.tools}
|
|
assert names == {
|
|
"bridge_status",
|
|
"submit_task",
|
|
"get_task",
|
|
"get_task_events",
|
|
"continue_task",
|
|
"cancel_task",
|
|
"list_tasks",
|
|
}
|
|
invalid = await session.call_tool(
|
|
"submit_task",
|
|
{
|
|
"instruction": "x",
|
|
"workspace": "demo",
|
|
"idempotency_key": "k",
|
|
"timeout_seconds": 0,
|
|
},
|
|
)
|
|
assert invalid.is_error
|
|
result = await session.call_tool(
|
|
"submit_task",
|
|
{"instruction": "hello", "workspace": "demo", "idempotency_key": "k"},
|
|
)
|
|
assert not result.is_error
|
|
assert result.structured_content["state"] == "queued"
|
|
repeated = await session.call_tool(
|
|
"submit_task",
|
|
{"instruction": "hello", "workspace": "demo", "idempotency_key": "k"},
|
|
)
|
|
assert not repeated.is_error
|
|
assert repeated.structured_content["id"] == result.structured_content["id"]
|
|
for tool in tools.tools:
|
|
assert tool.annotations is not None
|
|
assert tool.meta["securitySchemes"][0]["type"] == "oauth2"
|