Detailed changes
@@ -0,0 +1,37 @@
+feature:
+ name: api-client
+ product: cooked-mcp
+ description: Call Cooked's customer API predictably while hiding HTTP details from MCP tools.
+
+components:
+ REQUESTS:
+ requirements:
+ 1: JSON Cooked requests send Content-Type application/json when they have a body.
+ 2: JSON Cooked requests send Accept application/json.
+ 3: Cooked request paths are built without allowing malformed path joins.
+ 4: Cooked query parameters are URL-encoded.
+ 5: User-scoped Cooked API paths use the authenticated username from the login response.
+ ERRORS:
+ requirements:
+ 1: Cooked API error responses are converted into concise user-facing MCP tool errors.
+ 2: Cooked API errors include the HTTP status when available.
+ 3: Cooked API errors include Cooked's error code when available.
+ 4: Cooked API errors include Cooked's error message when available.
+ 5: Cooked API error handling preserves enough detail for the agent to choose a follow-up action.
+ 6: Cooked API error handling does not expose session cookies or credentials.
+ RESPONSES:
+ requirements:
+ 1: Cooked API responses are decoded and validated for fields used by MCP tools before formatting.
+ 2: Unknown fields in Cooked API responses do not break otherwise valid tool calls.
+ 3: Unexpected Cooked response shapes are reported as recoverable tool errors when possible.
+
+constraints:
+ LIMITS:
+ requirements:
+ 1: Cooked response bodies read for error reporting are bounded.
+ 2: List-like MCP tool text responses are summarized instead of returning unbounded result sets.
+ 3: When a response is truncated or paginated, the tool response says how to fetch more results.
+ VERIFICATION:
+ requirements:
+ 1: API client behaviour is verified with fake Cooked HTTP servers.
+ 2: API client tests do not contact the real Cooked service.
@@ -0,0 +1,62 @@
+feature:
+ name: authentication
+ product: cooked-mcp
+ description: Authenticate to Cooked with user credentials and maintain the Cooked session safely.
+
+components:
+ CREDENTIALS:
+ requirements:
+ 1: The server accepts the Cooked username from COOKED_LOGIN_USERNAME.
+ 2: The server accepts the Cooked password from COOKED_LOGIN_PASSWORD.
+ 3: The server accepts the Cooked username from TOML user.name.
+ 4: The server accepts the Cooked password from TOML user.password.
+ 5: The server accepts a command for producing the Cooked username from TOML user.name_cmd.
+ 6: The server accepts a command for producing the Cooked password from TOML user.password_cmd.
+ 7: A credential command returns the credential on stdout.
+ 7-1: Trailing newlines are trimmed from credential command stdout.
+ 7-2: Empty credential command output is rejected.
+ 8: The server rejects ambiguous TOML credential configuration for a single credential field.
+ 8-1: user.name and user.name_cmd are mutually exclusive.
+ 8-2: user.password and user.password_cmd are mutually exclusive.
+ 9: The server reports missing username or password configuration before serving.
+ 10: The server obtains Cooked session cookies by logging in with configured username and password credentials.
+ 11: COOKED_LOGIN_USERNAME takes precedence over TOML user.name and user.name_cmd.
+ 12: COOKED_LOGIN_PASSWORD takes precedence over TOML user.password and user.password_cmd.
+ 13: Browser-provided Cooked session cookies are not supported in this version.
+ 14: Social-login and passwordless Cooked accounts are not supported in this version.
+ 15: Credential command fields are TOML strings executed as shell commands.
+ 16: Credential commands must exit successfully within 5 seconds.
+ 17: Credential command stdout read by the server is capped at 64 KiB.
+ 18: Credential command stdout is trimmed of leading and trailing ASCII whitespace before use.
+ 19: Credential command stderr is not included in logs or user-facing errors.
+ 20: Non-zero credential command exits are reported as credential resolution failures without command output.
+ LOGIN:
+ requirements:
+ 1: The server logs in to Cooked with the configured username and password when an authenticated request needs a session.
+ 2: Login sends JSON credentials to Cooked's public login endpoint.
+ 3: Successful login stores response cookies in the session cookie jar.
+ 4: Failed login is reported as a user-facing authentication failure.
+ 5: Successful login records the authenticated username returned by Cooked.
+ 6: User-scoped Cooked API requests use the authenticated username returned by Cooked.
+ SESSION:
+ requirements:
+ 1: Authenticated Cooked API requests use an HTTP cookie jar for session cookies.
+ 2: Authenticated Cooked API requests do not manually construct Cookie headers.
+ 3: If Cooked rejects a session with 401, the server discards the stored session cookies.
+ 4: After a 401, the server retries login once.
+ 5: After a successful retry login, the server retries the original Cooked request once.
+ 6: If the retried request is rejected, the server reports the authentication failure without another retry.
+ 7: The Cooked session cookie jar is process-local and in-memory in this version.
+ 8: The server does not persist Cooked session cookies to disk.
+ 9: Restarting the server obtains a fresh session by logging in again with configured username and password credentials.
+
+constraints:
+ SECRETS:
+ requirements:
+ 1: The server never logs usernames, passwords, session cookies, credential command stdout, or credential command stderr.
+ 2: Credential command execution has a bounded runtime.
+ 3: Authentication error messages do not include credential values.
+ VERIFICATION:
+ requirements:
+ 1: Authentication behaviour is verified with fake Cooked HTTP servers.
+ 2: Authentication tests do not contact the real Cooked service.
@@ -0,0 +1,81 @@
+feature:
+ name: recipes
+ product: cooked-mcp
+ description: Let an agent find, read, preview, save, update, import, and delete Cooked recipes through task-oriented tools.
+
+components:
+ READ:
+ requirements:
+ 1: The read tool lists saved recipes when its target is recipes and no search query is provided.
+ 2: The read tool searches saved recipes when its target is recipes and a search query is provided.
+ 3: Recipe list and search results include recipe IDs and titles.
+ 4: Recipe list and search results omit thumbnails.
+ 5: The read tool reads a single recipe when its target is recipe and a recipe ID is provided.
+ 6: A single recipe read includes recipe metadata needed for agent decisions.
+ 6-1: A single recipe read includes the recipe title when Cooked provides it.
+ 6-2: A single recipe read includes owner or edit-permission information when Cooked provides it.
+ 7: A single recipe read includes recipe content.
+ 8: A single recipe read includes portions.
+ 9: Recipe reads omit image URLs unless a future feature explicitly exposes them.
+ PREVIEW_TEXT:
+ requirements:
+ 1: The preview_recipe_text tool previews raw recipe text without saving a recipe.
+ 1-1: Previewing raw recipe text requires a recipe title.
+ 1-2: Previewing raw recipe text requires the raw recipe text.
+ 2: The preview_recipe_text tool returns the preview title.
+ 3: The preview_recipe_text tool returns preview markdown.
+ 4: The preview_recipe_text tool returns preview portions.
+ SAVE:
+ requirements:
+ 1: The save_recipe tool saves a recipe from raw text.
+ 1-1: Saving raw recipe text requires a recipe title.
+ 1-2: Saving raw recipe text requires raw recipe text.
+ 2: The save_recipe tool saves a recipe from prepared markdown and portions.
+ 2-1: Saving prepared markdown requires a recipe title.
+ 2-2: Saving prepared markdown requires recipe markdown.
+ 2-3: Saving prepared markdown requires portions.
+ 3: The save_recipe tool imports a recipe from a URL.
+ 3-1: Importing a recipe from a URL requires a URL.
+ 4: When URL import creates a saved recipe immediately, save_recipe returns the new recipe ID.
+ 5: When URL import creates an extraction draft, save_recipe returns the draft ID and draft content for review.
+ 6: URL import drafts are not automatically saved.
+ 7: The save_recipe tool saves a reviewed extraction draft.
+ 7-1: Saving a reviewed extraction draft requires a draft ID.
+ 7-2: Saving a reviewed extraction draft requires reviewed markdown.
+ 7-3: Saving a reviewed extraction draft requires portions.
+ 8: The save_recipe tool updates an existing saved recipe.
+ 8-1: Updating an existing saved recipe requires a recipe ID.
+ 8-2: Updating an existing saved recipe requires recipe markdown.
+ 8-3: Updating an existing saved recipe requires portions.
+ 9: Recipe save and update results include the affected recipe ID.
+ 10: Recipe save requests use explicit source values.
+ 10-1: The recipe save source values are raw_text, prepared, url, draft, and existing.
+ 11: Saving raw recipe text hides Cooked's preview-then-save sequence behind one tool call.
+ 12: URL import draft responses include draft portions when Cooked provides them.
+ 13: MCP recipe markdown maps to Cooked's description field.
+ 14: When URL import returns an extraction draft, save_recipe fetches the draft metadata and content before returning to the agent.
+ 15: URL import draft responses include draft_id, title when available, markdown, and portions when available.
+ 16: The server never saves an extraction draft unless save_recipe is called with source draft and an explicit draft ID.
+ DELETE:
+ requirements:
+ 1: The delete_recipe tool deletes a saved recipe by recipe ID.
+ 2: Recipe deletion reports which recipe ID was deleted.
+
+constraints:
+ PAGINATION:
+ requirements:
+ 1: Recipe list and search requests accept a page number.
+ 2: Recipe list requests accept a result limit that maps to Cooked's page-count parameter.
+ 3: Recipe search requests accept a result limit for client-side response truncation.
+ 4: Recipe list and search result limits default to 10.
+ 5: Recipe list and search result limits are capped at 30.
+ 6: Recipe list and search responses tell the agent when more pages may be available.
+ SAFETY:
+ requirements:
+ 1: Draft-saving requires an explicit draft ID.
+ 2: Existing recipe updates require an explicit recipe ID.
+ 3: Recipe deletion requires an explicit recipe ID.
+ VERIFICATION:
+ requirements:
+ 1: Recipe behaviour is verified with fake Cooked HTTP servers.
+ 2: Recipe tests do not contact the real Cooked service.
@@ -0,0 +1,63 @@
+feature:
+ name: server
+ product: cooked-mcp
+ description: Start Cooked as a single-user MCP server over stdio or local HTTP.
+
+components:
+ IDENTITY:
+ requirements:
+ 1: The MCP server identifies itself as Cooked.
+ 2: The command starts the MCP server without requiring subcommands.
+ TRANSPORT:
+ requirements:
+ 1: The server starts with stdio transport by default.
+ 2: The server accepts an explicit transport selection through a --transport flag.
+ 2-1: The --transport stdio value selects stdio transport.
+ 2-2: The --transport http value selects Streamable HTTP.
+ 3: HTTP transport listens on a configurable address.
+ 3-1: HTTP transport defaults to 127.0.0.1:8123.
+ 4: The server rejects unknown transport selections before serving.
+ 5: HTTP transport serves MCP requests at /mcp.
+ CONFIG:
+ requirements:
+ 1: The server loads configuration from environment variables.
+ 2: The server loads configuration from a TOML configuration file.
+ 3: Environment variables take precedence over TOML configuration values for the same setting.
+ 4: The Cooked base URL defaults to https://cooked.wiki.
+ 4-1: COOKED_BASE_URL configures the Cooked base URL.
+ 4-2: TOML cooked.base_url configures the Cooked base URL.
+ 5: The server validates configured HTTP URLs before serving.
+ 6: The server can be pointed at a specific TOML configuration file with --config.
+ 7: If no TOML configuration path is supplied, the server loads config.toml from $XDG_CONFIG_HOME/cooked-mcp.
+ 7-1: If XDG_CONFIG_HOME is unset, the server loads config.toml from ~/.config/cooked-mcp.
+ 8: HTTP transport address is configurable with --http-addr.
+ 8-1: COOKED_MCP_HTTP_ADDR configures the HTTP transport address.
+ 8-2: TOML mcp.http_addr configures the HTTP transport address.
+
+constraints:
+ SINGLE_USER:
+ requirements:
+ 1: The server supports exactly one configured Cooked account per process.
+ 2: MCP requests do not provide or select Cooked usernames.
+ 3: Multi-account routing, per-client users, and per-request Cooked credentials are out of scope.
+ SECURITY:
+ requirements:
+ 1: HTTP transport refuses non-loopback listeners unless MCP HTTP authentication is configured.
+ 2: HTTP authentication secrets are never logged.
+ 3: HTTP transport supports bearer-token authentication.
+ 4: HTTP bearer tokens can be configured through COOKED_MCP_HTTP_TOKEN.
+ 5: HTTP bearer tokens can be configured through TOML mcp.http_token or mcp.http_token_cmd.
+ 6: HTTP bearer authentication uses the Authorization header with the Bearer scheme.
+ 7: When an HTTP token is configured, every MCP HTTP request must provide the matching bearer token.
+ 8: TOML mcp.http_token and mcp.http_token_cmd are mutually exclusive.
+ 9: COOKED_MCP_HTTP_TOKEN takes precedence over TOML mcp.http_token and mcp.http_token_cmd.
+ 10: TOML mcp.http_token_cmd follows the same command execution, trimming, timeout, and secrecy rules as Cooked credential commands.
+ 11: Empty HTTP bearer tokens are rejected before serving.
+ COMPATIBILITY:
+ requirements:
+ 1: The server does not require MCP resource support from clients.
+ 2: Every operation described by the cooked-mcp feature specs is available through MCP tools.
+ 3: Agents do not need to call Cooked REST endpoints directly.
+ VERIFICATION:
+ requirements:
+ 1: Startup and configuration behaviour is verified without contacting the real Cooked service.
@@ -0,0 +1,69 @@
+feature:
+ name: shopping-list
+ product: cooked-mcp
+ description: Let an agent read and change the Cooked shopping list without needing to understand Cooked's REST update semantics.
+
+components:
+ READ:
+ requirements:
+ 1: The read tool reads the shopping list when its target is shopping_list.
+ 2: Shopping-list reads include aisle names.
+ 3: Shopping-list reads include aisle IDs.
+ 4: Shopping-list reads include product group IDs.
+ 5: Shopping-list reads include product names.
+ 6: Shopping-list reads include quantities when Cooked provides them.
+ 7: Shopping-list reads include selected state.
+ 8: Shopping-list reads include each product group's containing aisle ID.
+ 9: Shopping-list reads include recipe IDs associated with the list when Cooked provides them.
+ ADD:
+ requirements:
+ 1: The change_shopping_list tool adds plain-text ingredients to the shopping list.
+ 2: Adding ingredients accepts one or more newline-separated ingredients.
+ 3: Adding ingredients may associate the ingredients with a saved recipe ID or import draft ID.
+ 4: Adding ingredients reports how many ingredients Cooked added.
+ UPDATE_ITEM:
+ requirements:
+ 1: The change_shopping_list tool updates a shopping-list product group.
+ 2: Updating a product group accepts partial changes from the agent.
+ 3: The server reads the current shopping list before sending a product-group update when needed to preserve omitted fields.
+ 4: Updating a product group preserves omitted editable fields.
+ 5: Updating a product group reports the product group ID that changed.
+ 6: Updating a product group requires an explicit product group ID.
+ 7: Updating a missing product group reports a user-facing tool error.
+ 8: Partial product-group updates preserve the current name, quantity, aisle ID, and selected state unless replacements are provided.
+ 9: If update_item omits any editable field, the server fills omitted name, quantity, aisle ID, and selected values from the current shopping list before calling Cooked.
+ SELECTION:
+ requirements:
+ 1: The change_shopping_list tool replaces the complete selected product-group set.
+ 2: The change_shopping_list tool adds product groups to the selected set without requiring the agent to provide the complete selected set.
+ 3: The change_shopping_list tool removes product groups from the selected set without requiring the agent to provide the complete selected set.
+ 4: The server reads the current shopping list before add or remove selection changes.
+ 5: Selection changes report the resulting selected product-group IDs.
+ 6: Selection changes use explicit replace_selection, add_selection, and remove_selection actions.
+ 7: Selection changes require product group IDs.
+ 8: replace_selection sends exactly the provided product group IDs as the full selected set.
+ 9: add_selection reads the current list, unions the provided product group IDs with the current selected set, then sends the full selected set.
+ 10: remove_selection reads the current list, subtracts the provided product group IDs from the current selected set, then sends the full selected set.
+ REMOVE:
+ requirements:
+ 1: The change_shopping_list tool removes one or more product groups by ID.
+ 2: Removing product groups reports the removed product-group IDs.
+ CLEAR:
+ requirements:
+ 1: The change_shopping_list tool clears all shopping-list items.
+ 2: Clearing the shopping list reports that the list was cleared.
+
+constraints:
+ ACTIONS:
+ requirements:
+ 1: Shopping-list mutations use explicit action values.
+ 2: Unknown shopping-list actions are rejected before calling Cooked.
+ SAFETY:
+ requirements:
+ 1: Removing product groups requires at least one product group ID.
+ 2: Clearing the shopping list is treated as destructive.
+ 3: Clearing the shopping list requires the explicit clear action.
+ VERIFICATION:
+ requirements:
+ 1: Shopping-list behaviour is verified with fake Cooked HTTP servers.
+ 2: Shopping-list tests do not contact the real Cooked service.
@@ -0,0 +1,86 @@
+feature:
+ name: tools
+ product: cooked-mcp
+ description: Expose Cooked through a small LLM-oriented MCP tool surface instead of a REST-shaped endpoint mirror.
+
+components:
+ SURFACE:
+ requirements:
+ 1: The server exposes a read tool named read.
+ 2: The server exposes a recipe text preview tool named preview_recipe_text.
+ 3: The server exposes a recipe save tool named save_recipe.
+ 4: The server exposes a recipe deletion tool named delete_recipe.
+ 5: The server exposes a shopping-list mutation tool named change_shopping_list.
+ 6: The server does not expose one MCP tool per Cooked API endpoint.
+ 7: The server does not expose MCP resources.
+ 8: The read tool supports recipe lists, single recipes, and the shopping list through explicit target values.
+ READ_TOOL:
+ requirements:
+ 1: The read tool target values are recipes, recipe, and shopping_list.
+ 2: The read tool accepts recipe_id when target is recipe.
+ 3: The read tool requires recipe_id when target is recipe.
+ 4: The read tool accepts query when target is recipes.
+ 5: The read tool accepts page with default 1 and minimum 1.
+ 6: The read tool accepts limit with default 10, minimum 1, and maximum 30.
+ PREVIEW_RECIPE_TEXT_TOOL:
+ requirements:
+ 1: The preview_recipe_text tool requires title.
+ 2: The preview_recipe_text tool requires text.
+ SAVE_RECIPE_TOOL:
+ requirements:
+ 1: The save_recipe source values are raw_text, prepared, url, draft, and existing.
+ 2: source raw_text requires title and text.
+ 3: source prepared requires title, markdown, and portions.
+ 4: source url requires url.
+ 5: source draft requires draft_id, markdown, and portions.
+ 6: source existing requires recipe_id, markdown, and portions.
+ DELETE_RECIPE_TOOL:
+ requirements:
+ 1: The delete_recipe tool requires recipe_id.
+ CHANGE_SHOPPING_LIST_TOOL:
+ requirements:
+ 1: The change_shopping_list action values are add, update_item, replace_selection, add_selection, remove_selection, remove, and clear.
+ 2: action add requires ingredients.
+ 3: action add accepts recipe_id.
+ 4: action update_item requires product_group_id.
+ 5: action update_item accepts name, quantity, aisle_id, and selected.
+ 6: action replace_selection requires product_group_ids.
+ 7: action add_selection requires product_group_ids.
+ 8: action remove_selection requires product_group_ids.
+ 9: action remove requires product_group_ids.
+ 10: action clear has no required parameters beyond action.
+ READ_WRITE_SPLIT:
+ requirements:
+ 1: Read-only operations are exposed separately from operations that change Cooked data.
+ 2: Recipe deletion is exposed separately from recipe saving and updating.
+ 3: Previewing recipe text is exposed separately from saving recipe text.
+ RESPONSES:
+ requirements:
+ 1: Tool responses include concise text written for an LLM agent.
+ 2: Tool responses include IDs required for likely follow-up calls.
+ 3: Tool responses omit thumbnail URLs.
+ 4: Tool responses avoid dumping raw Cooked API responses.
+ 5: Tool responses include structured output when supported by the MCP SDK.
+ 6: Tool errors are returned as user-facing MCP tool errors when the agent can recover.
+ 7: Tool text and structured outputs omit Cooked session cookies, credentials, credential command output, and HTTP bearer tokens.
+ ANNOTATIONS:
+ requirements:
+ 1: Read tools are annotated as read-only.
+ 2: Write tools are not annotated as read-only.
+ 3: Destructive tools are annotated as destructive.
+ 4: Tools that call Cooked are annotated as open-world.
+ 5: Every tool includes a human-readable title annotation.
+ 6: The shopping-list mutation tool is annotated as destructive because some actions remove data.
+
+constraints:
+ NAMING:
+ requirements:
+ 1: Tool names are concise when prefixed by the MCP client with the server name.
+ 2: Tool names do not repeat the server name Cooked.
+ SCHEMA:
+ requirements:
+ 1: Tool parameters use explicit enumerations for mode or action fields.
+ 2: Tool parameters validate bounded numeric inputs.
+ 3: Tool descriptions state important behavioural limits and follow-up tools.
+ 4: Tool schemas reject unsupported read targets, recipe save sources, and shopping-list actions before calling Cooked.
+ 5: The shopping-list mutation tool description distinguishes destructive remove and clear actions from non-destructive actions.