Wrap Any APIs as MCP Server: Test in Claude and Postman

Additional menu

Collection of skills, ideas and reflections

Wrap Any APIs as MCP Server: Test in Claude and Postman

posted on June 20, 2025

How-To Build Your First MCP Server with PyCharm

In this video, I’m going to show you how to wrap any APIs into a MCP Server, and then test it with Claude Desktop and Postman.
Github: https://github.com/portkeys/nasa-mcp

🎯 What You’ll Learn

By the end of this guide, you’ll know how to:

  • Use FastMCP for rapid MCP server development
  • Configure Claude Desktop to use custom MCP servers
  • Test Python MCP servers with both Claude and Postman
  • Leverage PyCharm’s AI Assistant for enhanced development

🚀 What We’re Building

We’ll create an MCP server that wraps two powerful NASA APIs:

  • Astronomy Picture of the Day (APOD) – Get stunning space imagery with detailed descriptions
  • NASA Image and Video Library – Search through NASA’s vast collection of space media

Four-step Plan


Step 1: Project Setup with UV Package Manager

First, let’s set up our project with UV, a modern Python package manager that’s faster and more reliable than pip.

Installing Dependencies

# uv add requests python-dotenv mcp

Environment Configuration

Create a .env file in your project root:

1 NASA_API_KEY=your_nasa_api_key_here

This approach keeps sensitive API keys out of your source code and makes your project more secure and portable.

Step 2: API Development & Testing

Now we’ll create our NASA API functions.

Create a new file nasa_api/nasa.py:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 import os from dotenv ``import load_dotenv import requests from typing ``import Optional, ``Dict load_dotenv() NASA_API_KEY ``= os.getenv(``"NASA_API_KEY"``) ``or "DEMO_KEY" def make_api_request(url: ``str``, params: ``dict``, timeout: ``int = 10``) ``-``> Optional[``Dict``]: """ Make an HTTP GET request to the specified URL with given parameters. Args: url (str): The URL to make the request to params (dict): Dictionary of parameters to include in the request timeout (int, optional): Request timeout in seconds. Defaults to 10. Returns: Optional[Dict]: JSON response as a dictionary if successful, None if failed Raises: Prints error message to console if request fails """ try``: response ``= requests.get(url, params``=``params, timeout``=``timeout) # Check if the response status code indicates success response.raise_for_status() # Try to parse JSON response return response.json() except requests.exceptions.Timeout: print``(f``"Request timeout after {timeout} seconds for URL: {url}"``) return None except requests.exceptions.ConnectionError: print``(f``"Connection error occurred for URL: {url}"``) return None except requests.exceptions.HTTPError as e: print``(f``"HTTP error {response.status_code} for URL: {url} - {e}"``) return None except requests.exceptions.RequestException as e: print``(f``"Request error for URL: {url} - {e}"``) return None except ValueError as e: print``(f``"JSON decode error for URL: {url} - Invalid JSON response: {e}"``) return None except Exception as e: print``(f``"Unexpected error for URL: {url} - {e}"``) return None def get_nasa_apod(date: Optional[``str``] ``= None``): """ Retrieve NASA's Astronomy Picture of the Day (APOD). Args: api_key (str, optional): NASA API key. Defaults to NASA_API_KEY from environment. date (Optional[str], optional): Date in YYYY-MM-DD format for specific APOD. If None, returns today's APOD. Defaults to None. Returns: Optional[Dict]: Dictionary containing APOD data including title, explanation, image URL, and other metadata. Returns None if request fails. Example: apod = get_nasa_apod(date="2023-01-01") print(apod["title"]) """ # Build API URL and parameters base_url ``= "[https://api.nasa.gov/planetary/apod](https://api.nasa.gov/planetary/apod)" params ``= { "api_key"``: NASA_API_KEY, } if date: # params[``"date"``] ``= date return make_api_request(base_url, params, timeout``=``10``) def search_nasa_images(query: ``str``, size: ``int = 3``) ``-``> Optional[``Dict``]: """ Search NASA's Image and Video Library for images matching the query. Args: query (str): Search term to look for in NASA's image library size (int, optional): Number of results to return (page size). Defaults to 3. Returns: Optional[Dict]: Dictionary containing search results with image metadata, URLs, and descriptions. Returns None if request fails. Example: results = search_nasa_images("Mars rover", size=5) for item in results["collection"]["items"]: print(item["data"][0]["title"]) """ # NASA Image and Video Library API endpoint base_url ``= "[https://images-api.nasa.gov/search](https://images-api.nasa.gov/search)" # Build parameters params ``= { "q"``: query, "media_type"``: ``"image"``, "page"``: ``1``, "page_size"``: size } return make_api_request(base_url, params, timeout``=``15``)

