### Install and Configure Pons (Bash) Source: https://github.com/nicolaischmid/pons/blob/main/README.md This snippet outlines the initial setup steps for Pons, including cloning the repository, installing dependencies using pnpm, and starting the Convex development server and the Next.js development server. ```bash git clone https://github.com/NicolaiSchmid/pons.git cd pons pnpm install # Start Convex dev (opens browser for auth on first run) npx convex dev # In another terminal pnpm run dev:next ``` -------------------------------- ### Install Dependencies and Start Development Servers Source: https://github.com/nicolaischmid/pons/blob/main/AGENTS.md Commands to install project dependencies, set up the Convex development environment, and start the Next.js development server. These are essential steps for local development. ```bash # Install dependencies pnpm install # Set up Convex npx convex dev # In another terminal, start Next.js pnpm dev ``` -------------------------------- ### Set Up Pons with Convex and Vercel (Bash) Source: https://context7.com/nicolaischmid/pons/llms.txt This bash script outlines the steps for self-hosting the Pons project using Convex and Vercel. It covers cloning the repository, installing dependencies, starting the Convex development server, configuring environment variables, and deploying to Vercel. Ensure Node.js 18+ is installed. ```bash # 1. Clone and install git clone https://github.com/NicolaiSchmid/pons.git cd pons pnpm install # 2. Start Convex (creates new project on first run) npx convex dev # 3. Create .env.local cat > .env.local << EOF NEXT_PUBLIC_CONVEX_URL=https://your-deployment.convex.cloud CONVEX_AUTH_SECRET=$(openssl rand -base64 32) EOF # 4. Set Convex environment variables (in Convex dashboard) # CONVEX_AUTH_SECRET - same as .env.local # AUTH_GOOGLE_ID - from Google Cloud Console # AUTH_GOOGLE_SECRET - from Google Cloud Console # 5. Run development servers pnpm dev # Runs both Convex and Next.js in parallel # 6. Deploy to Vercel # Set environment variables: # - NEXT_PUBLIC_CONVEX_URL # - CONVEX_DEPLOY_KEY (from Convex dashboard) # Build command: pnpm convex deploy --cmd 'pnpm run build' # IMPORTANT: Disable Deployment Protection for /api/webhook ``` -------------------------------- ### Start Convex Development Server Source: https://github.com/nicolaischmid/pons/blob/main/content/docs/self-hosting.mdx Initiates the Convex development server, which also handles the initial deployment of your Convex schema. This command will typically open a browser window for authentication on its first run. Note the deployment URL provided upon successful setup. ```bash npx convex dev ``` -------------------------------- ### Clone and Install Pons Dependencies Source: https://github.com/nicolaischmid/pons/blob/main/content/docs/self-hosting.mdx This snippet demonstrates how to clone the Pons repository from GitHub and install its project dependencies using pnpm. Ensure you have Git and pnpm installed and configured on your system. ```bash git clone https://github.com/NicolaiSchmid/pons.git cd pons pnpm install ``` -------------------------------- ### WhatsApp Webhook POST Handler Example (TypeScript) Source: https://github.com/nicolaischmid/pons/blob/main/content/blog/whatsapp-cloud-api-webhook-nextjs.mdx An example of a Next.js POST handler that first reads the raw request body as text, validates the HMAC signature using `verifySignature`, and then parses the body as JSON for further processing. This approach ensures the signature is validated before the body is consumed. ```typescript import { NextRequest, NextResponse } from "next/server"; // Assuming verifySignature function is defined elsewhere or imported // async function verifySignature(req: NextRequest, body: string): Promise { ... } export async function POST(req: NextRequest) { const rawBody = await req.text(); if (!(await verifySignature(req, rawBody))) { return NextResponse.json( { error: "Invalid signature" }, { status: 401 } ); } const body = JSON.parse(rawBody); // ... process the webhook return NextResponse.json({ message: "Webhook received" }, { status: 200 }); } ``` -------------------------------- ### Run Pons Locally with Convex and Next.js Source: https://github.com/nicolaischmid/pons/blob/main/content/docs/self-hosting.mdx Starts both the Convex development server and the Next.js development server concurrently for local development. This allows you to test the application in real-time by visiting `http://localhost:3000` in your browser. ```bash # Terminal 1: Convex dev server npx convex dev # Terminal 2: Next.js dev server pnpm run dev:next ``` -------------------------------- ### API Key Format Example Source: https://github.com/nicolaischmid/pons/blob/main/content/docs/api-keys.mdx Illustrates the standard format for Pons API keys, which begins with 'pons_' followed by a random string. ```text pons_a1b2c3d4e5f6... ``` -------------------------------- ### Conventional Commits Example Source: https://github.com/nicolaischmid/pons/blob/main/AGENTS.md Illustrates the structure and examples of commit messages following the Conventional Commits specification. This standard helps in automating changelog generation and improving commit history readability. ```text (): [optional body] [optional footer(s)] **Types:** `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`, `ci` **Examples:** - `feat(webhook): add message status tracking` - `fix(mcp): handle media download timeout` - `docs: update API documentation` - `chore(deps): upgrade convex` ``` -------------------------------- ### Environment Variables Configuration Source: https://github.com/nicolaischmid/pons/blob/main/AGENTS.md Configures essential environment variables for Convex deployment and Next.js public URL. WhatsApp per-account credentials are also listed but are only needed for initial setup or single-tenant mode. ```env CONVEX_DEPLOYMENT=your-deployment-name NEXT_PUBLIC_CONVEX_URL=https://your-deployment.convex.cloud # WhatsApp (per-account credentials stored in Convex DB) # Only needed for initial setup or single-tenant mode: # WHATSAPP_ACCESS_TOKEN= # WHATSAPP_PHONE_NUMBER_ID= # WHATSAPP_VERIFY_TOKEN= # WHATSAPP_APP_SECRET= ``` -------------------------------- ### Call MCP Tool via cURL Source: https://github.com/nicolaischmid/pons/blob/main/content/blog/whatsapp-customer-support-ai-agents.mdx This example demonstrates how to call an MCP tool, specifically `list_unanswered`, using a cURL command. It requires specifying the endpoint, authorization token, and the method and parameters for the tool call. This is useful for interacting with MCP services from the command line or in scripts. ```bash curl -X POST https://pons.chat/api/mcp \ -H "Authorization: Bearer pons_your_key" \ -H "Content-Type: application/json" \ -d '{"method": "tools/call", "params": {"name": "list_unanswered"}}' ``` -------------------------------- ### Configure WhatsApp Business Account with Bash Source: https://context7.com/nicolaischmid/pons/llms.txt This bash snippet details the necessary credentials and webhook configurations for connecting a Meta Business App to Pons. It lists the required information from the Meta Developer Console, such as WABA ID, Phone Number ID, Access Token, and App Secret. It also outlines the webhook setup in the Meta Developer Console and the environment variable for verification. ```bash # Required credentials from Meta Developer Console: # 1. WABA ID - WhatsApp > Getting Started > WhatsApp Business Account ID # 2. Phone Number ID - WhatsApp > Getting Started > Phone number ID # 3. Access Token - Create permanent System User token with permissions: # - whatsapp_business_management # - whatsapp_business_messaging # 4. App Secret - App Settings > Basic > App Secret # Webhook configuration in Meta Developer Console: # Callback URL: https://your-domain.com/api/webhook # Verify Token: Generated by Pons when creating account # Subscribe to: messages (webhook field) # Environment variable for webhook verification: WEBHOOK_VERIFY_TOKEN=your_verify_token_here ``` -------------------------------- ### WhatsApp Webhook Verification with Next.js Source: https://github.com/nicolaischmid/pons/blob/main/content/blog/whatsapp-cloud-api-webhook-nextjs.mdx Handles the GET request from Meta for webhook verification. It checks the hub mode and verify token, returning the challenge token if valid. Requires WHATSAPP_VERIFY_TOKEN environment variable. ```typescript import { type NextRequest, NextResponse } from "next/server"; // GET — Webhook verification export async function GET(req: NextRequest) { const searchParams = req.nextUrl.searchParams; const mode = searchParams.get("hub.mode"); const token = searchParams.get("hub.verify_token"); const challenge = searchParams.get("hub.challenge"); // Your verify token — set this in Meta's developer console const verifyToken = process.env.WHATSAPP_VERIFY_TOKEN; if (mode === "subscribe" && token === verifyToken) { // Return the challenge as plain text return new NextResponse(challenge, { status: 200 }); } return NextResponse.json( { error: "Verification failed" }, { status: 403 } ); } ``` -------------------------------- ### MCP Server Configuration Source: https://context7.com/nicolaischmid/pons/llms.txt Configure your MCP client to connect to the Pons server endpoint with your API key. This includes examples for Claude Desktop, Cursor, and OpenCode. ```APIDOC ## MCP Server Configuration Configure your MCP client to connect to the Pons server endpoint with your API key. ### Example Configuration ```json { "mcpServers": { "pons": { "url": "https://pons.chat/api/mcp", "headers": { "Authorization": "Bearer pons_your_api_key_here" } } } } ``` ### Claude Desktop Configuration Edit the Claude Desktop config file to add the Pons MCP server. ```json // macOS: ~/Library/Application Support/Claude/claude_desktop_config.json // Windows: %APPDATA%\Claude\claude_desktop_config.json { "mcpServers": { "pons": { "url": "https://pons.chat/api/mcp", "headers": { "Authorization": "Bearer pons_your_api_key_here" } } } } ``` ### Cursor Configuration Configure Cursor's MCP settings in your project's `.cursor/mcp.json` file. ```json { "mcpServers": { "pons": { "url": "https://pons.chat/api/mcp", "headers": { "Authorization": "Bearer pons_your_api_key_here" } } } } ``` ### OpenCode Configuration Edit the OpenCode config file at `~/.config/opencode/config.json`. ```json { "mcp": { "pons": { "type": "remote", "url": "https://pons.chat/api/mcp", "headers": { "Authorization": "Bearer pons_your_api_key_here" } } } } ``` ``` -------------------------------- ### WhatsApp Incoming Message and Status Handling with Next.js Source: https://github.com/nicolaischmid/pons/blob/main/content/blog/whatsapp-cloud-api-webhook-nextjs.mdx Handles the POST request from Meta containing WhatsApp events. It parses incoming messages and status updates, logging them to the console. It's crucial to return a 200 status code quickly to avoid retries. ```typescript // POST — Receive webhook events export async function POST(req: NextRequest) { const body = await req.json(); // Every webhook has this structure: // body.entry[].changes[].value for (const entry of body.entry ?? []) { for (const change of entry.changes ?? []) { const value = change.value; // New messages if (value.messages) { for (const message of value.messages) { console.log("New message:", { from: message.from, // phone number type: message.type, // text, image, video, etc. text: message.text?.body, timestamp: message.timestamp, }); } } // Status updates (sent, delivered, read) if (value.statuses) { for (const status of value.statuses) { console.log("Status update:", { messageId: status.id, status: status.status, // sent, delivered, read recipientId: status.recipient_id, }); } } } } // Always return 200 quickly — Meta retries on failure return NextResponse.json({ status: "ok" }); } ``` -------------------------------- ### Download Media URL from WhatsApp Graph API (TypeScript) Source: https://github.com/nicolaischmid/pons/blob/main/content/blog/whatsapp-cloud-api-webhook-nextjs.mdx Fetches the download URL for WhatsApp media (images, videos, documents) using the Graph API. This function requires the media ID and an access token. The obtained URL is temporary and expires within 5 minutes, necessitating immediate download. ```typescript // Get media URL from Meta const mediaResponse = await fetch( `https://graph.facebook.com/v21.0/${mediaId}`, { headers: { Authorization: `Bearer ${accessToken}` } } ); const { url } = await mediaResponse.json(); // Download immediately — URL expires in 5 minutes const media = await fetch(url, { headers: { Authorization: `Bearer ${accessToken}` }, }); ``` -------------------------------- ### Handle WhatsApp Webhooks with TypeScript Source: https://context7.com/nicolaischmid/pons/llms.txt This snippet demonstrates how to set up a webhook endpoint to receive incoming messages and status updates from Meta's WhatsApp Cloud API. It includes details on signature verification using HMAC-SHA256 and provides an example payload structure. The endpoint requires specific headers for POST requests. ```typescript // Webhook URL: https://your-domain.com/api/webhook // GET - Webhook Verification (called by Meta during setup) // Request: GET /api/webhook?hub.mode=subscribe&hub.verify_token=YOUR_TOKEN&hub.challenge=CHALLENGE // Response: Returns the challenge string if token matches // POST - Incoming Messages and Status Updates // Headers required: x-hub-signature-256 (HMAC-SHA256 signature) // Example incoming message payload from Meta: { "object": "whatsapp_business_account", "entry": [{ "id": "WABA_ID", "changes": [{ "value": { "messaging_product": "whatsapp", "metadata": { "display_phone_number": "15551234567", "phone_number_id": "PHONE_NUMBER_ID" }, "contacts": [{ "profile": { "name": "Alice" }, "wa_id": "491234567890" }], "messages": [{ "id": "wamid.HBgNNDkxMjM0...", "from": "491234567890", "timestamp": "1705312200", "type": "text", "text": { "body": "Hello!" } }] }, "field": "messages" }] }] } ``` -------------------------------- ### Testing Webhooks Locally with ngrok Source: https://github.com/nicolaischmid/pons/blob/main/AGENTS.md Instructions for testing webhooks locally by exposing your local server to the internet using ngrok. This involves running ngrok and configuring the Meta webhook URL to point to your ngrok URL. ```bash # Use ngrok to expose local server ngrok http 3000 # Configure Meta webhook URL to: # https://your-ngrok-url.ngrok.io/api/webhook ``` -------------------------------- ### get_conversation Source: https://context7.com/nicolaischmid/pons/llms.txt Get a specific conversation with its recent message history. Shows contact details, 24-hour window status, and message thread with timestamps and delivery status. Requires the `read` scope. ```APIDOC ## get_conversation Get a specific conversation with its recent message history. Shows contact details, 24-hour window status, and message thread with timestamps and delivery status. Requires the `read` scope. ### Method MCP Tool Call ### Parameters #### Request Body - **tool** (string) - Required - The name of the tool to call, which is `get_conversation`. - **arguments** (object) - Required - The arguments for the `get_conversation` tool. - **from** (string) - Optional - Your WhatsApp Business number. - **phone** (string) - Optional - Recipient phone number. Omit to see recent contacts. - **messageLimit** (integer) - Optional - Maximum number of messages to return. Defaults to 50. ### Request Example ```json { "tool": "get_conversation", "arguments": { "from": "+493023324724", "phone": "+491234567890", "messageLimit": 50 } } ``` ### Response Example ``` // Response format: // Contact: Alice (+491234567890) // 24-hour Window: Open until 2024-01-16T10:30:00.000Z // // Messages: // ← [2024-01-15T10:00:00.000Z] Hi, I need help with my order (wamid.abc123) // → [2024-01-15T10:05:00.000Z] [delivered] Sure, what's your order number? (wamid.def456) // ← [2024-01-15T10:10:00.000Z] Order #12345 (wamid.ghi789) ``` ``` -------------------------------- ### Run Pons Development Commands Source: https://github.com/nicolaischmid/pons/blob/main/content/docs/self-hosting.mdx Provides a set of useful commands for developing and maintaining the Pons application. These include running Convex and Next.js in parallel, linting and formatting code, performing TypeScript checks, and building for production. ```bash pnpm dev # Convex + Next.js in parallel pnpm run dev:next # Just Next.js pnpm run check:write # Biome lint + format (auto-fix) pnpm run typecheck # TypeScript check pnpm run build # Production build ``` -------------------------------- ### Configure Pons Environment Variables Source: https://github.com/nicolaischmid/pons/blob/main/content/docs/self-hosting.mdx Creates a `.env.local` file to configure essential environment variables for Pons, including the Convex deployment URL and a secret key for authentication. The `CONVEX_AUTH_SECRET` should be generated securely and also set in the Convex dashboard. ```bash NEXT_PUBLIC_CONVEX_URL=https://your-deployment.convex.cloud CONVEX_AUTH_SECRET= ``` -------------------------------- ### Use SuspenseQuery with Convex React Source: https://github.com/nicolaischmid/pons/blob/main/AGENTS.md Demonstrates the correct and incorrect usage of Convex React hooks. `useSuspenseQuery` is recommended over `useQuery` to leverage React Suspense for better data handling and avoiding race conditions. Components using `useSuspenseQuery` should be wrapped in a `` boundary. ```tsx import { useSuspenseQuery } from "convex/react"; const { data: accounts } = useSuspenseQuery(api.accounts.list); // ❌ WRONG — never do this import { useQuery } from "convex/react"; const accounts = useQuery(api.accounts.list); ``` -------------------------------- ### Validate HMAC Signature for WhatsApp Webhooks (TypeScript) Source: https://github.com/nicolaischmid/pons/blob/main/content/blog/whatsapp-cloud-api-webhook-nextjs.mdx Verifies the HMAC-SHA256 signature of incoming POST requests from Meta to ensure authenticity. It uses Node.js crypto module for secure signature comparison, preventing timing attacks. Requires the 'x-hub-signature-256' header and the WHATSAPP_APP_SECRET environment variable. ```typescript import { createHmac, timingSafeEqual } from "node:crypto"; import { NextRequest } from "next/server"; async function verifySignature( req: NextRequest, body: string ): Promise { const signature = req.headers.get("x-hub-signature-256"); if (!signature) return false; const appSecret = process.env.WHATSAPP_APP_SECRET; if (!appSecret) return false; const expectedSignature = "sha256=" + createHmac("sha256", appSecret).update(body).digest("hex"); // Use timing-safe comparison to prevent timing attacks try { return timingSafeEqual( Buffer.from(signature), Buffer.from(expectedSignature) ); } catch { return false; } } ``` -------------------------------- ### Local Convex Development and Production Deployment Source: https://github.com/nicolaischmid/pons/blob/main/AGENTS.md Commands for local Convex development and production deployment. Local development syncs functions to a dev deployment, while production deployment is handled by pushing to the main branch, triggering Vercel builds. ```bash # Local development only — syncs functions to dev deployment npx convex dev # Production deploy: just push to main git push origin main ``` -------------------------------- ### Get Specific WhatsApp Conversation History (MCP) Source: https://context7.com/nicolaischmid/pons/llms.txt Fetches a detailed history of a specific WhatsApp conversation, including contact information, the 24-hour window status, and the message thread with timestamps and delivery status. This function requires the 'read' scope and allows filtering by sender and recipient, as well as limiting the number of messages. ```typescript // MCP Tool Call { "tool": "get_conversation", "arguments": { "from": "+493023324724", // Your WhatsApp Business number (optional) "phone": "+491234567890", // Recipient phone number (optional - omit to see recent contacts) "messageLimit": 50 // Max messages to return (default 50) } } // Response format: // Contact: Alice (+491234567890) // 24-hour Window: Open until 2024-01-16T10:30:00.000Z // // Messages: // ← [2024-01-15T10:00:00.000Z] Hi, I need help with my order (wamid.abc123) // → [2024-01-15T10:05:00.000Z] [delivered] Sure, what's your order number? (wamid.def456) // ← [2024-01-15T10:10:00.000Z] Order #12345 (wamid.ghi789) ``` -------------------------------- ### Configure Pons MCP Server in Cursor Project Source: https://github.com/nicolaischmid/pons/blob/main/content/blog/connect-cursor-to-whatsapp.mdx This JSON configuration file sets up the Pons MCP server for Cursor within a specific project. It defines the server URL and necessary authorization headers, allowing Pons to access WhatsApp Business messages directly from the editor. ```json { "mcpServers": { "pons": { "url": "https://pons.chat/api/mcp", "headers": { "Authorization": "Bearer pons_your_api_key_here" } } } } ``` -------------------------------- ### Security Guidelines: Authentication and Authorization Source: https://github.com/nicolaischmid/pons/blob/main/AGENTS.md Security rules for authentication and authorization in Convex actions and webhook endpoints. Emphasizes checking user IDs, membership, and verifying request signatures to ensure secure access and data handling. ```text - Every public Convex action must call auth.getUserId(ctx) and throw "Unauthorized" if null - Every action that takes accountId must also call checkMembership — never assume auth alone is sufficient - Webhook endpoints (Twilio, Meta) must verify request signatures cryptographically before processing - MCP routes (GET, POST, DELETE) must all require a valid API key ``` -------------------------------- ### Webhook Flow Processing Logic Source: https://github.com/nicolaischmid/pons/blob/main/AGENTS.md Illustrates the step-by-step process of handling incoming webhooks from Meta. It covers signature verification, immediate response, calling Convex actions for processing, media handling, and data storage. ```mermaid graph TD Meta sends webhook │ ▼ ┌───────────────────┐ │ POST /api/webhook │ │ • Verify signature│ │ • Return 200 fast │ │ • Call Convex │ └────────┬──────────┘ │ ▼ ┌───────────────────┐ │ Convex Action: │ │ processWebhook │ └────────┬──────────┘ │ ├──► Parse webhook payload │ ├──► If media message: │ │ │ └──► downloadMedia action │ • GET graph.facebook.com/{media_id} │ • Download binary (within 5 min!) │ • Upload to Convex storage │ ├──► mutations.contacts.upsert │ ├──► mutations.conversations.upsert │ └──► mutations.messages.store │ └──► Real-time update to all subscribed clients! ``` -------------------------------- ### List Templates API Source: https://context7.com/nicolaischmid/pons/llms.txt Lists available pre-approved message templates for the account. Templates must be created and approved in Meta Business Suite before use. Requires the `read` scope. ```APIDOC ## POST /list_templates ### Description Lists available pre-approved message templates for the account. Templates must be created and approved in Meta Business Suite before use. ### Method POST ### Endpoint /list_templates ### Parameters #### Query Parameters - **from** (string) - Optional - Your WhatsApp Business number. ### Request Example ```json { "tool": "list_templates", "arguments": { "from": "+493023324724" } } ``` ### Response #### Success Response (200) - **templates** (array) - An array of template objects, each detailing name, language, category, body, and variables. #### Response Example ```json [ { "name": "hello_world", "language": "en_US", "status": "APPROVED", "category": "UTILITY", "body": "Hello {{1}}, welcome to our service!", "variables": [ { "name": "1", "type": "POSITIONAL" } ] }, { "name": "order_update", "language": "de_DE", "status": "APPROVED", "category": "UTILITY", "body": "Hi {{name}}, your order {{order_id}} has been {{status}}.", "variables": [ { "name": "name", "type": "NAMED" }, { "name": "order_id", "type": "NAMED" }, { "name": "status", "type": "NAMED" } ] } ] ``` ``` -------------------------------- ### Configure OpenCode MCP for Pons Source: https://github.com/nicolaischmid/pons/blob/main/content/blog/connect-opencode-to-whatsapp.mdx This JSON configuration snippet shows how to add Pons as a remote MCP service to OpenCode. It specifies the service type, API endpoint URL, and necessary authorization headers, including a placeholder for your Pons API key. Ensure you replace 'pons_your_api_key_here' with your actual API key. ```json { "mcp": { "pons": { "type": "remote", "url": "https://pons.chat/api/mcp", "headers": { "Authorization": "Bearer pons_your_api_key_here" } } } } ``` -------------------------------- ### Write Tools Source: https://github.com/nicolaischmid/pons/blob/main/content/docs/mcp-tools.mdx These tools require the 'write' scope for managing message states and reactions. ```APIDOC ## POST /mark_as_read ### Description Mark a message as read (sends read receipt to the sender). ### Method POST ### Endpoint /mark_as_read ### Parameters #### Request Body - **waMessageId** (string) - Required - The WhatsApp message ID (`wamid.xxx`) to mark as read ### Request Example { "waMessageId": "wamid.HBgNNjQ1NTY4NzQ1NjQ4NzQ1NjQ4NQAxMDAwMDAwMDAwMA==" } ### Response #### Success Response (200) - **message** (string) - Confirmation that the message was marked as read. #### Response Example { "message": "Message marked as read successfully." } ``` ```APIDOC ## POST /send_reaction ### Description React to a message with an emoji. ### Method POST ### Endpoint /send_reaction ### Parameters #### Request Body - **conversationId** (string) - Required - The conversation ID - **phone** (string) - Required - Phone number in E.164 format (e.g., `+491234567890`) - **waMessageId** (string) - Required - The WhatsApp message ID to react to - **emoji** (string) - Required - Emoji to react with (e.g., 👍, ❤️, 😂) ### Request Example { "conversationId": "conv_abc123", "phone": "+1234567890", "waMessageId": "wamid.HBgNNjQ1NTY4NzQ1NjQ4NzQ1NjQ4NQAxMDAwMDAwMDAwMA==", "emoji": "👍" } ### Response #### Success Response (200) - **message** (string) - Confirmation that the reaction was sent. #### Response Example { "message": "Reaction sent successfully." } ``` -------------------------------- ### MCP Tools for AI Agents - Metadata Source: https://github.com/nicolaischmid/pons/blob/main/AGENTS.md Provides AI agents with tools to access metadata related to WhatsApp messaging. This includes fetching available message templates and retrieving URLs for media attachments. ```plaintext Metadata - `get_templates` - List available message templates - `get_media_url` - Get URL for a media attachment ``` -------------------------------- ### Securely Passing API Tokens with Authorization Header (TypeScript) Source: https://github.com/nicolaischmid/pons/blob/main/AGENTS.md Demonstrates the correct method of passing API access tokens using the `Authorization: Bearer` header in fetch requests, contrasting it with the insecure practice of including tokens in URL query parameters. This prevents token leakage in logs and proxies. ```typescript // ✅ CORRECT — token in Authorization header const res = await fetch(`${META_API_BASE}/${id}?fields=name,status`, { headers: { Authorization: `Bearer ${token}` }, }); // ❌ WRONG — token leaked in URL (visible in logs, proxies, referers) const res = await fetch(`${META_API_BASE}/${id}?fields=name&access_token=${token}`); ```