Jasonkim8652 commited on
Commit
c088eff
·
verified ·
1 Parent(s): 8476db7

docs: custom MCP guide + minimal FastAPI stub

Browse files

- Delete obsolete example_server.py (old HTTP-endpoint
submission model, superseded by contamination-safe flow).
- Add example_mcp_server.py: ~150-line FastAPI stub showing
the MCP contract (POST {name, arguments} -> JSON),
bearer-token auth, 17 tool name list, and placeholder
handlers for fork-and-replace.
- README.md: new 'Bringing your own MCP tools' section with
the contract, hosting option matrix (Modal / cloud VM /
Runpod / k8s / ngrok+local GPU), link to the reference
implementation at RomeroLab/protein-design-mcp.
- app.py About tab: rewrite 'How to submit' for the new
we-host-the-agent architecture; link to custom-MCP docs
and example stub.

Files changed (4) hide show
  1. README.md +66 -0
  2. app.py +50 -53
  3. example_mcp_server.py +147 -0
  4. example_server.py +0 -205
README.md CHANGED
@@ -39,6 +39,72 @@ Novelty, and Diversity. See the *About* tab for the full methodology and the
39
  - **Depth Gap** — Forced-depth and low-diversity intervention results
40
  - **About** — Methodology, submission guide, and citation info
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  ## Backend pipeline phases
43
 
44
  Submission processing runs in 4 admin-controlled phases:
 
39
  - **Depth Gap** — Forced-depth and low-diversity intervention results
40
  - **About** — Methodology, submission guide, and citation info
41
 
