SeqBench

Wiring an AI Agent to Real Bioinformatics Tools via MCP

11 min read · Updated July 14, 2026

Three short DNA sequence strips on the left converge with arrows into a single wider results card on the right labeled "batch results", listing seq_1, seq_2, and seq_3 each marked with a checkmark.many sequencesATGCAAGGTACCCATGCGprocessed as one batchbatch resultsseq_1 ✓seq_2 ✓seq_3 ✓...

An AI coding or research agent asked to compute a primer's melting temperature, scan a coding sequence for a Type IIS restriction site, or confirm that a synonymous codon swap actually preserved a protein is doing arithmetic and lookups it has no reliable way to check from its own weights. Wiring that agent to a Model Context Protocol (MCP) server that runs the real calculation turns "the model guessed" into "the model called a pure function and read back a typed result," which matters the moment the output feeds a synthesis order or a cloning plan. This walkthrough shows exactly what that looks like against SeqBench's production MCP server: one JSON-RPC tools/call against melting_temperature with real numbers, then the full multi-step domesticate_for_golden_gate recipe (construct_qc, construct_autofix, and a re-check) run end to end with real request and response bodies captured from the live endpoint.

The transport is the boring part; JSON-RPC 2.0 over HTTP is the same regardless of vendor. What's worth studying closely is what rides alongside every result: an objective pass/fail gate with an explicit list of what it did not check, and a provenance receipt. That combination is the difference between a tool an agent can safely loop on during a design-then-check cycle and a wrapper that just moves a Tm calculation from the model's head onto a server without changing whether anything downstream can trust the answer.

What an agent gets wrong estimating sequence math itself

Large language models are unreliable at exactly the operations bioinformatics tooling exists to make deterministic: nearest-neighbour thermodynamics, scanning both strands and all three reading frames for a restriction site, tracking whether a base substitution is actually synonymous under the genetic code, or computing a sliding-window GC% correctly at the edges of a sequence. None of this is exotic math, but it is the kind of multi-step bookkeeping where a fluent, plausible-looking answer can be wrong by a few percent or by an entire formula, with no signal in the model's own output that anything is off.

A concrete version of this shows up later in this article: applying the Wallace rule (calibrated for oligos under about 14 nt) to a 32-nt primer produces a Tm estimate of 92°C, a number no real 32-mer DNA duplex reaches in an aqueous PCR buffer. A model reciting "Tm = 2(A+T) + 4(G+C)" from memory, without tracking that the formula stops being appropriate past a certain primer length, would make that exact mistake and state it with full confidence.

Calling a tool instead sidesteps this category of error, because the number comes from the same nearest-neighbour engine, codon table, or restriction-site scanner SeqBench's own web tools use, not from next-token prediction. That doesn't make the agent smarter. It makes the arithmetic it's relying on independently checkable, by a human or by another tool call, rather than only checkable by re-asking the same model and hoping for a different answer.

MCP in one paragraph

Model Context Protocol is a JSON-RPC 2.0 protocol for exposing tools, resources, and prompts to an AI client over a single endpoint. A client opens with an initialize call (protocol version, client info), discovers what's available with tools/list (each tool advertises a JSON-Schema for its own arguments) and prompts/list, then invokes a tool with tools/call {name, arguments} or fetches a canned multi-step recipe with prompts/get. Any client implementing this handshake, including Claude (Desktop or Code), Cursor, and other MCP-speaking agents, can drive the same server without the server author writing a separate integration for each client.

Connecting to SeqBench's MCP server

SeqBench runs a stateless Streamable-HTTP MCP server at https://seqbench.com/api/mcp: POST a JSON-RPC message, get a JSON-RPC response back, with no session cookie or handshake state kept between requests, aside from the deliberately time-boxed session_* tools described later in this article.

