Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions packages/datacommons-mcp/datacommons_mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from fastmcp import FastMCP
from pydantic import ValidationError
from starlette.requests import Request
from starlette.responses import PlainTextResponse
from starlette.responses import JSONResponse

import datacommons_mcp.settings as settings
from datacommons_mcp.clients import create_dc_client
Expand All @@ -44,6 +44,7 @@
from datacommons_mcp.services import (
search_indicators as search_indicators_service,
)
from datacommons_mcp.version import __version__

# The `datacommons_mcp.data_models.search` module is imported under `if TYPE_CHECKING:`
# because the `SearchResponse` model is only needed for type hinting. This pattern
Expand All @@ -57,6 +58,7 @@
# Configure logging
logger = logging.getLogger(__name__)


# Create client based on settings
try:
dc_settings = settings.get_dc_settings()
Expand All @@ -69,12 +71,12 @@
logger.error("Failed to create DC client: %s", e)
raise

mcp = FastMCP("DC MCP Server")
mcp = FastMCP("DC MCP Server", version=__version__)


@mcp.custom_route("/health", methods=["GET"])
async def health_check(request: Request) -> PlainTextResponse: # noqa: ARG001 request param required for decorator
return PlainTextResponse("OK")
async def health_check(request: Request) -> JSONResponse: # noqa: ARG001 request param required for decorator
return JSONResponse({"status": "OK", "version": __version__})


@mcp.tool()
Expand Down
4 changes: 2 additions & 2 deletions scripts/get_next_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def get_next_version(base_version: str, release_type: str = "rc") -> None:
releases = data.get("releases", {}).keys()
except urllib.error.HTTPError as e:
if e.code == 404:
print(f"{base_version}{release_type}1")
print(f"{base_version}.{release_type}1")
return
raise

Expand All @@ -72,7 +72,7 @@ def get_next_version(base_version: str, release_type: str = "rc") -> None:
max_ver = ver_num

next_ver = max_ver + 1
print(f"{base_version}{release_type}{next_ver}")
print(f"{base_version}.{release_type}{next_ver}")


if __name__ == "__main__":
Expand Down
56 changes: 36 additions & 20 deletions scripts/wait_for_pypi.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,53 @@
"""

import argparse
import ssl
import subprocess
import sys
import time
import urllib.request

import certifi


def check_pypi(package_name: str, version: str, repository_url: str) -> bool:
"""Checks for the existence of a package version on a PyPI repository."""
url = f"{repository_url}/{package_name}/"
context = ssl.create_default_context(cafile=certifi.where())

# Normalize version: PyPI often normalizes 1.1.3dev1 to 1.1.3.dev1
normalized_version = version.replace("dev", ".dev").replace("rc", ".rc")
"""Checks for the existence of a package version using pip."""
if "test.pypi.org" in repository_url:
# If checking TestPyPI, we need to handle dependencies that might be on main PyPI
# But for existence check, we can just say --no-deps
pass

print(
f"Checking for {package_name}=={version} (or {normalized_version}) at {url}..."
f"Verifying downloadability of {package_name}=={version} from {repository_url}..."
)

for i in range(60): # 60 * 5s = 300s = 5 minutes timeout
import tempfile

for i in range(60): # 5 minutes
try:
with urllib.request.urlopen(url, context=context) as response: # noqa: S310
content = response.read()
# Simple string check in the HTML/Simple API response
if (
version.encode() in content
or normalized_version.encode() in content
):
print(f"Success: Version {version} found!")
# Use pip download --no-deps to verify the file is actually resolvable
# We use --no-cache-dir to avoid false positives from local cache
with tempfile.TemporaryDirectory() as temp_dir:
cmd = [
sys.executable,
"-m",
"pip",
"download",
f"{package_name}=={version}",
"--no-deps",
"--no-cache-dir",
"--index-url",
repository_url,
"--dest",
temp_dir, # Download to tmp to verify file retrieval
]

result = subprocess.run( # noqa: S603
cmd, check=False, capture_output=True, text=True
)

if result.returncode == 0:
print(
f"Success: pip successfully located and downloaded {package_name}=={version}!"
)
return True

except Exception as e:
print(f"Error checking PyPI: {e}")

Expand Down