# Code Examples

Ready-to-use code snippets for integrating with BuildStability's MCP server and API.

**Get your token:** Business Settings → API & Integrations → **Copy Token** (when API access is enabled), or see the [Authentication Guide](/auth-guide).

## TypeScript/Node.js

### Basic MCP Client

```typescript
interface JsonRpcRequest {
  jsonrpc: '2.0';
  id: string | number;
  method: string;
  params?: Record<string, unknown>;
}

interface JsonRpcResponse {
  jsonrpc: '2.0';
  id: string | number | null;
  result?: unknown;
  error?: {
    code: number;
    message: string;
    data?: unknown;
  };
}

class BuildStabilityMCP {
  private baseUrl = 'https://api.buildstability.com/api/mcp';
  private accessToken: string;

  constructor(accessToken: string) {
    this.accessToken = accessToken;
  }

  async call(method: string, params?: Record<string, unknown>): Promise<unknown> {
    const request: JsonRpcRequest = {
      jsonrpc: '2.0',
      id: Date.now(),
      method,
      params
    };

    const response = await fetch(this.baseUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.accessToken}`
      },
      body: JSON.stringify(request)
    });

    const data: JsonRpcResponse = await response.json();

    if (data.error) {
      throw new Error(`MCP Error ${data.error.code}: ${data.error.message}`);
    }

    return data.result;
  }

  async checkChurnRisk(threshold = 40) {
    return this.call('buildstability/check_churn_risk', { threshold });
  }

  async getClientSummary(clientId: string) {
    return this.call('buildstability/get_client_summary', { client_id: clientId });
  }

  async listActivePrograms(limit = 10) {
    return this.call('buildstability/list_active_programs', { limit });
  }

  async getBusinessStats() {
    return this.call('buildstability/get_business_stats');
  }
}

// Usage
const mcp = new BuildStabilityMCP('your-access-token');
const atRiskClients = await mcp.checkChurnRisk(40);
console.log(atRiskClients);
```

## Python

### Python MCP Client

```python
import requests
import json
from typing import Optional, Dict, Any

