Temporary fork: integrate upstream PRs 63, 59 and 62 #1

Merged
HoroTW merged 137 commits from hakalya/temporary-upstream-pr-integration into main 2026-10-11 19:47:31 +00:00 AGit
Collaborator
No description provided.
feat(server): initialize Picnic client with provided credentials for authentication
feat(server): add support for PICNIC_USERNAME and PICNIC_PASSWORD environment variables
feat(server): add tools for interacting with Picnic API including login, search, suggestions, articles, categories, cart management, delivery management, user info, lists, payment, transactions, 2FA
feat(server): implement tools for handling delivery scenarios, cancellation, rating, user details, MGM details
feat(server): implement tools for wallet transactions and transaction details
feat(server): implement tools for generating and verifying 2FA codes
feat(server): add error handling for uninitialized Picnic client
feat(server): reset Picnic client instance when needed
feat(server): update StreamableHttpServer to handle request body and connect to Picnic client
feat(server): update StreamableHttpServer to set request handler and close connection properly
feat(tests): add unit tests for StreamableHttpServer handling of request body and connection
feat(utils): add Picnic client utility functions for initialization, retrieval, and resetting
quick dinner solutions, healthy eating, special occasions, pantry restocking,
order management, recipe recreation, dietary substitutions, and delivery optimization.
feat(prompts): add Picnic-specific prompts for meal planning, budget …
feat(picnic-tools.ts): add tool to get order status for a specific order
feat(server.ts): add support for process.env.PORT environment variable to be able to run app on a configurable port
feat(server.ts): change port variable case from lowercase port to uppercase PORT to improve semantics
feat(picnic-tools.ts): add tool to send delivery invoice email for co…
feat: smithery
to ensure client is initialized before each tool execution. This improves
code readability and reduces duplication.
credentials from environment variables for login process
handling using environment variables for username and password
fix(picnic-client.ts): change console.log to console.error for better visibility
and consistency in logging messages
fix(auth): remove login tools
fix: optimize for efficient context output
chore(Dockerfile): remove unused environment variables ENABLE_HTTP_SERVER, HTTP_PORT, and HTTP_HOST
docs(README.md): add smithery badge to showcase project on smithery.ai
fix(.npmrc): remove @contentful registry configuration from .npmrc …
chore(Dockerfile): separate npm install commands to install all dependencies and only production dependencies
chore(Dockerfile): update environment variable names for Picnic credentials to be more descriptive
chore(Dockerfile): optimize Dockerfile by copying package files first…
feat(inspect.js): refactor CLI command building for flexibility and readability
feat(picnic-tools.ts): enhance 'picnic_get_categories' tool with more flexible
filtering options and use case optimization
feat(picnic-tools.ts): add 'picnic_get_category_details' tool for detailed
category information retrieval with customizable options
feat(picnic-tools.ts): introduce 'picnic_analyze_response_size' tool for
analyzing response size and structure for optimization
feat(picnic-tools): add support for process.env.PORT environment variable to be able to run app on a configurable port
feat(picnic-tools): remove picnic_get_article tool and update documentation to reflect
feat(picnic-tools): update filterCartData function to include additional cart data
feat(picnic-tools): update filterCartData function to summarize delivery slots
feat(picnic-tools): update filterCartData function to include checkout total price and total savings
feat(picnic-tools): update filterCartData function to include price for items
feat(picnic-tools): update filterCartData function to include delivery slots summary
feat(picnic-tools): remove picnic_debug_search_article diagnostic tool as product detail endpoints are deprecated
Add MseeP.ai badge
refactor(picnic-tools.ts): remove delivery slots summary from filterC…
Resolves #10 - The country code was hardcoded to "NL" in the codebase,
causing authentication failures for users from other countries (like DE).

Changes:
- Added PICNIC_COUNTRY_CODE to config schema with default value of "NL"
- Updated initializePicnicClient calls to use config.PICNIC_COUNTRY_CODE
- Modified both index.ts and picnic-tools.ts to pass country code from config

