Skip to main content
Glama
cbcoutinho

Nextcloud MCP Server

by cbcoutinho
news.py6.19 kB
"""Pydantic models for Nextcloud News app responses.""" from typing import List from pydantic import BaseModel, ConfigDict, Field from .base import BaseResponse class NewsFolder(BaseModel): """Model for a News folder.""" model_config = ConfigDict(populate_by_name=True) id: int = Field(description="Folder ID") name: str = Field(description="Folder name") class NewsFeed(BaseModel): """Model for a News feed (RSS/Atom subscription).""" model_config = ConfigDict(populate_by_name=True) id: int = Field(description="Feed ID") url: str = Field(description="Feed URL") title: str = Field(description="Feed title") favicon_link: str | None = Field( None, alias="faviconLink", description="Favicon URL" ) link: str | None = Field(None, description="Website link") added: int = Field(description="Unix timestamp when feed was added") folder_id: int | None = Field( None, alias="folderId", description="Parent folder ID" ) unread_count: int = Field( 0, alias="unreadCount", description="Number of unread items" ) ordering: int = Field( 0, description="Feed ordering (0=default, 1=oldest, 2=newest)" ) pinned: bool = Field(False, description="Whether feed is pinned to top") update_error_count: int = Field( 0, alias="updateErrorCount", description="Consecutive update failures" ) last_update_error: str | None = Field( None, alias="lastUpdateError", description="Last update error message" ) @property def has_errors(self) -> bool: """Check if feed has update errors.""" return self.update_error_count > 0 class NewsItem(BaseModel): """Model for a News item (article) with full content.""" model_config = ConfigDict(populate_by_name=True) id: int = Field(description="Item ID") guid: str = Field(description="Globally unique identifier") guid_hash: str = Field(alias="guidHash", description="MD5 hash of GUID") url: str | None = Field(None, description="Article URL") title: str = Field(description="Article title") author: str | None = Field(None, description="Article author") pub_date: int | None = Field( None, alias="pubDate", description="Publication timestamp" ) body: str | None = Field(None, description="Article content (HTML)") enclosure_mime: str | None = Field( None, alias="enclosureMime", description="Enclosure MIME type" ) enclosure_link: str | None = Field( None, alias="enclosureLink", description="Enclosure URL" ) media_thumbnail: str | None = Field( None, alias="mediaThumbnail", description="Media thumbnail URL" ) media_description: str | None = Field( None, alias="mediaDescription", description="Media description" ) feed_id: int = Field(alias="feedId", description="Parent feed ID") unread: bool = Field(True, description="Whether item is unread") starred: bool = Field(False, description="Whether item is starred") rtl: bool = Field(False, description="Right-to-left text") last_modified: int = Field( alias="lastModified", description="Last modification timestamp" ) fingerprint: str | None = Field( None, description="Content fingerprint for deduplication" ) content_hash: str | None = Field( None, alias="contentHash", description="Content hash" ) class NewsItemSummary(BaseModel): """Lightweight model for News item list responses.""" model_config = ConfigDict(populate_by_name=True) id: int = Field(description="Item ID") title: str = Field(description="Article title") feed_id: int = Field(alias="feedId", description="Parent feed ID") unread: bool = Field(True, description="Whether item is unread") starred: bool = Field(False, description="Whether item is starred") pub_date: int | None = Field( None, alias="pubDate", description="Publication timestamp" ) url: str | None = Field(None, description="Article URL") author: str | None = Field(None, description="Article author") class NewsStatus(BaseModel): """Model for News app status.""" version: str = Field(description="News app version") warnings: dict = Field(default_factory=dict, description="Configuration warnings") # --- Response Models --- class ListFoldersResponse(BaseResponse): """Response model for listing folders.""" results: List[NewsFolder] = Field(description="List of folders") total_count: int = Field(description="Total number of folders") class ListFeedsResponse(BaseResponse): """Response model for listing feeds.""" results: List[NewsFeed] = Field(description="List of feeds") starred_count: int = Field(0, description="Number of starred items") newest_item_id: int | None = Field(None, description="ID of newest item") total_count: int = Field(description="Total number of feeds") class ListItemsResponse(BaseResponse): """Response model for listing items.""" results: List[NewsItemSummary] = Field(description="List of items") total_count: int = Field(description="Number of items returned") has_more: bool = Field(False, description="Whether more items exist") oldest_id: int | None = Field(None, description="Oldest item ID (for pagination)") class GetItemResponse(BaseResponse): """Response model for getting a single item.""" item: NewsItem = Field(description="Full item details") class FeedHealthResponse(BaseResponse): """Response model for feed health status.""" feed_id: int = Field(description="Feed ID") title: str = Field(description="Feed title") url: str = Field(description="Feed URL") has_errors: bool = Field(description="Whether feed has update errors") error_count: int = Field(description="Number of consecutive errors") last_error: str | None = Field(None, description="Last error message") class GetStatusResponse(BaseResponse): """Response model for app status.""" version: str = Field(description="News app version") warnings: dict = Field(default_factory=dict, description="Configuration warnings")

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/cbcoutinho/nextcloud-mcp-server'

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