> ## Documentation Index
> Fetch the complete documentation index at: https://docs.supermodel.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Hello World Example

> Simple calculator app demonstrating SuperModel basics

# Hello World: Calculator App

This example walks through creating a simple calculator app using SuperModel's zero-inference architecture. You'll see how routing and UI generation work via [MCP sampling](https://modelcontextprotocol.org).

## User Request

**Input**: "Show me a calculator"

This simple request triggers SuperModel's layered architecture to route the request and generate an interactive calculator interface.

## Step 1: Request Routing via Sampling

SuperModel's gateway doesn't decide which tool to use - it asks the client's LLM:

<CodeGroup>
  ```json Routing Sampling Request
  {
    "method": "sampling/createMessage",
    "params": {
      "messages": [{
        "role": "user",
        "content": {
          "type": "text",
          "text": "User request: 'Show me a calculator'\n\nAvailable tools:\n- calculator-ui: Interactive calculator with basic arithmetic operations\n- form-builder-ui: Dynamic form generation and validation\n- data-viz-ui: Charts and data visualization\n- product-search-ui: E-commerce product search interface\n\nWhich tool should handle this request? Return JSON with tool name and any relevant parameters."
        }
      }],
      "systemPrompt": "You are a routing assistant. Analyze the user request and return JSON: {\"tool\": \"tool-name\", \"params\": {...}}"
    }
  }
  ```

  ```json Client LLM Response
  {
    "role": "assistant",
    "content": {
      "type": "text",
      "text": "{\"tool\": \"calculator-ui\", \"params\": {\"type\": \"basic\", \"operations\": [\"add\", \"subtract\", \"multiply\", \"divide\"]}}"
    }
  }
  ```
</CodeGroup>

<Note>
  **Zero Inference Cost**: The gateway server made no LLM API calls. The client's LLM handled the routing decision.
</Note>

## Step 2: Tool Selection & Execution

Based on the routing response, SuperModel selects the `calculator-ui` tool and executes it with the provided parameters.

```typescript
// Gateway routes to calculator tool
const selectedTool = gateway.getTool('calculator-ui');
const result = await selectedTool.execute({
  type: 'basic',
  operations: ['add', 'subtract', 'multiply', 'divide']
}, context);
```

## Step 3: UI Generation via Sampling

The calculator tool uses MCP sampling to generate the actual UI component:

<CodeGroup>
  ```json UI Generation Sampling
  {
    "method": "sampling/createMessage",
    "params": {
      "messages": [{
        "role": "user",
        "content": {
          "type": "text",
          "text": "Create an AG-UI calculator component with the following requirements:\n\n- Buttons for numbers 0-9\n- Operation buttons: +, -, *, /, =\n- Clear button (C) and clear all (CA)\n- Display screen showing current number and result\n- Professional, clean design\n- Use AG-UI event system for all button interactions\n\nGenerate a complete React component that follows AG-UI patterns for event handling."
        }
      }],
      "systemPrompt": "You are an expert React developer specializing in AG-UI components. Generate clean, functional code with proper event handlers for the AG-UI protocol.",
      "maxTokens": 1500
    }
  }
  ```

  ```jsx Generated Calculator Component
  function Calculator() {
    const [display, setDisplay] = useState('0');
    const [previousValue, setPreviousValue] = useState(null);
    const [operation, setOperation] = useState(null);
    const [waitingForNewValue, setWaitingForNewValue] = useState(false);

    const inputNumber = (num) => {
      if (waitingForNewValue) {
        setDisplay(String(num));
        setWaitingForNewValue(false);
      } else {
        setDisplay(display === '0' ? String(num) : display + num);
      }

      // AG-UI event emission
      window.parent.postMessage({
        type: 'ag-ui-event',
        eventType: 'USER_INPUT',
        payload: { action: 'number_input', value: num }
      }, '*');
    };

    const inputOperation = (nextOperation) => {
      const inputValue = parseFloat(display);

      if (previousValue === null) {
        setPreviousValue(inputValue);
      } else if (operation) {
        const currentValue = previousValue || 0;
        const newValue = calculate(currentValue, inputValue, operation);

        setDisplay(String(newValue));
        setPreviousValue(newValue);
      }

      setWaitingForNewValue(true);
      setOperation(nextOperation);

      // AG-UI event emission
      window.parent.postMessage({
        type: 'ag-ui-event',
        eventType: 'TOOL_CALL',
        payload: { 
          action: 'operation', 
          operation: nextOperation,
          current_value: inputValue 
        }
      }, '*');
    };

    const calculate = (firstValue, secondValue, operation) => {
      switch (operation) {
        case '+': return firstValue + secondValue;
        case '-': return firstValue - secondValue;
        case '*': return firstValue * secondValue;
        case '/': return firstValue / secondValue;
        case '=': return secondValue;
        default: return secondValue;
      }
    };

    const performCalculation = () => {
      const inputValue = parseFloat(display);
      
      if (previousValue !== null && operation) {
        const newValue = calculate(previousValue, inputValue, operation);
        setDisplay(String(newValue));
        setPreviousValue(null);
        setOperation(null);
        setWaitingForNewValue(true);

        // AG-UI event emission
        window.parent.postMessage({
          type: 'ag-ui-event',
          eventType: 'CALCULATION_COMPLETE',
          payload: { result: newValue, operation: operation }
        }, '*');
      }
    };

    const clearAll = () => {
      setDisplay('0');
      setPreviousValue(null);
      setOperation(null);
      setWaitingForNewValue(false);

      // AG-UI event emission
      window.parent.postMessage({
        type: 'ag-ui-event',
        eventType: 'TOOL_CALL',
        payload: { action: 'clear_all' }
      }, '*');
    };

    return (
      <div className="calculator">
        <div className="display">
          <div className="screen">{display}</div>
        </div>
        
        <div className="buttons">
          <div className="row">
            <button onClick={clearAll} className="function">CA</button>
            <button onClick={() => setDisplay(display.slice(0, -1) || '0')} className="function">⌫</button>
            <button onClick={() => inputOperation('/')} className="operator">÷</button>
          </div>
          
          <div className="row">
            <button onClick={() => inputNumber(7)}>7</button>
            <button onClick={() => inputNumber(8)}>8</button>
            <button onClick={() => inputNumber(9)}>9</button>
            <button onClick={() => inputOperation('*')} className="operator">×</button>
          </div>
          
          <div className="row">
            <button onClick={() => inputNumber(4)}>4</button>
            <button onClick={() => inputNumber(5)}>5</button>
            <button onClick={() => inputNumber(6)}>6</button>
            <button onClick={() => inputOperation('-')} className="operator">−</button>
          </div>
          
          <div className="row">
            <button onClick={() => inputNumber(1)}>1</button>
            <button onClick={() => inputNumber(2)}>2</button>
            <button onClick={() => inputNumber(3)}>3</button>
            <button onClick={() => inputOperation('+')} className="operator">+</button>
          </div>
          
          <div className="row">
            <button onClick={() => inputNumber(0)} className="zero">0</button>
            <button onClick={() => inputNumber('.')}>.</button>
            <button onClick={performCalculation} className="operator">=</button>
          </div>
        </div>
        
        <style jsx>{`
          .calculator {
            width: 300px;
            background: #2c3e50;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.3);
          }
          
          .display {
            background: #1a252f;
            padding: 20px;
            border-radius: 5px;
            margin-bottom: 20px;
          }
          
          .screen {
            color: #fff;
            font-size: 2.5rem;
            text-align: right;
            font-family: 'Courier New', monospace;
            min-height: 60px;
            display: flex;
            align-items: center;
            justify-content: flex-end;
          }
          
          .buttons {
            display: grid;
            grid-template-rows: repeat(5, 1fr);
            gap: 10px;
          }
          
          .row {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 10px;
          }
          
          button {
            height: 60px;
            border: none;
            border-radius: 5px;
            font-size: 1.5rem;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.2s;
          }
          
          button:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 10px rgba(0,0,0,0.3);
          }
          
          button:active {
            transform: translateY(0);
          }
          
          .row button {
            background: #34495e;
            color: #fff;
          }
          
          .operator {
            background: #e74c3c !important;
            color: #fff;
          }
          
          .function {
            background: #95a5a6 !important;
            color: #2c3e50;
          }
          
          .zero {
            grid-column: span 2;
          }
        `}</style>
      </div>
    );
  }
  ```
