delete_protocol_step
Remove a specific step from a protocols.io protocol by providing both the protocol ID and step ID to delete unwanted or outdated protocol components.
Instructions
Delete a specific step from a protocol by providing both the protocol ID and step ID.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| protocol_id | Yes | Unique identifier for the protocol | |
| step_id | Yes | Unique identifier for the step to be deleted |
Implementation Reference
- The main handler function for the 'delete_protocol_step' tool. It is decorated with @mcp.tool(), which registers it as an MCP tool. The function deletes a specific step from a protocol using the Protocols.io API and returns the updated list of steps.@mcp.tool() async def delete_protocol_step( protocol_id: Annotated[int, Field(description="Unique identifier for the protocol")], step_id: Annotated[str, Field(description="Unique identifier for the step to be deleted")] ) -> list[ProtocolStep] | ErrorMessage: """ Delete a specific step from a protocol by providing both the protocol ID and step ID. """ response_delete_protocol_step = await helpers.access_protocols_io_resource("DELETE", f"/v4/protocols/{protocol_id}/steps", {"steps": [step_id]}) if response_delete_protocol_step["status_code"] != 0: return ErrorMessage.from_string(response_delete_protocol_step["status_text"]) response_get_protocol_steps = await helpers.access_protocols_io_resource("GET", f"/v4/protocols/{protocol_id}/steps?content_format=markdown") if response_get_protocol_steps["status_code"] != 0: return ErrorMessage.from_string(response_get_protocol_steps["status_text"]) steps = [ProtocolStep.from_api_response(step) for step in response_get_protocol_steps.get("payload", [])] return steps
- src/protocols_io_mcp/tools/protocol.py:349-349 (registration)The @mcp.tool() decorator registers the delete_protocol_step function as an MCP tool.@mcp.tool()
- Input schema defined via Annotated types in the function signature: protocol_id (int), step_id (str). Output is list[ProtocolStep] or ErrorMessage.async def delete_protocol_step( protocol_id: Annotated[int, Field(description="Unique identifier for the protocol")], step_id: Annotated[str, Field(description="Unique identifier for the step to be deleted")] ) -> list[ProtocolStep] | ErrorMessage: """ Delete a specific step from a protocol by providing both the protocol ID and step ID. """ response_delete_protocol_step = await helpers.access_protocols_io_resource("DELETE", f"/v4/protocols/{protocol_id}/steps", {"steps": [step_id]}) if response_delete_protocol_step["status_code"] != 0: return ErrorMessage.from_string(response_delete_protocol_step["status_text"]) response_get_protocol_steps = await helpers.access_protocols_io_resource("GET", f"/v4/protocols/{protocol_id}/steps?content_format=markdown") if response_get_protocol_steps["status_code"] != 0: return ErrorMessage.from_string(response_get_protocol_steps["status_text"]) steps = [ProtocolStep.from_api_response(step) for step in response_get_protocol_steps.get("payload", [])] return steps
- ProtocolStep model used for parsing and returning steps in the tool's output.class ProtocolStep(BaseModel): id: Annotated[str, Field(description="Unique identifier for the step")] description: Annotated[str, Field(description="Description of the step")] materials: Annotated[list[Material], Field(description="Materials required for this step. Empty if no materials are needed or if source data could not be parsed")] = Field(default_factory=list) reference_protocol_ids: Annotated[list[int], Field(description="Protocol IDs referenced by this step. Empty if no references exist or if source data could not be parsed")] = Field(default_factory=list) @staticmethod def parse(step: str) -> dict: description = [] materials = [] reference_protocol_ids = [] material_flag = False reference_flag = False for line in step.splitlines(): if material_flag is False and reference_flag is False: if line == "[Materials]": material_flag = True reference_flag = False elif line == "[Protocol References]": reference_flag = True material_flag = False elif len(line) > 0: description.append(line) elif material_flag: if len(line) == 0 or line[0] != '-': material_flag = False continue data = line.split() materials.append(Material( name=data[1], quantity=float(data[2]), unit=data[3] )) elif reference_flag: if len(line) == 0 or line[0] != '-': reference_flag = False continue data = line.split("[")[1].split("]")[0] reference_protocol_ids.append(int(data)) description = "\n".join(description) return { "description": description, "materials": materials, "reference_protocol_ids": reference_protocol_ids } @classmethod def from_api_response(cls, data: dict) -> "ProtocolStep": parsed_step = ProtocolStep.parse(data["step"]) return cls( id=data["guid"], description=parsed_step["description"], materials=parsed_step["materials"], reference_protocol_ids=parsed_step["reference_protocol_ids"] )
- ErrorMessage model used for error responses in the tool.class ErrorMessage(BaseModel): error_message: Annotated[str, Field(description="Error message describing the issue encountered")] @classmethod def from_string(cls, message: str) -> "ErrorMessage": return cls(error_message=message)