Skip to main content
Glama
slaarhuis
by slaarhuis
README.md
# Templafy MCP Server

A production-ready MCP (Model Context Protocol) server for Templafy Data Sources API. This server provides a middle layer between Claude and the Templafy Public API, focusing exclusively on Data Sources functionality.

## Features

- **Complete Data Sources API Coverage**: All CRUD operations for data sources, fields, items, and item fields
- **Type Safety**: Full TypeScript support with Zod validation
- **Robust Error Handling**: Proper HTTP error mapping with special handling for 423 Locked responses
- **Retry Logic**: Exponential backoff for server errors with configurable retry attempts
- **Security**: API key redaction in logs, input validation, and rate limiting
- **Observability**: Structured logging with request tracking and performance metrics
- **Production Ready**: Comprehensive error handling, graceful shutdown, and proper resource management

## Prerequisites

- Node.js 20 or higher
- Templafy API access with Admin permissions
- Valid API key from Templafy Admin

## Installation

1. Clone or download this repository
2. Install dependencies:

```bash
npm install
```

3. Copy the environment configuration:

```bash
cp env.example .env
```

4. Configure your environment variables in `.env`:

```bash
# Required
TENANT_ID=your-tenant-id
TEMPLAFY_API_KEY=your-api-key

# Optional (defaults shown)
TEMPLAFY_API_VERSION=v2
AUTH_HEADER_NAME=Authorization
AUTH_SCHEME=ApiKey
REQUEST_TIMEOUT_MS=30000
DEBUG_HTTP=false
```

## Environment Variables

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `TENANT_ID` | Yes | - | Your Templafy tenant ID |
| `TEMPLAFY_API_KEY` | Yes | - | API key from Templafy Admin |
| `TEMPLAFY_API_VERSION` | No | `v2` | API version to use |
| `AUTH_HEADER_NAME` | No | `Authorization` | HTTP header name for authentication |
| `AUTH_SCHEME` | No | `ApiKey` | Authentication scheme |
| `REQUEST_TIMEOUT_MS` | No | `30000` | Request timeout in milliseconds |
| `DEBUG_HTTP` | No | `false` | Enable HTTP request/response logging |

## Usage

### Development

Start the server in development mode with hot reload:

```bash
npm run dev
```

### Production

Build and run the production server:

```bash
npm run build
node dist/server.js
```

### Registering with Claude Desktop

Add the following configuration to your Claude Desktop MCP settings:

```json
{
  "mcpServers": {
    "templafy": {
      "command": "node",
      "args": ["/path/to/templafy-mcp-server/dist/server.js"],
      "env": {
        "TENANT_ID": "your-tenant-id",
        "TEMPLAFY_API_KEY": "your-api-key"
      }
    }
  }
}
```

## Available Tools

### Data Sources

#### `listDataSources`
List data sources with optional search and pagination.

**Parameters:**
- `searchQuery` (optional): Search query to filter data sources
- `page` (optional): Page number (default: 1)
- `pageSize` (optional): Items per page (default: 50, max: 200)

**Example:**
```json
{
  "searchQuery": "customer data",
  "page": 1,
  "pageSize": 25
}
```

#### `getDataSource`
Get a specific data source by ID.

**Parameters:**
- `id` (required): Data source ID

#### `createDataSource`
Create a new data source.

**Parameters:**
- `name` (required): Data source name
- `description` (optional): Data source description
- `fields` (optional): Array of field definitions

**Example:**
```json
{
  "name": "Customer Database",
  "description": "Customer information and contact details",
  "fields": [
    {
      "name": "Customer Name",
      "type": "text",
      "required": true,
      "description": "Full customer name"
    },
    {
      "name": "Email",
      "type": "text",
      "required": true,
      "description": "Customer email address"
    }
  ]
}
```

#### `updateDataSource`
Update an existing data source.

**Parameters:**
- `id` (required): Data source ID
- `name` (optional): Updated name
- `description` (optional): Updated description
- `fields` (optional): Updated field definitions

#### `deleteDataSource`
Delete a data source.

**Parameters:**
- `id` (required): Data source ID

### Fields

#### `getField`
Get a specific field from a data source.

**Parameters:**
- `dataSourceId` (required): Data source ID
- `fieldId` (required): Field ID

#### `createField`
Create a new field in a data source.

**Parameters:**
- `dataSourceId` (required): Data source ID
- `field` (required): Field definition

**Example:**
```json
{
  "dataSourceId": "ds-123",
  "field": {
    "name": "Phone Number",
    "type": "text",
    "required": false,
    "description": "Customer phone number"
  }
}
```

#### `updateField`
Update an existing field.

**Parameters:**
- `dataSourceId` (required): Data source ID
- `fieldId` (required): Field ID
- `field` (required): Updated field definition