This allows users to set their country code via the PICNIC_COUNTRY_CODE
environment variable without needing to modify the source code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Added comprehensive test coverage for the PICNIC_COUNTRY_CODE environment
variable to prevent regression of issue #10.

Test coverage includes:
- Default value validation (NL)
- Valid country code acceptance (NL, DE)
- Invalid country code rejection (FR, empty string, null, numeric, lowercase)
- Backward compatibility verification
- Required fields validation
- Integration test with actual config object

This ensures that the country code configuration continues to work correctly
and prevents the issue from being reintroduced in future changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Cleaned up the initializePicnicClient function to follow the same pattern
as username and password - reading from config internally rather than
requiring callers to pass config values.

Changes:
- Made countryCode parameter optional in initializePicnicClient
- Added loginCountryCode variable using countryCode || config.PICNIC_COUNTRY_CODE
- Removed config import and parameter passing from index.ts
- Removed config import and parameter passing from picnic-tools.ts

This makes the code cleaner and more consistent, following the same
pattern used for username and password configuration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Enhanced README with detailed documentation for the PICNIC_COUNTRY_CODE
environment variable to help users properly configure their country setting.

Changes:
- Added dedicated "Country Configuration" section explaining the setting
- Updated all configuration examples to include PICNIC_COUNTRY_CODE
- Added clear guidance on when and how to set the country code
- Documented supported values (NL, DE) and default behavior
- Updated examples in English, Dutch, and German sections
- Emphasized that the country code must match the account's registration

This documentation ensures users, especially those in Germany, understand
they need to set PICNIC_COUNTRY_CODE=DE to avoid authentication issues.

Relates to issue #10

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
fix: use PICNIC_COUNTRY_CODE environment variable for authentication
The picnic-api v3.1.3 returns empty arrays for search queries because
Picnic changed their API response structure. Version 3.1.4 introduced
a "more universal approach" that handles the new structure correctly.

This update fixes the search functionality without requiring any code
changes to the MCP server.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
fix: update picnic-api to v3.2.0 to fix empty search results
Add id-token permission and registry-url for GitHub OIDC support,
and enable provenance attestation in semantic-release npm plugin.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ci: enable npm provenance with OIDC publishing
Bump actions/checkout and actions/setup-node from v3 to v4 for
improved performance and Node.js compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update semantic-release and plugins to versions that support npm OIDC
trusted publishing, removing the need for NPM_TOKEN (which required
OTP). The workflow now authenticates via GitHub Actions OIDC identity.

- semantic-release: ^22 → ^25
- @semantic-release/npm: ^11 → ^13 (adds OIDC verification)
- @semantic-release/github: ^9 → ^12
- @semantic-release/commit-analyzer: ^11 → ^13
- @semantic-release/release-notes-generator: ^12 → ^14
- Remove NPM_TOKEN/NODE_AUTH_TOKEN env vars from workflow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds automated session management: saves authKey to a local file after
login/2FA, reuses it on startup, and falls back to fresh login if expired.

Based on PR #20 by Thomas van Tilburg, with additional fixes:
- Add picnic-session.json to .gitignore
- Clean up session file in resetPicnicClient

Co-Authored-By: Thomas van Tilburg <thomas@vantilburg.me>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests cover session loading/reuse, fallback to fresh login on invalid
session, session saving after login, singleton behavior, resetPicnicClient
cleanup, and getPicnicClient error handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The relative default path `picnic-session.json` fails with EROFS in
Claude Desktop's read-only sandbox. Default to `~/.picnic-session.json`
instead, which is always writable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two issues fixed:
- 2FA endpoints return empty bodies, causing JSON parse errors in
  picnic-api. Catch SyntaxError in generate/verify handlers since
  the actual API call succeeds.
