{"name":"ai-netcafe","title":"AI NetCafé","version":"1.5.0","logo":"https://ainetcafe.com/assets/logo-512.png","description":"Open-source AI applications hosted ready to run, plus multi-model LLM access with real per-call cost metering.","protocolVersion":"2025-06-18","supportedVersions":["2026-07-28","2025-06-18","2025-03-26"],"transport":{"type":"streamable-http","url":"https://ainetcafe.com/mcp"},"authentication":{"type":"bearer","optional":true,"note":"Anonymous access has a free quota. One AllRouter key (\"Authorization: Bearer sk-...\") unlocks all 48 tools at direct token rates, no markup."},"tools":[{"name":"what_can_you_do","title":"Find the right tool for a task","description":"Describe a task in plain language (any language) and get back exactly which tools on this server do it, with ready-to-run example calls — instead of reading the whole catalogue and guessing. Also returns multi-step recipes when a task needs several tools chained (invoices to a ledger, a bank statement reconciled, a messy CSV turned into a deliverable). Deterministic and free: it calls no model, costs nothing, and never runs out of quota. Call this FIRST when you are not sure what this server offers.","inputSchema":{"type":"object","required":["task"],"properties":{"task":{"type":"string","description":"What you are trying to do, e.g. \"reconcile a bank statement against my books\" or \"把一堆发票整理成能入账的表格\""}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"list_apps","title":"List hosted open-source AI applications","description":"List the open-source AI applications hosted and ready to run at AI NetCafé (ainetcafe.com). Each one normally requires local setup (Docker/Python + your own model API key); here they run pre-configured. Use this to find a tool for a task like translating a PDF with formulas intact, generating a PowerPoint file, polishing an academic paper, or running an autonomous research report. Do not call this first when the request already clearly matches compare_models, translate_pdf, deep_research, or make_slides; call that task tool directly. Example — GET https://ainetcafe.com/t/list_apps","inputSchema":{"type":"object","properties":{"category":{"type":"string","description":"Optional filter, e.g. \"office\", \"research\", \"chat\"."}}},"outputSchema":{"type":"object","properties":{"apps":{"type":"array","items":{"type":"object"}},"try_in_browser":{"type":"string"}},"required":["apps"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"get_app","title":"Get details of one application","description":"Full details of one hosted application: what it does, how to use it, measured benchmark scores, source repository, and the URL a human can open to run it. Example — GET https://ainetcafe.com/t/get_app?slug=<slug-from-list_apps>","inputSchema":{"type":"object","properties":{"slug":{"type":"string","description":"Application slug, from list_apps."}},"required":["slug"]},"outputSchema":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"open_url":{"type":"string"}},"required":["slug","name"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ask_model","title":"Run a prompt on a specific LLM","description":"Send a prompt to one specific large language model and get the answer plus its exact cost in USD. Useful when you want a second opinion from a different model, or a cheaper model for a bulk subtask. Example — GET https://ainetcafe.com/t/ask_model?prompt=Say+hi&model=deepseek-v4-flash","inputSchema":{"type":"object","properties":{"prompt":{"type":"string","description":"The prompt to send."},"model":{"type":"string","description":"Model id. Call list_models for available ids. Defaults to a cheap capable model."},"system":{"type":"string","description":"Optional system instruction."},"max_tokens":{"type":"integer","description":"Optional output cap."}},"required":["prompt"]},"outputSchema":{"type":"object","properties":{"model":{"type":"string"},"answer":{"type":"string"},"cost_usd":{"type":"number"},"latency_ms":{"type":"number"}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"compare_models","title":"Run the same prompt on several models and compare","description":"Run one prompt across multiple LLMs in parallel and return every answer side by side with its real measured cost and latency. This answers \"which model should I actually use for this kind of task?\" with data instead of guesswork — useful before committing a long job to an expensive model. Example — GET https://ainetcafe.com/t/compare_models?prompt=Explain+CAP+theorem+in+1+line","inputSchema":{"type":"object","properties":{"prompt":{"type":"string","description":"The prompt to send to every model."},"models":{"type":"array","items":{"type":"string"},"description":"Model ids to compare (2-5). Defaults to a cheap/mid/strong spread."},"system":{"type":"string","description":"Optional system instruction applied to all."}},"required":["prompt"]},"outputSchema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object"}},"summary":{"type":["object","null"]}},"required":["results"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"list_models","title":"List available models with prices","description":"List every model callable through AI NetCafé with its input/output price per million tokens, so you can pick by cost as well as capability. Example — GET https://ainetcafe.com/t/list_models","inputSchema":{"type":"object","properties":{"tier":{"type":"string","enum":["free","premium"],"description":"Optional filter. \"free\" models run on the anonymous quota; \"premium\" needs your own AllRouter key."}}},"outputSchema":{"type":"object","properties":{"models":{"type":"array","items":{"type":"object"}}},"required":["models"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"submit_project","title":"Publish an app to AI NetCafé hosting","description":"Submit a GitHub repository (a web app, typically AI-built) to the AI NetCafé hosting platform. The automated pipeline reviews it, containerizes it, deploys it on a dedicated subdomain with HTTPS and a pre-wired multi-LLM gateway, lists it in the store for humans, and exposes it to AI agents. Every use is metered and the author accrues a revenue share. Use this when a user says \"deploy my project\", \"publish my app somewhere\", or \"I built something with AI, where can people use it?\". Free to submit. Example — tools/call submit_project {\"repo\":\"owner/name\"}","inputSchema":{"type":"object","properties":{"repo":{"type":"string","description":"GitHub repository as owner/name (or full github.com URL)."},"contact":{"type":"string","description":"Optional contact (email / X / GitHub handle) for listing and revenue notifications."},"note":{"type":"string","description":"Optional one-liner: who is it for, what does it solve."}},"required":["repo"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"project_status","title":"Check a submitted or hosted project","description":"Check where a repository stands on AI NetCafé: live (with its public page and app URL), in the deployment pipeline, rejected (with the reason), or unknown. Use after submit_project. Example — GET https://ainetcafe.com/t/project_status?repo=<owner/name>","inputSchema":{"type":"object","properties":{"repo":{"type":"string","description":"GitHub repository owner/name, full URL, or the listed slug."}},"required":["repo"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"remember","title":"Store a memory (persists across sessions; with a key, across machines & agents)","description":"Persist a durable memory: an architecture decision, a stable user preference, a verified bug fix, or an important discovery. Anonymous callers get a small per-network memory pool; callers sending an AllRouter key (Authorization: Bearer sk-...) get a large pool shared across ALL their machines and agents — the same key on a laptop's Claude Code and a desktop's Codex recalls the same memories. Do not store secrets or raw logs. Example — tools/call remember {\"content\":\"Deploy key rotates monthly\"}","inputSchema":{"type":"object","properties":{"content":{"type":"string","description":"The memory itself, self-contained (≤2000 chars)."},"kind":{"type":"string","enum":["decision","preference","bugfix","discovery","note"],"description":"Category; default \"note\"."},"project":{"type":"string","description":"Optional project name to scope recall later."}},"required":["content"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"recall","title":"Recall stored memories","description":"Retrieve previously stored memories, optionally filtered by search query and/or project. Call at the start of work on a known project to restore context: why decisions were made, known fixes, preferences. Example — GET https://ainetcafe.com/t/recall?query=<what+to+remember>  (needs a workspace/key for durable memory)","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"Optional search terms; omit to list the most recent."},"project":{"type":"string","description":"Optional project filter."},"limit":{"type":"integer","description":"Max results (default 8, up to 20)."}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"forget","title":"Delete a stored memory by id","description":"Permanently delete one memory you own (id from recall). Use when a memory is wrong or sensitive. Example — tools/call forget {\"id\":\"<memory-id>\"}","inputSchema":{"type":"object","properties":{"id":{"description":"Memory id from recall (integer for keyword engine, uuid string for semantic engine)."}},"required":["id"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false}},{"name":"web_search","title":"Search the web (meta-search)","description":"Search the live web through a self-hosted SearXNG meta-search (aggregates dozens of engines, no tracking). Returns titles, URLs and snippets. Use when you need current information or sources. Example — GET https://ainetcafe.com/t/web_search?query=latest+MCP+spec","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"The search query."},"max_results":{"type":"integer","description":"Max results (default 8, up to 20)."}},"required":["query"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"fetch_page","title":"Fetch a web page as clean Markdown","description":"Fetch any public URL and return LLM-ready clean Markdown (rendered via Crawl4AI, handles JS pages). Use after web_search to read a source, or to ingest any page for analysis. Example — GET https://ainetcafe.com/t/fetch_page?url=https://example.com","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"The page URL to fetch."}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"translate_text","title":"Translate text (offline engine)","description":"Translate text between languages using a self-hosted LibreTranslate engine (fully offline, no big-tech API). For whole PDFs with layout preserved, use translate_pdf instead. Example — GET https://ainetcafe.com/t/translate_text?text=hello+world&to=zh","inputSchema":{"type":"object","properties":{"text":{"type":"string","description":"Text to translate (≤5000 chars)."},"target":{"type":"string","description":"Target language code, e.g. \"zh\", \"en\", \"ja\"."},"source":{"type":"string","description":"Source language code; default \"auto\"."}},"required":["text","target"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"model_costs","title":"Measured per-call cost across models","description":"What one call actually costs on each model, measured. Vendors publish per-million-token list prices, but a call's cost depends on how many tokens the model chooses to emit — models differ by an order of magnitude on the same prompt. standard_bench sends an IDENTICAL prompt to every model, so the difference is the model, not the workload — use that to choose a model before bulk work. production_mixed is real traffic and is NOT comparable across models. Free to cite, CC BY 4.0. Example — GET https://ainetcafe.com/t/model_costs","inputSchema":{"type":"object","properties":{"days":{"type":"integer","description":"Measurement window in days (default 30)."}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"translate_srt","title":"Translate subtitles, timeline untouched","description":"Translate an .srt subtitle file into another language while keeping every timestamp and cue number byte-identical. Cues are anchored by index and refilled in code, so the timeline cannot drift — the usual failure mode when you hand a whole .srt to a model.","inputSchema":{"type":"object","properties":{"srt":{"type":"string","description":"The .srt file content."},"url":{"type":"string","description":"Or a link to the .srt file."},"to":{"type":"string","description":"Target language, e.g. \"English\", \"日本語\"."}},"required":[]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"translate_i18n_json","title":"Translate an i18n locale file","description":"Translate an i18n JSON locale file, keeping the key structure identical and placeholders ({name}, {{count}}, %s, HTML tags) intact. Pass existing_json to translate only the keys that are missing from it — the incremental sync people usually hand-roll a script for.","inputSchema":{"type":"object","properties":{"json":{"type":"string","description":"Source locale file content (JSON)."},"url":{"type":"string","description":"Or a link to the source JSON."},"to":{"type":"string","description":"Target language."},"existing_json":{"type":"string","description":"Existing target locale; only missing keys get translated."}},"required":[]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"redact_text","title":"Redact secrets and PII before sending text on","description":"Strip emails, phone numbers, ID numbers, API keys, private keys, JWTs, card numbers and IPs out of text, returning the redacted text plus a mapping table to restore them afterwards. Rule-based only — no model sees the input. The same value always maps to the same placeholder, so the answer can be restored.","inputSchema":{"type":"object","properties":{"text":{"type":"string","description":"The text to redact."},"only":{"type":"string","description":"Optional comma-separated subset, e.g. \"EMAIL,API_KEY,PRIVATE_KEY\"."}},"required":["text"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"ai_visibility","title":"Can AI assistants read and cite this site?","description":"Audit a URL for AI visibility: which AI crawlers robots.txt actually allows (parsed per user-agent group, not keyword-matched), whether llms.txt / sitemap / JSON-LD / canonical exist, and how much real text an agent gets without running JavaScript. Returns a score plus the specific fixes, ordered by impact.","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Page to audit, e.g. https://example.com"}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"csv_to_qbo","title":"Transaction CSV → QuickBooks .qbo bank feed file","description":"Convert a transaction CSV into a .qbo / OFX bank-feed file that QuickBooks and similar accounting software import directly. Needs date, description and amount columns (or debit + credit). Pairs with extract_statement: statement PDF in, importable bank feed out.","inputSchema":{"type":"object","properties":{"csv":{"type":"string","description":"CSV content with a header row."},"url":{"type":"string","description":"Or a link to the CSV."},"account_id":{"type":"string","description":"Your account number as the accounting software expects it."},"bank_id":{"type":"string","description":"Routing / bank identifier, if your import asks for one."},"currency":{"type":"string","description":"Three-letter currency code, default USD."}},"required":[]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"check_resume","title":"Can an ATS parse this resume?","description":"Check a resume (PDF or .docx) the way an applicant tracking system reads it: is the text extractable, are email/phone/sections findable, do multi-column layouts, tables or emoji break parsing. Returns a score plus concrete fixes ordered by impact — like the W3C validator, but for resumes.","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Public URL of the resume (PDF or .docx)."}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"pdf_to_markdown","title":"PDF or scanned page → structured Markdown","description":"Convert a PDF (or a scanned page image) into clean Markdown that keeps headings, lists and tables, and puts multi-column pages in the right reading order. Text-layer PDFs are read exactly and cost far less; images go through a vision model.","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Public URL of the PDF, or of a page image (png/jpg) for scanned documents."}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"extract_tables","title":"PDF tables → structured rows (with schema alignment)","description":"Extract tables from a PDF into structured rows (JSON + CSV). Pass fields to force a fixed set of columns — that aligns a pile of documents that each name their headers differently into one consistent table. Rows the model was unsure about are flagged rather than guessed. Text-layer PDFs only.","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Public URL of the PDF."},"fields":{"type":"string","description":"Optional comma-separated target columns, e.g. \"invoice_no,supplier,date,amount\". Omit to infer from the header."}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"extract_statement","title":"Bank statement PDF → transactions + reconciliation check","description":"Turn a bank statement or transaction PDF into a clean transaction table (JSON + CSV), then cross-check it: opening + credits - debits must equal the stated closing balance. If it does not balance you get the exact difference and which row the running balance first breaks at — so you know whether the table is safe to use for accounting. Text-layer PDFs only (scanned images not yet supported).","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Public URL of the statement PDF."}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"json_yaml","title":"JSON ↔ YAML, either direction, auto-detected","description":"Converts JSON to YAML or YAML to JSON. It works out which one you gave it, so you do not have to say. A parse failure comes back with the parser message instead of silently producing something that looks fine and is not. Use when a config, a CI file, or a Kubernetes manifest needs to be in the other format.","inputSchema":{"type":"object","properties":{"text":{"type":"string","description":"The JSON or YAML content."},"to":{"type":"string","description":"Optional: \"json\" or \"yaml\" to force the direction."}},"required":["text"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"validate_json","title":"Is this JSON valid — and does it have the keys you need?","description":"Checks that text parses as JSON, and optionally that required keys are present with the right top-level types. Returns the specific violations, not just true/false. Checks required + types only — not full JSON Schema, and it says so rather than pretending. Use before feeding generated JSON into something that will fail on it.","inputSchema":{"type":"object","properties":{"text":{"type":"string","description":"The JSON to validate."},"schema":{"type":"string","description":"Optional JSON Schema (as JSON text) — required[] and properties[].type are checked."}},"required":["text"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"diff_text","title":"What changed between two texts, line by line","description":"Returns which lines were added and which were removed, with line numbers — computed with a longest-common-subsequence, not guessed by a model. Use to compare two versions of a config, a document, or any command output, instead of asking an LLM to eyeball two blobs and hoping it notices.","inputSchema":{"type":"object","properties":{"a":{"type":"string","description":"The first (before) text."},"b":{"type":"string","description":"The second (after) text."}},"required":["a","b"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"jwt_decode","title":"See inside a JWT — header, payload, and whether it has expired","description":"Decodes the header and payload of a JWT and reports issued-at / expiry as readable timestamps plus seconds remaining. The signature is NOT verified and the response says so — decoding is fine for debugging a token you already hold, but never treat these values as proof of anything; verification needs the secret and belongs in your own service.","inputSchema":{"type":"object","properties":{"token":{"type":"string","description":"The JWT string."}},"required":["token"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"regex_test","title":"Does this regex match — and what does it capture?","description":"Runs a regular expression against sample text and returns every match with its position and capture groups (named groups included). Use before wiring a pattern into code, instead of guessing whether the escaping survived the trip through JSON and the shell.","inputSchema":{"type":"object","properties":{"pattern":{"type":"string","description":"The regular expression, without surrounding slashes."},"text":{"type":"string","description":"The text to test against."},"flags":{"type":"string","description":"Optional flags, e.g. \"gi\". Default \"g\"."}},"required":["pattern","text"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"diff_tables","title":"Two tables → what differs (the VLOOKUP job, no amounts needed)","description":"Matches rows across two CSVs on a key column and reports three things: keys only in A, keys only in B, and keys in both whose other columns disagree — naming the exact column and both values. Unlike reconcile_ledger this needs no amount column, so it also fits name lists, inventory counts, permission tables, and any \"these two exports should match\" check.","inputSchema":{"type":"object","properties":{"url_a":{"type":"string","description":"Link to the first CSV."},"url_b":{"type":"string","description":"Link to the second CSV."},"text_a":{"type":"string","description":"Or the first CSV content directly."},"text_b":{"type":"string","description":"Or the second CSV content directly."},"key":{"type":"string","description":"Column that identifies a row, e.g. id."}},"required":["key"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"clean_table","title":"Messy CSV → tidy CSV, with a report of every change","description":"Tidies a spreadsheet export: removes duplicate rows, trims whitespace (half-width and full-width — Chinese exports are full of 　), unifies the half-dozen ways a cell can say \"empty\" (NA / null / - / 无), drops empty rows and columns, and can split one column into several. Returns the cleaned CSV plus exactly what changed: rows in, rows out, duplicates removed, cells trimmed per column. It can also transpose rows/columns and unpivot a wide table into a long one. The row arithmetic is verified in code — if in − removed ≠ out, the response says so instead of handing back a table nobody can check. Use when a CSV came out of Excel or an export and needs cleaning before analysis.","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Link to the CSV. Provide this or text."},"text":{"type":"string","description":"The CSV content itself. Provide this or url."},"ops":{"type":"string","description":"Comma-separated, default \"dedupe,trim,drop_empty,unify_blank\". Also available: split_column, transpose (swap rows/columns), wide_to_long (unpivot a wide table into the long format analysis tools expect)."},"keep":{"type":"string","description":"For wide_to_long: comma-separated id columns to keep as-is. Defaults to the first column."},"split_column":{"type":"string","description":"Column name to split (requires ops to include split_column)."},"split_by":{"type":"string","description":"Separator to split on, default a single space."}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"merge_tables","title":"Several CSVs → one, columns unioned, row counts proven","description":"Combines up to 20 CSVs into a single table. Headers do not have to match: columns are unioned and a file missing a column contributes blanks for it, so rows never shift silently — the failure mode that makes hand-merged spreadsheets untrustworthy. Reports each source file row count and checks in code that they sum to the merged total. Use for monthly exports, per-store sheets, or any set of files with the same subject but drifting headers.","inputSchema":{"type":"object","properties":{"urls":{"type":"string","description":"Comma-separated CSV links, at least two."},"texts":{"type":"array","items":{"type":"string"},"description":"Or pass the CSV contents directly as an array."}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"reconcile_ledger","title":"Two tables → what does not match (the VLOOKUP job), with the arithmetic proof","description":"Reconciles two sets of records — your books against a bank, platform, or supplier statement. Matches rows on a key column, compares an amount column, and returns three lists: only in A, only in B, and same key but different amount. Amounts are compared in integer cents, so 0.1 + 0.2 never invents a phantom difference for someone to chase. The response also proves the result: the listed differences are re-added and must equal the gap between the two totals, checked in code. Use for month-end close, platform payouts vs orders, or any \"these two numbers should agree and do not\" problem. This is the job people do by hand with VLOOKUP or a groupby and then cannot prove they got right.","inputSchema":{"type":"object","properties":{"url_a":{"type":"string","description":"Link to side A (e.g. your books)."},"url_b":{"type":"string","description":"Link to side B (e.g. the statement)."},"text_a":{"type":"string","description":"Or the CSV content of side A directly."},"text_b":{"type":"string","description":"Or the CSV content of side B directly."},"key":{"type":"string","description":"Column name to match rows on, e.g. order_id."},"amount":{"type":"string","description":"Numeric column to compare, e.g. amount."}},"required":["key","amount"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"extract_invoices","title":"A batch of invoices → one ledger-ready table (arithmetic-checked)","description":"Give it up to 20 invoice URLs (PDF or page images) and get back one table ready to post: number, date, seller, buyer, net / tax / gross, currency. Every row is checked in code — net + tax must equal gross — and the batch total is re-added independently, so a row the model misread is flagged with the exact difference instead of quietly landing in your books. Mixed currencies get no batch total on purpose: adding them together would be an accounting error. CSV is UTF-8 with BOM so Excel opens it right.","inputSchema":{"type":"object","properties":{"urls":{"type":"string","description":"Invoice URLs — comma-separated, or pass an array. Up to 20 per call."}},"required":["urls"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"create_pipeline","title":"Freeze a sequence of tool calls into a named production line","description":"Turn the tool calls you just made into a repeatable pipeline that runs on our servers. Each run produces a work order with per-step arithmetic proofs; runs whose checks fail are not billed. Free trial 7 days, then $9/30 days per line. Chain values between steps with \"$prev.<field>\" or \"$steps.N.<field>\". Pipeline-enabled tools: china_reachability, fetch_page, web_search, match_transactions, diff_tables, reconcile_ledger, dedupe_entities, read_xlsx, write_xlsx, clean_table, merge_tables, csv_to_chart, hs_lookup, exchange_rate, render_diagram, make_chart, model_costs. Schedule it with create_task kind=\"pipeline\", input=<pipeline_id>.","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"Human-readable line name, e.g. \"daily bank reconciliation\"."},"steps":{"type":"array","description":"Ordered steps: [{\"tool\":\"...\",\"args\":{...}}]. Max 6. Use \"$prev.field\" to pass values.","items":{"type":"object","properties":{"tool":{"type":"string"},"args":{"type":"object"}},"required":["tool"]}}},"required":["name","steps"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"run_pipeline","title":"Run a production line once, now","description":"Execute one of your pipelines immediately and get the work order (per-step results and proofs). The scheduler calls this same tool — running it yourself is exactly one scheduled run.","inputSchema":{"type":"object","properties":{"id":{"type":"string","description":"pipeline_id from create_pipeline or list_pipelines."}},"required":["id"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"list_pipelines","title":"List your production lines","description":"Pipelines on this workspace: steps, trial/paid status, run counts, work-order pages.","inputSchema":{"type":"object","properties":{},"required":[]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"delete_pipeline","title":"Delete a production line","description":"Remove a pipeline. Its scheduled task (if any) will start failing — delete that too.","inputSchema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"create_task","title":"Schedule a recurring task that runs on our servers","description":"Create a task that runs on a schedule in our cloud — you do not keep anything running. It only notifies you when the result actually changes. Kinds: watch_page (Watch a web page and report when its content changes); daily_answer (Re-run a web-researched question on a schedule and report when the answer changes); watch_reachability (Track whether a site stays reachable from mainland China); pipeline (Run one of your production lines (create_pipeline) on a schedule; every run leaves a proof-carrying work order). Needs a workspace token (?w=ws_... on your MCP URL) so you can manage it later.","inputSchema":{"type":"object","properties":{"kind":{"type":"string","description":"watch_page | daily_answer | watch_reachability | pipeline"},"input":{"type":"string","description":"The URL to watch, or the question to re-research."},"interval_seconds":{"type":"integer","description":"How often to run. Minimum 900 (15 min), default 3600."},"notify_url":{"type":"string","description":"Optional https webhook to POST results to when they change."}},"required":["kind","input"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"list_tasks","title":"List your scheduled tasks","description":"Show the scheduled tasks on this workspace, when each runs next, how many times it has run and what it has cost so far.","inputSchema":{"type":"object","properties":{},"required":[]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"get_task_runs","title":"See what a scheduled task has produced","description":"Recent runs of one scheduled task: what it returned, whether the result changed, and what each run cost.","inputSchema":{"type":"object","properties":{"task_id":{"type":"integer","description":"From create_task or list_tasks."},"limit":{"type":"integer","description":"How many recent runs, max 20, default 5."}},"required":["task_id"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"delete_task","title":"Delete a scheduled task","description":"Stop and remove a scheduled task and its run history.","inputSchema":{"type":"object","properties":{"task_id":{"type":"integer","description":"From list_tasks."}},"required":["task_id"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true,"openWorldHint":false}},{"name":"pdf_add_page_numbers","title":"Add page numbers to a PDF","description":"Stamp page numbers or footer text onto every page of a PDF. Supports a starting number, roman numerals, skipping a cover page, position and font size — the combination Acrobat cannot do without scripting. Template supports {n} and {total}, e.g. \"Page {n} of {total}\".","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Public URL of the PDF."},"style":{"type":"string","description":"arabic (default) | roman (i, ii, iii) | ROMAN (I, II, III)"},"start_at":{"type":"integer","description":"Number to start from (default 1)."},"skip_first":{"type":"integer","description":"Leave this many leading pages unnumbered, e.g. 1 for a cover."},"position":{"type":"string","description":"bottom-center (default) | bottom-left | bottom-right | top-center | top-left | top-right"},"text":{"type":"string","description":"Template, default \"{n}\". Use {n} and {total}."},"font_size":{"type":"integer","description":"Font size, default 10."}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"split_spritesheet","title":"Split a sprite sheet into individual PNGs","description":"Cut a packed sprite sheet / texture atlas into separate transparent PNGs, returned as a zip. Give rows and cols for a uniform grid, or omit them to auto-detect sprites by transparent gaps.","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Public URL of the sprite sheet image."},"rows":{"type":"integer","description":"Grid rows. Omit together with cols to auto-detect."},"cols":{"type":"integer","description":"Grid columns."},"margin":{"type":"integer","description":"Pixels to trim inside each grid cell (for sheets with padding)."}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"fix_csv_encoding","title":"Fix a CSV that opens garbled in Excel","description":"Detect the real encoding of a CSV (GB18030, Shift-JIS, Windows-1252…), repair mojibake (UTF-8 that was read as Latin-1, e.g. \"Ã©\"), and re-emit UTF-8 with a BOM so Excel opens it correctly.","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Public URL of the CSV."},"text":{"type":"string","description":"Or paste the CSV content directly."}},"required":[]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"package_info","title":"Look up a package (npm / PyPI / crates / Go)","description":"Latest version, license, repo, description, dependencies and weekly downloads for any public package. Use it before adding a dependency, or to check whether the version in a lockfile is current.","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"Package name, e.g. \"react\", \"requests\", \"serde\", \"github.com/gin-gonic/gin\"."},"ecosystem":{"type":"string","description":"npm (default) | pypi | crates | go"}},"required":["name"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"check_vulns","title":"Check a package for known vulnerabilities","description":"Query OSV.dev for known CVE/GHSA vulnerabilities affecting a package (optionally a specific version), and get the versions they were fixed in. Use it when reviewing dependencies or a lockfile. Covers npm, PyPI, crates.io, Go, Maven, NuGet and Packagist.","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"Package name."},"version":{"type":"string","description":"Exact version to check, e.g. \"4.17.15\". Omit to list all known vulns for the package."},"ecosystem":{"type":"string","description":"npm (default) | pypi | crates | go | maven | nuget | packagist"}},"required":["name"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"transpile_sql","title":"Translate SQL between dialects","description":"Convert a SQL statement from one dialect to another — mysql, postgres, sqlite, tsql, oracle, snowflake, bigquery, redshift, spark, hive, presto, trino, duckdb, clickhouse, databricks, doris, starrocks and more. Deterministic parser (sqlglot), not an LLM: the same input always produces the same output, and syntax errors come back with the exact line and column. Use it when migrating queries between databases or debugging dialect-specific syntax.","inputSchema":{"type":"object","properties":{"sql":{"type":"string","description":"The SQL statement (or several, separated by semicolons)."},"read":{"type":"string","description":"Source dialect, e.g. \"mysql\". Omit to auto-detect from generic SQL."},"write":{"type":"string","description":"Target dialect, e.g. \"postgres\", \"bigquery\", \"doris\"."}},"required":["sql","write"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"make_qr","title":"Make a QR code","description":"Any text or URL → a QR code PNG you can embed or download. Stateless URL form: https://ainetcafe.com/i/qr/<text>","inputSchema":{"type":"object","properties":{"text":{"type":"string","description":"The text or URL to encode."}},"required":["text"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"get_weather","title":"Get current weather","description":"Current weather and short forecast for a city or coordinates. Works for Chinese cities too.","inputSchema":{"type":"object","properties":{"city":{"type":"string","description":"City name, e.g. \"Shanghai\" / \"上海\". Or pass lat/lon."},"lat":{"type":"number","description":"Latitude (alternative to city)."},"lon":{"type":"number","description":"Longitude (alternative to city)."}},"required":[]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"china_reachability","title":"Test if a URL is reachable from mainland China","description":"Fetch a URL from a real mainland-China network egress and report HTTP status, latency and China DNS resolution. Answers \"is my site/API usable from China?\" with a measurement instead of a guess — you cannot get this from a VPS abroad.","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Full URL to test, e.g. https://example.com"}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"text_to_image","title":"Generate an image from a text prompt","description":"Text prompt → a generated image, returned as a hosted URL you can embed straight into Markdown, HTML or a chat reply. Use it for illustrations, covers, concept art, social cards and mockups. Returns a job_id; poll check_job for the image url (about 1 minute). Metered per image, no account needed for the free quota.","inputSchema":{"type":"object","properties":{"prompt":{"type":"string","description":"What to draw. Be specific about subject, style and composition."},"aspect":{"type":"string","description":"Aspect ratio: \"1:1\" (default), \"16:9\", \"9:16\", \"4:3\", \"3:4\"."}},"required":["prompt"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"make_badge","title":"Make a README badge (SVG)","description":"Label + message + colour → a shields.io-style badge SVG, plus a ready-to-paste Markdown embed line. Stateless URL form: https://ainetcafe.com/i/badge/<label>-<message>-<color> — embed it and it renders forever.","inputSchema":{"type":"object","properties":{"label":{"type":"string","description":"Left side text, e.g. \"build\"."},"message":{"type":"string","description":"Right side text, e.g. \"passing\"."},"color":{"type":"string","description":"brightgreen | green | blue | red | orange | yellow | grey | purple, or a hex like \"007ec6\"."}},"required":["label","message"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"make_chart","title":"Make a chart image","description":"Labels + values (or a full Chart.js config) → a chart PNG URL. Bar, line, pie, radar, scatter. Stateless URL form for embedding: https://ainetcafe.com/i/chart/<labels>|<values>","inputSchema":{"type":"object","properties":{"labels":{"type":"string","description":"Comma-separated labels, e.g. \"Mon,Tue,Wed\"."},"values":{"type":"string","description":"Comma-separated numbers, e.g. \"3,7,5\"."},"type":{"type":"string","description":"bar (default) | line | pie | doughnut | radar | scatter."},"config":{"type":"string","description":"Optional full Chart.js JSON config; overrides labels/values."}},"required":[]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"render_diagram","title":"Render a diagram from text","description":"Turn diagram-as-code into an image: Mermaid, PlantUML, Graphviz/DOT, C4, Excalidraw and 20+ more (self-hosted Kroki). Returns a hosted SVG/PNG URL you can embed directly in Markdown or HTML. Example — GET \"https://ainetcafe.com/t/render_diagram?source=graph TD;A--%3EB&format=png\"","inputSchema":{"type":"object","properties":{"source":{"type":"string","description":"The diagram source code (e.g. a Mermaid flowchart)."},"type":{"type":"string","description":"Diagram language: mermaid (default), plantuml, graphviz, c4plantuml, excalidraw, blockdiag, erd…"},"format":{"type":"string","description":"\"svg\" (default) or \"png\"."}},"required":["source"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"check_grammar","title":"Check grammar and style","description":"Check text for grammar, spelling and style issues in 30+ languages (self-hosted LanguageTool). Returns each issue with a suggested replacement — apply them to produce corrected text. Example — GET https://ainetcafe.com/t/check_grammar?text=Their+going+to+the+park","inputSchema":{"type":"object","properties":{"text":{"type":"string","description":"The text to check (≤10000 chars)."},"language":{"type":"string","description":"Language code like \"en-US\", \"zh-CN\"; default \"auto\"."}},"required":["text"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"transcribe_audio","title":"Transcribe audio to text","description":"Fetch an audio file from a URL and transcribe it to text with open-source Whisper (100 languages, self-hosted). Good for voice memos, podcast clips and meeting recordings up to ~15 MB. Example — GET https://ainetcafe.com/t/transcribe_audio?url=<public-audio-url>","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Public URL of the audio file (mp3/wav/m4a/ogg, ≤15 MB)."},"language":{"type":"string","description":"Hint language code like \"zh\", \"en\"; default auto-detect."}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"convert_to_pdf","title":"Convert a web page or HTML to PDF","description":"Print-quality PDF from a URL or raw HTML via self-hosted Gotenberg (headless Chromium). Returns a hosted PDF download URL. Example — GET https://ainetcafe.com/t/convert_to_pdf?url=https://example.com","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Page URL to convert (either url or html is required)."},"html":{"type":"string","description":"Raw HTML to convert (alternative to url)."}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"deep_research","title":"Run an autonomous research agent","description":"Start an autonomous web research task. The agent plans sub-questions, searches the web, reads the sources and writes a report with citations — this is real research, not a single model call, and takes 2-5 minutes. Returns a job_id immediately; poll check_job to get the report. Use this when you need sourced, current information rather than what a model already knows. Powered by gpt-researcher (29k stars) hosted at AI NetCafé. Example — tools/call deep_research {\"topic\":\"State of MCP adoption in 2026?\"} → poll check_job","inputSchema":{"type":"object","properties":{"topic":{"type":"string","description":"The research question. Phrase it as a question, not a keyword."},"depth":{"type":"string","enum":["quick","standard"],"description":"quick = outline only (~1 min); standard = full cited report (~3 min). Default standard."}},"required":["topic"]},"outputSchema":{"type":"object","properties":{"job_id":{"type":"string"},"status":{"type":"string"},"poll_interval_seconds":{"type":"integer"}},"required":["job_id","status"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"check_job","title":"Check a long-running job","description":"Get the status or result of a job started by deep_research, translate_pdf, or make_slides. Poll every 15-30 seconds until status is \"done\" or \"error\". While work is pending, follow retry_after_seconds and next_action; when complete, prefer structured_result when present. Example — GET https://ainetcafe.com/t/check_job?job_id=<id-from-a-job-tool>","inputSchema":{"type":"object","properties":{"job_id":{"type":"string","description":"The job_id returned when the task was started."}},"required":["job_id"]},"outputSchema":{"type":"object","properties":{"job_id":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string"},"is_terminal":{"type":"boolean"},"retry_after_seconds":{"type":"integer"},"next_action":{"type":["object","null"]},"result":{},"structured_result":{},"error":{"type":"string"}},"required":["job_id","status"]},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"translate_pdf","title":"Translate a PDF keeping its layout","description":"Translate a PDF from a URL while preserving the original layout — formulas, figures and two-column academic typesetting stay intact, unlike ordinary translators that flatten the document. Returns a job_id; poll check_job for the download links (translated-only and bilingual side-by-side). Typically 20-60 seconds for a few pages. Powered by PDFMathTranslate (36k stars) hosted at AI NetCafé. Example — tools/call translate_pdf {\"url\":\"<pdf-url>\",\"target\":\"zh\"} → poll check_job","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"Direct URL to the PDF (e.g. an arXiv PDF link)."},"lang_to":{"type":"string","description":"Target language, e.g. \"Simplified Chinese\", \"Japanese\". Default Simplified Chinese."},"pages":{"type":"string","enum":["first","first5","all"],"description":"How much to translate. first = 1 page, first5 = first 5 pages (default), all = whole document (slow and expensive)."}},"required":["url"]},"outputSchema":{"type":"object","properties":{"job_id":{"type":"string"},"status":{"type":"string"},"poll_interval_seconds":{"type":"integer"}},"required":["job_id","status"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"make_slides","title":"Generate a PowerPoint deck","description":"Turn a topic or an outline into a real downloadable .pptx file — not a link into someone's web editor. Returns a job_id; poll check_job for the download URL. Usually 1-3 minutes. Powered by Presenton (open source) hosted at AI NetCafé. Example — tools/call make_slides {\"topic\":\"Q3 review\",\"slides\":8} → poll check_job","inputSchema":{"type":"object","properties":{"topic":{"type":"string","description":"The topic, or a full outline to follow."},"slides":{"type":"integer","description":"Number of slides (default 8)."},"language":{"type":"string","description":"Output language, e.g. \"Chinese\", \"English\". Default Chinese."},"instructions":{"type":"string","description":"Optional extra guidance on style or emphasis."}},"required":["topic"]},"outputSchema":{"type":"object","properties":{"job_id":{"type":"string"},"status":{"type":"string"},"poll_interval_seconds":{"type":"integer"}},"required":["job_id","status"]},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}},{"name":"build_app","title":"Build and deploy a web app from a description","description":"Turn one plain-language description into a LIVE single-page web tool: code is generated, deployed to managed hosting with HTTPS, and listed — you get the public URL in ~1-2 minutes. Best for tool-style apps: calculators, converters, checklists, timers, generators, small games. Async — poll with check_job. Example — tools/call build_app {\"description\":\"a tip calculator web app\"} → poll check_job","inputSchema":{"type":"object","properties":{"description":{"type":"string","description":"What the tool should do, in any language. Be specific about inputs/outputs."},"name":{"type":"string","description":"Optional short app name (defaults to the description)."},"visibility":{"type":"string","description":"\"public\" (default, listed in the store) or \"unlisted\" (URL-only, not in the store)."},"refine":{"type":"string","description":"Slug of an app you built earlier (e.g. \"u-1a23e679\") to modify instead of building from scratch — describe only the change in `description`."}},"required":["description"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false}}],"workflows":[{"slug":"publish-an-app-to-managed-hosting","title":"Publish an app to managed hosting with one tool call","use_when":"The user built an app (often AI-built) and wants it deployed, listed, callable by agents, and earning a revenue share — without doing ops.","tool":"submit_project","arguments_example":{"repo":"you/your-app","contact":"you@example.com","note":"What it does, for whom."},"result":"Pipeline starts immediately: review, source build, deploy on a dedicated subdomain, dual listing. Poll project_status for live/rejected.","follow_up_tool":"project_status","guide":"https://ainetcafe.com/agent-guides/publish-an-app-to-managed-hosting"},{"slug":"compare-llm-cost-for-a-prompt","title":"Compare LLM cost and latency on one real prompt","use_when":"The user needs evidence for which model can complete a specific task at the lowest real cost.","tool":"compare_models","arguments_example":{"prompt":"Return valid JSON with keys title, summary, and risks for this product brief."},"result":"Answers from 2-5 models with actually metered USD cost, latency, cheapest model, and fastest model.","guide":"https://ainetcafe.com/agent-guides/compare-llm-cost-for-a-prompt"},{"slug":"translate-arxiv-pdf-without-breaking-equations","title":"Translate an arXiv PDF without breaking equations or layout","use_when":"The user supplies a public PDF URL and needs formulas, figures, and columns preserved.","tool":"translate_pdf","arguments_example":{"url":"https://arxiv.org/pdf/1706.03762","lang_to":"Simplified Chinese","pages":"first5"},"result":"A job_id, followed by translated-only and bilingual PDF download URLs from check_job.","follow_up_tool":"check_job","guide":"https://ainetcafe.com/agent-guides/translate-arxiv-pdf-without-breaking-equations"},{"slug":"best-model-for-gpt-researcher","title":"Run cited web research and inspect the model benchmark","use_when":"The question is current, requires multiple web sources, and needs citations rather than model memory.","tool":"deep_research","arguments_example":{"topic":"How has remote MCP adoption changed in 2026?","depth":"standard"},"result":"A job_id, followed by a cited Markdown report from check_job.","follow_up_tool":"check_job","guide":"https://ainetcafe.com/agent-guides/best-model-for-gpt-researcher"},{"slug":"generate-downloadable-pptx-with-mcp","title":"Generate a real downloadable PowerPoint file","use_when":"The user wants an editable .pptx from a topic or outline, not a web-editor preview.","tool":"make_slides","arguments_example":{"topic":"How AI agents choose tools","slides":8,"language":"English"},"result":"A job_id, followed by a downloadable .pptx URL from check_job.","follow_up_tool":"check_job","guide":"https://ainetcafe.com/agent-guides/generate-downloadable-pptx-with-mcp"},{"slug":"render-diagram-from-text","title":"Render Mermaid/PlantUML code into an embeddable image","use_when":"The reply needs an actual diagram image, not a code block the user must paste elsewhere.","tool":"render_diagram","arguments_example":{"source":"graph TD; A-->B","type":"mermaid","format":"svg"},"result":"A hosted SVG/PNG URL, content-addressed and permanently cacheable, ready for Markdown embedding.","guide":"https://ainetcafe.com/agent-guides/render-diagram-from-text"},{"slug":"transcribe-audio-url-via-mcp","title":"Transcribe an audio URL to text with self-hosted Whisper","use_when":"The user supplies an audio file URL (voice memo, podcast clip, recording) and needs the words.","tool":"transcribe_audio","arguments_example":{"url":"https://example.com/memo.mp3"},"result":"Plain-text transcript plus detected language; audio never leaves the self-hosted stack.","guide":"https://ainetcafe.com/agent-guides/transcribe-audio-url-via-mcp"}],"capabilities":"https://ainetcafe.com/agent-capabilities.json","documentation":"https://ainetcafe.com/mcp.html"}