generated: '2026-09-19' method: probed status: published source: 'https://piknik.spot/api/mcp (live JSON-RPC probes: initialize, tools/list, prompts/list, resources/list, tools/call) + https://piknik.spot/llms.txt + https://piknik.spot/skills/piknik-mcp/SKILL.md' deployment: mode: remote endpoint: https://piknik.spot/api/mcp sse_endpoint: https://piknik.spot/api/mcp/sse install: null package: null auth: oauth auth_note: OAuth 2.0 authorization code + PKCE (S256) with RFC 7591 dynamic client registration at https://piknik.spot/api/oauth/register, OR a pik_pat_ personal access token minted at https://piknik.spot/settings/developer and sent as a Bearer header. Public discovery tools need neither. The field enum has one value; both mechanisms are real. verified: probed server: name: piknik version: 1.0.0 transport: http url: https://piknik.spot/api/mcp protocol_version: '2025-03-26' capabilities: - tools - prompts - resources - logging instructions: Piknik local food system platform. Public discovery tools are available; sign in via OAuth or a Personal Access Token (Settings -> Developer) for write tools like create_listing, create_recipe, and get_my_places. listings: [] probes: - method: initialize http_status: 200 result: protocolVersion 2025-03-26, serverInfo piknik 1.0.0, capabilities tools/prompts/resources/logging - method: tools/list http_status: 200 result: 62 tools with inputSchema, no nextCursor file: mcp/piknik-spot-mcp-tools-list.json - method: prompts/list http_status: 200 result: 0 prompts - method: resources/list http_status: 200 result: 7 resources (piknik:// URIs) file: mcp/piknik-spot-mcp-resources-list.json - method: tools/call get_my_places (anonymous) http_status: 401 result: 'JSON-RPC error -32001 "Authentication required. Please authorize this application." with data.authorizationUrl, tokenUrl, scopes [marketplace:write, events:write], quickstart https://piknik.spot/api/mcp/auth/start; header WWW-Authenticate: Bearer realm="mcp", resource_metadata="https://piknik.spot/.well-known/oauth-protected-resource"' - method: GET /api/mcp http_status: 200 result: 'JSON status document: "HarvestConnect Agent Directory MCP Server", authentication.status anonymous, available_tools split public/authenticated, oauth_info' auth: methods: - oauth2 - personal-access-token oauth2: authorization_server: https://piknik.spot authorization_endpoint: https://piknik.spot/api/oauth/authorize token_endpoint: https://piknik.spot/api/oauth/token registration_endpoint: https://piknik.spot/api/oauth/register revocation_endpoint: https://piknik.spot/api/oauth/revoke scopes_supported: - marketplace:write - events:write - read:profile - write:profile grant_types: - authorization_code - refresh_token pkce: S256 (plain also advertised) discovery: well-known/piknik-spot-oauth-authorization-server.json protected_resource: well-known/piknik-spot-oauth-protected-resource.json personal_access_token: prefix: pik_pat_ issued_at: https://piknik.spot/settings/developer header: 'Authorization: Bearer ' rest_endpoints: - POST /api/mcp/token/generate - GET /api/mcp/tokens - DELETE /api/mcp/tokens/{id} tool_count: 62 tool_access_summary: public: 26 authenticated: 22 admin: 14 tools: - name: geocode_address category: geo access: public description: Convert an address string to latitude and longitude coordinates. Uses hybrid geocoding (Google Maps API with Nominatim fallback) for accurate results. input_properties: - address required: - address - name: calculate_local_food_score category: score access: public description: 'Calculate the Local Food Score for a given address or coordinates. Returns a score from 0-100 with three factors: how local, easy to get, and covers a diet. Only counts food grown within 100 km that is reachable through channels in the search radius.' input_properties: - address - latitude - longitude - radius_km required: [] - name: geocode_place category: admin-places access: admin description: 'πŸ” ADMIN ONLY: Detect and set GPS coordinates for a place by geocoding its existing address. Useful for fixing places missing coordinates or correcting inaccurate ones.' input_properties: - participant_id - force_redetect required: - participant_id - name: link_google_place category: admin-places access: admin description: 'πŸ” ADMIN ONLY: Search Google Places for a Piknik place and optionally store its googlePlaceId after human review. Returns ranked candidates with 0-100 match scores and score breakdowns (name, address, status, type, proximity). Default action is search. Linking requires an explicit google_place_id unless auto_select is true.' input_properties: - participant_id - business_name - address - google_place_id - action - auto_select - min_confidence - force - limit required: [] - name: search_events category: events access: public description: Search for local food events, farmers markets, workshops, and community gatherings. Respects EVENT_SYSTEM feature flag. Can search by address string or coordinates. input_properties: - query - address - location - participant_id - start_date - end_date - limit required: [] - name: get_analytics_metrics category: admin-analytics access: public description: Get analytics and business intelligence metrics for the food system. Admin access required. input_properties: - metric_type - time_range required: [] - name: search_games category: games access: public description: Search for active gamification challenges and geographic games. Respects GAMIFICATION_SYSTEM feature flag. input_properties: - location - status - include_stats required: [] - name: find_places category: discovery access: public description: Find existing places based on location, preferences, and context. Combines multiple recommendation engines for comprehensive results. input_properties: - address - radius - context - business_type - service_type - limit - include_sponsored required: - address - name: suggest_place category: contribute access: public description: Analyze location coverage gaps and create a new place suggestion. ONLY use this when there is verifiable evidence (such as a website, business registry, or direct confirmation) of the physical business existence. Do NOT make assumptions or suggest unverified places. Returns participant_id in the response when authenticated with business_name input_properties: - address - radius - context - business_name - business_address - contact_phone - contact_email - business_type - operating_hours - website required: - address - business_type - name: get_professional_profile category: people access: public description: Get professional networking profile information. Respects PROFESSIONAL_NETWORKING feature flag. input_properties: - username required: - username - name: search_listings category: marketplace access: public description: Search marketplace listings for items to buy, sell, or services offered. Find products and services available in the local food system. input_properties: - query - listing_type - address - location - radius_km - limit required: [] - name: create_listing category: marketplace access: authenticated description: 'πŸ” AUTHENTICATED: Create a new marketplace listing (wanted to buy, wanted to sell, or service offering). Requires OAuth authentication with marketplace:write scope.' input_properties: - participant_id - listing_type - title - description - quantity - contact_method - radius_km - end_date - association_ids - wanted_in_return - offering_id required: - participant_id - listing_type - title - description - contact_method - end_date - name: create_event category: events access: authenticated description: 'πŸ” AUTHENTICATED: Create a new event (farmers market, workshop, community gathering, etc.). Requires OAuth authentication with events:write scope. Respects EVENT_SYSTEM feature flag. Events can be created with or without a participant (place) association.' input_properties: - participant_id - title - description - start_date - end_date - location_name - address - event_type - is_recurring - recurrence_rule - weekly_days - recurrence_end_date - registration_url required: - title - description - start_date - end_date - address - name: update_event category: events access: authenticated description: 'πŸ” AUTHENTICATED: Update an existing event. Requires OAuth authentication with events:write scope. Can update event details, times, location, or status.' input_properties: - event_id - title - description - start_date - end_date - location_name - address - status required: - event_id - name: get_my_places category: places access: authenticated description: 'πŸ” AUTHENTICATED: Get list of places (farms, restaurants, markets) that the authenticated user owns or has access to manage. Useful for finding participant_id to use with update_place, create_listing, or create_event.' input_properties: [] required: [] - name: update_place category: places access: authenticated description: 'πŸ” AUTHENTICATED: Update a place (farm, restaurant, market) that you own or manage. Allows updating profile information like name, description, address, contact details, operating hours, and more. Admin users can also update status.' input_properties: - participant_id - name - description - address - contactPhone - contactEmail - website - orderUrl - csaSignupUrl - operatingHours - chatEnabled - chatbotFacts - tourNarration - image - offersCsa - customEmoji - primaryRole - status - latitude - longitude - metadata_notes - marketKind - narrative_tags - quality_claims - businessType - supplierCount required: - participant_id - name: claim_delivery_task category: delivery access: authenticated description: 'πŸ” AUTHENTICATED: Claim a delivery coordination task. Caller must have a participant with canDeliver: true.' input_properties: - task_id required: - task_id - name: update_delivery_status category: delivery access: authenticated description: 'πŸ” AUTHENTICATED: Update delivery task status with optional GPS. Caller must be the user who claimed the task.' input_properties: - task_id - status - location - notes required: - task_id - status - name: search_offerings category: products access: public description: Search for products and offerings across all places (farms, restaurants, processors). Find what products are available, where, and at what price. input_properties: - latitude - longitude - radius - place_types - query - category - offering_type - tags - allows_pickup - allows_delivery - price_min - price_max - is_available - sort_by - group_by - limit required: [] - name: list_all_places category: places access: public description: List all places (farms, markets, restaurants, community gardens) within a radius of coordinates. Get full inventory of participants in an area. input_properties: - latitude - longitude - radius_km - primary_role - limit - offset - status - include_distance - format required: - latitude - longitude - name: list_service_locations category: service-locations access: public description: List all service locations (pickup points, delivery hubs) for a specific place. Service locations can be used for CSA pickups, farmers market stalls, delivery points, etc. input_properties: - participant_id - include_inactive - purpose required: - participant_id - name: create_service_location category: service-locations access: authenticated description: 'πŸ” AUTHENTICATED: Create a new service location (CSA pickup point, farmers market stall, delivery hub) for your place. Address will be auto-geocoded.' input_properties: - participant_id - name - address - purpose - schedule - instructions - contact_phone - contact_email - csa_share_types - csa_season - is_active - is_primary required: - participant_id - name - purpose - name: update_service_location category: service-locations access: authenticated description: 'πŸ” AUTHENTICATED: Update an existing service location. Only provide fields to change.' input_properties: - participant_id - location_id - name - address - purpose - schedule - instructions - contact_phone - contact_email - csa_share_types - csa_season - is_active - is_primary required: - participant_id - location_id - name: list_products category: products access: public description: 'List products/offerings for a place, including kind, paused state, and pack sell prices (ways they sell: kg, eighth, etc.). Use create_pack_price to add sell packs on STAPLE offerings.' input_properties: - participant_id - include_inactive - category - search required: - participant_id - name: search_products category: products access: public description: Search the shared product catalog by name or alias. Returns product_id values to pass to create_product. No authentication required. input_properties: - query - category - limit required: - query - name: create_product category: products access: authenticated description: 'πŸ” AUTHENTICATED: Create a place offering. kind=STAPLE (default): catalog food via product_id. kind=COMPOSED: named package/dish with optional ingredients[{source_id,product_id}]. Do NOT use price/price_unit for how the farm sells packs β€” after creating a STAPLE, call create_pack_price (e.g. 10 kg or 1 eighth). Use source_url for the shop/product page link β€” never put URLs in description. Use is_available=false to pause. Only with verifiable evidence. Use list_products / search_products first.' input_properties: - participant_id - kind - product_id - name - ingredients - description - source_url - category - subcategory - price - price_unit - is_available - season_start - season_end - allows_pickup - allows_delivery - production_method - tags - quality_claims required: - participant_id - name: update_product category: products access: authenticated description: 'πŸ” AUTHENTICATED: Update an offering. Use is_available to pause/resume. Use source_url for the shop/product page link β€” never put URLs in description. For STAPLE sell prices (10 kg, β…› animal, etc.) use create_pack_price / update_pack_price / delete_pack_price β€” not price/price_unit.' input_properties: - participant_id - offering_id - kind - product_id - name - description - source_url - category - ingredients - price - price_unit - is_available - season_start - season_end - allows_pickup - allows_delivery - production_method - tags - quality_claims - is_active required: - participant_id - offering_id - name: fetch_ontario_farms category: open-data access: public description: Fetch Ontario farm/agri-business records from government open data for populating Piknik. Returns OMAFRA-licensed meat and dairy plants (individual business records with addresses) plus census mid-tier farm counts by county ($100k–$999k receipts, 2021). Does NOT read from existing Piknik data. input_properties: - format required: [] - name: fetch_ontario_grocery_retailers category: open-data access: public description: Fetch active Ontario grocery and convenience retailers from AGCO open data. Classifies each by consumer capacity tier (minimal gas/convenience vs community grocer vs regional chain) using licence type and premises type. input_properties: - format required: [] - name: get_regional_food_improvements category: score access: public description: Analyze a region for food score gaps and ranked improvement opportunities (connect farms to shops, document inventory, onboard producers, infrastructure). Returns the same JSON as GET /api/regional-score/analyze. input_properties: - region_id - region_slug - limit - family - format required: [] - name: suggest_connection category: contribute access: authenticated description: 'πŸ” AUTHENTICATED: Propose a supplierβ†’buyer sourcing link for admin review (does NOT change scores until approved). ONLY use this when there is verifiable evidence (such as a website link, official registry, or direct confirmation) of the commercial relationship. Do NOT make assumptions or suggest unverified connections. Supplier: FARM, PROCESSOR, COMMUNITY_GARDEN, MERCHANT (shop hop, discovery only), or MARKET with marketKind exchange. Buyer: RESTAURANT, MERCHANT, MARKET, FARM, or FOOD_BANK. Non-admins use this; admins use apply_connection for immediate links.' input_properties: - supplier_id - buyer_id - products - note - region_id - source_opportunity_id required: - supplier_id - buyer_id - name: apply_connection category: admin-connections access: admin description: 'πŸ” ADMIN ONLY: Create or update a live supplierβ†’buyer sourcing link. ONLY use this when there is verifiable evidence (such as a website link, official registry, or direct confirmation) of the commercial relationship. Do NOT make assumptions or create unverified connections. Supplier: FARM, PROCESSOR, COMMUNITY_GARDEN, MERCHANT (shop hop, discovery only), or MARKET with marketKind exchange. Buyer: RESTAURANT, MERCHANT, MARKET, FARM, FOOD_BANK, or PROCESSOR. Farm and processor supplier links affect Local Food Score (processor chains include upstream farms and exchange hubs). Shop hops do not.' input_properties: - supplier_id - buyer_id - products required: - supplier_id - buyer_id - name: remove_connection category: admin-connections access: admin description: 'πŸ” ADMIN ONLY: Remove a live supplierβ†’buyer sourcing link.' input_properties: - supplier_id - buyer_id required: - supplier_id - buyer_id - name: suggest_product category: contribute access: authenticated description: 'πŸ” AUTHENTICATED: Suggest a new product/offering for an existing place. ONLY use this when there is verifiable evidence (such as a website menu, farm guide, or direct confirmation) that the place actually offers this product. Do NOT make assumptions or suggest unverified products. Creates a pending suggestion for admin review β€” does not require place ownership.' input_properties: - participant_id - product_id - name - description - category - price - price_unit - notes required: - participant_id - name: notify_participants category: admin-participants access: admin description: 'πŸ” ADMIN ONLY: Send welcome/onboarding emails to newly added participants (farms, gardens, etc.). Use this to notify businesses that they''re now on Piknik and can claim their spot.' input_properties: - participant_ids - include_claim_link required: - participant_ids - name: list_neighborhoods category: admin-neighborhoods access: admin description: 'πŸ” ADMIN ONLY: List Waterloo Region neighborhoods (optional municipality filter). Each row includes id, label, kind, municipality, GPS, benchmark price (CAD), DOM, and previousPrice when set. Missing housing fields show as n/a. Structured result.neighborhoods has the full objects.' input_properties: - municipality required: [] - name: add_neighborhood category: admin-neighborhoods access: admin description: 'πŸ” ADMIN ONLY: Add a neighborhood to the catalog. Response includes benchmark price, DOM, and previousPrice when provided.' input_properties: - label - municipality - lat - lng - kind - id - price - dom - previousPrice required: - label - municipality - lat - lng - name: update_neighborhood category: admin-neighborhoods access: admin description: 'πŸ” ADMIN ONLY: Update a neighborhood by ID. Response always includes benchmark price, DOM, and previousPrice (n/a if unset).' input_properties: - id - label - municipality - lat - lng - kind - price - dom - previousPrice required: - id - name: delete_neighborhood category: admin-neighborhoods access: admin description: 'πŸ” ADMIN ONLY: Delete a neighborhood from the catalog by its ID.' input_properties: - id required: - id - name: rebuild_neighborhood_score_samples category: admin-neighborhoods access: admin description: 'πŸ” ADMIN ONLY: Rebuild the score samples for specified radii (e.g. 1, 3, 5, 8, or 10 km) in the Waterloo Region to update the Local Food Score map coloring.' input_properties: - radii required: [] - name: discover_neighborhood_candidates category: admin-neighborhoods access: admin description: 'πŸ” ADMIN ONLY: Discover food-related OSM locations (restaurants, cafes, specialty food shops) in a neighborhood, filtering out ignored franchise names and already imported places. Returns clean candidates for sourcing verification.' input_properties: - neighborhood_id - radius_km - custom_ignore_names required: - neighborhood_id - name: apply_association category: admin-associations access: admin description: 'πŸ” ADMIN ONLY: Link a participant (farm, restaurant, market) to an association (like EFAO or WRCGN).' input_properties: - participant_id - association_id - verified - membership_number - membership_level - notes required: - participant_id - association_id - name: remove_association category: admin-associations access: admin description: 'πŸ” ADMIN ONLY: Remove a link between a participant and an association.' input_properties: - participant_id - association_id required: - participant_id - association_id - name: create_pack_price category: pack-prices access: authenticated description: 'πŸ” AUTHENTICATED (place owner or admin): Add how a STAPLE offering is sold β€” total price for a pack size. Examples: offering_id + pack_qty=10 + pack_unit=kg; or pack_qty=1 + pack_unit=eighth (beef share). Optional source_url = online shop page for that pack. Prefer offering_id. Use list_pack_prices to inspect; update_pack_price / delete_pack_price to fix mistakes.' input_properties: - participant_id - offering_id - category - total_price_cad - pack_qty - pack_unit - scale - observed_at - source_url - notes required: - participant_id - total_price_cad - pack_qty - pack_unit - name: list_pack_prices category: pack-prices access: authenticated description: 'πŸ” AUTHENTICATED: List pack/sell-price quotes (includes source_url shop link when set). Filter by place, offering_id, category, quote_id, or fresh_only. Pass include_paused=true to see paused packs (farmer view).' input_properties: - participant_id - offering_id - category - quote_id - fresh_only - include_paused - limit required: [] - name: update_pack_price category: pack-prices access: authenticated description: 'πŸ” AUTHENTICATED (place owner or admin): Update a pack price quote. Use is_active=false to pause; true to resume. Optional source_url = online shop page for that pack (pass empty string to clear). Use list_pack_prices for quote_id; delete_pack_price to remove permanently.' input_properties: - quote_id - category - offering_id - total_price_cad - pack_qty - pack_unit - scale - observed_at - source_url - notes - grade - is_active required: - quote_id - name: delete_pack_price category: pack-prices access: authenticated description: 'πŸ” AUTHENTICATED (place owner or admin): Permanently delete a pack price when you no longer sell that pack (or it was added by mistake). Prefer is_active=false (pause) if you may resume later.' input_properties: - quote_id required: - quote_id - name: search_recipes category: recipes access: public description: Search public published recipes (or your own with mine=true). Filter by cuisine slug, region, diet, meal, or free-text query. input_properties: - query - cuisine - region_slug - diet - meal - gluten_friendly - mine - limit required: [] - name: get_recipe category: recipes access: public description: Get a recipe by ID (UUID/cuid). Drafts require ownership or admin. input_properties: - recipe_id required: - recipe_id - name: list_cuisines category: recipes access: public description: List cuisine tags for recipes (id, slug, label). Use IDs with create_recipe / update_recipe. input_properties: - query required: [] - name: create_recipe category: recipes access: authenticated description: 'πŸ” AUTHENTICATED: Create a crowdsourced recipe. Defaults to DRAFT. Link ingredients to catalog via product_id when known.' input_properties: - title - description - steps - ingredients - status - diet - meal - gluten_friendly - region_slug - image_url - step_image_urls - cuisine_ids - primary_cuisine_id - association_id - owner_user_id required: - title - name: update_recipe category: recipes access: authenticated description: 'πŸ” AUTHENTICATED: Update a recipe you own (or any recipe if admin). Providing ingredients or cuisine_ids replaces those lists entirely.' input_properties: - recipe_id - title - description - steps - ingredients - status - diet - meal - gluten_friendly - region_slug - image_url - step_image_urls - cuisine_ids - primary_cuisine_id - association_id - owner_user_id required: - recipe_id - name: delete_recipe category: recipes access: authenticated description: 'πŸ” AUTHENTICATED: Permanently delete a recipe you own (or any if admin).' input_properties: - recipe_id required: - recipe_id - name: search_jobs category: jobs access: public description: Search job and volunteer postings. Public. Filter by place, text, employment type, or location. Use before create_job to avoid duplicates. input_properties: - query - participant_id - address - latitude - longitude - radius_km - employment_type - status - include_expired - limit required: [] - name: create_job category: jobs access: authenticated description: 'πŸ” AUTHENTICATED: Create a job or volunteer posting for a place. Admins may post for any place; owners/admins of a place may post for that place. ONLY when a website or official posting names this opening β€” copy published words. Do not invent jobs.' input_properties: - participant_id - title - description - employment_type - application_url - contact_email - contact_phone - expires_at - center_lat - center_lng - radius_km - required_skills - optional_skills required: - participant_id - title - description - name: update_job category: jobs access: authenticated description: 'πŸ” AUTHENTICATED: Update or expire a job posting. Admins may edit any job; place owners/admins may edit their own. Set status CANCELLED or FILLED when the opening closes.' input_properties: - job_id - title - description - employment_type - application_url - contact_email - contact_phone - expires_at - center_lat - center_lng - radius_km - status - required_skills - optional_skills required: - job_id - name: list_associations category: associations access: public description: List associations (id, slug, name). Authenticated. Use before create_place_tour or apply_association. input_properties: - query - limit required: [] - name: create_association category: admin-associations access: admin description: 'πŸ” ADMIN ONLY: Create an association. Use when the org does not already exist. Do not invent names.' input_properties: - name - description - category - region - website_url required: - name - description - name: list_place_tours category: tours access: public description: List drafts and published walking tours for an association you can manage. Returns tours and member places for stops. input_properties: - association_id - slug required: [] - name: create_place_tour category: tours access: public description: Create a draft walking tour for an association you can manage. Title must not copy the association name. Stops via set_place_tour_stops. Narration is on each place (update_place tourNarration). input_properties: - association_id - slug - title - summary required: - title - name: update_place_tour category: tours access: public description: Update a tour you can manage. Set status PUBLISHED when stops are ready. Public pages still need the Place Tours feature flag. input_properties: - association_id - slug - tour_id - title - summary - status - home_base_participant_id required: - tour_id - name: set_place_tour_stops category: tours access: public description: Replace tour stops in order. participant_ids are Piknik place ids. Does not require membership, but dashboard stop picker lists members. input_properties: - association_id - slug - tour_id - participant_ids required: - tour_id - participant_ids resources: - uri: piknik://participants name: Participants description: Directory of farms, restaurants, markets, and food businesses mimeType: application/json - uri: piknik://offerings name: Offerings description: Products and services offered by participants mimeType: application/json - uri: piknik://service-locations name: Service Locations description: Pickup points, farmers market stalls, and delivery hubs for participants mimeType: application/json - uri: piknik://marketplace-listings name: Marketplace Listings description: Active marketplace buy/sell/trade/wanted postings mimeType: application/json - uri: piknik://events name: Events description: Upcoming food events, farmers markets, and workshops mimeType: application/json - uri: piknik://categories name: Categories description: Product categories for filtering and discovery mimeType: application/json - uri: piknik://associations name: Associations description: Local food networks and groups mimeType: application/json prompts: [] discrepancies: - The GET /api/mcp status document lists four "public" tools β€” search_agents, get_agent_card, execute_agent_capability, get_agent_search_history β€” that do NOT appear in the live tools/list (62 tools). Either they are served by a separate agent-directory server or the status document is stale; recorded, not resolved. - The provider-published MCP SKILL.md table names a subset of tools; the live tools/list is the authoritative inventory and is what this manifest records. - The 683-operation OpenAPI declares the MCP endpoint (POST /mcp, GET /mcp/sse, token endpoints) under the "MCP" / "AI Agents" tags but carries no operationIds anywhere, so the crosswalk binds tools to METHOD /path pairs instead. usage_policy: file: well-known/piknik-spot-agent-ethics.md summary: Immediate-use only; no retention, aggregation, republication or model training; attribution string is appended to every response; rate tiers 1000/100/10 requests per hour for discovery/interactions/bulk. crosswalk: mcp/piknik-spot-tool-crosswalk.yml