- Session validation used getUserInfo() which succeeds pre-2FA.
  Switched to getShoppingCart() which requires full authentication.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The picnic-api library's sendRequest doesn't capture response headers,
so if the API returns an updated x-picnic-auth after 2FA verification,
it was silently lost. Now we bypass sendRequest for 2FA verify and make
a direct fetch to capture the header.

Also delays session saving until after 2FA is completed when required,
and adds a debug script (scripts/debug-2fa.mjs) to inspect the full
2FA flow including response headers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Explains that users with 2FA enabled need to complete verification
via the AI assistant before using shopping tools. Updated the
Authentication section in all three languages (EN, NL, DE) with
step-by-step instructions, example conversations, and session
persistence details.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: implement session persistence for Picnic client. Contributed by @thomasvt1
Migrate all method calls to v4 domain-based architecture
(client.domain.method()). Remove tools with no v4 equivalent:
categories, lists, mgm, and diagnostic tool. Clean up `as any`
casts now that authKey/url are public on HttpClient.

- Bump picnic-api ^3.2.0 -> ^4.0.0
- Migrate 25 method calls across picnic-client.ts and picnic-tools.ts
- Remove 6 deprecated tool registrations (~300 lines)
- Update test mocks to match v4 domain structure

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: upgrade picnic-api from v3 to v4
refactor(base.ts): replace specific request types with 'any' to resolve TypeScript errors and improve compatibility with the SDK
fix(transports): update variable names to reflect the new McpServer type for better readability and maintainability

refactor(tests): rename Server to McpServer for consistency and clarity in test files
fix(tests): update references to mock server handlers to match new structure of McpServer

test: refactor StreamableHttpServer tests to use HTTP requests for health check and route validation
test: update server-factory tests to mock McpServer instead of Server for accuracy
refactor(pkg updates): update dependencies and migrate Server to McpServer
Closes #25

Add a tool that resolves product IDs (from cart, orders, or search) to
their full product metadata via picnic-api's getProductDetails endpoint.

Supports a `full` parameter to control response verbosity:
- false (default): essential fields only (id, name, brand, price, unit, image)
- true: complete details including description, allergens, ingredients,
  promotions, bundles, and similar products
The cart filter was treating OrderLines as flat items, losing the nested
OrderArticle data that contains the selling unit ID (product_id). This
made it impossible for LLMs to pass cart items to picnic_get_product_details.

Now properly traverses OrderLine.items to expose product_id, name, unit,
price, and image_id per article.
feat(http): support URL token auth and docker-compose token config
Add HTTP header authentication support for HTTP transport
Expose the picnic-api `recipe` service through six new MCP tools:

- picnic_get_recipes — recipes overview Fusion page
- picnic_get_recipe_details — single recipe Fusion page
- picnic_save_recipe / picnic_unsave_recipe — manage saved recipes
- picnic_add_product_to_recipe / picnic_remove_product_from_recipe —
  cart mutations carrying recipe context for Picnic's recipe stepper UI

Includes documentation updates (README.md, PICNIC_TOOLS.md) and unit
tests covering input validation, argument forwarding, and registration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The recipe.getRecipesPage() endpoint in picnic-api targets `meals-page-root`,
which is just the navigation shell. The actual recipe content lives one
level deeper in `cookbook-page-content` (highlights) and the
`recipe_cattree_*` category pages.

Rework picnic_get_recipes to:

- Hit `cookbook-page-content` by default, returning ~30 highlighted recipes
  plus the list of available category IDs.
- Accept a `category` parameter (bare id or full page id) to fetch a
  specific `recipe_cattree_<id>` page; a single category can hold hundreds
  of recipes, so add limit/offset pagination.
- Project each recipe to {recipe_id, title, cooking_time, tagline?, image_id?}
  by walking the FusionPage and using the Snowplow recipe analytics
  context as the stable id, with a longest-string heuristic for the title
  that works across both the cookbook and category layouts.
