Added template mcp server and client, env values, requirements and compose objects

This commit is contained in:
Viswamedha Nalabotu 2026-01-18 16:47:13 +00:00
parent 08fb386b14
commit 69458b7fed
7 changed files with 205 additions and 1 deletions

View file

@ -35,3 +35,7 @@ POSTGRES_USER=postgres_user
POSTGRES_PASSWORD=postgres_password
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
# MCP Server
MCP_SERVER_HOST=localhost
MCP_SERVER_PORT=8001

View file

@ -82,6 +82,24 @@ services:
fyp-postgres-dev:
condition: service_healthy
fyp-mcp-dev:
container_name: fyp-mcp-dev
build:
context: ../../
dockerfile: compose/dev/mcp/Dockerfile
env_file:
- ../../.env
volumes:
- ../../:/app
ports:
- "0.0.0.0:8001:8001"
depends_on:
fyp-redis-dev:
condition: service_healthy
fyp-postgres-dev:
condition: service_healthy
volumes:
fyp_postgres_data:
fyp_redis_data:

View file

@ -0,0 +1,39 @@
FROM nvidia/cuda:11.8.0-runtime-ubuntu22.04
WORKDIR /app
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
python3 \
python3-pip \
build-essential \
git \
ca-certificates \
&& rm -rf /var/lib/apt/lists/* \
&& ln -sf /usr/bin/python3 /usr/bin/python \
&& ln -sf /usr/bin/pip3 /usr/bin/pip
RUN pip install --no-cache-dir --upgrade pip setuptools wheel && \
apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
python3-dev \
libffi-dev \
libssl-dev \
cmake \
pkg-config \
&& rm -rf /var/lib/apt/lists/*
RUN if [ ! -e /usr/lib/x86_64-linux-gnu/libcudart.so.11.0 ]; then \
found=$(ls /usr/local/cuda/lib64/libcudart.so* 2>/dev/null | head -n1 || true); \
if [ -n "$found" ]; then \
mkdir -p /usr/lib/x86_64-linux-gnu || true; \
ln -sf "$found" /usr/lib/x86_64-linux-gnu/libcudart.so.11.0 || true; \
fi; \
fi
COPY requirements/mcp.txt .
RUN pip install --no-cache-dir --requirement mcp.txt
ENV PYTHONUNBUFFERED=1
ENV DJANGO_SETTINGS_MODULE=config.settings
EXPOSE 8001
CMD ["python", "-m", "mcp_agent.mcp_server"]

0
mcp_agent/__init__.py Normal file
View file

42
mcp_agent/mcp_client.py Normal file
View file

@ -0,0 +1,42 @@
import httpx
import asyncio
class MCPClient:
def __init__(self, server_url: str):
self.server_url = server_url
self.client = httpx.AsyncClient(timeout=60)
async def send(self, tool: str, arguments: dict):
response = await self.client.post(
f"{self.server_url}/execute",
json={
"tool": tool,
"arguments": arguments,
},
)
response.raise_for_status()
return response.json()
async def health(self):
response = await self.client.get(f"{self.server_url}/health")
response.raise_for_status()
return response.json()
async def close(self):
await self.client.aclose()
async def main():
client = MCPClient("http://localhost:8001")
result = await client.send(
tool="echo",
arguments={"message": "hello from client"},
)
print(result)
await client.close()
if __name__ == "__main__":
asyncio.run(main())

95
mcp_agent/mcp_server.py Normal file
View file

@ -0,0 +1,95 @@
import asyncio
import json
import os
import sys
from aiohttp import web
from mcp.server import Server
from mcp.types import Tool, TextContent
app = Server("minimal-mcp-server")
@app.list_tools()
async def list_tools():
return [
Tool(
name="echo",
description="Echo back the provided input",
inputSchema={
"type": "object",
"properties": {
"message": {"type": "string"}
},
"required": ["message"]
},
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict):
if name != "echo":
raise ValueError(f"Unknown tool: {name}")
return [
TextContent(
type="text",
text=json.dumps(
{
"received": arguments,
"status": "ok",
},
indent=2,
),
)
]
async def handle_execute(request: web.Request) -> web.Response:
try:
payload = await request.json()
tool = payload.get("tool")
arguments = payload.get("arguments", {})
if not tool:
return web.json_response(
{"error": "Missing 'tool' field"}, status=400
)
result = await call_tool(tool, arguments)
return web.json_response(
{
"tool": tool,
"result": [c.text for c in result],
}
)
except json.JSONDecodeError:
return web.json_response({"error": "Invalid JSON"}, status=400)
except Exception as e:
return web.json_response({"error": str(e)}, status=500)
async def handle_health(request: web.Request) -> web.Response:
return web.json_response({"status": "healthy"})
async def run_http_server():
host = os.getenv("MCP_HTTP_HOST", "0.0.0.0")
port = int(os.getenv("MCP_HTTP_PORT", "8001"))
app_http = web.Application()
app_http.router.add_post("/execute", handle_execute)
app_http.router.add_get("/health", handle_health)
runner = web.AppRunner(app_http)
await runner.setup()
site = web.TCPSite(runner, host, port)
await site.start()
print(f"HTTP server running on {host}:{port}", file=sys.stderr)
await asyncio.Event().wait()
if __name__ == "__main__":
asyncio.run(run_http_server())

6
requirements/mcp.txt Normal file
View file

@ -0,0 +1,6 @@
aiohttp==3.8.4
mcp==1.25.0
pyjwt==2.10.1
python-multipart==0.0.21
sse-starlette==3.2.0
starlette==0.52.1