Skip to main content
Glama

MCP Simple Timeserver

MIT License
22
  • Apple
#!/usr/bin/env python3 """ Prepare DXT package directory structure for mcp-simple-timeserver. This script creates a directory ready to be packaged by the DXT CLI tool. """ import json import os import platform import shutil import subprocess import sys from pathlib import Path import tomllib def to_display_name(name: str) -> str: """Converts a slug-like name to a display name. Example: "mcp-simple-timeserver" -> "MCP Simple Timeserver" """ parts = name.split('-') transformed_parts = [] for part in parts: if part.lower() == 'mcp': transformed_parts.append('MCP') else: transformed_parts.append(part.capitalize()) return ' '.join(transformed_parts) def prepare_dxt_package(): """Prepare the DXT package directory structure.""" # Determine paths script_dir = Path(__file__).parent root_dir = script_dir.parent build_dir = root_dir / "dxt_build" server_dir = build_dir / "server" venv_dir = server_dir / "venv" # Read metadata from pyproject.toml print("Reading metadata from pyproject.toml...") pyproject_path = root_dir / "pyproject.toml" try: with open(pyproject_path, "rb") as f: pyproject_data = tomllib.load(f) project_meta = pyproject_data["project"] project_name = project_meta["name"] project_version = project_meta["version"] project_description = project_meta["description"] author_info = project_meta["authors"][0] dependencies = project_meta.get("dependencies", []) homepage_url = project_meta.get("urls", {}).get("Homepage", "") python_version_req = project_meta.get("requires-python", ">=3.11") license_str = "MIT" # Default for classifier in project_meta.get("classifiers", []): if "License :: OSI Approved" in classifier: license_str = classifier.split("::")[-1].strip().replace(" License", "") except (FileNotFoundError, KeyError, IndexError) as e: print(f"Error: Could not read {pyproject_path} or it is malformed. {e}") sys.exit(1) # Generate display name display_name = to_display_name(project_name) # Clean previous build if build_dir.exists(): print(f"Cleaning previous build directory: {build_dir}") shutil.rmtree(build_dir) # Create directory structure print("Creating DXT directory structure...") server_dir.mkdir(parents=True, exist_ok=True) # Copy server files print("Copying server files...") shutil.copytree( root_dir / "mcp_simple_timeserver", server_dir / "mcp_simple_timeserver", ignore=shutil.ignore_patterns("__pycache__", "*.pyc", "*.pyo") ) # Copy launcher scripts print("Copying launcher scripts...") shutil.copy2(script_dir / "launcher.bat", build_dir / "launcher.bat") shutil.copy2(script_dir / "launcher.sh", build_dir / "launcher.sh") # Copy icon if it exists icon_path = script_dir / "icon.png" if icon_path.exists(): shutil.copy2(icon_path, build_dir / "icon.png") # Make launcher.sh executable launcher_sh = build_dir / "launcher.sh" launcher_sh.chmod(launcher_sh.stat().st_mode | 0o755) # Create virtual environment print(f"Creating virtual environment in {venv_dir}...") subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True) # Install dependencies print("Installing dependencies...") if platform.system() == "Windows": pip_path = venv_dir / "Scripts" / "pip.exe" else: pip_path = venv_dir / "bin" / "pip" subprocess.run([ str(pip_path), "install", "--no-cache-dir", *dependencies ], check=True) # Remove home line from pyvenv.cfg to make it relocatable pyvenv_cfg = venv_dir / "pyvenv.cfg" if pyvenv_cfg.exists(): print("Making virtual environment relocatable...") lines = pyvenv_cfg.read_text().splitlines() # Keep all lines except the home line - let launcher set it filtered_lines = [line for line in lines if not line.startswith("home = ")] # Add a placeholder that the launcher will replace filtered_lines.insert(0, "home = WILL_BE_SET_BY_LAUNCHER") pyvenv_cfg.write_text("\n".join(filtered_lines) + "\n") # Determine platform-specific command system = platform.system() if system == "Windows": entry_point = "launcher.bat" mcp_command = "cmd.exe" mcp_args = ["/c", "${__dirname}\\launcher.bat"] else: entry_point = "launcher.sh" mcp_command = "/bin/bash" mcp_args = ["${__dirname}/launcher.sh"] # Create manifest with all required DXT fields manifest = { "dxt_version": "0.1", "name": project_name, "display_name": display_name, "version": project_version, "description": project_description, "author": { "name": author_info.get("name"), "email": author_info.get("email"), "url": "https://mcp.andybrandt.net/" # DXT-specific author URL }, "license": license_str, "homepage": homepage_url, "repository": { "type": "git", "url": homepage_url }, "keywords": ["time", "ntp", "mcp", "server", "utility"], "server": { "type": "binary", "entry_point": entry_point, "mcp_config": { "command": mcp_command, "args": mcp_args, "env": { "PYTHONPATH": "${__dirname}/server" } } }, "tools": [ { "name": "get_server_time", "description": "Returns the current local time and timezone from the server hosting this tool." }, { "name": "get_utc", "description": "Returns accurate UTC time from an NTP server." } ], "compatibility": { "claude_desktop": ">=0.10.0", "platforms": ["darwin", "win32"], "runtimes": { "python": python_version_req } } } # Add icon if it exists if (build_dir / "icon.png").exists(): manifest["icon"] = "icon.png" manifest_path = build_dir / "manifest.json" print(f"Creating manifest.json for {system}...") with open(manifest_path, "w") as f: json.dump(manifest, f, indent=2) print(f"\nDXT package prepared in: {build_dir}") print(f"Platform: {system}") print(f"Command: {mcp_command} {' '.join(mcp_args)}") print("\nTo create the DXT package, run:") print(f" npx @anthropic-ai/dxt pack ./dxt_build mcp-simple-timeserver-{system.lower()}.dxt") # Write version to a file for the CI workflow to use (build_dir / "version.txt").write_text(project_version) return build_dir if __name__ == "__main__": prepare_dxt_package()

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/andybrandt/mcp-simple-timeserver'

If you have feedback or need assistance with the MCP directory API, please join our Discord server