Skip to main content
python -m venv venv
source venv/bin/activate    # macOS/Linux
venv\Scripts\activate       # Windows

2. Install FastApps & Create Project

pip install fastapps
fastapps init my-app
When you run fastapps init my-app, this structure is generated:
my-app/
├── server/
│   ├── __init__.py              # Empty file
│   ├── main.py                  # Auto-discovery server (pre-configured)
│   └── tools/
│       ├── __init__.py          # Empty file
│       └── my_widget_tool.py    # ← YOUR CODE: Widget backend

├── widgets/
│   └── my-widget/
│       └── index.jsx            # ← YOUR CODE: Widget frontend

├── requirements.txt
└── package.json

3. Install Dependencies

cd my-app
pip install -r requirements.txt
npm install

4. Create Your First Widget

fastapps create my-widget
This adds to your project:
my-app/
├── server/
│   └── tools/
│       └── my_widget_tool.py # ← Generated: MCP tool (backend)
└── widgets/
    └── my-widget/
        └── index.jsx         # ← Generated: React component (frontend)

5. Edit Your Widget Code

You only need to edit these 2 files:

server/tools/my_widget_tool.py - Backend Logic

from fastapps import BaseWidget, Field, ConfigDict
from pydantic import BaseModel
from typing import Dict, Any

class MyWidgetInput(BaseModel):
    model_config = ConfigDict(populate_by_name=True)
    name: str = Field(default="World")

class MyWidgetTool(BaseWidget):
    identifier = "my-widget"
    title = "My Widget"
    input_schema = MyWidgetInput
    invoking = "Processing..."
    invoked = "Done!"
    
    widget_csp = {
        "connect_domains": [],      # APIs you'll call
        "resource_domains": []      # Images/fonts you'll use
    }
    
    async def execute(self, input_data: MyWidgetInput) -> Dict[str, Any]:
        # Your logic here
        return {
            "name": input_data.name,
            "message": f"Hello, {input_data.name}!"
        }

widgets/my-widget/index.jsx - Frontend UI

import React from 'react';
import { useWidgetProps } from 'fastapps';

export default function MyWidget() {
  const props = useWidgetProps();
  
  return (
    <div style={{
      padding: '40px',
      textAlign: 'center',
      background: '#4A90E2',
      color: 'white',
      borderRadius: '12px'
    }}>
      <h1>{props.message}</h1>
      <p>Welcome, {props.name}!</p>
    </div>
  );
}
That’s it! These are the only files you need to write.

6. Build and Run

# Build
npm run build

# Start dev server
fastapps dev
On first run, you’ll be prompted for your ngrok auth token: You’ll see:
🚀 FastApps Development Server
┌─────────┬─────────────────────────┐
│ Local   │ http://0.0.0.0:8001    │
│ Public  │ https://xyz.ngrok.io   │
└─────────┴─────────────────────────┘

📡 MCP Server Endpoint: https://xyz.ngrok.io
Now add your public URL to ChatGPT in Settings > Connectors. For example: https://<custom_endpoint>.ngrok-free.app/mcp

✅ Ready for Next Steps

  • Follow the Tutorial for a guided build
  • Explore Widgets and Tools to customize logic and UI
  • Connect APIs or state management when you need more power
I