class BuildStabilityMCP:
    def __init__(self, access_token: str):
        self.base_url = "https://api.buildstability.com/api/mcp"
        self.access_token = access_token
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

    def call(self, method: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        request = {
            "jsonrpc": "2.0",
            "id": 1,
            "method": method,
            "params": params or {}
        }

        response = requests.post(
            self.base_url,
            headers=self.headers,
            json=request
        )
        response.raise_for_status()
        data = response.json()

        if "error" in data:
            error = data["error"]
            raise Exception(f"MCP Error {error['code']}: {error['message']}")

        return data.get("result")

    def check_churn_risk(self, threshold: int = 40) -> Dict[str, Any]:
        return self.call("buildstability/check_churn_risk", {"threshold": threshold})

    def get_client_summary(self, client_id: str) -> Dict[str, Any]:
        return self.call("buildstability/get_client_summary", {"client_id": client_id})

    def list_active_programs(self, limit: int = 10) -> Dict[str, Any]:
        return self.call("buildstability/list_active_programs", {"limit": limit})

    def get_business_stats(self) -> Dict[str, Any]:
        return self.call("buildstability/get_business_stats")

# Usage
mcp = BuildStabilityMCP("your-access-token")
at_risk = mcp.check_churn_risk(threshold=40)
print(f"Found {at_risk['at_risk_count']} clients at risk")
```

## JavaScript (Browser)

### Browser MCP Client

```javascript
class BuildStabilityMCP {
  constructor(accessToken) {
    this.baseUrl = 'https://api.buildstability.com/api/mcp';
    this.accessToken = accessToken;
  }

  async call(method, params = {}) {
    const request = {
      jsonrpc: '2.0',
      id: Date.now(),
      method,
      params
    };

    const response = await fetch(this.baseUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.accessToken}`
      },
      body: JSON.stringify(request)
    });

    const data = await response.json();

    if (data.error) {
      throw new Error(`MCP Error ${data.error.code}: ${data.error.message}`);
    }

    return data.result;
  }

  async checkChurnRisk(threshold = 40) {
    return this.call('buildstability/check_churn_risk', { threshold });
  }

  async getClientSummary(clientId) {
    return this.call('buildstability/get_client_summary', { client_id: clientId });
  }
}

// Usage
const mcp = new BuildStabilityMCP('your-access-token');
mcp.checkChurnRisk(40).then(result => {
  console.log(`Found ${result.at_risk_count} clients at risk`);
});
```

## cURL Examples

### List Available Tools

```bash
curl -X POST https://api.buildstability.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list"
  }'
```

### Check Churn Risk

```bash
curl -X POST https://api.buildstability.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "buildstability/check_churn_risk",
    "params": {
      "threshold": 40
    }
  }'
```

### Get Today's Schedule

```bash
curl -X POST https://api.buildstability.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "buildstability/get_schedule",
    "params": {
      "date": "today"
    }
  }'
```

### List All Clients

```bash
curl -X POST https://api.buildstability.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "id": 4,
    "method": "buildstability/list_clients",
    "params": {
      "status": "active",
      "limit": 50
    }
  }'
```

### Get Available Booking Slots

```bash
curl -X POST https://api.buildstability.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "id": 5,
    "method": "buildstability/get_available_slots",
    "params": {
      "date": "2025-01-20",
      "duration_minutes": 60
    }
  }'
```

### Send Client Message

```bash
curl -X POST https://api.buildstability.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "id": 6,
    "method": "buildstability/send_client_message",
    "params": {
      "client_id": "uuid-here",
      "message": "Just checking in - how are you feeling after yesterday'\''s session?",
      "message_type": "motivation"
    }
  }'
```

### Create Client Note

```bash
curl -X POST https://api.buildstability.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "id": 7,
    "method": "buildstability/create_client_note",
    "params": {
      "client_id": "uuid-here",
      "title": "Session Notes - Jan 18",
      "content": "Great progress on squats. Increased weight by 5kg. Focus on form next session.",
      "document_type": "note"
    }
  }'
```

## Error Handling Example

```typescript
try {
  const result = await mcp.getClientSummary('invalid-id');
} catch (error) {
  if (error.message.includes('-32602')) {
    console.error('Invalid parameters provided');
  } else if (error.message.includes('-32001')) {
    console.error('Authentication required');
  } else {
    console.error('Unexpected error:', error);
  }
}
```

## Rate Limiting

BuildStability enforces rate limits to ensure fair usage and cost protection:

### Rate Limits (per 15-minute window)

| Plan | Rate Limit | Daily Cap |
|------|------------|-----------|
| **Free Trial** | 25 req/15min | 500/day |
| **Essential** | 50 req/15min | 1,000/day |
| **Starter** | 100 req/15min | 5,000/day |
| **Pro** | 200 req/15min | 15,000/day |
| **Studio** | 500 req/15min | 50,000/day |

### Query Complexity Limits (per request)

| Plan | Max Clients | Max Programs |
|------|-------------|--------------|
| **Essential** | 10 | 5 |
| **Starter** | 25 | 10 |
| **Pro** | 50 | 20 |
| **Studio** | 100 | 50 |

### Response Headers

All API responses include usage headers:
- `X-RateLimit-Limit` - Your rate limit
- `X-RateLimit-Remaining` - Requests remaining in window
- `X-DailyLimit-Limit` - Your daily cap
- `X-DailyLimit-Remaining` - Requests remaining today
- `X-DailyLimit-Reset` - When daily cap resets (midnight UTC)

Handle rate limits gracefully with exponential backoff:

```typescript
async function callWithRetry(mcp: BuildStabilityMCP, method: string, params: any, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await mcp.call(method, params);
    } catch (error: any) {
      if (error.message.includes('429') && i < maxRetries - 1) {
        const waitTime = Math.pow(2, i) * 1000; // Exponential backoff
        await new Promise(resolve => setTimeout(resolve, waitTime));
        continue;
      }
      throw error;
    }
  }
}
```

## Next Steps

- Read the [Quick Start Guide](/quickstart-mcp.md)
- Review the [Authentication Guide](/auth-guide.md)
- Check the [OpenAPI Specification](/buildstability-openapi.json)