42
+ ## Bringing your own MCP tools
43
+
44
+ BioDesignBench is "bring your own LLM, optionally bring your own tools."
45
+ The **Custom MCP** submission mode lets you evaluate any 17-tool
46
+ implementation against the identical 76 tasks, the identical agent
47
+ harness, and the identical scoring rubric used by the paper's reference
48
+ runs. Our [`protein-design-mcp`](https://github.com/RomeroLab/protein-design-mcp)
49
+ is just one reference implementation.
50
+
51
+ ### The contract
52
+
53
+ Your MCP server is a public HTTPS endpoint that accepts POST requests:
54
+
55
+ ```
56
+ POST https://your-mcp.example.com/
57
+ Authorization: Bearer <optional shared token>
58
+ Content-Type: application/json
59
+
60
+ {
61
+ "name": "predict_structure",
62
+ "arguments": {"sequence": "MKKL..."}
63
+ }
64
+ ```
65
+
66
+ The response must be a JSON object. Report errors in a top-level
67
+ `error` field rather than via HTTP status codes so the agent loop can
68
+ see the reason.
69
+
70
+ ### Tool schemas
71
+
72
+ The 17 reference tool names plus full JSON Schema for each argument
73
+ set live in [`mcp_tool_schemas.json`](./mcp_tool_schemas.json). Your
74
+ implementation must accept the same tool names and argument shapes —
75
+ the leaderboard's agent loop picks tools by name from this list.
76
+
77
+ ### Reference implementation
78
+
79
+ See [`RomeroLab/protein-design-mcp`](https://github.com/RomeroLab/protein-design-mcp)
80
+ for the lab's reference implementation. It is published as a Docker
81
+ image and a Modal app; you can fork it, replace individual tool
82
+ handlers, and redeploy.
83
+
84
+ ### Hosting options
85
+
86
+ Any public HTTPS endpoint works — we only check that the contract is
87
+ satisfied:
88
+
89
+ | Option | Pros | Cons |
90
+ |---|---|---|
91
+ | **Modal** (serverless GPU) | Cheap pay-per-use, auto-scale | Modal account needed |
92
+ | **AWS / GCP / Azure VM** | Full control, reuse existing cloud | 24/7 billing or manual shutdown |
93
+ | **Runpod / Lambda Labs / Vast** | Cheap GPU rentals | Manual spin-up per submission |
94
+ | **Kubernetes / HPC** | Reuse on-prem GPU | Ops overhead |
95
+ | **ngrok + local GPU** | $0, fastest iteration | URL is ephemeral |
96
+
97
+ The lab's reference MCP is hosted on Modal for serverless
98
+ pay-per-use cost control; your submission does not have to match.
99
+
100
+ ### Minimal stub
101
+
102
+ A ~150-line FastAPI template you can fork is at
103
+ [`example_mcp_server.py`](./example_mcp_server.py). Replace the
104
+ `handle_*` stubs with your implementations, deploy, and paste the URL
105
+ into the submission form's **Advanced: Custom MCP** section.
106
+
107
+
108
  ## Backend pipeline phases
109
 
110
  Submission processing runs in 4 admin-controlled phases:
app.py CHANGED
@@ -816,70 +816,67 @@ def build_about() -> str:
816
 
817
  <div {card}>
818
  <h2 {h2}>How to submit</h2>
819
- <h3 {h3}>1. Build your agent</h3>
820
  <p {p}>
821
- Create a protein design agent that runs the full plan &rarr;
822
- sample &rarr; evaluate &rarr; iterate loop on each task. Pick one
823
- of two MCP options:</p>
824
- <ul style="color:#475569;padding-left:1.5rem;margin-bottom:0.8rem;
825
  line-height:1.7">
826
- <li><strong>Reference MCP</strong> &mdash; connect to our published
 
 
 
 
 
 
 
 
827
  <a href="https://github.com/RomeroLab/protein-design-mcp"
828
  style="color:#2563eb;font-weight:600">protein-design-mcp</a>
829
- server (Docker image / Modal endpoint, in progress). Eligible for
830
- the reference ranking.</li>
831
- <li><strong>Custom MCP</strong> &mdash; bring your own tool
832
- implementations. Tagged with a <code>custom</code> badge on the
833
- leaderboard, excluded from the reference ranking.</li>
834
- </ul>
835
- <h3 {h3}>2. Host an API endpoint</h3>
836
- <p {p}>
837
- Your agent must be accessible as a POST endpoint that accepts
838
- task payloads and returns designed sequences plus a tool-call
839
- trace. See <code>biodesignbench-leaderboard/example_server.py</code>
840
- for a 200-line reference.</p>
841
- <h3 {h3}>API specification</h3>
842
- <pre style="background:#0f172a;color:#e2e8f0;padding:1.2rem;
843
- border-radius:10px;font-size:0.8rem;overflow-x:auto;
844
- line-height:1.6">POST /api/run
845
-
846
- Request:
847
- {{
848
- "task_id": "dnb_ab_001",
849
- "task_description": "Design a de novo binder for...",
850
- "available_tools": [...],
851
- "input_files": {{ "<pdb-name>": "<base64>" }},
852
- "design_constraints": {{ ... }},
853
- "max_steps": 50,
854
- "timeout_sec": 300
855
- }}
856
-
857
- Response:
858
- {{
859
- "sequences": ["MKKL..."],
860
- "run_log": [{{ "step": 1, "tool": "...", "success": true }}],
861
- "total_steps": 12,
862
- "total_time_sec": 142.5,
863
- "metrics": {{}}
864
- }}</pre>
865
- <h3 {h3}>3. Submit and wait</h3>
866
  <p {p}>
867
- We dispatch 73 hidden tasks to your endpoint, run Boltz-2
868
- structure verification on each design, and score against the
869
- 100-point hybrid rubric (algorithmic + 3-judge LLM panel).
870
- Maximum <strong>1 submission per month</strong> per
871
- organization &mdash; LLM-judge API costs are paid by Romero
872
- Lab.</p>
 
 
 
 
 
873
  <p {p}>
874
- 3 example tasks are publicly available for development and
875
- testing your endpoint before submission.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
876
 
877
  <h3 {h3}>Limits</h3>
878
  <ul style="color:#475569;padding-left:1.5rem;margin-bottom:0.8rem;
879
  line-height:1.7">
880
  <li>Maximum 1 submission per calendar month per organization</li>
881
- <li>73 hidden tasks are used for ranking</li>
882
- <li>3 public example tasks are available for development</li>
 
 
883
  </ul>
884
  </div>
885
 
 
816
 
817
  <div {card}>
818
  <h2 {h2}>How to submit</h2>
 
819
  <p {p}>
820
+ Unlike most agent benchmarks, <strong>you do not host an HTTP
821
+ endpoint</strong>. The 76 task descriptions never leave Romero
822
+ Lab infrastructure. Instead you provide:</p>
823
+ <ol style="color:#475569;padding-left:1.5rem;margin-bottom:0.8rem;
824
  line-height:1.7">
825
+ <li>an <strong>LLM provider + API key</strong>
826
+ (Anthropic / OpenAI / Google / DeepSeek).
827
+ We run the BioDesignBench agent loop against your chosen
828
+ model inside the leaderboard backend. Your key is
829
+ <em>scrubbed</em> from our records immediately after the
830
+ dispatch phase completes.</li>
831
+ <li>optionally, a <strong>custom MCP URL</strong> if you want
832
+ to evaluate your own tool implementations. Otherwise, the
833
+ agent calls our reference
834
  <a href="https://github.com/RomeroLab/protein-design-mcp"
835
  style="color:#2563eb;font-weight:600">protein-design-mcp</a>
836
+ endpoint (in progress).</li>
837
+ </ol>
838
+
839
+ <h3 {h3}>Data flow</h3>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
840
  <p {p}>
841
+ Each task prompt is sent to your chosen LLM provider via
842
+ their standard API (Anthropic, OpenAI, Google, DeepSeek) &mdash;
843
+ that single channel is the only path by which task data leaves
844
+ Romero Lab. The MCP server (reference or custom) only ever
845
+ sees operational tool arguments (sequences, PDB paths, hotspot
846
+ residues); it never sees the raw task prompt or evaluation
847
+ criteria. Every task prompt also carries a unique 16-character
848
+ canary token as an HTML comment, for retrospective leakage
849
+ detection.</p>
850
+
851
+ <h3 {h3}>Bring your own tools (Custom MCP)</h3>
852
  <p {p}>
853
+ If you want to benchmark a new tool implementation (a faster
854
+ structure predictor, a different diffusion backbone, your own
855
+ stability model) against the same 76 tasks and rubric, stand
856
+ up an HTTPS endpoint that satisfies the MCP contract and paste
857
+ the URL into the submission form's
858
+ <em>Advanced: Custom MCP</em> section:</p>
859
+ <ul style="color:#475569;padding-left:1.5rem;margin-bottom:0.8rem;
860
+ line-height:1.7">
861
+ <li><strong>Contract + hosting options</strong>:
862
+ <a href="https://github.com/RomeroLab/BioDesignBench/blob/main/biodesignbench-leaderboard/README.md#bringing-your-own-mcp-tools"
863
+ style="color:#2563eb;font-weight:600">leaderboard README</a></li>
864
+ <li><strong>Minimal FastAPI stub (~150 lines)</strong>:
865
+ <a href="https://github.com/RomeroLab/BioDesignBench/blob/main/biodesignbench-leaderboard/example_mcp_server.py"
866
+ style="color:#2563eb;font-weight:600"><code>example_mcp_server.py</code></a></li>
867
+ <li><strong>Reference implementation to fork</strong>:
868
+ <a href="https://github.com/RomeroLab/protein-design-mcp"
869
+ style="color:#2563eb;font-weight:600">RomeroLab/protein-design-mcp</a></li>
870
+ </ul>
871
 
872
  <h3 {h3}>Limits</h3>
873
  <ul style="color:#475569;padding-left:1.5rem;margin-bottom:0.8rem;
874
  line-height:1.7">
875
  <li>Maximum 1 submission per calendar month per organization</li>
876
+ <li>73 hidden tasks are used for ranking; 3 public example
877
+ tasks are available for development</li>
878
+ <li>LLM-judge API costs are paid by Romero Lab; your own
879
+ agent LLM calls are billed to your provider</li>
880
  </ul>
881
  </div>
882
 
example_mcp_server.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Minimal reference implementation of the BioDesignBench MCP contract.
2
+
3
+ Submitters who want to evaluate their own tool implementations against
4
+ the BioDesignBench leaderboard can fork this file, plug in their own
5
+ logic for each tool, deploy it behind a public HTTPS URL, and paste
6
+ that URL into the submission form under "Advanced: Custom MCP".
7
+
8
+ The leaderboard's agent loop will POST each tool invocation to your
9
+ endpoint and treat the JSON response as the tool result. The MCP never
10
+ sees the raw task description or evaluation criteria — only the
11
+ operational arguments the agent chooses to pass (a protein sequence,
12
+ a PDB path, a set of hotspot residues, etc.).
13
+
14
+ Contract:
15
+
16
+ POST <your-url>/
17
+ Authorization: Bearer <optional shared token>
18
+ Content-Type: application/json
19
+
20
+ {
21
+ "name": "<tool_name>", # one of the 17 tool names
22
+ "arguments": { ... } # per-tool JSON object
23
+ }
24
+
25
+ Response: arbitrary JSON object describing the tool output.
26
+ Errors should be reported in a top-level "error" field rather
27
+ than via HTTP status codes.
28
+
29
+ Install:
30
+ pip install fastapi uvicorn
31
+
32
+ Run (locally, with ngrok for a public URL):
33
+ uvicorn example_mcp_server:app --host 0.0.0.0 --port 8000
34
+ ngrok http 8000
35
+
36
+ Deploy (Modal example):
37
+ modal deploy example_mcp_server.py # see bdb-boltz as a template
38
+
39
+ Tool name list (17 total) — the full JSON Schema for each lives in
40
+ `mcp_tool_schemas.json` in this repo:
41
+
42
+ design_binder, analyze_interface, validate_design, optimize_sequence,
43
+ suggest_hotspots, get_design_status, predict_complex, predict_structure,
44
+ score_stability, energy_minimize, generate_backbone, rosetta_score,
45
+ rosetta_relax, rosetta_interface_score, rosetta_design,
46
+ predict_structure_boltz, predict_affinity_boltz
47
+ """
48
+
49
+ from __future__ import annotations
50
+
51
+ import os
52
+ from typing import Any
53
+
54
+ from fastapi import FastAPI, Header, HTTPException
55
+ from pydantic import BaseModel
56
+
57
+ app = FastAPI(title="BioDesignBench MCP (example stub)")
58
+
59
+ SHARED_TOKEN = os.environ.get("BDB_MCP_TOKEN", "")
60
+
61
+
62
+ class MCPRequest(BaseModel):
63
+ name: str
64
+ arguments: dict[str, Any] = {}
65
+
66
+
67
+ # ---------------------------------------------------------------------------
68
+ # Tool handlers (REPLACE THESE STUBS WITH YOUR ACTUAL IMPLEMENTATIONS)
69
+ # ---------------------------------------------------------------------------
70
+
71
+
72
+ def handle_predict_structure(args: dict) -> dict:
73
+ """Predict the structure of a single protein sequence.
74
+
75
+ Real implementations would call AlphaFold2, ESMFold, Boltz, etc.
76
+ """
77
+ sequence = args.get("sequence") or ""
78
+ if not sequence:
79
+ return {"error": "predict_structure requires a 'sequence' argument"}
80
+ # TODO: replace this stub with your structure predictor.
81
+ return {
82
+ "pdb": ">dummy\nATOM ...",
83
+ "pLDDT": 0.0,
84
+ "pTM": 0.0,
85
+ "note": "stub implementation -- replace with your predictor",
86
+ }
87
+
88
+
89
+ def handle_design_binder(args: dict) -> dict:
90
+ """Design a protein binder against a target. Real implementations
91
+ would call RFdiffusion followed by ProteinMPNN and AlphaFold2."""
92
+ return {"error": "design_binder not implemented in this stub"}
93
+
94
+
95
+ def handle_score_stability(args: dict) -> dict:
96
+ """Score single-point stability. Real implementations might call
97
+ Rosetta, DDG_predictor, or a learned model."""
98
+ return {"error": "score_stability not implemented in this stub"}
99
+
100
+
101
+ TOOL_HANDLERS = {
102
+ "predict_structure": handle_predict_structure,
103
+ "design_binder": handle_design_binder,
104
+ "score_stability": handle_score_stability,
105
+ # ... add handlers for the other 14 tools here
106
+ }
107
+
108
+
109
+ # ---------------------------------------------------------------------------
110
+ # Dispatcher
111
+ # ---------------------------------------------------------------------------
112
+
113
+
114
+ @app.post("/")
115
+ def call_tool(
116
+ req: MCPRequest,
117
+ authorization: str | None = Header(default=None),
118
+ ) -> dict:
119
+ if SHARED_TOKEN:
120
+ bearer = (authorization or "").removeprefix("Bearer ").strip()
121
+ if bearer != SHARED_TOKEN:
122
+ raise HTTPException(status_code=401, detail="Unauthorized")
123
+
124
+ handler = TOOL_HANDLERS.get(req.name)
125
+ if handler is None:
126
+ return {
127
+ "error": f"Unknown tool: {req.name}",
128
+ "available": sorted(TOOL_HANDLERS.keys()),
129
+ }
130
+
131
+ try:
132
+ return handler(req.arguments)
133
+ except Exception as e:
134
+ return {"error": f"{type(e).__name__}: {e}", "tool": req.name}
135
+
136
+
137
+ @app.get("/health")
138
+ def health() -> dict:
139
+ return {
140
+ "ok": True,
141
+ "implemented_tools": sorted(TOOL_HANDLERS.keys()),
142
+ "note": (
143
+ "This is the reference stub. Replace the handle_* functions "
144
+ "with your actual tool implementations before submitting to "
145
+ "the BioDesignBench leaderboard."
146
+ ),
147
+ }
example_server.py DELETED
@@ -1,205 +0,0 @@
1
- """Reference FastAPI server for BioDesignBench submitters.
2
-
3
- This example shows how to implement the API endpoint that BioDesignBench
4
- will call during benchmarking. Replace the mock agent logic with your
5
- actual LLM agent + MCP tool pipeline.
6
-
7
- Usage:
8
- pip install fastapi uvicorn
9
- python example_server.py
10
-
11
- # Or with uvicorn directly:
12
- uvicorn example_server:app --host 0.0.0.0 --port 8000
13
-
14
- Your endpoint will receive POST requests at /api/run with the task payload.
15
-
16
- Task Payload Format:
17
- {
18
- "task_id": "dnb_sig_001",
19
- "task_description": "Design a de novo binder for...",
20
- "available_tools": [... 17 tool schemas ...],
21
- "input_files": {"7n1j.pdb": "<base64>"},
22
- "design_constraints": {"length_range": [80, 150], "max_designs": 10},
23
- "max_steps": 50,
24
- "timeout_sec": 300
25
- }
26
-
27
- Expected Response Format:
28
- {
29
- "sequences": ["MKKL...", "MFQR..."],
30
- "run_log": [{"step": 1, "tool": "suggest_hotspots", "success": true}, ...],
31
- "total_steps": 12,
32
- "total_time_sec": 142.5,
33
- "metrics": {}
34
- }
35
- """
36
-
37
- from __future__ import annotations
38
-
39
- import base64
40
- import random
41
- import time
42
- from pathlib import Path
43
- from typing import Any
44
-
45
- from fastapi import FastAPI
46
- from pydantic import BaseModel
47
-
48
- app = FastAPI(
49
- title="BioDesignBench Example Agent",
50
- description="Reference implementation for benchmark submission",
51
- version="0.1.0",
52
- )
53
-
54
-
55
- # ---------------------------------------------------------------------------
56
- # Request/Response models
57
- # ---------------------------------------------------------------------------
58
-
59
-
60
- class TaskPayload(BaseModel):
61
- task_id: str
62
- task_description: str
63
- available_tools: list[dict[str, Any]] = []
64
- input_files: dict[str, str] = {} # filename -> base64 data
65
- design_constraints: dict[str, Any] = {}
66
- max_steps: int = 50
67
- timeout_sec: int = 300
68
-
69
-
70
- class AgentResponse(BaseModel):
71
- sequences: list[str]
72
- run_log: list[dict[str, Any]]
73
- total_steps: int
74
- total_time_sec: float
75
- metrics: dict[str, Any] = {}
76
-
77
-
78
- # ---------------------------------------------------------------------------
79
- # Mock agent (replace with your real agent)
80
- # ---------------------------------------------------------------------------
81
-
82
- # Standard amino acids for mock sequence generation
83
- _AAS = "ACDEFGHIKLMNPQRSTVWY"
84
-
85
-
86
- def _generate_mock_sequence(length: int) -> str:
87
- """Generate a random protein sequence with reasonable composition."""
88
- # Weight towards common amino acids
89
- weights = [
90
- 7, 2, 5, 6, 4, 7, 2, 5, 6, 9, # A C D E F G H I K L
91
- 2, 4, 5, 4, 5, 7, 6, 7, 1, 3, # M N P Q R S T V W Y
92
- ]
93
- return "".join(random.choices(_AAS, weights=weights, k=length))
94
-
95
-
96
- def mock_agent(payload: TaskPayload) -> AgentResponse:
97
- """Mock agent that generates random but valid designs.
98
-
99
- Replace this with your actual LLM agent + MCP tool pipeline.
100
- This mock demonstrates the expected response format.
101
- """
102
- start = time.monotonic()
103
-
104
- # Determine design parameters
105
- constraints = payload.design_constraints
106
- length_range = constraints.get("length_range", [80, 150])
107
- max_designs = constraints.get("max_designs", 10)
108
- num_designs = min(max_designs, 5) # Generate 5 for this mock
109
-
110
- # "Decode" input PDB files (in a real agent, you'd use these)
111
- for filename, b64_data in payload.input_files.items():
112
- pdb_bytes = base64.b64decode(b64_data)
113
- # In a real agent: save to temp file and pass to MCP tools
114
-
115
- # Simulate a multi-step design pipeline
116
- run_log = [
117
- {
118
- "step": 1,
119
- "tool": "suggest_hotspots",
120
- "success": True,
121
- "args_summary": {"target": "from_pdb"},
122
- "output_summary": "Found 5 hotspot residues",
123
- },
124
- {
125
- "step": 2,
126
- "tool": "generate_backbone",
127
- "success": True,
128
- "args_summary": {"length": length_range[0]},
129
- "output_summary": f"Generated {num_designs} backbones",
130
- },
131
- {
132
- "step": 3,
133
- "tool": "optimize_sequence",
134
- "success": True,
135
- "args_summary": {"optimization_target": "both"},
136
- "output_summary": f"Optimized {num_designs} sequences",
137
- },
138
- {
139
- "step": 4,
140
- "tool": "predict_structure",
141
- "success": True,
142
- "args_summary": {"predictor": "esmfold"},
143
- "output_summary": "Predicted structures for all designs",
144
- },
145
- {
146
- "step": 5,
147
- "tool": "validate_design",
148
- "success": True,
149
- "args_summary": {},
150
- "output_summary": "Validated all designs",
151
- },
152
- ]
153
-
154
- # Generate mock sequences
155
- min_len, max_len = length_range
156
- sequences = [
157
- _generate_mock_sequence(random.randint(min_len, max_len))
158
- for _ in range(num_designs)
159
- ]
160
-
161
- elapsed = time.monotonic() - start
162
-
163
- return AgentResponse(
164
- sequences=sequences,
165
- run_log=run_log,
166
- total_steps=len(run_log),
167
- total_time_sec=round(elapsed, 2),
168
- metrics={}, # Agent-reported metrics (optional)
169
- )
170
-
171
-
172
- # ---------------------------------------------------------------------------
173
- # API endpoint
174
- # ---------------------------------------------------------------------------
175
-
176
-
177
- @app.post("/api/run", response_model=AgentResponse)
178
- async def run_task(payload: TaskPayload) -> AgentResponse:
179
- """Run a single benchmark task.
180
-
181
- This is the endpoint that BioDesignBench will POST to during benchmarking.
182
- Replace mock_agent() with your actual agent logic.
183
- """
184
- return mock_agent(payload)
185
-
186
-
187
- @app.get("/health")
188
- async def health():
189
- """Health check endpoint."""
190
- return {"status": "ok", "agent": "example-mock"}
191
-
192
-
193
- # ---------------------------------------------------------------------------
194
- # Entry point
195
- # ---------------------------------------------------------------------------
196
-
197
- if __name__ == "__main__":
198
- import uvicorn
199
-
200
- print("Starting BioDesignBench example server...")
201
- print("POST endpoint: http://localhost:8000/api/run")
202
- print("Health check: http://localhost:8000/health")
203
- print()
204
- print("Replace mock_agent() with your real agent logic.")
205
- uvicorn.run(app, host="0.0.0.0", port=8000)