mcp-sentiment / docs /connect_to_hf_mcp.md
phil71x
feat: Update dependencies and add new packages for sentiment analysis
48a7f49
# Connecting to Your MCP Server on Hugging Face Spaces
This guide explains how to connect to your Gradio MCP server deployed on Hugging Face Spaces, based on real-world testing and troubleshooting.
**⚠️ Important:** This guide reflects actual testing results and working solutions, not just theoretical approaches.
---
## 1. Find Your MCP Endpoint
After deploying your Gradio app to Hugging Face Spaces, your MCP endpoint will be:
```
https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/gradio_api/mcp/sse
```
**Example:**
If your username is `freemansel` and your space is `mcp-sentiment`, your endpoint is:
```
https://freemansel-mcp-sentiment.hf.space/gradio_api/mcp/sse
```
**Testing the endpoint:** You can verify the SSE stream is working by visiting the URL in a browser - you should see periodic ping messages every 15 seconds.
---
## 2. βœ… Working Solutions (Tested & Verified)
### A. smolagents MCPClient ⭐ **RECOMMENDED**
**Performance:** ~0.11 seconds per request (fastest!)
**Status:** βœ… Works perfectly
**Protocol:** Native MCP via smolagents
Based on the [Hugging Face MCP Course](https://huggingface.co/learn/mcp-course/unit2/gradio-client), this is the proper way to use MCP.
#### Installation
```bash
pdm add "smolagents[mcp]"
# or
pip install "smolagents[mcp]"
```
#### Python Code
```python
#!/usr/bin/env python3
"""
Working MCP client using smolagents.
Performance: ~0.11 seconds per request
"""
import time
from smolagents.mcp_client import MCPClient
def analyze_sentiment_mcp(text):
"""Analyze sentiment using MCP protocol."""
mcp_client = None
try:
mcp_client = MCPClient(
{"url": "https://freemansel-mcp-sentiment.hf.space/gradio_api/mcp/sse"}
)
tools = mcp_client.get_tools()
sentiment_tool = tools[0] # The sentiment analysis tool
result = sentiment_tool(text=text)
return result
finally:
if mcp_client:
mcp_client.disconnect()
# Example usage
result = analyze_sentiment_mcp("I love this product!")
print(f"Polarity: {result['polarity']}")
print(f"Assessment: {result['assessment']}")
# Output: Polarity: 0.69, Assessment: positive
```
**Why this works:** smolagents handles all the MCP protocol complexity automatically, including the SSE connection and handshake.
---
### B. Gradio Client πŸ”„ **BACKUP SOLUTION**
**Performance:** ~1.3 seconds per request
**Status:** βœ… Very reliable backup
**Protocol:** Direct Gradio API access
This bypasses MCP entirely and connects directly to the Gradio API.
#### Installation
```bash
pdm add gradio_client
# or
pip install gradio_client
```
#### Python Code
```python
#!/usr/bin/env python3
"""
Backup solution using Gradio client.
Performance: ~1.3 seconds per request
"""
import time
from gradio_client import Client
def analyze_sentiment_gradio(text):
"""Analyze sentiment using Gradio client."""
client = Client("https://freemansel-mcp-sentiment.hf.space")
result = client.predict(text, api_name="/predict")
return result
# Example usage
result = analyze_sentiment_gradio("I love this product!")
print(f"Polarity: {result['polarity']}")
print(f"Assessment: {result['assessment']}")
# Output: Polarity: 0.69, Assessment: positive
```
**Why this works:** Direct API access to Gradio's built-in endpoints, no MCP protocol involved.
---
## 3. ❌ Known Issues & Failed Approaches
### A. Low-Level MCP Clients (Don't Use)
**❌ Problem:** The following approach causes `session.initialize()` to hang indefinitely:
```python
# ❌ THIS HANGS - DON'T USE
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def broken_mcp_approach():
server_params = StdioServerParameters(
command="npx",
args=["mcp-remote", "https://freemansel-mcp-sentiment.hf.space/gradio_api/mcp/sse"]
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# ❌ This line hangs forever (tested timeout: 45+ seconds)
await session.initialize()
```
**Root Cause:**
- The low-level MCP client requires manual protocol handling
- `session.initialize()` times out during MCP handshake
- Even though `mcp-remote` connects successfully, the protocol negotiation fails
**Evidence:**
- STDIO client connects instantly (0.0s)
- Session creation works fine
- Failure occurs specifically in `session.initialize()`
- Error: "unhandled errors in a TaskGroup (1 sub-exception)"
---
### B. Direct HTTP Requests (Don't Work)
**❌ Problem:** MCP endpoints don't accept standard HTTP POST requests:
```python
# ❌ THIS FAILS - DON'T USE
import requests
url = "https://freemansel-mcp-sentiment.hf.space/gradio_api/call/sentiment_analysis"
payload = {"data": ["I love this product!"]}
response = requests.post(url, json=payload)
# Result: 500 Internal Server Error or 405 Method Not Allowed
```
**Why it fails:**
- MCP servers use Server-Sent Events (SSE) protocol
- Standard REST API endpoints are not exposed when `mcp_server=True`
- The `/gradio_api/mcp/sse` endpoint only accepts SSE connections
---
### C. mcp-remote with Manual Clients (Problematic)
**⚠️ Partial Success:** `mcp-remote` proxy connects but has protocol issues:
```bash
# This establishes SSE connection but MCP protocol still fails
npx mcp-remote https://freemansel-mcp-sentiment.hf.space/gradio_api/mcp/sse
```
**What happens:**
1. βœ… HTTP attempt fails (405 Method Not Allowed) - expected
2. βœ… SSE fallback succeeds - connection established
3. ❌ MCP protocol handshake fails - timeout in client
**Evidence from testing:**
```
[8216] Using transport strategy: http-first
[8216] Received error: Error POSTing to endpoint (HTTP 405): Method Not Allowed
[8216] Recursively reconnecting for reason: falling-back-to-alternate-transport
[8216] Using transport strategy: sse-only
[8216] Connected to remote server using SSEClientTransport
[8216] Local STDIO server running
[8216] Proxy established successfully
```
---
## 4. Performance Comparison
| Method | Speed | Reliability | Protocol | Status |
|--------|-------|-------------|----------|---------|
| **smolagents MCP** | **0.11s** | βœ… Excellent | Native MCP | ⭐ Best |
| **Gradio Client** | 1.3s | βœ… Very Good | Direct API | βœ… Backup |
| Low-level MCP | ❌ Timeout | ❌ Broken | Manual MCP | ❌ Don't use |
| HTTP Requests | ❌ 405 Error | ❌ Broken | REST | ❌ Don't use |
---
## 5. Real-World Troubleshooting
### A. Import Debugging
If you have import issues, create this debugging script:
```python
#!/usr/bin/env python3
"""Debug MCP imports"""
def check_imports():
try:
import smolagents.mcp_client
print("βœ… smolagents available - use smolagents approach")
return True
except ImportError:
print("❌ Install: pip install 'smolagents[mcp]'")
try:
import gradio_client
print("βœ… gradio_client available - use backup approach")
return True
except ImportError:
print("❌ Install: pip install gradio_client")
return False
check_imports()
```
### B. Connection Testing
Test the SSE endpoint directly in your browser:
```
https://freemansel-mcp-sentiment.hf.space/gradio_api/mcp/sse
```
You should see:
```
: ping - 2025-05-23 18:36:12.808434+00:00
: ping - 2025-05-23 18:36:27.809481+00:00
```
If you don't see pings, the Hugging Face Space might be sleeping.
### C. Common Error Messages
**"unhandled errors in a TaskGroup"** β†’ Use smolagents instead of low-level MCP
**"HTTP 405 Method Not Allowed"** β†’ Use Gradio client instead of HTTP requests
**"Connection timeout"** β†’ Check if HF Space is running, try Gradio client
**"Import error: smolagents"** β†’ Install with `pip install "smolagents[mcp]"`
---
## 6. Ready-to-Use Scripts
Complete, tested scripts are available in the `usage/` folder:
```bash
# Primary solution (fastest)
pdm run python usage/sentiment_mcp.py
# Backup solution (reliable)
pdm run python usage/sentiment_gradio.py
# Debug imports if needed
pdm run python usage/debug_imports.py
```
---
## 7. Cursor AI Integration
For Cursor AI, use the working smolagents approach:
```json
{
"mcpServers": {
"sentiment-analysis": {
"command": "python",
"args": [
"-c",
"from smolagents.mcp_client import MCPClient; client = MCPClient({'url': 'https://freemansel-mcp-sentiment.hf.space/gradio_api/mcp/sse'}); tools = client.get_tools(); result = tools[0](text=input('Text: ')); print(f'Sentiment: {result}')"
]
}
}
}
```
**Note:** This is a simplified example. For production use, create a proper MCP server script.
---
## 8. Key Learnings from Real Testing
1. **Always use high-level clients** - `smolagents.MCPClient` works, low-level `mcp.ClientSession` doesn't
2. **Follow official documentation** - The [Hugging Face MCP Course](https://huggingface.co/learn/mcp-course/unit2/gradio-client) shows the right approach
3. **Have a backup plan** - Gradio client provides reliable fallback when MCP has issues
4. **Test everything** - Theoretical solutions often don't work in practice
5. **Performance varies dramatically** - smolagents (0.11s) vs Gradio (1.3s) vs broken approaches (timeout)
---
## 9. References
- [Hugging Face MCP Course](https://huggingface.co/learn/mcp-course/unit2/gradio-client) - **Use this approach**
- [smolagents Documentation](https://huggingface.co/docs/smolagents) - High-level MCP client
- [Gradio Client Documentation](https://gradio.app/guides/getting-started-with-the-python-client/) - Backup approach
- [MCP Protocol Documentation](https://modelcontextprotocol.io/) - Low-level details
---
**βœ… This guide is based on extensive real-world testing and provides only verified, working solutions!**