npm package: @olbrain/cdp-api-mcp
Description: CDP (Customer Data Platform) API MCP Server for user management operations
Author: Alchemist
Latest version: 2.2.3

# CDP API MCP Server

A Model Context Protocol (MCP) server for interacting with CDP (Customer Data Platform) APIs. Provides complete CRUD operations for user management.

**Status**: ✅ Production Ready | **Default Server**: `https://converse.showroom.lumegalabs.com` | **Tools**: 6

## Features

### User Management
- **Create User**: Add new users with flexible attributes including interests (ID auto-generated if not provided)
- **Get Current User**: Automatically identify and retrieve current user from session
- **Search Users**: Search for users by email, phone, or name
- **Get All Users**: Retrieve paginated list of users
- **Update User**: Modify existing user information including interests
- **Delete User**: Remove users from the CDP

### Autonomous Execution
- **Auto-User Identification**: Automatically identifies users at conversation start
- **Session Awareness**: Integrates with Firestore session data for user context
- **Template-Based Execution**: Executor pattern for autonomous tool execution
- **Personalized Interactions**: Retrieves user profile, interests, and attributes automatically

## Autonomous Execution

The CDP API MCP server supports **autonomous, template-based execution** for session-aware workflows. This enables the agent to automatically identify users at conversation start without requiring explicit tool calls.

### How It Works

1. **Session Start**: When a conversation begins, the agent automatically executes `cdp_get_current_user`
2. **User Identification**: The server identifies the user from session data (email, phone, or user_id)
3. **CDP Lookup**: Searches the CDP database for the matching user profile
4. **Profile Retrieval**: Returns user data including interests, attributes, and purchase history
5. **Personalization**: Agent uses this data for personalized recommendations and interactions

### User Identification Priority

The system identifies users using this priority order:

1. **User ID** - Most reliable, direct database lookup
2. **OTP Authenticated Phone** - Verified phone number from OTP authentication
3. **Verified Email** - Email verified during registration
4. **Mobile Number** - User profile mobile number
5. **WhatsApp Channel ID** - For WhatsApp conversations

### Example Sales Workflow

```
Customer: "Hi, I'm looking for products"

→ Agent automatically calls cdp_get_current_user
→ Identifies user via session email/phone
→ Retrieves: {name: "John", interests: ["electronics", "laptops"], budget: "$1000-$2000"}

Agent: "Hi John! I see you're interested in electronics.
       Based on your budget, I can recommend some great laptops.
       How can I help you today?"
```

### Configuration

Enable/disable auto-identification in server configuration:

```json
{
  "CDP_AUTO_IDENTIFY": true
}
```

When enabled (default), the agent automatically retrieves user profiles at conversation start.

### Session Integration

The CDP server integrates with Firestore `agent_sessions` collection to access:
- User authentication data
- Session metadata
- Verified contact information
- Channel-specific identifiers

**Note**: In MCP stdio mode (direct testing), session awareness features are disabled. Full autonomous execution requires integration with olbrain-studio backend.

## Sales Agent Role (Backend Template Injection)

The CDP MCP server includes a **Sales Agent role** with automatic prompt template injection. When you select the "Sales Agent" role in olbrain-studio, the backend automatically appends specialized instructions to the agent's system prompt.

### How It Works

1. **Role Selection**: User selects "Sales Agent" role when configuring an agent
2. **Backend Injection**: olbrain-studio backend automatically appends the sales agent template to the system prompt
3. **Automatic Behavior**: Agent automatically calls `cdp_get_current_user` at every conversation start
4. **No User Configuration**: Template is invisible to users - works automatically

### Sales Agent Features

When the Sales Agent role is active, the agent will:

✅ **Auto-identify customers** at conversation start using CDP data
✅ **Personalize greetings** with customer name and interests
✅ **Recommend products** based on customer preferences and budget
✅ **Update profiles** as new customer preferences and interests are discovered
✅ **Follow sales workflow** from greeting → needs discovery → recommendation → purchase

### Sales Workflow (Automated)

The template instructs the agent to follow this workflow:

```
1. Session Start → Auto-call cdp_get_current_user
2. Personalized Greeting → "Hi John! I see you're interested in laptops..."
3. Needs Discovery → Listen and match with CDP profile
4. Product Recommendation → Use BYS API + CDP preferences
5. Purchase Flow → BYS checkout
6. Follow-up → Update CDP with latest preferences and interests
```

### Example Conversations

