Conversation
| - **Build package**: `uv run python -m build .` | ||
|
|
||
| ### Development Setup | ||
| - **Sync all dependencies**: `uv sync` (installs all optional groups automatically) |
There was a problem hiding this comment.
do you have it configured somewhere to automatically install all optional groups? if not, then only if you add --all-extras would it install them
| After setup, you can use Lobster models directly in Cursor or Claude Desktop with natural language commands like: | ||
| #### Option 1: One-Click Install (Recommended) | ||
|
|
||
| [](cursor://anysphere.cursor-deeplink/mcp/install?name=lobster-inference&config=eyJjb21tYW5kIjogInV2IiwgImFyZ3MiOiBbInJ1biIsICItLXByb2plY3QiLCAiLiIsICItLWV4dHJhIiwgIm1jcCIsICJsb2JzdGVyX21jcF9zZXJ2ZXIiXSwgImVudiI6IHt9LCAiY3dkIjogIiR7d29ya3NwYWNlRm9sZGVyfSJ9Cg==) |
There was a problem hiding this comment.
the command encoded in this link will only work if the cursor working dir is the lobster project dir, right? (because you have uv run --project . ...). I don't think there's a great way to get around this with a local MCP server, but you could use the --directory option and then tell a user to set that to the directory where they cloned the lobster repo.
| self.app = app | ||
| self._registered_tools = {} | ||
|
|
||
| def register_all_tools(self) -> None: |
There was a problem hiding this comment.
Your solution is fine and makes a lot of sense, but it does require that new tools are always imported and added here. Another way of doing it would be to move tool registration to where the tools are defined, e.g., you could have a @register_tool decorator or something. Or, if new tools in tools/ are always meant to be registered, you could have some sort of auto-registration that just registers all functions it's able to import from tools.
| logger = logging.getLogger("lobster-fastmcp-server") | ||
|
|
||
|
|
||
| def get_sequence_concepts(model_name: str, sequences: list[str]) -> dict: |
There was a problem hiding this comment.
nit: more specific type hint dict[str, Any]? If you want to be more specific, use a Pydantic model (actually I'm not completely sure whether that's supported for function output, but you could try): https://gofastmcp.com/servers/tools#pydantic-models. It would also be nice if fastmcp just supported TypedDict
| raise | ||
|
|
||
|
|
||
| def get_supported_concepts(model_name: str) -> dict: |
| concept: str, | ||
| edits: int = 5, | ||
| intervention_type: Literal["positive", "negative"] = "negative", | ||
| ) -> dict: |
| sequences: list[str], | ||
| model_type: Literal["masked_lm", "concept_bottleneck"], | ||
| representation_type: Literal["cls", "pooled", "full"] = "pooled", | ||
| ) -> SequenceRepresentationResult: |
There was a problem hiding this comment.
Have you tested whether the dataclass output works? The only thing I can find in the docs on more complex data is Pydantic models: https://gofastmcp.com/servers/tools#pydantic-models
There was a problem hiding this comment.
it seems to, i don't think that it's necessary though
| return "cuda" if torch.cuda.is_available() else "cpu" | ||
|
|
||
|
|
||
| def _load_model(model_name: str, model_type: str): |
There was a problem hiding this comment.
slap on a @cache decorator from functools?
| return "cuda" if torch.cuda.is_available() else "cpu" | ||
|
|
||
|
|
||
| def _load_model(model_name: str, model_type: str): |
| return model | ||
|
|
||
|
|
||
| def list_available_models() -> dict[str, Any]: |
There was a problem hiding this comment.
It seems like the MCP client workflow right now requires a list_available_models call at some point to discover which models are available and then passing in the correct names into the tool functions via model_name. To avoid requiring the list_available_models call, you could modify AVAILABLE_MODELS to be an Enum instead (or split into two enums for masked_lm and concept_bottleneck) and then set the model_name (and model_type) type hint to the enum class: https://gofastmcp.com/servers/tools#enums
That being said, I'm not sure whether the information from the enum type hint is provided as context to the LLM when it calls a tool, but if it is, then you'd always have the available model info automatically for each tool call.
* hot fix badge * mcp * fix and expand tests * mcp factory * changes * fixes * test fixes --------- Co-authored-by: freyn6 <freyn6@gene.com>
* hot fix badge * mcp * fix and expand tests * mcp factory * changes * fixes * test fixes --------- Co-authored-by: freyn6 <freyn6@gene.com>
Description
This pull request introduces significant updates to the documentation, architecture, and tooling for the Lobster MCP server, focusing on modularity, usability, and integration with external tools like Cursor and Claude Desktop. Key changes include the introduction of a modular architecture for the MCP server, enhanced documentation for development workflows, and improved setup instructions for integration with Cursor and Claude Desktop.
Documentation Enhancements:
docs/MCP_INTEGRATION.mdon the modular architecture, including descriptions of themodels/,schemas/, andtools/directories, as well as theserver.pyfile. These updates emphasize separation of concerns and scalability. [1] [2]README.mdanddocs/MCP_INTEGRATION.mdwith clearer setup instructions for Cursor and Claude Desktop, including automated and manual installation options. [1] [2]Code Organization:
tools/, request/response schemas toschemas/, and model management tomodels/. Theserver.pyfile now serves as the main entry point. [1] [2]inference_server.pyfile in favor of the newserver.pyimplementation.Integration Improvements:
docs/MCP_INTEGRATION.mdfor concise setup and usage instructions.Tooling Updates:
pyproject.tomlfile to point thelobster_mcp_serverentry to the newserver.pyimplementation.Code Quality and Testing:
Type of Change
Testing
Checklist