Alex Liberzon Qwen-Coder commited on
Commit
bbf1ba3
·
1 Parent(s): 330e646

feat: Add Hugging Face Spaces deployment

Browse files

- app.py: Entry point for Hugging Face Spaces
- src/http_server.py: HTTP server wrapper with uvicorn
- Dockerfile: Container config for HF Spaces deployment
- requirements.txt: Python dependencies for deployment
- README_HF.md: Hugging Face Spaces metadata
- .dockerignore: Exclude unnecessary files from Docker build
- Updated README.md with deployment instructions

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Files changed (7) hide show
  1. .dockerignore +16 -0
  2. Dockerfile +27 -0
  3. README.md +46 -0
  4. README_HF.md +14 -0
  5. app.py +36 -0
  6. requirements.txt +7 -0
  7. src/http_server.py +29 -0
.dockerignore ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .git
2
+ .gitignore
3
+ .venv
4
+ __pycache__
5
+ *.pyc
6
+ *.pyo
7
+ *.pyd
8
+ .Python
9
+ demo/
10
+ tests/
11
+ *.md
12
+ !README_HF.md
13
+ piv_quiver.png
14
+ *.egg-info
15
+ dist/
16
+ build/
Dockerfile ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.14-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Install system dependencies
6
+ RUN apt-get update && apt-get install -y --no-install-recommends \
7
+ libgl1-mesa-glx \
8
+ libglib2.0-0 \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ # Copy requirements first for better caching
12
+ COPY requirements.txt .
13
+ RUN pip install --no-cache-dir -r requirements.txt
14
+
15
+ # Copy application code
16
+ COPY src/ ./src/
17
+ COPY app.py .
18
+
19
+ # Expose the port Hugging Face expects
20
+ EXPOSE 7860
21
+
22
+ # Set environment variables
23
+ ENV HOST=0.0.0.0
24
+ ENV PORT=7860
25
+
26
+ # Run the application
27
+ CMD ["python", "app.py"]
README.md CHANGED
@@ -139,6 +139,52 @@ Summary Statistics:
139
  | pandas | >=3.0.1 |
140
  | matplotlib | (auto-installed) |
141
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  ## License
143
 
144
  MIT License - see LICENSE file for details.
 
139
  | pandas | >=3.0.1 |
140
  | matplotlib | (auto-installed) |
141
 
142
+ ## Deployment
143
+
144
+ ### Hugging Face Spaces (Free)
145
+
146
+ Deploy to Hugging Face Spaces for free HTTP access:
147
+
148
+ 1. **Create a new Space** at https://huggingface.co/spaces
149
+ - Click "Create new Space"
150
+ - Name: `openpiv-mcp`
151
+ - License: MIT
152
+ - Select **Docker** SDK
153
+
154
+ 2. **Connect your GitHub repo**
155
+ - In your Space settings, enable "Link to GitHub repository"
156
+ - Select `openpiv/openpiv-mcp`
157
+
158
+ 3. **Configure the Space**
159
+ - Copy `README_HF.md` content to your Space's README.md (HF metadata)
160
+ - The Dockerfile will build automatically
161
+
162
+ 4. **Connect MCP client**
163
+ - Once deployed, your endpoint will be: `https://<username>-openpiv-mcp.hf.space`
164
+ - Configure your MCP client:
165
+
166
+ ```json
167
+ {
168
+ "mcpServers": {
169
+ "openpiv": {
170
+ "url": "https://<username>-openpiv-mcp.hf.space/mcp"
171
+ }
172
+ }
173
+ }
174
+ ```
175
+
176
+ **Note:** Free Spaces sleep after 15 minutes of inactivity. First request after sleep has ~30s cold start.
177
+
178
+ ### Local HTTP Server
179
+
180
+ Run the server with HTTP transport locally:
181
+
182
+ ```bash
183
+ uv run python src/http_server.py
184
+ ```
185
+
186
+ Connect to `http://localhost:8000/mcp`
187
+
188
  ## License
189
 
190
  MIT License - see LICENSE file for details.
README_HF.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ title: OpenPIV MCP Server
2
+ emoji: 🌊
3
+ colorFrom: blue
4
+ colorTo: purple
5
+ sdk: docker
6
+ pinned: false
7
+ license: mit
8
+
9
+ # Hardware configuration
10
+ hardware: cpu-basic
11
+
12
+ # Scale to zero when idle (saves resources)
13
+ # Note: First request after idle period will have cold start delay
14
+ scale_to_zero_timeout: 15
app.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Hugging Face Spaces entry point for OpenPIV MCP Server.
3
+
4
+ This app runs the MCP server with HTTP transport on Hugging Face Spaces.
5
+ The server exposes PIV analysis tools via HTTP.
6
+
7
+ API Endpoint:
8
+ /mcp - MCP HTTP endpoint (streamable HTTP)
9
+
10
+ Usage with MCP client:
11
+ Configure your MCP client to connect to:
12
+ https://<your-space>.hf.space/mcp
13
+ """
14
+
15
+ import os
16
+ import logging
17
+ import uvicorn
18
+ from openpiv_mcp import mcp
19
+
20
+ # Configure logging
21
+ logging.basicConfig(level=logging.INFO)
22
+ logger = logging.getLogger(__name__)
23
+
24
+ # Get configuration from environment
25
+ HOST = os.environ.get("HOST", "0.0.0.0")
26
+ PORT = int(os.environ.get("PORT", 7860))
27
+
28
+ # Create the ASGI app for HTTP transport
29
+ app = mcp.streamable_http_app()
30
+
31
+ if __name__ == "__main__":
32
+ logger.info(f"Starting OpenPIV MCP Server on {HOST}:{PORT}")
33
+ logger.info("MCP endpoint: /mcp")
34
+
35
+ # Run with uvicorn
36
+ uvicorn.run(app, host=HOST, port=PORT)
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ mcp>=1.26.0
2
+ openpiv>=0.25.1
3
+ numpy>=2.4.3
4
+ pandas>=3.0.1
5
+ matplotlib>=3.9.0
6
+ setuptools>=82.0.1
7
+ uvicorn>=0.30.0
src/http_server.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ HTTP Server wrapper for OpenPIV MCP Server.
3
+
4
+ This module provides an HTTP endpoint for the OpenPIV MCP server,
5
+ enabling remote clients to connect via HTTP instead of stdio.
6
+
7
+ Usage:
8
+ uv run python src/http_server.py
9
+
10
+ Or on Hugging Face Spaces, it runs automatically via app.py
11
+ """
12
+
13
+ import os
14
+ import uvicorn
15
+ from openpiv_mcp import mcp
16
+
17
+ # Get host/port from environment (for Hugging Face Spaces)
18
+ HOST = os.environ.get("HOST", "0.0.0.0")
19
+ PORT = int(os.environ.get("PORT", 8000))
20
+
21
+ # Create the ASGI app for HTTP transport
22
+ app = mcp.streamable_http_app()
23
+
24
+ if __name__ == "__main__":
25
+ print(f"Starting OpenPIV MCP Server on {HOST}:{PORT}")
26
+ print("Endpoint: http://{HOST}:{PORT}/mcp")
27
+
28
+ # Run with uvicorn
29
+ uvicorn.run(app, host=HOST, port=PORT)