""" Standalone Flask MCP Server Extracted from streamlit.py to run as separate service """ import sys import os sys.path.insert(0, '/app') from flask import Flask, request, jsonify from flask_cors import CORS import numpy as np import warnings warnings.filterwarnings('ignore') # Helper function to convert numpy arrays to JSON-serializable format def clean_for_json(obj): """Convert numpy arrays and other non-serializable objects to JSON-safe format""" if isinstance(obj, dict): return {k: clean_for_json(v) for k, v in obj.items()} elif isinstance(obj, list): return [clean_for_json(item) for item in obj] elif isinstance(obj, np.ndarray): return obj.tolist() elif isinstance(obj, (np.integer, np.int64, np.int32)): return int(obj) elif isinstance(obj, (np.floating, np.float64, np.float32)): if np.isnan(obj) or np.isinf(obj): return 0.0 return float(obj) else: return obj # Import TSNEExplorer from streamlit.py try: import importlib.util spec = importlib.util.spec_from_file_location("streamlit_module", "/app/streamlit.py") streamlit_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(streamlit_module) TSNEExplorer = streamlit_module.TSNEExplorer except Exception as e: print(f"Error importing TSNEExplorer: {e}") TSNEExplorer = None app = Flask(__name__) CORS(app) backend = None def get_backend(): global backend if backend is None and TSNEExplorer is not None: backend = TSNEExplorer() return backend @app.route('/mcp/health', methods=['GET']) def health(): return jsonify({ 'status': 'ok', 'service': 'mcp-server', 'message': 'MCP server running on HF Spaces' }) @app.route('/mcp/generate_simplex_points', methods=['POST']) def generate_simplex_points(): try: data = request.json backend = get_backend() result = backend.generate_simplex_points( int(data['n']), int(data['d']), int(data['k']), int(data.get('seed', 42)) ) return jsonify(clean_for_json(result)) except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @app.route('/mcp/load_mnist', methods=['POST']) def load_mnist(): try: data = request.json backend = get_backend() result = backend.load_mnist( int(data.get('max_samples', 1000)), data.get('subset', 'train') ) return jsonify(clean_for_json(result)) except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @app.route('/mcp/run_tsne', methods=['POST']) def run_tsne(): try: data = request.json backend = get_backend() X = np.array(data['X']) result = backend.run_tsne( X, int(data.get('perplexity', 30)), int(data.get('learning_rate', 200)), int(data.get('n_iter', 1000)), int(data.get('early_exaggeration', 12)), float(data.get('momentum', 0.8)), int(data.get('seed', 42)) ) return jsonify(clean_for_json(result)) except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @app.route('/mcp/run_clustering', methods=['POST']) def run_clustering(): try: data = request.json backend = get_backend() Y = np.array(data['Y']) result = backend.run_clustering( Y, data.get('method', 'kmeans'), int(data.get('k', 3)), float(data.get('eps', 0.5)), int(data.get('min_samples', 5)) ) return jsonify(clean_for_json(result)) except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 if __name__ == '__main__': print('Starting Flask MCP Server on port 5000...') app.run(host='0.0.0.0', port=5000, debug=False, threaded=True)