Spaces:
Sleeping
Sleeping
Upload 6 files
Browse files- Dockerfile +18 -0
- README.md +27 -5
- app.py +45 -0
- requirements.txt +14 -0
- run_docker.ps1 +35 -0
- run_docker.sh +82 -0
Dockerfile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.10
|
| 2 |
+
|
| 3 |
+
RUN useradd -m -u 1000 user && python -m pip install --upgrade pip
|
| 4 |
+
USER user
|
| 5 |
+
ENV PATH="/home/user/.local/bin:$PATH"
|
| 6 |
+
|
| 7 |
+
WORKDIR /app
|
| 8 |
+
|
| 9 |
+
COPY --chown=user ./requirements.txt requirements.txt
|
| 10 |
+
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
| 11 |
+
|
| 12 |
+
COPY --chown=user . /app
|
| 13 |
+
ENV MCP_TRANSPORT=http
|
| 14 |
+
ENV MCP_PORT=7860
|
| 15 |
+
|
| 16 |
+
EXPOSE 7860
|
| 17 |
+
|
| 18 |
+
CMD ["python", "openmc/mcp_output/start_mcp.py"]
|
README.md
CHANGED
|
@@ -1,10 +1,32 @@
|
|
| 1 |
---
|
| 2 |
-
title: Openmc
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: docker
|
|
|
|
|
|
|
| 7 |
pinned: false
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Openmc MCP
|
| 3 |
+
emoji: 🤖
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: purple
|
| 6 |
sdk: docker
|
| 7 |
+
sdk_version: "4.26.0"
|
| 8 |
+
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Openmc MCP Service
|
| 13 |
+
|
| 14 |
+
Auto-generated MCP service for openmc.
|
| 15 |
+
|
| 16 |
+
## Usage
|
| 17 |
+
|
| 18 |
+
```
|
| 19 |
+
https://None-openmc-mcp.hf.space/mcp
|
| 20 |
+
```
|
| 21 |
+
|
| 22 |
+
## Connect with Cursor
|
| 23 |
+
|
| 24 |
+
```json
|
| 25 |
+
{
|
| 26 |
+
"mcpServers": {
|
| 27 |
+
"openmc": {
|
| 28 |
+
"url": "https://None-openmc-mcp.hf.space/mcp"
|
| 29 |
+
}
|
| 30 |
+
}
|
| 31 |
+
}
|
| 32 |
+
```
|
app.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI
|
| 2 |
+
import os
|
| 3 |
+
import sys
|
| 4 |
+
|
| 5 |
+
mcp_plugin_path = os.path.join(os.path.dirname(__file__), "openmc", "mcp_output", "mcp_plugin")
|
| 6 |
+
sys.path.insert(0, mcp_plugin_path)
|
| 7 |
+
|
| 8 |
+
app = FastAPI(
|
| 9 |
+
title="Openmc MCP Service",
|
| 10 |
+
description="Auto-generated MCP service for openmc",
|
| 11 |
+
version="1.0.0"
|
| 12 |
+
)
|
| 13 |
+
|
| 14 |
+
@app.get("/")
|
| 15 |
+
def root():
|
| 16 |
+
return {
|
| 17 |
+
"service": "Openmc MCP Service",
|
| 18 |
+
"version": "1.0.0",
|
| 19 |
+
"status": "running",
|
| 20 |
+
"transport": os.environ.get("MCP_TRANSPORT", "http")
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
@app.get("/health")
|
| 24 |
+
def health_check():
|
| 25 |
+
return {"status": "healthy", "service": "openmc MCP"}
|
| 26 |
+
|
| 27 |
+
@app.get("/tools")
|
| 28 |
+
def list_tools():
|
| 29 |
+
try:
|
| 30 |
+
from mcp_service import create_app
|
| 31 |
+
mcp_app = create_app()
|
| 32 |
+
tools = []
|
| 33 |
+
for tool_name, tool_func in mcp_app.tools.items():
|
| 34 |
+
tools.append({
|
| 35 |
+
"name": tool_name,
|
| 36 |
+
"description": tool_func.__doc__ or "No description available"
|
| 37 |
+
})
|
| 38 |
+
return {"tools": tools}
|
| 39 |
+
except Exception as e:
|
| 40 |
+
return {"error": f"Failed to load tools: {str(e)}"}
|
| 41 |
+
|
| 42 |
+
if __name__ == "__main__":
|
| 43 |
+
import uvicorn
|
| 44 |
+
port = int(os.environ.get("PORT", 7860))
|
| 45 |
+
uvicorn.run(app, host="0.0.0.0", port=port)
|
requirements.txt
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastmcp
|
| 2 |
+
fastapi
|
| 3 |
+
uvicorn[standard]
|
| 4 |
+
pydantic>=2.0.0
|
| 5 |
+
numpy
|
| 6 |
+
h5py
|
| 7 |
+
scipy
|
| 8 |
+
ipython
|
| 9 |
+
matplotlib
|
| 10 |
+
pandas
|
| 11 |
+
lxml
|
| 12 |
+
uncertainties
|
| 13 |
+
setuptools
|
| 14 |
+
endf
|
run_docker.ps1
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cd $PSScriptRoot
|
| 2 |
+
|
| 3 |
+
$ErrorActionPreference = "Stop"
|
| 4 |
+
|
| 5 |
+
$entryName = if ($env:MCP_ENTRY_NAME) { $env:MCP_ENTRY_NAME } else { "openmc" }
|
| 6 |
+
$entryUrl = if ($env:MCP_ENTRY_URL) { $env:MCP_ENTRY_URL } else { "http://localhost:7860/mcp" }
|
| 7 |
+
$imageName = if ($env:MCP_IMAGE_NAME) { $env:MCP_IMAGE_NAME } else { "openmc-mcp" }
|
| 8 |
+
|
| 9 |
+
$mcpDir = Join-Path $env:USERPROFILE ".cursor"
|
| 10 |
+
$mcpPath = Join-Path $mcpDir "mcp.json"
|
| 11 |
+
if (!(Test-Path $mcpDir)) { New-Item -ItemType Directory -Path $mcpDir | Out-Null }
|
| 12 |
+
|
| 13 |
+
$config = @{}
|
| 14 |
+
if (Test-Path $mcpPath) {
|
| 15 |
+
try { $config = Get-Content $mcpPath -Raw | ConvertFrom-Json } catch { $config = @{} }
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
# Rebuild mcpServers as ordered and append the entry last
|
| 19 |
+
$serversOrdered = [ordered]@{}
|
| 20 |
+
if ($config -and ($config.PSObject.Properties.Name -contains "mcpServers") -and $config.mcpServers) {
|
| 21 |
+
$existing = $config.mcpServers
|
| 22 |
+
if ($existing -is [pscustomobject]) {
|
| 23 |
+
foreach ($p in $existing.PSObject.Properties) { if ($p.Name -ne $entryName) { $serversOrdered[$p.Name] = $p.Value } }
|
| 24 |
+
} elseif ($existing -is [System.Collections.IDictionary]) {
|
| 25 |
+
foreach ($k in $existing.Keys) { if ($k -ne $entryName) { $serversOrdered[$k] = $existing[$k] } }
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
$serversOrdered[$entryName] = @{ url = $entryUrl }
|
| 29 |
+
$config = @{ mcpServers = $serversOrdered }
|
| 30 |
+
|
| 31 |
+
$config | ConvertTo-Json -Depth 10 | Set-Content -Path $mcpPath -Encoding UTF8
|
| 32 |
+
Write-Host ("Updated $entryName in " + $mcpPath + " -> " + $entryUrl)
|
| 33 |
+
|
| 34 |
+
docker build -t $imageName .
|
| 35 |
+
docker run --rm -p 7860:7860 $imageName
|
run_docker.sh
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
set -euo pipefail
|
| 3 |
+
|
| 4 |
+
# Switch to the directory where this script is located
|
| 5 |
+
cd "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
| 6 |
+
|
| 7 |
+
mcp_entry_name="${MCP_ENTRY_NAME:-openmc}"
|
| 8 |
+
mcp_entry_url="${MCP_ENTRY_URL:-http://localhost:7860/mcp}"
|
| 9 |
+
mcp_dir="${HOME}/.cursor"
|
| 10 |
+
mcp_path="${mcp_dir}/mcp.json"
|
| 11 |
+
mkdir -p "${mcp_dir}"
|
| 12 |
+
|
| 13 |
+
if command -v python3 >/dev/null 2>&1; then
|
| 14 |
+
python3 - "${mcp_path}" "${mcp_entry_name}" "${mcp_entry_url}" <<'PY'
|
| 15 |
+
import json, os, sys
|
| 16 |
+
path, name, url = sys.argv[1:4]
|
| 17 |
+
cfg = {"mcpServers": {}}
|
| 18 |
+
if os.path.exists(path):
|
| 19 |
+
try:
|
| 20 |
+
with open(path, "r", encoding="utf-8") as f:
|
| 21 |
+
cfg = json.load(f)
|
| 22 |
+
except Exception:
|
| 23 |
+
cfg = {"mcpServers": {}}
|
| 24 |
+
if not isinstance(cfg, dict):
|
| 25 |
+
cfg = {"mcpServers": {}}
|
| 26 |
+
servers = cfg.get("mcpServers")
|
| 27 |
+
if not isinstance(servers, dict):
|
| 28 |
+
servers = {}
|
| 29 |
+
ordered = {}
|
| 30 |
+
for k, v in servers.items():
|
| 31 |
+
if k != name:
|
| 32 |
+
ordered[k] = v
|
| 33 |
+
ordered[name] = {"url": url}
|
| 34 |
+
cfg = {"mcpServers": ordered}
|
| 35 |
+
with open(path, "w", encoding="utf-8") as f:
|
| 36 |
+
json.dump(cfg, f, indent=2, ensure_ascii=False)
|
| 37 |
+
PY
|
| 38 |
+
elif command -v python >/dev/null 2>&1; then
|
| 39 |
+
python - "${mcp_path}" "${mcp_entry_name}" "${mcp_entry_url}" <<'PY'
|
| 40 |
+
import json, os, sys
|
| 41 |
+
path, name, url = sys.argv[1:4]
|
| 42 |
+
cfg = {"mcpServers": {}}
|
| 43 |
+
if os.path.exists(path):
|
| 44 |
+
try:
|
| 45 |
+
with open(path, "r", encoding="utf-8") as f:
|
| 46 |
+
cfg = json.load(f)
|
| 47 |
+
except Exception:
|
| 48 |
+
cfg = {"mcpServers": {}}
|
| 49 |
+
if not isinstance(cfg, dict):
|
| 50 |
+
cfg = {"mcpServers": {}}
|
| 51 |
+
servers = cfg.get("mcpServers")
|
| 52 |
+
if not isinstance(servers, dict):
|
| 53 |
+
servers = {}
|
| 54 |
+
ordered = {}
|
| 55 |
+
for k, v in servers.items():
|
| 56 |
+
if k != name:
|
| 57 |
+
ordered[k] = v
|
| 58 |
+
ordered[name] = {"url": url}
|
| 59 |
+
cfg = {"mcpServers": ordered}
|
| 60 |
+
with open(path, "w", encoding="utf-8") as f:
|
| 61 |
+
json.dump(cfg, f, indent=2, ensure_ascii=False)
|
| 62 |
+
PY
|
| 63 |
+
elif command -v jq >/dev/null 2>&1; then
|
| 64 |
+
name="${mcp_entry_name}"; url="${mcp_entry_url}"
|
| 65 |
+
if [ -f "${mcp_path}" ]; then
|
| 66 |
+
tmp="$(mktemp)"
|
| 67 |
+
jq --arg name "$name" --arg url "$url" '
|
| 68 |
+
.mcpServers = (.mcpServers // {})
|
| 69 |
+
| .mcpServers as $s
|
| 70 |
+
| ($s | with_entries(select(.key != $name))) as $base
|
| 71 |
+
| .mcpServers = ($base + {($name): {"url": $url}})
|
| 72 |
+
' "${mcp_path}" > "${tmp}" && mv "${tmp}" "${mcp_path}"
|
| 73 |
+
else
|
| 74 |
+
printf '{ "mcpServers": { "%s": { "url": "%s" } } }
|
| 75 |
+
' "$name" "$url" > "${mcp_path}"
|
| 76 |
+
fi
|
| 77 |
+
else
|
| 78 |
+
echo "Warning: neither python nor jq found; skipped updating ~/.cursor/mcp.json" >&2
|
| 79 |
+
fi
|
| 80 |
+
|
| 81 |
+
docker build -t openmc-mcp .
|
| 82 |
+
docker run --rm -p 7860:7860 openmc-mcp
|