Spaces:
Running
Running
Upload 8 files
Browse files- Dockerfile +17 -20
- arithmetic_server.py +0 -14
- stock_server.py +1 -16
Dockerfile
CHANGED
@@ -1,31 +1,28 @@
|
|
|
|
1 |
FROM python:3.10-slim
|
2 |
|
3 |
-
# Set working directory in the container
|
4 |
WORKDIR /app
|
|
|
|
|
|
|
5 |
|
6 |
-
# Unbuffer STDIO for subprocess pipes (fixes hanging in MCP stdio)
|
7 |
-
ENV PYTHONUNBUFFERED=1
|
8 |
|
9 |
-
# Copy requirements and install dependencies
|
10 |
-
COPY requirements.txt .
|
11 |
-
RUN pip install --no-cache-dir -r requirements.txt
|
12 |
|
13 |
-
#
|
14 |
-
RUN
|
15 |
-
adduser --disabled-password --gecos '' --uid 1000 --gid 1000 user && \
|
16 |
-
chown -R user:user /app
|
17 |
|
18 |
-
#
|
19 |
-
COPY .
|
|
|
20 |
|
21 |
-
#
|
22 |
-
|
23 |
|
24 |
-
#
|
25 |
-
|
26 |
|
27 |
-
# Health check for Streamlit
|
28 |
-
HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health || exit 1
|
29 |
|
30 |
-
#
|
31 |
-
CMD ["
|
|
|
|
|
|
1 |
+
# Dockerfile
|
2 |
FROM python:3.10-slim
|
3 |
|
|
|
4 |
WORKDIR /app
|
5 |
+
# tells the system to treat /app as the "home" directory, so Streamlit will create /app/.streamlit instead of /.streamlit.
|
6 |
+
# /app is already writable as root, so no permission issues.
|
7 |
+
ENV HOME=/app
|
8 |
|
|
|
|
|
9 |
|
|
|
|
|
|
|
10 |
|
11 |
+
# (Optional) system deps if you need them; safe to remove if not needed
|
12 |
+
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
|
|
|
|
|
13 |
|
14 |
+
# Install Python deps
|
15 |
+
COPY requirements.txt /app/
|
16 |
+
RUN pip install --upgrade pip && pip install --no-cache-dir -r requirements.txt
|
17 |
|
18 |
+
# Copy code
|
19 |
+
COPY . /app
|
20 |
|
21 |
+
# Do NOT set STREAMLIT_SERVER_PORT here.
|
22 |
+
# Spaces will inject $PORT at runtime.
|
23 |
|
|
|
|
|
24 |
|
25 |
+
# Start Streamlit on the port Spaces provides, and bind to 0.0.0.0
|
26 |
+
# CMD ["bash", "-lc", "streamlit run /app/frontend.py --server.port $PORT --server.address 0.0.0.0"]
|
27 |
+
# CMD ["sh", "-c", "streamlit run /app/frontend.py --server.port $PORT --server.address 0.0.0.0"]
|
28 |
+
CMD ["streamlit", "run", "/app/frontend.py", "--server.port", "8501", "--server.address", "0.0.0.0"]
|
arithmetic_server.py
CHANGED
@@ -1,8 +1,4 @@
|
|
1 |
from mcp.server.fastmcp import FastMCP
|
2 |
-
from starlette.applications import Starlette
|
3 |
-
from starlette.routing import Mount
|
4 |
-
import contextlib
|
5 |
-
import uvicorn
|
6 |
|
7 |
# Creates a server named "Arithmetic"
|
8 |
mcp = FastMCP("Arithmetic")
|
@@ -29,16 +25,6 @@ def divide(a: int, b: int) -> float:
|
|
29 |
raise ValueError("Division by zero is not allowed.")
|
30 |
return a / b
|
31 |
|
32 |
-
@contextlib.asynccontextmanager
|
33 |
-
async def lifespan(app: Starlette):
|
34 |
-
async with contextlib.AsyncExitStack() as stack:
|
35 |
-
await stack.enter_async_context(mcp.session_manager.run())
|
36 |
-
yield
|
37 |
-
|
38 |
-
app = Starlette(
|
39 |
-
routes=[Mount("/", mcp.streamable_http_app())],
|
40 |
-
lifespan=lifespan,
|
41 |
-
)
|
42 |
|
43 |
if __name__ == "__main__":
|
44 |
mcp.run(transport="stdio")
|
|
|
1 |
from mcp.server.fastmcp import FastMCP
|
|
|
|
|
|
|
|
|
2 |
|
3 |
# Creates a server named "Arithmetic"
|
4 |
mcp = FastMCP("Arithmetic")
|
|
|
25 |
raise ValueError("Division by zero is not allowed.")
|
26 |
return a / b
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
if __name__ == "__main__":
|
30 |
mcp.run(transport="stdio")
|
stock_server.py
CHANGED
@@ -2,10 +2,6 @@ from mcp.server.fastmcp import FastMCP
|
|
2 |
import aiohttp
|
3 |
import json
|
4 |
from typing import Optional
|
5 |
-
from starlette.applications import Starlette
|
6 |
-
from starlette.routing import Mount
|
7 |
-
import contextlib
|
8 |
-
import uvicorn
|
9 |
|
10 |
mcp = FastMCP("StockMarket")
|
11 |
|
@@ -63,16 +59,5 @@ async def get_company_news(symbol: str, limit: int = 3) -> str:
|
|
63 |
2. Analysts upgrade {symbol} to 'Buy' rating
|
64 |
3. {symbol} unveils new product line for 2025"""
|
65 |
|
66 |
-
@contextlib.asynccontextmanager
|
67 |
-
async def lifespan(app: Starlette):
|
68 |
-
async with contextlib.AsyncExitStack() as stack:
|
69 |
-
await stack.enter_async_context(mcp.session_manager.run())
|
70 |
-
yield
|
71 |
-
|
72 |
-
app = Starlette(
|
73 |
-
routes=[Mount("/", mcp.streamable_http_app())],
|
74 |
-
lifespan=lifespan,
|
75 |
-
)
|
76 |
-
|
77 |
if __name__ == "__main__":
|
78 |
-
mcp.run(transport="stdio")
|
|
|
2 |
import aiohttp
|
3 |
import json
|
4 |
from typing import Optional
|
|
|
|
|
|
|
|
|
5 |
|
6 |
mcp = FastMCP("StockMarket")
|
7 |
|
|
|
59 |
2. Analysts upgrade {symbol} to 'Buy' rating
|
60 |
3. {symbol} unveils new product line for 2025"""
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
if __name__ == "__main__":
|
63 |
+
mcp.run(transport="stdio")
|