Skip to main content
Glama
deck.py7.5 kB
from datetime import datetime from typing import Any, Dict, List, Optional, Union from pydantic import BaseModel, Field, field_validator from .base import BaseResponse, StatusResponse class DeckUser(BaseModel): primaryKey: str uid: str displayname: str class DeckPermissions(BaseModel): PERMISSION_READ: bool PERMISSION_EDIT: bool PERMISSION_MANAGE: bool PERMISSION_SHARE: bool class DeckLabel(BaseModel): id: int title: str color: str boardId: Optional[int] = None cardId: Optional[int] = None class DeckACL(BaseModel): id: int participant: DeckUser type: int boardId: int permissionEdit: bool permissionShare: bool permissionManage: bool owner: bool class DeckBoardSettings(BaseModel): calendar: bool cardDetailsInModal: Optional[bool] = Field(default=None, alias="cardDetailsInModal") cardIdBadge: Optional[bool] = Field(default=None, alias="cardIdBadge") groupLimit: Optional[List[Dict[str, str]]] = Field(default=None, alias="groupLimit") notify_due: Optional[str] = Field(default=None, alias="notify-due") class DeckBoard(BaseModel): id: int title: str owner: DeckUser color: str archived: bool labels: List[DeckLabel] acl: List[DeckACL] permissions: DeckPermissions users: List[DeckUser] deletedAt: int lastModified: Optional[int] = None settings: Optional[DeckBoardSettings] = None etag: Optional[str] = Field(default=None, alias="ETag") @field_validator("settings", mode="before") @classmethod def validate_settings(cls, v): # Handle case where API returns empty array instead of dict/null if isinstance(v, list) and len(v) == 0: return None return v class DeckAssignedUser(BaseModel): id: int participant: DeckUser cardId: int type: int class DeckCard(BaseModel): id: int title: str stackId: int type: str order: int archived: bool owner: Union[str, DeckUser] # Can be either string or user object description: Optional[str] = None duedate: Optional[datetime] = None done: Optional[datetime] = None lastModified: Optional[int] = None createdAt: Optional[int] = None labels: Optional[List[DeckLabel]] = None assignedUsers: Optional[List[Union[DeckUser, DeckAssignedUser]]] = None attachments: Optional[List[Any]] = None # Define a proper Attachment model later attachmentCount: Optional[int] = None deletedAt: Optional[int] = None commentsUnread: Optional[int] = None overdue: Optional[int] = None etag: Optional[str] = Field(default=None, alias="ETag") @field_validator("owner", mode="before") @classmethod def validate_owner(cls, v): # Handle case where API returns user object instead of string if isinstance(v, dict): return v.get("uid", v.get("primaryKey", str(v))) return v @field_validator("assignedUsers", mode="before") @classmethod def validate_assigned_users(cls, v): # Handle different formats of assigned users from the API if not v: return v validated_users = [] for user in v: if isinstance(user, dict): # Check if it's an assignment object with participant if "participant" in user: validated_users.append(user) # Check if it's a direct user object elif "uid" in user or "primaryKey" in user: validated_users.append(user) else: validated_users.append(user) return validated_users class DeckStack(BaseModel): id: int title: str boardId: int order: int deletedAt: int lastModified: Optional[int] = None cards: Optional[List[DeckCard]] = None etag: Optional[str] = Field(default=None, alias="ETag") class DeckAttachmentExtendedData(BaseModel): filesize: int mimetype: str info: Dict[str, str] class DeckAttachment(BaseModel): id: int cardId: int type: str data: str lastModified: int createdAt: int createdBy: str deletedAt: int extendedData: DeckAttachmentExtendedData class DeckComment(BaseModel): id: int objectId: int message: str actorId: str actorType: str actorDisplayName: str creationDateTime: datetime mentions: List[Dict[str, str]] replyTo: Optional[Any] = None # Self-referencing, handle later if needed class DeckSession(BaseModel): token: str class DeckConfig(BaseModel): calendar: bool cardDetailsInModal: bool cardIdBadge: bool groupLimit: Optional[List[Dict[str, str]]] = None # Response Models for MCP Tools class ListBoardsResponse(BaseResponse): """Response model for listing deck boards.""" boards: List[DeckBoard] = Field(description="List of deck boards") total: int = Field(description="Total number of boards") class CreateBoardResponse(BaseResponse): """Response model for board creation.""" id: int = Field(description="The created board ID") title: str = Field(description="The created board title") color: str = Field(description="The created board color") class BoardOperationResponse(StatusResponse): """Response model for board operations like update/delete.""" board_id: int = Field(description="ID of the affected board") # Stack Response Models class ListStacksResponse(BaseResponse): """Response model for listing deck stacks.""" stacks: List[DeckStack] = Field(description="List of deck stacks") total: int = Field(description="Total number of stacks") class CreateStackResponse(BaseResponse): """Response model for stack creation.""" id: int = Field(description="The created stack ID") title: str = Field(description="The created stack title") order: int = Field(description="The created stack order") class StackOperationResponse(StatusResponse): """Response model for stack operations like update/delete.""" stack_id: int = Field(description="ID of the affected stack") board_id: int = Field(description="ID of the board containing the stack") # Card Response Models class CreateCardResponse(BaseResponse): """Response model for card creation.""" id: int = Field(description="The created card ID") title: str = Field(description="The created card title") description: Optional[str] = Field(description="The created card description") stackId: int = Field(description="The stack ID the card belongs to") class CardOperationResponse(StatusResponse): """Response model for card operations like update/delete.""" card_id: int = Field(description="ID of the affected card") stack_id: int = Field(description="ID of the stack containing the card") board_id: int = Field(description="ID of the board containing the card") # Label Response Models class CreateLabelResponse(BaseResponse): """Response model for label creation.""" id: int = Field(description="The created label ID") title: str = Field(description="The created label title") color: str = Field(description="The created label color") class LabelOperationResponse(StatusResponse): """Response model for label operations like update/delete.""" label_id: int = Field(description="ID of the affected label") board_id: int = Field(description="ID of the board containing the label")

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/No-Smoke/nextcloud-mcp-comprehensive'

If you have feedback or need assistance with the MCP directory API, please join our Discord server