Documentation Index
Fetch the complete documentation index at: https://docs.snappy.com/llms.txt
Use this file to discover all available pages before exploring further.
Snappy’s MCP (Model Context Protocol) Server allows AI systems — such as Microsoft Copilot, custom AI agents, or any MCP-compatible client — to send gifts through natural language interactions. Instead of building API integrations manually, your AI agent can call Snappy’s MCP tools directly to manage campaigns and send gifts on behalf of users.
This integration path is designed for AI-driven environments. If you’re building a standard programmatic integration, use the Snappy REST API instead.
Prerequisites
Before connecting an AI system to the MCP server, make sure the following are configured in your Snappy Dashboard:
- A valid Snappy user account (username, password, and optional TOTP)
- At least one Company and Account
- At least one Collection configured for your Account
- Recipients set up, or ready to be managed via API
The MCP server endpoint is provisioned by Snappy. Contact your account manager to get the URL for your environment.
How It Works
Your AI system connects to the Snappy MCP server and authenticates using user credentials. Once authenticated, it can call a set of structured tools to retrieve collections, generate personalized content, create campaigns, and send gifts — all through a standardized protocol.
Authentication
The MCP server uses session-based authentication. Call the sign-in tool with your Snappy credentials to establish a session:
{
"method": "tools/call",
"params": {
"name": "sign-in",
"arguments": {
"username": "your@email.com",
"password": "your_password",
"totp": "123456"
}
}
}
Successful response:
{
"content": [
{
"type": "text",
"text": "Successfully signed in. Available accounts: [Account data]"
}
]
}
For HTTP transport, each request must include authentication. For SSE transport, the session is maintained automatically after sign-in.
Never hardcode usernames, passwords, or TOTP codes. Use environment variables or a secrets manager. See Best Practices below.
| Tool | Purpose | Required auth | Key parameters |
|---|
sign-in | Authenticate with the MCP server | No | username, password, totp? |
check-sign-in | Verify current authentication status | No | None |
get-account-collections | List collections available to an Account | Yes | accountId |
get-collection-products | Retrieve products within a collection | Yes | collectionId, maxBudget?, country? |
create-email | Generate AI-powered email content | Yes | occasion, tone?, primaryColor? |
create-greeting | Generate a personalized greeting card | Yes | occasion, tone?, primaryColor? |
choose-reveal | Select the gift reveal experience | Yes | occasion, brandColors? |
create-campaign | Create a new gift campaign | Yes | companyId, accountId, collectionId, name, budgets, recipientsIds |
send-gifts | Send gifts within a campaign | Yes | campaignId, recipients, budget, productCollectionId |
get-account-collections
{
"method": "tools/call",
"params": {
"name": "get-account-collections",
"arguments": {
"accountId": "account_12345"
}
}
}
Response:
{
"content": [{
"type": "text",
"text": "[{\"_id\":\"coll_123\",\"name\":\"Premium Business Collection\",\"rank\":1},{\"_id\":\"coll_456\",\"name\":\"Holiday Special Collection\",\"rank\":2}]"
}]
}
create-campaign
{
"method": "tools/call",
"params": {
"name": "create-campaign",
"arguments": {
"companyId": "comp_789",
"accountId": "acc_123",
"collectionId": "coll_456",
"name": "Q4 Employee Appreciation Campaign",
"maxBudget": 75,
"minBudget": 25,
"recipientsIds": ["recipient_1", "recipient_2"],
"email": {
"mailSubject": "A special gift for you!",
"mailGreeting": "Dear {receiver_first_name}",
"mailBody": "We appreciate your hard work this quarter.",
"mailSignature": "Best regards, The Team"
}
}
}
}
The Gift Sending Flow
Regardless of which AI system you’re connecting, the gifting flow follows the same sequence:
sign-in — authenticate and establish a session
get-account-collections — retrieve available collections
create-email + create-greeting + choose-reveal — generate personalized content (these three can run in parallel)
create-campaign — set up the campaign with recipients and content
send-gifts — trigger the gift send
Quick Start: Adding to Your AI Agent (MCP Config)
To add Snappy to any MCP-compatible AI environment, point your MCP configuration to the Snappy server URL provided by your account manager:
const mcpConfig = {
serverUrl: "<your-snappy-mcp-server-url>",
transport: "http",
authentication: {
type: "user_credentials",
endpoint: "/auth/sign-in"
}
};
Worked Example: Node.js Bot
A complete Node.js example that handles a /sendgift chat command, authenticates, generates personalized content in parallel, and creates and sends a campaign.
const MCPClient = require('./mcp-client');
class SnappyGiftBot {
constructor() {
this.mcpClient = new MCPClient(process.env.SNAPPY_MCP_URL);
}
async sendGift(params) {
// 1. Authenticate (use cached session in production)
await this.mcpClient.signIn(
process.env.SNAPPY_USERNAME,
process.env.SNAPPY_PASSWORD
);
// 2. Get collections and pick one for the occasion
const collections = await this.mcpClient.getAccountCollections(params.accountId);
const selectedCollection = this.selectBestCollection(collections, params.occasion);
// 3. Generate personalized content in parallel
const [email, greeting, reveal] = await Promise.all([
this.mcpClient.createEmail({ occasion: params.occasion, tone: 'professional' }),
this.mcpClient.createGreeting({ occasion: params.occasion }),
this.mcpClient.chooseReveal({ occasion: params.occasion })
]);
// 4. Create campaign
const campaign = await this.mcpClient.createCampaign({
companyId: params.companyId,
accountId: params.accountId,
collectionId: selectedCollection._id,
name: `${params.occasion} Gift - ${new Date().toLocaleDateString()}`,
maxBudget: params.maxBudget,
minBudget: params.minBudget,
recipientsIds: [params.recipientId],
email: JSON.parse(email.content)
});
// 5. Send gifts
await this.mcpClient.sendGifts({
campaignId: campaign.created._id,
recipients: { type: 'ids', recipientsList: [params.recipientId] },
budget: { plan: params.budget, max: params.maxBudget, min: params.minBudget },
productCollectionId: selectedCollection._id
});
return { campaignName: campaign.name, collectionName: selectedCollection.name };
}
}
Error Handling
Common error scenarios
Authentication failed
{
"error": {
"code": "AUTH_FAILED",
"message": "Login failed",
"details": "Invalid username or password"
}
}
TOTP required
{
"content": [{
"type": "text",
"text": "Please enter your TOTP code from your authenticator app"
}]
}
When you see this response, prompt the user (or your secret store) for the current TOTP and re-call sign-in with the totp argument populated.
Resource not found
{
"error": {
"code": "NOT_FOUND",
"message": "Collection not found",
"collectionId": "invalid_collection_id"
}
}
No products available for criteria
{
"error": {
"code": "NO_PRODUCTS_AVAILABLE",
"message": "No products available for the specified criteria",
"details": {
"budget": 25,
"country": "US",
"collectionId": "coll_123"
}
}
}
Retry strategy
Use exponential backoff for transient failures (network errors, timeouts, 5xx). Do not retry AUTH_FAILED or NOT_FOUND.
class MCPErrorHandler {
static async withRetry(operation, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
if (attempt === maxRetries || !this.isRetryableError(error)) {
throw error;
}
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
static isRetryableError(error) {
return ['NETWORK_ERROR', 'TIMEOUT', 'SERVER_ERROR'].includes(error.code);
}
}
Best Practices
Secure credentials. Never hardcode username, password, or TOTP. Pull them from environment variables or a secrets manager. When logging tool calls for observability, redact password and totp before writing.
Reuse sessions. Don’t call sign-in on every request. Cache the session and refresh only when expired:
class MCPSessionManager {
constructor() {
this.session = null;
this.lastAuth = null;
}
async getValidSession() {
if (this.isSessionExpired()) {
this.session = await this.authenticate();
this.lastAuth = Date.now();
}
return this.session;
}
}
Run content generation in parallel. create-email, create-greeting, and choose-reveal are independent — call them concurrently to cut latency.
Cache collections. Collection data changes infrequently. A 5-minute in-memory cache keyed by accountId is usually sufficient.
Troubleshooting
Check authentication status before debugging tool calls:
const authStatus = await mcpClient.checkSignIn();
console.log('Auth Status:', authStatus);
Confirm account setup if collections come back empty:
const collections = await mcpClient.getAccountCollections(accountId);
if (collections.length === 0) {
throw new Error('No collections available. Set up collections in the Snappy Dashboard.');
}
Test individual tools in isolation when narrowing down a failing flow — call get-account-collections and get-collection-products directly to verify the data exists before calling create-campaign.
For additional support, contact your Snappy account manager.