</CodeGroup>

<Note>
  **Zero Inference Cost**: Again, the calculator tool made no LLM API calls. The client's LLM generated the entire UI component.
</Note>

## Step 4: Resource Packaging

The calculator tool packages the generated component as an MCP-UI resource:

```typescript
// Tool packages the generated UI
const uiResource = {
  type: 'resource',
  resource: {
    uri: 'ui://calculator/calc-001',
    mimeType: 'application/vnd.mcp-ui.ag-ui',
    text: generatedCalculatorComponent
  }
};
```

## Step 5: Final Response

SuperModel returns the complete response to the client:

<CodeGroup>
  ```json Final MCP Response
  {
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
      "content": [
        {
          "type": "text",
          "text": "Here's your calculator! It includes all basic arithmetic operations with a clean, professional interface."
        },
        {
          "type": "resource",
          "resource": {
            "uri": "ui://calculator/calc-001",
            "mimeType": "application/vnd.mcp-ui.ag-ui",
            "text": "function Calculator() { /* component code */ }"
          }
        }
      ]
    }
  }
  ```

  ```jsx Rendered Result
  // Client renders the interactive calculator
  <div className="calculator">
    <div className="display">
      <div className="screen">0</div>
    </div>
    <div className="buttons">
      <!-- Fully interactive calculator buttons -->
    </div>
  </div>
  ```
