Skip to main content
Glama

chemdraw-mcp

CI Release License: Apache-2.0

채팅 → 화학 구조. Claude Desktop용 MCP 서버: 분자, 반응 또는 실험 결과를 평범한 말로 설명하면, 서버가 그림을 그려 줍니다 — RDKit으로 로컬에서 렌더링한 인쇄용 PNG/SVG와 채팅 안의 대화형 미리보기까지. "아스피린 그려 줘" 는 그 자체로 완전한 명령입니다.

육각형을 클릭하는 데 너무 많은 시간을 쓰는 약학·화학 전공 학생들을 위해 만들어졌습니다. 리포트나 슬라이드에 실제로 필요한 것을 20개의 도구가 담당합니다: 구조, 반응식, 단계별 메커니즘, 기질 범위 그림, TLC 플레이트, 적정 곡선, 개략적 스펙트럼, 물질 데이터 시트, Ph.Eur. 함량 계산, Anki 덱.

비용은 설치 명령 하나뿐입니다. Apache-2.0, API 키 없음, 서버 가입 없음, ChemDraw 라이선스 불필요 — Claude Desktop과 uv만 있으면 나머지는 한 번에 가져옵니다. 렌더링은 전적으로 사용자 컴퓨터에서 실행되며, 이름 해석과 데이터베이스 조회만 인터넷에 접속합니다. ChemDraw CDXML은 그곳에서 계속 편집하고 싶은 사람들을 위한 선택적 추가 형식일 뿐, 필수 조건이 아닙니다.

출력 예시

"카페인 그려 줘" — generate_molecule이 생성한 인쇄용 PNG:

"에탄올과 아세트산의 Fischer 에스터화 반응 보여 줘" — generate_reaction이 화살표 위에 조건을 표시한 반응식을 채팅 패널에 실시간으로 렌더링합니다:

"Fischer 에스터화 메커니즘을 단계별로 보여 줘" — generate_mechanism이 대화형 패널에 곡선 전자 흐름 화살표를 렌더링합니다:

"내 Suzuki 커플링 범위 그림을 만들어 줘: 3a 92%, 3b 88% (12시간 후), 3c 64% (ee 94%, dr 10:1), 3d 71%" — generate_scope_table이 일반 반응식을 조건과 함께 위에, 생성물들을 그 아래에 배치하며, 공통 결합 길이와 공통 캡션 기준선을 사용합니다:

"에틸 아세테이트의 IR 스펙트럼을 스케치해 줘" — generate_spectrum(주어진 피크를 유형별 축 규칙에 따라 그립니다):

"내 에스터화 반응의 TLC: 출발물질 0.30, 생성물 0.65, co-spot은 둘 다 보이고, 출발물질이 일부 남아 있음" — generate_tlc가 실험 보고서가 요구하는 플레이트를 이동상과 검출법을 캡션으로 넣어 그립니다:

"카페인을 3D로 보여 줘" — generate_3d가 분자(ETKDG + 포스 필드)를 임베드하고 채팅 패널에 드래그로 회전 가능한 ball-and-stick 뷰어를 엽니다:

"이부프로펜과 나프록센, 케토프로펜의 차이는 무엇인가요?" — compare_molecules가 공통 스캐폴드(MCS)는 중립으로 유지하고 다른 모든 부분을 강조합니다:

"인산을 NaOH로 적정하는 곡선, 지시약은 페놀프탈레인" — generate_titration_curve가 정확한 전하 균형에서 pH를 계산하며, 당량점, 완충점(pH = pKa), 지시약 변색 범위를 표시합니다. 그 자매 도구인 generate_species_distribution은 각 pH에서 어떤 양성자화 종이 우세한지 보여 줍니다:

"중요한 분자들로 Anki 덱을 만들고 Anki에서 열어 줘" — export_anki_deck이 렌더링된 구조가 포함된 가져오기 준비 완료 .apkg를 만듭니다. 선택적 AnkiConnect 애드온을 사용하면 카드가 실행 중인 Anki에 바로 들어가며 클릭이 필요 없습니다:

Related MCP server: ChemMCP

기능

서버가 제공하는 20개 도구 전체. 파일은 ~/ChemDraw-Output/에 작성되며, 모든 그리기 도구는 채팅 패널용 실시간 미리보기도 반환합니다.

구조 및 반응식

  • generate_molecule — 이름/SMILES → PNG + SVG 2D 구조(선택적으로 CDXML), 물성, 작용기 검출, Lipinski 5의 법칙 검사 포함

  • batch_generate — 한 번의 호출로 구조 목록 전체

  • generate_reaction — 출발물질 + 생성물 + 조건 → 화살표 위에 조건이 표시된 반응식

  • generate_mechanism — 곡선 화살표 메커니즘(SN1, SN2, Fischer 에스터화)을 단계별로

  • generate_scope_table — 방법론 문헌의 기질 범위 그림: 조건이 위에 있는 일반 반응식, 그 아래에 생성물 그리드, 각각 식별자("1a")와 수율("78%") 및 선택적 ee/dr/시간 표시. 모든 구조는 하나의 결합 길이를 공유하고 모든 캡션은 하나의 기준선을 사용합니다. 해석할 수 없는 항목은 치명적 오류가 아닌 보고로 처리됩니다

  • compare_molecules — 2~4개 구조를 나란히 비교, 차이점 강조, 공통 스캐폴드(MCS)는 중립

  • generate_3d — 채팅 패널에서 회전 가능한 3D ball-and-stick 컨포머(ETKDGv3 + 포스 필드) 및 SDF 내보내기

실험 결과 및 분석

  • generate_spectrum — 피크 목록에서 개략적 스펙트럼 생성(IR, NIR, Raman, UV/Vis, 형광, ORD, CD, ¹H/¹³C NMR, MS) — 유형별 축 규칙 적용, 주어진 피크를 그릴 뿐 스펙트럼을 예측하지는 않습니다

  • generate_tlc — Rf 값에서 TLC 플레이트 스케치: 아래쪽 시작선, 위쪽 용매 전면, 적용 지점별 캡션 레인(출발물질 / 반응 / co-spot), 각 스팟에 Rf 주석, 이동상과 검출법을 캡션으로 표시 — 실험 보고서가 요구하는 스케치

  • generate_titration_curve — 정확한 전하 균형에서 계산한 pH 대 적정제 부피 곡선, 당량점, 완충점(pH = pKa), 지시약 변색 범위 포함

  • generate_species_distribution — pH에 따른 양성자화 종 분율(Henderson–Hasselbalch), pKa 교차점 표시

  • generate_calibration_curve — 표준물질을 통한 최소제곱 회귀선과, 자로 재듯 그 선에서 읽어낸 미지 시료 값. 검량 범위 밖의 시료는 조용히 보고하지 않고 외삽으로 표시합니다. 검출 한계와 정량 한계(DIN 32645)도 검증 문제에 함께 제공됩니다

