Skip to main content
Glama
cbcoutinho

Nextcloud MCP Server

by cbcoutinho
conftest.py18.2 kB
import httpx # ============================================================================ # Mock Response Helpers for Unit Tests # ============================================================================ def create_mock_response( status_code: int = 200, json_data: dict | list | None = None, headers: dict | None = None, content: bytes | None = None, ) -> httpx.Response: """Create a mock httpx.Response for testing. Args: status_code: HTTP status code json_data: JSON data to return from response.json() headers: Response headers content: Raw response content (if not using json_data) Returns: Mock httpx.Response object """ import json as json_module if headers is None: headers = {} # If json_data is provided, serialize it to content if json_data is not None: content = json_module.dumps(json_data).encode("utf-8") headers.setdefault("content-type", "application/json") if content is None: content = b"" # Create a mock request request = httpx.Request("GET", "http://test.local/api") # Create the response return httpx.Response( status_code=status_code, headers=headers, content=content, request=request, ) def create_mock_note_response( note_id: int = 1, title: str = "Test Note", content: str = "Test content", category: str = "Test", etag: str = "abc123", **kwargs, ) -> httpx.Response: """Create a mock response for a Nextcloud note. Args: note_id: Note ID title: Note title content: Note content category: Note category etag: ETag header value **kwargs: Additional note fields Returns: Mock httpx.Response with note data """ note_data = { "id": note_id, "title": title, "content": content, "category": category, "etag": etag, "modified": 1234567890, "favorite": False, **kwargs, } return create_mock_response( status_code=200, json_data=note_data, headers={"etag": f'"{etag}"'}, ) def create_mock_error_response( status_code: int, message: str = "Error", ) -> httpx.Response: """Create a mock error response. Args: status_code: HTTP error status code (e.g., 404, 412) message: Error message Returns: Mock httpx.Response with error """ return create_mock_response( status_code=status_code, json_data={"message": message}, ) def create_mock_recipe_response( recipe_id: int = 1, name: str = "Test Recipe", description: str = "Test description", recipe_category: str = "Test", keywords: str = "test", recipe_yield: int = 4, **kwargs, ) -> httpx.Response: """Create a mock response for a Nextcloud Cookbook recipe. Args: recipe_id: Recipe ID name: Recipe name description: Recipe description recipe_category: Recipe category keywords: Recipe keywords (comma-separated) recipe_yield: Recipe yield (number of servings) **kwargs: Additional recipe fields (recipeIngredient, recipeInstructions, etc.) Returns: Mock httpx.Response with recipe data """ recipe_data = { "id": recipe_id, "name": name, "description": description, "recipeCategory": recipe_category, "keywords": keywords, "recipeYield": recipe_yield, "recipeIngredient": kwargs.get("recipeIngredient", []), "recipeInstructions": kwargs.get("recipeInstructions", []), "prepTime": kwargs.get("prepTime", "PT15M"), "cookTime": kwargs.get("cookTime", "PT30M"), "totalTime": kwargs.get("totalTime", "PT45M"), "url": kwargs.get("url", ""), **{ k: v for k, v in kwargs.items() if k not in [ "recipeIngredient", "recipeInstructions", "prepTime", "cookTime", "totalTime", "url", ] }, } return create_mock_response( status_code=200, json_data=recipe_data, ) def create_mock_recipe_list_response( recipes: list[dict] = None, ) -> httpx.Response: """Create a mock response for a list of recipe stubs. Args: recipes: List of recipe stub dictionaries. If None, returns empty list. Returns: Mock httpx.Response with recipe list data """ if recipes is None: recipes = [] return create_mock_response( status_code=200, json_data=recipes, ) def create_mock_deck_board_response( board_id: int = 1, title: str = "Test Board", color: str = "0000FF", **kwargs, ) -> httpx.Response: """Create a mock response for a Nextcloud Deck board. Args: board_id: Board ID title: Board title color: Board color (hex without #) **kwargs: Additional board fields Returns: Mock httpx.Response with board data """ board_data = { "id": board_id, "title": title, "color": color, "owner": { "primaryKey": "testuser", "uid": "testuser", "displayname": "Test User", }, "archived": False, "labels": [], "acl": [], "permissions": { "PERMISSION_READ": True, "PERMISSION_EDIT": True, "PERMISSION_MANAGE": True, "PERMISSION_SHARE": True, }, "users": [], "deletedAt": 0, **kwargs, } return create_mock_response(status_code=200, json_data=board_data) def create_mock_deck_stack_response( stack_id: int = 1, title: str = "Test Stack", board_id: int = 1, order: int = 1, **kwargs, ) -> httpx.Response: """Create a mock response for a Nextcloud Deck stack. Args: stack_id: Stack ID title: Stack title board_id: Parent board ID order: Stack order **kwargs: Additional stack fields Returns: Mock httpx.Response with stack data """ stack_data = { "id": stack_id, "title": title, "boardId": board_id, "order": order, "deletedAt": 0, **kwargs, } return create_mock_response(status_code=200, json_data=stack_data) def create_mock_deck_card_response( card_id: int = 1, title: str = "Test Card", stack_id: int = 1, description: str = "Test description", **kwargs, ) -> httpx.Response: """Create a mock response for a Nextcloud Deck card. Args: card_id: Card ID title: Card title stack_id: Parent stack ID description: Card description **kwargs: Additional card fields Returns: Mock httpx.Response with card data """ card_data = { "id": card_id, "title": title, "stackId": stack_id, "type": "plain", "order": 999, "archived": False, "owner": "testuser", "description": description, "labels": [], "assignedUsers": [], **kwargs, } return create_mock_response(status_code=200, json_data=card_data) def create_mock_deck_label_response( label_id: int = 1, title: str = "Test Label", color: str = "FF0000", board_id: int = 1, **kwargs, ) -> httpx.Response: """Create a mock response for a Nextcloud Deck label. Args: label_id: Label ID title: Label title color: Label color (hex without #) board_id: Parent board ID **kwargs: Additional label fields Returns: Mock httpx.Response with label data """ label_data = { "id": label_id, "title": title, "color": color, "boardId": board_id, **kwargs, } return create_mock_response(status_code=200, json_data=label_data) def create_mock_deck_comment_response( comment_id: int = 1, message: str = "Test comment", card_id: int = 1, **kwargs, ) -> httpx.Response: """Create a mock response for a Nextcloud Deck comment (OCS format). Args: comment_id: Comment ID message: Comment message card_id: Parent card ID **kwargs: Additional comment fields Returns: Mock httpx.Response with comment data in OCS format """ comment_data = { "id": comment_id, "objectId": card_id, "message": message, "actorId": "testuser", "actorDisplayName": "Test User", "actorType": "users", "creationDateTime": "2024-01-01T00:00:00+00:00", "mentions": [], # Required field **kwargs, } # Wrap in OCS format ocs_response = {"ocs": {"meta": {"status": "ok"}, "data": comment_data}} return create_mock_response(status_code=200, json_data=ocs_response) def create_mock_tables_list_response( tables: list[dict] = None, ) -> httpx.Response: """Create a mock response for list of Nextcloud Tables (OCS format). Args: tables: List of table dictionaries. If None, returns empty list. Returns: Mock httpx.Response with tables list data in OCS format """ if tables is None: tables = [] ocs_response = {"ocs": {"meta": {"status": "ok"}, "data": tables}} return create_mock_response(status_code=200, json_data=ocs_response) def create_mock_table_schema_response( table_id: int = 1, columns: list[dict] = None, **kwargs, ) -> httpx.Response: """Create a mock response for Nextcloud Tables schema. Args: table_id: Table ID columns: List of column definitions. If None, creates sample columns. **kwargs: Additional schema fields Returns: Mock httpx.Response with table schema data """ if columns is None: columns = [ {"id": 1, "title": "Column 1", "type": "text"}, {"id": 2, "title": "Column 2", "type": "number"}, ] schema_data = { "id": table_id, "columns": columns, **kwargs, } return create_mock_response(status_code=200, json_data=schema_data) def create_mock_table_row_response( row_id: int = 1, table_id: int = 1, data: list[dict] = None, **kwargs, ) -> httpx.Response: """Create a mock response for Nextcloud Tables row. Args: row_id: Row ID table_id: Table ID data: List of column data dicts. If None, creates sample data. **kwargs: Additional row fields Returns: Mock httpx.Response with row data """ if data is None: data = [ {"columnId": 1, "value": "Test value"}, {"columnId": 2, "value": 42}, ] row_data = { "id": row_id, "tableId": table_id, "createdBy": "testuser", "createdAt": "2024-01-01T00:00:00+00:00", "lastEditBy": "testuser", "lastEditAt": "2024-01-01T00:00:00+00:00", "data": data, **kwargs, } return create_mock_response(status_code=200, json_data=row_data) def create_mock_table_row_ocs_response( row_id: int = 1, table_id: int = 1, data: list[dict] = None, **kwargs, ) -> httpx.Response: """Create a mock OCS response for Nextcloud Tables row (used by create_row). Args: row_id: Row ID table_id: Table ID data: List of column data dicts. If None, creates sample data. **kwargs: Additional row fields Returns: Mock httpx.Response with row data in OCS format """ if data is None: data = [ {"columnId": 1, "value": "Test value"}, {"columnId": 2, "value": 42}, ] row_data = { "id": row_id, "tableId": table_id, "createdBy": "testuser", "createdAt": "2024-01-01T00:00:00+00:00", "lastEditBy": "testuser", "lastEditAt": "2024-01-01T00:00:00+00:00", "data": data, **kwargs, } ocs_response = {"ocs": {"meta": {"status": "ok"}, "data": row_data}} return create_mock_response(status_code=200, json_data=ocs_response) # ============================================================================ # News Mock Response Helpers # ============================================================================ def create_mock_news_folders_response( folders: list[dict] | None = None, ) -> httpx.Response: """Create a mock response for News folders list. Args: folders: List of folder dictionaries. If None, returns empty list. Returns: Mock httpx.Response with folders data """ if folders is None: folders = [] return create_mock_response(status_code=200, json_data={"folders": folders}) def create_mock_news_folder_response( folder_id: int = 1, name: str = "Test Folder", **kwargs, ) -> httpx.Response: """Create a mock response for a News folder. Args: folder_id: Folder ID name: Folder name **kwargs: Additional folder fields Returns: Mock httpx.Response with folder data """ folder_data = { "id": folder_id, "name": name, **kwargs, } return create_mock_response(status_code=200, json_data={"folders": [folder_data]}) def create_mock_news_feeds_response( feeds: list[dict] | None = None, starred_count: int = 0, newest_item_id: int | None = None, ) -> httpx.Response: """Create a mock response for News feeds list. Args: feeds: List of feed dictionaries. If None, returns empty list. starred_count: Number of starred items newest_item_id: ID of newest item Returns: Mock httpx.Response with feeds data """ if feeds is None: feeds = [] data = { "feeds": feeds, "starredCount": starred_count, } if newest_item_id is not None: data["newestItemId"] = newest_item_id return create_mock_response(status_code=200, json_data=data) def create_mock_news_feed_response( feed_id: int = 1, url: str = "https://example.com/feed", title: str = "Test Feed", favicon_link: str | None = None, folder_id: int | None = None, unread_count: int = 0, **kwargs, ) -> httpx.Response: """Create a mock response for a News feed. Args: feed_id: Feed ID url: Feed URL title: Feed title favicon_link: Favicon URL folder_id: Parent folder ID unread_count: Number of unread items **kwargs: Additional feed fields Returns: Mock httpx.Response with feed data """ feed_data = { "id": feed_id, "url": url, "title": title, "faviconLink": favicon_link, "folderId": folder_id, "unreadCount": unread_count, "link": kwargs.get("link", "https://example.com"), "added": kwargs.get("added", 1700000000), "updateErrorCount": kwargs.get("updateErrorCount", 0), "lastUpdateError": kwargs.get("lastUpdateError"), **{ k: v for k, v in kwargs.items() if k not in ["link", "added", "updateErrorCount", "lastUpdateError"] }, } return create_mock_response(status_code=200, json_data={"feeds": [feed_data]}) def create_mock_news_items_response( items: list[dict] | None = None, ) -> httpx.Response: """Create a mock response for News items list. Args: items: List of item dictionaries. If None, returns empty list. Returns: Mock httpx.Response with items data """ if items is None: items = [] return create_mock_response(status_code=200, json_data={"items": items}) def create_mock_news_item( item_id: int = 1, feed_id: int = 1, title: str = "Test Article", body: str = "<p>Test content</p>", url: str = "https://example.com/article", author: str | None = "Test Author", pub_date: int = 1700000000, unread: bool = True, starred: bool = False, **kwargs, ) -> dict: """Create a mock News item dictionary. Args: item_id: Item ID feed_id: Parent feed ID title: Article title body: Article body (HTML) url: Article URL author: Article author pub_date: Publication timestamp (Unix) unread: Whether item is unread starred: Whether item is starred **kwargs: Additional item fields Returns: Item dictionary """ return { "id": item_id, "feedId": feed_id, "title": title, "body": body, "url": url, "author": author, "pubDate": pub_date, "unread": unread, "starred": starred, "guid": kwargs.get("guid", f"guid-{item_id}"), "guidHash": kwargs.get("guidHash", f"hash-{item_id}"), "lastModified": kwargs.get("lastModified", pub_date * 1000000), "enclosureLink": kwargs.get("enclosureLink"), "enclosureMime": kwargs.get("enclosureMime"), "fingerprint": kwargs.get("fingerprint", f"fp-{item_id}"), "contentHash": kwargs.get("contentHash", f"ch-{item_id}"), **{ k: v for k, v in kwargs.items() if k not in [ "guid", "guidHash", "lastModified", "enclosureLink", "enclosureMime", "fingerprint", "contentHash", ] }, } def create_mock_news_status_response( version: str = "25.0.0", warnings: dict | None = None, ) -> httpx.Response: """Create a mock response for News status. Args: version: News app version warnings: Warning messages Returns: Mock httpx.Response with status data """ data = { "version": version, "warnings": warnings or {}, } return create_mock_response(status_code=200, json_data=data)

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