save_results
Save GIS analysis results to files in multiple formats for later use or sharing. Specify formats and location to store geospatial data outputs.
Instructions
MCP Tool: Save any GIS-MCP result dict to files, only when the user requests.
Args: data: The dictionary returned by any GIS-MCP tool. filename: Base filename without extension. formats: List of formats to save (default = all). folder: Target folder (relative to configured storage directory, or absolute path).
Returns: Dict with 'saved_files' mapping format -> path.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | ||
| filename | No | ||
| formats | No | ||
| folder | No | outputs |
Implementation Reference
- src/gis_mcp/save_tool.py:161-189 (handler)The handler function decorated with @gis_mcp.tool(), implementing the core logic of the 'save_results' MCP tool by calling the save_output helper.@gis_mcp.tool() def save_results( data: Dict[str, Any], filename: Optional[str] = None, formats: Optional[List[str]] = None, folder: str = "outputs" ) -> Dict[str, Any]: """ MCP Tool: Save any GIS-MCP result dict to files, only when the user requests. Args: data: The dictionary returned by any GIS-MCP tool. filename: Base filename without extension. formats: List of formats to save (default = all). folder: Target folder (relative to configured storage directory, or absolute path). Returns: Dict with 'saved_files' mapping format -> path. """ try: paths = save_output(data, filename=filename, folder=folder, formats=formats) return { "status": "success", "saved_files": paths, "message": "Results saved successfully." } except Exception as e: return {"status": "error", "message": f"Failed to save results: {e}"}
- src/gis_mcp/save_tool.py:27-158 (helper)Supporting function that handles saving data to multiple file formats (JSON, CSV, shapefile, GeoTIFF, etc.), called by the save_results handler.def save_output( output: Dict[str, Any], filename: Optional[str] = None, folder: str = "outputs", formats: Optional[List[str]] = None, ) -> Dict[str, str]: """ Save the output dictionary to multiple formats: JSON, CSV, TXT, YAML, XLSX, SHP, GEOJSON, GeoTIFF, TIFF. The folder path is resolved relative to the configured storage directory. If an absolute path is provided, it's used as-is. Returns a mapping of format -> saved file path. """ # Resolve folder path relative to storage directory folder_path = resolve_path(folder, relative_to_storage=True) folder_path.mkdir(parents=True, exist_ok=True) if not filename: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"output_{timestamp}" if formats is None: formats = ["json", "csv", "txt", "yaml", "xlsx", "shp", "geojson", "geotiff", "tiff"] saved_files = {} # JSON if "json" in formats: path = folder_path / f"{filename}.json" with open(path, "w", encoding="utf-8") as f: json.dump(output, f, indent=4, ensure_ascii=False) saved_files["json"] = str(path) # CSV if "csv" in formats: try: path = folder_path / f"{filename}.csv" df = pd.json_normalize(output) df.to_csv(path, index=False) saved_files["csv"] = str(path) except Exception as e: print(f"Could not save CSV: {e}") # TXT if "txt" in formats: path = folder_path / f"{filename}.txt" with open(path, "w", encoding="utf-8") as f: for k, v in output.items(): f.write(f"{k}: {v}\n") saved_files["txt"] = str(path) # YAML if "yaml" in formats: path = folder_path / f"{filename}.yaml" with open(path, "w", encoding="utf-8") as f: yaml.safe_dump(output, f, allow_unicode=True) saved_files["yaml"] = str(path) # Excel if "xlsx" in formats: try: path = folder_path / f"{filename}.xlsx" df = pd.json_normalize(output) df.to_excel(path, index=False) saved_files["xlsx"] = str(path) except Exception as e: print(f"Could not save Excel: {e}") # Shapefile if "shp" in formats and "geometry" in output: try: path = folder_path / f"{filename}.shp" geom = wkt.loads(output["geometry"]) gdf = gpd.GeoDataFrame([output], geometry=[geom], crs="EPSG:4326") gdf.to_file(path, driver="ESRI Shapefile") saved_files["shp"] = str(path) except Exception as e: print(f"Could not save Shapefile: {e}") # GeoJSON if "geojson" in formats and "geometry" in output: try: path = folder_path / f"{filename}.geojson" geom = wkt.loads(output["geometry"]) gdf = gpd.GeoDataFrame([output], geometry=[geom], crs="EPSG:4326") gdf.to_file(path, driver="GeoJSON") saved_files["geojson"] = str(path) except Exception as e: print(f"Could not save GeoJSON: {e}") # GeoTIFF if "geotiff" in formats and "raster" in output: try: path = folder_path / f"{filename}.tif" raster_data = np.array(output["raster"]) transform = from_origin(0, 0, 1, 1) crs = output.get("crs", "EPSG:4326") with rasterio.open( path, "w", driver="GTiff", height=raster_data.shape[0], width=raster_data.shape[1], count=1 if raster_data.ndim == 2 else raster_data.shape[2], dtype=raster_data.dtype, crs=crs, transform=transform, ) as dst: if raster_data.ndim == 2: dst.write(raster_data, 1) else: for i in range(raster_data.shape[2]): dst.write(raster_data[:, :, i], i + 1) saved_files["geotiff"] = str(path) except Exception as e: print(f"Could not save GeoTIFF: {e}") # TIFF if "tiff" in formats and "image" in output: try: path = folder_path / f"{filename}.tiff" img = Image.fromarray(np.uint8(output["image"])) img.save(path, format="TIFF") saved_files["tiff"] = str(path) except Exception as e: print(f"Could not save TIFF: {e}") return saved_files
- src/gis_mcp/save_tool.py:161-161 (registration)Decorator that registers the save_results function as an MCP tool named 'save_results'.@gis_mcp.tool()