Hi Zach and Tom, Glad you're excited! I managed to improve things a lot by adding a new method to my chimerax mcp tool (see below my signature) to leverage the info command when it needs to identify specific chains. Now it doesn't need help to identify the correct chain! But it still gets confused by the show/hide syntax. Of course for now it is completely blind, so it doesn't even notice that it has hidden everything. I think I'd like to try to leverage an MCP server such as this one <https://github.com/kitfactory/PyMCPAutoGUI> to help with this. That way the agent could check what the chimerax window looks like after hiding/showing things. I really like the idea of having the MCP server ship as part of ChimeraX rather than building my own. So today for the first time I am attempting to build ChimeraX from source (I see mcp_server showed up just now when I pulled from your repo). Do questions about ChimeraX development also go to this mailing list, or should I email privately with those? Cheers, Alexis async def get_chimerax_chain_description( session_id: str, model_spec: str = "#1" ) -> Dict[str, Any]: """ Get detailed information about chains in a ChimeraX model This is useful for identifying which chain corresponds to which protein, especially in multi-chain structures. It runs 'info chains' to get chain IDs, then 'info chains attribute description' to get the descriptive text for each chain. According to ChimeraX documentation, the description attribute contains: "descriptive text shown in the status line upon mouseover of the chain" Args: session_id: ID of the session to use model_spec: Model specifier (e.g., "#1", "#2", default: "#1") Returns: Dictionary with chain information including: - chains: List of chain dictionaries with chain_id and description - model_spec: The model that was queried - formatted_output: Human-readable formatted chain information """ if session_id not in _active_sessions: return { 'success': False, 'error': f"Session {session_id} not found", 'available_sessions': list(_active_sessions.keys()) } session = _active_sessions[session_id] # Get chain information using info chains with specific attributes # First get chain IDs command_ids = f"info chains {model_spec}" result_ids = await session.run_command(command_ids) if not result_ids['success']: return result_ids # Parse chain IDs from the output log_messages_ids = result_ids.get('raw_response', {}).get('log messages', {} ) info_messages_ids = log_messages_ids.get('info', []) chain_ids_output = '\n'.join(info_messages_ids) # Extract chain IDs (format is typically "chain_id" per line) chain_ids = [] for line in chain_ids_output.split('\n'): line = line.strip() if line and not line.startswith('#') and len(line) <= 5: # Chain IDs are short chain_ids.append(line) # Now get descriptions for all chains command_desc = f"info chains {model_spec} attribute description" result_desc = await session.run_command(command_desc) if not result_desc['success']: # Fall back to basic chain info return { 'success': True, 'model_spec': model_spec, 'chains': [{'chain_id': cid, 'description': 'N/A'} for cid in chain_ids], 'formatted_output': f"Chain IDs for model {model_spec}:\n" + '\n'.join( chain_ids), 'message': f"Found {len(chain_ids)} chains but could not retrieve descriptions" } # Parse descriptions # ChimeraX returns data in 'note' field of log messages, not 'info'! log_messages_desc = result_desc.get('raw_response', {}).get('log messages', {}) note_messages_desc = log_messages_desc.get('note', []) # The chain info is typically in the second element of the note array descriptions_output = '\n'.join(note_messages_desc) # Parse the output - format is: # chain id /A description "DNA-directed RNA polymerase subunit beta" # chain id /X description NtcA chain_data = [] for line in descriptions_output.split('\n'): line = line.strip() if not line or not line.startswith('chain id'): continue # Parse format: chain id /A description "..." # Remove quotes if present if 'description' in line: parts = line.split('description', 1) if len(parts) == 2: # Extract chain ID from "chain id /A" chain_part = parts[0].strip() if '/' in chain_part: chain_id = chain_part.split('/')[-1].strip() else: chain_id = chain_part.replace('chain id', '').strip() # Extract description, removing quotes description = parts[1].strip().strip('"') chain_data.append({ 'chain_id': chain_id, 'description': description }) # If we didn't get descriptions but have chain IDs, use those if not chain_data and chain_ids: chain_data = [{'chain_id': cid, 'description': 'N/A'} for cid in chain_ids] # Build formatted output formatted_output = f"Chain information for model {model_spec}\n\n" if chain_data: formatted_output += f"Found {len(chain_data)} chain(s):\n\n" for chain in chain_data: formatted_output += f"Chain {chain['chain_id']}: {chain['description']}\n" else: formatted_output += "No chain information available.\n" formatted_output += f"\nRaw output:\n{chain_ids_output}\n{ descriptions_output}" return { 'success': True, 'model_spec': model_spec, 'chains': chain_data if chain_data else None, 'formatted_output': formatted_output, 'raw_chain_ids': chain_ids_output, 'raw_descriptions': descriptions_output, 'message': formatted_output } On Thu, Oct 16, 2025 at 3:55 PM Zach Pearson <z.pearson9@gmail.com> wrote:
I was so excited to see this working that I had to get it up and running locally to play around with it. I hope to have it shipped to users soon. Ideally a bundle would be able to automatically install the node prerequisite @modelcontextprotocol/sdk and then guide users through setting things up with their AI tool of choice.
— Zach
On 16 Oct 2025, at 15:44, Tom Goddard via ChimeraX-users < chimerax-users@cgl.ucsf.edu> wrote:
Hi Alexis,
Thanks for the videos! I am amazed at how well Claude handled ChimeraX and my example queries. A key aspect I didn't understand until you made these videos is that when Claude / MCP sends a command to ChimeraX it gets back the JSON response which includes what was written to the Log. So it sees when the command generated an error, and then it tries to fix it. Wow, and does it ever try! I was dazzled by the number of different approaches it took to my final question about how many hydrogen bonds fentanyl makes with the opioid receptor.
Zach on the UCSF ChimeraX team setup Claude with MCP and we ran the opioid example here to get a better look. I was amazed in your video that Claude figured out which chain was the anti-body by asking ChimeraX for the sequences of the chains and then identifying which sequence looked like an antibody. The PDB data does not say "antibody". Likewise the PDB entry 8ef5 identifies fentanyl as chemical component code :7v7 and iupac name N-phenyl-N-[1-(2-phenylethyl)piperidin-4-yl]propanamide output to the Log that Claude got as json and figured out that was fentanyl. Very nice how Claude heavily uses ChimeraX command output. Claude was often trying the "info" ChimeraX command to get more knowledge about the atomic structures.
Of course, it was also stunning how simple things eluded it that no human would trip over. The "hbond" command reported "0 hydrogen bonds found" and yet Claude tried heroically to count the hydrogen bonds with many commands. And Claude hid the entire opioid structure so nothing was shown and of course was oblivious because it cannot see the image of the graphics is black. Or maybe MCP is able to capture an image of the application.
My impression is that ChimeraX is remarkably well suited for AI agent control since everything can be done by commands, the command documentation is extremely detailed thanks to Elaine in our lab, and ChimeraX gives JSON feedback on the results of every command. One way ChimeraX is not ideal for agents is that Claude often tried old Chimera command syntax and has a hard time distinguishing online information about the two different programs Chimera and ChimeraX. Humans have the same problem.
I agree that if we study some of the failure modes we can probably make Claude / MCP work better with ChimeraX. Claude queried ChimeraX with the info command many times. I think if we exposed more of the PDB human readable text annotations through the info command it would help Claude connect what we request in our typed prompts to the atomic structures.
Tom
On Oct 16, 2025, at 1:09 PM, Alexis Rohou via ChimeraX-users < chimerax-users@cgl.ucsf.edu> wrote:
Hi Tom,
Thanks for suggesting test scenarios. See the video captures below. Basically, it can't quite succeed without some help. The basic thing is that I should probably give it a "recipe" for getting the chain annotations at the command line (what would you suggest?). In the case of the opioid receptor it also confused itself and hid all the chains so I had to tell it about that. This is why I think having visual feedback would be very valuable (also, to click on buttons when setting up ISOLDE, which doesn't have every function available at the command line).
Ntca (no help; it selects the wrong chain) 251016_chimerax_mcp_demo_ntca_tf_only.mov
Ntca (with help - I pointed it to the correct chains, asked it to double-check but I'm not sure it really double-checked or just blindly followed by hint):
251016_chimerax_mcp_demo_ntca_tf_only_with_help.mov
Opioid receptor (it needed my help there because early on it hid all the chains):
251016_chimerax_mcp_demo_fenta_OR_with_help.mov
Note that all I've told the MCP so far is how to start, stop chimerax, check if it's still running, list sessions that are running, and how to submit commands. I have given it no additional context to help it use the commands properly (the obvious thing to do would be to tell it about the "help" and "usage" commands, and to point it to the docs). So any success at all is from the LLM's baked-in training.
I think by studying a few failure modes and giving it tools to help it work things out, it should work pretty well, eventually.
Cheers, Alexis
On Thu, Oct 16, 2025 at 10:16 AM Tom Goddard <goddard@sonic.net> wrote: Hi Alexis,
Beautiful! You and AI are in charge of making our end-of-year ChimeraX holiday card!
I'm impressed Claude got the right ChimeraX commands. A user on the ChimeraX mailing list several days ago asked about how to color a structure red and said he tried many proposals from ChatGPT and none worked. (They were all using old Chimera syntax "color red #1" instead of ChimeraX "color #1 red").
My first thought is when does this fail. What if you try a more realistic use case? For example,
Show me trascription factor Ntca in pdb 8h40 I'd like to see just the trascription factor bound to the DNA without the polymerase Could you show those in ribbon style without atoms
Or how about
I'd like to look at how fentanyl interacts with the opioid receptor, PDB 8ef5 Could you hide the G proteins? Also hide the antibody. Show the receptor as ribbon Show just one copy of the receptor Can you show the protein residues near fentanyl in stick style Can you show hydrogen bonds between fentanyl and the protein? How many are there?
If the Claude MCP agent could do this I would be blown away.
Regarding having the agent control the ChimeraX GUI (push buttons, use menus) when there are no equivalent commands, I think that is not too necessary with ChimeraX because almost every GUI actions has an equivalent command and those commands are echoed to the ChimeraX Log panel, so it is even pretty easy to learn the equivalent commands.
Tom
On Oct 15, 2025, at 10:25 PM, Alexis Rohou via ChimeraX-users < chimerax-users@cgl.ucsf.edu> wrote:
Hi Tom,
I mocked something up quickly. See demos below, where I'm using Cursor as the MCP client and agent with Claude 4.5 Sonnet as the LLM:
Demo 0 (start ChimeraX, open a pdb, color it) Demo 1 (change colors) Demo 2 (change colors again, the JA version)
Curious to hear if anyone else is working on something similar. I think getting commands to work nicely should be easy (famous last words?). Next level will be to have the agent interact directly with the GUI, check what is being displayed, and possibly click on buttons when there are no commands to perform specific tasks. There are existing MCPs that I hope will make this feasible.
Cheers, Alexis
On Wed, Oct 15, 2025 at 7:12 PM Tom Goddard <goddard@sonic.net> wrote: Hi Alexis,
The UCSF ChimeraX team has not looked at using ChimeraX as an AI agent or at Model Context Protocol (MCP). Your links to github repositories that have tried to hook up AI agents to ChimeraX with MCP were a surprise to me. It would be cool to see a video using an AI agent with ChimeraX.
Tom
On Oct 15, 2025, at 6:29 PM, Alexis Rohou via ChimeraX-users < chimerax-users@cgl.ucsf.edu> wrote:
Hi all,
I would like to use ChimeraX via an agent. Quick googling suggests I'm not the first person to think of this (here, here), but before I dive in I thought I'd check - anyone else actively working on this? Or maybe you have worked on it and hit a roadblock?
Cheers, Alexis _______________________________________________ ChimeraX-users mailing list -- chimerax-users@cgl.ucsf.edu To unsubscribe send an email to chimerax-users-leave@cgl.ucsf.edu Archives: https://mail.cgl.ucsf.edu/mailman/archives/list/chimerax-users@cgl.ucsf.edu/
_______________________________________________ ChimeraX-users mailing list -- chimerax-users@cgl.ucsf.edu To unsubscribe send an email to chimerax-users-leave@cgl.ucsf.edu Archives: https://mail.cgl.ucsf.edu/mailman/archives/list/chimerax-users@cgl.ucsf.edu/
_______________________________________________ ChimeraX-users mailing list -- chimerax-users@cgl.ucsf.edu To unsubscribe send an email to chimerax-users-leave@cgl.ucsf.edu Archives: https://mail.cgl.ucsf.edu/mailman/archives/list/chimerax-users@cgl.ucsf.edu/
_______________________________________________ ChimeraX-users mailing list -- chimerax-users@cgl.ucsf.edu To unsubscribe send an email to chimerax-users-leave@cgl.ucsf.edu Archives: https://mail.cgl.ucsf.edu/mailman/archives/list/chimerax-users@cgl.ucsf.edu/