Buckets:

download
raw
60.6 kB
<meta charset="utf-8" /><meta name="hf:doc:metadata" content="{&quot;title&quot;:&quot;Hands-On: Build and Deploy an MCP Server&quot;,&quot;local&quot;:&quot;hands-on-build-and-deploy-an-mcp-server&quot;,&quot;sections&quot;:[{&quot;title&quot;:&quot;Project Overview&quot;,&quot;local&quot;:&quot;project-overview&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Part 1: Build the Server Locally&quot;,&quot;local&quot;:&quot;part-1-build-the-server-locally&quot;,&quot;sections&quot;:[{&quot;title&quot;:&quot;Step 1: Set Up Your Project&quot;,&quot;local&quot;:&quot;step-1-set-up-your-project&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3},{&quot;title&quot;:&quot;Step 2: Create the FastMCP Server&quot;,&quot;local&quot;:&quot;step-2-create-the-fastmcp-server&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3},{&quot;title&quot;:&quot;Step 3: Test the Server Locally&quot;,&quot;local&quot;:&quot;step-3-test-the-server-locally&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3}],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Part 2: Create a Gradio Web UI + MCP Server&quot;,&quot;local&quot;:&quot;part-2-create-a-gradio-web-ui--mcp-server&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Part 3: Deploy to Hugging Face Spaces&quot;,&quot;local&quot;:&quot;part-3-deploy-to-hugging-face-spaces&quot;,&quot;sections&quot;:[{&quot;title&quot;:&quot;Step 1: Create a New Space&quot;,&quot;local&quot;:&quot;step-1-create-a-new-space&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3},{&quot;title&quot;:&quot;Step 2: Upload Your Files&quot;,&quot;local&quot;:&quot;step-2-upload-your-files&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3},{&quot;title&quot;:&quot;Step 3: Configure Your Agent&quot;,&quot;local&quot;:&quot;step-3-configure-your-agent&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3},{&quot;title&quot;:&quot;Step 4: Test with Your Agent&quot;,&quot;local&quot;:&quot;step-4-test-with-your-agent&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3}],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Debugging&quot;,&quot;local&quot;:&quot;debugging&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Challenge Extensions&quot;,&quot;local&quot;:&quot;challenge-extensions&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Key Takeaways&quot;,&quot;local&quot;:&quot;key-takeaways&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2}],&quot;depth&quot;:1}">
<link href="/docs/context-course/pr_7/en/_app/immutable/assets/0.e3b0c442.css" rel="modulepreload">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/entry/start.55c3acaa.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/chunks/scheduler.4048030c.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/chunks/singletons.42509544.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/chunks/index.dd3f5310.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/chunks/paths.f6762227.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/entry/app.10ec5479.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/chunks/preload-helper.665302cf.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/chunks/index.5d0b9360.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/nodes/0.b63aa764.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/chunks/each.e59479a4.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/nodes/12.e5ef8c3d.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/chunks/MermaidChart.svelte_svelte_type_style_lang.99c2e6c8.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/chunks/CodeBlock.ff2a3276.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/chunks/HfOption.0fd5270b.js">
<link rel="modulepreload" href="/docs/context-course/pr_7/en/_app/immutable/chunks/stores.0a12db33.js"><!-- HEAD_svelte-u9bgzb_START --><meta name="hf:doc:metadata" content="{&quot;title&quot;:&quot;Hands-On: Build and Deploy an MCP Server&quot;,&quot;local&quot;:&quot;hands-on-build-and-deploy-an-mcp-server&quot;,&quot;sections&quot;:[{&quot;title&quot;:&quot;Project Overview&quot;,&quot;local&quot;:&quot;project-overview&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Part 1: Build the Server Locally&quot;,&quot;local&quot;:&quot;part-1-build-the-server-locally&quot;,&quot;sections&quot;:[{&quot;title&quot;:&quot;Step 1: Set Up Your Project&quot;,&quot;local&quot;:&quot;step-1-set-up-your-project&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3},{&quot;title&quot;:&quot;Step 2: Create the FastMCP Server&quot;,&quot;local&quot;:&quot;step-2-create-the-fastmcp-server&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3},{&quot;title&quot;:&quot;Step 3: Test the Server Locally&quot;,&quot;local&quot;:&quot;step-3-test-the-server-locally&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3}],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Part 2: Create a Gradio Web UI + MCP Server&quot;,&quot;local&quot;:&quot;part-2-create-a-gradio-web-ui--mcp-server&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Part 3: Deploy to Hugging Face Spaces&quot;,&quot;local&quot;:&quot;part-3-deploy-to-hugging-face-spaces&quot;,&quot;sections&quot;:[{&quot;title&quot;:&quot;Step 1: Create a New Space&quot;,&quot;local&quot;:&quot;step-1-create-a-new-space&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3},{&quot;title&quot;:&quot;Step 2: Upload Your Files&quot;,&quot;local&quot;:&quot;step-2-upload-your-files&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3},{&quot;title&quot;:&quot;Step 3: Configure Your Agent&quot;,&quot;local&quot;:&quot;step-3-configure-your-agent&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3},{&quot;title&quot;:&quot;Step 4: Test with Your Agent&quot;,&quot;local&quot;:&quot;step-4-test-with-your-agent&quot;,&quot;sections&quot;:[],&quot;depth&quot;:3}],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Debugging&quot;,&quot;local&quot;:&quot;debugging&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Challenge Extensions&quot;,&quot;local&quot;:&quot;challenge-extensions&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Key Takeaways&quot;,&quot;local&quot;:&quot;key-takeaways&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2}],&quot;depth&quot;:1}"><!-- HEAD_svelte-u9bgzb_END --> <p></p> <div class="items-center shrink-0 min-w-[100px] max-sm:min-w-[50px] justify-end ml-auto flex" style="float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"><div class="inline-flex rounded-md max-sm:rounded-sm"><button class="inline-flex items-center gap-1 h-7 max-sm:h-7 px-2 max-sm:px-1.5 text-sm font-medium text-gray-800 border border-r-0 rounded-l-md max-sm:rounded-l-sm border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-live="polite"><span class="inline-flex items-center justify-center rounded-md p-0.5 max-sm:p-0 hover:text-gray-800 dark:hover:text-gray-200"><svg class="sm:size-3.5 size-3" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg></span> <span>Copy page</span></button> <button class="inline-flex items-center justify-center w-6 max-sm:w-5 h-7 max-sm:h-7 disabled:pointer-events-none text-sm text-gray-500 hover:text-gray-700 dark:hover:text-white rounded-r-md max-sm:rounded-r-sm border border-l transition border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-haspopup="menu" aria-expanded="false" aria-label="Open copy menu"><svg class="transition-transform text-gray-400 overflow-visible sm:size-3.5 size-3 rotate-0" width="1em" height="1em" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L6 6L11 1" stroke="currentColor"></path></svg></button></div> </div> <h1 class="relative group"><a id="hands-on-build-and-deploy-an-mcp-server" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#hands-on-build-and-deploy-an-mcp-server"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Hands-On: Build and Deploy an MCP Server</span></h1> <p data-svelte-h="svelte-13k6ltx">In this project, you’ll build a complete MCP server that provides text processing tools, test it locally, and deploy it to Hugging Face Spaces.</p> <h2 class="relative group"><a id="project-overview" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#project-overview"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Project Overview</span></h2> <p data-svelte-h="svelte-1o446a9">You’ll create a text processing MCP server that allows code agents to:</p> <ul data-svelte-h="svelte-1npj0g1"><li>Analyze text statistics (word count, character count, etc.)</li> <li>Extract key phrases and entities</li> <li>Check spelling and grammar basics</li> <li>Summarize text</li></ul> <p data-svelte-h="svelte-13w3hn5">This is a real, shareable tool that works with any MCP-compatible agent.</p> <h2 class="relative group"><a id="part-1-build-the-server-locally" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#part-1-build-the-server-locally"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Part 1: Build the Server Locally</span></h2> <h3 class="relative group"><a id="step-1-set-up-your-project" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-1-set-up-your-project"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 1: Set Up Your Project</span></h3> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-built_in">mkdir</span> text-processor-mcp
<span class="hljs-built_in">cd</span> text-processor-mcp
python -m venv venv
<span class="hljs-built_in">source</span> venv/bin/activate <span class="hljs-comment"># On Windows: venv\Scripts\activate</span>
pip install <span class="hljs-string">&quot;mcp[cli]&quot;</span><!-- HTML_TAG_END --></pre></div> <h3 class="relative group"><a id="step-2-create-the-fastmcp-server" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-2-create-the-fastmcp-server"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 2: Create the FastMCP Server</span></h3> <p data-svelte-h="svelte-g4gw6x">Create <code>server.py</code>:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">from</span> mcp.server.fastmcp <span class="hljs-keyword">import</span> FastMCP
<span class="hljs-keyword">import</span> json
mcp = FastMCP(<span class="hljs-string">&quot;text-processor&quot;</span>)
<span class="hljs-meta">@mcp.tool()</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">analyze_text</span>(<span class="hljs-params">text: <span class="hljs-built_in">str</span></span>) -&gt; <span class="hljs-built_in">str</span>:
<span class="hljs-string">&quot;&quot;&quot;Analyze text and return statistics.
Args:
text: The input text to analyze
Returns:
JSON string with analysis results
&quot;&quot;&quot;</span>
words = text.split()
chars = <span class="hljs-built_in">len</span>(text)
chars_no_spaces = <span class="hljs-built_in">len</span>(text.replace(<span class="hljs-string">&quot; &quot;</span>, <span class="hljs-string">&quot;&quot;</span>))
sentences = text.count(<span class="hljs-string">&quot;.&quot;</span>) + text.count(<span class="hljs-string">&quot;!&quot;</span>) + text.count(<span class="hljs-string">&quot;?&quot;</span>)
avg_word_length = <span class="hljs-built_in">round</span>(chars_no_spaces / <span class="hljs-built_in">len</span>(words), <span class="hljs-number">2</span>) <span class="hljs-keyword">if</span> words <span class="hljs-keyword">else</span> <span class="hljs-number">0</span>
avg_sentence_length = <span class="hljs-built_in">round</span>(<span class="hljs-built_in">len</span>(words) / <span class="hljs-built_in">max</span>(sentences, <span class="hljs-number">1</span>), <span class="hljs-number">2</span>)
<span class="hljs-keyword">return</span> json.dumps({
<span class="hljs-string">&quot;total_characters&quot;</span>: chars,
<span class="hljs-string">&quot;characters_without_spaces&quot;</span>: chars_no_spaces,
<span class="hljs-string">&quot;total_words&quot;</span>: <span class="hljs-built_in">len</span>(words),
<span class="hljs-string">&quot;total_sentences&quot;</span>: <span class="hljs-built_in">max</span>(sentences, <span class="hljs-number">1</span>),
<span class="hljs-string">&quot;average_word_length&quot;</span>: avg_word_length,
<span class="hljs-string">&quot;average_sentence_length&quot;</span>: avg_sentence_length,
<span class="hljs-string">&quot;unique_words&quot;</span>: <span class="hljs-built_in">len</span>(<span class="hljs-built_in">set</span>(word.lower() <span class="hljs-keyword">for</span> word <span class="hljs-keyword">in</span> words))
})
<span class="hljs-meta">@mcp.tool()</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">extract_keywords</span>(<span class="hljs-params">text: <span class="hljs-built_in">str</span>, count: <span class="hljs-built_in">int</span> = <span class="hljs-number">5</span></span>) -&gt; <span class="hljs-built_in">str</span>:
<span class="hljs-string">&quot;&quot;&quot;Extract keywords (most common words) from text.
Args:
text: The input text
count: Number of keywords to return (default 5)
Returns:
JSON string with keywords and frequencies
&quot;&quot;&quot;</span>
<span class="hljs-comment"># Remove common words</span>
stopwords = {
<span class="hljs-string">&quot;the&quot;</span>, <span class="hljs-string">&quot;a&quot;</span>, <span class="hljs-string">&quot;an&quot;</span>, <span class="hljs-string">&quot;and&quot;</span>, <span class="hljs-string">&quot;or&quot;</span>, <span class="hljs-string">&quot;but&quot;</span>, <span class="hljs-string">&quot;in&quot;</span>, <span class="hljs-string">&quot;on&quot;</span>, <span class="hljs-string">&quot;at&quot;</span>, <span class="hljs-string">&quot;to&quot;</span>, <span class="hljs-string">&quot;for&quot;</span>,
<span class="hljs-string">&quot;of&quot;</span>, <span class="hljs-string">&quot;with&quot;</span>, <span class="hljs-string">&quot;is&quot;</span>, <span class="hljs-string">&quot;are&quot;</span>, <span class="hljs-string">&quot;was&quot;</span>, <span class="hljs-string">&quot;were&quot;</span>, <span class="hljs-string">&quot;be&quot;</span>, <span class="hljs-string">&quot;been&quot;</span>, <span class="hljs-string">&quot;by&quot;</span>, <span class="hljs-string">&quot;from&quot;</span>
}
words = text.lower().split()
filtered = [w.strip(<span class="hljs-string">&quot;.,!?;:&quot;</span>) <span class="hljs-keyword">for</span> w <span class="hljs-keyword">in</span> words <span class="hljs-keyword">if</span> w.lower() <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> stopwords]
<span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> Counter
word_freq = Counter(filtered)
top_words = word_freq.most_common(count)
<span class="hljs-keyword">return</span> json.dumps({
<span class="hljs-string">&quot;keywords&quot;</span>: [{<span class="hljs-string">&quot;word&quot;</span>: w, <span class="hljs-string">&quot;frequency&quot;</span>: f} <span class="hljs-keyword">for</span> w, f <span class="hljs-keyword">in</span> top_words]
})
<span class="hljs-meta">@mcp.tool()</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">check_reading_level</span>(<span class="hljs-params">text: <span class="hljs-built_in">str</span></span>) -&gt; <span class="hljs-built_in">str</span>:
<span class="hljs-string">&quot;&quot;&quot;Estimate reading difficulty level.
Args:
text: The input text
Returns:
JSON string with reading level estimate
&quot;&quot;&quot;</span>
sentences = <span class="hljs-built_in">max</span>(text.count(<span class="hljs-string">&quot;.&quot;</span>) + text.count(<span class="hljs-string">&quot;!&quot;</span>) + text.count(<span class="hljs-string">&quot;?&quot;</span>), <span class="hljs-number">1</span>)
words = <span class="hljs-built_in">len</span>(text.split())
syllables = text.count(<span class="hljs-string">&quot;a&quot;</span>) + text.count(<span class="hljs-string">&quot;e&quot;</span>) + text.count(<span class="hljs-string">&quot;i&quot;</span>) + text.count(<span class="hljs-string">&quot;o&quot;</span>) + text.count(<span class="hljs-string">&quot;u&quot;</span>)
<span class="hljs-keyword">if</span> words == <span class="hljs-number">0</span>:
<span class="hljs-keyword">return</span> json.dumps({<span class="hljs-string">&quot;error&quot;</span>: <span class="hljs-string">&quot;No text to analyze&quot;</span>})
<span class="hljs-comment"># Flesch Kincaid Grade</span>
grade = (<span class="hljs-number">0.39</span> * (words / sentences)) + (<span class="hljs-number">11.8</span> * (syllables / words)) - <span class="hljs-number">15.59</span>
grade = <span class="hljs-built_in">max</span>(<span class="hljs-number">0</span>, <span class="hljs-built_in">round</span>(grade, <span class="hljs-number">1</span>))
<span class="hljs-keyword">if</span> grade &lt; <span class="hljs-number">6</span>:
level = <span class="hljs-string">&quot;Elementary School&quot;</span>
<span class="hljs-keyword">elif</span> grade &lt; <span class="hljs-number">9</span>:
level = <span class="hljs-string">&quot;Middle School&quot;</span>
<span class="hljs-keyword">elif</span> grade &lt; <span class="hljs-number">13</span>:
level = <span class="hljs-string">&quot;High School&quot;</span>
<span class="hljs-keyword">else</span>:
level = <span class="hljs-string">&quot;College/Academic&quot;</span>
<span class="hljs-keyword">return</span> json.dumps({
<span class="hljs-string">&quot;grade_level&quot;</span>: grade,
<span class="hljs-string">&quot;reading_level&quot;</span>: level
})
<span class="hljs-meta">@mcp.tool()</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">reverse_text</span>(<span class="hljs-params">text: <span class="hljs-built_in">str</span></span>) -&gt; <span class="hljs-built_in">str</span>:
<span class="hljs-string">&quot;&quot;&quot;Reverse a string.
Args:
text: The input text
Returns:
The reversed text
&quot;&quot;&quot;</span>
<span class="hljs-keyword">return</span> text[::-<span class="hljs-number">1</span>]
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">&quot;__main__&quot;</span>:
mcp.run()<!-- HTML_TAG_END --></pre></div> <h3 class="relative group"><a id="step-3-test-the-server-locally" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-3-test-the-server-locally"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 3: Test the Server Locally</span></h3> <p data-svelte-h="svelte-1q51zrc">Start the server:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->python server.py<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1n0dg4c">The server listens on stdin/stdout. Open it in the MCP Inspector to list and call tools:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->mcp dev server.py<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1w199ve">This launches the inspector in your browser connected to your server, where you can see all four tools and try them.</p> <h2 class="relative group"><a id="part-2-create-a-gradio-web-ui--mcp-server" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#part-2-create-a-gradio-web-ui--mcp-server"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Part 2: Create a Gradio Web UI + MCP Server</span></h2> <p data-svelte-h="svelte-1rd1by5">Create <code>app.py</code> to add a web interface:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">import</span> gradio <span class="hljs-keyword">as</span> gr
<span class="hljs-keyword">import</span> json
<span class="hljs-keyword">def</span> <span class="hljs-title function_">analyze_text</span>(<span class="hljs-params">text: <span class="hljs-built_in">str</span></span>) -&gt; <span class="hljs-built_in">str</span>:
<span class="hljs-string">&quot;&quot;&quot;Analyze text and return statistics.
Args:
text: The input text to analyze
Returns:
JSON string with analysis results
&quot;&quot;&quot;</span>
words = text.split()
chars = <span class="hljs-built_in">len</span>(text)
chars_no_spaces = <span class="hljs-built_in">len</span>(text.replace(<span class="hljs-string">&quot; &quot;</span>, <span class="hljs-string">&quot;&quot;</span>))
sentences = text.count(<span class="hljs-string">&quot;.&quot;</span>) + text.count(<span class="hljs-string">&quot;!&quot;</span>) + text.count(<span class="hljs-string">&quot;?&quot;</span>)
avg_word_length = <span class="hljs-built_in">round</span>(chars_no_spaces / <span class="hljs-built_in">len</span>(words), <span class="hljs-number">2</span>) <span class="hljs-keyword">if</span> words <span class="hljs-keyword">else</span> <span class="hljs-number">0</span>
avg_sentence_length = <span class="hljs-built_in">round</span>(<span class="hljs-built_in">len</span>(words) / <span class="hljs-built_in">max</span>(sentences, <span class="hljs-number">1</span>), <span class="hljs-number">2</span>)
<span class="hljs-keyword">return</span> json.dumps({
<span class="hljs-string">&quot;total_characters&quot;</span>: chars,
<span class="hljs-string">&quot;characters_without_spaces&quot;</span>: chars_no_spaces,
<span class="hljs-string">&quot;total_words&quot;</span>: <span class="hljs-built_in">len</span>(words),
<span class="hljs-string">&quot;total_sentences&quot;</span>: <span class="hljs-built_in">max</span>(sentences, <span class="hljs-number">1</span>),
<span class="hljs-string">&quot;average_word_length&quot;</span>: avg_word_length,
<span class="hljs-string">&quot;average_sentence_length&quot;</span>: avg_sentence_length
}, indent=<span class="hljs-number">2</span>)
<span class="hljs-keyword">def</span> <span class="hljs-title function_">extract_keywords</span>(<span class="hljs-params">text: <span class="hljs-built_in">str</span>, count: <span class="hljs-built_in">int</span> = <span class="hljs-number">5</span></span>) -&gt; <span class="hljs-built_in">str</span>:
<span class="hljs-string">&quot;&quot;&quot;Extract keywords (most common words) from text.
Args:
text: The input text
count: Number of keywords to return (default 5)
Returns:
JSON string with keywords and frequencies
&quot;&quot;&quot;</span>
stopwords = {
<span class="hljs-string">&quot;the&quot;</span>, <span class="hljs-string">&quot;a&quot;</span>, <span class="hljs-string">&quot;an&quot;</span>, <span class="hljs-string">&quot;and&quot;</span>, <span class="hljs-string">&quot;or&quot;</span>, <span class="hljs-string">&quot;but&quot;</span>, <span class="hljs-string">&quot;in&quot;</span>, <span class="hljs-string">&quot;on&quot;</span>, <span class="hljs-string">&quot;at&quot;</span>, <span class="hljs-string">&quot;to&quot;</span>, <span class="hljs-string">&quot;for&quot;</span>,
<span class="hljs-string">&quot;of&quot;</span>, <span class="hljs-string">&quot;with&quot;</span>, <span class="hljs-string">&quot;is&quot;</span>, <span class="hljs-string">&quot;are&quot;</span>, <span class="hljs-string">&quot;was&quot;</span>, <span class="hljs-string">&quot;were&quot;</span>, <span class="hljs-string">&quot;be&quot;</span>, <span class="hljs-string">&quot;been&quot;</span>, <span class="hljs-string">&quot;by&quot;</span>, <span class="hljs-string">&quot;from&quot;</span>
}
words = text.lower().split()
filtered = [w.strip(<span class="hljs-string">&quot;.,!?;:&quot;</span>) <span class="hljs-keyword">for</span> w <span class="hljs-keyword">in</span> words <span class="hljs-keyword">if</span> w.lower() <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> stopwords]
<span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> Counter
word_freq = Counter(filtered)
top_words = word_freq.most_common(count)
<span class="hljs-keyword">return</span> json.dumps({
<span class="hljs-string">&quot;keywords&quot;</span>: [{<span class="hljs-string">&quot;word&quot;</span>: w, <span class="hljs-string">&quot;frequency&quot;</span>: f} <span class="hljs-keyword">for</span> w, f <span class="hljs-keyword">in</span> top_words]
}, indent=<span class="hljs-number">2</span>)
<span class="hljs-keyword">def</span> <span class="hljs-title function_">check_reading_level</span>(<span class="hljs-params">text: <span class="hljs-built_in">str</span></span>) -&gt; <span class="hljs-built_in">str</span>:
<span class="hljs-string">&quot;&quot;&quot;Estimate reading difficulty level.
Args:
text: The input text
Returns:
JSON string with reading level estimate
&quot;&quot;&quot;</span>
sentences = <span class="hljs-built_in">max</span>(text.count(<span class="hljs-string">&quot;.&quot;</span>) + text.count(<span class="hljs-string">&quot;!&quot;</span>) + text.count(<span class="hljs-string">&quot;?&quot;</span>), <span class="hljs-number">1</span>)
words = <span class="hljs-built_in">len</span>(text.split())
vowels = <span class="hljs-string">&quot;aeiou&quot;</span>
syllables = <span class="hljs-built_in">sum</span>(<span class="hljs-number">1</span> <span class="hljs-keyword">for</span> c <span class="hljs-keyword">in</span> text.lower() <span class="hljs-keyword">if</span> c <span class="hljs-keyword">in</span> vowels)
<span class="hljs-keyword">if</span> words == <span class="hljs-number">0</span>:
<span class="hljs-keyword">return</span> json.dumps({<span class="hljs-string">&quot;error&quot;</span>: <span class="hljs-string">&quot;No text to analyze&quot;</span>})
grade = <span class="hljs-built_in">max</span>(<span class="hljs-number">0</span>, (<span class="hljs-number">0.39</span> * (words / sentences)) + (<span class="hljs-number">11.8</span> * (syllables / words)) - <span class="hljs-number">15.59</span>)
<span class="hljs-keyword">if</span> grade &lt; <span class="hljs-number">6</span>:
level = <span class="hljs-string">&quot;Elementary School&quot;</span>
<span class="hljs-keyword">elif</span> grade &lt; <span class="hljs-number">9</span>:
level = <span class="hljs-string">&quot;Middle School&quot;</span>
<span class="hljs-keyword">elif</span> grade &lt; <span class="hljs-number">13</span>:
level = <span class="hljs-string">&quot;High School&quot;</span>
<span class="hljs-keyword">else</span>:
level = <span class="hljs-string">&quot;College/Academic&quot;</span>
<span class="hljs-keyword">return</span> json.dumps({
<span class="hljs-string">&quot;grade_level&quot;</span>: <span class="hljs-built_in">round</span>(grade, <span class="hljs-number">1</span>),
<span class="hljs-string">&quot;reading_level&quot;</span>: level
}, indent=<span class="hljs-number">2</span>)
<span class="hljs-comment"># Create web UI</span>
<span class="hljs-keyword">with</span> gr.Blocks(title=<span class="hljs-string">&quot;Text Processor&quot;</span>) <span class="hljs-keyword">as</span> demo:
gr.Markdown(<span class="hljs-string">&quot;# Text Processing Tools&quot;</span>)
gr.Markdown(<span class="hljs-string">&quot;Analyze text statistics, extract keywords, and check reading difficulty.&quot;</span>)
<span class="hljs-keyword">with</span> gr.Tab(<span class="hljs-string">&quot;Analyze Text&quot;</span>):
text_input1 = gr.Textbox(
label=<span class="hljs-string">&quot;Enter text&quot;</span>,
lines=<span class="hljs-number">8</span>,
placeholder=<span class="hljs-string">&quot;Paste your text here...&quot;</span>
)
analysis_output = gr.Textbox(label=<span class="hljs-string">&quot;Analysis Results&quot;</span>, lines=<span class="hljs-number">8</span>)
gr.Button(<span class="hljs-string">&quot;Analyze&quot;</span>, size=<span class="hljs-string">&quot;lg&quot;</span>).click(analyze_text, text_input1, analysis_output)
<span class="hljs-keyword">with</span> gr.Tab(<span class="hljs-string">&quot;Extract Keywords&quot;</span>):
text_input2 = gr.Textbox(label=<span class="hljs-string">&quot;Enter text&quot;</span>, lines=<span class="hljs-number">8</span>)
count_input = gr.Slider(<span class="hljs-number">1</span>, <span class="hljs-number">20</span>, value=<span class="hljs-number">5</span>, step=<span class="hljs-number">1</span>, label=<span class="hljs-string">&quot;Number of keywords&quot;</span>)
keywords_output = gr.Textbox(label=<span class="hljs-string">&quot;Keywords&quot;</span>, lines=<span class="hljs-number">8</span>)
gr.Button(<span class="hljs-string">&quot;Extract&quot;</span>, size=<span class="hljs-string">&quot;lg&quot;</span>).click(
extract_keywords,
[text_input2, count_input],
keywords_output
)
<span class="hljs-keyword">with</span> gr.Tab(<span class="hljs-string">&quot;Reading Level&quot;</span>):
text_input3 = gr.Textbox(label=<span class="hljs-string">&quot;Enter text&quot;</span>, lines=<span class="hljs-number">8</span>)
level_output = gr.Textbox(label=<span class="hljs-string">&quot;Reading Level Analysis&quot;</span>, lines=<span class="hljs-number">5</span>)
gr.Button(<span class="hljs-string">&quot;Check Level&quot;</span>, size=<span class="hljs-string">&quot;lg&quot;</span>).click(check_reading_level, text_input3, level_output)
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">&quot;__main__&quot;</span>:
demo.launch(mcp_server=<span class="hljs-literal">True</span>)<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-13kcf0j">Test it:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->pip install gradio
python app.py<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-a85td7">Visit <code>http://localhost:7860</code> to use the web UI. The MCP endpoint is automatically available at <code>http://localhost:7860/gradio_api/mcp/</code>.</p> <h2 class="relative group"><a id="part-3-deploy-to-hugging-face-spaces" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#part-3-deploy-to-hugging-face-spaces"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Part 3: Deploy to Hugging Face Spaces</span></h2> <h3 class="relative group"><a id="step-1-create-a-new-space" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-1-create-a-new-space"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 1: Create a New Space</span></h3> <ol data-svelte-h="svelte-2bbgjx"><li>Go to <a href="https://huggingface.co/new-space" rel="nofollow">huggingface.co/new-space</a></li> <li>Name it (e.g., <code>text-processor-mcp</code>)</li> <li>Select “Gradio” SDK</li> <li>Choose “Public”</li> <li>Create</li></ol> <h3 class="relative group"><a id="step-2-upload-your-files" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-2-upload-your-files"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 2: Upload Your Files</span></h3> <p data-svelte-h="svelte-xn4p8q">Create these files in your Space:</p> <p data-svelte-h="svelte-14n6j2g"><strong>app.py</strong> — Use the Gradio version from Part 2</p> <p data-svelte-h="svelte-rije3p"><strong>requirements.txt:</strong></p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-attribute">gradio</span>&gt;=<span class="hljs-number">4</span>.<span class="hljs-number">0</span>.<span class="hljs-number">0</span><!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-kkp0x4">The Space will automatically build and deploy.</p> <h3 class="relative group"><a id="step-3-configure-your-agent" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-3-configure-your-agent"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 3: Configure Your Agent</span></h3> <p data-svelte-h="svelte-1gjcvlb">Once deployed, add your Space’s MCP endpoint to your agent:</p> <div class="flex space-x-2 items-center my-1.5 mr-8 h-7 !pl-0 -mx-3 md:mx-0"><div class="flex items-center border rounded-lg px-1.5 py-1 leading-none select-none text-smd border-gray-800 bg-black dark:bg-gray-700 text-white">Claude Code </div><div class="flex items-center border rounded-lg px-1.5 py-1 leading-none select-none text-smd text-gray-500 cursor-pointer opacity-90 hover:text-gray-700 dark:hover:text-gray-200 hover:shadow-sm">Codex </div><div class="flex items-center border rounded-lg px-1.5 py-1 leading-none select-none text-smd text-gray-500 cursor-pointer opacity-90 hover:text-gray-700 dark:hover:text-gray-200 hover:shadow-sm">OpenCode </div><div class="flex items-center border rounded-lg px-1.5 py-1 leading-none select-none text-smd text-gray-500 cursor-pointer opacity-90 hover:text-gray-700 dark:hover:text-gray-200 hover:shadow-sm">Pi </div></div> <div class="language-select"><div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->claude mcp add --transport http --scope user text-processor https://YOUR-USERNAME-text-processor-mcp.hf.space/gradio_api/mcp/<!-- HTML_TAG_END --></pre></div> </div> <h3 class="relative group"><a id="step-4-test-with-your-agent" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#step-4-test-with-your-agent"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Step 4: Test with Your Agent</span></h3> <p data-svelte-h="svelte-vmja6a">Restart your agent. Now you can ask it:</p> <ul data-svelte-h="svelte-r3yycw"><li>“Analyze the readability of this text: [text]”</li> <li>“What are the keywords in this article?”</li> <li>“What’s the reading level of this passage?”</li></ul> <p data-svelte-h="svelte-13smt05">Your agent will use the MCP server to process text in real-time.</p> <h2 class="relative group"><a id="debugging" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#debugging"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Debugging</span></h2> <p data-svelte-h="svelte-jsa30u">If the server doesn’t work:</p> <ol data-svelte-h="svelte-7iw15"><li><strong>Check Space logs</strong> — Click “Logs” in the Space UI</li> <li><strong>Test the web UI</strong> — Confirm the Gradio app works at <code>https://your-space.hf.space</code></li> <li><strong>Verify MCP endpoint</strong> — Test <code>https://your-space.hf.space/gradio_api/mcp/</code> in your browser</li> <li><strong>Check function signatures</strong> — Ensure all functions have type hints and docstrings</li> <li><strong>Test locally first</strong> — Debug on your machine before deploying</li></ol> <h2 class="relative group"><a id="challenge-extensions" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#challenge-extensions"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Challenge Extensions</span></h2> <p data-svelte-h="svelte-1o6w7mr">Try these improvements:</p> <ol data-svelte-h="svelte-15vd0fz"><li><strong>Add sentiment analysis</strong> — Detect positive/negative tone</li> <li><strong>Add language detection</strong> — Identify the language of text</li> <li><strong>Add text summarization</strong> — Create short summaries</li> <li><strong>Add spell checking</strong> — Identify misspelled words</li> <li><strong>Add readability tips</strong> — Suggest improvements for clarity</li></ol> <h2 class="relative group"><a id="key-takeaways" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#key-takeaways"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Key Takeaways</span></h2> <p data-svelte-h="svelte-27137g">You’ve built an MCP server with FastMCP, wrapped the same functions in a Gradio UI that doubles as an MCP server, deployed it to Hugging Face Spaces, and pointed an agent at it. The same pattern scales to API integrations, data processing, and custom analysis tools.</p> <a class="!text-gray-400 !no-underline text-sm flex items-center not-prose mt-4" href="https://github.com/huggingface/context-course/blob/main/units/en/unit2/hands-on.mdx" target="_blank"><svg class="mr-1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M31,16l-7,7l-1.41-1.41L28.17,16l-5.58-5.59L24,9l7,7z"></path><path d="M1,16l7-7l1.41,1.41L3.83,16l5.58,5.59L8,23l-7-7z"></path><path d="M12.419,25.484L17.639,6.552l1.932,0.518L14.351,26.002z"></path></svg> <span data-svelte-h="svelte-zjs2n5"><span class="underline">Update</span> on GitHub</span></a> <p></p>
<script>
{
__sveltekit_ck2jc = {
assets: "/docs/context-course/pr_7/en",
base: "/docs/context-course/pr_7/en",
env: {}
};
const element = document.currentScript.parentElement;
const data = [null,null];
Promise.all([
import("/docs/context-course/pr_7/en/_app/immutable/entry/start.55c3acaa.js"),
import("/docs/context-course/pr_7/en/_app/immutable/entry/app.10ec5479.js")
]).then(([kit, app]) => {
kit.start(app, element, {
node_ids: [0, 12],
data,
form: null,
error: null
});
});
}
</script>

Xet Storage Details

Size:
60.6 kB
·
Xet hash:
0d05fdb06f81e0ccfa19bda8fea006fed32cf0d639e9eb5603750ab5cf03242d

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.