### Setup and Install ChemMCP (uv) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/get-started.md Navigates into the ChemMCP directory, synchronizes packages using uv, and installs ChemMCP with no build isolation. ```bash cd ChemMCP uv sync uv pip install -e . --no-build-isolation ``` -------------------------------- ### Install ChemMCP Dependencies (Optional) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/get-started.md Installs project dependencies from a requirements file and installs ChemMCP in an existing environment. ```bash # Install dependencies pip install -r requirements # Install ChemMCP pip install -e . --no-build-isolation ``` -------------------------------- ### Install uv (Windows) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/get-started.md Installs the uv package and project manager on Windows systems using Powershell. ```powershell # On Windows, use Powershell powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" ``` -------------------------------- ### Install uv (macOS/Linux) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/get-started.md Installs the uv package and project manager on macOS and Linux systems using a curl command. ```bash # On macOS and Linux curl -LsSf https://astral.sh/uv/install.sh | sh ``` -------------------------------- ### Clone ChemMCP Repository Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/get-started.md Clones the ChemMCP project repository from GitHub using Git. ```bash git clone https://github.com/OSU-NLP-Group/ChemMCP.git ``` -------------------------------- ### Claude Desktop Integration Configuration Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/get-started.md JSON configuration for integrating ChemMCP with Claude Desktop as an MCP server, specifying command, arguments, timeouts, and environment variables. ```json { "mcpServers": { "ChemMCP": { "command": "/ABSTRACT/PATH/TO/uv", // Use `which uv` to get its path "args": ["run", "-m", "chemmcp"], "toolCallTimeoutMillis": 300000, // Set this value because some tools may be slow in response of requests "env": { "CHEMSPACE_API_KEY": "API_KEY", "RXN4CHEM_API_KEY": "API_KEY", "TAVILY_API_KEY": "API_KEY", "LLM_MODEL_NAME": "openai/gpt-4o", // Or any other LLM names supported by LiteLLM // Add required LLM credentials // ... } } } } ``` -------------------------------- ### Activate Virtual Environment (macOS/Linux) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/get-started.md Activates the Python virtual environment created by uv on macOS and Linux systems. ```bash # On macOS and Linux source .venv/bin/activate ``` -------------------------------- ### Activate Virtual Environment (Windows CMD) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/get-started.md Activates the Python virtual environment created by uv on Windows Command Prompt. ```cmd # On Windows (CMD) .venv\Scripts\activate.bat ``` -------------------------------- ### Connect ChemMCP with OpenAI Agents SDK Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/get-started.md Demonstrates how to establish a connection to a ChemMCP server using the OpenAI Agents SDK. It configures essential parameters such as the command path, arguments, tool call timeout, and environment variables including API keys for various services and the LLM model name. ```python async with MCPServerStdio( params={ "command": "/ABSTRACT/PATH/TO/uv", # Use `which uv` to get its path "args": ["--directory", "/ABSTRACT/PATH/TO/ChemMCP", "run", "-m", "chemmcp"], "toolCallTimeoutMillis": 300000, # Set this value because some tools may be slow in response of requests "env": { "CHEMSPACE_API_KEY": "API_KEY", "RXN4CHEM_API_KEY": "API_KEY", "TAVILY_API_KEY": "API_KEY", "LLM_MODEL_NAME": "openai/gpt-4o-2024-08-06", # Or any other LLM names supported by LiteLLM # Aad required LLM credentials # ... } } ) as server: tools = await server.list_tools() ``` -------------------------------- ### Call ChemMCP Tools Directly in Python Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/get-started.md Shows how to use ChemMCP tools programmatically within a Python script. This involves importing specific tools, setting required environment variables for API keys and LLM configurations, and then executing a tool's functionality, such as performing a web search. ```python import os from chemmcp.tools import WebSearch # or any of the tool names # Of course, you can set only those variables required by the tools to use envs = { "CHEMSPACE_API_KEY": "API_KEY", "RXN4CHEM_API_KEY": "API_KEY", "TAVILY_API_KEY": "API_KEY", "LLM_MODEL_NAME": "openai/gpt-4o-2024-08-06", # Or any other LLM names supported by LiteLLM # Aad required LLM credentials # ... } for key, value in envs: os.environ[key] = value web_search = WebSearch() result = web_search.run_code('What is the boiling point of water?') ``` -------------------------------- ### Define a New ChemMCP Tool Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/dev-guide.md This snippet demonstrates the basic structure for defining a new tool in ChemMCP. It includes the necessary decorator, class inheritance, and essential metadata fields such as name, version, description, dependencies, categories, and tags. It also shows how to define input and output signatures and provide examples. ```Python import logging import os from typing import Optional from src.chemmcp.base import BaseTool from src.chemmcp.utils.errors import ChemMCPToolError from src.chemmcp.manager import ChemMCPManager from openai import OpenAI logger = logging.getLogger(__name__) @ChemMCPManager.register_tool class MyNewTool(BaseTool): __version__ = "0.1.0" name = "MyNewTool" func_name = "do_something" description = "Brief description of what MyNewTool does." implementation_description = "Brief description of how the tool works, e.g., with what models/packages." oss_dependencies = [ ("Dependency name", "Depenendency URL", "Dependency license (None if not found)") ] services_and_software = [ ("Service or software name", "URL (None if no specific URL)") ] categories = ["General"] tags = ["API", "Neural Networks", "Molecular Properties", "LLMs"] required_envs = [ ("OPENAI_API_KEY", "API key for OpenAI") ] code_input_sig = [ ("smiles", "str", "N/A", "SMILES string of the molecule."), ("threshold", "float", "0.5", "Cutoff threshold.") ] text_input_sig = [ ("smiles_and_threshold", "str", "N/A", "The SMILES string of the moledule and the cutoff threshold, separated by a space.") ] output_sig = [ ("result", "float", "The score of the input molecule.") ] examples = [ { "code_input": { "molecule_smiles": "CCO", "threshold": 0.7 }, "text_input": { "smiles_and_threshold": "CCO 0.7" }, "output": { "result": 0.13 } } ] def __init__( self, openai_api_key: Optional[str] = None, init: bool = True, interface: str = "code" ): if openai_api_key is None: openai_api_key = os.getenv("MY_TOOL_API_KEY") if openai_api_key is None: raise ChemMCPToolError("Please set `MY_TOOL_API_KEY`.") self.openai_api_key = openai_api_key super().__init__(init=init, interface=interface) def _init_modules(self): """ Load some checkpoints or initialize some external clients. """ self.openai_client = OpenAI(self.openai_api_key) def _run_base(self, smiles: str, threshold: float = 0.5) -> float: """ Core logic of your tool. """ # … your implementation of the tool function … pass ``` -------------------------------- ### Tool Implementation Template Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/dev-guide.md This is a template for implementing a new ChemMCP tool. It includes necessary imports from the ChemMCP library and placeholders for custom errors and core functionalities. ```Python import os import logging from typing import Optional from openai import OpenAI from ..utils.base_tool import BaseTool from ..utils.errors import ChemMCPToolError # your custom errors from ..utils.mcp_app import ChemMCPManager, run_mcp_server ``` -------------------------------- ### Tool Testing with Code and Text Inputs Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/dev-guide.md This Python snippet demonstrates how to test a custom tool (`MyNewTool`) by initializing it and calling its `run_code` and `run_text` methods with sample inputs. It also shows setting an environment variable for API keys. ```Python import os from chemmcp.tools import MyNewTool os.environ['OPENAI_API_KEY'] = "YOUR_API_KEY" my_new_tool = MyNewTool() # it calls your _run_base function result = my_new_tool.run_code(smiles="CCO", threshold=0.5) # it calls your _run_text function result = my_new_tool.run_text(smiles_and_threshold="CCO 0.5") ``` -------------------------------- ### Hugo Template for Background Images (Go Template) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/layouts/partials/home/custom.html This snippet uses Hugo's template language to get and display background images. It retrieves 'bubble_background.svg' and 'background.svg' using resources.Get and then uses RelPermalink to get their relative URLs for display. ```Go Template {{ $bubbleBg := resources.Get "img/bubble_background.svg" }} {{ $staticBg := resources.Get "img/background.svg" }} ![]({{ $bubbleBg.RelPermalink }}) ![]({{ $staticBg.RelPermalink }}) ``` -------------------------------- ### Register Tool in __init__.py Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/dev-guide.md This snippet shows how to register a new tool by adding an entry to the _tool_module_map in the __init__.py file. The key is the Tool Name, and the value is the corresponding File Name (module name). ```Python _tool_module_map = { # … existing entries … "MyNewTool": "my_new_tool", # Tool Name: File Name. } ``` -------------------------------- ### Run Base Function Example Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/dev-guide.md This Python snippet demonstrates a simplified example of calling an OpenAI client's predict method within a tool's base run function. It takes SMILES as input and returns a score. ```Python score: float = self.openai_client.predict(smiles) # this is just a simplified example return score ``` -------------------------------- ### Testing Tool with MCP Inspector Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/dev-guide.md This Bash command demonstrates how to use the MCP Inspector tool to test a ChemMCP tool. It assumes the tool is saved in `src.chemmcp.tools.my_new_tool` and uses `uv run` to execute it. ```Bash # Assume your file name is `my_new_tool.py` npx @modelcontextprotocol/inspector uv run -m src.chemmcp.tools.my_new_tool ``` -------------------------------- ### Add New Tool Development Guide (Python) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/layouts/partials/home/custom.html This refers to a development guide for adding new tools to ChemMCP. It indicates that new tools are added by writing a Python file and that all tools follow a consistent schema for clear interfaces and maintenance. ```Python # See here for adding a new tool: https://osu-nlp-group.github.io/ChemMCP/dev-guide/ ``` -------------------------------- ### CSS for Code Highlighting and Styling Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/layouts/partials/home/custom.html This CSS code provides styling for code highlighting and blocks, matching the QuickConfig page's appearance. It includes styles for wrappers, highlights, preformatted text blocks, and specific overrides for BibTeX language highlighting to ensure a clean presentation. ```css /* Code highlighting styles to match QuickConfig page */ .highlight-wrapper { @apply block; } .highlight { @apply relative z-0; } /* Code block styling */ pre.chroma { margin: 0 !important; } /* Override Prism.js styles */ pre.language-bibtex { text-shadow: none !important; background: none !important; } ``` -------------------------------- ### Go Template for Homepage Image Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/layouts/partials/quick-config/custom.html This Go template code snippet handles the display of a homepage background image. It checks for a remote URL or a local resource and sets the image accordingly. If an image is found, it's displayed using Markdown syntax. ```Go Template {{ $homepageImage := "" }} {{ with .Site.Params.defaultBackgroundImage }} {{ if or (strings.HasPrefix . "http:") (strings.HasPrefix . "https:") }} {{ $homepageImage = resources.GetRemote . }} {{ else }} {{ $homepageImage = resources.Get . }} {{ end }} {{ end }} {{ with .Site.Params.homepage.homepageImage }} {{ if or (strings.HasPrefix . "http:") (strings.HasPrefix . "https:") }} {{ $homepageImage = resources.GetRemote . }} {{ else }} {{ $homepageImage = resources.Get . }} {{ end }} {{ end }} {{ if $homepageImage }} ![]({{ $homepageImage.RelPermalink }}) {{ end }} ``` -------------------------------- ### Logging in ChemMCP Tools Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/dev-guide.md This snippet shows how to use the `logger.info()` or `logger.debug()` methods for printing messages within a ChemMCP tool, as recommended instead of using the standard `print()` function. ```Python import logging logger = logging.getLogger(__name__) # Example usage within a tool: # logger.info("Processing molecule...") # logger.debug("Threshold value is: %f", threshold) ``` -------------------------------- ### Demonstrate Background Layout Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/_index.md This snippet demonstrates a 'background' layout within a UI component. It includes a warning message and a button to switch the layout. The code highlights the use of HTML, CSS classes for styling, and a button element for user interaction. ```html
{{< icon "triangle-exclamation" >}} This is a demo of the background layout.
``` -------------------------------- ### Load and Display Tools with JavaScript Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/layouts/partials/quick-config/custom.html This snippet fetches tool environment data from a JSON file, sorts the tools alphabetically, and dynamically creates checkboxes for each tool. It includes functionality to categorize tools if enabled and adds event listeners for tool selection to update the configuration display. ```JavaScript document.addEventListener('DOMContentLoaded', async function() { // Load tools data const dataUrl = '{{ "data/tool_envs/all_tool_envs.json" | absURL }}'; const response = await fetch(dataUrl); const toolsEnvsDict = await response.json(); const allTools = Object.keys(toolsEnvsDict).sort(); // Sort tools alphabetically const toolCheckboxesContainer = document.getElementById('tool-checkboxes'); const configDisplay = document.getElementById('config-display'); const selectAllBtn = document.getElementById('select-all'); const selectNoneBtn = document.getElementById('select-none'); // Helper function to create tool category header function createCategoryHeader(title) { const header = document.createElement('div'); header.className = 'col-span-2 sm:col-span-3 md:col-span-4 mt-3 mb-2 pb-1 border-b border-neutral-200 dark:border-neutral-700'; const headerText = document.createElement('h3'); headerText.className = 'text-sm font-bold text-primary-600 dark:text-primary-400'; headerText.textContent = title; header.appendChild(headerText); return header; } // Optional: Categorize tools (modify this to match your categorization) const toolCategories = { "General Tools": ["WebSearch", "PubchemSearch", "PubchemSearchQA"], "Molecule Tools": ["MoleculeCaptioner", "MoleculeGenerator", "MoleculeSimilarity", "MoleculeWeight", "FunctionalGroups", "SmilesCanonicalization", "MoleculeAtomCount", "MoleculePrice", "PatentCheck", "SolubilityPredictor", "LogDPredictor", "BbbpPredictor", "ToxicityPredictor", "HivInhibitorPredictor", "SideEffectPredictor", "Iupac2Smiles", "Smiles2Iupac", "Smiles2Formula", "Name2Smiles", "Selfies2Smiles", "Smiles2Selfies"], "Reaction Tools": ["ForwardSynthesis", "Retrosynthesis"] }; const useCategorization = false; // Check if we want to categorize tools if (useCategorization) { // Process tools by category Object.entries(toolCategories).forEach(([category, categoryTools]) => { // Add category header toolCheckboxesContainer.appendChild(createCategoryHeader(category)); // Add tools in this category categoryTools.forEach(toolName => { if (allTools.includes(toolName)) { addToolCheckbox(toolName); } }); }); // Add any uncategorized tools const categorizedTools = Object.values(toolCategories).flat(); const uncategorizedTools = allTools.filter(tool => !categorizedTools.includes(tool)); if (uncategorizedTools.length > 0) { toolCheckboxesContainer.appendChild(createCategoryHeader("Other Tools")); uncategorizedTools.forEach(toolName => { addToolCheckbox(toolName); }); } } else { // Add all tools without categorization allTools.forEach(toolName => { addToolCheckbox(toolName); }); } // Function to create a tool checkbox function addToolCheckbox(toolName) { // Create a container element const checkboxDiv = document.createElement('div'); checkboxDiv.className = 'flex items-center px-3 py-2 rounded-md tool-item'; // Create the checkbox element const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.id = `tool-${toolName}`; checkbox.name = 'tools'; checkbox.value = toolName; checkbox.checked = true; // Default: all tools are selected checkbox.className = 'h-5 w-5 rounded border-gray-300 text-primary-600 focus:ring-primary-600 cursor-pointer tool-checkbox'; checkbox.addEventListener('change', updateConfig); // Create the label that wraps everything - this ensures clicking anywhere toggles the checkbox const label = document.createElement('label'); label.htmlFor = `tool-${toolName}`; label.className = 'flex items-center w-full cursor-pointer'; // Add checkbox to label label.appendChild(checkbox); // Add a small spacer const spacer = document.createElement('span'); spacer.className = 'ml-3'; // Add text node const textSpan = document.createElement('span'); textSpan.textContent = toolName; textSpan.className = 'text-sm font-medium text-neutral-800 dark:text-neutral-200'; // Put it all together label.appendChild(spacer); label.appendChild(textSpan); checkboxDiv.appendChild(label); toolCheckboxesContainer.appendChild(checkboxDiv); } // Select All button selectAllBtn.addEventListener('click', () => { document.querySelectorAll('.tool-checkbox').forEach(checkbox => { checkbox.checked = true; }); updateConfig(); }); // Select None button selectNoneBtn.addEventListener('click', () => { document.querySelectorAll('.tool-checkbox').forEach(checkbox => { checkbox.checked = false; }); updateConfig(); }); // Initial configuration update updateConfig(); }); function updateConfig() { const selectedTools = Array.from(document.querySelectorAll('.tool-checkbox:checked')).map(checkbox => checkbox.value); const configDisplay = document.getElementById('config-display'); const noToolSelectedMessage = document.getElementById('no-tool-selected-message'); if (selectedTools.length === 0) { configDisplay.innerHTML = ''; if (noToolSelectedMessage) { noToolSelectedMessage.classList.remove('hidden'); } } else { if (noToolSelectedMessage) { noToolSelectedMessage.classList.add('hidden'); } // In a real application, you would generate the config here based on selectedTools // For this example, we'll just display the selected tools configDisplay.innerHTML = `
Configuration for: ${selectedTools.join(', ')}
`; } } ``` -------------------------------- ### MolT5 Dependent Tools Source: https://github.com/osu-nlp-group/chemmcp/blob/main/README.md MoleculeCaptioner and MoleculeGenerator utilize MolT5, which is distributed under the BSD 3-Clause license. ```Python MoleculeCaptioner: [MolT5](https://github.com/blender-nlp/MolT5) (BSD 3-Clause) Hosted Service / Software: - ``` ```Python MoleculeGenerator: [MolT5](https://github.com/blender-nlp/MolT5) (BSD 3-Clause) Hosted Service / Software: - ``` -------------------------------- ### MCP Server Execution Block Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/dev-guide.md This Python code block is intended to be placed at the end of a tool file. It ensures that the `run_mcp_server` function is called only when the script is executed directly, typically for running the tool within the MCP server environment. ```Python if __name__ == "__main__": run_mcp_server() ``` -------------------------------- ### Run Text Function Implementation Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/content/dev-guide.md This Python function, `_run_text`, is designed to handle string inputs for tools that only support a single string argument. It parses the input string to extract SMILES and a threshold, then calls the `_run_base` function with these parsed arguments. ```Python def _run_text(self, smiles_and_threshold: str) -> str: """ Parse the only text str input, and then call _run_base. Return the result of _run_base. """ # parse the text query into _run_base's input arguments smiles, threshold = smiles_and_threshold.strip().split() smiles = str(smiles) threshold = float(threshold) # call _run_base result = self._run_base(smiles, threshold) return result ``` -------------------------------- ### PythonExecutor Tool Source: https://github.com/osu-nlp-group/chemmcp/blob/main/README.md The PythonExecutor tool depends on Jupyter Notebook and Docker for execution, utilizing its BSD 3-Clause license. ```Python PythonExecutor: [Jupyter Notebook](https://github.com/jupyter/notebook) (BSD 3-Clause) Hosted Service / Software: [docker](https://www.docker.com/) ``` -------------------------------- ### List and Filter NLP Tools (Go) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/layouts/shortcodes/tools-directory.html This Go code snippet demonstrates how to iterate through site pages categorized as 'tools', extract their titles, descriptions, categories, languages, and tags, and then sort and display them. It also includes logic for filtering and displaying categories and tags separately. ```Go Project: /osu-nlp-group/chemmcp Content: Categories {{ $categories := slice }} {{ $tools := where site.RegularPages "Section" "tools" }} {{ range $tools }} {{ with .Params.categories }} {{ range . }} {{ $categories = $categories | append . }} {{ end }} {{ end }} {{ end }} {{ range (sort (uniq $categories)) }}* {{ . }} {{ end }} Tags {{ $tags := slice }} {{ $tools := where site.RegularPages "Section" "tools" }} {{ range $tools }} {{ with .Params.tags }} {{ range . }} {{ $tags = $tags | append . }} {{ end }} {{ end }} {{ end }} {{ range (sort (uniq $tags)) }}* {{ . }} {{ end }} Filters Filters × Categories {{ $categories := slice }} {{ $tools := where site.RegularPages "Section" "tools" }} {{ range $tools }} {{ with .Params.categories }} {{ range . }} {{ $categories = $categories | append . }} {{ end }} {{ end }} {{ end }} {{ range (sort (uniq $categories)) }}* {{ . }} {{ end }} Tags {{ $tags := slice }} {{ $tools := where site.RegularPages "Section" "tools" }} {{ range $tools }} {{ with .Params.tags }} {{ range . }} {{ $tags = $tags | append . }} {{ end }} {{ end }} {{ end }} {{ range (sort (uniq $tags)) }}* {{ . }} {{ end }} {{ $tools := where site.RegularPages "Section" "tools" }} {{ range sort $tools "Params.weight" }} [{{ .Title }}]({{ .RelPermalink }}) {{ if gt (len .Params.description) 180 }} {{ slicestr .Params.description 0 180 }}... {{ else }} {{ .Params.description }} {{ end }} {{ range .Params.categories }} {{ . }} {{ end }} {{ range .Params.languages }} {{ . }} {{ end }} {{ range .Params.tags }} {{ . }} {{ end }} {{ end }} .tools-directory { display: flex; gap: 2rem; flex-direction: row; } .tools-sidebar { min-width: 220px; max-width: 260px; } .tools-search-input { width: 100%; padding: 0.5em; margin-bottom: 1em; border-radius: 6px; border: 1px solid #ccc !important; color: #0f172a !important; background: #fff !important; color-scheme: light dark; } .dark .tools-search-input { color: #e5e7eb !important; background: #0f172a !important; border-color: #334155 !important; } .tools-filters { width: 100%; } .filters-chip { display: inline-flex; align-items: center; background: #f1f5f9; color: #334155; border: 1px solid #e2e8f0; border-radius: 999px; font-size: 1em; font-weight: 500; padding: 0.35em 1em 0.35em 0.7em; box-shadow: none; cursor: pointer; transition: background 0.15s, border 0.15s; margin-bottom: 0.5em; } .filters-chip:hover, .filters-chip:focus { background: #e0f2fe; border-color: #38bdf8; } .dark .filters-chip { background: #1e293b; color: #e5e7eb; border-color: #334155; } .filters-chip.active { background: #bae6fd; color: #0369a1; border-color: #38bdf8; } .filters-modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; } .filters-modal-backdrop { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(30,41,59,0.35); z-index: 1; } .filters-modal-content { display: flex; flex-direction: column; height: 100%; max-height: 90vh; position: relative; z-index: 2; background: linear-gradient(135deg, #f8fafc 0%, #e0e7ef 100%); border-radius: 22px; box-shadow: 0 8px 40px rgba(30,41,59,0.18), 0 1.5px 8px rgba(30,41,59,0.10); border: 1.5px solid #e2e8f0; padding: 2.7em 2.5em 2.5em 2.5em; width: 90%; margin: 2.5vh auto; } .dark .filters-modal-content { background: linear-gradient(135deg, #1e293b 0%, #334155 100%); border-color: #334155; } .filters-modal-header { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.5em; padding-bottom: 0.2em; border-bottom: 1.5px solid #e2e8f0; } .dark .filters-modal-header { border-bottom: 1.5px solid #334155; } .filters-modal-title { font-size: 1.45em; font-weight: 800; letter-spacing: 0.01em; color: #0f172a; } .dark .filters-modal-title { color: #e5e7eb; } .filters-modal-close { background: none; border: none; font-size: 2.1em; color: #64748b; cursor: pointer; padding: 0 0.3em; line-height: 1; border-radius: 6px; margin-left: 1em; margin-right: -0.3em; transition: background 0.15s; } .filters-modal-close:hover, .filters-modal-close:focus { background: #e0f2fe; } .dark .filters-modal-close { color: #e5e7eb; } .filters-modal-scroll { flex: 1 1 0%; overflow-y: auto; min-height: 0; margin-top: 0.5em; } .filters-modal-section { margin-bottom: 1.7em; } .filters-group-title { font-size: 1.15em; font-weight: 700; margin-bottom: 0.7em; margin-top: 0.2em; color: #0f172a; letter-spacing: 0.01em; } .dark .filters-group-title { color: #e5e7eb; } .filters-divider { border-top: 1.5px solid #e2e8f0; margin: 0.7em 0 1.3em 0; } .dark .filters-divider { border-top: 1.5px solid #334155; } .filters-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.7em; } .filters-checkbox-label { display: flex; align-items: center; font-size: 1.08em; font-weight: 500; color: #334155; padding: 0.2em 0.1em; border-radius: 6px; transition: background 0.15s; } .filters-checkbox-label:hover { background: #f1f5f9; } .dark .filters-c ``` -------------------------------- ### PubChemSearch and Related Tools Source: https://github.com/osu-nlp-group/chemmcp/blob/main/README.md PubchemSearch, PubchemSearchQA, Smiles2Formula, and Smiles2Iupac interact with the PubChem service. PubchemSearchQA also uses Custom LLMs, while Smiles2Formula has no listed OSS dependencies. ```Python PubchemSearch: - Hosted Service / Software: [PubChem](https://pubchem.ncbi.nlm.nih.gov/) ``` ```Python PubchemSearchQA: - Hosted Service / Software: [PubChem](https://pubchem.ncbi.nlm.nih.gov/), Custom LLMs ``` ```Python Smiles2Formula: - Hosted Service / Software: [PubChem](https://pubchem.ncbi.nlm.nih.gov/) ``` ```Python Smiles2Iupac: [PubChemPy](https://github.com/mcs07/PubChemPy) (MIT) Hosted Service / Software: [PubChem](https://pubchem.ncbi.nlm.nih.gov/) ``` -------------------------------- ### Configure Recent Articles Display (Go/HTML) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/layouts/partials/recent-articles-demo.html This snippet demonstrates how to configure the display of recent articles using Go templating within an HTML context. It allows setting the number of recent articles to display and conditionally showing a 'show more' link. ```Go {{ $recentArticles := 5 }} {{ $showMoreLinkDest := "/posts/" }} {{ if index .Site.Params.homepage "showRecentItems" }} {{ $recentArticles = .Site.Params.homepage.showRecentItems }} {{ end }} {{ i18n "shortcode.recent_articles" | emojify }} ------------------------------------------------- This is a demo of theme's list configurations: `card view` Switch config ↻ {{ partial "recent-articles/cardview.html" . }} {{ partial "recent-articles/cardview-fullwidth.html" . }} {{ partial "recent-articles/list.html" . }} {{ if .Site.Params.homepage.showMoreLink | default false }} {{ if index .Site.Params.homepage "showRecentItems" }} {{ $showMoreLinkDest = .Site.Params.homepage.showMoreLinkDest }} {{ end }} [{{ i18n "recent.show_more" | markdownify }}]({{ $showMoreLinkDest }}) {{ end }} ``` -------------------------------- ### MCP-enabled LLM Clients Integration (Python) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/layouts/partials/home/custom.html This highlights the ease of integrating ChemMCP tools into MCP-enabled LLM clients. It suggests that integration can be done in minutes without additional training, leveraging the Model Context Protocol. ```Python # Integrate into any MCP-enabled LLM clients: https://github.com/punkpeye/awesome-mcp-clients ``` -------------------------------- ### Copy Configuration to Clipboard Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/layouts/partials/quick-config/custom.html This snippet provides functionality to copy the generated JSON configuration to the clipboard. It includes event listeners for a copy button and handles the clipboard interaction, including fallback mechanisms. ```javascript // Add copy button functionality to match Blowfish theme behavior function createCopyButton(highlightDiv) { const button = document.createElement("button"); button.className = "copy-button"; button.type = "button"; button.ariaLabel = "Copy"; button.innerText = "Copy"; button.addEventListener("click", () => copyCodeToClipboard(button, highlightDiv)); addCopyButtonToDom(button, highlightDiv); } async function copyCodeToClipboard(button, highlightDiv) { const codeToCopy = highlightDiv.querySelector(":last-child").innerText; try { result = await navigator.permissions.query({ name: "clipboard-write" }); if (result.state == "granted" || result.state == "prompt") { await navigator.clipboard.writeText(codeToCopy); } else { copyCodeBlockExecCommand(codeToCopy, highlightDiv); } } catch (_) { copyCodeBlockExecCommand(codeToCopy, highlightDiv); } finally { codeWasCopied(button); } } function copyCodeBlockExecCommand(codeToCopy, highlightDiv) { const textArea = document.createElement("textArea"); textArea.contentEditable = "true"; textArea.readOnly = "false"; textArea.className = "copy-textarea"; textArea.value = codeToCopy; highlightDiv.insertBefore(textArea, highlightDiv.firstChild); const range = document.createRange(); range.selectNodeContents(textArea); const sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); textArea.setSelectionRange(0, 999999); document.execCommand("copy"); highlightDiv.removeChild(textArea); } functi ``` -------------------------------- ### Header Rendering Logic (Go) Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/layouts/partials/header/basic.html This Go template code handles the rendering of website headers, including logos, titles, navigation menus, search icons, and appearance switchers. It uses Hugo's resource functions and partials for modularity. ```Go {{ if .Site.Params.Logo }} {{ $logo := resources.Get .Site.Params.Logo }} {{ if $logo }} [{{ .Site.Title | markdownify }} {{ if eq $logo.MediaType.SubType "svg" }} {{ $logo.Content | safeHTML }} {{ else }} ![{{ .Site.Title }}]({{ $logo.RelPermalink }}) {{ end }}]({{ ) {{ end }} {{- end }} {{ if not .Site.Params.disableTextInHeader | default true }} [{{ .Site.Title | markdownify }}]({{ ) {{ end }} {{ if .Site.Menus.main }} {{ range .Site.Menus.main }} {{ partial "header/header-option.html" . }} {{ end }} {{ end }} {{ partial "translations.html" . }} {{ if .Site.Params.enableSearch | default false }} {{ partial "icon.html" "search" }} {{ end }} {{/\* Appearance switch \*/}} {{ if .Site.Params.footer.showAppearanceSwitcher | default false }} {{ partial "icon.html" "sun" }} {{ partial "icon.html" "moon" }} {{ end }} {{ partial "translations.html" . }} {{ if .Site.Params.enableSearch | default false }} {{ partial "icon.html" "search" }} {{ end }} {{/\* Appearance switch \*/}} {{ if .Site.Params.footer.showAppearanceSwitcher | default false }} {{ partial "icon.html" "sun" }} {{ partial "icon.html" "moon" }} {{ end }} {{ if .Site.Menus.main }} {{ partial "icon.html" "bars" }} * {{ partial "icon.html" "xmark" }} {{ range .Site.Menus.main }} {{ partial "header/header-mobile-option.html" . }} {{ end }} {{ if .Site.Menus.subnavigation }} * * * {{ range .Site.Menus.subnavigation }}* [{{ if .Pre }} {{ partial "icon.html" .Pre }} {{ end }} {{ .Name | markdownify }} ]({{ .URL }}) {{ end }} {{ end }} {{ end }} {{ if .Site.Menus.subnavigation }} {{ range .Site.Menus.subnavigation }} [{{ if .Pre }} {{ partial "icon.html" .Pre }} {{ end }} {{ .Name | markdownify }} ]({{ .URL }}){{ end }} {{ end }} ``` -------------------------------- ### ForwardSynthesis and Retrosynthesis Tools Source: https://github.com/osu-nlp-group/chemmcp/blob/main/README.md These tools leverage ChemCrow and rxn4chemistry for their functionality, integrating with IBM RXN for Chemistry. They are designed for chemical synthesis planning and retrosynthesis. ```Python ForwardSynthesis: [ChemCrow](https://github.com/ur-whitelab/chemcrow-public) (MIT), [rxn4chemistry](https://github.com/rxn4chemistry/rxn4chemistry) (MIT) Hosted Service / Software: [IBM RXN for Chemistry](https://rxn.app.accelerate.science/) ``` ```Python Retrosynthesis: [ChemCrow](https://github.com/ur-whitelab/chemcrow-public) (MIT), [rxn4chemistry](https://github.com/rxn4chemistry/rxn4chemistry) (MIT) Hosted Service / Software: [IBM RXN for Chemistry](https://rxn.app.accelerate.science/) ``` -------------------------------- ### CSS: Code Highlighting and Styling Source: https://github.com/osu-nlp-group/chemmcp/blob/main/site/layouts/partials/quick-config/custom.html This CSS code defines styles for code highlighting, including wrapper, highlight, and copy button elements. It also includes styles for text areas, Chroma highlighting, preformatted text, tool items, and custom checkboxes. ```css /* Code highlighting styles from Blowfish theme */ .highlight-wrapper { @apply block; } .highlight { @apply relative z-0 shadow-sm; } .highlight:hover>.copy-button { @apply visible; } .copy-button { @apply absolute top-0 right-0 z-10 invisible w-20 py-1 font-mono text-sm cursor-pointer opacity-90 bg-neutral-200 whitespace-nowrap rounded-bl-md rounded-tr-md text-neutral-700 dark:bg-neutral-600 dark:text-neutral-200; } .copy-button:hover, .copy-button:focus, .copy-button:active, .copy-button:active:hover { @apply bg-primary-100 dark:bg-primary-600; } .copy-textarea { @apply absolute opacity-5 -z-10; } /* Chroma Highlight */ .chroma { @apply static rounded-md text-neutral-700 bg-neutral-50 dark:bg-neutral-700 dark:text-neutral-200; } pre { @apply block w-auto px-6 py-4 overflow-auto text-base; } /* Clean tool item styles without hover effects */ .tool-item { @apply border-b border-neutral-200 dark:border-neutral-700; margin-bottom: -1px; } /* Last rows shouldn't have bottom borders */ @media (min-width: 640px) { .tool-item:nth-last-child(-n+2) { border-bottom: none; } } @media (min-width: 768px) { .tool-item:nth-last-child(-n+3) { border-bottom: none; } } /* Equal column heights */ #tool-checkboxes { grid-auto-rows: minmax(45px, auto); } /* Custom checkbox styling */ .tool-checkbox { @apply rounded !important; } ```