Turn any MCP server into CLI
Turn any MCP server into a compiled CLI binary. One command. Designed for agents.
clihub generate --url https://mcp.linear.app/mcp
# → ./out/linear (6.5MB static binary, zero runtime dependencies)
Every tool the server exposes becomes a subcommand with flags derived from its JSON Schema. Auth is handled automatically — OAuth, bearer tokens, API keys, and more.
go install github.com/thellimist/clihub@latest
If clihub is not found after install, run export PATH="$(go env GOPATH)/bin:$PATH" to add Go-installed binaries (usually ~/go/bin) to your current shell PATH.
Or build from source:
git clone https://github.com/thellimist/clihub.git
cd clihub
go build -o clihub .
install -m 755 clihub ~/.local/bin/clihub
If you're contributing, run bash scripts/install-hooks.sh once after cloning.
If ~/.local/bin is not in your PATH, add it in your shell config (for example ~/.zshrc):
export PATH="$HOME/.local/bin:$PATH"
Requires Go 1.24+.
Add the following to your AGENTS.md
## Tools
- Check if tool exists in `bin`.
- If not, check if official CLI exists. If so, download it and add it to AGENTS.md
- If not, check official MCP exists. If so, use clihub `go run github.com/thellimist/clihub@latest ` (see `--help`). to create a CLI and move the executable to bin folder. Then add it to AGENTS.md
- If both failed, give suggestions to create a CLI using official docs and https://clig.dev/
clihub generate --url https://mcp.linear.app/mcp
./out/linear list-teams
clihub generate --url https://mcp.notion.com/mcp --oauth
./out/notion notion-search --query "meeting notes"
clihub generate --stdio "npx @modelcontextprotocol/server-github" \
--env GITHUB_TOKEN=$GITHUB_TOKEN
./out/github list-repos --owner octocat
clihub generate --url https://mcp.stripe.com \
--platform linux/amd64,darwin/arm64,windows/amd64
Generated CLIs include a --from-json flag on each tool command. This lets you pass the full tool input object directly.
./out/linear create-issue --from-json '{"title":"Bug report","priority":"high"}'
Rules:
--from-json bypasses typed tool flags.--from-json cannot be combined with typed flags in the same call.--from-json flag from its schema, clihub uses --clihub-from-json for passthrough instead.tools/listThe generated binary is standalone — no runtime dependencies, no config files, no clihub needed.
Generated CLIs handle auth at runtime. For HTTP servers, the auth subcommand manages credentials:
# OAuth browser flow (auto-discovers endpoints via RFC 9728 / RFC 8414)
./out/linear auth
# Manual bearer token
./out/linear auth --token $TOKEN
# Check status
./out/linear auth status
# Logout
./out/linear auth logout
Some MCPs require generatin-time auth. Use
clihub generate --help-auth
Auth is resolved in this order:
--auth-token flag--auth-type + related flags (--auth-header-name, --auth-key-file, etc.)CLIHUB_AUTH_TOKEN environment variable~/.clihub/credentials.json (persisted from previous auth)| Type | Description |
|---|---|
| OAuth 2.0 | Browser flow with PKCE, auto-discovery, token refresh |
| Dynamic Client Registration | RFC 7591 — auto-registers OAuth clients |
| Bearer Token | Static Authorization: Bearer |
| API Key | Custom header (e.g. X-API-Key) |
| Basic Auth | Username/password |
| S2S OAuth 2.0 | Client credentials grant (no browser) |
| Google Service Account | JWT signed with service account key |
…
cmd/ CLI commands (root, generate)
internal/
auth/ Auth providers, OAuth flow, credential store
codegen/ Go template for generated CLIs
compile/ Go compiler invocation, cross-compilation
nameutil/ Binary name inference from URLs/commands
schema/ JSON Schema → Go flag mapping
toolfilter/ Tool include/exclude with fuzzy matching
gocheck/ Go installation detection
main.go Entry point
git checkout -b feature/my-change)bash scripts/install-hooks.shgo test ./...feat(scope): descriptionHook files are tracked in this repo (.githooks/), so git clone downloads them automatically.
Run this once per clone to activate them:
bash scripts/install-hooks.sh
The repo-managed pre-push hook runs:
gofmt formatting check (fails on unformatted .go files)go vet ./...go test ./...golangci-lint run (if installed)Pushes to main also require both:
VERSION updated in the pushed commitsvX.Y.Z that matches VERSION and points at pushed main HEADscripts/install-hooks.sh also sets push.followTags=true, so matching annotated tags are pushed automatically.
Example release bump flow:
bash scripts/bump-version.sh --prepare-push patch # bumps VERSION, amends HEAD, creates vX.Y.Z tag
git push --follow-tags origin main
Tag-only repair flow (if VERSION is already correct but tag is missing/misaligned):
Before changing behavior, review docs in docs/:
docs/project/project.md for scope and goalsdocs/architecture/architecture.md for generation and command flowdocs/auth/auth.md for auth behavior and precedencedocs/releasing/releasing.md for release/version/tag rulesbash scripts/bump-version.sh --sync-tag
git push --follow-tags origin main
go test ./...
go build -o clihub .
No open issues yet, or sync has not completed.