벤치 계산 (숫자 그리고 풀이 과정 — 실험 보고서는 둘 다 요구합니다)

  • calculate_solution — 칭량할 양(m = c · V · M), 실제로 얻은 값, 희석(C₁V₁ = C₂V₂, 용매 부피 명시), 혼합 십자법, CuSO₄·5H₂O 같은 수화물을 포함한 몰 질량. 계산된 분취량이 분석 저울의 분해능보다 낮으면 경고합니다 — 그럴 때는 더 큰 분취량을 희석하는 것이 올바른 방법입니다

  • calculate_content — 프로토콜이 요구하는 방식의 함량 측정: 측정값별 함량 → Grubbs 이상치 검정 → 평균, s, RSD → 표시 함량에 대한 t-검정. 적정(기준 적정에서 역가 결정 포함)과 광도법, 그리고 산가, 검화가, 에스터가, 요오드가 같은 지방 특성과 Karl Fischer 수분 함량을 추가 method로 제공

  • calculate_ph — 약산·강산, 약염기·강염기, 완충액, 칭량 가능한 질량까지 내려가는 완충액 조제법. 정확한 전하 균형으로 풀고 교과서 근사식을 옆에 함께 표시합니다: 둘이 어긋날 때는 근사식의 가정이 무너졌다는 뜻이며 그렇게 알려 줍니다. 10⁻⁸ M HCl은 pH 8이 아니라 6.98로 나옵니다

물질 데이터 (온라인 조회)

  • lookup — 질문당 하나의 topic으로 텍스트 형태의 사실 정보: properties(분자식, 질량, CAS, InChIKey — 기본값), safety(GHS 유해·위험 문구, 픽토그램, 신호어), physical(녹는점/끓는점, 용해도, 밀도), biochem(ChEBI 분류 및 관련 UniProt 항목), pathway(KEGG의 대사 경로)

  • lookup_molecule_data — PubChem + GHS를 하나의 데이터 시트로 결합하여 채팅 패널에 표시, 구조 포함

  • predict_spectrum — 구조가 보여야 할 IR 밴드(강도와 밴드 모양 포함), 측정된 파수(wavenumber)가 무엇에 해당할 수 있는지, 예상되는 ¹H 신호 수와 적분비. 결정론적이므로 할 수 없는 일도 명확히 말합니다: ppm 단위의 화학적 이동은 제공하지 않으며, diastereotopic 양성자는 하나의 신호로 계산합니다

시험 준비

  • export_anki_deck — 가져오기 준비 완료 Anki .apkg 형태의 플래시카드: 구조↔이름 암기(선택적으로 양방향: 하나의 노트로 두 방향 모두), cloze/빈칸 채우기 카드, 확인/검출 반응, 스펙트럼 밴드 배정 — 렌더링된 이미지 임베드, 카드별 태그, Parent::Child 하위 덱 포함. 덱을 다시 내보내면 카드가 중복되지 않고 업데이트됩니다. 선택적으로 AnkiConnect 애드온을 통해 실행 중인 Anki로 직접 전달. 직접 만든 카드 대신 curated_deck_id를 전달하면 검증된 소규모 스타터 덱(고전 진통제, Ph.Eur. 확인 반응)을 받을 수 있습니다

모든 도구는 다섯 영역 중 하나에 속합니다 — 그리기, 실험 그래픽, 조회, 계산, Anki — 그리고 각 도구는 자신이 무엇을 위한 것이 아닌지 양방향으로 명시하므로, "아스피린 그려 줘"가 기질 범위 그리드에 들어갈 수 없고 "내 완충액의 pH는 얼마지?"가 플로팅 도구에 들어갈 수 없습니다. 이 영역 밖에 있는 도구가 하나 있습니다: save_png는 패널의 내보내기 버튼의 서버 측으로, 버튼을 클릭할 때 호출되며 단독으로는 호출되지 않습니다.

두 개의 선택적 볼트 도구(search_vault, read_vault_entry)는 CHEMDRAW_VAULT_PATH가 설정된 경우에만 나타나며, 설정이 없으면 서버는 정확히 위의 20개 도구만 제공합니다.

그리기 도구의 옵션

  • formats — 기본값은 ["png","svg"]이며, generate_molecule, generate_reaction, batch_generate에는 여기에 "cdxml"이 추가됩니다. 그림 도구(generate_scope_table, generate_tlc, generate_spectrum)는 의미 없는 파일을 쓰는 대신 명확한 오류와 함께 CDXML을 거부합니다.

  • abbreviate_groups=True — 흔한 치환기를 화학자들이 실제로 쓰는 라벨(Ph, Bn, OMe, OAc, tBu, CO₂H, Boc, Ts, TBS)로 그립니다. 셀이 작아질 때 유용합니다. 기질 간에 다른 부분만 풀어서 표기되므로 스코프 그림이 계속 읽기 쉽게 유지됩니다. generate_molecule, generate_reaction, generate_scope_table, batch_generate에서 사용할 수 있습니다.

  • render_style — 렌더링 파라미터 묶음 대신 이름이 붙은 스타일로, 동일한 네 가지 도구에서 사용합니다. "compact"(가는 결합, 제한된 라벨 크기, 좁은 여백)는 2단 레이아웃의 작은 그림용, "presentation"(두 배 결합 폭, 최소 글꼴 크기, 더 넉넉한 패딩)은 강의 슬라이드용, "grayscale"은 흑백 인쇄용으로, 이 경우 빨간색과 파란색이 구분할 수 없는 두 회색으로 보이는 문제를 방지합니다. 비어 있으면 기본 모양을 그대로 사용합니다.

  • annotate_stereo=True — 2D 그림(generate_molecule, batch_generate)에 CIP 입체 설명자(R/S, E/Z)를 표시합니다.

설치

세 가지 방법이 있습니다. 하나를 선택하세요. 옵션 1과 2는 설정에 멱등적으로 병합되며, 먼저 백업해 두고 다른 MCP 서버 설정은 건드리지 않습니다. 그 후 Claude Desktop을 재시작하고 *"caffeine 그려줘"*라고 물어보세요.

옵션 1 — 저장소 클론 (코드를 읽거나 수정하려면 권장; uv가 없으면 설치하고, 의존성을 동기화하고, 서버를 등록합니다):

git clone https://github.com/jurimaxam-dotcom/chemdraw-mcp.git
cd chemdraw-mcp && ./install.sh

옵션 2 — PyPI에서, 클론 없이 (uv 필요):

uv tool install chemdraw-mcp
chemdraw-install

chemdraw-install은 설치된 런처의 절대 경로를 사용하여 Claude Desktop 항목을 작성하고, 등록한 시작 명령을 출력합니다.