#### Returning Customer (Found in CDP)
```
[Agent automatically identifies user from CDP]

Agent: "Hi Sarah! Great to see you again. I see you're interested in
        electronics. How can I help you today?"

Customer: "I need a new laptop for work"

Agent: [Checks Sarah's CDP profile: budget $1000-$2000, prefers Dell/Lenovo]
       [Searches BYS product catalog with filters]
       "Based on your budget and preferences, I have these options:
        1. Dell XPS 13 - $1,299 (your preferred brand)
        2. Lenovo ThinkPad - $1,199 (great for work)
        Which would you like to know more about?"

Customer: "Tell me about the Dell XPS"

Agent: [Provides details...]
       "Would you like to purchase this?"

Customer: "Yes please"

Agent: [BYS API: Add to cart, checkout]
       [Updates CDP user: adds "Dell XPS 13" to interests]
       "Order confirmed! You'll receive tracking details shortly."
```

#### New Customer (NOT Found in CDP)
```
[Agent calls cdp_get_current_user - returns "user not found"]

Agent: "Hi! Welcome! I'm here to help you find exactly what you need.
        What are you looking for today?"

Customer: "I need a laptop for gaming"

Agent: "Gaming laptops, excellent! I can help with that.
        By the way, I'm Alex. What should I call you?"

Customer: "I'm Mike"

Agent: "Nice to meet you, Mike! What's your budget range for the gaming laptop?"

Customer: "Around $1500"

Agent: [Searches products]
       "Perfect! I have great options. Do you have any preferred brands?"

Customer: "I like ASUS"

Agent: "Excellent choice! Before I show you the best ASUS gaming laptops,
        mind if I email you the details? What's your email?"

Customer: "mike@example.com"

Agent: [Creates CDP profile with cdp_create_user:
        full_name="Mike", email_id="mike@example.com", msisdn="+91..."]
       [Updates profile to add first interest:
        product_required="gaming laptops"]
       [Updates profile to add second interest:
        product_required="ASUS", previous_interest="gaming laptops"]

       "Thanks Mike! Here are the top ASUS gaming laptops in your range..."
       [Continues with recommendations]
```

**Key Difference**: New customers experience natural, conversational data collection without forms or registration prompts.

### Configuration

The Sales Agent template is configured in `server_config.json`:

```json
"prompt_templates": {
  "sales_agent": {
    "file": "templates/sales_agent_template.txt",
    "role_name": "Sales Agent",
    "injection_point": "append",
    "visibility": "backend_only"
  }
}
```

**Key Points:**
- Template is **backend-only** (not visible to users)
- Automatically injected when role is selected
- No manual configuration needed
- Works seamlessly with CDP auto-identification

### Template Storage (Firestore)

The Sales Agent template is stored in **Firebase Firestore** for dynamic loading and updates:

- **Collection**: `mcp_server_templates`
- **Document**: `cdp-api-sales-agent`
- **Fallback**: `templates/sales_agent_template.txt` (if Firestore unavailable)

**Benefits:**
- ✅ Update templates without redeploying MCP server
- ✅ Version control and audit trail
- ✅ Instant rollout to all agents
- ✅ A/B testing capabilities
- ✅ Centralized management

**For Backend Team:**
See [FIRESTORE_TEMPLATE_SETUP.md](./FIRESTORE_TEMPLATE_SETUP.md) for:
- Initial upload process
- Loading implementation
- Update procedures
- Security configuration

## Quick Start

### For olbrain-studio Users (Easiest)

1. Open any agent → **Tools** → **MCP Servers**
2. Search for **"CDP API"** in public servers
3. Click **"Add to Agent"**
4. Default configuration connects to production CDP server (`https://converse.showroom.lumegalabs.com`)
5. Start using: *"Show me all users from the CDP"*

### NPM/NPX Installation

```bash
npx -y @olbrain/cdp-api-mcp@latest
```

### Manual Installation
```bash
# Clone the repository
git clone https://github.com/alchemist-ai/alchemist-public-tools.git
cd alchemist-public-tools/mcp_servers/cdp-api

# Install Node.js dependencies
npm install

# Install Python dependencies
pip3 install -r requirements.txt
```

## Configuration

### Default Production Server

The MCP server is pre-configured to connect to the production CDP server:
- **URL**: `https://converse.showroom.lumegalabs.com`
- **Authentication**: Bearer token required
- **Status**: ✅ Online and verified

No configuration needed for default use!

### Custom Server Configuration

If you want to use your own CDP server:

#### Required Environment Variables