</CodeGroup>

## What Just Happened?

<Steps>
  <Step title="Zero Server Inference">
    The server made **zero LLM API calls**. All reasoning (routing + generation) happened on the client via MCP sampling.
  </Step>

  <Step title="Intelligent Routing">
    Client's LLM correctly identified that "Show me a calculator" should route to the calculator-ui tool.
  </Step>

  <Step title="Dynamic UI Generation">
    Client's LLM generated a complete, functional React component with proper AG-UI event handling.
  </Step>

  <Step title="Interactive Result">
    User receives a fully functional calculator that works immediately in their MCP client.
  </Step>
</Steps>

## AG-UI Event Handling

The generated calculator includes proper AG-UI event handling:

<AccordionGroup>
  <Accordion title="User Input Events">
    ```javascript
    // Number button clicks
    window.parent.postMessage({
      type: 'ag-ui-event',
      eventType: 'USER_INPUT',
      payload: { action: 'number_input', value: 7 }
    }, '*');
    ```
  </Accordion>

  <Accordion title="Tool Call Events">
    ```javascript
    // Operation button clicks  
    window.parent.postMessage({
      type: 'ag-ui-event',
      eventType: 'TOOL_CALL',
      payload: { 
        action: 'operation',
        operation: '+',
        current_value: 42
      }
    }, '*');
    ```
  </Accordion>

  <Accordion title="Calculation Events">
    ```javascript
    // Calculation completion
    window.parent.postMessage({
      type: 'ag-ui-event',
      eventType: 'CALCULATION_COMPLETE',
      payload: { result: 49, operation: '+' }
    }, '*');
    ```
  </Accordion>
</AccordionGroup>

## Cost Analysis

**Traditional Approach**:

* Routing decision: \$0.02
* UI generation: \$0.08
* **Total**: \$0.10 per calculator request

**SuperModel Approach**:

* Server costs: \$0.00
* Client handles all LLM work
* **Total**: \$0.00 per calculator request

**Savings**: 100% cost reduction

## Try It Yourself

Want to implement this example? Here's the complete setup:

<CardGroup cols={2}>
  <Card title="Quick Start Guide" icon="rocket" href="/quickstart">
    Follow our step-by-step guide to set up SuperModel and create this calculator.
  </Card>
</CardGroup>

## Next Examples

<CardGroup cols={2}>
  <Card title="Multi-App Workflow" icon="workflow" href="/examples/multi-app-workflow">
    See how context flows between multiple specialized UI apps.
  </Card>

  <Card title="Context Handoff" icon="arrow-right-arrow-left" href="/examples/context-handoff">
    Learn how apps share context for seamless user experiences.
  </Card>
</CardGroup>
