Skip to main content
Glama
cbcoutinho

Nextcloud MCP Server

by cbcoutinho
cookbook.py7.74 kB
"""Client for Nextcloud Cookbook app operations.""" import logging from typing import Any, Dict, List from httpx import Timeout from .base import BaseNextcloudClient logger = logging.getLogger(__name__) class CookbookClient(BaseNextcloudClient): """Client for Nextcloud Cookbook app operations.""" app_name = "cookbook" async def get_version(self) -> Dict[str, Any]: """Get Cookbook app and API version.""" response = await self._make_request("GET", "/apps/cookbook/api/version") return response.json() async def get_config(self) -> Dict[str, Any]: """Get current Cookbook app configuration.""" response = await self._make_request("GET", "/apps/cookbook/api/v1/config") return response.json() async def set_config(self, config: Dict[str, Any]) -> Dict[str, Any]: """Set Cookbook app configuration. Args: config: Configuration dictionary with fields like: - folder: Recipe folder path - update_interval: Auto-rescan interval in minutes - print_image: Whether to print images with recipes - visibleInfoBlocks: Visible info blocks configuration Returns: Response with status message """ response = await self._make_request( "POST", "/apps/cookbook/api/v1/config", json=config ) return response.json() async def reindex(self) -> str: """Trigger a rescan of all recipes into the caching database. Returns: Success message """ response = await self._make_request("POST", "/apps/cookbook/api/v1/reindex") return response.json() async def list_recipes(self) -> List[Dict[str, Any]]: """Get all recipes in the database. Returns: List of recipe stubs with basic information """ response = await self._make_request("GET", "/apps/cookbook/api/v1/recipes") return response.json() async def get_recipe(self, recipe_id: int) -> Dict[str, Any]: """Get a single recipe by ID. Args: recipe_id: The recipe ID Returns: Full recipe data """ response = await self._make_request( "GET", f"/apps/cookbook/api/v1/recipes/{recipe_id}" ) return response.json() async def create_recipe(self, recipe_data: Dict[str, Any]) -> int: """Create a new recipe. Args: recipe_data: Recipe data following schema.org/Recipe format. Required: name Optional: description, ingredients, instructions, etc. Returns: ID of the newly created recipe """ response = await self._make_request( "POST", "/apps/cookbook/api/v1/recipes", json=recipe_data ) return response.json() async def update_recipe(self, recipe_id: int, recipe_data: Dict[str, Any]) -> int: """Update an existing recipe. Args: recipe_id: The recipe ID to update recipe_data: Updated recipe data Returns: ID of the updated recipe """ response = await self._make_request( "PUT", f"/apps/cookbook/api/v1/recipes/{recipe_id}", json=recipe_data ) return response.json() async def delete_recipe(self, recipe_id: int) -> str: """Delete a recipe. Args: recipe_id: The recipe ID to delete Returns: Success message """ response = await self._make_request( "DELETE", f"/apps/cookbook/api/v1/recipes/{recipe_id}" ) return response.json() async def import_recipe(self, url: str) -> Dict[str, Any]: """Import a recipe from a URL using schema.org metadata. Args: url: URL of the recipe to import Returns: Full imported recipe data """ logger.info(f"Importing recipe from URL: {url}") response = await self._make_request( "POST", "/apps/cookbook/api/v1/import", json={"url": url}, timeout=Timeout(300.0), ) return response.json() async def get_recipe_image(self, recipe_id: int, size: str = "full") -> bytes: """Get the main image of a recipe. Args: recipe_id: The recipe ID size: Image size - "full", "thumb" (250px), or "thumb16" (16px) Returns: Image bytes """ response = await self._make_request( "GET", f"/apps/cookbook/api/v1/recipes/{recipe_id}/image", params={"size": size}, ) return response.content async def search_recipes(self, query: str) -> List[Dict[str, Any]]: """Search for recipes by keywords, tags, and categories. Args: query: Search string (URL-encoded, space/comma separated) Returns: List of matching recipe stubs """ # URL encode the query from urllib.parse import quote encoded_query = quote(query) response = await self._make_request( "GET", f"/apps/cookbook/api/v1/search/{encoded_query}" ) return response.json() async def list_categories(self) -> List[Dict[str, Any]]: """Get all known categories. Note: A category name of '*' indicates recipes with no category. Returns: List of categories with recipe counts """ response = await self._make_request("GET", "/apps/cookbook/api/v1/categories") return response.json() async def get_recipes_in_category(self, category: str) -> List[Dict[str, Any]]: """Get all recipes in a specific category. Args: category: Category name (use "_" for recipes with no category) Returns: List of recipe stubs in the category """ from urllib.parse import quote encoded_category = quote(category) response = await self._make_request( "GET", f"/apps/cookbook/api/v1/category/{encoded_category}" ) return response.json() async def rename_category(self, old_name: str, new_name: str) -> str: """Rename a category. Args: old_name: Current category name new_name: New category name Returns: New category name """ from urllib.parse import quote encoded_old_name = quote(old_name) response = await self._make_request( "PUT", f"/apps/cookbook/api/v1/category/{encoded_old_name}", json={"name": new_name}, ) return response.json() async def list_keywords(self) -> List[Dict[str, Any]]: """Get all known keywords/tags. Returns: List of keywords with recipe counts """ response = await self._make_request("GET", "/apps/cookbook/api/v1/keywords") return response.json() async def get_recipes_with_keywords( self, keywords: List[str] ) -> List[Dict[str, Any]]: """Get all recipes associated with certain keywords. Args: keywords: List of keywords to filter by Returns: List of recipe stubs matching the keywords """ from urllib.parse import quote # Join keywords with commas keywords_str = ",".join(keywords) encoded_keywords = quote(keywords_str) response = await self._make_request( "GET", f"/apps/cookbook/api/v1/tags/{encoded_keywords}" ) return response.json()

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