Skip to main content
Glama

scan-dicom-directory

Scan directories to find and organize DICOM medical image files into structured series for analysis and management.

Instructions

Scan a directory for DICOM files and organize them into series

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
directoryYesPath to directory containing DICOM files

Implementation Reference

  • MCP tool handler for 'scan-dicom-directory': validates directory, calls scan_directory helper, stores series in global state, notifies clients of resource changes, and returns summary of found series.
    elif name == "scan-dicom-directory":
        directory = arguments.get("directory")
        if not directory or not os.path.isdir(directory):
            raise ValueError(f"Invalid directory: {directory}")
            
        # Scan the directory for DICOM files
        series_list = scan_directory(directory)
        
        # Update state with found series
        for series in series_list:
            dicom_data[series.series_uid] = series
            
        # Notify clients that resources have changed
        await server.request_context.session.send_resource_list_changed()
        
        return [
            types.TextContent(
                type="text",
                text=f"Found {len(series_list)} DICOM series in {directory}:\n" + 
                     "\n".join([f"- {s.modality or 'Unknown'}: {s.description or s.series_uid} ({s.file_count} files)" for s in series_list])
            )
        ]
  • Registration of the 'scan-dicom-directory' tool in handle_list_tools(), including description and JSON input schema requiring 'directory' path.
    types.Tool(
        name="scan-dicom-directory",
        description="Scan a directory for DICOM files and organize them into series",
        inputSchema={
            "type": "object",
            "properties": {
                "directory": {"type": "string", "description": "Path to directory containing DICOM files"},
            },
            "required": ["directory"],
        },
    ),
  • Pydantic model (schema) for DicomSeries used as return type for scan_directory and stored in server state.
    class DicomSeries(BaseModel):
        """Model representing a DICOM series"""
        series_uid: str
        study_uid: Optional[str] = None
        modality: str
        description: Optional[str] = None
        path: str
        file_count: int
        patient_id: Optional[str] = None
  • Core helper function that scans directory recursively for DICOM files using glob and pydicom, groups by SeriesInstanceUID, extracts metadata, and returns list of DicomSeries objects.
    def scan_directory(directory: str) -> List[DicomSeries]:
        """Scan a directory for DICOM files and organize them into series"""
        series_dict = {}
        
        # Find all DICOM files (recursively if needed)
        dicom_files = []
        for ext in [".dcm", ".DCM", ""]:  # Empty string for no extension files
            dicom_files.extend(glob.glob(os.path.join(directory, f"**/*{ext}"), recursive=True))
        
        for file_path in dicom_files:
            try:
                ds = pydicom.dcmread(file_path, stop_before_pixels=True)
                series_uid = ds.SeriesInstanceUID
                
                if series_uid not in series_dict:
                    series_dict[series_uid] = {
                        "files": [],
                        "study_uid": getattr(ds, "StudyInstanceUID", None),
                        "modality": getattr(ds, "Modality", "Unknown"),
                        "description": getattr(ds, "SeriesDescription", None),
                        "patient_id": getattr(ds, "PatientID", None)
                    }
                
                series_dict[series_uid]["files"].append(file_path)
            except Exception as e:
                print(f"Error reading {file_path}: {e}")
        
        # Convert to DicomSeries objects
        result = []
        for series_uid, data in series_dict.items():
            # Use the directory of the first file as the series path
            series_path = os.path.dirname(data["files"][0]) if data["files"] else ""
            
            result.append(DicomSeries(
                series_uid=series_uid,
                study_uid=data["study_uid"],
                modality=data["modality"],
                description=data["description"],
                path=series_path,
                file_count=len(data["files"]),
                patient_id=data["patient_id"]
            ))
        
        return result
Behavior2/5

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

With no annotations provided, the description carries full burden but lacks behavioral details. It doesn't disclose what 'organize into series' entails (e.g., grouping by study/patient, output format), potential side effects (e.g., file system access), error handling, or performance considerations (e.g., large directories).

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 a single, efficient sentence with zero waste. It's front-loaded with the core action and outcome, making it easy to parse quickly.

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

Completeness2/5

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

For a tool with no annotations, no output schema, and behavioral complexity (scanning and organizing files), the description is incomplete. It omits critical details like return format (e.g., list of series, structured data), error cases, and how organization works, leaving gaps for an AI agent.

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 100%, so the schema already documents the single 'directory' parameter. The description adds no additional meaning beyond implying the directory contains DICOM files, which is redundant with the schema's description. Baseline 3 is appropriate when schema does the heavy lifting.

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 clearly states the specific action ('scan'), target resource ('directory for DICOM files'), and outcome ('organize them into series'). It distinguishes from siblings like 'extract-dicom-metadata' (metadata extraction) and 'load-dicom-series' (loading already organized series).

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

Usage Guidelines2/5

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

No explicit guidance on when to use this tool versus alternatives is provided. It doesn't mention prerequisites (e.g., directory must exist, files must be DICOM format) or contrast with siblings like 'load-dicom-series' (for pre-organized series). Usage is implied but not articulated.

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

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shaunporwal/DICOM-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server