- Expose `full: true` to fall back to the raw FusionPage.

Add unit tests covering both layouts, deduplication, pagination, category
discovery, and the full=true escape hatch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
picnic-api's `recipe.getRecipeDetailsPage()` targets the retired
`recipe-details-page-root` page id and now 404s. The live recipe page
is served as `selling-group-details-page?selling_group_id=<recipe_id>`,
so reach for it directly via `client.app.getPage()`.

The page is a 1.7MB FusionPage; project it into a clean shape using
Picnic's own stable block ids:

- `sellable-components-CORE-list`             → ingredients
- `sellable-components-CORE_STOCKABLE-list`   → likely_in_stock
- `sellable-components-CUPBOARD-list`         → pantry ("uit eigen keuken")
- `sellable-components-COMPLEMENTARY-list`    → complementary
- `instructions-section` PML                  → steps + tip
- `sellable-header-container`                 → tagline / name / description
- `selling-group-details-image-wrapper`       → image_id
- the `selling_units` arrays embedded throughout the tree provide the
  selling_unit_id / quantity / checked fields, joined by ingredient_id.

Each ingredient comes back as `{selling_unit_id, ingredient_id, name,
brand?, price (cents), unit_quantity?, needed?, quantity, checked}`,
ready to be passed to the cart tools. `full: true` falls back to the
raw FusionPage.

Verified live against recipe 69a6d2ab92f7b13019c86579 (kip-kormaballetjes):
10 core ingredients, 1 likely-in-stock, 3 pantry, 1 complementary,
6 steps, and the variation tip — all extracted with correct fields.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trim the recipe-tools surface and harden the detail-page extractor:

- Drop `picnic_add_product_to_recipe` and `picnic_remove_product_from_recipe`.
  The selling_unit_id surfaced by `picnic_get_recipe_details` is the same id
  used by `picnic_add_to_cart` / `picnic_remove_from_cart`, so the
  recipe-context variants only added analytics noise without giving callers
  more capability.
- Make the price extractor locale-aware: accept either `.` (NL) or `,` (DE)
  as decimal separator and normalise before parsing.
- Tighten brand detection so a trailing allergen sentence or other prose
  text after the brand slot does not silently bleed into the `brand` field.
- Reject empty `recipeId` at the schema level instead of letting it 4xx
  against Picnic.
- Update PICNIC_TOOLS.md and the English/Dutch/German README sections,
  including a recipe-browsing example conversation in each language.
- Gitignore `scripts/probe-*` so local exploration scripts that read the
  user's session file stay out of the PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add recipe support backed by Picnic's selling-group pages (a recipe id is a
selling_group_id; 24 hex chars for catalog recipes, 32 for user-defined ones):

- picnic_get_recipe: fetch /pages/selling-group-details-page and return
  structured data (name, description, quality cue, timing, servings, image,
  saved state, ingredients, pantry items, tools, tips, preparation steps) plus a
  canonical source URL.
- picnic_browse_recipes / picnic_get_saved_recipes / picnic_get_own_recipes:
  list the cookbook (/pages/cookbook-page-content), grouped by typed
  segment_type (SAVED_RECIPES, USER_DEFINED_RECIPES, ...).
- picnic_save_recipe / picnic_unsave_recipe / picnic_add_recipe_to_cart.

Extraction is structured-first and language-agnostic (name/description/image/
portions/saved-state from typed selling_group_*_data fields); ingredient and
step lines come from the localized RICH_TEXT sections (DE/NL/FR). Steps are
anchored on the per-step "Schritt/Stap/Étape N" labels and the instruction
header must follow the ingredient header, so personalized/scaled recipes parse
cleanly; "Eigene Zutaten"/"Du benötigst"/"Tipp" are split into pantry/tools/tips
and servings is taken only from a clean "N Portionen" value. User-defined recipe
names come from the `recipe` analytics context.