#### `deleteField`
Delete a field from a data source.

**Parameters:**
- `dataSourceId` (required): Data source ID
- `fieldId` (required): Field ID

### Items

#### `listItems`
List items in a data source with pagination.

**Parameters:**
- `dataSourceId` (required): Data source ID
- `page` (optional): Page number (default: 1)
- `pageSize` (optional): Items per page (default: 50, max: 200)

#### `getItem`
Get a specific item from a data source.

**Parameters:**
- `dataSourceId` (required): Data source ID
- `itemId` (required): Item ID

#### `createItem`
Create a new item in a data source.

**Parameters:**
- `dataSourceId` (required): Data source ID
- `fields` (optional): Item field values

**Example:**
```json
{
  "dataSourceId": "ds-123",
  "fields": {
    "customer-name": "John Doe",
    "email": "john@example.com",
    "phone": "+1-555-0123"
  }
}
```

#### `updateItem`
Update an existing item.

**Parameters:**
- `dataSourceId` (required): Data source ID
- `itemId` (required): Item ID
- `fields` (optional): Updated field values

#### `deleteItem`
Delete an item from a data source.

**Parameters:**
- `dataSourceId` (required): Data source ID
- `itemId` (required): Item ID

### Item Fields

#### `putItemField`
Set or update a specific field value for an item.

**Parameters:**
- `dataSourceId` (required): Data source ID
- `itemId` (required): Item ID
- `fieldId` (required): Field ID
- `value` (required): Field value (type depends on field type)

**Example:**
```json
{
  "dataSourceId": "ds-123",
  "itemId": "item-456",
  "fieldId": "field-789",
  "value": "Updated value"
}
```

#### `deleteItemField`
Delete a specific field value from an item.

**Parameters:**
- `dataSourceId` (required): Data source ID
- `itemId` (required): Item ID
- `fieldId` (required): Field ID

## Field Types

The following field types are supported:

- `text`: Text strings
- `number`: Numeric values
- `image`: Image references
- `reference`: References to other data
- `color`: Color values
- `theme`: Theme references
- `font`: Font specifications

## Error Handling

The server provides comprehensive error handling:

- **Validation Errors**: Input validation with clear error messages
- **HTTP Errors**: Proper mapping of HTTP status codes to MCP errors
- **423 Locked**: Special handling for locked resources with lock reason and dependent resources
- **Retry Logic**: Automatic retry with exponential backoff for server errors
- **Rate Limiting**: Built-in protection against excessive API calls

### Example Error Response

```json
{
  "ok": false,
  "error": {
    "status": 423,
    "code": "LOCKED",
    "message": "Data source is locked",
    "lockReason": {
      "reason": "Data source is being used by active templates",
      "dependentResources": ["template-1", "template-2"]
    }
  }
}
```

## Development

### Scripts

- `npm run dev`: Start development server with hot reload
- `npm run build`: Build production bundle
- `npm run lint`: Run ESLint
- `npm run typecheck`: Run TypeScript type checking
- `npm run test`: Run test suite
- `npm run test:watch`: Run tests in watch mode

### Testing

The project includes a comprehensive test suite using Vitest and MSW (Mock Service Worker):

```bash
# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run specific test file
npm test dataSources.test.ts
```

### Code Structure

```
src/
├── server.ts              # MCP server entry point
├── templafyClient.ts      # HTTP client with retry logic
├── types.ts              # TypeScript types and Zod schemas
├── tools/                # MCP tool implementations
│   ├── dataSources.ts    # Data source tools
│   ├── fields.ts         # Field tools
│   ├── items.ts          # Item tools
│   └── itemFields.ts     # Item field tools
└── util/                 # Utility modules
    ├── env.ts           # Environment configuration
    ├── logger.ts        # Logging utilities
    └── errors.ts        # Error handling
```

## Security

- API keys are automatically redacted from logs
- Input validation prevents injection attacks
- Rate limiting protects against abuse
- No sensitive data is logged in production

## Monitoring

The server provides structured logging with:

- Request/response tracking with unique IDs
- Performance metrics (duration, status codes)
- Error tracking with context
- Optional HTTP debugging mode

## Troubleshooting

### Common Issues

1. **Authentication Errors**: Verify your `TENANT_ID` and `TEMPLAFY_API_KEY` are correct
2. **Timeout Errors**: Increase `REQUEST_TIMEOUT_MS` for slow networks
3. **Rate Limiting**: The server includes built-in rate limiting; reduce concurrent requests if needed
4. **423 Locked Errors**: Check the `lockReason` for dependent resources that need to be unlocked first

### Debug Mode

Enable debug logging to troubleshoot issues:

```bash
DEBUG_HTTP=true npm run dev
```

This will log all HTTP requests and responses (with sensitive data redacted).

## License

This project is licensed under the MIT License.