@markstiles/sitecore-cdp-mcp
v1.0.0
Published
Model Context Protocol (MCP) server for Sitecore Customer Data Platform APIs
Downloads
9
Maintainers
Readme
Sitecore CDP MCP Server
A Model Context Protocol (MCP) server for the Sitecore Customer Data Platform (CDP) APIs. This package enables AI assistants like Claude to interact with Sitecore CDP for guest management, order tracking, and audience exports.
Features
- Guest Management: Create, search, retrieve, update, and patch guest profiles
- Type-Safe: Full TypeScript support with exported types
- Validation: Input validation using Zod schemas matching OpenAPI specs
- Error Handling: Comprehensive error handling with retry logic
- Pagination: Support for paginated results with user control
- Environment-Based: Configuration via environment variables
Installation
npm install @markstiles/sitecore-cdp-mcpConfiguration
Environment Variables
Create a .env file in your project root:
# Required: Your CDP instance base URL
CDP_BASE_URL=https://api-engage-us.sitecorecloud.io
# Required: Basic Auth credentials (for Guest and Order APIs)
CDP_CLIENT_KEY=your_client_key
CDP_API_TOKEN=your_api_token
# Optional: OAuth 2.0 credentials (for Audience Export API)
# Note: Only required if using Audience Export features
# These are different from Basic Auth credentials above
CDP_OAUTH_KEY=your_oauth_client_id
CDP_OAUTH_SECRET=your_oauth_client_secret
# Optional: Retry configuration
CDP_RETRY_MAX_ATTEMPTS=3
CDP_RETRY_DELAY_MS=1000Finding Your Credentials
Basic Auth Credentials (Guest & Order APIs)
In Sitecore CDP:
- Navigate to Settings > API Access
- Client Key = Your username for Basic Auth (
CDP_CLIENT_KEY) - API Token = Your password for Basic Auth (
CDP_API_TOKEN)
OAuth 2.0 Credentials (Audience Export API)
For Audience Export functionality, you need separate OAuth credentials:
- Navigate to Settings > API Access > OAuth
- Create or use existing OAuth client credentials
- OAuth Client ID =
CDP_OAUTH_KEY - OAuth Client Secret =
CDP_OAUTH_SECRET
Note: OAuth tokens are managed automatically by the server with in-memory caching (24-hour expiry with 5-minute refresh buffer).
MCP Server Setup
Claude Desktop Configuration
Add to your Claude Desktop configuration file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"sitecore-cdp": {
"command": "node",
"args": [
"/path/to/node_modules/@markstiles/sitecore-cdp-mcp/dist/index.js"
],
"env": {
"CDP_BASE_URL": "https://api-engage-us.sitecorecloud.io",
"CDP_CLIENT_KEY": "your_client_key",
"CDP_API_TOKEN": "your_api_token",
"CDP_OAUTH_KEY": "your_oauth_client_id",
"CDP_OAUTH_SECRET": "your_oauth_client_secret"
}
}
}
}Note: OAuth credentials are only required if you plan to use Audience Export features. Guest and Order management only require Basic Auth credentials.
Or if installed globally:
{
"mcpServers": {
"sitecore-cdp": {
"command": "sitecore-cdp-mcp",
"env": {
"CDP_BASE_URL": "https://api-engage-us.sitecorecloud.io",
"CDP_CLIENT_KEY": "your_client_key",
"CDP_API_TOKEN": "your_api_token",
"CDP_OAUTH_KEY": "your_oauth_client_id",
"CDP_OAUTH_SECRET": "your_oauth_client_secret"
}
}
}
}Available MCP Tools
Phase 1: Guest Management
cdp_guest_create
Create a new guest profile in Sitecore CDP.
Important: Always search for existing guests by email before creating to avoid duplicates.
// Example usage in Claude
{
"guestType": "customer",
"firstName": "John",
"lastName": "Doe",
"email": "[email protected]",
"phoneNumbers": ["+353161123345"],
"city": "Dublin",
"country": "IE"
}Parameters:
guestType(required):"visitor","customer", or"traveller"firstName: Guest's first namelastName: Guest's last nameemail: Primary email addressemails: Array of email addressesphoneNumbers: Array of phone numbers (E.164 format)dateOfBirth: ISO 8601 date-time (must be in the past)gender:"male","female", or"unknown"title: Title (e.g., "Mr", "Mrs", "Dr")city,state,country,postCode,street: Address fieldsnationality,passportNumber,passportExpiry: Travel fieldsidentifiers: Array of{provider, id}objects for external system linking
cdp_guest_search
Search for guests by email, identifiers, or order information.
{
"email": "[email protected]",
"limit": 10,
"offset": 0
}Parameters:
email: Search by email addressidentifiers: Search by identifier (format:"provider:id")orderReferenceId: Search by order reference IDorderRef: Search by order referenceoffset: Pagination offset (default: 0)limit: Results per page (default: 10, max: 100)sort: Sort field (e.g.,"createdAt")expand: Include related data (default: false)
cdp_guest_get
Retrieve a guest profile by reference ID.
{
"guestRef": "guest-reference-id",
"expand": false
}Parameters:
guestRef(required): The guest reference IDexpand: Include data extensions and related data
cdp_guest_update
Update a guest profile with full replacement (PUT). All fields must be provided.
{
"guestRef": "guest-reference-id",
"guestType": "customer",
"firstName": "John",
"lastName": "Doe",
"email": "[email protected]",
"city": "London"
}Note: This is a full replacement. Use cdp_guest_patch for partial updates.
cdp_guest_patch
Update specific fields of a guest profile (PATCH). Only provided fields are updated.
{
"guestRef": "guest-reference-id",
"city": "London",
"country": "GB"
}Parameters: Same as create/update, but all fields are optional except guestRef.
Phase 2: Order Management
cdp_order_create
Create a new order in Sitecore CDP.
{
"referenceId": "ORDER-12345",
"orderedAt": "2024-01-15T10:30:00Z",
"currencyCode": "USD",
"price": 99.99,
"status": "PURCHASED",
"channel": "WEB"
}Required Parameters:
referenceId: Unique order identifier from your systemorderedAt: ISO 8601 timestamp when order was placedcurrencyCode: ISO 4217 3-letter currency code (e.g., USD, EUR, GBP)price: Order amount
Optional Parameters:
status: Order status -PENDING,CONFIRMED,PURCHASED,CANCELLED, etc.channel: Sales channel -WEB,MOBILE_APP,CALL_CENTER,BRANCH, etc.pointOfSale: Point of sale locationtotal: Total including taxes and shippingsubtotal: Subtotal before taxespaymentType: Payment methodcardType: Card type if applicable
cdp_order_get
Retrieve an order by reference.
{
"orderRef": "order-reference-id",
"expand": true
}cdp_order_search
Search for orders by reference ID or guest.
{
"guestRef": "guest-reference-id",
"limit": 10,
"offset": 0
}Parameters:
referenceId: Filter by order reference IDguestRef: Filter by guest referenceoffset,limit,sort,expand: Pagination options
cdp_order_update
Update an order (full replacement - all fields required).
cdp_order_patch
Partially update an order (only provided fields updated).
cdp_order_item_add
Add an item to an existing order.
{
"orderRef": "order-reference-id",
"type": "product",
"name": "Premium Widget",
"price": 49.99,
"currencyCode": "USD",
"status": "CONFIRMED",
"productId": "WIDGET-001",
"referenceId": "ITEM-12345",
"quantity": 2
}Required Parameters:
orderRef: The order to add the item totype: Item type (e.g.,product,service)name: Item name/descriptionprice: Item pricecurrencyCode: Currency codestatus: Item status (e.g.,CONFIRMED)productId: Product identifierreferenceId: Item reference
cdp_order_contact_create
Create an order contact to link an order to a guest.
{
"orderRef": "order-reference-id",
"guestRef": "guest-reference-id",
"firstName": "John",
"lastName": "Doe",
"emails": ["[email protected]"]
}Parameters:
orderRef(required): The order referenceguestRef(optional): Link to existing guest- Contact fields:
firstName,lastName,emails,phoneNumbers,street,city, etc.
Programmatic Usage
You can also use this package programmatically in your Node.js applications:
import { GuestClient } from '@markstiles/sitecore-cdp-mcp';
const client = new GuestClient();
// Create a guest
const result = await client.createGuest({
guestType: 'customer',
firstName: 'Jane',
lastName: 'Smith',
email: '[email protected]',
});
console.log('Guest created:', result.ref);
// Search for guests
const searchResults = await client.searchGuests({
email: '[email protected]',
});
console.log('Found guests:', searchResults.items.length);
// Get guest details
const guest = await client.getGuest(result.ref);
console.log('Guest details:', guest);
// Update guest
const updated = await client.patchGuest(result.ref, {
city: 'Dublin',
country: 'IE',
});
// Delete guest
await client.deleteGuest(result.ref);Order Management
import { OrderClient, GuestClient } from '@markstiles/sitecore-cdp-mcp';
const orderClient = new OrderClient();
const guestClient = new GuestClient();
// Create an order
const order = await orderClient.createOrder({
referenceId: 'ORDER-12345',
orderedAt: new Date().toISOString(),
currencyCode: 'USD',
price: 149.99,
status: 'PURCHASED',
channel: 'WEB',
});
console.log('Order created:', order.ref);
// Add items to the order
const item = await orderClient.createOrderItem(order.ref, {
type: 'product',
name: 'Premium Widget',
price: 49.99,
currencyCode: 'USD',
status: 'CONFIRMED',
productId: 'WIDGET-001',
referenceId: 'ITEM-001',
quantity: 3,
});
// Link order to a guest via order contact
const contact = await orderClient.createOrderContact(
order.ref,
{
firstName: 'Jane',
lastName: 'Smith',
emails: ['[email protected]'],
},
guestRef // Optional: link to existing guest
);
// Search for guest's orders
const guestOrders = await orderClient.searchOrders({
guestRef: guestRef,
limit: 10,
});
console.log('Guest orders:', guestOrders.items.length);Type Exports
All TypeScript types are exported for use in your applications:
import {
// Guest types
Guest,
GuestCreateRequest,
GuestUpdateRequest,
GuestPatchRequest,
GuestSearchParams,
// Order types
Order,
OrderCreateRequest,
OrderUpdateRequest,
OrderPatchRequest,
OrderSearchParams,
OrderItem,
OrderItemCreateRequest,
OrderContact,
OrderContactCreateRequest,
// Common types
PaginatedResponse,
CdpError,
Identifier,
GuestType,
} from '@markstiles/sitecore-cdp-mcp';Testing
Running Integration Tests
Integration tests run against your real CDP environment:
- Set up your
.envfile with test credentials - Run tests:
npm testNote: Integration tests create and delete real data in your CDP instance. Use a test/development environment.
Test Coverage
npm run test:coverageWatch Mode
npm run test:watchDevelopment
Building
npm run buildDevelopment Mode
npm run devError Handling
All errors from the CDP API are transformed into structured CdpError objects:
interface CdpError {
status: number; // HTTP status code
code: number; // CDP error code
message: string; // User-friendly message
developerMessage: string; // Technical details
moreInfoUrl?: string; // Support documentation link
}Retry Logic
The client automatically retries failed requests for:
- 5xx server errors
- 429 rate limiting errors
Retry behavior is configurable via environment variables:
CDP_RETRY_MAX_ATTEMPTS: Maximum retry attempts (default: 3)CDP_RETRY_DELAY_MS: Initial delay in milliseconds (default: 1000)
Exponential backoff is applied: delay * 2^retryCount
Regional Endpoints
Sitecore CDP is available in multiple regions. Set your base URL accordingly:
- US:
https://api-engage-us.sitecorecloud.io - EU:
https://api-engage-eu.sitecorecloud.io - AP:
https://api-engage-ap.sitecorecloud.io - JP:
https://api-engage-jpe.sitecorecloud.io
Security & Credential Management
Current Architecture (Environment Variables)
This MCP server uses environment variables for credential management, which is the most secure approach for several reasons:
- Credentials are never exposed in code or logs
- MCP clients (like Claude Desktop) securely pass environment variables to the server process
- Credentials are never transmitted over the network or stored in chat history
- Each user's credentials remain on their local machine
Alternative Approaches Considered
Option 1: Tool-Level Parameters (Not Recommended)
Passing credentials as parameters to each tool call would:
- ❌ Expose credentials in chat history and logs
- ❌ Require credentials to be provided with every request
- ❌ Create security risks if the conversation is shared
Option 2: MCP Server Prompts (Future Enhancement)
The MCP protocol supports prompting users for input. A future enhancement could:
- ✅ Prompt for credentials on first tool use
- ✅ Cache credentials in memory for the session
- ✅ Provide better UX for non-technical users
- ⚠️ Requires MCP client support for prompts
Current Status: Environment variables provide the best balance of security, simplicity, and compatibility across MCP clients.
VS Code Extension Integration
For VS Code extensions that provide MCP servers, the resolveMcpServerDefinition method can handle authentication dynamically:
resolveMcpServerDefinition(server, token) {
// Extension can prompt for credentials here
// Can integrate with VS Code's authentication API
return {
...server,
env: {
CDP_CLIENT_KEY: await getCredential('clientKey'),
CDP_API_TOKEN: await getCredential('apiToken')
}
};
}This approach is useful for shared/team extensions but requires VS Code-specific implementation.
Roadmap
✅ Phase 1: Guest Management (Completed)
- Create, search, retrieve, update, and patch guest profiles
- Full CRUD operations with validation
- Pagination and error handling
✅ Phase 2: Order Management (Completed)
- Create and manage orders
- Link orders to guests via order contacts
- Add order items with full product details
- Search orders by guest or reference ID
Phase 3: Data Extensions (Coming Soon)
- Guest data extensions
- Order data extensions
- Order item data extensions
- Custom field management
Phase 4: Audience Export (Coming Soon)
- List and retrieve audience export jobs
- Download exported audience data
- OAuth 2.0 authentication with automatic token refresh
Resources
- Sitecore CDP Developer Documentation
- Model Context Protocol Documentation
- Claude Desktop Documentation
Publishing to npm
This section is for maintainers who want to publish the package to npm.
Prerequisites
npm Account: Create an account at npmjs.com
Login to npm:
npm loginEnter your username, password, and email when prompted.
Verify Login:
npm whoami
First-Time Setup
If publishing a scoped package (like @markstiles/sitecore-cdp-mcp), decide on access level:
Option 1: Public Package (Free)
npm publish --access publicOption 2: Private Package (Requires paid npm account)
npm publishPublishing Process
Update Version
Follow Semantic Versioning:
# Patch release (1.0.0 → 1.0.1) - Bug fixes npm version patch # Minor release (1.0.0 → 1.1.0) - New features, backward compatible npm version minor # Major release (1.0.0 → 2.0.0) - Breaking changes npm version majorThis automatically:
- Updates version in package.json
- Creates a git commit
- Creates a git tag
Build the Package
npm run buildThe
prepublishOnlyscript will run this automatically, but it's good to verify first.Test the Package Locally (Optional)
# Create a tarball npm pack # This creates @markstiles-sitecore-cdp-mcp-1.0.0.tgz # Test install in another project: cd /path/to/test-project npm install /path/to/cdp2/@markstiles-sitecore-cdp-mcp-1.0.0.tgzRun Tests
npm testMake sure all tests pass before publishing.
Publish to npm
# For scoped packages (first time) npm publish --access public # For subsequent releases npm publishPush Git Changes
git push origin main --follow-tags
Package Contents
The published package includes (configured in package.json files array):
dist/- Compiled JavaScript and TypeScript declarationsREADME.md- Package documentationLICENSE- MIT license file
Excluded (via .npmignore):
- Source TypeScript files (
src/) - Tests (
test/) - Environment files (
.env*) - Development configs
Post-Publishing
Verify on npm: Visit
https://www.npmjs.com/package/@markstiles/sitecore-cdp-mcpTest Installation:
npm install @markstiles/sitecore-cdp-mcpCreate GitHub Release (Optional):
- Go to your GitHub repository
- Create a release from the version tag
- Add release notes describing changes
Version Management Strategy
Recommended approach for this project:
- Patch (1.0.x): Bug fixes, documentation updates, test improvements
- Minor (1.x.0): New tools, new API endpoints, new features (backward compatible)
- Example: Adding Phase 3 (Data Extensions) → 1.1.0
- Example: Adding Phase 4 (Audience Export) → 1.2.0
- Major (x.0.0): Breaking changes to public API, removed tools, changed interfaces
- Example: Changing tool names or parameters → 2.0.0
- Example: Requiring different authentication → 2.0.0
Troubleshooting
Error: "You do not have permission to publish"
- Make sure you're logged in:
npm whoami - For scoped packages, use
--access public - Verify the package name is available
Error: "Version already published"
- Update version:
npm version patch - Each version can only be published once
Error: "Package name too similar to existing package"
- Choose a different name or add a scope
- Scoped packages (@username/package) are unique to your account
Automated Publishing with GitHub Actions
For automated releases, create .github/workflows/publish.yml:
name: Publish to npm
on:
release:
types: [created]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm test
- run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}Then add your npm token to GitHub repository secrets as NPM_TOKEN.
License
MIT License - see LICENSE file for details
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and questions:
- GitHub Issues: https://github.com/markstiles/sitecore-cdp-mcp/issues
- Sitecore CDP Support: https://support.sitecore.com
Author
Mark Stiles
Acknowledgments
Built with:
