{"id":"8138a58d-e0ee-4231-8312-a114d4f298f4","slug":"tools-factory","kind":"mcp","name":"tools-factory","summary":"From any API surface to verified AI agent tools: Go CLI + MCP + skills + SQLite + policy + proofs.","owner":"JustVugg","repoUrl":"https://github.com/JustVugg/tools-factory","license":"MIT","licenseTier":"permissive","trust":"community","stars":59,"match":null,"fewStars":false,"format":"mcp","createdAt":"2026-05-08T22:57:30.000Z","addedAt":"2026-10-14T05:15:22.998Z","logoUrl":"https://avatars.githubusercontent.com/u/13022503?u=16b428ea8d9b8897f7268ab4257b57bfbad64c45&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["databases","developer-tools","browser-web"],"tags":["agent-tools","ai-agents","api-tools","automation","cli","code-generation","developer-tools","go"],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-17T07:10:34.387Z","sample":false,"url":"https://conduits.dev/tools/tools-factory","language":"Go","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Gutenberg CLI\n\n<p align=\"center\">\n  <img src=\"gutenberg-cli.jpg\" alt=\"gutenberg-cli_logo\" width=\"500\"/>\n</p>\n\n\n**A verified tool factory for AI agents.** From any API surface to safe, verified tools any agent runtime can use — Go CLI + MCP server + agent skills + SQLite/FTS5 cache + dry-run-by-default policy + hash-verifiable proof artifacts.\n\n## 30 seconds DEMO\n\n<img src=\"gutenberg.gif\" width=\"500\" >\n\n\n```bash\n$ gutenberg quick https://catfact.ninja/fact\ngutenberg quick: probing https://catfact.ninja/fact\ngutenberg quick: verdict = openapi-published (high)\ngutenberg quick: downloading spec from https://catfact.ninja/docs?api-docs.json\ngutenberg quick: generating tool at library/tools/catfact\ngutenberg quick: verifying catfact   ← go build · cli-smoke · mcp-handshake · go test\ngutenberg quick: verify ok\ngutenberg quick: installing catfact  → ~/.local/bin/catfact\n\n$ catfact fact                       ← Grade A · 100/100 · ~30 s end-to-end\nGET https://catfact.ninja/fact\nstatus: 200 OK\n{\n  \"fact\": \"In just 7 years, one un-spayed female cat and one un-neutered male cat...\",\n  \"length\": 121\n}\n```\n\n**One command. Any public API. A working tool surface for AI agents: CLI, MCP, skills, cache, policy and proofs. Verified by build, cli-smoke, MCP handshake, and Go tests.** Nothing else does this.\n\n## What \"quick\" does, in 6 numbered steps\n\n1. **probe** the URL (`try`) — classifies it as `openapi-published / json-endpoint / html-content / spa / lazy-rendered / anti-bot-challenge / http-error`\n2. **fetch the spec** (or seed a HAR if no spec is exposed; auto-infers baseUrl/schemas from real response bodies)\n3. **generate** Go CLI + MCP server + Claude skill + OpenClaw skill\n4. **verify** with build + cli smoke + MCP handshake + Go tests → `proofs/verification.json`\n5. **install** into `~/.local/bin/<slug>`\n6. **expose heroes** — zero-friction aliases auto-detected from the spec (e.g. `catfact fact`, `github meta`, `tvmaze shows`)\n\n## Or pass a natural language intent and route to the catalog\n\n```bash\n$ gutenberg quick \"top hacker news stories\"\ngutenberg quick: searching catalog for \"top hacker news stories\"\ngutenberg quick: top match: hacker-news topstories-json (score=5)\n[...executes against the cataloged tool...]\n```\n\n---\n\n## Why Gutenberg\n\nMost AI-agent infrastructure today gives you a model and tells you \"bring your own tools\". Gutenberg makes the tools — and makes sure they actually work before any agent calls them.\n\n| Primitive | What it does |\n|---|---|\n| **`forge` / `generate`** | OpenAPI / GraphQL / HAR / OpenAPI-from-Postman/Insomnia/curl → Go CLI + MCP server + Claude/OpenClaw skill |\n| **`verify`** | Runs `go build`, CLI smoke test, MCP handshake, `go test` — writes `proofs/verification.json`. **No proof = no Grade A.** |\n| **`try <url>`** | Autopilot: classifies the site (`openapi-published / json-endpoint / html-content / spa / lazy-rendered / anti-bot-challenge / http-error`) and tells you the exact next command |\n| **`extract` / `scrape`** | LLM-powered structured extraction (JSON-Schema validated, cache TTL, Anthropic/OpenAI/Ollama provider) + Firecrawl-style markdown scraping |\n| **`snapshot/replay`** | Generated tools support deterministic record + offline replay for tests and CI |\n| **`vault`** | Shared, AES-GCM-encrypted token vault across all generated tools |\n| **`lockfile` + `diff` + `upgrade` + `watch`** | Pin spec hashes, diff semantically, regenerate while preserving `// gutenberg:keep` blocks, poll upstream for drift |\n| **`compare`** | Call N tools on the same intent, see results side by side |\n| **`aggregator` kind** | One recipe → a fan-out Go CLI over N JSON sources with `merge.go` + `rank.go` |\n| **`heroes`** | Zero-friction aliases auto-detected (or curated via `x-gutenberg-hero`) — e.g. `espn nba`, `github meta`, `tvmaze shows` |\n\n## Installation\n\nGutenberg is currently installed from the GitHub repository. The npm package is not published yet, so do not use `npx gutenberg` for now.\n\nPrerequisites for the full workflow:\n\n- Node.js 20+\n- Go installed on `PATH` (`go version` must work), or `GUTENBERG_GOROOT=/path/to/go`\n- Git and curl\n- Optional: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or Ollama for `extract` / LLM-routed `run`\n\nInstall from source:\n\n```bash\ngit clone https://github.com/JustVugg/gutenberg.git\ncd gutenberg\nnpm install\nnode bin/gutenberg.js doctor\n```\n\nUse it directly from the repo:\n\n```bash\nnode bin/gutenberg.js search \"top hacker news stories\"\nnode bin/gutenberg.js try https://api.tvmaze.com/shows/1\n```\n\nOr install the `gutenberg` command globally from this local checkout:\n\n```bash\nnpm link\ngutenberg doctor\n```\n\nGenerated tools are installed into `~/.local/bin`. Make sure it is on your `PATH`:\n\n```bash\nexport PATH=\"$HOME/.local/bin:$PATH\"\n```\n\nFor browser recording flows only, install a Playwright browser:\n\n```bash\nnpx playwright install chromium\n```\n\n## First Tool\n\nThe fastest end-to-end test is `quick`: it probes a URL, generates a tool, verifies it, and installs the generated CLI.\n\n```bash\ngutenberg quick https://catfact.ninja/fact\ncatfact fact\n```\n\nIf you did not run `npm link`, use `node bin/gutenberg.js` instead of `gutenberg`.\n\nGenerate from a public OpenAPI spec:\n\n```bash\ncurl -fsSL -o /tmp/github.json \\\n  https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json\ngutenberg generate /tmp/github.json --out library/tools/github --name github --force --strict\ngutenberg verify library/tools/github\ngutenberg install library/tools/github\n\ngithub meta\ngithub call search/repos --param q=claude-code --select '[*].full_name'\n```\n\nProbe a site you've never seen:\n\n```bash\ngutenberg try https://www.thetrainline.com/it          # → \"spa, use record\"\ngutenberg try https://it.wikipedia.org/wiki/Bologna    # → \"html-content, use scrape/extract\"\ngutenberg try https://api.tvmaze.com/shows/1           # → \"json-endpoint, seed-har + import + generate\"\n```\n\n## What Gutenberg works on (honest table)\n\n| Site shape | Recommended path | Success rate | Examples we've shipped |\n|---|---|---|---|\n| **API with public OpenAPI** | `generate` directly | ✅ ~95% | GitHub (1183 ops), Stripe (587), Sentry (209) |\n| **API without spec but JSON endpoints** | `seed-har` → `import-har` → `generate` | ✅ ~90% | ESPN, TVMaze, Wikipedia REST, public JSON APIs |\n| **Plain HTML content site** | `scrape` (+ `--structured`) or `extract` with schema | ✅ ~80% | Wikipedia and content/documentation pages |\n| **SPA with reachable XHR** | `record` (Playwright) → `import-har` | ⚠️ ~40% | needs interactive triggering |\n| **SPA + Cloudflare Turnstile / strong anti-bot** | `record --backend browserbase` (paid) — or use an official partner API | ❌ ~5% with free tooling | thetrainline, lastminute, OpenTable, Subito.it |\n\n## Non-goals (what Gutenberg deliberately does NOT do)\n\n- **Bypass anti-bot protections.** Cloudflare Turnstile, JS challenges, fingerprint-based bot detection: Gutenberg does not try to defeat them. When a site invests in stopping bots, that's a product decision we respect. For legitimate browser-driven scraping use the official Browserbase backend (`record --backend browserbase`).\n- **Solve CAPTCHAs.** No 2Captcha-style integrations.\n- **Scrape against ToS.** The README of every generated tool tells users to respect rate limits, robots.txt, and terms of service.\n- **Be a model.** Gutenberg routes LLM calls (Anthropic / OpenAI / Ollama) but does not train or fine-tune.\n\n## Commands\n\n```bash\ngutenberg doctor                            Probe runtime, LLM providers, Browserbase\ngutenberg try <url>                         Autopilot — classify a site and pick the next command\ngutenberg discover <url>                    Look for a published OpenAPI/Swagger\ngutenberg seed-har <url> [<url>...]         Fetch URL(s) via plain HTTP, emit HAR (no browser)\ngutenberg record <url>                      Playwright HAR recording  [--storage-state state.json]\n                                                                       [--backend browserbase --key $KEY --project-id $PROJ]\ngutenberg login <url> --out state.json      Headed login flow, save storage-state for later record/extract\ngutenberg import-har <har>                  HAR → OpenAPI (with schema inference + auth sniffer)\ngutenberg import-graphql <source>           GraphQL SDL / introspection → OpenAPI\ngutenberg generate <spec> --out <dir>       OpenAPI → Go CLI + MCP + Claude skill (+ openclaw, optional)\n                                            [--strict] [--min-score 0.7] [--default-header 'k: v']\n                                            [--policy policy.json]\ngutenberg generate <recipe> --kind aggregator --out <dir>\ngutenberg verify <project-dir>              Runs build + cli-smoke + mcp-handshake + tests; writes proofs/\ngutenberg install <project-dir>             go build + symlink into ~/.local/bin\ngutenberg install starter-pack              Install Hacker News, ESPN, Wikipedia, TVMaze, Open-Meteo, GitHub\ngutenberg scorecard <project-dir>           Multi-dim scorecard with verification badges\ngutenberg publish <tool-dir>|--all          Validate proofs + skills + OpenClaw; sync registry\ngutenberg registry sync                     Rebuild library/registry.json from real manifests\ngutenberg upgrade <project-dir> [--spec ...] Regenerate, preserve `// gutenberg:keep` blocks, auto go mod tidy\ngutenberg watch <project-dir> <spec-url>    Poll spec URL, regenerate on drift\ngutenberg diff <old-spec> <new-spec>        Semantic spec diff\ngutenberg extract <url> -p PROMPT -s SCHEMA LLM extraction with JSON-Schema validation + --cache 1h\ngutenberg scrape <url> [--structured]       Main-content markdown (table detector for repeated patterns)\ngutenberg search <intent>                   Catalog discovery: top matching operations\ngutenberg run <intent> [--no-llm]           LLM-routed (or top-match) execute against catalog\ngutenberg compare <tool-a> <tool-b> --op X  Side-by-side call across tools\ngutenberg site build                        Rebuild web/data.js with scorecard + heroes\n```\n\nGenerated tools share a uniform sub-command surface:\n\n```bash\n<tool> operations [--json]                  List operations\n<tool> heroes [--json]                      List auto-detected hero aliases\n<tool> <hero-alias>                         Shortcut to call --digest\n<tool> call <op-id> [options]               Call with full control\n  --param k=v --path k=v --header 'k: v' --data '{...}' --yes\n  --json | --compact | --digest | --select 'data.events[*].name'\n  --stream                                  For SSE/NDJSON endpoints\n<tool> walk <op-id> --max N                 Auto-pagination (offset/limit, cursor, page)\n<tool> sync                                 Cache read operations locally (SQLite/FTS5)\n<tool> search <query>                       Full-text over cached responses\n<tool> resources [query]                    Search projected resource rows in SQLite\n<tool> auth <status|client-credentials|device|pkce-start|pkce-finish|refresh>\n<tool> mcp                                  Run as MCP stdio server\n```\n\n## Catalog included\n\n21 verified catalog entries with `proofs/verification.json`:\n\n| Tool | Ops | Source | Verified checks |\n|---|---:|---|---|\n| github | 1183 | GitHub OpenAPI official | build • cli • mcp • tests |\n| stripe | 587 | Stripe OpenAPI official | build • cli • mcp • tests |\n| sentry | 209 | Sentry OpenAPI official | build • cli • mcp • tests |\n| espn | 4 | HAR-seeded | build • cli • mcp • tests |\n| wikipedia-it | 5 | HAR-seeded (User-Agent default) | build • cli • mcp • tests |\n| tvmaze | 5 | HAR-seeded | build • cli • mcp • tests |\n| multi-demo | 2 sources | aggregator (ESPN + Open-Meteo) | build • cli • tests |\n| dev-pulse | 2 sources | aggregator (GitHub + ESPN) | build • cli • tests |\n\nPlus CatFact, CoinGecko, Dog API, Exchange Rates, Hacker News, npm registry, Open-Meteo, PokeAPI, public holidays, PyPI, RandomUser, REST Countries, and TVMaze quick. The complete source of truth is `library/registry.json`, generated by `gutenberg registry sync`.\n\nPlus 17+ recipe templates in `library/recipes/` for common sources (Hacker News, CoinGecko, PokeAPI, Open-Meteo, REST Countries, Nominatim, npm registry, PyPI, exchange rates, public holidays, Reddit, Spotify, Slack, Xquik, …).\n\n## Output targets\n\n`--targets go,mcp,skill,openclaw` controls what gets emitted next to the Go module:\n\n- **`go`** + **`mcp`** — Go binary + stdio MCP server (default)\n- **`skill`** — `skills/<slug>/SKILL.md` (Claude Code skill format)\n- **`openclaw`** — `openclaw/<slug>/skill.{json,md}` (agent-framework-neutral schema)\n\n## Architecture diff vs other open-source factories\n\nCompared to **site2cli** (PyPI) and **printingpress.dev** (~82 CLIs, npm), Gutenberg uniquely ships:\n\n- Verification proofs gate (no Grade A without `proofs/verification.json`)\n- `gutenberg try <url>` autopilot\n- Aggregator-as-recipe (declarative)\n- Snapshot/replay deterministic mode (built into every generated tool)\n- Shared AES-GCM token vault\n- `lockfile` + `diff` + `upgrade` + `watch`\n- `cross-tool compare`\n- LLM-provider-agnostic extract (Anthropic / OpenAI / Ollama) + cache TTL\n- HAR → OpenAPI with **response schema inference** and **auth scheme sniffer**\n- Built-in JSONPath `--select` and `--stream` for SSE/NDJSON\n\nWhat we don't have yet: their catalog scale (82 vs 21) and packaged npm distribution. The catalog grows with recipes and `gutenberg publish --all --fix-assets`.\n\n## Run tests\n\n```bash\nnode --test tests/*.test.js\n```\n\nLocal-network-dependent tests skip cleanly in sandboxes that deny `127.0.0.1` listeners. Browser tests remain opt-in (`GUTENBERG_BROWSER_TESTS=1` to exercise live Playwright).\n\n## Environment variables\n\n| Var | What |\n|---|---|\n| `ANTHROPIC_API_KEY` | Use Anthropic for `extract` / `run` |\n| `OPENAI_API_KEY` | Use OpenAI for `extract` / `run` |\n| `OLLAMA_HOST` (default `http://localhost:11434`) + `GUTENBERG_LLM_PROVIDER=ollama` | Use local or remote Ollama for `extract` |\n| `BROWSERBASE_API_KEY` + `BROWSERBASE_PROJECT_ID` | Required for `record --backend browserbase` |\n| `GUTENBERG_VAULT_KEY` (32-byte hex) | Encrypt the shared OAuth vault with AES-GCM |\n| `GUTENBERG_TELEMETRY=1` + `GUTENBERG_TELEMETRY_FILE` | Opt-in local JSONL log of operation calls (never sent anywhere) |\n| `<TOOL_ENV>_SNAPSHOT_MODE=record\\|replay` + `<TOOL_ENV>_SNAPSHOT_DIR` | Deterministic HTTP record/replay per tool |\n| `<TOOL_ENV>_AUTO_REFRESH=0` | Disable automatic OAuth refresh in a generated tool |\n\n## License\n\nMIT.\n\n## Status\n\n`v0.1.0` — public. Honest about its boundaries:\n\n- ✅ Verified end-to-end on GitHub, Stripe, Sentry, ESPN, Wikipedia IT, TVMaze and the public-API starter catalog\n- ✅ 21 catalog entries shipped, 17+ recipe templates\n- ❌ Cannot bypass Cloudflare Turnstile / strong anti-bot. Use `record --backend browserbase` or an official partner API for that class of site.\n"}