Type System
Related Topics: Endpoints (use types in definitions) | Policies (filter by type) | YAML Schemas (complete field reference) | Testing (validate types)
MXCP’s type system provides robust data validation for endpoint parameters and return values. It combines JSON Schema compatibility with DuckDB type mapping, ensuring type safety across your entire application.
Why types matter:
- Validation - Invalid data is rejected before execution
- Documentation - LLMs understand what values are expected
- SQL Safety - Parameters are properly typed in queries
- Policy Filtering - Sensitive fields can be automatically filtered
Base Types
Section titled “Base Types”MXCP supports six base types:
| Type | Description | Example | DuckDB Type |
|---|---|---|---|
string | Text values | "hello" | VARCHAR |
number | Floating-point | 3.14 | DOUBLE |
integer | Whole numbers | 42 | INTEGER |
boolean | True/false | true | BOOLEAN |
array | Ordered list | [1, 2, 3] | ARRAY |
object | Key-value structure | {"key": "value"} | STRUCT |
String Format Annotations
Section titled “String Format Annotations”String types can have format annotations for specialized handling:
| Format | Description | Example | DuckDB Type |
|---|---|---|---|
email | Email address | "user@example.com" | VARCHAR |
uri | URL/URI | "https://example.com" | VARCHAR |
date | ISO 8601 date | "2024-01-15" | DATE |
time | ISO 8601 time | "14:30:00" | TIME |
date-time | ISO 8601 timestamp | "2024-01-15T14:30:00Z" | TIMESTAMP WITH TIME ZONE |
duration | ISO 8601 duration | "P1DT2H" | VARCHAR |
timestamp | Unix timestamp | 1705329000 | TIMESTAMP |
Using Formats
Section titled “Using Formats”parameters: - name: email type: string format: email description: User's email address
- name: start_date type: string format: date description: Start date (YYYY-MM-DD)
- name: created_at type: string format: date-time description: Creation timestampFormat annotations are validated automatically when values are passed to endpoints.
Type Annotations
Section titled “Type Annotations”Common Annotations
Section titled “Common Annotations”Available for all types:
| Annotation | Description |
|---|---|
description | Human-readable description |
default | Default value if not provided |
examples | Example values for documentation |
enum | List of allowed values |
parameters: - name: status type: string description: Order status enum: ["pending", "shipped", "delivered"] default: "pending" examples: ["pending", "shipped"]Required vs Optional Parameters
Section titled “Required vs Optional Parameters”Parameters are required by default. A parameter becomes optional when it has a default value:
parameters: # Required - must be provided - name: user_id type: integer description: User ID
# Optional - uses default if not provided - name: limit type: integer description: Maximum results default: 10String Annotations
Section titled “String Annotations”| Annotation | Description |
|---|---|
minLength | Minimum string length |
maxLength | Maximum string length |
format | Specialized format |
- name: username type: string minLength: 3 maxLength: 50 description: Username (3-50 characters)Numeric Annotations
Section titled “Numeric Annotations”| Annotation | Description |
|---|---|
minimum | Minimum value (inclusive) |
maximum | Maximum value (inclusive) |
exclusiveMinimum | Minimum value (exclusive) |
exclusiveMaximum | Maximum value (exclusive) |
multipleOf | Value must be multiple of this |
- name: age type: integer minimum: 0 maximum: 150 description: Age in years
- name: quantity type: integer minimum: 1 multipleOf: 5 description: Quantity (must be multiple of 5)
- name: price type: number minimum: 0 exclusiveMaximum: 1000000 description: Price in dollarsNote:
multipleOfworks reliably with integers. For decimal precision (e.g., currency), use integer cents instead ofmultipleOf: 0.01due to floating-point precision limitations.
Array Annotations
Section titled “Array Annotations”| Annotation | Description |
|---|---|
items | Schema for array items |
minItems | Minimum array length |
maxItems | Maximum array length |
uniqueItems | Items must be unique |
- name: tags type: array items: type: string minItems: 1 maxItems: 10 uniqueItems: true description: List of tags (1-10 unique strings)Object Annotations
Section titled “Object Annotations”| Annotation | Description |
|---|---|
properties | Schema for object properties |
required | List of required properties |
additionalProperties | Allow (and preserve) undefined properties. Default: true (if omitted). Use false to reject unknown keys. |
- name: address type: object properties: street: type: string city: type: string zip: type: string required: ["street", "city"]Nested Types
Section titled “Nested Types”Types can be nested to any depth:
Array of Objects
Section titled “Array of Objects”return: type: array description: List of users items: type: object properties: id: type: integer name: type: string email: type: string format: emailObject with Nested Objects
Section titled “Object with Nested Objects”return: type: object properties: user: type: object properties: id: type: integer name: type: string orders: type: array items: type: object properties: order_id: type: string amount: type: numberSensitive Data
Section titled “Sensitive Data”Mark fields containing sensitive data with sensitive: true. The sensitive flag can be applied to any type - strings, numbers, integers, booleans, arrays, or objects:
return: type: object properties: username: type: string password: type: string sensitive: true balance: type: number sensitive: true # Numbers can also be sensitive config: type: object properties: host: type: string api_key: type: string sensitive: true # Nested sensitive fieldSensitive fields are:
- Redacted in audit logs - Replaced with
[REDACTED] - Filterable by policies - Can be removed with
filter_sensitive_fieldsaction - Documented as sensitive - Clear indication in schemas
Marking Entire Objects
Section titled “Marking Entire Objects”You can mark entire objects as sensitive:
return: type: object properties: public_data: type: object properties: name: type: string credentials: type: object sensitive: true properties: access_token: type: string refresh_token: type: stringUsing with Policies
Section titled “Using with Policies”The filter_sensitive_fields policy action automatically removes all fields marked as sensitive:
policies: output: - condition: "user.role != 'admin'" action: filter_sensitive_fields reason: "Non-admin users cannot see sensitive data"This is more maintainable than filter_fields as sensitive fields are defined once in the schema rather than repeated in policies.
Using Types in SQL
Section titled “Using Types in SQL”Parameters defined in your YAML are available in SQL queries using $parameter_name syntax:
parameters: - name: user_id type: integer - name: status type: string enum: ["active", "inactive"]SELECT * FROM usersWHERE id = $user_id AND status = $statusThe type system ensures parameters are properly escaped and typed when passed to DuckDB.
Type Conversion
Section titled “Type Conversion”MXCP automatically handles type conversion between:
- JSON/YAML input → Python types
- Python types → DuckDB types
- DuckDB results → Python types
- Python types → JSON/YAML output
Python to DuckDB Mapping
Section titled “Python to DuckDB Mapping”| Python Type | DuckDB Type |
|---|---|
str | VARCHAR |
int | INTEGER |
float | DOUBLE |
bool | BOOLEAN |
list | ARRAY |
dict | STRUCT |
datetime | TIMESTAMP |
date | DATE |
time | TIME |
Complete Example
Section titled “Complete Example”Here’s a complete parameter definition showcasing various type features:
parameters: - name: user_id type: integer description: Unique user identifier minimum: 1 examples: [1, 42, 100]
- name: email type: string format: email description: User's email address examples: ["user@example.com"]
- name: role type: string description: User role enum: ["admin", "user", "guest"] default: "user"
- name: tags type: array items: type: string minItems: 0 maxItems: 5 description: User tags
- name: preferences type: object description: User preferences properties: theme: type: string enum: ["light", "dark", "auto"] default: "auto" notifications: type: boolean default: true language: type: string default: "en" required: ["theme"]
- name: created_after type: string format: date-time description: Filter users created after this timeLimitations
Section titled “Limitations”MXCP intentionally restricts schema complexity:
Not supported:
$ref- No schema referencesallOf,oneOf,anyOf- No union typespattern,patternProperties- No regex-based constraints- Conditional schemas (
if/then)
These restrictions ensure:
- Static, serializable schemas
- SQL-compatible types
- AI tooling compatibility
- Simpler validation and testing
Validation Errors
Section titled “Validation Errors”MXCP provides clear error messages:
Error: Invalid email format: not-an-emailError: Value must be >= 0Error: String must be at least 3 characters longError: Missing required properties: name, emailError: Value 'invalid' not in enum: ['admin', 'user', 'guest']Best Practices
Section titled “Best Practices”Always Add Descriptions
Section titled “Always Add Descriptions”Every parameter and return field should have a description:
- name: user_id type: integer description: Unique identifier for the userUse Format Annotations
Section titled “Use Format Annotations”Specify formats for specialized strings:
- name: email type: string format: email # Validates email formatSet Defaults for Optional Parameters
Section titled “Set Defaults for Optional Parameters”Make optional parameters explicit:
- name: limit type: integer default: 10 # Optional - uses 10 if not providedUse Enums for Fixed Values
Section titled “Use Enums for Fixed Values”Constrain to valid options:
- name: status type: string enum: ["active", "inactive", "pending"]Mark Sensitive Data
Section titled “Mark Sensitive Data”Protect sensitive information:
- name: api_key type: string sensitive: true # Redacted in logs, filterable by policiesDefine Complete Return Types
Section titled “Define Complete Return Types”Always specify return schemas with required fields:
return: type: object properties: id: type: integer name: type: string required: ["id", "name"]Provide Examples
Section titled “Provide Examples”Include examples for documentation and testing:
- name: region type: string examples: ["North", "South", "East", "West"]Be Explicit with Constraints
Section titled “Be Explicit with Constraints”Define array and numeric constraints:
- name: items type: array items: type: string minItems: 1 maxItems: 100Validate Early
Section titled “Validate Early”Use mxcp validate to check type definitions before deployment:
mxcp validateGroup Sensitive Data
Section titled “Group Sensitive Data”Consider putting all sensitive fields in a dedicated object that can be marked sensitive as a whole:
return: type: object properties: public: type: object properties: name: { type: string } secrets: type: object sensitive: true properties: token: { type: string } key: { type: string }