Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/core/schema_adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,22 @@ class ListAuthorizedPropertiesResponse(AdCPBaseModel):
last_updated: str | None = Field(None, description="ISO 8601 timestamp of when authorization list was last updated")
errors: list[Any] | None = Field(None, description="Task-specific errors and warnings")

def dict(self, **kwargs):
"""Override dict to use model_dump with exclude_none=True for AdCP compliance.

FastMCP may use dict() for serialization instead of model_dump().
This ensures optional fields with None values are excluded from the response.
"""
return self.model_dump(**kwargs)

def __iter__(self):
"""Override iteration to exclude None values for AdCP compliance.

When dict() or json.dumps() iterates over the model, it will only include
non-None fields. This ensures the response is spec-compliant.
"""
return iter(self.model_dump().items())

def __str__(self) -> str:
"""Return human-readable message for protocol layer.

Expand Down
13 changes: 8 additions & 5 deletions src/core/tools/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,14 @@ def _list_authorized_properties_impl(
# Create response with AdCP spec-compliant fields
# Note: Optional fields (advertising_policies, errors, etc.) should be omitted if not set,
# not set to None or empty values. AdCPBaseModel.model_dump() uses exclude_none=True by default.
response = ListAuthorizedPropertiesResponse(
publisher_domains=publisher_domains, # Required per AdCP v2.4 spec
advertising_policies=advertising_policies_text,
# errors omitted - only include if there are actual errors
)
# Build response dict with only non-None values
response_data = {"publisher_domains": publisher_domains} # Required per AdCP v2.4 spec

# Only add optional fields if they have actual values
if advertising_policies_text:
response_data["advertising_policies"] = advertising_policies_text

response = ListAuthorizedPropertiesResponse(**response_data)

# Log audit
audit_logger = get_audit_logger("AdCP", tenant_id)
Expand Down