옵션 3 — 설정을 직접 편집. claude_desktop_config.json의 mcpServers 아래에 다음을 추가하세요 (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json):

"chemdraw-tool": {
  "command": "/opt/homebrew/bin/uvx",
  "args": ["chemdraw-mcp"]
}

수동 설치를 망가뜨리는 유일한 함정: Claude Desktop은 로그인 셸에서 MCP 서버를 시작하지 않습니다. 최소 GUI PATH를 사용합니다. 따라서 "uvx"나 "uv"만 적어서는 해석되지 않고, 서버는 아무 말 없이 시작에 실패합니다. 항상 여러분 머신에서 which uvx가 출력하는 절대 경로를 command에 넣으세요. 옵션 1과 2는 이 작업을 대신 해줍니다.

선택적 추가 기능

  • Java 런타임 (예: brew install openjdk)이 있으면 OPSIN이 체계적 IUPAC 이름을 오프라인으로 해석할 수 있습니다. 데이터베이스에 없는 이름도 포함됩니다. Java가 없으면 리졸버는 단순히 PubChem/NCI 온라인 조회로 넘어갑니다.

  • AnkiConnect 애드온이 있으면 export_anki_deck이 실행 중인 Anki로 카드를 직접 푸시할 수 있습니다. 없으면 .apkg 파일을 받아 직접 가져오면 됩니다.

  • ChemDraw (macOS)는 절대 필요하지 않습니다. formats=["cdxml"]을 요청하고 계속 편집하려면 파일을 직접 여세요.

뭔가 작동하지 않나요? doctor를 실행하세요

chemdraw-doctor                            # after "uv tool install chemdraw-mcp"
uv run chemdraw-doctor                     # in the cloned repo
uvx --from chemdraw-mcp chemdraw-doctor    # without installing anything

이것이 가장 먼저 시도할 방법입니다. "서버가 아무것도 안 함"을 원인 이름으로 바꿔줍니다. 채팅에서 서버가 죽은 것처럼 보이게 만드는 여섯 가지(RDKit 렌더링, Java/OPSIN 런타임, uv 경로, Claude Desktop 항목, 이름 데이터베이스, 출력 디렉터리)를 확인하고, 각 문제에 대해 정확한 해결 명령을 출력합니다. 세 가지 수준으로 구분됩니다: [OK], [LIMITED](작동하지만 제한됨), [FAIL](고장); [NOTE]는 해당하지 않는 검사(예: Claude Desktop이 설치되지 않은 경우)를 표시합니다. 서버가 사용 가능한 한 종료 코드는 0으로 유지되므로 스크립트에서 실행할 수 있습니다. (PyPI 설치에서는 uv 및 Claude Desktop 검사가 [NOTE]로 보고됩니다. 이는 저장소 설치 프로그램과 관련된 항목입니다.)

제한 사항

보고서에서 놀라운 일이 없도록 미리 밝힙니다:

  • Java는 선택 사항이며, 그 대가가 있습니다. JRE가 없으면 OPSIN을 건너뛰고 이름은 PubChem/NCI를 통해 온라인으로 해석됩니다. 따라서 이름 조회는 인터넷 연결이 필요하고 해당 데이터베이스가 색인한 이름에 대해서만 작동합니다. SMILES 입력은 네트워크에 접촉하지 않습니다.

  • 스펙트럼은 개략적입니다. generate_spectrum은 전달받은 피크를 스펙트럼 유형에 맞는 축 규칙으로 그립니다. 측정하거나 예측하지 않습니다. 피크 값이 계측기가 아니라 채팅에서 온 것이라면 보고서에 넣기 전에 검증하세요.

  • TLC 강도는 그리기 힌트입니다. 선택적 intensity(0…1)는 스케치에서 반점을 더 흐리게 만듭니다. 농도 측정이 아니며 정량적 의미를 갖지 않습니다.

  • CDXML은 보조 경로입니다. RDKit 분자에서 작성되고 왕복 검증되지만, PNG/SVG가 기본 출력이며 픽셀 테스트가 다루는 대상입니다. CDXML은 기본적으로 꺼져 있고 구조와 반응식으로 제한됩니다. TLC 플레이트, 스코프 그림, 스펙트럼은 이를 거부합니다.

  • 3D는 단일 컨포머입니다. generate_3d는 ETKDGv3로 임베딩하고 MMFF로 최적화합니다(UFF가 대체). 이는 보기 위한 그럴듯한 기하 구조이지, 컨포메이션 탐색도 에너지 진술도 아닙니다.

  • ChemDraw 브리지는 macOS 전용이며 로컬에 설치된 ChemDraw가 필요합니다. 그 외 모든 것은 그것 없이 작동합니다.

작동 방식

name / SMILES
   │
   ▼
resolver ──► OPSIN (systematic IUPAC names, offline) ──► PubChem / NCI (names)  ·  direct parse (SMILES)
   │
   ▼
RDKit 2D coordinates ──► validation (sanity, round-trip)
   │
   ├──► image_export   → PNG + SVG files          (primary, offline)
   ├──► svg_renderer   → interactive chat preview (MCP App resource)
   └──► cdxml_writer   → ChemDraw CDXML           (optional, on request)

개발

Python 3.11+, 패키지 관리자 uv.

uv sync                      # backend deps
cd chemdraw_tool/ui && npm install && npx playwright install chromium  # frontend, once
./test.sh                    # the gate: pytest + JS unit + headless-Chromium e2e

테스트 우선 방식으로 작성된 600개 이상의 테스트. e2e 테스트는 실제 RDKit SVG를 헤드리스 Chromium에서 래스터화하고 정확한 픽셀 스냅샷과 비교합니다. 내보내기 경로와 채팅 내 미리보기는 동일한 그리기 상수로 유지됩니다.

라이선스

Apache-2.0 — LICENSE 참조. 저작권 2026 jurimaxam-dotcom.

고지: 이는 비공식적이고 독립적인 프로젝트로, Revvity와 제휴하거나 보증하지 않습니다. ChemDraw는 Revvity Signals Software, Inc.의 상표입니다. 이 도구는 ChemDraw를 포함하거나 요구하지 않습니다. 선택적으로 개방형 CDXML 형식으로 파일을 내보낼 수 있습니다.

Available Tools

7 tools
batch_generateA

Draw several individual compounds as separate PNG/SVG files and panels.

Failed names are reported in failed while successful structures are returned. Pass English or IUPAC names, or SMILES.

Not this tool for: one compound (use generate_molecule), structural differences (use compare_molecules), or a reaction scheme (use generate_reaction).

