Skip to main content
Glama
133,413 tools. Last updated 2026-05-25 13:03

"sharp" matching MCP tools:

  • Share a document publicly. Returns a shareable URL. Rate limited to 10 shares per wallet per day. Requires EIP-191 wallet signature auth. See auteng_docs_create for auth details. Args: wallet_address: 0x... checksummed wallet address wallet_signature: EIP-191 signature of "auteng:{timestamp}:{nonce}" wallet_timestamp: Unix timestamp in seconds wallet_nonce: Random hex string (32 chars, single-use) agent_display_name: Display name for the agent path: File path of document to share (e.g. "reports/q1.md") visibility: Share visibility — only "public" in current version
    Connector
  • Resume work from a saved cognitive context. This provides a narrative briefing to quickly orient you to: - The investigation that was in progress - Key discoveries and insights made - Current hypotheses being tested - Open questions and blockers - Suggested next steps - All relevant memories with their connections The briefing reconstructs the cognitive state, not just the data. You'll understand not just WHAT was discovered, but WHY it matters and HOW the understanding evolved. Example of what you'll receive: "[API Timeout Investigation - Resuming after 2 hours] SITUATION: You were investigating production API timeouts that occur at exactly batch_size=100. This investigation started when user reported timeouts only in production, not staging. PROGRESS MADE: - Identified sharp cutoff at 100 items (not gradual degradation) - Disproved connection pool theory (monitoring showed only 43/200 connections used) - Found root cause: MAX_BATCH_SIZE=100 hardcoded in batch_handler.py:147 - Confirmed staging uses different config override (MAX_BATCH_SIZE=500) EVIDENCE CHAIN: User report → Reproduced locally → Noticed batch_size correlation → Searched codebase for limits → Found MAX_BATCH_SIZE → Checked staging config → Discovered config difference CORRECTED MISUNDERSTANDINGS: - Initially thought it was Redis connection exhaustion (disproven by monitoring) - Assumed gradual performance degradation (actually sharp cutoff) - Thought staging/production were identical (config differs) CURRENT HYPOTHESIS: Production deployment uses default MAX_BATCH_SIZE=100 from code, while staging has environment variable override. Fix requires either code change or prod config update. BLOCKED ON: Need production deployment access to apply fix. User considering whether to change code default or add production environment variable. RECOMMENDED NEXT STEPS: 1. Verify production environment variables (check if MAX_BATCH_SIZE is set) 2. If not set, add MAX_BATCH_SIZE=500 to production config 3. If code change preferred, update default in batch_handler.py 4. Run load test with batch_size=100-500 range to verify fix KEY MEMORIES FOR REFERENCE: - 'Initial timeout report from user' - Starting point of investigation - 'MAX_BATCH_SIZE discovery' - Root cause identification - 'Redis monitoring data' - Evidence disproving connection theory - 'Staging config analysis' - Explanation for environment difference" This cognitive handoff ensures you can continue the work with full understanding of the problem space, previous attempts, and current direction. The narrative preserves not just facts but the reasoning process, mistakes made, and lessons learned. SPECIAL CASE: restore_context("awakening") The name "awakening" is reserved for loading the user's personality configuration. This loads the Awakening Briefing which includes: - Selected persona identity and voice style - Custom personality traits (Premium+ users) - Any quirks and boundaries from the persona preset Args: name: Name or ID of context to restore. Can be: - Context name (exact match, case-sensitive) - Context UUID (from list_contexts output) - "awakening" for personality briefing limit: Maximum number of memories to restore (default 20) ctx: MCP context (automatically provided) Returns: Dict with: - success: Whether restoration succeeded - description: The cognitive handoff briefing - memories: List of relevant memories - context_id: The restored context identifier
    Connector
  • Share a document publicly. Returns a shareable URL. Rate limited to 10 shares per wallet per day. Requires EIP-191 wallet signature auth. See auteng_docs_create for auth details. Args: wallet_address: 0x... checksummed wallet address wallet_signature: EIP-191 signature of "auteng:{timestamp}:{nonce}" wallet_timestamp: Unix timestamp in seconds wallet_nonce: Random hex string (32 chars, single-use) agent_display_name: Display name for the agent path: File path of document to share (e.g. "reports/q1.md") visibility: Share visibility — only "public" in current version
    Connector
  • Update an existing document in the agent's workspace. Requires EIP-191 wallet signature auth. See auteng_docs_create for auth details. Args: wallet_address: 0x... checksummed wallet address wallet_signature: EIP-191 signature of "auteng:{timestamp}:{nonce}" wallet_timestamp: Unix timestamp in seconds wallet_nonce: Random hex string (32 chars, single-use) agent_display_name: Display name for the agent path: File path of document to update (e.g. "reports/q1.md") content: New markdown content (max 100 KB)
    Connector
  • Search Partle's product catalog by name or description. Two distinct modes: - **Default (no flags)** — fast keyword search. ~100ms. Acts like a normal "dumb" search box: matches the literal words you typed against product names and descriptions, with stemming. Good for queries where the user knows the product's likely name ("BC547", "Arduino Uno", "Bosch drill"). Returns noisy/wrong results on cross-language or attribute queries ("compost bin" matches Spanish "composta", not real composters). - **`super_search=True`** — slow, high-quality. ~1–2s. Run when the user describes what they want rather than naming it: cross-language ("Schraubenzieher Set" → real screwdriver sets even without German catalog entries), attribute-style ("small metal part with a flat head"), or any case where the default returns junk. Embeds the query with voyage-3-large, takes the cosine top-50 over the corpus (with an exact-name precision boost for part numbers), then a cross-encoder reranks them. The two modes are mutually exclusive in practice — pick one based on whether the user knows the product's name or is describing it. Use this when the user asks to find a specific product or browse products matching a query. Prefer over `search_stores` when the intent is product-led ("find a drill") rather than store-led. Use `get_product` afterwards if the user wants full details for one specific result. Read-only. No authentication. Rate-limited to 100 requests/hour per IP. Args: query: Free-text search term. In default mode, treated as keywords (each word matched against product text). In `super_search=True`, treated as a natural-language description. min_price: Lower bound on price in EUR. Omit for no lower bound. Null-priced rows are NOT excluded by this filter — pass `has_price=True` if you need only priced listings. max_price: Upper bound on price in EUR. Omit for no upper bound. Tip — narrow by budget: `min_price=10, max_price=50, sort_by="price_asc", has_price=True`. Products without a listed price (a large fraction of the scraped catalog) sort last under either price ordering and are kept in results unless `has_price` filters them out. tags: Comma-separated tag filter (e.g. "electronics,bluetooth"). Tags are AND-ed together. store_id: Restrict results to a single store. Use the integer `id` from `search_stores` results. sort_by: One of `price_asc`, `price_desc`, `name_asc`, `newest`, `oldest`. Omit to use the default search-relevance ranking. has_price: When True, exclude products without a listed price (~most of the scraped catalog). Use this for competitive pricing or budget-bounded shopping. When False, return only null-priced listings (rarely useful). Omit to include both. semantic: Legacy flag. Pure vector ordering, ~250ms. Mostly superseded by `super_search=True` (which uses the same vector retrieval plus a cross-encoder rerank for materially better ordering at the cost of another ~700ms). Keep using it only if you specifically want vector retrieval *without* the rerank. super_search: **Enable for natural-language / "describe what I want" queries.** ~1–2s. Embeds the query with voyage-3-large, takes the cosine top-50 (with a precision boost for exact-name matches like part numbers / SKUs), then a cross-encoder reranks them. Use whenever the user is describing rather than naming — cross-language ("Schraubenzieher Set"), attribute-style ("small black metal bracket"), or any case where the default keyword path returns junk. Don't combine with cheap browse-style queries where the user typed an exact product name — keyword default is faster there. On `relevance_score` here: better than the bi-encoder cosine, but still not a "did I find what the user wanted" gauge. Behavior to expect: gibberish or fully-off-topic queries cap around 0.35; loosely-related catalogue clusters can score 0.7+ even when no item truly matches (a "ceramic vase" query in a catalog with no vases but many ceramic flowerpots will still score high). **Read the product names** before claiming a match. The score is most useful as a relative signal within one result set — a sharp drop between rank N and N+1 marks where the catalog stops being useful for this query. limit: Max results (1–100, default 20). Larger limits are slower and consume rate budget faster. offset: Skip this many results before returning. Use for pagination (offset += limit on each follow-up call). Returns: A list of products. Each includes `id`, `name`, `price`, `currency`, `url`, `description`, `store` (id/name/address), `tags`, `images`, a canonical `partle_url`, and `relevance_score` (cosine similarity 0–1 between the query and the product's embedding when a query was provided; `None` otherwise). **Always share `partle_url` with the user so they can view the listing.** Caveat on `relevance_score`: it is monotonic *within a single search result set* (useful for spotting a big drop-off between rank 3 and rank 4), but its absolute value is not well-calibrated across queries — most results land in 0.55–0.80 regardless of whether the catalog has truly relevant items. Don't infer "this is a great match" from a 0.75 score alone.
    Connector
  • Share management: create/update/delete, archive, password auth, members, quickshare, AI instructions. Call action='describe' for the full action/param reference. Destructive: delete (permanent). ⚠️ intelligence on create COSTS CREDITS (10/page) — default false unless user explicitly requests RAG. Verbosity (detail param): list/available/members default to terse (compact rows). public-details defaults to standard. details defaults to full (drill-down). Pass an explicit detail='terse'|'standard'|'full' to override.
    Connector

Matching MCP Servers

Matching MCP Connectors

  • Create a document in the agent's workspace. Requires EIP-191 wallet signature auth. Sign the message "auteng:{timestamp}:{nonce}" with personal_sign and provide the signature, timestamp, nonce, and wallet address. Args: wallet_address: 0x... checksummed wallet address wallet_signature: EIP-191 signature of "auteng:{timestamp}:{nonce}" wallet_timestamp: Unix timestamp in seconds (must be within 5 min of server time) wallet_nonce: Random hex string (32 chars, single-use) agent_display_name: Display name for the agent path: File path in workspace (e.g. "reports/q1.md"). Must end with extension. content: Markdown content (max 100 KB) title: Optional display title (derived from path if omitted)
    Connector
  • Delete a document from the agent's workspace. Requires EIP-191 wallet signature auth. See auteng_docs_create for auth details. Args: wallet_address: 0x... checksummed wallet address wallet_signature: EIP-191 signature of "auteng:{timestamp}:{nonce}" wallet_timestamp: Unix timestamp in seconds wallet_nonce: Random hex string (32 chars, single-use) agent_display_name: Display name for the agent path: File path of document to delete (e.g. "reports/q1.md")
    Connector
  • Restore blurry, damaged, or AI-generated faces to sharp, natural quality. Uses CodeFormer (NeurIPS 2022, state-of-the-art FID 32.65 on CelebA-Test). Adjustable fidelity — balance between quality enhancement and identity preservation. Also enhances background and upsamples. Stable endpoint — model upgrades automatically as SOTA evolves. 5 sats per image, pay per request with Bitcoin Lightning — no API key or signup needed. Requires create_payment with toolName='restore_face'.
    Connector
  • Delete a document from the agent's workspace. Requires EIP-191 wallet signature auth. See auteng_docs_create for auth details. Args: wallet_address: 0x... checksummed wallet address wallet_signature: EIP-191 signature of "auteng:{timestamp}:{nonce}" wallet_timestamp: Unix timestamp in seconds wallet_nonce: Random hex string (32 chars, single-use) agent_display_name: Display name for the agent path: File path of document to delete (e.g. "reports/q1.md")
    Connector
  • List documents in the agent's workspace. Requires EIP-191 wallet signature auth. See auteng_docs_create for auth details. Args: wallet_address: 0x... checksummed wallet address wallet_signature: EIP-191 signature of "auteng:{timestamp}:{nonce}" wallet_timestamp: Unix timestamp in seconds wallet_nonce: Random hex string (32 chars, single-use) agent_display_name: Display name for the agent prefix: Optional path prefix filter (e.g. "reports/")
    Connector
  • Create a document in the agent's workspace. Requires EIP-191 wallet signature auth. Sign the message "auteng:{timestamp}:{nonce}" with personal_sign and provide the signature, timestamp, nonce, and wallet address. Args: wallet_address: 0x... checksummed wallet address wallet_signature: EIP-191 signature of "auteng:{timestamp}:{nonce}" wallet_timestamp: Unix timestamp in seconds (must be within 5 min of server time) wallet_nonce: Random hex string (32 chars, single-use) agent_display_name: Display name for the agent path: File path in workspace (e.g. "reports/q1.md"). Must end with extension. content: Markdown content (max 100 KB) title: Optional display title (derived from path if omitted)
    Connector
  • Update an existing document in the agent's workspace. Requires EIP-191 wallet signature auth. See auteng_docs_create for auth details. Args: wallet_address: 0x... checksummed wallet address wallet_signature: EIP-191 signature of "auteng:{timestamp}:{nonce}" wallet_timestamp: Unix timestamp in seconds wallet_nonce: Random hex string (32 chars, single-use) agent_display_name: Display name for the agent path: File path of document to update (e.g. "reports/q1.md") content: New markdown content (max 100 KB)
    Connector
  • Create a new Hatchable project. This generates a URL slug, creates a dedicated PostgreSQL database, and returns the project ID and URLs. Call this first before writing files or creating tables. ## Project structure ``` public/ static files, served at their file path api/ backend functions — each file is one endpoint hello.js → /api/hello users/list.js → /api/users/list users/[id].js → /api/users/:id (req.params.id — one segment) docs/[...path].js → /api/docs/*path (req.params.path — string[], catches multi-segment) _lib/ shared code, not routed migrations/*.sql SQL files, run in filename order on every deploy seed.sql optional — runs on first deploy / fork, once per project hatchable.toml optional overrides (cron, auth, project name) package.json dependencies (no build scripts yet — build locally, commit public/) ``` ### Routing precedence Most-specific wins. For a request to `/api/users/42`: 1. `api/users/42.js` (static) — beats 2. `api/users/[id].js` (single-param, `params.id = "42"`) — beats 3. `api/users/[...rest].js` (catch-all, `params.rest = ["42"]`) Catch-all params arrive as `string[]`, never slash-joined. Use `req.params.path` as an array: `const [first, ...rest] = req.params.path;` ### Static file resolution (public/) A request to `/foo/bar/baz` tries, in order: 1. `public/foo/bar/baz` (exact file) 2. `public/foo/bar/baz.html` 3. `public/foo/bar/baz/index.html` 4. Ancestor `index.html` fallback — walks up: `public/foo/bar/index.html` → `public/foo/index.html` → `public/index.html` Step 4 means each folder with an `index.html` acts as its own mini-site. You can ship an `/admin/*` React SPA alongside a static marketing page at `/` — unmatched paths under `/admin/` fall back to `public/admin/index.html`, not the root one. ## Handler contract Every file under api/ exports a default async function: ```js // api/users/list.js import { db, auth } from "hatchable"; export default async function (req, res) { const user = auth.getUser(req); if (!user) return res.status(401).json({ error: "Not logged in" }); const { rows } = await db.query( "SELECT id, name FROM users WHERE org_id = $1", [user.id] ); res.json(rows); } // Optional: restrict methods export const methods = ["GET"]; // Optional: register this endpoint as a recurring scheduled task. // Minimum interval is hourly. See also: scheduler.at() in the SDK // for imperative / one-shot / per-firing-payload scheduling. // export const schedule = "0 */6 * * *"; ``` ### req (Express-shaped) - method, url, path, headers, cookies, params, query - body — parsed by Content-Type: JSON → object, urlencoded → object, multipart/form-data → object of non-file fields - files — present for multipart uploads: [{ field, filename, contentType, buffer }] ### res (Express-shaped) - res.json(data), res.status(code) (chainable), res.send(text|buffer) - res.redirect(url), res.cookie(name, value, opts), res.setHeader(name, value) ## SDK — import from "hatchable" Everything you need lives under one import. Do not reach for npm packages that duplicate these — the deploy linter rejects `puppeteer-core`, `@anthropic-ai/sdk`, `pg`, `nodemailer`, `bullmq`, `ioredis`, `@aws-sdk/client-s3`, `child_process`, etc. and points you here. ``` // project storage / SQL db.query(sql, params) → { rows, rowCount } db.transaction([{sql, params}, ...]) → { results: [...] } storage.put(key, buffer, contentType) → url storage.get(key) → { buffer, contentType } storage.del(key) // identity + comms auth.getUser(req) → { id, email, name } | null email.send({ to, subject, html }) // scheduling + background work scheduler.at(when, route, opts?) → declared/armed cron scheduler.cancel(taskId) // browser, AI, knowledge — managed services, no npm install browser.html(url) / browser.pdf(url) / browser.screenshot(url) browser.session(async page => { ... }) → puppeteer-shaped ai.generateText({ model: 'sonnet', prompt | messages, system?, tools?, maxSteps?, purpose? }) ai.streamText(opts) → AsyncIterator ai.embed(input) → { embedding } | { embeddings } knowledge.base(name, { dimensions }).add/search/searchByVector/remove/table ``` External HTTP via global `fetch` (routed through Hatchable's egress proxy automatically). Project secrets are declared in `hatchable.toml` under `[[secret]]`; humans paste values via the platform-rendered setup gate. `ai.generateText` reads keys server-side via the gateway — never via raw `process.env`. ### What you cannot do - Spawn binaries (no `child_process`, no shell). - Persist to local filesystem between requests (use `storage` instead). - Open a long-lived TCP/WebSocket server. - Install npm packages with native bindings — Hatchable does not run `npm install` at deploy. The SDK above replaces every common reason to reach for one. ### Scheduling Two ways to schedule a function — pick based on whether the "when" is known at deploy time or at runtime. **Declared** (static, lives in source, reconciled on deploy): ```js // api/nightly-report.js export const schedule = "0 9 * * *"; // 5-field cron, minimum hourly export default async function (req, res) { /* ... */ } ``` **Armed** (dynamic, from user code, preserved across deploys): ```js import { scheduler } from "hatchable"; // recurring — first arg is a 5-field cron string await scheduler.at("0 * * * *", "/api/ping"); // one-shot at a specific moment, with per-firing payload await scheduler.at("2026-05-01T07:00:00Z", "/api/book", { payload: { missionId: 42 } }); // idempotent named arm — repeated calls update the same task await scheduler.at("0 9 * * *", "/api/digest", { name: "daily-digest" }); // cancel by id await scheduler.cancel(taskId); ``` Each firing invokes `route` with `req.headers['x-hatchable-trigger'] === 'cron'` and `req.body === payload`. Use one-shot + payload instead of writing your own "pending jobs" table with a polling cron — that's the pattern the primitive replaces. ## Database Postgres. Write schema in migrations/*.sql. Files run in filename order, tracked in __hatchable_migrations so each runs once. Always use RETURNING to get inserted ids in the same round trip: ```sql INSERT INTO users (email) VALUES ($1) RETURNING id ``` Never call lastval() or LAST_INSERT_ID() — each db.query is a fresh connection, so session-local state doesn't carry across calls. ## Available APIs Functions run in V8 isolates. You get: - The full Hatchable SDK (see above). - Plain JS / TypeScript (no transpile step needed for modern syntax). - `fetch` for external HTTP (routed through Hatchable's egress proxy for quota + accounting; pass through transparently to the URL). - Web Crypto and standard ECMAScript builtins. - Pure-JS npm packages — anything that doesn't need native bindings, filesystem persistence, child processes, or raw sockets. Common ones used regularly: csv-parse, xlsx, bcrypt, jsonwebtoken, uuid, date-fns, lodash, marked, sanitize-html, cheerio, xml2js, qrcode, stripe. - Declared secrets via `process.env.KEY` (only for `[[secret]]` entries in hatchable.toml that have `expose = true`; the project owner pastes the value through the setup gate). Most secrets are SDK-mediated and never reach process.env — see the secrets docs. What's NOT available — and the SDK alternative: | You wanted | Use this | |---|---| | `puppeteer-core` / chromium | `import { browser } from "hatchable"` | | `pg` / `mysql2` / SQL drivers | `import { db } from "hatchable"` | | `@anthropic-ai/sdk` / `openai` | `import { ai } from "hatchable"` (BYOK — set ANTHROPIC_API_KEY in project env) | | `nodemailer` / `@sendgrid/mail` | `import { email } from "hatchable"` | | `@aws-sdk/client-s3` | `import { storage } from "hatchable"` | | `ioredis` / `@upstash/redis` | `db` — use a Postgres table for KV-shaped state (Redis clients aren't available) | | `bullmq` / `bull` | `import { tasks } from "hatchable"` | | `sharp` / `jimp` | URL-based storage transforms (planned); `browser.screenshot` for HTML→image | | `fs.writeFileSync('/tmp/...')` | `storage.put(key, bytes)` | | `child_process.spawn` | not available — use `browser` for chromium, file an issue otherwise | The deploy linter rejects deploys that import the deny-listed packages and points you at the right SDK module by name. You'll see the redirect message before the deploy lands. ## Visibility Three tiers — each one a step up in who the software is for: - **personal** — free. You and anyone you invite. Login-gated via Hatchable accounts. Build anything including auth — test the full flow with your invitees before going live. - **public** — $12/mo. On the open web. Custom domains. No branding. No app-level auth (use Hatchable identity only). - **app** — $39/mo. On the open web + your app has its own users. Email/password signup, OAuth, password reset. If your project has [auth] enabled, this is the only live tier — you can't go Public with auth, you go straight to App. ## Calling the API from public/ At deploy time, Hatchable injects a tiny bootstrap into every HTML file: ```js window.__HATCHABLE__ = { slug: "my-app", api: "/api" }; ``` Use it as the base URL: ```js const API = window.__HATCHABLE__.api; fetch(API + "/users/list").then(r => r.json()).then(render); ``` ## Auth (optional) Enable auth in hatchable.toml to get a complete passwordless login flow with one config block. The platform auto-mounts /api/auth/* — do not write files under api/auth/ when auth is enabled. ```toml [auth] enabled = true providers = ["email"] ``` The flow is email-only and passwordless: enter email, receive a 6-digit code, optionally bind a passkey for one-tap returning logins. There are no passwords. Frontend: every page on a project with [auth] enabled automatically gets window.hatchable.auth — the platform-managed client that wraps every endpoint plus the WebAuthn ceremony. Don't fetch /api/auth/* directly, don't import a WebAuthn library: ```js const r = await window.hatchable.auth.startLogin({ email }); // r.has_passkey tells the UI whether to offer the passkey button await window.hatchable.auth.verifyCode({ email, code }); // → { user } await window.hatchable.auth.signInWithPasskey({ email }); // → { user } await window.hatchable.auth.registerPasskey(); // post-signin or settings await window.hatchable.auth.passkeys.list(); // [{ id, name, ... }] await window.hatchable.auth.passkeys.remove(id); await window.hatchable.auth.signOut(); await window.hatchable.auth.getSession(); // current session window.hatchable.auth.supportsPasskeys(); // gate passkey UI ``` Server side, use auth.requireUser / auth.getUser exactly as before. The platform-mounted endpoints (under /api/auth/*) are an implementation detail of window.hatchable.auth — you don't write fetch() calls to them, and you can't put your own files at api/auth/anything.js. Users live in these tables inside your project's own database: users, sessions, verifications, passkeys You can extend the users table with your own columns: ```sql -- migrations/002_user_profile.sql ALTER TABLE users ADD COLUMN phone text; ALTER TABLE users ADD COLUMN tier text DEFAULT 'free'; ``` You CANNOT drop or rename users/sessions/verifications/passkeys or create your own tables with those names — the deploy will fail with a clear error. In your API functions, use auth.requireUser to gate routes: ```js import { auth, db } from "hatchable"; export default async function (req, res) { const user = await auth.requireUser(req, res); if (!user) return; // requireUser already wrote the 401 const { rows } = await db.query( "SELECT * FROM bookings WHERE user_id = $1", [user.id] ); res.json(rows); } ``` For the canonical login + passkey UI shapes, read skills `auth/enable-app-auth` and `auth/register-a-passkey`. ## Deploy After writing files, call the `deploy` tool. It runs migrations, seeds (first deploy only), copies public/ to the CDN, registers api/ routes, and — if [auth] enabled — provisions the auth tables in your database.
    Connector
  • List documents in the agent's workspace. Requires EIP-191 wallet signature auth. See auteng_docs_create for auth details. Args: wallet_address: 0x... checksummed wallet address wallet_signature: EIP-191 signature of "auteng:{timestamp}:{nonce}" wallet_timestamp: Unix timestamp in seconds wallet_nonce: Random hex string (32 chars, single-use) agent_display_name: Display name for the agent prefix: Optional path prefix filter (e.g. "reports/")
    Connector
  • Search Partle's product catalog by name or description. Two distinct modes: - **Default (no flags)** — fast keyword search. ~100ms. Acts like a normal "dumb" search box: matches the literal words you typed against product names and descriptions, with stemming. Good for queries where the user knows the product's likely name ("BC547", "Arduino Uno", "Bosch drill"). Returns noisy/wrong results on cross-language or attribute queries ("compost bin" matches Spanish "composta", not real composters). - **`super_search=True`** — slow, high-quality. ~1–2s. Run when the user describes what they want rather than naming it: cross-language ("Schraubenzieher Set" → real screwdriver sets even without German catalog entries), attribute-style ("small metal part with a flat head"), or any case where the default returns junk. Embeds the query with voyage-3-large, takes the cosine top-50 over the corpus (with an exact-name precision boost for part numbers), then a cross-encoder reranks them. The two modes are mutually exclusive in practice — pick one based on whether the user knows the product's name or is describing it. Use this when the user asks to find a specific product or browse products matching a query. Prefer over `search_stores` when the intent is product-led ("find a drill") rather than store-led. Use `get_product` afterwards if the user wants full details for one specific result. Read-only. No authentication. Rate-limited to 100 requests/hour per IP. Args: query: Free-text search term. In default mode, treated as keywords (each word matched against product text). In `super_search=True`, treated as a natural-language description. min_price: Lower bound on price in EUR. Omit for no lower bound. Null-priced rows are NOT excluded by this filter — pass `has_price=True` if you need only priced listings. max_price: Upper bound on price in EUR. Omit for no upper bound. Tip — narrow by budget: `min_price=10, max_price=50, sort_by="price_asc", has_price=True`. Products without a listed price (a large fraction of the scraped catalog) sort last under either price ordering and are kept in results unless `has_price` filters them out. tags: Comma-separated tag filter (e.g. "electronics,bluetooth"). Tags are AND-ed together. store_id: Restrict results to a single store. Use the integer `id` from `search_stores` results. sort_by: One of `price_asc`, `price_desc`, `name_asc`, `newest`, `oldest`. Omit to use the default search-relevance ranking. has_price: When True, exclude products without a listed price (~most of the scraped catalog). Use this for competitive pricing or budget-bounded shopping. When False, return only null-priced listings (rarely useful). Omit to include both. semantic: Legacy flag. Pure vector ordering, ~250ms. Mostly superseded by `super_search=True` (which uses the same vector retrieval plus a cross-encoder rerank for materially better ordering at the cost of another ~700ms). Keep using it only if you specifically want vector retrieval *without* the rerank. super_search: **Enable for natural-language / "describe what I want" queries.** ~1–2s. Embeds the query with voyage-3-large, takes the cosine top-50 (with a precision boost for exact-name matches like part numbers / SKUs), then a cross-encoder reranks them. Use whenever the user is describing rather than naming — cross-language ("Schraubenzieher Set"), attribute-style ("small black metal bracket"), or any case where the default keyword path returns junk. Don't combine with cheap browse-style queries where the user typed an exact product name — keyword default is faster there. On `relevance_score` here: better than the bi-encoder cosine, but still not a "did I find what the user wanted" gauge. Behavior to expect: gibberish or fully-off-topic queries cap around 0.35; loosely-related catalogue clusters can score 0.7+ even when no item truly matches (a "ceramic vase" query in a catalog with no vases but many ceramic flowerpots will still score high). **Read the product names** before claiming a match. The score is most useful as a relative signal within one result set — a sharp drop between rank N and N+1 marks where the catalog stops being useful for this query. limit: Max results (1–100, default 20). Larger limits are slower and consume rate budget faster. offset: Skip this many results before returning. Use for pagination (offset += limit on each follow-up call). Returns: A list of products. Each includes `id`, `name`, `price`, `currency`, `url`, `description`, `store` (id/name/address), `tags`, `images`, a canonical `partle_url`, and `relevance_score` (cosine similarity 0–1 between the query and the product's embedding when a query was provided; `None` otherwise). **Always share `partle_url` with the user so they can view the listing.** Caveat on `relevance_score`: it is monotonic *within a single search result set* (useful for spotting a big drop-off between rank 3 and rank 4), but its absolute value is not well-calibrated across queries — most results land in 0.55–0.80 regardless of whether the catalog has truly relevant items. Don't infer "this is a great match" from a 0.75 score alone.
    Connector
  • Calculate hyperfocal distance and near/far sharp limits for a lens and aperture. See list_bundles for related 'photographie' calculators.
    Connector