Spaces:
Running
Running
| """Gradio UI that doubles as an MCP server. | |
| `demo.launch(mcp_server=True)` exposes each function wrapped in a click handler | |
| as an MCP tool at /gradio_api/mcp/. The same code thus serves a human web UI | |
| AND any MCP-compatible code agent (Claude Code, Codex, OpenCode, Pi). | |
| Run locally: python app.py -> http://localhost:7860 | |
| -> MCP at http://localhost:7860/gradio_api/mcp/ | |
| Deployed: same on HF Spaces -> /gradio_api/mcp/ | |
| """ | |
| from __future__ import annotations | |
| import json | |
| from collections import Counter | |
| import gradio as gr | |
| STOPWORDS = { | |
| "the", "a", "an", "and", "or", "but", "in", "on", "at", "to", "for", | |
| "of", "with", "is", "are", "was", "were", "be", "been", "by", "from", | |
| } | |
| def analyze_text(text: str) -> str: | |
| """Analyze text and return statistics. | |
| Args: | |
| text: The input text to analyze. | |
| Returns: | |
| JSON string with character, word, and sentence statistics. | |
| """ | |
| words = text.split() | |
| chars = len(text) | |
| chars_no_spaces = len(text.replace(" ", "")) | |
| sentences = max(text.count(".") + text.count("!") + text.count("?"), 1) | |
| avg_word_length = round(chars_no_spaces / len(words), 2) if words else 0 | |
| avg_sentence_length = round(len(words) / sentences, 2) if words else 0 | |
| return json.dumps({ | |
| "total_characters": chars, | |
| "characters_without_spaces": chars_no_spaces, | |
| "total_words": len(words), | |
| "total_sentences": sentences, | |
| "average_word_length": avg_word_length, | |
| "average_sentence_length": avg_sentence_length, | |
| }, indent=2) | |
| def extract_keywords(text: str, count: int = 5) -> str: | |
| """Extract keywords (most common non-stopword words) from text. | |
| Args: | |
| text: The input text. | |
| count: Number of keywords to return (default 5). | |
| Returns: | |
| JSON string with the top-N keywords and frequencies. | |
| """ | |
| filtered = [ | |
| w.strip(".,!?;:") for w in text.lower().split() if w not in STOPWORDS | |
| ] | |
| top = Counter(filtered).most_common(max(1, int(count))) | |
| return json.dumps( | |
| {"keywords": [{"word": w, "frequency": f} for w, f in top]}, | |
| indent=2, | |
| ) | |
| def check_reading_level(text: str) -> str: | |
| """Estimate reading difficulty via a Flesch-Kincaid-style grade. | |
| Args: | |
| text: The input text. | |
| Returns: | |
| JSON string with the numeric grade and a coarse label. | |
| """ | |
| sentences = max(text.count(".") + text.count("!") + text.count("?"), 1) | |
| words = len(text.split()) | |
| if words == 0: | |
| return json.dumps({"error": "No text to analyze"}) | |
| syllables = sum(1 for c in text.lower() if c in "aeiou") | |
| grade = max( | |
| 0.0, | |
| (0.39 * (words / sentences)) + (11.8 * (syllables / words)) - 15.59, | |
| ) | |
| if grade < 6: | |
| label = "Elementary School" | |
| elif grade < 9: | |
| label = "Middle School" | |
| elif grade < 13: | |
| label = "High School" | |
| else: | |
| label = "College/Academic" | |
| return json.dumps( | |
| {"grade_level": round(grade, 1), "reading_level": label}, | |
| indent=2, | |
| ) | |
| with gr.Blocks(title="Text Processor (MCP)") as demo: | |
| gr.Markdown("# Text Processing Tools") | |
| gr.Markdown( | |
| "Analyze text statistics, extract keywords, and check reading " | |
| "difficulty. Also exposed as an MCP server at `/gradio_api/mcp/`." | |
| ) | |
| with gr.Tab("Analyze"): | |
| text_in1 = gr.Textbox(label="Enter text", lines=8, | |
| placeholder="Paste your text here…") | |
| out1 = gr.Textbox(label="Analysis", lines=10) | |
| gr.Button("Analyze", variant="primary").click( | |
| analyze_text, text_in1, out1 | |
| ) | |
| with gr.Tab("Extract Keywords"): | |
| text_in2 = gr.Textbox(label="Enter text", lines=8) | |
| count_in = gr.Slider(1, 20, value=5, step=1, label="Number of keywords") | |
| out2 = gr.Textbox(label="Keywords", lines=10) | |
| gr.Button("Extract", variant="primary").click( | |
| extract_keywords, [text_in2, count_in], out2 | |
| ) | |
| with gr.Tab("Reading Level"): | |
| text_in3 = gr.Textbox(label="Enter text", lines=8) | |
| out3 = gr.Textbox(label="Reading level", lines=5) | |
| gr.Button("Check", variant="primary").click( | |
| check_reading_level, text_in3, out3 | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(mcp_server=True) | |