Args: molecules: List of English/IUPAC compound names or SMILES strings. formats: Output file formats, any of "png", "svg", "cdxml" (default: ["png", "svg"]). Include "cdxml" ONLY when the user wants to edit the structures in ChemDraw. abbreviate_groups: Set True to draw common substituents as short labels (Ph, Bn, OAc, OMe, CO2H, tBu, Boc, Ts …) instead of full skeletons. Applies to every molecule in the batch, so a series of structures stays visually consistent. render_style: Named look applied to every molecule in the batch. Empty = standard style. "compact" for small printed figures, "presentation" for slides, "grayscale" for grayscale printing.

NameRequiredDescriptionDefault
formatsNo
moleculesYes
render_styleNo
annotate_stereoNo
abbreviate_groupsNo

Output Schema

NameRequiredDescription
typeNo
failedNo
moleculesNo
cdxml_pathsNo

TDQS

A4.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Since no annotations are provided, the description carries the full burden and performs well. It explicitly details a key behavioral trait: failed names are reported while successful structures are returned. It also explains the conditional use of 'cdxml' for ChemDraw editing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The tool definition is structured logically, starting with the core function, then providing limitations, and finally detailing parameters. Every section is tightly written and efficiently organized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of handling batch processing, multiple formats, and custom rendering, the description is remarkably complete. It provides all the necessary context and constraints for an agent to invoke the tool correctly despite the sparse structured data.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite having 0% schema description coverage, the description provides high-value semantic context for every parameter. For instance, it explains the functional difference between 'abbreviate_groups' (consistency) and 'render_style' (use case for printing/slides), adding meaning far beyond the schema data.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The purpose is highly specific: drawing multiple individual compounds as PNG/SVG files and panels. It clearly distinguishes itself from sibling tools by stating it is not suitable for single compounds (use generate_molecule), reaction schemes, or structural comparisons.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The tool explicitly forbids certain use cases, detailing that it should not be used for single molecules, structural differences, or reaction schemes. It provides direct redirection to the correct alternative sibling tool for each specific scenario.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compare_moleculesA

Compare 2-4 molecules side by side with their DIFFERENCES highlighted.

Computes the maximum common substructure (MCS): the shared scaffold stays neutral, everything outside it is highlighted — ideal for teaching drug classes ("what distinguishes ibuprofen from naproxen?"), homologous series or derivatives.

Use this when the user wants to compare structures, see differences between compounds, or study a drug class.

Reach for it in conversation too, not only on request: the word "difference" in a question about two substances is the trigger. Answering "what distinguishes ibuprofen from naproxen?" in prose leaves the reader to find the difference in two separate pictures — this figure marks it.

Not this tool for: a single structure (generate_molecule), or several structures that are merely to be drawn rather than contrasted (batch_generate).

Args: structures: 2-4 English/IUPAC names or SMILES strings. labels: Optional display names under each panel (localizable). title: Optional heading for the comparison (localizable).

NameRequiredDescriptionDefault
titleNo
labelsNo
structuresYes

Output Schema

NameRequiredDescription
svgNo
nameYes
typeNo
filesNo
notesNo
subtitleNo

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full load — it discloses the algorithmic behavior (MCS computed, shared scaffold kept neutral for contrast) and that the result is a figure rather than prose, which is meaningful behavioral context. It stops short of stating failure behavior for unresolvable names or whether a file is written, which are the remaining gaps for an annotation-free tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core definition, then usage, then exclusions, then args — a rational order with clear sectioning. The conversational-trigger paragraph is slightly padded and repeats the ibuprofen/naproxen example already used earlier, costing a point.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and the description covers scope, exclusions, and all three parameters. The only thin spot is edge-case behavior — what happens with fewer than 2 structures, more than 4, or an unresolvable name.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: structures accepts 2-4 English/IUPAC names or SMILES, labels are per-panel display names that are localizable, and title is an optional localizable heading. This adds real meaning beyond the bare schema types and closes the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Compare 2-4 molecules side by side') and explains the mechanism (maximum common substructure with non-shared parts highlighted), which tells the agent exactly what the output depicts. It also names the siblings it is not (generate_molecule, batch_generate), so it is distinguishable without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use triggers ('user wants to compare structures', 'study a drug class'), an explicit not-for clause with named alternatives for both exclusions, and even a conversational trigger word ('difference'). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_anki_deckA

Export an Anki flashcard deck (.apkg) with rendered chemistry images.

Use this whenever the user wants flashcards, Anki cards or a study deck for molecules, reactions (e.g. pharmacopoeia identity tests) or spectra. A stated intention to learn or an exam coming up is the same request: offer a deck and write the cards yourself.

Two ways to fill the deck. Either pass cards you wrote yourself, or pass curated_deck_id for a ready-made, formula-verified starter deck:

  • "analgesics-structures": structure → name drills for 8 classic analgesics (NSAIDs, paracetamol, morphine, celecoxib).

  • "pheur-identity-basics": classic Ph.Eur. identity tests — reagent, observation and reaction scheme where it helps.

The tool renders the images — YOU supply the card content from your knowledge. Each card side carries text plus at most ONE visual: structure (name or SMILES), reaction ({reactants, products, conditions}) or spectrum ({spectrum_type, peaks, title}). Proven types: structure↔name, identity reactions (question front, scheme back), functional-group recognition, band assignment, name drills.

Re-exporting under the SAME deck name updates existing cards instead of duplicating them — the front identifies the card.

Options: reversed=true drills both directions (one note, two cards); cloze=true makes fill-in-the-blank cards (front.text carries {{c1::...}}, back.text becomes the extra note). "Parent::Child" nests subdecks.

IMPORTANT: structures take English/IUPAC names or SMILES; card TEXTS may be localized. Never deliver via AnkiConnect unless asked.

Args: deck_name: Deck name, also the filename; re-use it to update a deck. Ignored when curated_deck_id is set. cards: The flashcards. Fronts unambiguous, explanations on the back. default_tags: Tags added to every card. deliver: "apkg" (file only), "open" (also opens it in Anki, macOS) or "ankiconnect" (imports via the AnkiConnect add-on). curated_deck_id: "analgesics-structures" or "pheur-identity-basics".

NameRequiredDescriptionDefault
cardsNo
deliverNoapkg
deck_nameNo
default_tagsNo
curated_deck_idNo

Output Schema