The page routes are called via sendRequest because the picnic-api recipe.*
methods target outdated page ids (recipe-details-page-root) that 404; see
MRVDH/picnic-api#44 / #45. Short-link resolution is restricted to picnic.app
over HTTPS to avoid SSRF.
- picnic_get_recipes: reject path/query characters in `category` via the
  input schema (P1). The id ends up unencoded in the /pages/ request path,
  so '../cart' could otherwise turn the tool into an arbitrary
  authenticated same-origin GET.
- Identify title/tagline by Picnic's color-marker structure instead of
  text length. This also fixes a live bug: newer cookbook tiles carry
  compound times ("15 min bereiden | 30 min totaal") that are longer than
  many titles and won the title slot under the length heuristic.
- Extract compound cooking times via a loose `<digits> min` token fallback
  restricted to color-wrapped texts.
- Recognize DE/FR step, tip and cooking-time markers and extend the UI
  label / promo / needed-amount filters to DE/FR (NL verified live, DE/FR
  best-effort), instead of NL-only parsing.
- Ground header tagline/description relative to the canonical recipe name
  instead of fixed [0]/[1]/[2] slots, so extra badges/chips cannot shift
  the fields.
- Describe `full: true` as a debugging-only escape hatch (raw pages exceed
  LLM context windows).
- Commit the live-API probe scripts under scripts/ (with README) instead
  of gitignoring them; probe-recipes now exercises the real tool handler.
- Prettier pass over the touched files.

Verified against the live API (NL account): cookbook, category and detail
pages extract correctly, including compound-time tiles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Multi-angle review of the recipe tools surfaced several real defects,
confirmed against the live API:

- Category round-trip was broken: extractRecipeCategoryIds stripped the
  prefix to a bare slug, but the handler always re-prefixed with the
  underscore form. Picnic emits both 'recipe_cattree_' and 'recipe-cattree-'
  and is strict (recipe_cattree_jamie-oliver 404s; recipe-cattree-jamie-oliver
  resolves), so ~half the advertised categories were unfetchable. Now the
  full page id is surfaced and forwarded verbatim. Verified live: jamie-oliver
  returns 32 recipes.
- Theme categories (e.g. recipe_cattree_thema-kids) hold only sub-category
  links and no recipes; surface those sub-categories so drilling into a theme
  isn't a dead end. Verified live (4 sub-categories surfaced).
- Ingredient names starting with a digit ("100% pindakaas", "30+ kaas") were
  dropped by the `/^\d/` filter; tightened to number-then-space/end so real
  names survive.
- Price/promo labels ("nu €2.29") leaked into the ingredient name slot,
  pushing the real name into `brand`; any €-bearing text is now chrome.
  Verified live on the enchilada recipe.
- unit_quantity now accepts comma decimals (like the price parser) and
  spelled-out / DE-FR units (liter, Stück, pièces).
- Listing titles now strip `**bold**` (the detail path already did); the
  color-marker "wrapped" cue is computed independently so a bold-only title
  stays a title. Deduped stripColorMarkers into stripMd.
- stripMd NFC-normalizes so NFD-encoded accented locale tokens (Étape,
  Hinzufügen) still match.
- extractStepsAndTip no longer consumes a following header as a step body
  when a step's body text is missing.
- limit/offset are now .int() so fractional values can't desync pagination.
- full:true returns compact JSON (the registry pretty-prints objects,
  inflating the already-oversized raw page by ~a third).
- scripts/README: corrected the false claim that a saved session alone
  suffices — config requires PICNIC_USERNAME/PICNIC_PASSWORD at startup.