Calling initialize with {"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "clientInfo": {"name": "test", "version": "0.1"}}} returns the protocol version echoed back (or defaulting to 2025-06-18 if the client omits it), a serverInfo block ({"name": "SeqBench MCP", "version": "1.1.0"} as of this writing), and an instructions string the calling client is expected to fold into its own system context. That string tells the agent, in plain language, to prefer calling these tools over hand-estimating, and flags upfront which built-in screens are intentionally narrow, such as primer_specificity's curated genome set and plasmid_identify's roughly 30-vector catalog.

The same set of tools is also reachable as plain REST under /api/v1/{tool} for callers that don't want an MCP client at all, and SeqBench has a server.json prepared for the official MCP registry that has not been published there yet, so an agent won't currently discover this server by browsing that registry; it has to be pointed at the URL directly.

  • tools/list currently returns 59 tools: 57 deterministic sequence/protein tools (four of them, session_create, session_get, session_set, and session_run, are the sole stateful exception) plus batch and workflow for running a tool, or a short multi-tool pipeline, over an entire multi-FASTA file in one call.
  • prompts/list currently exposes four canned recipes: design_specific_primers, verify_clone_batch, domesticate_for_golden_gate, and identify_unknown_plasmid.
  • Coverage spans primer/oligo design and QC, reverse-complement/translate/ORF-finding, cloning simulation (restriction digest, Gibson and Golden Gate assembly, plasmid annotation, construct QC, virtual gel), plasmid backbone identification, protein properties, codon optimization, sequence alignment, CRISPR gRNA design, and GenBank/FASTQ/Sanger .ab1 parsing.
  • Every successful tools/call response includes a gate object (or null) and a provenance object; errors carry a typed code and a retryable boolean instead of only a message string. Both of these are the subject of a dedicated section below.

A single call: melting_temperature

Here is a complete, real request against a 32-nt forward primer that has an NheI site (GCTAGC) engineered into its 5' end for cloning, with a target Tm supplied so the response comes back graded:

{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "melting_temperature", "arguments": {"sequence": "ATGGCTAGCAAAGGAGAAGAACTTTTCACTGG", "targetTm": 60, "tmTolerance": 2}}}

And the response, trimmed to the fields that matter (the real payload also includes a content array carrying the same data serialized as text, for clients that only consume plain text rather than structuredContent):

{"jsonrpc": "2.0", "id": 2, "result": {"structuredContent": {"length": 32, "gcContent": 43.75, "recommended": 61.8, "recommendedFormula": "Salt-adjusted", "tmNearestNeighbor": 69.11, "tmWallace": 92, "tmSaltAdjusted": 61.83, "ssDnaMw": 9921.54, "dsDnaMw": 19646.92}, "gate": {"pass": true, "checks": [{"id": "tm-window", "label": "Tm within target window", "severity": "hard", "pass": true, "message": "Recommended Tm 61.8°C is 1.8°C from the 60°C target (±2°C window), via Salt-adjusted.", "value": 61.8, "threshold": "60±2°C"}], "notChecked": ["primer specificity against any genome (not computed by this tool)"]}, "provenance": {"apiVersion": "1.1.0", "tool": "melting_temperature", "generatedAt": "2026-07-13T14:12:18.121Z"}}}

The tool reports three separate Tm estimates rather than one: a nearest-neighbour value (SantaLucia 1998 parameters), the Wallace rule, and a salt-adjusted formula, then names one of them recommended based on primer length (Wallace under about 14 nt, salt-adjusted otherwise) instead of leaving the caller to pick. At 32 nt the two simpler formulas disagree sharply: Wallace returns 92°C, an obviously wrong number for a duplex this length, while the salt-adjusted estimate (61.83°C, surfaced as 61.8°C) is the one actually appropriate here and is the one the tool labels recommended.

Supplying targetTm and tmTolerance is what turns this into a graded call. With both present, gate is a real object carrying one hard check, tm-window, comparing the recommended Tm against a window around the target; here it passes with 0.2°C of margin (61.8°C is 1.8°C above 60, inside the 2°C tolerance). Omit targetTm and the same call returns gate: null, not a fabricated pass; there was simply nothing supplied to grade against. notChecked is a single blunt line here: Tm math says nothing about whether this primer binds anywhere else in a genome. That's a different tool, primer_specificity, with its own separately scoped gate.

  • tmNearestNeighbor: 69.11°C (SantaLucia 1998 nearest-neighbour parameters)
  • tmWallace: 92°C (short-oligo rule, not appropriate at 32 nt, reported anyway for reference)
  • tmSaltAdjusted: 61.83°C, surfaced as recommended: 61.8°C, since this primer is well past Wallace's valid range

Chaining calls: domesticate_for_golden_gate end to end