NameRequiredDescription
fileNo
nameYes
typeNo
cardsYes
mediaYes
frontsNo
deliveryNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does it well: same deck name updates rather than duplicates (front is the key), `deck_name` is ignored when `curated_deck_id` is set, `deliver` has three concrete modes, `reversed` produces one note/two cards, `cloze` changes what front/back mean, and 'Parent::Child' nests subdecks. These are non-obvious side effects an agent could not infer from the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Long but front-loaded and segmented: purpose first, then triggers, then the two fill paths, then card anatomy, then options, then per-argument notes. Every paragraph answers a distinct question an agent would otherwise have to guess at.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex nested-card export tool with 5 params, the description covers card construction, proven card types, update semantics and delivery modes; the output schema relieves it of explaining return values. Minor gap: it doesn't say what happens if neither `cards` nor `curated_deck_id` is supplied, nor where the .apkg file is written.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% at the top level, but the Args block documents all five parameters, including the enum-like values for `deliver` and `curated_deck_id` that the schema does not constrain. The card-side constraint (text plus at most ONE visual, with the shapes of structure/reaction/spectrum) supplies the nesting semantics the schema leaves implicit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and artifact: 'Export an Anki flashcard deck (.apkg) with rendered chemistry images.' It also clarifies the division of labour (tool renders images, the agent supplies card content), which no sibling tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the triggering situations (flashcards, study deck, exam coming up, intent to learn) and routes between the two fill modes: own `cards` vs `curated_deck_id`. It also states an exclusion ('Never deliver via AnkiConnect unless asked') and names both curated deck IDs with their contents.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generate_moleculeA

Draw one compound as a 2D structure — the default for a single substance.

Writes PNG/SVG files and returns an interactive panel with the structure, properties and functional groups. A bare compound name ("caffeine") also means this tool, and so does a question about why one compound behaves as it does (acidity, solubility) — the answer is in its structure. No ChemDraw required. A Fischer or Haworth projection of a sugar or amino acid, or a drawing with all H atoms, is this tool too: set view to "fischer", "haworth" or "all_h".

Not this tool for: several individual structures (use batch_generate), structural differences (use compare_molecules), a reaction scheme (use generate_reaction), or a data sheet (use lookup_molecule_data).

Pass English or IUPAC names, or SMILES; use label for a localized display name.

Args: name_or_smiles: English/IUPAC compound name or SMILES string. label: Display name shown below the structure (may be localized). formats: Any of "png", "svg", "cdxml" (default: png + svg). Add "cdxml" only when the structure is to be edited in ChemDraw. annotate_stereo: True prints CIP descriptors (R/S, E/Z) at each stereocenter. abbreviate_groups: True draws common substituents as the short labels chemists write by hand (Ph, Bn, OAc, OMe, CO2H, NO2, tBu, Boc, Ts, TMS). The chemistry is unchanged; no hover tooltips in the panel. render_style: "" standard · "compact" thin bonds for small print · "presentation" thick bonds for slides · "grayscale" b/w palette. stereo_variants: True returns every stereoisomer of the open centers (max 3) as a pick list instead of a drawing; only on request. view: "fischer"/"haworth"/"all_h" opens on that drawing, only if the user names it.

NameRequiredDescriptionDefault
viewNo
labelNo
formatsNo
render_styleNo
name_or_smilesYes
annotate_stereoNo
stereo_variantsNo
abbreviate_groupsNo

Output Schema

NameRequiredDescription
svgNo
nameNo
typeNo
atomsNo
filesNo
viewsNo
messageNo
viewSvgNo
lipinskiNo
subtitleNo
viewAtomsNo
candidatesNo
cdxml_pathNo
propertiesNo
stereoNoteNo
initialViewNo
viewRequestNo
projectionNoteNo
stereoWarningsNo
functionalGroupsNo

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses the file side effects (writes PNG/SVG), the return artifact (interactive panel with structure, properties, functional groups), and non-obvious behavioral consequences per flag (abbreviate_groups kills hover tooltips; stereo_variants returns a pick list instead of a drawing). It stops short of error behavior for invalid names/SMILES or whether existing files are overwritten.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Roughly front-loaded: purpose first, then routing, then args. Minor redundancy — the fischer/haworth/all_h options are stated once in prose and again under view — and 'No ChemDraw required' is filler, but no sentence is genuinely wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Eight parameters, no annotations, and an output schema. The description covers routing, all parameter semantics, side effects, and the return artifact, so an agent can call it correctly without reading anything else.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must supply all meaning, and it does: formats lists allowed values and the default, view names its three accepted values, render_style enumerates all four modes with intent, and the boolean flags each explain their effect (CIP R/S and E/Z labels; abbreviation set Ph/Bn/OAc/...; max 3 stereoisomer pick list).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a specific verb and resource ('draw one compound as a 2D structure') plus its scope ('the default for a single substance'). It then enumerates non-obvious inputs that also route here (bare compound name, a behavior question like acidity/solubility, Fischer/Haworth projections) and names each sibling that handles the other cases.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

An explicit 'Not this tool for:' block routes to batch_generate (several structures), compare_molecules (differences), generate_reaction (reaction schemes) and lookup_molecule_data (data sheets). Positive triggers are also given, including indirect ones like a question about why a compound behaves as it does.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generate_reactionA

Draw a reaction scheme from reactants, products and conditions.

Writes PNG/SVG files and returns a panel with conditions above and below the arrow. arrow: "forward" (→), "equilibrium" (⇌, reversible) or "retro" (⇒). Use it when explaining a reaction as well as for explicit drawing requests. This draws the net reaction, without step-by-step electron-flow mechanisms. Pass English or IUPAC compound names, or SMILES.

Not this tool for: one compound or a property of one compound such as its acidity (use generate_molecule), independent structures (use batch_generate), or structural differences (use compare_molecules).

Args: reactants: List of English/IUPAC reactant names or SMILES strings. products: List of English/IUPAC product names or SMILES strings. conditions: Text above the arrow (e.g. 'H2SO4, 0-5 °C'); formula digits are subscripted, a line break starts a new line. conditions_below: Text under the arrow (e.g. 'reflux, 2 h'). arrow: "forward" (→), "equilibrium" (⇌, reversible reaction) or "retro" (⇒, retrosynthesis: target as reactants, precursors as products). name: Display name for the reaction step (can be localized). formats: Any of "png", "svg", "cdxml" (default: png + svg). Add "cdxml" only when the scheme is to be edited in ChemDraw. abbreviate_groups: True draws common substituents as short labels (Ph, OAc, OMe, CO2H, tBu, Boc …); the CDXML keeps full structures. render_style: "" standard · "compact" small print · "presentation" slides · "grayscale" b/w palette. coefficients: One integer per species, reactants then products ([2, 1, 2] draws 2 H2 + O2 → 2 H2O). Set only when the user asks for a balanced equation; otherwise draw as given — the panel's "Apply coefficients" button sets them.

NameRequiredDescriptionDefault
nameNo
arrowNoforward
formatsNo
productsYes
reactantsYes
conditionsNo
coefficientsNo
render_styleNo
conditions_belowNo
abbreviate_groupsNo

Output Schema

