Insipration
Traditional online chemistry research can be a hassle, with multiple tabs and half an hour of searching just to look up a molecule. As an example, to find a non-toxic polymer precursor built from only period-2 elements, the typical routine is searching PubChem and noting down hazard classifications and cross-checking molecular weights, a tough ask if you want to do it in a single tab.
What it does
The interface is an interactive periodic table and chemistry bench. A user describes a research goal, and through WebMCP an agent runs the workflow. On the interface, there is a build panel that keeps the scientist(user or agent) in control; everything is audited(keystrokes, tool calls) and logged by the trace panel via a ghost cursor.
Beginners/Non-experts can interactively play with the periodic table by combining elements. Full explanations for both successful molecules and rejected combinations.
Across the app, 23 tools are registered on document.modelContext.
Tools include
Selection and bonding: for 2D/3D molecular visualization.
** PubChem lookup:** for data grounding via the public API.
Molecular design and comparison: for similarity evaluation, comparative analysis, alternative search, hazard classification. All scored transparently.
Constraint solving: Async routines for multivariable discovery jobs, status streaming, candidate ranking and task cancellation
utilty and state: Full state serialisation.
All numbers are sourced directly from PubChem live and PubChem cached. Honest degradation to an offline bundled set when the API is unreachable.
How we built it
Vite and TypeScript

WebMCP.
@mcp-b/globalwraps a nativedocument.modelContextwhen the browser has one; a small spec-shaped shim covers the rest. Tools register synchronously at module load, so an agent scanning on page load already sees them.The store is a tiny observable. Every UI handler and every tool mutates state through it. A built-in operator runs the same tool that an external agent calls, so the command bar and a real agent share one code path. That was also our test harness.
Data comes from PubChem PUG REST and PUG View, called straight from the browser.
Rendering. 3Dmol.js for the 3D viewer, lazy-loaded and smiles-drawer for 2D structures.
Deployment: Vercel.
Challenges we ran into
PubChem rate-limiting Its public API throttles per client address and returns 503 under load, it was unreliable during quick iterations, so we bundled an offline compound set as fallback.
Finding the right surface Our first version registered tools on
navigator.modelContext. ChatGPT reported "no callable tools". Agents readdocument.modelContext. We moved there and added the shim.Async tool contracts The constraint solver could take fifteen seconds, and a timeout left half-built state on the canvas. We reworked it into a job that returns an id immediately, streams status, can be cancelled, and commits its result in a single step.
The 3D viewer got stuck Two model loads racing in before the 3Dmol chunk finished each created their own viewer on the same element, and later updates landed on the orphan. We used a single-flight guard to resolve this.
Trust in a science tool PubChem's aggregated GHS data includes minority-notifier misclassifications, so water in some examples was showing false hazards. We now read only the primary classification.
Accomplishments that we're proud of
- It works in one turn. Ask for a molecule by constraints, get a ranked, hazard-checked answer with a 3D model on the canvas, then edit a constraint and re-run without re-prompting.
- The beauty of the shared canvas. The agent and the person operate one instrument exactly like we envisioned
- Every claim is checkable: source and fetch time on every number, evidence-based hazard language, per-candidate rejection reasons.
- Our bundled fallback held out when PubChem was unreachable.
What we learned
WebMCP's value is shared state on a live surface. A headless MCP server can answer questions. It cannot manipulate pixels or read back what you just did.
Agent tools need async contracts. This is helpful for debugging.
Test against the actual agent surface early. ChatGPT caught the registration bug in minutes.
The built-in operator running the same tool path as an external agent was the best decision for development speed.
What's next for Valence
A richer chemistry surface with cross-references and deeper bioassay data.
A shareable recipe-card permalink, so a build can be sent to someone.
A multi-compound bench, so an agent can lay out a small reaction rather than one molecule at a time.
A resilient data path for the PubChem rate limits, and more teach-mode content for beginners.
Built With
- codex
- javascript
- pubchem
- vercel
- webmcp
Log in or sign up for Devpost to join the conversation.