### Installing and Initializing FastApps Project (Bash)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/quickstart/index.mdx
These commands install FastApps using uv, initialize a new project, navigate to it, and start the development server. Requires uv tool manager; outputs a running widget at a temporary public URL via cloudflared. Limitations: URL is temporary and public access is needed for testing.
```bash
# 0. Install using uv
uv tool install fastapps
uv tool install --upgrade fastapps # Update to the latest version
# 1. Create project
fastapps init my-app
# 2. Run
cd my-app
fastapps dev
```
```bash
fastapps create another-widget
```
--------------------------------
### Install FastApps CLI and Initialize Project
Source: https://context7.com/dooilabs/fastapps_docs/llms.txt
Installs the FastApps command‑line tool, updates it to the latest version, creates a new FastApps project, and starts the development server with an automatic Cloudflare tunnel. These commands set up the environment required for building widgets. No additional dependencies are needed beyond uv.
```bash
# Install FastApps CLI
uv tool install fastapps
# Update to latest version
uv tool install --upgrade fastapps
# Create new project
fastapps init my-app
# Navigate to project
cd my-app
# Start development server with automatic cloudflare tunnel
fastapps dev
```
--------------------------------
### Demonstrate Code Syntax Highlighting
Source: https://github.com/dooilabs/fastapps_docs/blob/main/README_BLOG.md
Examples of properly formatted code blocks for JavaScript and Python languages, demonstrating syntax highlighting capabilities within blog posts. Shows inline comments and function definitions for reference.
```javascript
// JavaScript example
const example = "Code examples use syntax highlighting";
```
```python
# Python example
def example_function():
return "Python code is also supported"
```
--------------------------------
### Configure Navigation for Blog Posts
Source: https://github.com/dooilabs/fastapps_docs/blob/main/README_BLOG.md
Example configuration for adding new blog posts to the docs.json navigation file. Shows proper structure for including blog posts in the documentation navigation with groups and pages array. Must always add new posts to the end of the pages array.
```JSON
{
"tab": "Blog",
"groups": [
{
"group": "Blog",
"pages": [
"blog/index",
"blog/what-are-apps-in-chatgpt-and-why-they-are-the-future-of-software",
"blog/inside-the-chatgpt-apps-sdk-how-it-actually-works",
"blog/your-new-post"
]
}
]
}
```
--------------------------------
### Complete authenticated server example
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/server-configuration/index.mdx
Complete example of an authenticated FastApps server with OAuth configuration. Includes widget building, environment variable loading, and server startup. Uses uvicorn for running the application server.
```python
# server/main.py
import os
from pathlib import Path
from fastapps import WidgetBuilder, WidgetMCPServer
from fastapps.cli.loader import auto_load_tools
PROJECT_ROOT = Path(__file__).parent
# Build all widgets
builder = WidgetBuilder(PROJECT_ROOT)
build_results = builder.build_all()
tools = auto_load_tools(build_results)
# Create authenticated server
server = WidgetMCPServer(
name="my-secure-widgets",
widgets=tools,
# OAuth Configuration
auth_issuer_url=os.getenv("AUTH_ISSUER_URL"),
auth_resource_server_url=os.getenv("AUTH_RESOURCE_SERVER_URL"),
auth_audience=os.getenv("AUTH_AUDIENCE"),
auth_required_scopes=["user"],
)
app = server.get_app()
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8001)
```
--------------------------------
### Start Server with Python
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/troubleshooting/index.mdx
Runs the FastMCP server locally for testing authentication.
```bash
python server/main.py
```
--------------------------------
### Install Authentication Dependencies
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/troubleshooting/index.mdx
Installs required PyJWT and cryptography packages and upgrades fastmcp to ensure authentication support.
```bash
pip install "PyJWT>=2.8.0" "cryptography>=41.0.0"
pip install --upgrade fastmcp
```
--------------------------------
### Premium Content Access Widget (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/examples/index.mdx
Creates an analytics dashboard with a freemium model. It provides different levels of access and data based on user authentication status and 'premium' scope.
```python
from fastapps import BaseWidget, optional_auth, UserContext
from pydantic import BaseModel
class AnalyticsInput(BaseModel):
pass
@optional_auth(scopes=["user"])
class AnalyticsWidget(BaseWidget):
identifier = "analytics"
title = "Analytics Dashboard"
input_schema = AnalyticsInput
async def execute(self, input_data, context, user: UserContext):
# Base analytics available to everyone
base_analytics = await get_public_analytics()
if not user.is_authenticated:
# Free tier - public data only
return {
"tier": "free",
"analytics": base_analytics,
"features": ["basic_charts"],
"message": "Sign in for more features"
}
# Standard tier - authenticated users
user_analytics = await get_user_analytics(user.subject)
if user.has_scope("premium"):
# Premium tier - full features
advanced_analytics = await get_advanced_analytics(user.subject)
custom_reports = await get_custom_reports(user.subject)
return {
"tier": "premium",
"analytics": {
"base": base_analytics,
"user": user_analytics,
"advanced": advanced_analytics
},
"custom_reports": custom_reports,
"features": ["basic_charts", "advanced_charts", "export", "api_access"],
"user_id": user.subject
}
# Standard tier
return {
"tier": "standard",
"analytics": {
"base": base_analytics,
"user": user_analytics
},
"features": ["basic_charts", "user_charts"],
"upgrade_message": "Upgrade to premium for advanced analytics",
"user_id": user.subject
}
```
--------------------------------
### Custom Deployment Widget - Configurable Search
Source: https://github.com/dooilabs/fastapps_docs/blob/main/server/mcp-integration/index.mdx
Advanced widget example showing how to customize Metorial integration with specific deployment IDs and model selection. The example demonstrates parameter override capabilities and conditional model selection based on input configuration.
```python
from fastapps import BaseWidget
from pydantic import BaseModel, Field
from server.api.metorial_mcp import call_metorial
class CustomSearchInput(BaseModel):
query: str = Field(..., description="Search query")
use_mini: bool = Field(default=False, description="Use mini model")
class CustomSearchWidget(BaseWidget):
identifier = "custom-search"
title = "Custom Search"
input_schema = CustomSearchInput
async def execute(self, input_data: CustomSearchInput, ctx):
# Customize deployment and model
result = await call_metorial(
message=f"Find latest: {input_data.query}",
deployment_id="custom_deployment_id", # Optional: override default
model="gpt-4o-mini" if input_data.use_mini else "gpt-4o",
max_steps=10
)
return {
"query": input_data.query,
"results": result
}
```
--------------------------------
### Sample OpenID Configuration JSON
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/providers/index.mdx
Example of the JSON document returned by the OpenID configuration endpoint, showing issuer, authorization, token, JWKS, and registration URLs.
```json
{
"issuer": "https://your-oauth-provider.com",
"authorization_endpoint": "...",
"token_endpoint": "...",
"jwks_uri": "...",
"registration_endpoint": "...",
...
}
```
--------------------------------
### Basic Widget Integration - News Search Example
Source: https://github.com/dooilabs/fastapps_docs/blob/main/server/mcp-integration/index.mdx
Demonstrates basic integration of Metorial MCP in a FastApps widget. The example shows how to create a simple news search widget using Pydantic models for input validation and the BaseWidget framework. Uses default deployment configuration from environment variables.
```python
from fastapps import BaseWidget
from pydantic import BaseModel, Field
from server.api.metorial_mcp import call_metorial
class NewsSearchInput(BaseModel):
query: str = Field(..., description="Search query for news")
class NewsSearchWidget(BaseWidget):
identifier = "news-search"
title = "Search News"
input_schema = NewsSearchInput
invoking = "Searching..."
invoked = "Search complete!"
async def execute(self, input_data: NewsSearchInput, ctx):
# Simple usage - uses default deployment ID from environment
result = await call_metorial(f"Search for: {input_data.query}")
return {
"query": input_data.query,
"results": result
}
```
--------------------------------
### Testing Widget with MCPJam Inspector (Bash)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/quickstart/index.mdx
Runs the MCPJam Inspector tool to test tools and UI in a controlled environment. Requires npx and @mcpjam/inspector package; inputs public URL endpoint; outputs tabs for tool calls and LLM playground. Limitations: Deterministic testing only; requires prior app run with public URL.
```bash
npx @mcpjam/inspector@latest
```
--------------------------------
### Complete User Profile Widget Example in Python
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/user-context/index.mdx
This is a full example of a FastApps widget using UserContext for authentication, user data access, and scope checks. It requires fastapps library and auth_required decorator with scopes. Outputs user profile dictionary with authentication and permission info. Assumes fetch_user_data function for database access.
```python
from fastapps import BaseWidget, auth_required, UserContext
@auth_required(scopes=["user"])
class UserProfileWidget(BaseWidget):
identifier = "user-profile"
title = "User Profile"
async def execute(self, input_data, context, user: UserContext):
# Check authentication status
if not user.is_authenticated:
return {"error": "Authentication required"}
# Access user information
user_id = user.subject
email = user.claims.get('email')
name = user.claims.get('name')
picture = user.claims.get('picture')
# Check permissions
is_premium = user.has_scope("premium")
is_admin = user.has_scope("admin")
# Fetch user data from your database
user_data = await fetch_user_data(user_id)
return {
"user_id": user_id,
"email": email,
"name": name,
"picture": picture,
"is_premium": is_premium,
"is_admin": is_admin,
"profile": user_data,
"scopes": user.scopes
}
```
--------------------------------
### Multi-organization support (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/examples/index.mdx
Widget demonstrating multi-organization membership checks. Requires user authentication and verifies organization membership via custom claim. Returns organization-specific data and user role.
```python
from fastapps import BaseWidget, auth_required, UserContext
from pydantic import BaseModel, Field
class OrgDataInput(BaseModel):
organization_id: str = Field(..., description="Organization ID")
@auth_required(scopes=["user"])
class OrganizationDataWidget(BaseWidget):
identifier = "org-data"
title = "Organization Data"
input_schema = OrgDataInput
async def execute(self, input_data, context, user: UserContext):
# Get user's organizations from custom claim
user_orgs = user.claims.get('https://example.com/organizations', [])
# Check if user belongs to requested organization
if input_data.organization_id not in user_orgs:
return {
"error": "Access denied",
"message": "You don't belong to this organization"
}
# Fetch organization data
org_data = await fetch_org_data(input_data.organization_id)
# Check user's role in this organization
org_role = await get_user_org_role(
user.subject,
input_data.organization_id
)
return {
"organization": org_data,
"role": org_role,
"user_id": user.subject,
"organizations": user_orgs
}
```
--------------------------------
### Implementing Widget Backend Logic (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/quickstart/index.mdx
Defines the backend for a widget using FastApps BaseWidget, including input schema with Pydantic, execution logic, and CSP configuration. Depends on fastapps and pydantic libraries; inputs are validated via MyWidgetInput model; outputs a dictionary with processed data. Limitations: Async execution required; custom APIs need CSP updates.
```python
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}!"
}
```
--------------------------------
### Create a widget in React with FastApps
Source: https://github.com/dooilabs/fastapps_docs/blob/main/what-is-fastapps/index.mdx
Shows how to create a simple React widget for FastApps. The widget is a basic React component that can be displayed in the ChatGPT app. Requires React to be installed.
```javascript
import React from 'react';
export default function HelloWidget() {
return (
Hello world!
);
}
```
--------------------------------
### Authentication Decorator Usage Examples
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/troubleshooting/index.mdx
Shows correct and incorrect ways to import and apply the @auth_required decorator in FastMCP widgets.
```python
# ✅ Correct
from fastapps import auth_required
@auth_required(scopes=["user"])
class MyWidget(BaseWidget):
pass
# ❌ Wrong syntax
@auth_required["user"] # Wrong syntax
class MyWidget(BaseWidget):
pass
# ❌ Wrong import
from fastapps import auth # Missing _required
```
--------------------------------
### Deploy FastApps project to cloud with Bash
Source: https://context7.com/dooilabs/fastapps_docs/llms.txt
Bash commands for deploying FastApps projects to the FastApps Cloud with automatic validation and custom subdomain assignment. The deployment process includes project validation, React widget building, server code packaging, and Vercel deployment. Requires the FastApps CLI to be installed.
```bash
# Login to FastApps Cloud
fastapps cloud login
# Deploy your project
fastapps cloud deploy
# The deployment process automatically:
# 1. Validates project structure
# 2. Builds React widgets to static HTML
# 3. Packages server code
# 4. Deploys to Vercel serverless infrastructure
# 5. Assigns custom *.dooi.app subdomain
```
--------------------------------
### Configure Environment Variables - Metorial Setup
Source: https://github.com/dooilabs/fastapps_docs/blob/main/server/mcp-integration/index.mdx
Sets up required environment variables for Metorial integration. These variables are essential for authentication and deployment configuration. The .env file should be placed in the project root directory and contains API keys and deployment identifiers.
```bash
# .env
METORIAL_API_KEY=your_metorial_api_key
OPENAI_API_KEY=your_openai_api_key
METORIAL_DEPLOYMENT_ID=your_deployment_id
```
--------------------------------
### Build Personalized Content widget with optional authentication (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/examples/index.mdx
Implements a content widget that works with optional authentication, providing full content and personalization for authenticated users and a preview for anonymous visitors. Uses the optional_auth decorator and accesses user preferences, recommendations, and view history when available. Relies on FastApps BaseWidget and various content-fetching utilities.
```Python
from fastapps import BaseWidget, optional_auth, UserContext\nfrom pydantic import BaseModel, Field\n\nclass ContentInput(BaseModel):\n content_id: str = Field(..., description=\"Content ID to fetch\")\n\n@optional_auth(scopes=[\"user\"])\nclass PersonalizedContentWidget(BaseWidget):\n identifier = \"personalized-content\"\n title = \"Personalized Content\"\n input_schema = ContentInput\n \n async def execute(self, input_data, context, user: UserContext):\n # Fetch base content\n content = await fetch_content(input_data.content_id)\n \n if user.is_authenticated:\n # Authenticated: full content + personalization\n user_preferences = await get_preferences(user.subject)\n recommendations = await get_recommendations(user.subject)\n view_history = await get_view_history(user.subject)\n \n # Track view\n await track_view(user.subject, input_data.content_id)\n \n return {\n \"content\": content,\n \"full_access\": True,\n \"preferences\": user_preferences,\n \"recommendations\": recommendations,\n \"history\": view_history,\n \"user_id\": user.subject\n }\n \n # Anonymous: preview only\n return {\n \"content\": content[:500] + \"...\", # Preview\n \"full_access\": False,\n \"message\": \"Sign in for full access and personalized recommendations\"\n }
```
--------------------------------
### Verify OpenID configuration via curl
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/troubleshooting/index.mdx
Command line tool to check OpenID Connect configuration endpoint. Validates issuer URL and required endpoints. Requires jq for JSON parsing. Essential for troubleshooting authentication setup.
```bash
curl https://your-tenant.auth0.com/.well-known/openid-configuration | jq
```
--------------------------------
### Create FastApps Widget with Bash
Source: https://github.com/dooilabs/fastapps_docs/blob/main/widgets/index.mdx
This Bash command creates a new FastApps widget project by scaffolding the directory structure with server and widget components. It requires the FastApps CLI to be installed and configured. Input: Widget name (e.g., mywidget). Output: Generated project files including Python backend and React frontend. Limitations: Generates boilerplate only; custom logic must be added manually.
```bash
fastapps create mywidget
```
--------------------------------
### Implementing Widget Frontend UI (JSX)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/quickstart/index.mdx
Renders the widget UI using React and FastApps hooks to access props from backend. Depends on React and fastapps libraries; inputs props include name and message; outputs a styled div with greeting. Limitations: Styles are inline; no additional state management shown.
```jsx
import React from 'react';
import { useWidgetProps } from 'fastapps';
export default function MyWidget() {
const props = useWidgetProps();
return (
{props.message}
Welcome, {props.name}!
);
}
```
--------------------------------
### Add Blog Post to Index in MDX
Source: https://github.com/dooilabs/fastapps_docs/blob/main/README_BLOG.md
MDX code snippet for adding a new blog post to the index. Includes HTML structure with classes for styling and metadata. Requires proper image paths and post details.
```mdx
```
--------------------------------
### Document access control (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/examples/index.mdx
Widget for controlling document access by user and organization. Requires authentication with read:documents scope. Implements organization checks, ownership verification, and permission evaluation.
```python
from fastapps import BaseWidget, auth_required, UserContext
from pydantic import BaseModel, Field
class DocumentInput(BaseModel):
document_id: str = Field(..., description="Document ID to access")
@auth_required(scopes=["user", "read:documents"])
class DocumentWidget(BaseWidget):
identifier = "document-viewer"
title = "Document Viewer"
input_schema = DocumentInput
async def execute(self, input_data, context, user: UserContext):
# Fetch document
document = await fetch_document(input_data.document_id)
if not document:
return {"error": "Document not found"}
# Check if user has access
user_org = user.claims.get('https://example.com/organization')
if document.organization != user_org:
return {
"error": "Access denied",
"message": "This document belongs to another organization"
}
# Check if user is document owner or has read permission
is_owner = document.owner_id == user.subject
has_read = user.has_scope("read:documents")
if not (is_owner or has_read):
return {
"error": "Access denied",
"message": "You don't have permission to view this document"
}
# Check write permission for editing
can_edit = is_owner or user.has_scope("write:documents")
can_delete = is_owner or user.has_scope("delete:documents")
# Log access
await log_document_access(user.subject, input_data.document_id, "read")
return {
"document": document,
"permissions": {
"read": True,
"edit": can_edit,
"delete": can_delete
},
"user_id": user.subject,
"is_owner": is_owner
}
```
--------------------------------
### Role-Based Dashboard Widget (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/examples/index.mdx
Implements a dashboard that displays different views based on the authenticated user's role (admin, manager, or user). It uses 'auth_required' decorator and retrieves role information from user claims.
```python
from fastapps import BaseWidget, auth_required, UserContext
from pydantic import BaseModel
class DashboardInput(BaseModel):
pass
@auth_required(scopes=["user"])
class RoleBasedDashboardWidget(BaseWidget):
identifier = "dashboard"
title = "Dashboard"
input_schema = DashboardInput
async def execute(self, input_data, context, user: UserContext):
# Get role from custom claims
role = user.claims.get('role', 'user')
if role == 'admin':
return await self._admin_view(user)
elif role == 'manager':
return await self._manager_view(user)
else:
return await self._user_view(user)
async def _admin_view(self, user: UserContext):
return {
"view": "admin",
"data": await get_all_data(),
"users": await get_all_users(),
"analytics": await get_full_analytics(),
"permissions": ["read", "write", "delete", "manage_users"]
}
async def _manager_view(self, user: UserContext):
team_id = user.claims.get('team_id')
return {
```
--------------------------------
### Create User Profile widget displaying authenticated user data (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/examples/index.mdx
Defines a user profile widget that requires the "user" scope. It extracts user information from the token, fetches additional data from the database, and returns a comprehensive profile object. Depends on FastApps BaseWidget, auth_required decorator, and user data retrieval functions.
```Python
from fastapps import BaseWidget, auth_required, UserContext\nfrom pydantic import BaseModel\n\nclass UserProfileInput(BaseModel):\n pass\n\n@auth_required(scopes=[\"user\"])\nclass UserProfileWidget(BaseWidget):\n identifier = \"user-profile\"\n title = \"User Profile\"\n input_schema = UserProfileInput\n \n async def execute(self, input_data, context, user: UserContext):\n # Get user information from token\n user_id = user.subject\n email = user.claims.get(\'email\')\n name = user.claims.get(\'name\')\n picture = user.claims.get(\'picture\')\n \n # Fetch additional user data from database\n user_data = await fetch_user_from_db(user_id)\n preferences = await fetch_user_preferences(user_id)\n \n return {\n \"user_id\": user_id,\n \"email\": email,\n \"name\": name,\n \"picture\": picture,\n \"joined_date\": user_data.created_at,\n \"preferences\": preferences,\n \"is_premium\": user.has_scope(\"premium\"),\n \"scopes\": user.scopes\n }
```
--------------------------------
### HTTPS URL Configuration in Python
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/advanced/index.mdx
Demonstrates proper HTTPS URL setup for authentication resources in MCP servers. This ensures secure communication by avoiding plaintext HTTP. No external dependencies required. Input is URL string, output is configured server.
```python
# ✅ Good
auth_resource_server_url="https://yourdomain.com/mcp"
```
```python
# ❌ Bad
auth_resource_server_url="http://yourdomain.com/mcp"
```
--------------------------------
### Public search with user history (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/examples/index.mdx
Implements a public search widget that tracks history for authenticated users. Uses optional authentication with user scopes. Returns different responses for authenticated vs anonymous users with personalized results.
```python
from fastapps import BaseWidget, optional_auth, UserContext
from pydantic import BaseModel, Field
class SearchInput(BaseModel):
query: str = Field(..., description="Search query")
@optional_auth(scopes=["user"])
class PublicSearchWidget(BaseWidget):
identifier = "public-search"
title = "Search"
input_schema = SearchInput
async def execute(self, input_data, context, user: UserContext):
# Perform search (available to everyone)
results = await search_database(input_data.query)
if user.is_authenticated:
# Save search history for authenticated users
await save_search_history(user.subject, input_data.query)
# Get user's search history
history = await get_search_history(user.subject)
# Personalize results
results = await personalize_results(results, user.subject)
return {
"query": input_data.query,
"results": results,
"personalized": True,
"history": history,
"user_id": user.subject
}
# Anonymous search
return {
"query": input_data.query,
"results": results,
"personalized": False,
"message": "Sign in to save your search history"
}
```
--------------------------------
### Async API Integration - Python External Services
Source: https://context7.com/dooilabs/fastapps_docs/llms.txt
Shows async/await patterns for integrating external APIs and databases. Dependencies include aiohttp for HTTP requests and asyncpg for PostgreSQL. Handles API responses with error checking and transforms results to dictionary format. Includes examples for weather API calls and database query execution with connection management.
```python
from fastapps import BaseWidget
from pydantic import BaseModel
import aiohttp
import asyncpg
class WeatherInput(BaseModel):
city: str
units: str = "metric"
class WeatherWidget(BaseWidget):
identifier = "weather"
title = "Weather Forecast"
input_schema = WeatherInput
invoking = "Fetching weather data..."
invoked = "Weather forecast ready!"
widget_csp = {
"connect_domains": ["api.openweathermap.org"]
}
async def execute(self, inputs: WeatherInput, ctx) -> dict:
api_key = ctx.settings.get("OPENWEATHER_API_KEY")
async with aiohttp.ClientSession() as session:
url = f"https://api.openweathermap.org/data/2.5/weather"
params = {
"q": inputs.city,
"units": inputs.units,
"appid": api_key
}
async with session.get(url, params=params) as response:
if response.status == 200:
data = await response.json()
return {
"city": data["name"],
"temperature": data["main"]["temp"],
"description": data["weather"][0]["description"],
"humidity": data["main"]["humidity"],
"wind_speed": data["wind"]["speed"]
}
else:
return {
"error": f"API error: {response.status}",
"city": inputs.city
}
# Database integration example
class DatabaseQueryWidget(BaseWidget):
identifier = "db-query"
title = "Database Query"
input_schema = QueryInput
invoking = "Querying database..."
invoked = "Query complete!"
async def execute(self, inputs: QueryInput, ctx) -> dict:
db_url = ctx.settings.get("DATABASE_URL")
conn = await asyncpg.connect(db_url)
try:
rows = await conn.fetch(
"SELECT * FROM users WHERE active = $1 LIMIT $2",
True,
inputs.limit
)
users = [dict(row) for row in rows]
return {
"users": users,
"count": len(users)
}
finally:
await conn.close()
```
--------------------------------
### Implement Admin Dashboard widget with admin scope (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/examples/index.mdx
Creates an admin dashboard widget that requires the "admin" scope. It validates the user's admin rights, fetches administrative statistics, user lists, and recent activity, then returns them. Requires FastApps BaseWidget, auth_required decorator, and asynchronous data-fetching functions.
```Python
from fastapps import BaseWidget, auth_required, UserContext\nfrom pydantic import BaseModel\n\nclass AdminDashboardInput(BaseModel):\n pass\n\n@auth_required(scopes=[\"admin\"])\nclass AdminDashboardWidget(BaseWidget):\n identifier = \"admin-dashboard\"\n title = \"Admin Dashboard\"\n input_schema = AdminDashboardInput\n \n async def execute(self, input_data, context, user: UserContext):\n # Double-check admin scope\n if not user.has_scope(\"admin\"):\n return {\n \"error\": \"Admin access required\",\n \"message\": \"Contact your administrator for access\"\n }\n \n # Fetch admin statistics\n stats = await get_admin_stats()\n users = await get_user_list()\n activity = await get_recent_activity()\n \n return {\n \"admin\": user.subject,\n \"admin_email\": user.claims.get(\'email\'),\n \"stats\": stats,\n \"users\": users,\n \"activity\": activity,\n \"permissions\": user.scopes\n }
```
--------------------------------
### Configure WidgetMCPServer with OAuth Authentication in Python
Source: https://context7.com/dooilabs/fastapps_docs/llms.txt
This code sets up a WidgetMCPServer instance with OAuth 2.1 configuration, specifying issuer URL, resource server, audience, required scopes, and optional JWKS endpoint. It requires the fastapps library and supports providers like Auth0, Okta, Azure AD, AWS Cognito, Clerk. The server runs when the script is executed directly. Inputs include widget tools and auth parameters; outputs a running server. Limitations: Auto-discovery of JWKS if not provided; assumes valid OAuth provider setup.
```python
# Configure server with OAuth authentication
server = WidgetMCPServer(
name="my-widgets",
widgets=tools,
# OAuth 2.1 configuration (Auth0 example)
auth_issuer_url="https://tenant.auth0.com",
auth_resource_server_url="https://my-app.example.com/mcp",
auth_audience="https://api.example.com",
auth_required_scopes=["user"], # Default scopes for all widgets
# Optional: Custom JWKS endpoint (auto-discovered if not provided)
auth_jwks_url="https://tenant.auth0.com/.well-known/jwks.json"
)
# Run the server
if __name__ == "__main__":
server.run()
```
--------------------------------
### Execute GraphQL Queries using aiohttp in Python
Source: https://github.com/dooilabs/fastapps_docs/blob/main/server/integration/index.mdx
Provides a FastApps widget that sends a GraphQL query to retrieve user data. The example builds the query string, sets variables, and posts the request via aiohttp, handling errors and returning the user object along with the executed query details. Requires aiohttp and FastApps BaseWidget.
```python
import aiohttp
from fastapps import BaseWidget
class GraphQLWidget(BaseWidget):
identifier = "graphql"
title = "GraphQL Widget"
input_schema = GraphQLInput
invoking = "Querying GraphQL API…"
invoked = "Query executed!"
async def execute(self, inputs: GraphQLInput, ctx):
query = """
query GetUserData($userId: ID!) {
user(id: $userId) {
id
name
email
posts {
id
title
content
createdAt
}
}
}
"""
variables = {"userId": inputs.user_id}
payload = {
"query": query,
"variables": variables
}
async with aiohttp.ClientSession() as session:
async with session.post(
"https://api.example.com/graphql",
json=payload,
headers={"Content-Type": "application/json"}
) as response:
result = await response.json()
if "errors" in result:
raise Exception(f"GraphQL errors: {result['errors']}")
return {
"user": result["data"]["user"],
"query": query,
"variables": variables
}
```
--------------------------------
### Creating Custom Convenience Hooks in FastApps
Source: https://github.com/dooilabs/fastapps_docs/blob/main/widgets/react-hooks/index.mdx
Shows how to create custom hooks in FastApps to simplify access to frequently used global variables provided by `useOpenAiGlobal`. Examples include creating hooks for theme, tool input, and locale.
```tsx
import { useOpenAiGlobal } from 'fastapps';
// Custom hook for theme
export function useTheme() {
return useOpenAiGlobal('theme');
}
// Custom hook for tool input
export function useToolInput() {
return useOpenAiGlobal('toolInput') as T | null;
}
// Custom hook for locale
export function useLocale() {
return useOpenAiGlobal('locale');
}
```
--------------------------------
### Enable Debug Logging for Authentication
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/troubleshooting/index.mdx
Configures Python logging to DEBUG and initializes the WidgetMCPServer with authentication parameters to trace the authentication flow.
```python
import logging
logging.basicConfig(level=logging.DEBUG)
server = WidgetMCPServer(
name="my-widgets",
widgets=,
auth_issuer_url="https://tenant.auth0.com",
auth_resource_server_url="https://example.com/mcp",
auth_required_scopes=["user"],
)
```
--------------------------------
### Configure FastApps server with WidgetMCPServer (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/providers/index.mdx
Creates a WidgetMCPServer instance to serve widgets, specifying server name, widget list, and Cognito authentication parameters. Requires the WidgetMCPServer class and a list of widget tools. Returns a configured server object ready to run.
```python
server = WidgetMCPServer(
name="my-widgets",
widgets=tools,
auth_issuer_url="https://cognito-idp.{region}.amazonaws.com/{user-pool-id}",
auth_resource_server_url="https://yourdomain.com/mcp",
auth_audience="{app-client-id}",
auth_required_scopes=["user"],
)
```
--------------------------------
### Expose Server via Ngrok
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/troubleshooting/index.mdx
Creates a publicly accessible tunnel to the local server on port 8001 for ChatGPT to reach the widgets.
```bash
ngrok http 8001
```
--------------------------------
### Create authenticated server with OAuth 2.1
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/server-configuration/index.mdx
Creates a WidgetMCPServer instance with OAuth 2.1 authentication parameters. Requires auth_issuer_url and auth_resource_server_url to enable authentication. Dependencies: fastapps, fastapps.cli.loader. Uses auto-loaded tools from widget builds.
```python
from fastapps import WidgetBuilder, WidgetMCPServer
from fastapps.cli.loader import auto_load_tools
# Build widgets
builder = WidgetBuilder(PROJECT_ROOT)
build_results = builder.build_all()
tools = auto_load_tools(build_results)
# Create server with authentication
server = WidgetMCPServer(
name="my-widgets",
widgets=tools,
auth_issuer_url="https://tenant.auth0.com",
auth_resource_server_url="https://example.com/mcp",
auth_required_scopes=["user"],
)
app = server.get_app()
```
--------------------------------
### CORS Middleware Setup in Python
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/advanced/index.mdx
Configures CORS for secure cross-origin requests using Starlette middleware. Allows specific origins and methods. Inputs app from server, outputs configured app with CORS.
```python
from starlette.middleware.cors import CORSMiddleware
app = server.get_app()
app.add_middleware(
CORSMiddleware,
allow_origins=["https://chatgpt.com"], # Specific origins
allow_methods=["POST", "GET"], # Specific methods
allow_headers=["Authorization"], # Specific headers
allow_credentials=True,
)
```
--------------------------------
### Print server authentication configuration
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/troubleshooting/index.mdx
Display current server authentication settings for verification. Shows issuer URL, resource server URL, and required scopes. Useful for confirming runtime configuration matches expected values.
```python
# Print server configuration
print(f"Auth Issuer: {server.mcp._mcp_server.auth_issuer_url}")
print(f"Resource Server: {server.mcp._mcp_server.auth_resource_server_url}")
print(f"Required Scopes: {server.mcp._mcp_server.auth_required_scopes}")
```
--------------------------------
### Get OAuth Client ID in Python
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/user-context/index.mdx
This code accesses the OAuth client ID from UserContext. It uses the client_id property for logging access. Outputs the client ID string. Requires authenticated user with valid client ID.
```python
client = user.client_id
log_access(client_id=client, user_id=user.subject)
```
--------------------------------
### Generate Metorial Integration - FastApps CLI
Source: https://github.com/dooilabs/fastapps_docs/blob/main/server/mcp-integration/index.mdx
Uses FastApps CLI to generate the Metorial integration file. This command creates a metorial_mcp.py file under the /api folder and sets up the basic integration structure. Requires FastApps CLI to be installed and configured.
```bash
fastapps use metorial
```
--------------------------------
### Create MCP Tool Backend
Source: https://github.com/dooilabs/fastapps_docs/blob/main/index.mdx
Defines a simple widget backend using FastApps with Pydantic models. The tool accepts an input name and returns a greeting message. Requires FastApps and Pydantic dependencies. Output is a dictionary containing the response message.
```python
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!"
async def execute(self, input_data: MyWidgetInput) -> Dict[str, Any]:
return {"message": f"Hello, {input_data.name}!"}
```
--------------------------------
### Handle Configurations in Python Widgets
Source: https://github.com/dooilabs/fastapps_docs/blob/main/server/integration/index.mdx
This widget manages settings like API timeouts, retries, and feature flags from context. It switches logic based on feature flags, using new or old API implementations. Configurable via settings with defaults provided.
```python
from fastapps import BaseWidget
class ConfigurableWidget(BaseWidget):
identifier = "configurable"
title = "Configurable Widget"
input_schema = ConfigurableInput
invoking = "Processing with configuration…"
invoked = "Processing complete!"
async def execute(self, inputs: ConfigurableInput, ctx):
# Get configuration from settings
config = {
"api_timeout": ctx.settings.get("API_TIMEOUT", 30),
"max_retries": ctx.settings.get("MAX_RETRIES", 3),
"cache_ttl": ctx.settings.get("CACHE_TTL", 3600),
"feature_flags": ctx.settings.get("FEATURE_FLAGS", {}),
"api_endpoints": ctx.settings.get("API_ENDPOINTS", {})
}
# Use configuration in your logic
if config["feature_flags"].get("new_api", False):
result = await self.use_new_api(inputs, config)
else:
result = await self.use_old_api(inputs, config)
return {
"result": result,
"config_used": config,
"feature_flags": config["feature_flags"]
}
async def use_new_api(self, inputs, config):
# Implementation using new API
pass
async def use_old_api(self, inputs, config):
# Implementation using old API
pass
```
--------------------------------
### Implement BaseWidget class in Python
Source: https://github.com/dooilabs/fastapps_docs/blob/main/server/index.mdx
Defines a custom widget by inheriting from BaseWidget in FastApps. Includes required attributes like identifier, title, and input_schema, along with optional ones such as description and widget_accessible. The execute method contains the business logic and returns structured data.
```python
class MyWidget(BaseWidget):
# Required attributes
identifier = "my_widget" # Unique identifier
title = "My Widget Title" # Display name
input_schema = MyInputModel # Pydantic model
invoking = "Setting up widget…" # Progress message
invoked = "Widget ready!" # Completion message
# Optional attributes
description = "Widget description" # Help text
widget_accessible = True # Allow component calls
def execute(self, inputs, ctx):
# Your business logic here
return {"data": "processed"}
```
--------------------------------
### Configure FastApps server using environment variables (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/providers/index.mdx
Loads environment variables via python-dotenv and configures a WidgetMCPServer using those values, enabling secure external configuration. Requires os, dotenv, and WidgetMCPServer.
```python
import os
from dotenv import load_dotenv
load_dotenv()
server = WidgetMCPServer(
name="my-widgets",
widgets=tools,
auth_issuer_url=os.getenv("AUTH_ISSUER_URL"),
auth_resource_server_url=os.getenv("AUTH_RESOURCE_SERVER_URL"),
_audience=os.getenv("AUTH_AUDIENCE"),
auth_required_scopes=["user"],
)
```
--------------------------------
### Get User Subject Identifier in Python
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/user-context/index.mdx
This code retrieves the user identifier from the JWT sub claim. It uses the subject property of UserContext. Outputs the user ID string for fetching additional data. Assumes user is authenticated; returns None if not.
```python
user_id = user.subject # e.g., "auth0|123456"
user_data = fetch_user_data(user_id)
```
--------------------------------
### Logging Authentication Events in Python
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/advanced/index.mdx
Logs access to sensitive data for auditing purposes using logging module. Applies in sensitive widget execute. Inputs user and action, outputs logged event and data. Limitations: Requires logging setup.
```python
import logging
@auth_required
class SensitiveWidget(BaseWidget):
async def execute(self, input_data, context, user: UserContext):
# Log access for audit trail
logging.info(
f"Sensitive data accessed: user={user.subject}, "
f"action={input_data.action}, "
f"timestamp={datetime.utcnow()}"
)
return {"data": "..."}
```
--------------------------------
### Send follow-up messages to ChatGPT conversation in TSX
Source: https://github.com/dooilabs/fastapps_docs/blob/main/widgets/advanced-patterns/index.mdx
Widgets can inject follow-up messages into the ongoing ChatGPT dialogue using window.openai.sendFollowUpMessage. Inputs are message prompts; outputs trigger conversational updates seamlessly. Requires widget setup and may depend on conversation context.
```tsx
export default function InteractiveWidget() {
const props = useWidgetProps();
const handleAskMore = async (item) => {
await window.openai.sendFollowUpMessage({
prompt: `Tell me more about ${item.name}`
});
};
return (
{props.items.map((item) => (
{item.name}
))}
);
}
```
--------------------------------
### Configure FastApps MCP Server with Okta using Python
Source: https://github.com/dooilabs/fastapps_docs/blob/main/auth/providers/index.mdx
This code snippet sets up a WidgetMCPServer for OAuth authentication with Okta. It depends on the FastApps library, accepts auth_issuer_url, auth_resource_server_url, and scopes, and returns a configured server. Note: Limited to Okta authorization server setup.
```python
server = WidgetMCPServer(
name="my-widgets",
widgets=tools,
auth_issuer_url="https://dev-12345.okta.com/oauth2/default",
auth_resource_server_url="https://yourdomain.com/mcp",
auth_required_scopes=["user"],
)
```
--------------------------------
### Use useWidgetProps Hook in React (TypeScript)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/widgets/react-hooks/index.mdx
This example demonstrates how to retrieve widget properties provided by the MCP tool using the useWidgetProps hook. It imports the hook, defines a TypeScript interface for the expected props, and renders the data in a React component. Works in the FastApps environment and requires the fastapps package.
```tsx
import { useWidgetProps } from 'fastapps';
interface MyWidgetProps {
message: string;
count: number;
items: string[];
}
export default function MyWidget() {
const props = useWidgetProps();
return (
{props.message}
Count: {props.count}
{props.items.map((item) => (
{item}
))}
);
}
```
--------------------------------
### Async Concurrently Fetch Weather Data (Python)
Source: https://github.com/dooilabs/fastapps_docs/blob/main/server/advanced/index.mdx
Demonstrates using asyncio/aiohttp with BaseWidget to fetch multiple weather sources concurrently for a city. Aggregates results and returns combined weather summary. Dependencies: fastapps, aiohttp, and a custom WeatherInput schema.
```python
import asyncio
import aiohttp
from fastapps import BaseWidget
class AsyncWeatherWidget(BaseWidget):
identifier = "async_weather"
title = "Async Weather Widget"
input_schema = WeatherInput
invoking = "Fetching weather data…"
invoked = "Weather data ready!"
async def execute(self, inputs: WeatherInput, ctx):
async with aiohttp.ClientSession() as session:
# Fetch multiple weather sources concurrently
tasks = [
self.fetch_weather(session, inputs.city, "openweather"),
self.fetch_weather(session, inputs.city, "weather_api"),
self.fetch_weather(session, inputs.city, "accuweather")
]
results = await asyncio.gather(*tasks, return_exceptions=True)
return {
"city": inputs.city,
"sources": len([r for r in results if not isinstance(r, Exception)]),
"weather": self.merge_weather_data(results)
}
async def fetch_weather(self, session, city, provider):
# Implementation details...
pass
```
--------------------------------
### Generate New FastApps Widget
Source: https://context7.com/dooilabs/fastapps_docs/llms.txt
Creates scaffolding for a new widget named "my-widget", generating both the Python backend tool and the React frontend component. This command accelerates development by providing ready‑made file structures. It requires an initialized FastApps project.
```bash
# Create a new widget named "my-widget"
fastapps create my-widget
```