MCP_README.md•12.4 kB
# Unsplash API MCP Integration
This project integrates the Unsplash API with the Model Context Protocol (MCP), allowing AI agents to interact with the Unsplash API in a structured way.
## What is MCP?
The Model Context Protocol (MCP) is an open standard that enables AI models to interact with external tools and services in a structured way. It provides a standardized interface for AI models to:
- Discover available tools and their capabilities
- Call tools with specific parameters
- Receive structured responses from tools
This implementation uses [FastAPI-MCP](https://github.com/tadata-org/fastapi-mcp), which automatically converts FastAPI endpoints into MCP tools.
## MCP Server Configuration
The MCP server is configured in the dedicated `src/app/mcp.py` file:
```python
"""
Model Context Protocol (MCP) configuration.
This module configures the FastAPI MCP integration, which allows exposing
FastAPI endpoints as Model Context Protocol (MCP) tools for AI agents.
"""
from fastapi import FastAPI
from fastapi_mcp import FastApiMCP, AuthConfig
from typing import Optional
import logging
from src.config import settings
# Configure logger for MCP requests
logger = logging.getLogger("mcp_logger")
def setup_mcp(app: FastAPI) -> FastApiMCP:
"""
Set up and configure the MCP server for the FastAPI application.
This function configures the FastAPI-MCP integration, which allows exposing
FastAPI endpoints as Model Context Protocol (MCP) tools for AI agents.
Args:
app: The FastAPI application instance.
Returns:
The configured FastApiMCP instance.
"""
# Get API key from settings
api_key = settings.UNSPLASH_CLIENT_ID
# Create authentication config if API key is available
auth_config: Optional[AuthConfig] = None
if api_key:
# In a real application, you would implement proper authentication
# This is just a placeholder for demonstration purposes
# Note: AuthConfig requires at least one of these fields:
# - dependencies: List of FastAPI dependencies for authentication
# - issuer: OAuth issuer URL
# - custom_oauth_metadata: Custom OAuth metadata
auth_config = AuthConfig(
# Empty list means no authentication is required, but satisfies the validation
dependencies=[]
)
# Create MCP server with enhanced configuration
mcp = FastApiMCP(
app,
name=f"{settings.PROJECT_NAME} MCP",
description="MCP server for Unsplash API, providing tools for AI agents to interact with image data.",
# Enable authentication if configured
auth_config=auth_config,
# Include detailed response schemas in tool descriptions
describe_all_responses=True,
describe_full_response_schema=True,
# Only include endpoints with these tags
include_tags=["photos", "search", "random"],
)
return mcp
```
And it's used in the `src/app/api.py` file:
```python
from src.app.mcp import setup_mcp
# Create FastAPI-MCP instance
mcp = setup_mcp(app)
```
## Available MCP Tools
The following endpoints are exposed as MCP tools with comprehensive documentation:
### 1. Search Photos
**Endpoint:** `search_photos`
**Tags:** `search`, `photos`
**Description:**
Search for images on Unsplash based on a query string. This endpoint allows you to search for photos using keywords. The results include comprehensive metadata about each photo, including descriptions, author information, download links, and engagement metrics.
**Parameters:**
- `query` (string): Search terms to find specific photos (e.g., 'mountain', 'ocean sunset', 'city skyline')
- Default: "nature"
- Example: "forest"
- `page` (integer): Page number for pagination (starts at 1)
- Default: 1
- Minimum: 1
- Example: 1
- `per_page` (integer): Number of photos to return per page
- Default: 10
- Range: 1-30
- Example: 10
- `order_by` (string): How to sort the photos
- Default: "relevant"
- Options: "relevant" (best match to query), "latest" (most recent)
- Example: "relevant"
**Example Queries:**
- Search for nature photos: `?query=nature&page=1&per_page=10&order_by=relevant`
- Search for city skylines: `?query=city+skyline&page=1&per_page=20&order_by=latest`
- Search for minimal workspace: `?query=minimal+workspace&page=1&per_page=5&order_by=relevant`
### 2. Get Photos
**Endpoint:** `get_photos`
**Tags:** `photos`
**Description:**
Retrieve a curated collection of photos from Unsplash. This endpoint returns a list of photos with complete metadata, sorted according to your preferences. It's useful for getting high-quality images without specific search criteria.
**Parameters:**
- `page` (integer): Page number for pagination (starts at 1)
- Default: 1
- Minimum: 1
- Example: 1
- `per_page` (integer): Number of photos to return per page
- Default: 10
- Range: 1-30
- Example: 10
- `order_by` (string): How to sort the photos
- Default: "latest"
- Options: "latest" (most recent), "oldest" (first published), "popular" (most liked/downloaded)
- Example: "latest"
**Example Queries:**
- Get 10 latest photos: `?page=1&per_page=10&order_by=latest`
- Get 20 popular photos: `?page=1&per_page=20&order_by=popular`
- Get 5 oldest photos: `?page=1&per_page=5&order_by=oldest`
### 3. Get Random Photos
**Endpoint:** `get_random_photos`
**Tags:** `photos`, `random`
**Description:**
Get random photos from Unsplash, optionally filtered by a search term. This endpoint returns a collection of random photos from Unsplash's extensive library. You can optionally provide a search query to get random photos matching specific criteria.
**Parameters:**
- `query` (string): Optional search term to filter random photos (e.g., 'beach', 'mountains', 'architecture')
- Default: "nature"
- Example: "landscape"
- `count` (integer): Number of random photos to return
- Default: 1
- Range: 1-30
- Example: 3
**Example Queries:**
- Get 1 completely random photo: `?count=1`
- Get 5 random nature photos: `?query=nature&count=5`
- Get 3 random architecture photos: `?query=architecture&count=3`
## Response Format
All endpoints return a consistent JSON response format with detailed photo metadata. Each photo object in the response array contains:
```json
{
"id": "Unique photo ID",
"created_at": "2023-06-20T10:15:30Z",
"updated_at": "2023-06-21T08:30:15Z",
"width": 5184,
"height": 3456,
"color": "#60544D",
"blur_hash": "LPF5?wt7M{ay~qj[M{ay-;ayfQj[",
"likes": 150,
"liked_by_user": false,
"description": "Mountain landscape with pine trees",
"alt_description": "green pine trees near mountain during daytime",
"user": {
"id": "Photographer's unique ID",
"username": "photographer_username",
"name": "Photographer Name",
"portfolio_url": "https://example.com/portfolio",
"bio": "Nature photographer based in Colorado",
"location": "Denver, CO",
"total_likes": 1240,
"total_photos": 86,
"total_collections": 12,
"profile_image": {
"small": "https://images.unsplash.com/profile-small.jpg",
"medium": "https://images.unsplash.com/profile-medium.jpg",
"large": "https://images.unsplash.com/profile-large.jpg"
}
},
"urls": {
"raw": "https://images.unsplash.com/photo-raw.jpg",
"full": "https://images.unsplash.com/photo-full.jpg",
"regular": "https://images.unsplash.com/photo-regular.jpg",
"small": "https://images.unsplash.com/photo-small.jpg",
"thumb": "https://images.unsplash.com/photo-thumb.jpg"
},
"links": {
"self": "https://api.unsplash.com/photos/photo-id",
"html": "https://unsplash.com/photos/photo-id",
"download": "https://unsplash.com/photos/photo-id/download",
"download_location": "https://api.unsplash.com/photos/photo-id/download"
},
"tags": [
{ "title": "mountain" },
{ "title": "nature" },
{ "title": "landscape" }
]
}
```
### Important Response Fields
- **id**: Unique identifier for the photo
- **created_at**: When the photo was added to Unsplash
- **description/alt_description**: Text describing the photo content
- **user**: Information about the photographer
- **urls**: Various resolution options for the image
- **links**: URLs for viewing and downloading the photo
- **tags**: Categories and keywords associated with the photo
This comprehensive metadata allows AI agents to select appropriate images based on various criteria, including visual attributes, photographer information, and engagement metrics.
## Authentication
The MCP server supports authentication if the `UNSPLASH_CLIENT_ID` environment variable is set. In a production environment, you would implement proper authentication using FastAPI dependencies.
## Connecting to the MCP Server
The MCP server is available at `/mcp` and uses Server-Sent Events (SSE) for transport. AI agents can connect to this endpoint to discover and use the available tools.
### Using with AI Agents
AI models that support the Model Context Protocol (MCP) can interact with these endpoints in a structured way. Here's how different AI agents can use these tools:
#### Claude Desktop
1. Open Claude Desktop
2. Go to Settings > Tools > Add Tool
3. Enter the MCP server URL: `http://your-server:8000/mcp`
4. Claude will automatically discover the available tools and their capabilities
#### Cursor AI
1. Open Cursor AI
2. Use the `/connect` command
3. Enter the MCP server URL: `http://your-server:8000/mcp`
4. Cursor AI will connect to the MCP server and make the tools available
#### Custom MCP Client
You can also create a custom MCP client to interact with the server:
```python
import requests
import json
class UnsplashMCPClient:
def __init__(self, base_url="http://localhost:8000"):
self.base_url = base_url
def _make_request(self, endpoint, data=None):
url = f"{self.base_url}/{endpoint}"
response = requests.post(url, json=data)
return response.json()
def list_tools(self):
return self._make_request("mcp/list_tools")
def search_photos(self, query="nature", page=1, per_page=10, order_by="relevant"):
return self._make_request("mcp/call_tool", {
"name": "search_photos",
"arguments": {
"query": query,
"page": page,
"per_page": per_page,
"order_by": order_by
}
})
# Usage example
client = UnsplashMCPClient()
nature_photos = client.search_photos("mountains", per_page=5)
```
### AI Agent Use Cases
The detailed documentation and examples provided for each endpoint make it easier for AI agents to:
1. **Understand tool capabilities**: AI agents can read the detailed descriptions to understand what each tool does
2. **Form correct queries**: The examples show how to structure queries for different scenarios
3. **Parse responses**: The response format documentation helps AI agents extract relevant information
4. **Make informed choices**: Parameter descriptions help AI agents select appropriate values
This enables AI agents to effectively use these tools for tasks like:
- Finding images that match specific criteria for content creation
- Retrieving high-quality photos for design mockups
- Generating random images for inspiration or placeholders
- Accessing detailed metadata about photos for analysis or attribution
## Error Handling
The MCP server includes custom error handling for MCP requests:
```python
@app.exception_handler(HTTPException)
async def mcp_http_exception_handler(request: Request, exc: HTTPException):
if request.url.path.startswith("/mcp"):
# Custom error formatting for MCP clients
return JSONResponse(
status_code=exc.status_code,
content={
"error": exc.detail,
"suggestion": "Try adjusting your query parameters or check the documentation.",
},
)
# Default handling for other clients
return await http_exception_handler(request, exc)
```
## Logging
MCP requests are logged using a custom middleware:
```python
@app.middleware("http")
async def log_mcp_requests(request: Request, call_next):
if request.url.path.startswith("/mcp"):
logger.info(f"MCP Request: {request.method} {request.url.path}")
response = await call_next(request)
return response
```