{
  "data": {
    "tool": {
      "category": "accounting",
      "endpoint": "https://ainetcafe.com/mcp?s=registry",
      "jsonUrl": "https://www.anchorterminal.com/api/v1/tools/ainetcafe-ai-netcafe.json",
      "kind": "mcp",
      "listed": "indexed",
      "liveUrl": "https://www.anchorterminal.com/api/v1/live/ainetcafe-ai-netcafe.json",
      "markdownUrl": "https://www.anchorterminal.com/tools/ainetcafe-ai-netcafe.md",
      "mcpTools": {
        "check": {
          "checker": "anchor-check/1.0",
          "totalTokens": 7810,
          "counts": {
            "error": 0,
            "note": 0,
            "warn": 2
          },
          "findings": [
            {
              "rule": "TC14",
              "severity": "warn",
              "tool": "create_task",
              "message": "allowed values are in the description, not an enum: kind",
              "fix": "Move them into enum."
            },
            {
              "rule": "TC18",
              "severity": "warn",
              "tool": "merge_tables",
              "message": "readOnlyHint is true but the name says \"merge\"",
              "fix": "If it changes anything, readOnlyHint must be false."
            }
          ]
        },
        "checkedAt": "2026-10-04T22:22:03Z",
        "count": 34,
        "note": "answered without the initialize handshake",
        "schemaTokens": 7810,
        "status": "ok",
        "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": {
              "properties": {
                "task": {
                  "description": "What you are trying to do, e.g. \"reconcile a bank statement against my books\" or \"把一堆发票整理成能入账的表格\"",
                  "type": "string"
                }
              },
              "required": [
                "task"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "category": {
                  "description": "Optional filter, e.g. \"office\", \"research\", \"chat\".",
                  "type": "string"
                }
              },
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "apps": {
                  "items": {
                    "type": "object"
                  },
                  "type": "array"
                },
                "try_in_browser": {
                  "type": "string"
                }
              },
              "required": [
                "apps"
              ],
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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=\u003cslug-from-list_apps\u003e",
            "inputSchema": {
              "properties": {
                "slug": {
                  "description": "Application slug, from list_apps.",
                  "type": "string"
                }
              },
              "required": [
                "slug"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "name": {
                  "type": "string"
                },
                "open_url": {
                  "type": "string"
                },
                "slug": {
                  "type": "string"
                }
              },
              "required": [
                "slug",
                "name"
              ],
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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 measured platform cost metadata. The beta platform covers the user charge ($0.00); capacity limits still apply. Example — GET https://ainetcafe.com/t/ask_model?prompt=Say+hi\u0026model=deepseek-v4-flash",
            "inputSchema": {
              "properties": {
                "max_tokens": {
                  "description": "Optional output cap.",
                  "type": "integer"
                },
                "model": {
                  "description": "Model id. Call list_models for available ids. Defaults to a cheap capable model.",
                  "type": "string"
                },
                "prompt": {
                  "description": "The prompt to send.",
                  "type": "string"
                },
                "system": {
                  "description": "Optional system instruction.",
                  "type": "string"
                }
              },
              "required": [
                "prompt"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "answer": {
                  "type": "string"
                },
                "cost_usd": {
                  "type": "number"
                },
                "latency_ms": {
                  "type": "number"
                },
                "model": {
                  "type": "string"
                }
              },
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": false,
              "openWorldHint": false,
              "readOnlyHint": 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 measured platform cost metadata and latency. The beta platform covers the user charge ($0.00). This answers \"which model should I actually use for this kind of task?\" with data instead of guesswork. Example — GET https://ainetcafe.com/t/compare_models?prompt=Explain+CAP+theorem+in+1+line",
            "inputSchema": {
              "properties": {
                "models": {
                  "description": "Model ids to compare (2-5). Defaults to a cheap/mid/strong spread.",
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "prompt": {
                  "description": "The prompt to send to every model.",
                  "type": "string"
                },
                "system": {
                  "description": "Optional system instruction applied to all.",
                  "type": "string"
                }
              },
              "required": [
                "prompt"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "results": {
                  "items": {
                    "type": "object"
                  },
                  "type": "array"
                },
                "summary": {
                  "type": [
                    "object",
                    "null"
                  ]
                }
              },
              "required": [
                "results"
              ],
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": false,
              "openWorldHint": false,
              "readOnlyHint": false
            }
          },
          {
            "name": "list_models",
            "title": "List available models and capacity",
            "description": "List every model currently available in the free beta with reference input/output rates and health metadata. Those rates are platform cost metadata only; every user charge is $0.00 during the beta. Example — GET https://ainetcafe.com/t/list_models",
            "inputSchema": {
              "properties": {
                "tier": {
                  "description": "Optional reference tier filter. All currently healthy tiers are available without a user key during the beta.",
                  "enum": [
                    "free",
                    "premium"
                  ],
                  "type": "string"
                }
              },
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "models": {
                  "items": {
                    "type": "object"
                  },
                  "type": "array"
                }
              },
              "required": [
                "models"
              ],
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "name": "remember",
            "title": "Store a memory (persists across sessions within your workspace)",
            "description": "Persist a durable memory: an architecture decision, a stable user preference, a verified bug fix, or an important discovery. The free beta provides a bounded per-caller/workspace memory pool; no personal API key is required. Do not store secrets or raw logs. Example — tools/call remember {\"content\":\"Deploy key rotates monthly\"}",
            "inputSchema": {
              "properties": {
                "content": {
                  "description": "The memory itself, self-contained (≤2000 chars).",
                  "type": "string"
                },
                "kind": {
                  "description": "Category; default \"note\".",
                  "enum": [
                    "decision",
                    "preference",
                    "bugfix",
                    "discovery",
                    "note"
                  ],
                  "type": "string"
                },
                "project": {
                  "description": "Optional project name to scope recall later.",
                  "type": "string"
                }
              },
              "required": [
                "content"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": false,
              "openWorldHint": false,
              "readOnlyHint": 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=\u003cwhat+to+remember\u003e  (needs a workspace/key for durable memory)",
            "inputSchema": {
              "properties": {
                "limit": {
                  "description": "Max results (default 8, up to 20).",
                  "type": "integer"
                },
                "project": {
                  "description": "Optional project filter.",
                  "type": "string"
                },
                "query": {
                  "description": "Optional search terms; omit to list the most recent.",
                  "type": "string"
                }
              },
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "max_results": {
                  "description": "Max results (default 8, up to 20).",
                  "type": "integer"
                },
                "query": {
                  "description": "The search query.",
                  "type": "string"
                }
              },
              "required": [
                "query"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "name": "fetch_page",
            "title": "Fetch a web page as clean Markdown",
            "description": "Fetch a public URL and return clean LLM-ready Markdown from the server-rendered response. This tool does not execute browser JavaScript; for SPA or empty-text pages, use web_search, a browser, or the site's API. Use it after web_search to read a reachable public source, or to ingest a static page for analysis. Example — GET https://ainetcafe.com/t/fetch_page?url=https://example.com",
            "inputSchema": {
              "properties": {
                "url": {
                  "description": "The page URL to fetch.",
                  "type": "string"
                }
              },
              "required": [
                "url"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "name": "model_costs",
            "title": "Measured platform cost across models",
            "description": "Measured platform cost metadata for one call on each model; your charge is $0.00 during the free beta. 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": {
              "properties": {
                "days": {
                  "description": "Measurement window in days (default 30).",
                  "type": "integer"
                }
              },
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "url": {
                  "description": "Page to audit, e.g. https://example.com",
                  "type": "string"
                }
              },
              "required": [
                "url"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "url": {
                  "description": "Public URL of the PDF, or of a page image (png/jpg) for scanned documents.",
                  "type": "string"
                }
              },
              "required": [
                "url"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "fields": {
                  "description": "Optional comma-separated target columns, e.g. \"invoice_no,supplier,date,amount\". Omit to infer from the header.",
                  "type": "string"
                },
                "url": {
                  "description": "Public URL of the PDF.",
                  "type": "string"
                }
              },
              "required": [
                "url"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "url": {
                  "description": "Public URL of the statement PDF.",
                  "type": "string"
                }
              },
              "required": [
                "url"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "text": {
                  "description": "The JSON or YAML content.",
                  "type": "string"
                },
                "to": {
                  "description": "Optional: \"json\" or \"yaml\" to force the direction.",
                  "type": "string"
                }
              },
              "required": [
                "text"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "schema": {
                  "description": "Optional JSON Schema (as JSON text) — required[] and properties[].type are checked.",
                  "type": "string"
                },
                "text": {
                  "description": "The JSON to validate.",
                  "type": "string"
                }
              },
              "required": [
                "text"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "a": {
                  "description": "The first (before) text.",
                  "type": "string"
                },
                "b": {
                  "description": "The second (after) text.",
                  "type": "string"
                }
              },
              "required": [
                "a",
                "b"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "token": {
                  "description": "The JWT string.",
                  "type": "string"
                }
              },
              "required": [
                "token"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "flags": {
                  "description": "Optional flags, e.g. \"gi\". Default \"g\".",
                  "type": "string"
                },
                "pattern": {
                  "description": "The regular expression, without surrounding slashes.",
                  "type": "string"
                },
                "text": {
                  "description": "The text to test against.",
                  "type": "string"
                }
              },
              "required": [
                "pattern",
                "text"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "key": {
                  "description": "Column that identifies a row, e.g. id.",
                  "type": "string"
                },
                "text_a": {
                  "description": "Or the first CSV content directly.",
                  "type": "string"
                },
                "text_b": {
                  "description": "Or the second CSV content directly.",
                  "type": "string"
                },
                "url_a": {
                  "description": "Link to the first CSV.",
                  "type": "string"
                },
                "url_b": {
                  "description": "Link to the second CSV.",
                  "type": "string"
                }
              },
              "required": [
                "key"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "keep": {
                  "description": "For wide_to_long: comma-separated id columns to keep as-is. Defaults to the first column.",
                  "type": "string"
                },
                "ops": {
                  "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).",
                  "type": "string"
                },
                "split_by": {
                  "description": "Separator to split on, default a single space.",
                  "type": "string"
                },
                "split_column": {
                  "description": "Column name to split (requires ops to include split_column).",
                  "type": "string"
                },
                "text": {
                  "description": "The CSV content itself. Provide this or url.",
                  "type": "string"
                },
                "url": {
                  "description": "Link to the CSV. Provide this or text.",
                  "type": "string"
                }
              },
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "texts": {
                  "description": "Or pass the CSV contents directly as an array.",
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "urls": {
                  "description": "Comma-separated CSV links, at least two.",
                  "type": "string"
                }
              },
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "amount": {
                  "description": "Numeric column to compare, e.g. amount.",
                  "type": "string"
                },
                "key": {
                  "description": "Column name to match rows on, e.g. order_id.",
                  "type": "string"
                },
                "text_a": {
                  "description": "Or the CSV content of side A directly.",
                  "type": "string"
                },
                "text_b": {
                  "description": "Or the CSV content of side B directly.",
                  "type": "string"
                },
                "url_a": {
                  "description": "Link to side A (e.g. your books).",
                  "type": "string"
                },
                "url_b": {
                  "description": "Link to side B (e.g. the statement).",
                  "type": "string"
                }
              },
              "required": [
                "key",
                "amount"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "urls": {
                  "description": "Invoice URLs — comma-separated, or pass an array. Up to 20 per call.",
                  "type": "string"
                }
              },
              "required": [
                "urls"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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. Application and model calls are subsidized during the free beta; your charge is $0.00 and capacity limits apply.",
            "inputSchema": {
              "properties": {
                "input": {
                  "description": "The URL to watch, or the question to re-research.",
                  "type": "string"
                },
                "interval_seconds": {
                  "description": "How often to run. Minimum 900 (15 min), default 3600.",
                  "type": "integer"
                },
                "kind": {
                  "description": "watch_page | daily_answer | watch_reachability | pipeline",
                  "type": "string"
                },
                "notify_url": {
                  "description": "Optional https webhook to POST results to when they change.",
                  "type": "string"
                }
              },
              "required": [
                "kind",
                "input"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": false,
              "openWorldHint": false,
              "readOnlyHint": false
            }
          },
          {
            "name": "list_tasks",
            "title": "List your scheduled tasks",
            "description": "Show scheduled tasks, next run times, run counts, and measured platform cost metadata. User charge is $0.00 during the beta.",
            "inputSchema": {
              "properties": {},
              "required": [],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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 measured platform cost metadata. User charge is $0.00.",
            "inputSchema": {
              "properties": {
                "limit": {
                  "description": "How many recent runs, max 20, default 5.",
                  "type": "integer"
                },
                "task_id": {
                  "description": "From create_task or list_tasks.",
                  "type": "integer"
                }
              },
              "required": [
                "task_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "name": "delete_task",
            "title": "Delete a scheduled task",
            "description": "Stop and remove a scheduled task and its run history.",
            "inputSchema": {
              "properties": {
                "task_id": {
                  "description": "From list_tasks.",
                  "type": "integer"
                }
              },
              "required": [
                "task_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": true,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": 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": {
              "properties": {
                "read": {
                  "description": "Source dialect, e.g. \"mysql\". Omit to auto-detect from generic SQL.",
                  "type": "string"
                },
                "sql": {
                  "description": "The SQL statement (or several, separated by semicolons).",
                  "type": "string"
                },
                "write": {
                  "description": "Target dialect, e.g. \"postgres\", \"bigquery\", \"doris\".",
                  "type": "string"
                }
              },
              "required": [
                "sql",
                "write"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "url": {
                  "description": "Full URL to test, e.g. https://example.com",
                  "type": "string"
                }
              },
              "required": [
                "url"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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\u0026format=png\"",
            "inputSchema": {
              "properties": {
                "format": {
                  "description": "\"svg\" (default) or \"png\".",
                  "type": "string"
                },
                "source": {
                  "description": "The diagram source code (e.g. a Mermaid flowchart).",
                  "type": "string"
                },
                "type": {
                  "description": "Diagram language: mermaid (default), plantuml, graphviz, c4plantuml, excalidraw, blockdiag, erd…",
                  "type": "string"
                }
              },
              "required": [
                "source"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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=\u003cid-from-a-job-tool\u003e",
            "inputSchema": {
              "properties": {
                "job_id": {
                  "description": "The job_id returned when the task was started.",
                  "type": "string"
                }
              },
              "required": [
                "job_id"
              ],
              "type": "object"
            },
            "outputSchema": {
              "properties": {
                "error": {
                  "type": "string"
                },
                "is_terminal": {
                  "type": "boolean"
                },
                "job_id": {
                  "type": "string"
                },
                "kind": {
                  "type": "string"
                },
                "next_action": {
                  "type": [
                    "object",
                    "null"
                  ]
                },
                "result": {},
                "retry_after_seconds": {
                  "type": "integer"
                },
                "status": {
                  "type": "string"
                },
                "structured_result": {}
              },
              "required": [
                "job_id",
                "status"
              ],
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": true,
              "openWorldHint": false,
              "readOnlyHint": true
            }
          },
          {
            "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": {
              "properties": {
                "description": {
                  "description": "What the tool should do, in any language. Be specific about inputs/outputs.",
                  "type": "string"
                },
                "name": {
                  "description": "Optional short app name (defaults to the description).",
                  "type": "string"
                },
                "refine": {
                  "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`.",
                  "type": "string"
                },
                "visibility": {
                  "description": "\"public\" (default, listed in the store) or \"unlisted\" (URL-only, not in the store).",
                  "type": "string"
                }
              },
              "required": [
                "description"
              ],
              "type": "object"
            },
            "outputSchema": {
              "additionalProperties": true,
              "type": "object"
            },
            "annotations": {
              "destructiveHint": false,
              "idempotentHint": false,
              "openWorldHint": false,
              "readOnlyHint": false
            }
          }
        ]
      },
      "name": "ai-netcafe",
      "note": "Indexed from the official MCP registry: facts and our own checks, not reviewed, so no score, grade or rank.",
      "packages": [
        {
          "registryType": "npm",
          "identifier": "ai-netcafe",
          "version": "1.2.1",
          "transport": "streamable-http"
        },
        {
          "registryType": "pypi",
          "identifier": "ai-netcafe",
          "version": "1.2.2",
          "transport": "streamable-http"
        }
      ],
      "pageJsonUrl": "https://www.anchorterminal.com/tools/ainetcafe-ai-netcafe.json",
      "popularity": {
        "githubStars": 1,
        "npmWeekly": 47,
        "pypiWeekly": 16
      },
      "registryName": "com.ainetcafe/ai-netcafe",
      "remotes": [
        {
          "type": "streamable-http",
          "url": "https://ainetcafe.com/mcp?s=registry"
        }
      ],
      "repository": "https://github.com/mario03690/ai-netcafe",
      "reviewed": false,
      "slug": "ainetcafe-ai-netcafe",
      "source": "the official MCP registry",
      "sourceUrl": "https://registry.modelcontextprotocol.io/v0.1/servers?search=com.ainetcafe/ai-netcafe",
      "summary": "Tables and ledgers checked by arithmetic, not by a model. 24 tools. MCP 2026-07-28 ready.",
      "updatedAt": "2026-08-14T13:30:22Z",
      "url": "https://www.anchorterminal.com/tools/ainetcafe-ai-netcafe",
      "vendor": "ainetcafe.com",
      "vendorUrl": "https://ainetcafe.com/mcp.html",
      "version": "1.7.0",
      "websiteUrl": "https://ainetcafe.com/mcp.html",
      "where": "both",
      "why": [
        "vendor"
      ]
    }
  },
  "kind": "anchor.page",
  "links": {
    "api": "https://www.anchorterminal.com/api/v1/index.json",
    "html": "https://www.anchorterminal.com/tools/ainetcafe-ai-netcafe",
    "json": "https://www.anchorterminal.com/tools/ainetcafe-ai-netcafe.json",
    "llms": "https://www.anchorterminal.com/llms.txt",
    "markdown": "https://www.anchorterminal.com/tools/ainetcafe-ai-netcafe.md",
    "slim": "https://www.anchorterminal.com/tools/ainetcafe-ai-netcafe.min.md"
  },
  "markdown": "# ai-netcafe\n\n\u003e Indexed, not reviewed: facts from the official MCP registry and our own checks. No score, grade or rank, and not in the rankings until the panel reviews it. How the index works: https://www.anchorterminal.com/indexed/\n\n- Kind: MCP server, by ainetcafe.com (https://ainetcafe.com/mcp.html)\n- Category: Accounting \u0026 invoicing (https://www.anchorterminal.com/categories/accounting.md)\n- Listed because: It's published in the registry under ainetcafe.com, a namespace the registry only gives to whoever proves they control that domain.\n- What the official MCP registry says: Tables and ledgers checked by arithmetic, not by a model. 24 tools. MCP 2026-07-28 ready.\n\n## Facts\n\n- MCP registry: `com.ainetcafe/ai-netcafe` 1.7.0\n- Endpoint: https://ainetcafe.com/mcp?s=registry (streamable HTTP)\n- Package: npm `ai-netcafe` (streamable-http)\n- Package: pypi `ai-netcafe` (streamable-http)\n- Source: https://github.com/mario03690/ai-netcafe\n- Website: https://ainetcafe.com/mcp.html\n- npm downloads a week: 47\n- PyPI downloads a week: 16\n- GitHub stars: 1\n- Registry entry updated: 2026-08-14\n\n## Tools\n\n- Tools it lists (34, about 7,810 tokens of context, `tools/list` without credentials, checked 2026-10-04 22:22 UTC):\n  - `what_can_you_do` (read-only): 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…\n  - `list_apps` (read-only): 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…\n  - `get_app` (read-only): 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.…\n  - `ask_model` (writes): Send a prompt to one specific large language model and get the answer plus measured platform cost metadata. The beta platform covers the user charge ($0.00);…\n  - `compare_models` (writes): Run one prompt across multiple LLMs in parallel and return every answer side by side with measured platform cost metadata and latency. The beta platform covers…\n  - `list_models` (read-only): List every model currently available in the free beta with reference input/output rates and health metadata. Those rates are platform cost metadata only; every…\n  - `remember` (writes): Persist a durable memory: an architecture decision, a stable user preference, a verified bug fix, or an important discovery. The free beta provides a bounded…\n  - `recall` (read-only): 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…\n  - `web_search` (read-only): 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…\n  - `fetch_page` (read-only): Fetch a public URL and return clean LLM-ready Markdown from the server-rendered response. This tool does not execute browser JavaScript; for SPA or empty-text…\n  - `model_costs` (read-only): Measured platform cost metadata for one call on each model; your charge is $0.00 during the free beta. Vendors publish per-million-token list prices, but a…\n  - `ai_visibility` (read-only): 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 /…\n  - `pdf_to_markdown` (read-only): 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.…\n  - `extract_tables` (read-only): 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…\n  - `extract_statement` (read-only): 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…\n  - `json_yaml` (read-only): 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…\n  - `validate_json` (read-only): 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…\n  - `diff_text` (read-only): 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…\n  - `jwt_decode` (read-only): 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…\n  - `regex_test` (read-only): 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…\n  - `diff_tables` (read-only): 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…\n  - `clean_table` (read-only): 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…\n  - `merge_tables` (read-only): 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…\n  - `reconcile_ledger` (read-only): 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…\n  - `extract_invoices` (read-only): 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…\n  - `create_task` (writes): 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…\n  - `list_tasks` (read-only): Show scheduled tasks, next run times, run counts, and measured platform cost metadata. User charge is $0.00 during the beta.\n  - `get_task_runs` (read-only): Recent runs of one scheduled task: what it returned, whether the result changed, and measured platform cost metadata. User charge is $0.00.\n  - `delete_task` (writes): Stop and remove a scheduled task and its run history.\n  - `transpile_sql` (read-only): Convert a SQL statement from one dialect to another — mysql, postgres, sqlite, tsql, oracle, snowflake, bigquery, redshift, spark, hive, presto, trino, duckdb,…\n  - `china_reachability` (read-only): 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?\"…\n  - `render_diagram` (read-only): 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…\n  - `check_job` (read-only): 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…\n  - `build_app` (writes): 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…\n- How its tools read to an agent (0 errors, 2 warnings, 0 notes, about 7,810 tokens; rules at https://www.anchorterminal.com/check.md; not part of the score):\n  - warn TC14 create_task: allowed values are in the description, not an enum: kind\n  - warn TC18 merge_tables: readOnlyHint is true but the name says \"merge\"\n\n- JSON: https://www.anchorterminal.com/api/v1/tools/ainetcafe-ai-netcafe.json\n- Being indexed says nothing about quality, and nobody can pay for it. Ask for a review: https://www.anchorterminal.com/builders/#claiming\n",
  "meta": {
    "attribution": "Anchor Terminal (https://www.anchorterminal.com)",
    "docs": "https://www.anchorterminal.com/docs/",
    "generatedAt": "2026-10-04",
    "license": "CC-BY-4.0",
    "method": "https://www.anchorterminal.com/benchmark/",
    "methodology": "0.3",
    "openapi": "https://www.anchorterminal.com/openapi.json",
    "preview": false,
    "run": "2026-10-01",
    "runLabel": "October 2026 research run"
  },
  "page": {
    "breadcrumbs": [
      {
        "name": "Home",
        "url": "https://www.anchorterminal.com/"
      },
      {
        "name": "Terminal",
        "url": "https://www.anchorterminal.com/tools/"
      },
      {
        "name": "Indexed",
        "url": "https://www.anchorterminal.com/indexed/"
      },
      {
        "name": "ai-netcafe",
        "url": ""
      }
    ],
    "description": "ai-netcafe, an MCP server by ainetcafe.com, listed from the official MCP registry. Indexed, not reviewed: facts and our own checks, no score or ranking. Tables and ledgers checked by arithmetic, not by a model. 24 tools. MCP 2026-07-28 ready.",
    "facts": [
      "not reviewed",
      "not ranked",
      "facts only"
    ],
    "h1": "ai-netcafe",
    "image": "https://www.anchorterminal.com/assets/og/indexed.png",
    "path": "/tools/ainetcafe-ai-netcafe",
    "published": "",
    "section": "indexed",
    "title": "ai-netcafe: MCP server, indexed from the official MCP registry",
    "toc": null,
    "updated": "2026-10-04",
    "url": "https://www.anchorterminal.com/tools/ainetcafe-ai-netcafe"
  },
  "tokens": {
    "markdown": 2200,
    "slim": 2130
  },
  "version": 1
}