229 unit tests pass (8 new); prettier clean; verified live against an NL
account (cookbook, category round-trip, theme sub-categories, detail parsing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Updated picnic-api dependency from version 4.0.0 to 4.5.0 in package.json and package-lock.json.
- Added optional configuration parameters for PICNIC_DEVICE_ID and PICNIC_AGENT in config schema.
- Enhanced README with new optional settings for device identity.
- Refactored picnic-tools to utilize the new 2FA verification method and improved error handling.
- Introduced unit tests for 2FA code generation and verification tools.
feat: added proper Docker support, CI/CD workflow, and optional authentication
chore: update picnic-api to version 4.5.0 and add optional configuration for device ID and agent
feat(recipes): add recipe tools (fetch, browse, cookbook, cart)
feat(recipes): add meal planning helpers
[codex] Fix streamable HTTP session cleanup recursion
[codex] clarify removed category tool docs
[codex] fix 2FA verification timeout
picnic-api uses Node's built-in fetch (undici), which ignores HTTP(S)_PROXY by
default. When HTTPS_PROXY is set, wrap globalThis.fetch with undici's
EnvHttpProxyAgent so all outbound requests (login, store API, recipes) honour
HTTPS_PROXY and NO_PROXY. No-op when HTTPS_PROXY is unset; best-effort if undici
is unavailable. Logs go to stderr to keep the stdio MCP transport clean.

Useful behind egress-restricted networks that require a forward proxy.
feat: optional HTTPS_PROXY support for outbound requests
The build script ran `chmod +x bin/mcp-server.js`, which fails on Windows
because chmod does not exist there, breaking `npm install` (via prepare)
and `npm run build`. Move the executable bit into build.js.

To keep the original guardrail (the old shell chmod failed if the declared
CLI entrypoint was missing), assert that bin/mcp-server.js exists and throw
if it does not, then chmod it. Only the chmod-unsupported case (ENOSYS /
EPERM, e.g. Windows or filesystems without POSIX permissions) is ignored;
any other error is rethrown.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
#46 wired PICNIC_DEVICE_ID / PICNIC_AGENT through to the client, but when
PICNIC_DEVICE_ID is not set the client falls back to picnic-api''s shared
default device id, so all unconfigured installs still send the same
x-picnic-did. This adds the auto-generated persisted fallback discussed in
 #39 / #40.

- add resolveDeviceId() (src/utils/device-id.ts): returns PICNIC_DEVICE_ID
  if set, otherwise reads a persisted id from PICNIC_DEVICE_FILE, otherwise
  generates a random 16-char id and persists it for reuse
- add PICNIC_DEVICE_FILE config (default ~/.picnic-device.json)
- initializePicnicClient now passes the resolved id instead of the possibly
  undefined PICNIC_DEVICE_ID

Backwards compatible: setting PICNIC_DEVICE_ID keeps current behaviour; the
session-file persistence pattern is mirrored for the device id.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix: make build work on Windows (chmod unavailable)
- picnic-client tests: assert no *session* write on the 2FA path instead of
  no write at all, now that resolveDeviceId() may persist a generated id
- add focused resolveDeviceId coverage (explicit, persisted, generated,
  malformed file, persistence failure)
- Dockerfile/README: default PICNIC_DEVICE_FILE to /app/data so a generated
  device id persists on the mounted volume across container restarts

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat: persist an auto-generated device id when PICNIC_DEVICE_ID is unset
feat(tools): browse Picnic recipes (cookbook, categories, structured details)
feat:  add weekly promotions tool
fix(2fa): source client version headers from the client instead of a stale copy
fix(cart): make failed cart mutations safe to act on
fix(image): make picnic_get_image actually return an image
Picnic removed promo-page-all-promos-redirect, so the hardcoded weekly-deals fetch 404s. Resolve the live page id from app bootstrap instead of baking it in.

Co-authored-by: Cursor <cursoragent@cursor.com>
Publish temporary Picnic fork integrating PRs 63, 59 and 62
Some checks failed
Release / Release (push) Has been cancelled
PR Check / Verify PR (pull_request) Has been cancelled
6bcb970952
HoroTW merged commit 6bcb970952 into main 2026-10-11 19:47:31 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
HoroTW/mcp-picnic!1
No description provided.