domesticate_for_golden_gate exists to remove internal Type IIS sites, and a short list of other synthesis-risk motifs, from a coding sequence before Golden Gate assembly, without altering the protein it encodes. Calling prompts/get with {"name": "domesticate_for_golden_gate"} returns the recipe as plain instructional text for an agent to follow: run construct_qc with the enzyme you plan to cut with in avoidEnzymes, run construct_autofix with the same sequence and enzyme list, inspect what's left in remaining and unfixableCategories, then re-run construct_qc to confirm the gate now passes before handing the part to assembly.

Take an 11-residue linker peptide, Met-Gly-Ser-Gly-Ser-Gly-Leu-Gly-Ser-Gly-Ser-stop, encoded as the 36-nt CDS ATGGGTAGCGGTAGCGGTCTCGGTAGCGGTAGCTAA. One way a Type IIS site slips into a coding sequence unnoticed is a codon boundary that happens to spell out the recognition sequence even though neither codon is unusual on its own: here, the glycine codon GGT immediately followed by the leucine codon CTC reads straight through as GGTCTC, BsaI's own recognition sequence, at nucleotides 16-21.

Step one, construct_qc: {"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "construct_qc", "arguments": {"sequence": "ATGGGTAGCGGTAGCGGTCTCGGTAGCGGTAGCTAA", "avoidEnzymes": ["BsaI"]}}} returns sequenceLength 36, proteinLength 11, counts {"error": 1, "warning": 0, "info": 0, "total": 1}, pass: false, synthesizability: "red", and one warning: {"severity": "error", "category": "restriction-site", "message": "BsaI site (GGTCTC) is present — it would break a planned Golden Gate digest with this enzyme (domesticate it before assembly).", "position": 16, "end": 21}. Its gate carries nine checks: eight soft ones (premature-stop, internal-rbs, polya-signal, gc-extreme, homopolymer, tandem-repeat, hairpin, cryptic-orf) that all pass on this short sequence, and one hard restriction-site check that fails with value 1. gate.pass is false overall even though eight of nine checks are clean, because a single failing hard check is enough to fail the whole gate regardless of how many soft checks pass.

Step two, construct_autofix, called with the same sequence, avoidEnzymes: ["BsaI"], and organism: "ecoli": it makes exactly one substitution, codon 6 at nucleotide position 16, GGT to GGC, still coding glycine (aminoAcid: "G"), tagged reason: "restriction-site". before.counts.error was 1 (synthesizability red); after.counts.error is 0 (synthesizability green); remaining and unfixableCategories are both empty, meaning nothing was left over that a synonymous swap couldn't resolve this time. The fixed sequence is ATGGGTAGCGGTAGCGGCCTCGGTAGCGGTAGCTAA. Its gate carries one hard check, no-hard-findings-remain, which now passes, and a three-item notChecked list worth reading in full: it did not touch premature stop codons or GC extremes (never auto-fixed, by design), it did not check genome-wide primer or oligo specificity, and it did not run any vendor-specific manufacturability scoring. A green synthesizability rating here means all nine of construct_qc's own categories came back clean: the avoided restriction site, premature stop codons, internal RBS and poly-A motifs, GC extremes, homopolymers, tandem repeats, predicted secondary structure, and hidden alt-frame ORFs. It is still not a vendor's proprietary manufacturability score, and it says nothing about primer or oligo specificity, which is a separate tool with its own gate.

Step three, re-running construct_qc on the fixed sequence with the same avoidEnzymes: ["BsaI"]: counts are now {"error": 0, "warning": 0, "info": 0, "total": 0}, pass: true, synthesizability: "green", warnings: [], and the gate's restriction-site check now reads "No sites found for: BsaI." with value 0. This is the actual point of the recipe: the agent driving this loop doesn't have to trust construct_autofix's own self-report. It re-runs the identical query it started with and gets a mechanically confirmable, independent pass. Only after that confirmation would the domesticated sequence go to the Cloning & Assembly Simulator's Golden Gate mode for the actual digest-and-ligate design.

The gate, provenance, and notChecked design: why it's the actual differentiator

A single-endpoint MCP wrapper around a Tm or GC-content calculation is a genuinely useful small project, and versions of this exist. What it typically returns is a number and a sentence: this primer's Tm is 61.8°C. Left there, the calling agent has to reinvent the pass/fail logic itself, either hardcoding its own ±2°C window client-side or, worse, asking the model to eyeball whether 61.8 looks close enough to 60. That reintroduces the exact failure mode tool-calling was supposed to remove: a model's judgment call standing in for a deterministic check.

SeqBench's convention is that every successful tools/call response carries two extra objects alongside the tool's own result: gate ({pass, checks, notChecked}) and provenance ({apiVersion, tool, generatedAt}). Each entry in checks has a stable id, a severity of hard or soft, its own pass/fail, and the numeric value or threshold it was computed from, so an agent or a human reviewing a log can see exactly which condition failed and by how much, not just an aggregate verdict. Severity matters mechanically: gate.pass is true only if every hard check passed. A failing soft check surfaces as a finding but never flips the overall verdict, which is why the first construct_qc call above still failed its gate on one hard restriction-site check despite eight clean soft checks.

gate is null, not a fabricated pass, whenever a call doesn't supply enough to grade against, as with melting_temperature called without a targetTm. That asymmetry between a missing gate and a false pass is deliberate: a tool that always emits some gate object trains its caller to trust the field's presence more than its content.

notChecked is the part actually worth building process around. It is not boilerplate disclaimer text; it changes what a specific call is allowed to mean. construct_qc's restriction-site check is only promoted from notChecked into an actual hard check when the caller supplies an avoidEnzymes list. An empty list is not silently treated as checked-and-clean, because that would fabricate a pass for enzymes nobody asked about. primer_specificity's notChecked explicitly excludes whole human and mouse nuclear genomes from its off-target screen; treating a specificity pass there as no off-target sites anywhere would be a real, costly mistake for anyone doing mammalian cell work. Reading notChecked before reading pass is the actual skill this design is trying to build into an agent, and into whoever is supervising it.

Errors follow the same philosophy. Instead of a bare message string, every thrown error carries a typed code (invalid_argument, unsupported, upstream_unavailable, upstream_timeout, rate_limited, or internal_error), a retryable boolean, and a suggestedAction. An agent driving an autonomous design loop can branch on retryable mechanically, retrying an upstream_timeout after a short delay but not retrying an invalid_argument unchanged and expecting a different result, instead of parsing English prose to guess whether resending is worth it.

For anyone assembling an AI-agent bio workflow with real consequences at the other end, an actual synthesis order or an actual cloning attempt, this is the property worth demanding from any tool it calls, not only from SeqBench: a pass/fail contract with an explicit, mandatory account of what it does not cover. A tool that returns only numbers and prose is asking the agent, or the human skimming its output, to supply that judgment silently from context every single time.

Other canned recipes

domesticate_for_golden_gate, covered step by step above, is one of four canned prompts exposed via prompts/list. Each packages the right sequence of calls for a recurring job so an agent doesn't have to rediscover or reinvent an ordering; the other three are:

  • design_specific_primers: primer_design generates candidate pairs, primer_specificity screens the top pair for off-target amplicons against curated reference genomes, then in_silico_pcr runs against the caller's own template to confirm exactly one product. The recipe reports the structural gate and the specificity gate together, so it's visible which sequences each one actually covered.
  • verify_clone_batch: runs batch with tool="sanger_vs_reference" across one FASTA record per well plus a shared reference sequence, then reads verdict, coverage_pct, and identity_pct per row. It's explicit that verdict="ambiguous_low_coverage" must never be treated as a pass, however clean the covered portion looks, because the read simply didn't span enough of the reference to say anything.
  • identify_unknown_plasmid: runs plasmid_identify and reports the full ranked topMatches list rather than only the top hit, treats unidentifiedRegions as the normal, expected signature of a backbone-plus-insert plasmid rather than an error, and flags possibleChimera or breakpoints explicitly, since that specifically means two different catalog backbones appear spliced together in one query sequence.

Stateful sessions for multi-part designs

Every tool discussed so far is a pure function: call it twice with the same arguments and get the same answer, with no memory of the previous call. session_create, session_get, session_set, and session_run break that pattern deliberately, and only for one purpose: letting an agent carry several named sequences or values, for example a vector, an insert, and a forward and reverse primer pair, across a multi-step design without re-pasting the actual sequences into its own context on every call.

session_create opens a session and optionally seeds it with named entries; session_set adds or overwrites entries in an existing one; session_get reads back named entries to inspect what a session currently holds. session_run is the one that does the real work: it resolves selected tool arguments from the session's named entries instead of taking them inline, runs any other SeqBench tool, and can optionally write selected fields of the result back into the session under new names. That is what makes a multi-part design, for example a primer designed against a stashed vector and then an assembly call that reads both that vector and a separately stashed insert by name, expressible without ever putting the raw sequences back through the calling model's own context.

Session data expires after 24 hours. It is scratch space for one working design session, not project storage; there's no expectation that a sessionId created today will resolve to anything tomorrow.

What this doesn't check

  • A passing construct_qc or construct_autofix gate is scoped to exactly the checks it lists: the avoided restriction sites, premature stop codons, GC extremes, homopolymers, tandem repeats, predicted secondary structure, and a few cryptic-motif classes (internal RBS-like motifs, poly-A signals, hidden alt-frame ORFs). It is not a vendor's manufacturability score, and its own notChecked says so.
  • construct_autofix never touches premature stop codons or GC-content extremes; those land in unfixableCategories and need a human decision, not a synonymous-codon patch.
  • primer_specificity's off-target screen runs against a small curated set of reference genomes, explicitly not whole human or mouse nuclear genomes; a pass there says nothing about mammalian off-target priming.
  • plasmid_identify's catalog is roughly 30 common vectors, not Addgene's or PlasmidScope's full listings. An honest no-good-match result usually means the plasmid isn't one of those 30 backbones, not that the sequence itself is invalid, and an unidentified stretch is the expected signature of a lab's own insert, not a defect.
  • A workflow step can chain only one sequence output into the next step's input; a step that genuinely needs two independent sequences at once, such as annealing a primer to a template that isn't the previous step's output, isn't expressible that way. session_run is the tool for that case.
  • session_* data expires after 24 hours and was never meant as a project store. It is scratch space for one working design session, not somewhere to park a construct between visits.
  • None of this replaces actually sequencing the finished clone. SeqBench's own instructions to calling agents state plainly that results are for research and educational use and that critical results should be verified independently; a green gate on a domesticated part is a claim about the sequence as submitted, not a guarantee about the plasmid eventually pulled from a bacterial colony.
  • An agent that only reads the human-readable content[0].text summary and ignores gate and structuredContent has thrown away the entire point of this design. A system prompt or client wrapper should tell it explicitly to check gate.pass and iterate on gate.checks and notChecked, not to free-associate from the prose sitting next to them.

Frequently asked questions

What's the MCP endpoint for SeqBench's tools?

https://seqbench.com/api/mcp accepts POST requests carrying JSON-RPC 2.0 messages: initialize, tools/list, tools/call, prompts/list, prompts/get, and ping. It's stateless Streamable HTTP, so no session cookie or handshake state is kept between requests, aside from the explicitly time-boxed session_* tools.

Do I need an MCP client to use SeqBench's tools, or can I call them directly?

Every tool behind the MCP server is also exposed as plain REST under /api/v1/{tool-name}, so a plain HTTP client or script can call the same deterministic logic without speaking MCP at all. The MCP layer exists specifically for AI agents that discover and invoke tools dynamically as part of a conversation.

Does a green construct_autofix result mean a sequence is ready to order for synthesis?

No. It means the specific findings construct_qc can check, such as unwanted restriction sites, homopolymers, tandem repeats, predicted secondary structure, and a few cryptic-motif classes, were resolved by synonymous codon swaps without changing the encoded protein. It does not run a vendor's proprietary manufacturability scoring, and it never touches premature stop codons or GC extremes, both of which need a human decision.

Why does melting_temperature return three different Tm numbers instead of one?

It reports a nearest-neighbour estimate using SantaLucia 1998 parameters, the Wallace rule, and a salt-adjusted formula, then labels one as recommended based on primer length: Wallace below about 14 nt, salt-adjusted otherwise. The formulas can disagree by tens of degrees at typical 20-35 nt primer lengths, which is why using the length-appropriate one instead of whichever formula is easiest to recall from memory matters.

How long does data stashed with session_create last on SeqBench's MCP server?

24 hours. The session_* tools are the only stateful tools in SeqBench's MCP server; everything else is a pure, idempotent function of its own arguments. Sessions are explicitly scratch space for one working design session, not a durable store.

Which AI agents or MCP clients can use SeqBench's server?

Any client implementing the standard MCP handshake, initialize plus tools/list and tools/call, and optionally prompts/list and prompts/get, can drive it, including Claude Desktop, Claude Code, and Cursor. SeqBench has a server.json prepared for the official MCP registry, but as of this writing it has not been published there, so an agent has to be pointed at the endpoint directly rather than discovering it via registry search.

Related tools

Related guides