""" Model Context Protocol (MCP) for TISSUE TISSUE (Transcript Imputation with Spatial Single-cell Uncertainty Estimation) provides methods for spatial gene expression prediction and uncertainty quantification in spatial transcriptomics data. It enables uncertainty-aware analysis including multiple imputation, cell filtering, and weighted PCA for improved downstream analysis. This MCP Server contains the tools extracted from the following tutorials: 1. tissue - predict_spatial_gene_expression: Predict spatial gene expression using paired spatial and scRNA-seq data - calibrate_uncertainties_and_prediction_intervals: Use TISSUE to calibrate uncertainties and obtain prediction intervals - multiple_imputation_hypothesis_testing: Hypothesis testing with TISSUE multiple imputation framework - tissue_cell_filtering_for_supervised_learning: TISSUE cell filtering for supervised learning applications - tissue_cell_filtering_for_pca: TISSUE cell filtering for PCA, clustering and visualization - tissue_weighted_pca: TISSUE-WPCA (weighted principal component analysis) """ import sys from pathlib import Path from fastmcp import FastMCP # Import the MCP tools from the tools folder from tools.tissue_readme import tissue_mcp from starlette.requests import Request from starlette.responses import PlainTextResponse, JSONResponse import os from fastapi.staticfiles import StaticFiles import uuid # Define the MCP server mcp = FastMCP(name = "TISSUE") # Mount the tools mcp.mount(tissue_mcp) # Use absolute directory for uploads BASE_DIR = os.path.dirname(os.path.abspath(__file__)) UPLOAD_DIR = os.path.join(BASE_DIR, "/data/upload") os.makedirs(UPLOAD_DIR, exist_ok=True) @mcp.custom_route("/health", methods=["GET"]) async def health_check(request: Request) -> PlainTextResponse: return PlainTextResponse("OK") @mcp.custom_route("/", methods=["GET"]) async def index(request: Request) -> PlainTextResponse: return PlainTextResponse("MCP is on https://Paper2Agent-tissue-mcp.hf.space/mcp") # Upload route @mcp.custom_route("/upload", methods=["POST"]) async def upload(request: Request): form = await request.form() up = form.get("file") if up is None: return JSONResponse({"error": "missing form field 'file'"}, status_code=400) # Generate a safe filename orig = getattr(up, "filename", "") or "" ext = os.path.splitext(orig)[1] name = f"{uuid.uuid4().hex}{ext}" dst = os.path.join(UPLOAD_DIR, name) # up is a Starlette UploadFile-like object with open(dst, "wb") as out: out.write(await up.read()) # Return only the absolute local path abs_path = os.path.abspath(dst) return JSONResponse({"path": abs_path}) app = mcp.http_app(path="/mcp") # Saved uploaded input files app.mount("/files", StaticFiles(directory=UPLOAD_DIR), name="files") # Saved output files app.mount("/outputs", StaticFiles(directory="/data/tmp_outputs"), name="outputs") # Run the MCP server if __name__ == "__main__": mcp.run(transport="http", host="127.0.0.1", port=8003)