cheminfo-mcp-server
OfficialClick on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@cheminfo-mcp-serverWhat's the monoisotopic mass of C6H12O6?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
cheminfo-mcp-server
Serve tools to MCP clients and to the cheminfo chat from one definition, with the structures, reaction schemes, spectra and files they produce carried beside the answer, never through the model.
One tool definition gives a server three routes:
Route | For | Answers |
| the chat, any client | the catalog: each tool's name, title, description, strict JSON Schema and hints |
| the chat, the page |
|
| MCP clients | MCP's Streamable HTTP, stateless: a server per request, JSON answers |
result is what the model reads. The other fields are drawn by the page or the chat beside it.
Installation
npm install cheminfo-mcp-serverThe server entry needs fastify (5) and zod (4). cheminfo-mcp-server/client and cheminfo-mcp-server/contract need only zod, and run in a browser.
Related MCP server: wazza-mcp-test-server
A server
import { fastify } from 'fastify';
import {
createToolRoutes,
defineTool,
wellKnownNotFound,
} from 'cheminfo-mcp-server';
import { z } from 'zod';
const mfInfo = defineTool({
name: 'mfInfo',
title: 'Molecular formula',
description: 'Mass and composition of a molecular formula, e.g. "C6H12O6".',
schema: z.strictObject({ mf: z.string() }),
execute: ({ mf }) => ({
result: { mf, monoisotopicMass: 180.0634 },
molecules: [{ smiles: 'OC[C@H]1OC(O)[C@H](O)[C@@H](O)[C@@H]1O' }],
}),
});
const app = fastify();
await app.register(wellKnownNotFound);
await app.register(
createToolRoutes({
name: 'molecules',
version: '1.0.0',
instructions: 'Tools on molecules and molecular formulas.',
tools: [mfInfo],
}),
{ prefix: '/v1' },
);A tool's schema is a strict zod object: an unknown parameter is refused. A parameter set to
nullis left out, and a single value under another name is moved to a tool's only parameter, because small models rename it.A tool that throws answers 500 to the JSON route and an error result to MCP. The error itself never reaches the caller;
onErroris told.A tool refuses a call with its own status by throwing
new ToolRefusalError({ status: 503, code: 'loading', error: 'The copy is loading.', retryAfter: 30, extra: { mirror } }). The JSON route answers that status,{ error, code, ...extra }and Retry-After; MCP answerserroras an error result.An unknown tool is a 404 before the caller is checked;
unknownToolMessagewords it.Tools are read-only by default (
READ_ONLY_ANNOTATIONS); a tool says otherwise withannotations.toolsmay be a function, evaluated per request, when the descriptions change at run time.routeConfigis merged into theconfigof the two POST routes, for@fastify/rate-limit.
Who is asking
A server whose tools need to know the caller resolves a context per request:
createToolRoutes<{ email: string }>({
name: 'scipeaks-mcp',
version,
tools,
resolveContext: async (request, route) => {
const email = await checkToken(request.headers['x-eln-token']);
return email === null
? {
ok: false,
refusal: {
status: 401,
code: 'no-credentials',
error: 'Send your token.',
},
}
: { ok: true, context: { email } };
},
});A refusal answers its status before MCP starts, with WWW-Authenticate: Bearer on a 401. A 503 is the exception: MCP still lists the tools, and each call answers the refusal's sentence, so a client sees the tools while the server catches up. route is 'mcp' or 'tools', for a server that accepts different credentials on each.
A browser Origin other than the page's own is refused on POST mcp unless listed in allowedOrigins.
A client
import { createToolClient } from 'cheminfo-mcp-server/client';
const molecules = createToolClient({
baseUrl: 'https://molecules.cheminfo.org/v1/',
});
const catalog = await molecules.catalog();
const run = await molecules.callTool('mfInfo', { mf: 'C6H12O6' });
if (run.ok) {
console.log(run.value.result, run.value.molecules);
} else {
console.log(run.failure.kind, run.failure.message);
}Every reply is checked against the contract. A malformed side channel is dropped, never the result. A redirect is never followed, so a credential never leaves for another address. A failure is refused (the server's own code and sentence, with Retry-After, and its whole refusal in reply, the server's own fields included), unreachable, timeout or invalid-reply.
The contract
cheminfo-mcp-server/contract holds the zod schemas and types every side shares: ToolCatalogSchema, ToolRunReplySchema, ErrorReplySchema, DisplayMoleculeSchema, DisplayReactionSchema, DisplaySpectrumSchema and DisplayFileSchema, with their limits (MAX_MOLECULES, MAX_REACTIONS, MAX_SPECTRA, MAX_FILES).
License
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Build your own tools from chat: design, test and host them on a shareable MCP server URL.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Remote MCP server exposing SMI Aware tools, resources, and skills over Streamable HTTP.
Related MCP Servers
- -licenseNot gradedqualityNot gradedmaintenanceA unified HTTP/HTTPS service that exposes Model Context Protocol (MCP) functionality over HTTP endpoints, allowing clients to list available tools and call them through a standardized API.6 npm-
- FlicenseNot gradedqualityDmaintenanceA simple HTTP server to validate MCP infrastructure for the Wazza MCP client, exposing endpoints for tool discovery and calling.-
- FlicenseAqualityDmaintenanceUniversal MCP proxy server that discovers, searches, and executes tools across all configured MCP servers from a single entry point.7-
- FlicenseNot gradedqualityBmaintenanceFramework for building and running MCP servers as HTTP services. Define tools as pure Python functions, wire up with two lines, run with one command.-