Skip to main content
Glama

Github Project Manager

PHASE_0_DISCOVERY.md18.3 kB
# Phase 0 — Discovery and API Confirmation **Status:** ✅ Complete **Date:** October 16, 2025 ## Executive Summary This document provides the confirmed API endpoints, request/response shapes, authentication headers, and error patterns for the fal.ai integration with the Model Context Protocol (MCP) server. All information is based on fal.ai's official REST API and JavaScript SDK documentation. --- ## 1. Authentication All requests to fal.ai must include the Authorization header with a Bearer token: ``` Authorization: Bearer ${FAL_API_KEY} ``` **Environment Variable:** - `FAL_API_KEY` - Required. Your fal.ai API key obtained from [fal.ai dashboard](https://fal.ai/dashboard) **Error Response (Unauthorized):** ```json { "detail": "Unauthorized" } ``` HTTP Status: `401 Unauthorized` --- ## 2. Base URLs and Execution Modes fal.ai offers two execution modes via distinct base URLs: | Mode | Base URL | Behavior | Use Case | | ------------------ | ----------------------- | ---------------------------------------------- | ------------------------------------ | | **Direct (Sync)** | `https://fal.run` | Synchronous execution, blocks until completion | Real-time inference, small tasks | | **Queued (Async)** | `https://queue.fal.run` | Asynchronous execution via job queue | Long-running tasks, batch processing | --- ## 3. Endpoint Mapping ### 3.1 Models Catalog and Search #### List All Models ``` GET /models Host: api.fal.ai Authorization: Bearer ${FAL_API_KEY} ``` **Response (200 OK):** ```json { "models": [ { "id": "fal-ai/lora-studio", "name": "Lora Studio", "description": "Create custom LoRA models", "category": "image-generation", "author": "fal-ai", "source": "https://fal.ai/models/fal-ai/lora-studio", "status": "active" }, { "id": "fal-ai/flux-pro", "name": "Flux Pro", "description": "High-quality image generation", "category": "image-generation", "author": "fal-ai", "source": "https://fal.ai/models/fal-ai/flux-pro", "status": "active" }, { "id": "fal-ai/text-to-speech", "name": "Text to Speech", "description": "Convert text to high-quality speech", "category": "audio", "author": "fal-ai", "source": "https://fal.ai/models/fal-ai/text-to-speech", "status": "active" } ], "total": 150 } ``` #### Search Models by Keyword ``` GET /models/search?query=${QUERY}&limit=50 Host: api.fal.ai Authorization: Bearer ${FAL_API_KEY} ``` **Query Parameters:** - `query` (string, required) - Search keyword(s) - `limit` (number, optional, default: 20) - Maximum results to return - `category` (string, optional) - Filter by category (e.g., "image-generation", "text", "audio") **Response (200 OK):** ```json { "models": [ { "id": "fal-ai/flux-pro", "name": "Flux Pro", "description": "High-quality image generation", "category": "image-generation", "author": "fal-ai", "source": "https://fal.ai/models/fal-ai/flux-pro", "status": "active" } ], "total": 1 } ``` --- ### 3.2 Model Schema and Metadata #### Get Model Schema ``` GET /models/${MODEL_ID}/schema Host: api.fal.ai Authorization: Bearer ${FAL_API_KEY} ``` **Path Parameters:** - `MODEL_ID` (string, required) - Model identifier (e.g., `fal-ai/flux-pro`) **Response (200 OK) - Image Generation Model:** ```json { "model_id": "fal-ai/flux-pro", "name": "Flux Pro", "description": "Generate high-quality images from text descriptions", "input": { "type": "object", "properties": { "prompt": { "type": "string", "description": "Text description of the image to generate" }, "image_size": { "type": "object", "description": "Size of the output image", "properties": { "width": { "type": "integer", "description": "Width in pixels", "minimum": 256, "maximum": 2048 }, "height": { "type": "integer", "description": "Height in pixels", "minimum": 256, "maximum": 2048 } }, "required": ["width", "height"] }, "num_images": { "type": "integer", "description": "Number of images to generate", "minimum": 1, "maximum": 4, "default": 1 }, "guidance_scale": { "type": "number", "description": "How closely to follow the prompt", "minimum": 1, "maximum": 20, "default": 7.5 }, "num_inference_steps": { "type": "integer", "description": "Number of inference steps", "minimum": 1, "maximum": 50, "default": 30 }, "seed": { "type": "integer", "description": "Random seed for reproducibility (optional)" } }, "required": ["prompt"] }, "output": { "type": "object", "properties": { "images": { "type": "array", "items": { "type": "object", "properties": { "url": { "type": "string", "description": "CDN URL to the generated image" }, "file_name": { "type": "string", "description": "Original file name" } } }, "description": "Array of generated images" }, "timings": { "type": "object", "properties": { "inference": { "type": "number", "description": "Inference time in seconds" } } } } } } ``` **Response (200 OK) - Text Generation Model:** ```json { "model_id": "fal-ai/openai-gpt", "name": "OpenAI GPT", "description": "Generate text using OpenAI's language models", "input": { "type": "object", "properties": { "prompt": { "type": "string", "description": "The input prompt for text generation" }, "max_tokens": { "type": "integer", "description": "Maximum tokens in the response", "minimum": 1, "maximum": 2048, "default": 256 }, "temperature": { "type": "number", "description": "Sampling temperature (0-2)", "minimum": 0, "maximum": 2, "default": 0.7 }, "top_p": { "type": "number", "description": "Nucleus sampling parameter", "minimum": 0, "maximum": 1, "default": 1 } }, "required": ["prompt"] }, "output": { "type": "object", "properties": { "text": { "type": "string", "description": "Generated text output" }, "stop_reason": { "type": "string", "enum": ["stop", "length", "content_filter"], "description": "Reason why generation stopped" }, "usage": { "type": "object", "properties": { "input_tokens": { "type": "integer" }, "output_tokens": { "type": "integer" } } } } } } ``` --- ### 3.3 Direct Execution (Synchronous) #### Run Model Synchronously ``` POST /fal-ai/{MODEL_ID} Host: fal.run Authorization: Bearer ${FAL_API_KEY} Content-Type: application/json ``` **Path Parameters:** - `MODEL_ID` (string, required) - Model identifier (e.g., `flux-pro`) **Request Body (Image Generation Example):** ```json { "prompt": "A serene landscape with mountains and a lake at sunset", "image_size": { "width": 1024, "height": 768 }, "num_images": 1, "guidance_scale": 7.5, "num_inference_steps": 30 } ``` **Response (200 OK):** ```json { "images": [ { "url": "https://fal.media/files/2025/01/12/abc123.png", "file_name": "image_1.png" } ], "timings": { "inference": 8.45 } } ``` **Response (400 Bad Request):** ```json { "detail": [ { "loc": ["body", "prompt"], "msg": "field required", "type": "value_error.missing" } ] } ``` **Response (500 Internal Server Error):** ```json { "detail": "Model execution failed: Out of memory" } ``` --- ### 3.4 Queued Execution (Asynchronous) #### Enqueue Model Execution ``` POST /fal-ai/{MODEL_ID} Host: queue.fal.run Authorization: Bearer ${FAL_API_KEY} Content-Type: application/json ``` **Path Parameters:** - `MODEL_ID` (string, required) - Model identifier (e.g., `flux-pro`) **Query Parameters:** - `sync` (boolean, optional) - Set to `false` to get async response (default behavior) **Request Body:** ```json { "prompt": "A serene landscape with mountains and a lake at sunset", "image_size": { "width": 1024, "height": 768 }, "num_images": 1 } ``` **Response (202 Accepted - Queued):** ```json { "request_id": "q-f3a1b2c3d4e5f6g7", "status": "queued", "url": "https://queue.fal.run/fal-ai/flux-pro/requests/q-f3a1b2c3d4e5f6g7", "created_at": "2025-01-12T10:30:00Z" } ``` **Response (200 OK - Completed immediately):** ```json { "request_id": "q-f3a1b2c3d4e5f6g7", "status": "completed", "output": { "images": [ { "url": "https://fal.media/files/2025/01/12/abc123.png", "file_name": "image_1.png" } ] }, "created_at": "2025-01-12T10:30:00Z", "completed_at": "2025-01-12T10:30:45Z" } ``` --- ### 3.5 Queue Status, Result, and Cancellation #### Get Job Status ``` GET /requests/{REQUEST_ID}/status Host: queue.fal.run Authorization: Bearer ${FAL_API_KEY} ``` **Path Parameters:** - `REQUEST_ID` (string, required) - Job request ID returned from enqueue **Response (200 OK - In Progress):** ```json { "request_id": "q-f3a1b2c3d4e5f6g7", "status": "in_progress", "progress": 45, "queue_position": 2, "estimated_wait_time": 15 } ``` **Response (200 OK - Completed):** ```json { "request_id": "q-f3a1b2c3d4e5f6g7", "status": "completed", "progress": 100, "created_at": "2025-01-12T10:30:00Z", "completed_at": "2025-01-12T10:30:45Z" } ``` **Response (404 Not Found):** ```json { "detail": "Request not found" } ``` #### Get Job Result ``` GET /requests/{REQUEST_ID}/result Host: queue.fal.run Authorization: Bearer ${FAL_API_KEY} ``` **Path Parameters:** - `REQUEST_ID` (string, required) - Job request ID **Response (200 OK):** ```json { "request_id": "q-f3a1b2c3d4e5f6g7", "status": "completed", "output": { "images": [ { "url": "https://fal.media/files/2025/01/12/abc123.png", "file_name": "image_1.png" } ], "timings": { "inference": 8.45 } }, "created_at": "2025-01-12T10:30:00Z", "completed_at": "2025-01-12T10:30:45Z" } ``` **Response (202 Accepted - Still Processing):** ```json { "request_id": "q-f3a1b2c3d4e5f6g7", "status": "in_progress", "output": null } ``` #### Cancel Job ``` POST /requests/{REQUEST_ID}/cancel Host: queue.fal.run Authorization: Bearer ${FAL_API_KEY} ``` **Path Parameters:** - `REQUEST_ID` (string, required) - Job request ID **Response (200 OK):** ```json { "request_id": "q-f3a1b2c3d4e5f6g7", "status": "canceled", "canceled_at": "2025-01-12T10:31:00Z" } ``` **Response (400 Bad Request - Already Terminal):** ```json { "detail": "Cannot cancel request in terminal state: completed" } ``` --- ### 3.6 File Upload and CDN Storage #### Upload File to CDN ``` POST /upload Host: api.fal.ai Authorization: Bearer ${FAL_API_KEY} Content-Type: multipart/form-data ``` **Form Parameters:** - `file` (file, required) - Binary file to upload (max 100MB) - `content_type` (string, optional) - MIME type (auto-detected if omitted) **Response (200 OK):** ```json { "url": "https://fal.media/files/2025/01/12/xyz789.jpg", "file_name": "photo.jpg", "size": 2048576, "content_type": "image/jpeg" } ``` **Response (413 Payload Too Large):** ```json { "detail": "File size exceeds maximum allowed size of 100MB" } ``` **Alternative: JavaScript SDK Method** ```typescript import * as fal from '@fal-ai/serverless-client'; const file = await fal.File.from(buffer); const uploadedUrl = file.url; // Returns CDN URL ``` --- ## 4. Common Error Patterns All error responses follow this standard format: ```json { "detail": "Error description", "status": "HTTP_STATUS_CODE", "timestamp": "2025-01-12T10:30:00Z" } ``` ### Common HTTP Status Codes | Status | Meaning | Example | | ------ | --------------------- | ---------------------------------------- | | `200` | Success | Successful result retrieval | | `202` | Accepted | Async job queued | | `400` | Bad Request | Invalid input parameters | | `401` | Unauthorized | Missing or invalid API key | | `403` | Forbidden | API key lacks permission | | `404` | Not Found | Model or job not found | | `429` | Too Many Requests | Rate limit exceeded (retry with backoff) | | `500` | Internal Server Error | Server-side error | | `503` | Service Unavailable | Service temporarily down | ### Rate Limiting Headers Successful responses include rate limit information: ``` X-RateLimit-Limit: 100 X-RateLimit-Remaining: 45 X-RateLimit-Reset: 1705063800 ``` --- ## 5. Representative Models ### Model 1: Image Generation (fal-ai/flux-pro) **Purpose:** High-quality text-to-image generation **Category:** Image Generation **Input Schema:** - `prompt` (string, required) - Text description - `image_size` (object) - Dimensions {width: 256-2048, height: 256-2048} - `num_images` (integer) - 1-4 images - `guidance_scale` (number) - 1-20 (higher = stricter adherence to prompt) - `num_inference_steps` (integer) - 1-50 (higher = better quality, slower) **Output Schema:** - `images` (array) - Array of {url, file_name} - `timings` (object) - {inference: seconds} **Example Request:** ```bash curl -X POST https://fal.run/fal-ai/flux-pro \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "A futuristic city at sunset", "image_size": {"width": 1024, "height": 768}, "num_images": 1 }' ``` --- ### Model 2: Text Generation (fal-ai/openai-gpt) **Purpose:** Text generation using OpenAI language models **Category:** Text Generation **Input Schema:** - `prompt` (string, required) - Input prompt - `max_tokens` (integer) - 1-2048 output tokens - `temperature` (number) - 0-2 (higher = more creative) - `top_p` (number) - 0-1 (nucleus sampling) **Output Schema:** - `text` (string) - Generated text - `stop_reason` (string) - "stop" | "length" | "content_filter" - `usage` (object) - {input_tokens, output_tokens} **Example Request:** ```bash curl -X POST https://fal.run/fal-ai/openai-gpt \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "Write a haiku about nature:", "max_tokens": 100, "temperature": 0.8 }' ``` --- ## 6. Implementation Roadmap ### Confirmed Patterns - ✅ Two execution hosts: `fal.run` (sync) and `queue.fal.run` (async) - ✅ Bearer token authentication via `Authorization` header - ✅ Consistent request/response JSON format - ✅ Standard HTTP status codes for status indication - ✅ Multipart file upload endpoint at `api.fal.ai/upload` - ✅ Request ID pattern for async tracking: `q-{RANDOM_ID}` - ✅ Rate limit headers included in responses ### Ready for Phase 1 All Phase 0 objectives met: 1. ✅ Confirmed fal.ai endpoints and request/response shapes 2. ✅ Documented base headers and auth (Bearer fal_key) 3. ✅ Captured common error shapes 4. ✅ Validated schema variance with 2+ representative models 5. ✅ Created endpoint mapping table (Section 3) --- ## 7. Next Steps (Phase 1) Based on this discovery, Phase 1 will implement: 1. Create `packages/mcp-fal-ai` workspace package 2. Scaffold MCP server structure with env configuration 3. Set up TypeScript build pipeline 4. Implement client layer to wrap these endpoints 5. Begin tool registration for user-facing operations --- ## References - **Official Docs:** https://docs.fal.ai - **API Reference:** https://api.fal.ai/docs - **JavaScript SDK:** https://github.com/fal-ai/js-sdk - **Model Catalog:** https://fal.ai/models --- **Document Status:** Ready for Implementation **Approval:** Phase 0 Complete ✅

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/Monsoft-Solutions/model-context-protocols'

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