NameRequiredDescription
nameNo
typeNo
arrowNo
filesNo
balanceNo
requestNo
productsNo
reactantsNo
cdxml_pathNo
conditionsNo
coefficientsNo
conditions_belowNo

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description does the heavy lifting: it discloses side effects (writes PNG/SVG/CDXML files), the return artifact (a panel with conditions above/below the arrow), and a limitation (no electron-flow mechanisms). It also warns that coefficients are only applied on request and that the CDXML keeps full structures under abbreviation. Missing only concrete file locations or overwrite behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then exclusions, then a per-argument list — easy to scan. It loses a point for duplicating the arrow enum definition verbatim in both the opening paragraph and the Args block.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter generative tool with an output schema, everything an agent needs is present: triggers, exclusions, input formats, output formats and defaults. Return value explanation is correctly omitted since an output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description fully compensates: it defines every non-obvious parameter, gives the enum meanings for arrow with glyphs and the retro semantics, enumerates formats with a default, explains render_style values, and specifies coefficients ordering ('reactants then products') with a worked example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Draw a reaction scheme from reactants, products and conditions') and immediately scopes it as the net reaction rather than a mechanism. Explicitly names each sibling it is not for and what to use instead.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives both a positive trigger ('Use it when explaining a reaction as well as for explicit drawing requests') and an explicit exclusion block listing generate_molecule, batch_generate and compare_molecules with the condition that selects each.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lookup_molecule_dataA

Show a compound's data sheet: structure, PubChem properties and GHS safety.

Use it for a data sheet or facts available from those sources. The molecule panel also calls this tool when the user clicks Data. Internet access is required. Missing values are not evidence that a property or hazard is absent.

Not this tool for: a bare compound name with no data requested — use generate_molecule. Pass English or IUPAC names, or SMILES.

Args: name: English/IUPAC compound name or SMILES (e.g. 'Aspirin').

NameRequiredDescriptionDefault
nameYes

Output Schema

NameRequiredDescription
nameNo
typeNo
atomsNo
smilesNo
sourcesNo
stereoNoteNo
molecule_svgNo
stereoWarningsNo
functionalGroupsNo

TDQS

A4.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Since no annotations were provided, the description carries the full burden of transparency. It explicitly states that 'Missing values are not evidence that a property or hazard is absent,' which is a critical behavioral caveat for a lookup tool pulling external data. It also notes the dependency on internet access.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is highly efficient. Every sentence adds value, moving from primary function to operational requirements, exclusions, and finally, parameter guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the critical nature of distinguishing it from `generate_molecule` and specifying input formats (SMILES/IUPAC/English), the description is maximally complete for an AI agent attempting correct tool selection.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema is extremely sparse (just 'name': 'string'). The description significantly enhances the schema by detailing that 'name' can be an English/IUPAC compound name or a SMILES string, providing concrete examples like 'Aspirin' to guide usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The purpose is immediately clear: to show a compound's data sheet including structure, PubChem properties, and GHS safety. It successfully differentiates itself from sibling tools by specifying its function as data retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The tool provides explicit instructions on when to use it and when *not* to use it, referring the agent to `generate_molecule` for bare compound names. It also adds the necessary operational constraint: internet access is required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

save_pngA

Internal helper for the panel UI — never call this directly.

The panel's export button calls it when the image clipboard is blocked by the sandbox; saving a picture is the user's click, not yours. The generate_* tools already write their PNG and SVG files themselves.

Expects a base64 PNG (with or without a data:image/png;base64, prefix) and returns the path it was written to.