- `CDP_API_BASE_URL`: Base URL of your CDP API server
  - Default: `https://converse.showroom.lumegalabs.com`
  - Example: `http://your-cdp-server.com:8000`

#### Optional Environment Variables

- `API_AUTH_TOKEN`: Bearer token for API authentication (if required)

### Configuration in olbrain-studio

When adding this MCP server to olbrain-studio:

1. Navigate to Tools → MCP Servers
2. Add new MCP server
3. Upload `server_config.json` or manually configure:
   - **CDP API Base URL**: Your CDP API endpoint
   - **API Authentication Token**: (Optional) If your API requires auth

## Available Tools

### User Tools

#### 1. `cdp_create_user`
Create a new user in the CDP.

**Parameters:**
- `full_name` (required): User's full name
- `msisdn` (required): Phone number in MSISDN format (e.g., +919876543210)
- `email_id` (optional): User's email address
- `gender` (optional): User's gender (e.g., 'MALE', 'FEMALE')
- `date_of_birth` (optional): Date of birth in DD/MM/YYYY format (e.g., 01/01/1995)
- `client_id` (optional): Client identifier for the user

**Example:**
```json
{
  "full_name": "John Doe",
  "msisdn": "+919876543210",
  "email_id": "john.doe@example.com",
  "gender": "MALE",
  "date_of_birth": "15/05/1990",
  "client_id": "CLT001"
}
```

**Notes:**
- ID is auto-generated by the system and should not be provided during creation
- To add interests, use `cdp_update_user` after creation with the `product_required` and `previous_interest` fields (see "Working with User Interests" section)

#### 2. `cdp_get_current_user`
Get the current user's CDP profile based on session identification.

**Parameters:** None (automatically identifies user from session)

**Description:**
This tool autonomously identifies the current user by:
- Extracting user identifier from session data (email, phone, or user_id)
- Searching CDP database for matching user
- Returning complete user profile with interests and attributes

**Response:**
```json
{
  "success": true,
  "message": "User identified successfully via email",
  "data": {
    "user_id": "user123456789",
    "full_name": "John Doe",
    "email": "john.doe@example.com",
    "phone": "+919876543210",
    "interests": [
      {
        "field": "product_interests",
        "value": "electronics, laptops"
      }
    ],
    "custom_attributes": {
      "budget_range": "$1000-$2000",
      "preferred_brands": "Apple, Dell"
    },
    "matched_by": "email"
  }
}
```

**Use Cases:**
- Personalized product recommendations
- Customer service with user history
- Sales workflows with customer context
- Automatic user profile retrieval at conversation start

#### 3. `cdp_search_users`
Search for users by email, phone, or name.

**Parameters:**
- `email` (optional): Email address to search for
- `phone` (optional): Phone number to search for (any format)
- `name` (optional): Name to search for (partial match supported)

**Description:**
Use this tool when automatic user identification fails (`cdp_get_current_user` returns error). Ask the customer for their email or phone number, then search the CDP database to see if they already have a profile before creating a new one.

**Response:**
```json
{
  "success": true,
  "message": "Found 1 matching user(s)",
  "data": [
    {
      "user_id": "user123456789",
      "full_name": "John Doe",
      "email": "john.doe@example.com",
      "phone": "+919876543210",
      "interests": ["laptops", "gaming"],
      "budget_range": "$1500"
    }
  ]
}
```

**When No Match Found:**
```json
{
  "success": false,
  "error": "No users found matching search criteria",
  "searched_with": {
    "email": "john@example.com",
    "phone": null,
    "name": null
  },
  "message": "No users found. User may need to be created first."
}
```

**Use Cases:**
- Manual user identification when session data unavailable
- Customer lookup by support agents
- Verify user existence before creating duplicate profiles
- Find returning customers who aren't logged in

**Flow:**
1. `cdp_get_current_user` fails (no session identifier)
2. Agent asks: "May I have your email address?"
3. Agent calls: `cdp_search_users(email="customer@example.com")`
4. If found: Use existing profile
5. If not found: Proceed to create new user with `cdp_create_user`

#### 4. `cdp_get_all_users`
Get paginated list of all users.

**Parameters:**
- `page` (optional, default: 0): Page number (0-indexed)
- `size` (optional, default: 10): Number of items per page

#### 5. `cdp_update_user`
Update an existing user.

**Important:** You must provide ALL mandatory fields (id, full_name, msisdn), not just the fields you want to change.