Step 3: MCP Server Implementation

This is where the magic happens. We’ll use FastMCP to transform our API functions into MCP tools that Claude can use.

Create nasa_mcp_server.py:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 import json from mcp.server.fastmcp ``import FastMCP from api.nasa ``import get_nasa_apod, search_nasa_images mcp ``= FastMCP() @mcp``.tool(``"get_nasa_apod"``) def get_apod_data(date: ``str = None``): """Get NASA's Astronomy Picture of the Day (APOD). Retrieves the featured astronomy image or video for a specific date, along with its title, explanation, and metadata from NASA's APOD service. Args: date: Optional date in YYYY-MM-DD format. If not provided, returns today's APOD. Must be between 1995-06-16 (first APOD) and today's date. Returns: JSON object containing APOD data including title, explanation, image URL, date, and other metadata, or error message if request fails. """ result ``= get_nasa_apod(date) if result: return json.dumps(result, indent``=``4``) else``: return {``"error"``: ``"Failed to retrieve APOD data"``} @mcp``.tool(``"search_images_data"``) def search_images_data(q: ``str``, size: ``int = 3``): """Search NASA's image and video library. Searches through NASA's extensive collection of images, videos, and audio files using keywords. Returns metadata and links to matching media assets. Args: q: Search query string. Can include keywords like mission names, celestial objects, astronauts, space phenomena, etc. (e.g., "Mars rover", "International Space Station") size: Number of results to return (default: 3). Recommended range: 1-20. Returns: JSON array containing search results with titles, descriptions, image URLs, dates, and other metadata for each matching item, or error message if search fails. """ result ``= search_nasa_images(query``=``q, size``=``size) if result: return json.dumps(result, indent``=``4``) else``: return {``"error"``: ``"Failed to search for images"``} def main(): mcp.run() if __name__ ``=``= "__main__"``: mcp.run()

Testing with MCP Inspector

Install MCP inspector globally

npm install -g @modelcontextprotocol/inspector

Run the inspector

mcp-inspector uv run python nasa_mcp_server.py

The inspector provides a web interface where you can test your MCP tools interactively, making debugging much easier.

Step 4: Test with Claude Desktop and Postman

Claude Desktop

Now we’ll configure Claude Desktop to use our custom MCP server. Edit your claude_desktop_config.json

{
    "mcpServers": {
      "nasa-mcp": {
          "command": "uv",
          "args":[
            "--directory",
            "/Users/wyang/Projects/2025/nasa_mcp/", 
            "run", 
            "nasa_mcp_server.py"]
      }
    }
  }

Important: Replace /path/to/your/project with the actual path to your project directory.

After updating the configuration:

  1. Restart Claude Desktop
  2. Look for the Claude settings and tools indicating MCP servers are connected
  3. Try asking Claude: “Show me today’s NASA Astronomy Picture of the Day”

Testing with Postman

uv --directory /Users/wyang/Projects/2025/nasa_mcp/ run nasa_mcp_server.py

🥳 Whohoo~

Filed Under: GenAI

Reader Interactions

Leave a Reply

You must be logged in to post a comment.

Primary Sidebar

Hey, I’m Wen!

Thanks for visiting Three Portkeys, I hope you enjoy it! Click around, and I look forward to connecting with you!

Recent Posts

Recent Comments

Archives

Categories

Recently Published

Copyright © 2025 · Authority Pro on Genesis Framework · WordPress · Log in