NameRequiredDescriptionDefault
filenameYes
png_base64Yes

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the behavioral burden and does disclose the invocation context, the clipboard/sandbox condition, accepted input format, and that it returns the written path. It does not mention overwrite behavior, permissions, or error handling for file writes, which are relevant gaps for a save operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The warning not to call the tool is front-loaded, and the remaining sentences are short and purposeful. Every sentence adds either usage context or a relevant input/output detail without repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the description need not explain return values in detail, and it already states that a path is returned. For a two-parameter internal helper it is largely complete, though filename semantics remain underspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It partially does by explaining that png_base64 is a base64 PNG with an optional data:image/png;base64, prefix, but it says nothing about the filename parameter's expected path, directory, extension, or overwrite semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action (save a PNG), the expected input (base64 PNG), and the result (returns the written path). It also explicitly distinguishes this from the generate_* tools, which already write their own PNG and SVG files, so an agent can tell this is not the normal image-generation path.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an unusually explicit usage rule: never call this directly, because the panel's export button invokes it when sandbox clipboard access is blocked. It also names the relevant alternative behavior by noting that generate_* tools already write their files themselves.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.6.0
    • Changedbatch_generate12 fields changed
      • addedOutput schema / $defs / IsomerCandidate
        Added value: +{
        +  "description": "One structure a family name (\"xylene\", \"Glucose\") can mean.",
        +  "properties": {
        +    "label": {
        +      "title": "Label",
        +      "type": "string"
        +    },
        +    "name": {
        +      "default": "",
        +      "title": "Name",
        +      "type": "string"
        +    },
        +    "smiles": {
        +      "title": "Smiles",
        +      "type": "string"
        +    },
        +    "svg": {
        +      "default": "",
        +      "title": "Svg",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "label",
        +    "smiles"
        +  ],
        +  "title": "IsomerCandidate",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / MoleculePayload / properties / candidates
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "$ref": "#/$defs/IsomerCandidate"
        +  },
        +  "title": "Candidates",
        +  "type": "array"
        +}
      • addedOutput schema / $defs / MoleculePayload / properties / initialView
        Added value: +{
        +  "default": "",
        +  "title": "Initialview",
        +  "type": "string"
        +}
      • addedOutput schema / $defs / MoleculePayload / properties / message
        Added value: +{
        +  "default": "",
        +  "title": "Message",
        +  "type": "string"
        +}
      • addedOutput schema / $defs / MoleculePayload / properties / projectionNote
        Added value: +{
        +  "default": "",
        +  "title": "Projectionnote",
        +  "type": "string"
        +}
      • addedOutput schema / $defs / MoleculePayload / properties / stereoNote
        Added value: +{
        +  "default": "",
        +  "title": "Stereonote",
        +  "type": "string"
        +}
      • addedOutput schema / $defs / MoleculePayload / properties / stereoWarnings
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "$ref": "#/$defs/StereoWarning"
        +  },
        +  "title": "Stereowarnings",
        +  "type": "array"
        +}
      • addedOutput schema / $defs / MoleculePayload / properties / viewAtoms
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "$ref": "#/$defs/AtomData"
        +  },
        +  "title": "Viewatoms",
        +  "type": "array"
        +}
      • addedOutput schema / $defs / MoleculePayload / properties / viewRequest
        Added value: +{
        +  "additionalProperties": true,
        +  "default": {},
        +  "title": "Viewrequest",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / MoleculePayload / properties / viewSvg
        Added value: +{
        +  "default": "",
        +  "title": "Viewsvg",
        +  "type": "string"
        +}
      • addedOutput schema / $defs / MoleculePayload / properties / views
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "type": "string"
        +  },
        +  "title": "Views",
        +  "type": "array"
        +}
      • addedOutput schema / $defs / StereoWarning
        Added value: +{
        +  "description": "Ein Stereoelement, dessen Konfiguration die Eingabe offen lässt.",
        +  "properties": {
        +    "atoms": {
        +      "default": [],
        +      "items": {
        +        "type": "integer"
        +      },
        +      "title": "Atoms",
        +      "type": "array"
        +    },
        +    "kind": {
        +      "title": "Kind",
        +      "type": "string"
        +    },
        +    "label": {
        +      "default": "",
        +      "title": "Label",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "kind"
        +  ],
        +  "title": "StereoWarning",
        +  "type": "object"
        +}
    • Changedgenerate_molecule14 fields changed
      • addedInput schema / properties / stereo_variants
        Added value: +{
        +  "default": false,
        +  "title": "Stereo Variants",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / view
        Added value: +{
        +  "default": "",
        +  "title": "View",
        +  "type": "string"
        +}
      • addedOutput schema / $defs / IsomerCandidate
        Added value: +{
        +  "description": "One structure a family name (\"xylene\", \"Glucose\") can mean.",
        +  "properties": {
        +    "label": {
        +      "title": "Label",
        +      "type": "string"
        +    },
        +    "name": {
        +      "default": "",
        +      "title": "Name",
        +      "type": "string"
        +    },
        +    "smiles": {
        +      "title": "Smiles",
        +      "type": "string"
        +    },
        +    "svg": {
        +      "default": "",
        +      "title": "Svg",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "label",
        +    "smiles"
        +  ],
        +  "title": "IsomerCandidate",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / StereoWarning
        Added value: +{
        +  "description": "Ein Stereoelement, dessen Konfiguration die Eingabe offen lässt.",
        +  "properties": {
        +    "atoms": {
        +      "default": [],
        +      "items": {
        +        "type": "integer"
        +      },
        +      "title": "Atoms",
        +      "type": "array"
        +    },
        +    "kind": {
        +      "title": "Kind",
        +      "type": "string"
        +    },
        +    "label": {
        +      "default": "",
        +      "title": "Label",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "kind"
        +  ],
        +  "title": "StereoWarning",
        +  "type": "object"
        +}
      • addedOutput schema / properties / candidates
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "$ref": "#/$defs/IsomerCandidate"
        +  },
        +  "title": "Candidates",
        +  "type": "array"
        +}
      • addedOutput schema / properties / initialView
        Added value: +{
        +  "default": "",
        +  "title": "Initialview",
        +  "type": "string"
        +}
      • addedOutput schema / properties / message
        Added value: +{
        +  "default": "",
        +  "title": "Message",
        +  "type": "string"
        +}
      • addedOutput schema / properties / projectionNote
        Added value: +{
        +  "default": "",
        +  "title": "Projectionnote",
        +  "type": "string"
        +}
      • addedOutput schema / properties / stereoNote
        Added value: +{
        +  "default": "",
        +  "title": "Stereonote",
        +  "type": "string"
        +}
      • addedOutput schema / properties / stereoWarnings
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "$ref": "#/$defs/StereoWarning"
        +  },
        +  "title": "Stereowarnings",
        +  "type": "array"
        +}
      • addedOutput schema / properties / viewAtoms
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "$ref": "#/$defs/AtomData"
        +  },
        +  "title": "Viewatoms",
        +  "type": "array"
        +}
      • addedOutput schema / properties / viewRequest
        Added value: +{
        +  "additionalProperties": true,
        +  "default": {},
        +  "title": "Viewrequest",
        +  "type": "object"
        +}
      • addedOutput schema / properties / viewSvg
        Added value: +{
        +  "default": "",
        +  "title": "Viewsvg",
        +  "type": "string"
        +}
      • addedOutput schema / properties / views
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "type": "string"
        +  },
        +  "title": "Views",
        +  "type": "array"
        +}
    • Changedgenerate_reaction10 fields changed
      • addedInput schema / properties / arrow
        Added value: +{
        +  "default": "forward",
        +  "enum": [
        +    "forward",
        +    "equilibrium",
        +    "retro"
        +  ],
        +  "title": "Arrow",
        +  "type": "string"
        +}
      • addedInput schema / properties / coefficients
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "integer"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Coefficients"
        +}
      • addedInput schema / properties / conditions_below
        Added value: +{
        +  "default": "",
        +  "title": "Conditions Below",
        +  "type": "string"
        +}
      • addedOutput schema / $defs / MolEntry / properties / coefficient
        Added value: +{
        +  "default": 1,
        +  "title": "Coefficient",
        +  "type": "integer"
        +}
      • addedOutput schema / $defs / ReactionBalance
        Added value: +{
        +  "description": "Atom and charge balance of the equation as drawn (all coefficients 1).",
        +  "properties": {
        +    "balanced": {
        +      "title": "Balanced",
        +      "type": "boolean"
        +    },
        +    "chargeDifference": {
        +      "default": 0,
        +      "title": "Chargedifference",
        +      "type": "integer"
        +    },
        +    "difference": {
        +      "additionalProperties": {
        +        "type": "integer"
        +      },
        +      "default": {},
        +      "title": "Difference",
        +      "type": "object"
        +    },
        +    "formulas": {
        +      "default": [],
        +      "items": {
        +        "type": "string"
        +      },
        +      "title": "Formulas",
        +      "type": "array"
        +    },
        +    "note": {
        +      "default": "",
        +      "title": "Note",
        +      "type": "string"
        +    },
        +    "suggestedCoefficients": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "type": "integer"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "title": "Suggestedcoefficients"
        +    },
        +    "suggestedEquation": {
        +      "default": "",
        +      "title": "Suggestedequation",
        +      "type": "string"
        +    },
        +    "summary": {
        +      "default": "",
        +      "title": "Summary",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "balanced"
        +  ],
        +  "title": "ReactionBalance",
        +  "type": "object"
        +}
      • addedOutput schema / properties / arrow
        Added value: +{
        +  "default": "forward",
        +  "title": "Arrow",
        +  "type": "string"
        +}
      • addedOutput schema / properties / balance
        Added value: +{
        +  "anyOf": [
        +    {
        +      "$ref": "#/$defs/ReactionBalance"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedOutput schema / properties / coefficients
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "type": "integer"
        +  },
        +  "title": "Coefficients",
        +  "type": "array"
        +}
      • addedOutput schema / properties / conditions_below
        Added value: +{
        +  "default": "",
        +  "title": "Conditions Below",
        +  "type": "string"
        +}
      • addedOutput schema / properties / request
        Added value: +{
        +  "additionalProperties": true,
        +  "default": {},
        +  "title": "Request",
        +  "type": "object"
        +}
    • Changedlookup_molecule_data9 fields changed
      • addedOutput schema / $defs / DatabaseSource / properties / groups
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "$ref": "#/$defs/GhsGroup"
        +  },
        +  "title": "Groups",
        +  "type": "array"
        +}
      • addedOutput schema / $defs / DatabaseSource / properties / note
        Added value: +{
        +  "default": "",
        +  "title": "Note",
        +  "type": "string"
        +}
      • addedOutput schema / $defs / DatabaseSource / properties / status
        Added value: +{
        +  "default": "",
        +  "title": "Status",
        +  "type": "string"
        +}
      • addedOutput schema / $defs / GhsGroup
        Added value: +{
        +  "description": "Die Einstufung EINER Quelle (PubChem ReferenceNumber).",
        +  "properties": {
        +    "hazards": {
        +      "default": [],
        +      "items": {
        +        "$ref": "#/$defs/GhsHazard"
        +      },
        +      "title": "Hazards",
        +      "type": "array"
        +    },
        +    "id": {
        +      "title": "Id",
        +      "type": "string"
        +    },
        +    "lead": {
        +      "default": false,
        +      "title": "Lead",
        +      "type": "boolean"
        +    },
        +    "not_classified": {
        +      "anyOf": [
        +        {
        +          "$ref": "#/$defs/GhsNotClassified"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null
        +    },
        +    "note": {
        +      "default": "",
        +      "title": "Note",
        +      "type": "string"
        +    },
        +    "p_codes": {
        +      "default": [],
        +      "items": {
        +        "type": "string"
        +      },
        +      "title": "P Codes",
        +      "type": "array"
        +    },
        +    "pictograms": {
        +      "default": [],
        +      "items": {
        +        "type": "string"
        +      },
        +      "title": "Pictograms",
        +      "type": "array"
        +    },
        +    "record_name": {
        +      "default": "",
        +      "title": "Record Name",
        +      "type": "string"
        +    },
        +    "reports_total": {
        +      "anyOf": [
        +        {
        +          "type": "integer"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "title": "Reports Total"
        +    },
        +    "signal": {
        +      "default": "",
        +      "title": "Signal",
        +      "type": "string"
        +    },
        +    "source": {
        +      "title": "Source",
        +      "type": "string"
        +    },
        +    "url": {
        +      "default": "",
        +      "title": "Url",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "source"
        +  ],
        +  "title": "GhsGroup",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / GhsHazard
        Added value: +{
        +  "properties": {
        +    "code": {
        +      "title": "Code",
        +      "type": "string"
        +    },
        +    "percent": {
        +      "anyOf": [
        +        {
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "title": "Percent"
        +    },
        +    "text": {
        +      "default": "",
        +      "title": "Text",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code"
        +  ],
        +  "title": "GhsHazard",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / GhsNotClassified
        Added value: +{
        +  "description": "Eine Quelle meldet ausdruecklich \"erfuellt die GHS-Kriterien nicht\".",
        +  "properties": {
        +    "percent": {
        +      "anyOf": [
        +        {
        +          "type": "number"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "title": "Percent"
        +    },
        +    "reports": {
        +      "anyOf": [
        +        {
        +          "type": "integer"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "title": "Reports"
        +    },
        +    "total": {
        +      "anyOf": [
        +        {
        +          "type": "integer"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "title": "Total"
        +    }
        +  },
        +  "title": "GhsNotClassified",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / StereoWarning
        Added value: +{
        +  "description": "Ein Stereoelement, dessen Konfiguration die Eingabe offen lässt.",
        +  "properties": {
        +    "atoms": {
        +      "default": [],
        +      "items": {
        +        "type": "integer"
        +      },
        +      "title": "Atoms",
        +      "type": "array"
        +    },
        +    "kind": {
        +      "title": "Kind",
        +      "type": "string"
        +    },
        +    "label": {
        +      "default": "",
        +      "title": "Label",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "kind"
        +  ],
        +  "title": "StereoWarning",
        +  "type": "object"
        +}
      • addedOutput schema / properties / stereoNote
        Added value: +{
        +  "default": "",
        +  "title": "Stereonote",
        +  "type": "string"
        +}
      • addedOutput schema / properties / stereoWarnings
        Added value: +{
        +  "default": [],
        +  "items": {
        +    "$ref": "#/$defs/StereoWarning"
        +  },
        +  "title": "Stereowarnings",
        +  "type": "array"
        +}
  2. 7 tool updatesv0.1.0
    • First observedbatch_generate
    • First observedcompare_molecules
    • First observedexport_anki_deck
    • First observedgenerate_molecule
    • First observedgenerate_reaction
    • First observedlookup_molecule_data
    • First observedsave_png

TDQS

A4.6/5.0

Scored across 7 tools

Disambiguation5/5

Each tool has a clearly distinct purpose, and the descriptions explicitly cross-reference when to use another tool (single vs. batch, compare vs. draw, reaction vs. molecule, data sheet vs. bare name). The only internal helper, save_png, is explicitly marked as never called directly, so it does not create ambiguity.

Naming Consistency4/5

All names use snake_case and are mostly verb-first (generate_molecule, lookup_molecule_data, generate_reaction, compare_molecules, export_anki_deck, save_png). The only minor deviation is batch_generate, where the verb is not first, but the convention remains readable and predictable overall.

Tool Count5/5

Seven tools is well within the appropriate range and each tool covers a distinct workflow: single drawing, batch drawing, reaction drawing, comparison, data lookup, Anki export, and an internal save helper. The set feels scoped rather than bloated or thin.

Completeness4/5

The surface covers the core chemical drawing lifecycle: single structures, batches, reactions, side-by-side comparison, external data lookup, and flashcard export. Minor gaps exist, such as no dedicated spectrum-generation tool despite spectra being supported in Anki card visuals, and no mechanism/electron-flow tool, though that appears intentionally out of scope.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Enables AI agents and applications to search, retrieve, and analyze chemical compounds, substances, and bioassays from PubChem's vast chemical information database through comprehensive tools for chemical research and discovery.
    10
    1,804 npm
    10
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    ChemMCP is an easy-to-use and extensible chemistry toolkit for LLMs and AI assistants, enabling molecular analysis, property prediction, and reaction synthesis tasks without domain-specific training.
    74
    Apache 2.0
  • A
    license
    C
    quality
    D
    maintenance
    Enables chemical reaction predictions (retrosynthesis, product, reagents), molecule validation, and property calculation through the Model Context Protocol, integrating with AI assistants.
    5
    MIT