**Parameters:**
- `id` (required): User ID
- `full_name` (required): User's full name (must include even if not changing)
- `msisdn` (required): User's phone number (must include even if not changing)
- `email_id` (optional): User's email address
- `gender` (optional): User's gender
- `date_of_birth` (optional): Date of birth in DD/MM/YYYY format
- `client_id` (optional): Client identifier
- `product_required` (optional): Current/latest product interest
- `previous_interest` (optional): Accumulated chain of past interests (format: "interest1 + interest2 + interest3")

**Example - Basic Update:**
```json
{
  "id": "user123456789",
  "full_name": "John Updated Doe",
  "msisdn": "+919876543210",
  "email_id": "john.updated@example.com",
  "gender": "MALE",
  "date_of_birth": "15/05/1990",
  "client_id": "CLT001"
}
```

**Example - Adding First Interest:**
```json
{
  "id": "user123456789",
  "full_name": "John Doe",
  "msisdn": "+919876543210",
  "product_required": "electronics"
}
```

**Example - Adding Second Interest (Chain Pattern):**
Assuming current state has `product_required: "electronics"` and `previous_interest: ""`:
```json
{
  "id": "user123456789",
  "full_name": "John Doe",
  "msisdn": "+919876543210",
  "product_required": "laptops",
  "previous_interest": "electronics"
}
```

**Example - Adding Third Interest:**
Assuming current state has `product_required: "laptops"` and `previous_interest: "electronics"`:
```json
{
  "id": "user123456789",
  "full_name": "John Doe",
  "msisdn": "+919876543210",
  "product_required": "gaming",
  "previous_interest": "electronics + laptops"
}
```

**Note:** See the "Working with User Interests" section above for complete details on the two-field chain mechanism.

#### 6. `cdp_delete_user`
Delete a user by ID.

**Parameters:**
- `user_id` (required): User ID to delete

## Working with User Interests

User interests use a **two-field chain mechanism**: `product_required` (current interest) and `previous_interest` (accumulated past interests).

### How Interest Chaining Works

**Two Fields:**
- **`product_required`**: Holds the current/latest product interest
- **`previous_interest`**: Accumulates all previous interests in a chain

**The Chain Pattern:**
When adding a new interest, you move the old `product_required` value into the `previous_interest` chain:

```
Current State:
  product_required: "example"
  previous_interest: "apple"

To Add New Interest "laptops":
  product_required: "laptops"           ← Set to new interest
  previous_interest: "apple + example"  ← Concatenate: old_previous + old_product_required
```

### Step-by-Step Example

**Step 1: Create User with First Interest**
```javascript
cdp_create_user({
  full_name: "John Doe",
  msisdn: "+919876543210",
  email_id: "john@example.com"
})
// Then update to add first interest:
cdp_update_user({
  id: "user123...",
  full_name: "John Doe",
  msisdn: "+919876543210",
  product_required: "electronics"
})

// State:
//   product_required: "electronics"
//   previous_interest: "" (empty)
```

**Step 2: Add Second Interest**
```javascript
cdp_update_user({
  id: "user123...",
  full_name: "John Doe",
  msisdn: "+919876543210",
  product_required: "laptops",           // ← New interest
  previous_interest: "electronics"       // ← Move old product_required here
})

// State:
//   product_required: "laptops"
//   previous_interest: "electronics"
```

**Step 3: Add Third Interest**
```javascript
cdp_update_user({
  id: "user123...",
  full_name: "John Doe",
  msisdn: "+919876543210",
  product_required: "gaming",                  // ← New interest
  previous_interest: "electronics + laptops"   // ← Concatenate: old_previous + old_product_required
})

// State:
//   product_required: "gaming"
//   previous_interest: "electronics + laptops"
```

**Step 4: Add Fourth Interest**
```javascript
cdp_update_user({
  id: "user123...",
  full_name: "John Doe",
  msisdn: "+919876543210",
  product_required: "smartphones",                      // ← New interest
  previous_interest: "electronics + laptops + gaming"   // ← Concatenate chain
})

// State:
//   product_required: "smartphones"
//   previous_interest: "electronics + laptops + gaming"
```

### Important Implementation Notes

**✅ DO:**
- Use `product_required` for the current/latest interest
- Use `previous_interest` to accumulate the chain of past interests
- Concatenate with ` + ` (space + plus + space) as the separator
- Always read the current values before updating to avoid overwriting

**❌ DON'T:**
- Don't overwrite `previous_interest` without including old values
- Don't pass arrays (only string concatenation supported)
- Don't add interests during user creation (use update after creation)

