### Copy Environment Files Source: https://github.com/chipgpt/full-stack-saas-mcp/blob/main/README.md Copy the example environment file to create configurations for different environments. This is a prerequisite before installing dependencies or starting the application. ```bash cp .env .env.{{username}} cp .env .env.development cp .env .env.production ``` -------------------------------- ### Install Dependencies Source: https://github.com/chipgpt/full-stack-saas-mcp/blob/main/README.md Install all project dependencies using npm. This command should be run after copying the environment files. ```bash npm install ``` -------------------------------- ### Start Local Development Server Source: https://github.com/chipgpt/full-stack-saas-mcp/blob/main/README.md Start the local development server using SST. This command deploys resources to AWS and runs your code locally, with live updates. ```bash npx sst dev ``` -------------------------------- ### Start Local PostgreSQL Database Source: https://github.com/chipgpt/full-stack-saas-mcp/blob/main/README.md Start a local PostgreSQL database instance using Docker. This is required for local development. ```bash npm run docker:up ``` -------------------------------- ### MCP Server - Get Profile Tool Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt MCP tool for retrieving user profile information. Requires OAuth 2.1 authentication with 'read' scope. ```APIDOC ## POST /mcp ### Description MCP tool endpoint to retrieve user profile information using a JSON-RPC 2.0 request. ### Method POST ### Endpoint /mcp ### Parameters #### Headers - **Content-Type** (string) - Required. Must be 'application/json'. - **Authorization** (string) - Required. Bearer token for OAuth 2.1 authentication (e.g., 'Bearer your-oauth-access-token'). Requires 'read' scope. - **mcp-session-id** (string) - Required. A unique session identifier (UUID). #### Request Body - **jsonrpc** (string) - Required. Must be '2.0'. - **id** (integer) - Required. The request ID. - **method** (string) - Required. Must be 'tools/call'. - **params** (object) - Required. Parameters for the tool call. - **name** (string) - Required. The name of the tool, 'get-profile'. - **arguments** (object) - Required. An empty object for the 'get-profile' tool. ### Request Example ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get-profile", "arguments": {} } } ``` ### Response #### Success Response (200 OK) - **jsonrpc** (string) - '2.0'. - **id** (integer) - The request ID. - **result** (object) - The result of the tool call. - **structuredContent** (object) - Structured profile data. - **profile** (object) - User profile details. - **id** (string) - The user's unique identifier. - **name** (string) - The user's name. - **email** (string) - The user's email address. - **context** (string) - A brief description of the user's context or interests. - **content** (array) - An array of content objects, typically text. - **type** (string) - The type of content (e.g., 'text'). - **text** (string) - The textual content. #### Response Example ```json { "jsonrpc": "2.0", "id": 1, "result": { "structuredContent": { "profile": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "John Doe", "email": "john@example.com", "context": "TypeScript developer interested in AI" } }, "content": [ { "type": "text", "text": "Here is your profile information." } ] } } ``` ``` -------------------------------- ### MCP Server - Get Profile Tool Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Utilizes an MCP tool to retrieve user profile information. Requires OAuth 2.1 authentication with 'read' scope and specific headers for the request. ```typescript // MCP Tool: get-profile // Requires OAuth scope: read // MCP Request (JSON-RPC 2.0) const mcpRequest = { jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: 'get-profile', arguments: {}, }, }; // Send to MCP endpoint const response = await fetch('https://mcp.chipgpt.biz/mcp', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer your-oauth-access-token', 'mcp-session-id': 'session-uuid', }, body: JSON.stringify(mcpRequest), }); // MCP Response const mcpResponse = await response.json(); // { // "jsonrpc": "2.0", // "id": 1, // "result": { // "structuredContent": { // "profile": { // "id": "550e8400-e29b-41d4-a716-446655440000", // "name": "John Doe", // "email": "john@example.com", // "context": "TypeScript developer interested in AI" // } // }, // "content": [ // { // "type": "text", // "text": "Here is your profile information." // } // ] // } // } ``` -------------------------------- ### Retrieve Vault Game Info with MCP Tool Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Use this tool to get the current vault game information. Requires OAuth 2.1 authentication with the 'read' scope. The request body is minimal, primarily for authentication. ```typescript // MCP Tool: get-vault // Requires OAuth scope: read const mcpRequest = { jsonrpc: '2.0', id: 3, method: 'tools/call', params: { name: 'get-vault', arguments: {}, }, }; const response = await fetch('https://mcp.chipgpt.biz/mcp/vault', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer your-oauth-access-token', 'mcp-session-id': 'session-uuid', }, body: JSON.stringify(mcpRequest), }); // MCP Response const mcpResponse = await response.json(); // { // "jsonrpc": "2.0", // "id": 3, // "result": { // "structuredContent": { // "vault": { // "id": "vault-uuid", // "name": "Weekly Prize Vault", // "min": 1, // "max": 999999, // "value": 1000, // "openedAt": null, // "guessed": false // } // }, // "content": [ // { // "type": "text", // "text": "Here is the current vault information." // } // ] // } // } ``` -------------------------------- ### Get OAuth Client Information Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Retrieve public information about a registered OAuth client by its ID. ```APIDOC ## GET /api/oauth/client ### Description Retrieve public information about a registered OAuth client by its ID. ### Method GET ### Endpoint /api/oauth/client ### Parameters #### Query Parameters - **id** (string) - Required - The unique identifier of the OAuth client. ### Request Example ```http GET /api/oauth/client?id=your-client-id HTTP/1.1 Host: chipgpt.biz ``` ### Response #### Success Response (200 OK) - **data** (object) - An object containing client details. - **id** (string) - The client ID. - **redirectUris** (array) - An array of registered redirect URIs. - **scope** (array) - An array of scopes the client is authorized for. - **name** (string) - The name of the client application. - **uri** (string) - The URI of the client application. #### Response Example ```json { "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "redirectUris": ["https://myapp.com/callback"], "scope": ["read", "write"], "name": "My Application", "uri": "https://myapp.com" } } ``` #### Error Response (400 Bad Request) - **error** (string) - A message indicating the error, e.g., 'Client ID is required'. #### Error Response Example ```json { "error": "Client ID is required" } ``` ``` -------------------------------- ### Handle Stripe Webhook Events Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Processes incoming Stripe webhook events for subscription lifecycle management. Includes example payload and callback handling after checkout. ```typescript // POST /webhook/stripe // Stripe webhook for subscription events // Stripe sends webhook for these events: // - customer.subscription.created // - customer.subscription.updated // - customer.subscription.deleted // Example webhook payload (sent by Stripe) const webhookPayload = { id: 'evt_1234567890', type: 'customer.subscription.created', data: { object: { id: 'sub_1234567890', customer: 'cus_1234567890', status: 'active', items: { data: [ { price: { id: 'price_starter_monthly', }, }, ], }, }, }, }; // GET /webhook/stripe?checkoutSessionId={id} // Callback after successful Stripe Checkout - updates user plan and redirects to dashboard // Usage from frontend window.location.href = 'https://chipgpt.biz/api/billing?plan=starter'; // User completes checkout // Stripe redirects to: /webhook/stripe?checkoutSessionId=cs_xxx // Handler updates user.plan = 'starter' // User redirected to /dashboard ``` -------------------------------- ### Get OAuth Client Information Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Retrieve public details about a registered OAuth client using its unique ID. Requires the `client_id` as a query parameter. Handles missing `client_id` with a 400 Bad Request error. ```typescript // GET /api/oauth/client?id={client_id} // Get client details const response = await fetch('https://chipgpt.biz/api/oauth/client?id=your-client-id'); // Response (200 OK) const client = await response.json(); // { // "data": { // "id": "550e8400-e29b-41d4-a716-446655440000", // "redirectUris": ["https://myapp.com/callback"], // "scope": ["read", "write"], // "name": "My Application", // "uri": "https://myapp.com" // } // } // Error Response (400 Bad Request) // { "error": "Client ID is required" } ``` -------------------------------- ### Get Vault Game Status Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Fetches the current status of the vault game, including prize value and previous guesses. Handles successful responses and errors. ```typescript // GET /api/vault // Get current vault game status const response = await fetch('https://chipgpt.biz/api/vault'); // Response (200 OK) const vault = await response.json(); // { // "data": { // "name": "Weekly Prize Vault", // "value": 1000, // "min": 1, // "max": 999999, // "guesses": [123456, 654321, 111111], // "winningVaultGuess": null // } // } // When vault is won // { // "data": { // "name": "Weekly Prize Vault", // "value": 1000, // "min": 1, // "max": 999999, // "guesses": [123456, 654321, 111111, 789012], // "winningVaultGuess": 789012 // } // } // Error Response (404) // { "error": "No vault info currently available" } ``` -------------------------------- ### GET /api/oauth/authorize - OAuth Authorization Code Flow Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Initiates the OAuth 2.1 authorization code flow. This endpoint is used after a user has authenticated via Cognito to obtain an authorization code, which can then be exchanged for access tokens. ```APIDOC ## GET /api/oauth/authorize ### Description Initiates the OAuth 2.1 authorization code flow. Requires user authentication via session. ### Method GET ### Endpoint /api/oauth/authorize ### Parameters #### Query Parameters - **client_id** (string) - Required - The client ID of the application requesting authorization. - **redirect_uri** (string) - Required - The URI to which the user will be redirected after authorization. - **response_type** (string) - Required - Must be set to 'code' for the authorization code flow. - **scope** (string) - Optional - A space-separated string of scopes requested by the client. - **state** (string) - Required - An opaque value used to maintain state between the request and callback, and to prevent CSRF attacks. - **code_challenge** (string) - Required - A challenge generated for Proof Key for Code Exchange (PKCE). - **code_challenge_method** (string) - Required - The method used to generate the code_challenge (e.g., 'S256'). ### Request Example ```typescript // Step 1: Redirect user to authorization endpoint const authUrl = new URL('https://chipgpt.biz/api/oauth/authorize'); authUrl.searchParams.set('client_id', 'your-client-id'); authUrl.searchParams.set('redirect_uri', 'https://myapp.com/callback'); authUrl.searchParams.set('response_type', 'code'); authUrl.searchParams.set('scope', 'read write'); authUrl.searchParams.set('state', 'random-state-string'); authUrl.searchParams.set('code_challenge', 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM'); authUrl.searchParams.set('code_challenge_method', 'S256'); window.location.href = authUrl.toString(); // Step 2: User is redirected back with authorization code // https://myapp.com/callback?code=AUTH_CODE&state=random-state-string ``` ### Response #### Success Response (Redirect) This endpoint initiates a redirect to the client's `redirect_uri` with an authorization code in the query parameters. #### Response Example (Callback) ```json { "authorizationCode": "abc123...", "expiresAt": "2024-01-15T12:00:00.000Z", "redirectUri": "https://myapp.com/callback", "scope": ["read", "write"] } ``` ``` -------------------------------- ### Log in to AWS SSO Source: https://github.com/chipgpt/full-stack-saas-mcp/blob/main/README.md Execute this command to log in to your AWS SSO. Ensure you have configured AWS SSO in your ~/.aws/config. ```bash npm run sso ``` -------------------------------- ### Initialize and Manage MCP Session Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Initializes an MCP session, lists available tools, and demonstrates how to delete the session. Requires an OAuth access token for authorization. ```typescript // Initialize MCP Session const initRequest = { jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2024-11-05', capabilities: { roots: { listChanged: true }, sampling: {}, }, clientInfo: { name: 'my-mcp-client', version: '1.0.0', }, }, }; const initResponse = await fetch('https://mcp.chipgpt.biz/mcp', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer your-oauth-access-token', }, body: JSON.stringify(initRequest), }); // Session ID returned in response header const sessionId = initResponse.headers.get('mcp-session-id'); // Use this session ID for subsequent requests // List available tools const listToolsRequest = { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {}, }; const toolsResponse = await fetch('https://mcp.chipgpt.biz/mcp', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer your-oauth-access-token', 'mcp-session-id': sessionId, }, body: JSON.stringify(listToolsRequest), }); // Tools list response includes: get-profile, update-profile // Vault endpoint includes: get-vault, submit-vault-combination // Delete session await fetch('https://mcp.chipgpt.biz/mcp', { method: 'DELETE', headers: { 'mcp-session-id': sessionId, 'Authorization': 'Bearer your-oauth-access-token', }, }); ``` -------------------------------- ### NextAuth Configuration with Cognito Provider Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Sets up NextAuth with the Cognito provider, including event handlers for user creation and integration with AWS resources. Requires `next-auth` and `sst` packages. ```typescript // src/auth.config.ts import NextAuth, { NextAuthConfig } from 'next-auth'; import Cognito from 'next-auth/providers/cognito'; import { Resource } from 'sst'; import SequelizeAdapter from './lib/@auth/sequelize-adapter'; export const nextAuthConfig: NextAuthConfig = { callbacks: { session: async ({ session }) => session, }, events: { // Send welcome email to new users createUser: async ({ user }) => { if (user.email) { await sendMailgunEmail(user.email, 'Welcome to ChipGPT', 'Welcome!', 'Welcome body'); } }, }, providers: [ Cognito({ clientId: Resource.MyUserPoolClient.id, clientSecret: Resource.MyUserPoolClient.secret, issuer: `https://cognito-idp.us-east-1.amazonaws.com/${Resource.MyUserPool.id}`, }), ], }; // With Sequelize adapter for database persistence export const getNextAuthConfig = async (): Promise => { const sequelize = new Sequelize({ /* connection config */ }); return { ...nextAuthConfig, adapter: SequelizeAdapter(sequelize, { models: { User: InitUserModel(sequelize) }, synchronize: true, }), }; }; // Usage in API routes import { auth } from '@/auth'; export async function GET() { const session = await auth(); if (!session?.user) { return Response.json({ error: 'Unauthenticated' }, { status: 401 }); } // Access session.user.id, session.user.email, session.user.plan, etc. } ``` -------------------------------- ### Create OAuth Client Programmatically Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Use this to programmatically create an OAuth client with specified grants and scopes. Client ID and secret are auto-generated. ```typescript // src/server/models/oauth-client.ts import { OAuthClient, OAuthClientGrantEnum, OAuthClientScopeEnum, } from '@/server/models/oauth-client'; // Available grant types enum OAuthClientGrantEnum { AuthorizationCode = 'authorization_code', RefreshToken = 'refresh_token', } // Available scopes enum OAuthClientScopeEnum { Read = 'read', // Read user data, vault info Write = 'write', // Update profile, submit vault guesses } // Create OAuth client programmatically const client = await OAuthClient.create({ name: 'My ChatGPT App', uri: 'https://myapp.com', redirectUris: ['https://myapp.com/callback'], grants: [OAuthClientGrantEnum.AuthorizationCode, OAuthClientGrantEnum.RefreshToken], scope: [OAuthClientScopeEnum.Read, OAuthClientScopeEnum.Write], accessTokenLifetime: 7 * 24 * 60 * 60, // 7 days refreshTokenLifetime: 30 * 24 * 60 * 60, // 30 days }); // Client ID and secret are auto-generated UUIDs console.log(client.id, client.secret); // Find client for validation const existingClient = await OAuthClient.findOne({ where: { id: clientId, secret: clientSecret }, }); ``` -------------------------------- ### Stripe Customer and Subscription Management Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Provides utility functions for server-side Stripe integration, including customer creation, checkout session generation, and subscription retrieval. Requires Stripe API keys and price/coupon IDs. ```typescript // src/server/utils/stripe.ts import { createCheckoutSession, createManagementSession, createCustomer, getCustomer, getSubscriptions, getCheckoutSession, } from '@/server/utils/stripe'; // Create a new Stripe customer const customer = await createCustomer({ id: 'user-uuid', email: 'user@example.com', }); // Returns: { id: 'cus_xxx', email: 'user@example.com', ... } // Create checkout session for new subscription const checkoutSession = await createCheckoutSession( 'cus_xxx', // Stripe customer ID 'price_starter', // Stripe price ID 'coupon_discount', // Optional coupon code 'user-uuid' // User ID for reference ); // Returns Stripe Checkout Session with .url for redirect // Create billing portal session for existing subscribers const portalSession = await createManagementSession('cus_xxx'); // Returns session with .url for Stripe Billing Portal // Get customer's active subscriptions const subscriptions = await getSubscriptions('cus_xxx'); // Returns array of Subscription objects // Get all subscriptions including canceled const allSubscriptions = await getSubscriptions('cus_xxx', true); // Get checkout session details (for webhook callback) const session = await getCheckoutSession('cs_xxx'); // Returns expanded session with customer and subscription details ``` -------------------------------- ### SST Infrastructure Configuration Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Configure AWS infrastructure using SST, including Cognito, Next.js app, ECS service, and DynamoDB. Environment variables are set here. ```typescript // sst.config.ts export default $config({ app(input) { return { name: 'chipgpt', removal: input.stage === 'production' ? 'retain' : 'remove', home: 'aws', providers: { aws: { version: '6.66.2' }, mailgun: '3.5.10', stripe: '0.0.24', }, }; }, async run() { // Environment variables const environment = { NODE_ENV: process.env.NODE_ENV || 'development', DATABASE_URL: process.env.DATABASE_URL || '', WEB_URL: process.env.WEB_URL || 'http://localhost:3000', }; // Cognito User Pool for authentication const pool = new sst.aws.CognitoUserPool('MyUserPool', { usernames: ['email'], }); const client = pool.addClient('MyUserPoolClient'); // Next.js web application const nextjs = new sst.aws.Nextjs('MyWeb', { environment: { ...environment, AUTH_SECRET: process.env.AUTH_SECRET }, link: [pool, client], domain: process.env.CUSTOM_DOMAIN ? { name: process.env.CUSTOM_DOMAIN } : undefined, }); // MCP Server on ECS const vpc = new sst.aws.Vpc('MyVpc', { nat: 'ec2' }); const cluster = new sst.aws.Cluster('MyCluster', { vpc }); const mcpService = new sst.aws.Service('MyMcpService', { cluster, image: { dockerfile: './Dockerfile.mcp' }, loadBalancer: { rules: [{ listen: '443/https', forward: '3333/http' }] }, cpu: '0.5 vCPU', memory: '1 GB', }); // DynamoDB for MCP session cache const sessionCache = new sst.aws.Dynamo('MyDynamoMCPSessionCache', { fields: { sessionId: 'string' }, primaryIndex: { hashKey: 'sessionId' }, ttl: 'expiresAt', }); return { web_url: nextjs.url, service_mcp_url: mcpService.url, }; }, }); ``` -------------------------------- ### Redirect to Stripe Checkout or Billing Portal Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Redirects users to Stripe for either checkout (new subscribers) or the billing portal (existing subscribers). Use `redirect: 'manual'` to prevent automatic redirection. ```typescript // GET /api/billing?plan=starter // Redirect to Stripe checkout or billing management // For new subscribers - redirects to Stripe Checkout const checkoutResponse = await fetch('https://chipgpt.biz/api/billing?plan=starter', { redirect: 'manual', // Don't auto-follow redirects }); // Returns 302 redirect to Stripe Checkout URL // For existing subscribers - redirects to Stripe Billing Portal const portalResponse = await fetch('https://chipgpt.biz/api/billing', { redirect: 'manual', }); // Returns 302 redirect to Stripe Billing Portal URL // Error responses // { "error": "Unauthenticated" } (401) // { "error": "Unable to access billing at this time" } (400) ``` -------------------------------- ### Register New OAuth 2.1 Client Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Use this endpoint to dynamically register new OAuth clients. It requires a JSON payload specifying redirect URIs, token endpoint authentication method, grant types, response types, client name, URI, and scope. ```typescript // POST /api/oauth/register // Register a new OAuth client // Request const response = await fetch('https://chipgpt.biz/api/oauth/register', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ redirect_uris: ['https://myapp.com/callback', 'http://localhost:3000/callback'], token_endpoint_auth_method: 'client_secret_basic', grant_types: ['authorization_code', 'refresh_token'], response_types: ['code'], client_name: 'My Application', client_uri: 'https://myapp.com', scope: 'read write', }), }); // Response (201 Created) const client = await response.json(); // { // "client_id": "550e8400-e29b-41d4-a716-446655440000", // "client_secret": "7c9e6679-7425-40de-944b-e07fc1f90ae7", // "client_id_issued_at": 1699900000, // "client_secret_expires_at": 0, // "redirect_uris": ["https://myapp.com/callback", "http://localhost:3000/callback"], // "grants": ["authorization_code", "refresh_token"], // "scope": "read write", // "client_name": "My Application", // "client_uri": "https://myapp.com" // } ``` -------------------------------- ### POST /api/oauth/register - Register OAuth Client Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Dynamically registers new OAuth clients. This endpoint allows for the creation of OAuth clients by specifying their redirect URIs, grant types, and scopes, facilitating the authorization code flow. ```APIDOC ## POST /api/oauth/register ### Description Registers a new OAuth client with specified configurations. ### Method POST ### Endpoint /api/oauth/register ### Parameters #### Request Body - **redirect_uris** (array[string]) - Required - An array of valid redirect URIs for the client. - **token_endpoint_auth_method** (string) - Optional - The method used to authenticate the client at the token endpoint (e.g., 'client_secret_basic'). - **grant_types** (array[string]) - Required - An array of grant types supported by the client (e.g., 'authorization_code', 'refresh_token'). - **response_types** (array[string]) - Required - An array of response types supported by the client (e.g., 'code'). - **client_name** (string) - Optional - The human-readable name of the client. - **client_uri** (string) - Optional - The URI of the client's website. - **scope** (string) - Optional - A space-separated string of scopes the client is requesting. ### Request Example ```json { "redirect_uris": ["https://myapp.com/callback", "http://localhost:3000/callback"], "token_endpoint_auth_method": "client_secret_basic", "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"], "client_name": "My Application", "client_uri": "https://myapp.com", "scope": "read write" } ``` ### Response #### Success Response (201 Created) - **client_id** (string) - The unique identifier for the registered client. - **client_secret** (string) - The secret associated with the client. - **client_id_issued_at** (integer) - The timestamp when the client ID was issued. - **client_secret_expires_at** (integer) - The timestamp when the client secret expires (0 if never). - **redirect_uris** (array[string]) - The registered redirect URIs. - **grants** (array[string]) - The grant types supported by the client. - **scope** (string) - The scopes granted to the client. - **client_name** (string) - The name of the client. - **client_uri** (string) - The URI of the client. #### Response Example ```json { "client_id": "550e8400-e29b-41d4-a716-446655440000", "client_secret": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "client_id_issued_at": 1699900000, "client_secret_expires_at": 0, "redirect_uris": ["https://myapp.com/callback", "http://localhost:3000/callback"], "grants": ["authorization_code", "refresh_token"], "scope": "read write", "client_name": "My Application", "client_uri": "https://myapp.com" } ``` ``` -------------------------------- ### Update User Profile with MCP Tool Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Use this tool to update a user's profile context. Requires OAuth 2.1 authentication with the 'write' scope. Ensure your access token and session ID are correctly provided. ```typescript // MCP Tool: update-profile // Requires OAuth scope: write const mcpRequest = { jsonrpc: '2.0', id: 2, method: 'tools/call', params: { name: 'update-profile', arguments: { context: 'I prefer TypeScript with strict mode enabled. Focus on functional patterns.', }, }, }; const response = await fetch('https://mcp.chipgpt.biz/mcp', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer your-oauth-access-token', 'mcp-session-id': 'session-uuid', }, body: JSON.stringify(mcpRequest), }); // MCP Response const mcpResponse = await response.json(); // { // "jsonrpc": "2.0", // "id": 2, // "result": { // "structuredContent": { // "success": true, // "message": "Profile updated successfully" // }, // "content": [ // { // "type": "text", // "text": "{\"success\":true,\"message\":\"Profile updated successfully\"}" // } // ] // } // } ``` -------------------------------- ### Sequelize User Model and Profile Schema Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Defines the Sequelize User model and associated interfaces for managing user data, including profile context for AI personalization. Supports finding and updating user information. ```typescript // src/server/models/user.ts import { User, IUser, IUserProfile } from '@/server/models/user'; // User interface interface IUser { id: string; name: string | null; email: string | null; emailVerified: Date | null; image: string | null; profile: IUserProfile; plan: string | null; // 'starter' | null stripeCustomerId: string | null; } interface IUserProfile { context: string; // AI personalization context } // Find user by ID const user = await User.findOne({ where: { id: 'user-uuid' }, }); // Update user profile await user.update( { profile: { context: 'User preferences and context for AI interactions', }, }, { fields: ['profile'] } ); // Find user by Stripe customer ID const userByStripe = await User.findOne({ where: { stripeCustomerId: 'cus_xxx' }, }); // Update subscription plan await user.update({ plan: 'starter' }, { fields: ['plan'] }); ``` -------------------------------- ### Exchange Authorization Code for Tokens (OAuth 2.1) Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Use this endpoint to exchange an authorization code for access and refresh tokens. Supports PKCE. Ensure the `redirect_uri` matches the one used during the authorization request. ```typescript // POST /api/oauth/token // Exchange authorization code for tokens const response = await fetch('https://chipgpt.biz/api/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ grant_type: 'authorization_code', code: 'AUTH_CODE_FROM_CALLBACK', redirect_uri: 'https://myapp.com/callback', client_id: 'your-client-id', client_secret: 'your-client-secret', code_verifier: 'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk', }), }); // Response (200 OK) const tokens = await response.json(); // { // "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...", // "token_type": "Bearer", // "expires_in": 604800, // "scope": "read write" // } // Refresh token exchange const refreshResponse = await fetch('https://chipgpt.biz/api/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ grant_type: 'refresh_token', refresh_token: tokens.refresh_token, client_id: 'your-client-id', client_secret: 'your-client-secret', }), }); ``` -------------------------------- ### Stripe Webhook Handler Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Handle Stripe webhook events for subscription lifecycle management and process Stripe Checkout callbacks. ```APIDOC ## POST /webhook/stripe ### Description Receives webhook events from Stripe related to subscription lifecycle changes. ### Method POST ### Endpoint /webhook/stripe ### Parameters #### Request Body - **id** (string) - The unique ID of the event. - **type** (string) - The type of event (e.g., 'customer.subscription.created'). - **data** (object) - Contains the event data. - **object** (object) - The Stripe object related to the event. - **id** (string) - The ID of the subscription or object. - **customer** (string) - The ID of the customer. - **status** (string) - The status of the subscription (e.g., 'active'). - **items** (object) - Details about the subscription items. - **data** (array) - Array of subscription items. - **price** (object) - Details about the price. - **id** (string) - The ID of the price. ### Request Example ```json { "id": "evt_1234567890", "type": "customer.subscription.created", "data": { "object": { "id": "sub_1234567890", "customer": "cus_1234567890", "status": "active", "items": { "data": [ { "price": { "id": "price_starter_monthly" } } ] } } } } ``` ### Response #### Success Response (200 OK) - Typically returns a 200 OK status to acknowledge receipt of the webhook. ## GET /webhook/stripe ### Description Callback endpoint after a successful Stripe Checkout. It updates the user's plan and redirects them to their dashboard. ### Method GET ### Endpoint /webhook/stripe ### Parameters #### Query Parameters - **checkoutSessionId** (string) - Required. The ID of the completed Stripe Checkout session. ### Request Example ```http GET /webhook/stripe?checkoutSessionId=cs_xxx HTTP/1.1 Host: chipgpt.biz ``` ### Response #### Success Response (Redirect) - Redirects the user to their dashboard (e.g., /dashboard) after updating their plan. #### Usage Example (Frontend) ```javascript window.location.href = 'https://chipgpt.biz/api/billing?plan=starter'; // User completes checkout // Stripe redirects to: /webhook/stripe?checkoutSessionId=cs_xxx // Handler updates user.plan = 'starter' // User redirected to /dashboard ``` ``` -------------------------------- ### Submit Vault Combination Guess with MCP Tool Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Use this tool to submit a vault combination guess. This action is rate-limited to one guess per hour per user. Ensure the combination is an integer between 1 and 999999. ```typescript // MCP Tool: submit-vault-combination // Requires OAuth scope: write const mcpRequest = { jsonrpc: '2.0', id: 4, method: 'tools/call', params: { name: 'submit-vault-combination', arguments: { combination: 123456, // Integer between 1 and 999999 }, }, }; const response = await fetch('https://mcp.chipgpt.biz/mcp/vault', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer your-oauth-access-token', 'mcp-session-id': 'session-uuid', }, body: JSON.stringify(mcpRequest), }); // Success Response (incorrect guess) // { // "jsonrpc": "2.0", // "id": 4, // "result": { // "structuredContent": { "success": false }, // "content": [{ "type": "text", "text": "{\"success\":false}" }] // } // } // Success Response (correct guess - vault opened!) // { // "jsonrpc": "2.0", // "id": 4, // "result": { // "structuredContent": { "success": true }, // "content": [{ "type": "text", "text": "{\"success\":true}" }] // } // } // Error: Already guessed this hour // "You have already submitted a guess for this hour to this vault. You can submit again at 2024-01-15T13:00:00.000Z" // Error: Combination already tried // "That combination has already been submitted to this vault. Try a different combination." ``` -------------------------------- ### Troubleshooting SST Dev Error Source: https://github.com/chipgpt/full-stack-saas-mcp/blob/main/README.md If you encounter an unexpected error when running 'npx sst dev', it might be due to expired AWS SSO credentials. Re-run 'npm run sso' to reauthorize. ```bash ✕ Unexpected error occurred. Please run with --print-logs or check .sst/log/sst.log if available. ``` -------------------------------- ### OAuth 2.1 Token Exchange Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Exchange an authorization code for access and refresh tokens. Supports PKCE (Proof Key for Code Exchange) for enhanced security. ```APIDOC ## POST /api/oauth/token ### Description Exchange an authorization code for access and refresh tokens. Supports PKCE (Proof Key for Code Exchange) for enhanced security. ### Method POST ### Endpoint /api/oauth/token ### Parameters #### Request Body - **grant_type** (string) - Required - Specifies the grant type. Use 'authorization_code' for initial token exchange or 'refresh_token' to refresh existing tokens. - **code** (string) - Required (for authorization_code grant type) - The authorization code received from the authorization server. - **redirect_uri** (string) - Required (for authorization_code grant type) - The redirect URI previously registered with the authorization server. - **client_id** (string) - Required - The client ID of your application. - **client_secret** (string) - Required - The client secret of your application. - **code_verifier** (string) - Required (for PKCE) - The code verifier used during the authorization request. - **refresh_token** (string) - Required (for refresh_token grant type) - The refresh token to obtain a new access token. ### Request Example ```json { "grant_type": "authorization_code", "code": "AUTH_CODE_FROM_CALLBACK", "redirect_uri": "https://myapp.com/callback", "client_id": "your-client-id", "client_secret": "your-client-secret", "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" } ``` ### Response #### Success Response (200 OK) - **access_token** (string) - The access token for authenticating API requests. - **refresh_token** (string) - The refresh token for obtaining new access tokens. - **token_type** (string) - The type of token, typically 'Bearer'. - **expires_in** (integer) - The lifetime in seconds of the access token. - **scope** (string) - The scopes granted to the access token. #### Response Example ```json { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...", "token_type": "Bearer", "expires_in": 604800, "scope": "read write" } ``` ``` -------------------------------- ### OAuth 2.1 Token Authentication Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Authenticate requests using OAuth access tokens. Returns user information for valid tokens. ```APIDOC ## GET /api/oauth/authenticate ### Description Validate an access token and retrieve associated user information. ### Method GET ### Endpoint /api/oauth/authenticate ### Parameters #### Headers - **Authorization** (string) - Required - The access token in the format 'Bearer YOUR_ACCESS_TOKEN'. ### Request Example ```http GET /api/oauth/authenticate HTTP/1.1 Host: chipgpt.biz Authorization: Bearer your-access-token ``` ### Response #### Success Response (200 OK) - **id** (string) - The unique identifier of the user. - **name** (string) - The name of the user. - **profile** (object) - An object containing user profile details. - **context** (string) - User-defined context or description. #### Response Example ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "John Doe", "profile": { "context": "I'm a software developer interested in AI tools." } } ``` #### Error Response (401 Unauthorized) - **error** (string) - Error code, e.g., 'invalid_token'. - **error_description** (string) - A human-readable description of the error. #### Error Response Example ```json { "error": "invalid_token", "error_description": "Access token not found" } ``` ``` -------------------------------- ### Billing Portal API Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt Redirect users to Stripe checkout or billing portal based on their subscription status. ```APIDOC ## GET /api/billing ### Description Redirects users to Stripe Checkout for new subscriptions or the Stripe Billing Portal for existing subscribers. ### Method GET ### Endpoint /api/billing ### Parameters #### Query Parameters - **plan** (string) - Optional. Specifies the subscription plan (e.g., 'starter'). If provided, redirects to Stripe Checkout. If omitted, redirects to the Stripe Billing Portal. ### Request Example ```http GET /api/billing?plan=starter HTTP/1.1 Host: chipgpt.biz ``` ```http GET /api/billing HTTP/1.1 Host: chipgpt.biz ``` ### Response #### Success Response (302 Redirect) - Redirects to a Stripe URL (Checkout or Billing Portal). #### Error Response (401) - **error** (string) - Message indicating the user is unauthenticated. #### Error Response Example (401) ```json { "error": "Unauthenticated" } ``` #### Error Response (400) - **error** (string) - Message indicating an issue accessing billing. #### Error Response Example (400) ```json { "error": "Unable to access billing at this time" } ``` ``` -------------------------------- ### Update User Profile Context Source: https://context7.com/chipgpt/full-stack-saas-mcp/llms.txt This API allows updating the user's profile context information. Authentication is handled automatically via session cookies (NextAuth/Cognito). The request body must be JSON and adhere to a maximum character limit for the context. ```typescript // POST /api/user // Update user profile context const response = await fetch('https://chipgpt.biz/api/user', { method: 'POST', headers: { 'Content-Type': 'application/json', // Session cookie is automatically included }, body: JSON.stringify({ context: 'I am a TypeScript developer focused on serverless architectures. I prefer functional programming patterns.', }), }); // Response (200 OK) const result = await response.json(); // { // "data": { // "id": "550e8400-e29b-41d4-a716-446655440000", // "name": "John Doe", // "email": "john@example.com", // "profile": { // "context": "I am a TypeScript developer focused on serverless architectures. I prefer functional programming patterns." // } // } // } // Error Response (401) // { "error": "Unauthenticated" } // Validation Error (400) // { "error": "Max 500 characters" } ```