@agentman/chat-widget
Version:
Agentman Chat Widget for easy integration with web applications
657 lines (556 loc) • 13.9 kB
Markdown
# MCP Response Structure Specification
## Core Response Schema
Every MCP response follows this structure to enable intelligent routing and rich UI rendering:
```typescript
interface MCPResponse {
// Required: Identifies the UI component type
uiType: string;
// Required: Minimal data for LLM understanding (token-efficient)
structuredContent: {
[key: string]: any;
// Keep this as small as possible
// Only include what the LLM needs to understand context
};
// Optional: Text/markdown for model narration
content?: Array<{
type: 'text' | 'markdown';
text: string;
}>;
// Required: Rich data for UI rendering (never sent to LLM)
_meta: {
[key: string]: any;
// Full data for UI components
// Can be as large as needed
};
// Optional: UI-specific metadata
uiMetadata?: {
component: string; // Specific component name
version: string; // Component version
provider: string; // Data provider (shopify, calendar, etc.)
priority?: 'high' | 'medium' | 'low';
renderMode?: 'immediate' | 'lazy' | 'progressive';
};
}
```
## Response Types by Category
### 1. Product Display Responses
#### Shopify Products Grid
```typescript
interface ShopifyProductsResponse extends MCPResponse {
uiType: 'shopify-products';
structuredContent: {
// Minimal for LLM (5-10 products max)
totalCount: number;
priceRange: {
min: number;
max: number;
currency: string;
};
topProducts: Array<{
id: string;
title: string;
price: number;
}>;
categories: string[];
};
_meta: {
// Full product data for UI
products: Array<{
id: string;
title: string;
description: string;
price: number;
compareAtPrice?: number;
images: Array<{
url: string;
alt: string;
}>;
variants: Array<{
id: string;
title: string;
price: number;
available: boolean;
sku: string;
}>;
vendor: string;
tags: string[];
rating?: number;
reviewCount?: number;
}>;
// Filtering and sorting options
filters: {
categories: string[];
priceRanges: Array<{ min: number; max: number; label: string }>;
vendors: string[];
tags: string[];
};
sortOptions: Array<{
value: string;
label: string;
default?: boolean;
}>;
// Pagination
pagination: {
page: number;
pageSize: number;
totalPages: number;
totalItems: number;
};
};
}
```
#### Single Product Detail
```typescript
interface ProductDetailResponse extends MCPResponse {
uiType: 'product-detail';
structuredContent: {
id: string;
title: string;
price: number;
available: boolean;
category: string;
};
_meta: {
product: DetailedProduct;
relatedProducts: Product[];
reviews: Review[];
shipping: ShippingInfo;
returnPolicy: string;
};
}
```
### 2. Form Responses
#### Lead Capture Form
```typescript
interface LeadFormResponse extends MCPResponse {
uiType: 'form-lead';
structuredContent: {
formType: 'lead_capture';
purpose: string;
requiredFields: string[];
estimatedTime: string; // "2 minutes"
};
_meta: {
formSchema: {
id: string;
title: string;
description?: string;
fields: Array<{
id: string;
type: 'text' | 'email' | 'tel' | 'select' | 'textarea' | 'checkbox' | 'radio';
label: string;
placeholder?: string;
required: boolean;
validation?: {
pattern?: string;
minLength?: number;
maxLength?: number;
min?: number;
max?: number;
customValidator?: string;
errorMessage?: string;
};
options?: Array<{
value: string;
label: string;
disabled?: boolean;
}>;
conditions?: Array<{
field: string;
operator: 'equals' | 'not_equals' | 'contains' | 'greater_than' | 'less_than';
value: any;
}>;
}>;
submitButton: {
text: string;
loadingText?: string;
successText?: string;
};
layout?: {
type: 'single-column' | 'two-column' | 'grid';
columns?: number;
};
};
submitConfig: {
endpoint: string;
method: 'POST' | 'PUT';
headers?: Record<string, string>;
successMessage: string;
errorMessage?: string;
redirectUrl?: string;
confirmationEmail?: boolean;
};
prefillData?: Record<string, any>;
analytics?: {
formId: string;
campaignId?: string;
source?: string;
};
};
}
```
#### Payment Form
```typescript
interface PaymentFormResponse extends MCPResponse {
uiType: 'form-payment';
structuredContent: {
formType: 'payment';
amount: number;
currency: string;
purpose: string;
secureFields: string[]; // Fields that need tokenization
};
_meta: {
formSchema: FormSchema; // Similar to lead form
paymentConfig: {
amount: number;
currency: string;
paymentMethods: Array<'card' | 'paypal' | 'apple_pay' | 'google_pay'>;
stripePublicKey?: string;
paypalClientId?: string;
useTokenization: boolean;
requiresBillingAddress: boolean;
requiresShippingAddress: boolean;
};
securityConfig: {
tokenizationEndpoint: string;
encryptionKey?: string;
pciCompliant: boolean;
};
};
}
```
#### Quick Choice Buttons
```typescript
interface ChoiceFormResponse extends MCPResponse {
uiType: 'form-choices';
structuredContent: {
question: string;
optionCount: number;
multiSelect: boolean;
};
_meta: {
question: string;
description?: string;
choices: Array<{
id: string;
label: string;
description?: string;
icon?: string;
color?: string;
value: any;
disabled?: boolean;
metadata?: Record<string, any>;
}>;
layout: {
type: 'buttons' | 'cards' | 'list' | 'grid';
columns?: number;
showIcons?: boolean;
showDescriptions?: boolean;
};
behavior: {
multiSelect: boolean;
minSelections?: number;
maxSelections?: number;
autoSubmit: boolean;
confirmationRequired: boolean;
};
};
}
```
### 3. Data Visualization Responses
#### Chart/Graph Display
```typescript
interface ChartResponse extends MCPResponse {
uiType: 'chart';
structuredContent: {
chartType: 'line' | 'bar' | 'pie' | 'scatter';
dataPoints: number;
summary: string; // "Sales increased 25% this month"
};
_meta: {
chartConfig: {
type: string;
title: string;
subtitle?: string;
data: {
labels: string[];
datasets: Array<{
label: string;
data: number[];
backgroundColor?: string | string[];
borderColor?: string;
// ... other chart.js options
}>;
};
options: {
responsive: boolean;
maintainAspectRatio: boolean;
legend?: object;
scales?: object;
// ... other chart.js options
};
};
interactivity?: {
clickable: boolean;
hoverable: boolean;
zoomable: boolean;
downloadable: boolean;
};
};
}
```
#### Table Display
```typescript
interface TableResponse extends MCPResponse {
uiType: 'table';
structuredContent: {
rowCount: number;
columnCount: number;
summary: string;
};
_meta: {
columns: Array<{
id: string;
label: string;
type: 'string' | 'number' | 'date' | 'boolean' | 'currency';
sortable?: boolean;
filterable?: boolean;
width?: string;
}>;
rows: Array<Record<string, any>>;
features?: {
pagination?: boolean;
pageSize?: number;
sorting?: boolean;
filtering?: boolean;
exporting?: boolean;
selecting?: boolean;
};
};
}
```
### 4. Interactive Components
#### Calendar/Scheduling
```typescript
interface CalendarResponse extends MCPResponse {
uiType: 'calendar';
structuredContent: {
availableSlots: number;
dateRange: {
start: string;
end: string;
};
timezone: string;
};
_meta: {
calendar: {
availableSlots: Array<{
date: string;
times: Array<{
start: string;
end: string;
available: boolean;
}>;
}>;
duration: number; // minutes
timezone: string;
booking: {
requiresApproval: boolean;
confirmationEmail: boolean;
reminderEmail: boolean;
cancellationPolicy?: string;
};
};
};
}
```
#### File Upload
```typescript
interface FileUploadResponse extends MCPResponse {
uiType: 'file-upload';
structuredContent: {
purpose: string;
maxFiles: number;
maxSizeMB: number;
};
_meta: {
uploadConfig: {
endpoint: string;
method: 'POST' | 'PUT';
headers?: Record<string, string>;
restrictions: {
maxFiles: number;
maxSizePerFile: number; // bytes
maxTotalSize: number; // bytes
allowedTypes: string[]; // MIME types or extensions
};
features: {
dragAndDrop: boolean;
preview: boolean;
progress: boolean;
chunking?: boolean;
resumable?: boolean;
};
};
};
}
```
### 5. Status/Confirmation Responses
#### Success Confirmation
```typescript
interface SuccessResponse extends MCPResponse {
uiType: 'success';
structuredContent: {
action: string;
status: 'success';
message: string;
};
_meta: {
title: string;
message: string;
icon?: string;
details?: {
confirmationNumber?: string;
timestamp?: string;
nextSteps?: string[];
};
actions?: Array<{
label: string;
action: string;
primary?: boolean;
}>;
};
}
```
#### Error Response
```typescript
interface ErrorResponse extends MCPResponse {
uiType: 'error';
structuredContent: {
error: string;
code?: string;
recoverable: boolean;
};
_meta: {
title: string;
message: string;
details?: string;
recovery?: {
suggestions: string[];
retryable: boolean;
contactSupport?: boolean;
};
};
}
```
## Response Metadata Standards
### UI Type Naming Convention
- Use kebab-case: `form-lead`, `shopify-products`
- Prefix with provider when specific: `shopify-cart`, `stripe-payment`
- Use generic names for common types: `table`, `chart`, `form`
### Version Management
```typescript
interface VersionedResponse extends MCPResponse {
uiMetadata: {
component: 'ProductGrid';
version: '2.0.0'; // Semantic versioning
minClientVersion?: '1.5.0'; // Minimum client version required
deprecated?: boolean;
migrationGuide?: string; // URL to migration docs
};
}
```
### Priority Hints
```typescript
interface PriorityResponse extends MCPResponse {
uiMetadata: {
priority: 'high' | 'medium' | 'low';
renderMode: 'immediate' | 'lazy' | 'progressive';
preload?: boolean; // Hint to preload resources
cacheStrategy?: 'none' | 'session' | 'persistent';
};
}
```
## Best Practices
### 1. Token Optimization
**DO:**
- Keep `structuredContent` under 100 tokens when possible
- Use summaries and aggregations
- Include only fields the LLM needs for reasoning
**DON'T:**
- Send full product descriptions to LLM
- Include base64 images in structuredContent
- Duplicate data between structuredContent and _meta
### 2. Type Safety
Always define TypeScript interfaces for your responses:
```typescript
// Define specific response types
type MyAppResponse =
| ShopifyProductsResponse
| LeadFormResponse
| PaymentFormResponse
| ChartResponse;
// Type guard functions
function isShopifyResponse(response: MCPResponse): response is ShopifyProductsResponse {
return response.uiType === 'shopify-products';
}
```
### 3. Backwards Compatibility
When updating response structures:
```typescript
interface BackwardsCompatibleResponse extends MCPResponse {
uiType: 'product-grid';
// New structure
_meta: {
version: 2,
products: NewProductFormat[];
};
// Legacy support
_legacy?: {
version: 1,
items: OldProductFormat[];
};
}
```
### 4. Error Handling
Always include error information in responses:
```typescript
interface ResponseWithError extends MCPResponse {
error?: {
code: string;
message: string;
details?: any;
recoverable: boolean;
};
}
```
## Testing Response Structures
### Mock Response Generator
```typescript
class MockResponseGenerator {
static generateProductResponse(count: number = 10): ShopifyProductsResponse {
return {
uiType: 'shopify-products',
structuredContent: {
totalCount: count,
priceRange: { min: 10, max: 100, currency: 'USD' },
topProducts: this.generateProducts(Math.min(5, count)),
categories: ['Electronics', 'Clothing']
},
_meta: {
products: this.generateProducts(count),
filters: this.generateFilters(),
sortOptions: this.generateSortOptions(),
pagination: { page: 1, pageSize: 10, totalPages: Math.ceil(count/10), totalItems: count }
}
};
}
// ... other mock generators
}
```
## Next Steps
1. See `CHAT_WIDGET_IMPLEMENTATION.md` for handling these responses
2. Check `COMPONENT_REGISTRY.md` for rendering components
3. Review `ROUTING_LOGIC.md` for routing decisions
4. Read `UNIVERSAL_FORM_SYSTEM.md` for form handling