**Chain Format:**
```
previous_interest: "interest1 + interest2 + interest3 + interest4"
```

### Reading User Interests

When retrieving user data, you'll see both fields:
```json
{
  "product_required": "smartphones",
  "previous_interest": "electronics + laptops + gaming"
}
```

To get the full interest history, combine them:
```
All interests: previous_interest.split(" + ") + [product_required]
Result: ["electronics", "laptops", "gaming", "smartphones"]
```

## API Format

### Field Name Format

The CDP API uses standard **snake_case** format for all field names.

**Format:** snake_case (lowercase with underscores)
- Used consistently across all API requests and responses
- Example: `full_name`, `email_id`, `msisdn`, `date_of_birth`, `client_id`, `product_required`, `previous_interest`

**Field Names:**
| Field Name | Description |
|-----------|-------------|
| `full_name` | User's full name |
| `email_id` | User's email address |
| `msisdn` | User's phone number in MSISDN format |
| `gender` | User's gender |
| `date_of_birth` | Date of birth (DD/MM/YYYY format) |
| `client_id` | Client identifier |
| `id` | User ID |
| `product_required` | Current/latest product interest |
| `previous_interest` | Accumulated chain of past interests |

**Example API Request:**
```json
{
  "full_name": "John Doe",
  "email_id": "john@example.com",
  "msisdn": "+919876543210",
  "gender": "MALE",
  "date_of_birth": "15/05/1990",
  "client_id": "CLT001",
  "product_required": "laptops",
  "previous_interest": "electronics"
}
```

All fields use snake_case consistently. No conversion or special formatting is required.

## Testing

To test the CDP API MCP server:

1. Ensure your CDP API is running:
   ```bash
   # Your CDP API should be accessible at the configured base URL
   curl https://converse.showroom.lumegalabs.com/cdp-user-api/users
   ```

2. Test the MCP server:
   ```bash
   # Set environment variables
   export CDP_API_BASE_URL=https://converse.showroom.lumegalabs.com

   # Run the server
   node index.js
   ```

3. Send MCP protocol messages via stdin:
   ```json
   {"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
   {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
   ```

## Development

### Project Structure
```
cdp-api/
├── index.js              # Node.js entry point
├── package.json          # NPM package configuration
├── requirements.txt      # Python dependencies
├── server_config.json    # MCP server configuration
├── README.md            # This file
├── templates/
│   └── sales_agent_template.txt  # Sales Agent role template (backend-injected)
└── src/
    ├── server.py         # Main MCP server implementation
    ├── cdp_client.py     # CDP API client
    ├── cdp_executor.py   # Template execution engine (session-aware)
    └── tools/
        └── user_tools.py   # User management tools
```

### Adding New Tools

1. Define tool in `user_tools.py`
2. Create async handler function
3. Add handler to `TOOL_HANDLERS` dict
4. Add tool definition to `TOOLS` list

## Requirements

- **Node.js**: >= 16.0.0
- **Python**: >= 3.7
- **Python Package**: requests >= 2.31.0

## Troubleshooting

### Server won't start
- Verify `CDP_API_BASE_URL` environment variable is set
- Check that Python 3 is installed and accessible
- Ensure `requirements.txt` dependencies are installed

### API requests failing
- Verify CDP API is running and accessible
- Check base URL format (should include protocol: http:// or https://)
- If using authentication, verify `API_AUTH_TOKEN` is correct

### Tool execution errors
- Check MCP server logs (written to stderr)
- Verify API endpoint paths match your CDP API implementation
- Ensure request data format matches expected schema (snake_case)

## Production Deployment

This MCP server is connected to a live production CDP server with real data:
- **8+ users** already in system
- **Real-time updates** supported
- **Authentication** required for production server

See [DEPLOYMENT.md](./DEPLOYMENT.md) for complete deployment guide.

## Testing

The server has been tested with:
- ✅ User creation with interests field (both camelCase and snake_case formats)
- ✅ User retrieval with pagination
- ✅ User updates including interests
- ✅ User deletions
- ✅ Current user identification from session
- ✅ User search by email, phone, or name
- ✅ Real production CDP server integration

## Documentation

- **[DEPLOYMENT.md](./DEPLOYMENT.md)** - Complete deployment guide
- **[README.md](./README.md)** - This file
- **[server_config.json](./server_config.json)** - MCP server configuration

## License

MIT

## Author

Alchemist

## Repository

https://github.com/alchemist-ai/alchemist-public-tools

## Support

For issues and feature requests, please visit the GitHub repository.