Skip to main content
Glama

Smithsonian Open Access MCP Server

by molanojustin
setup.sh13.2 kB
#!/bin/bash # This script sets up the development environment for the Smithsonian MCP server. # Exit immediately if a command exits with a non-zero status. set -e # --- Constants --- VENV_DIR=".venv" PYTHON_EXEC="$VENV_DIR/bin/python" PIP_EXEC="$VENV_DIR/bin/pip" REQUIREMENTS_FILE="requirements.txt" SERVICE_NAME="smithsonian-mcp" PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # --- Functions --- # Function to print messages info() { echo "INFO: $1" } error() { echo "ERROR: $1" >&2 } warning() { echo "WARNING: $1" } # Function to check if a command exists command_exists() { command -v "$1" >/dev/null 2>&1 } # Function to check if mcpo is available check_mcpo() { if command_exists mcpo; then return 0 elif command_exists uvx; then # Check if mcpo can be run via uvx if uvx mcpo --help >/dev/null 2>&1; then return 0 fi fi return 1 } # Function to setup mcpo configuration setup_mcpo_config() { local api_key="$1" info "Setting up mcpo configuration..." if [ ! -f "mcpo-config.example.json" ]; then warning "mcpo-config.example.json not found. Skipping mcpo setup." return 1 fi # Create mcpo config from example local config_file="mcpo-config.json" cp "mcpo-config.example.json" "$config_file" # Replace paths and API key in config local python_path="$PROJECT_DIR/$VENV_DIR/bin/python" sed -i.bak "s|/path/to/your/project/.venv/bin/python|$python_path|g" "$config_file" sed -i.bak "s|/path/to/your/project|$PROJECT_DIR|g" "$config_file" if [ -n "$api_key" ]; then sed -i.bak "s/your_api_key_here/$api_key/g" "$config_file" info "mcpo configuration created at: $config_file" info "Python path set to: $python_path" info "Project path set to: $PROJECT_DIR" info "You can start mcpo with: mcpo --config $config_file --port 8000" return 0 else warning "No API key provided. Edit $config_file and add your API key." return 1 fi } # Function to detect OS detect_os() { case "$(uname -s)" in Darwin*) echo "macos" ;; Linux*) echo "linux" ;; CYGWIN*|MINGW*|MSYS*) echo "windows" ;; *) echo "unknown" ;; esac } # Function to validate API key validate_api_key() { local api_key="$1" if [ -z "$api_key" ] || [ "$api_key" = "your_api_key_here" ]; then return 1 fi info "Validating API key..." if "$PYTHON_EXEC" -c " import sys import asyncio import httpx sys.path.insert(0, '$PROJECT_DIR') from smithsonian_mcp.config import Config import os os.environ['SMITHSONIAN_API_KEY'] = '$api_key' async def test_api_key(): try: headers = {'X-Api-Key': '$api_key'} async with httpx.AsyncClient(headers=headers, timeout=10.0) as client: response = await client.get('https://api.si.edu/openaccess/api/v1.0/search?q=test&rows=1') if response.status_code == 200: data = response.json() if isinstance(data, dict) and 'response' in data and 'rows' in data['response']: print('API key is valid') return True else: print('API key is valid') return True else: print(f'API returned status {response.status_code}') return False except Exception as e: print(f'API key validation failed: {e}') return False try: result = asyncio.run(test_api_key()) if result: sys.exit(0) else: sys.exit(1) except Exception as e: print(f'API key validation failed: {e}') sys.exit(1) " 2>/dev/null; then return 0 else return 1 fi } # Function to get API key from user get_api_key() { while true; do echo -n "Enter your Smithsonian API key (or press Enter to skip): " read -r api_key if [ -z "$api_key" ]; then warning "Skipping API key setup. You'll need to configure it later." return 1 fi if validate_api_key "$api_key"; then echo "$api_key" return 0 else error "Invalid API key. Please get a free key from https://api.data.gov/signup/" fi done } # Function to setup service setup_service() { local os="$1" info "Setting up $os service..." case "$os" in "linux") if command_exists systemctl; then setup_systemd_service else warning "systemctl not found. Manual service setup required." fi ;; "macos") setup_launchd_service ;; "windows") warning "Windows service setup not implemented in this script." ;; esac } # Function to setup systemd service setup_systemd_service() { local service_file="/etc/systemd/system/$SERVICE_NAME.service" local user_service_file="$HOME/.config/systemd/user/$SERVICE_NAME.service" # Prefer user service if directory exists if [ -d "$HOME/.config/systemd/user" ]; then service_file="$user_service_file" info "Creating user systemd service..." else info "Creating system systemd service (requires sudo)..." fi local service_content="[Unit] Description=Smithsonian MCP Server After=network.target [Service] Type=simple User=$USER WorkingDirectory=$PROJECT_DIR Environment=PATH=$PROJECT_DIR/$VENV_DIR/bin ExecStart=$PROJECT_DIR/$VENV_DIR/bin/python -m smithsonian_mcp.server Restart=always RestartSec=10 [Install] WantedBy=multi-user.target" if [ "$service_file" = "$user_service_file" ]; then echo "$service_content" > "$service_file" systemctl --user daemon-reload systemctl --user enable "$SERVICE_NAME" info "User service installed. Start with: systemctl --user start $SERVICE_NAME" else echo "$service_content" | sudo tee "$service_file" > /dev/null sudo systemctl daemon-reload sudo systemctl enable "$SERVICE_NAME" info "System service installed. Start with: sudo systemctl start $SERVICE_NAME" fi } # Function to setup launchd service setup_launchd_service() { local plist_file="$HOME/Library/LaunchAgents/com.smithsonian.mcp.plist" local plist_content="<?xml version=\"1.0\" encoding=\"UTF-8\"?> <!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"> <plist version=\"1.0\"> <dict> <key>Label</key> <string>com.smithsonian.mcp</string> <key>ProgramArguments</key> <array> <string>$PROJECT_DIR/$VENV_DIR/bin/python</string> <string>-m</string> <string>smithsonian_mcp.server</string> </array> <key>WorkingDirectory</key> <string>$PROJECT_DIR</string> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>$HOME/Library/Logs/com.smithsonian.mcp.log</string> <key>StandardErrorPath</key> <string>$HOME/Library/Logs/com.smithsonian.mcp.error.log</string> </dict> </plist>" mkdir -p "$(dirname "$plist_file")" echo "$plist_content" > "$plist_file" launchctl load "$plist_file" info "Launchd service installed and started." } # Function to setup Claude Desktop config setup_claude_config() { local api_key="$1" local config_dir="" local config_file="" case "$(detect_os)" in "macos") config_dir="$HOME/Library/Application Support/Claude" ;; "linux") config_dir="$HOME/.config/Claude" ;; "windows") config_dir="$APPDATA/Claude" ;; esac if [ -z "$config_dir" ]; then warning "Could not detect Claude Desktop config directory." return 1 fi config_file="$config_dir/claude_desktop_config.json" # Create config directory if it doesn't exist mkdir -p "$config_dir" # Backup existing config if [ -f "$config_file" ]; then cp "$config_file" "$config_file.backup.$(date +%Y%m%d_%H%M%S)" info "Backed up existing Claude Desktop config." fi # Create or update config local config_content="{\n \"mcpServers\": {\n \"smithsonian_open_access\": {\n \"command\": \"$PROJECT_DIR/$VENV_DIR/bin/python\",\n \"args\": [\"-m\", \"smithsonian_mcp.server\"],\n \"env\": {\n \"SMITHSONIAN_API_KEY\": \"$api_key\",\n \"LOG_LEVEL\": \"INFO\"\n }\n }\n }\n}" echo -e "$config_content" > "$config_file" info "Claude Desktop configuration updated at: $config_file" info "Restart Claude Desktop to apply changes." } # Function to run health check run_health_check() { info "Running health check..." # Test API connection if "$PYTHON_EXEC" examples/test-api-connection.py; then info "✓ API connection test passed" else error "✗ API connection test failed" return 1 fi # Test MCP server startup if timeout 10s "$PYTHON_EXEC" -m smithsonian_mcp.server --test 2>/dev/null; then info "✓ MCP server startup test passed" else warning "⚠ MCP server startup test inconclusive (this may be normal)" fi info "Health check completed." } # --- Main Script --- # 1. Check for Python 3 if ! command_exists python3; then error "Python 3 is not installed. Please install it to continue." exit 1 fi info "Python 3 found." # 2. Create virtual environment if it doesn't exist if [ ! -d "$VENV_DIR" ]; then info "Creating Python virtual environment in '$VENV_DIR'..." python3 -m venv "$VENV_DIR" else info "Virtual environment '$VENV_DIR' already exists." fi # 3. Install dependencies if [ -f "$REQUIREMENTS_FILE" ]; then info "Installing dependencies from '$REQUIREMENTS_FILE'..." "$PIP_EXEC" install -r "$REQUIREMENTS_FILE" info "Dependencies installed successfully." else warning "Warning: '$REQUIREMENTS_FILE' not found. Skipping dependency installation." fi # 4. Setup .env file and get API key api_key="" if [ ! -f ".env" ]; then if [ -f ".env.example" ]; then info "Creating .env from .env.example..." cp .env.example .env else warning "No .env.example found. Creating basic .env file." echo "SMITHSONIAN_API_KEY=your_api_key_here" > .env fi fi # Extract existing API key or get new one if [ -f ".env" ]; then existing_key=$(grep "^SMITHSONIAN_API_KEY=" .env | cut -d'=' -f2) if [ -n "$existing_key" ] && [ "$existing_key" != "your_api_key_here" ]; then if validate_api_key "$existing_key"; then api_key="$existing_key" info "Using existing valid API key from .env file." else warning "Existing API key is invalid. Please enter a new one." fi fi fi if [ -z "$api_key" ]; then api_key=$(get_api_key) if [ -n "$api_key" ]; then # Update .env with the new API key sed -i.bak "s/^SMITHSONIAN_API_KEY=.*/SMITHSONIAN_API_KEY=$api_key/" .env info "API key saved to .env file." fi fi # 5. Check for mcpo and offer setup if check_mcpo; then info "mcpo detected on your system." echo -n "Do you want to create an mcpo configuration file? (y/N): " read -r setup_mcpo if [[ "$setup_mcpo" =~ ^[Yy]$ ]]; then setup_mcpo_config "$api_key" fi else info "mcpo not found. For multi-MCP orchestration, install with: pip install mcpo" fi # 6. Setup service os=$(detect_os) if [ "$os" != "unknown" ]; then echo -n "Do you want to install $SERVICE_NAME as a system service? (y/N): " read -r install_service if [[ "$install_service" =~ ^[Yy]$ ]]; then setup_service "$os" fi fi # 7. Setup Claude Desktop config if [ -n "$api_key" ]; then echo -n "Do you want to automatically configure Claude Desktop? (y/N): " read -r setup_claude if [[ "$setup_claude" =~ ^[Yy]$ ]]; then setup_claude_config "$api_key" fi fi # 8. Run health check echo -n "Do you want to run a health check? (Y/n): " read -r run_check if [[ ! "$run_check" =~ ^[Nn]$ ]]; then run_health_check fi info "" info "🎉 Setup complete!" info "" info "Next steps:" if [ -n "$api_key" ]; then info "✓ API key configured and validated" else info "⚠ Edit .env and add your API key from https://api.data.gov/signup/" fi info "✓ Dependencies installed" info "✓ Virtual environment created at $VENV_DIR" info "" info "Usage:" info " Activate environment: source $VENV_DIR/bin/activate" info " Test connection: python examples/test-api-connection.py" info " Run server: python -m smithsonian_mcp.server" if command_exists systemctl && [ -f "/etc/systemd/system/$SERVICE_NAME.service" ] || [ -f "$HOME/.config/systemd/user/$SERVICE_NAME.service" ]; then info " Manage service: systemctl --user start/stop/status $SERVICE_NAME" fi info "" info "For troubleshooting, see README.md or run: python scripts/verify-setup.py"

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/molanojustin/smithsonian-mcp'

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