{"id":51526856,"url":"https://github.com/ehmo/mj","last_synced_at":"2026-07-08T22:30:32.036Z","repository":{"id":363270922,"uuid":"1262460312","full_name":"ehmo/mj","owner":"ehmo","description":"Unofficial Midjourney web CLI and MCP server. Bring your own account; drives a Camoufox browser via gomoufox.","archived":false,"fork":false,"pushed_at":"2026-06-08T06:29:28.000Z","size":126,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-08T08:12:53.052Z","etag":null,"topics":["ai-agents","camoufox","cli","golang","image-generation","mcp","midjourney","model-context-protocol"],"latest_commit_sha":null,"homepage":"https://github.com/ehmo/mj","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ehmo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-08T02:28:39.000Z","updated_at":"2026-06-08T06:29:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ehmo/mj","commit_stats":null,"previous_names":["ehmo/mj"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ehmo/mj","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmo%2Fmj","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmo%2Fmj/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmo%2Fmj/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmo%2Fmj/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ehmo","download_url":"https://codeload.github.com/ehmo/mj/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmo%2Fmj/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35280681,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-08T02:00:06.796Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","camoufox","cli","golang","image-generation","mcp","midjourney","model-context-protocol"],"created_at":"2026-07-08T22:30:31.094Z","updated_at":"2026-07-08T22:30:32.027Z","avatar_url":"https://github.com/ehmo.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mj\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Go 1.26\" src=\"https://img.shields.io/badge/Go-1.26-00ADD8?logo=go\u0026logoColor=white\"\u003e\n  \u003cimg alt=\"MIT license\" src=\"https://img.shields.io/badge/license-MIT-2ea44f\"\u003e\n  \u003cimg alt=\"MCP ready\" src=\"https://img.shields.io/badge/MCP-25%20tools-7c3aed\"\u003e\n  \u003cimg alt=\"platforms\" src=\"https://img.shields.io/badge/macOS%20%7C%20Linux-amd64%20%7C%20arm64-555\"\u003e\n  \u003cimg alt=\"status\" src=\"https://img.shields.io/badge/status-unofficial-orange\"\u003e\n\u003c/p\u003e\n\n`mj` drives Midjourney's web app from Go. It is a command-line tool and an MCP\nserver for AI agents. It uses your own Midjourney account. There is no Discord\nbot and no account pool.\n\nUnder the hood it drives a real [Camoufox](https://camoufox.com) browser through\n[gomoufox](https://github.com/ehmo/gomoufox), so every request to\n`midjourney.com` and the result CDN goes out the way a logged-in browser does.\nThat is the only path that clears Cloudflare.\n\n\u003e [!WARNING]\n\u003e Midjourney's Terms of Service prohibit automated access: \"You may not use\n\u003e automated tools to access, interact with, or generate Assets through the\n\u003e Services.\" Accounts have been banned for it. `mj` is bring-your-own-account\n\u003e only. Your account, your risk. It ships a conservative submit throttle, backs\n\u003e off when the server rate-limits you, and refuses to generate until you pass\n\u003e `--i-understand` once. Run it at low volume.\n\n## At a glance\n\n| You want to | Use |\n|---|---|\n| Generate images from a terminal or script | `mj imagine \"...\"` |\n| Give an AI agent image tools | `mj-mcp` (25 tools) |\n| Search and pull from the community gallery | `mj search`, `mj explore` |\n| Edit an image (zoom out, pan, inpaint, restyle) | `mj zoom`, `mj pan`, `mj vary-region`, `mj retexture` |\n| Watch a job render live | `mj imagine \"...\" --watch` |\n| Share one warm browser across many calls | `mj serve` |\n\n## Install\n\nYou need Go 1.26 or newer. On first run, gomoufox downloads a managed Camoufox\nbrowser (a Python venv plus a Firefox binary, about 300 to 660 MB). That happens\nonce.\n\nInstall with Homebrew:\n\n```bash\nbrew install ehmo/mj/mj\n```\n\nOr install the two binaries with Go:\n\n```bash\ngo install github.com/ehmo/mj/cmd/mj@latest\ngo install github.com/ehmo/mj/cmd/mj-mcp@latest\n```\n\nOr build from a clone:\n\n```bash\ngit clone https://github.com/ehmo/mj \u0026\u0026 cd mj\ngo build -o mj ./cmd/mj\ngo build -o mj-mcp ./cmd/mj-mcp\n```\n\nCheck the toolchain:\n\n```bash\nmj doctor\n```\n\n## Log in once\n\n```bash\nmj login --i-understand\n```\n\nA browser window opens. Sign in with Google or Discord, wait for the Create page\nto load, then press Enter in the terminal. `mj` saves the session to a local\nprofile. If you have [hasp](https://github.com/ehmo/hasp), it also stores the\nFirebase refresh token in your vault. The token never lands in `mj`'s own config.\n\n## First image\n\n```bash\nmj imagine \"a vintage teal bicycle on a pink wall --ar 3:2\" --wait --download ./out\n```\n\nThis submits one job (a 4-image grid), waits for it to finish, and saves the\nfour cells plus the grid to `./out`. Add `--json` for machine output.\n\nWant to watch it render? Swap `--wait` for `--watch`:\n\n```bash\nmj imagine \"a koi in dark water\" --watch --download ./out\n```\n\nYou get a live percentage from 0 to 100 over Midjourney's WebSocket.\n\n## When to use what\n\nUse the **CLI** when you drive Midjourney yourself, from a shell, a script, or a\ncron job. Pipe `--json` into `jq` and you have a generation pipeline.\n\nUse the **MCP server** when an agent should drive Midjourney. Claude (or any MCP\nclient) gets 25 tools: generate, vary, upscale, animate, search, edit, download,\nand a raw escape hatch.\n\nUse the **daemon** when you make many calls. Each one-off command cold-starts a\nbrowser, which costs about 4 to 6 seconds. A warm daemon shares one browser and\none session, so calls drop to under a second.\n\n## Use cases\n\n### 1. Generate from a script\n\n```bash\nfor p in \"red maple leaf\" \"blue spruce cone\" \"golden ginkgo\"; do\n  mj imagine \"$p, white background, studio light --ar 1:1\" --wait --download ./botany --json \\\n    | jq -r '.images[]'\ndone\n```\n\nEach line of output is a CDN URL. The files land in `./botany`.\n\n### 2. Let an agent make images\n\nRegister the server with Claude Code:\n\n```bash\nclaude mcp add midjourney -- mj-mcp\n```\n\nNow ask the agent in plain language: \"Generate three logo options for a coffee\nbrand, then upscale the one with the cleanest type.\" The agent calls\n`midjourney_imagine`, reads the result, and calls `midjourney_upscale`. See\n[docs/mcp.md](docs/mcp.md) for the full tool list and a worked transcript.\n\n### 3. Mine the community gallery\n\n```bash\nmj search \"brutalist concrete interior, soft light\" --limit 12 --download ./refs\nmj explore --feed top_week --limit 20\nmj styles                      # browse --sref style codes\n```\n\nSearch runs Midjourney's semantic vector search. Every result carries the full\nprompt and flags that made it, so you can reproduce or remix it.\n\n### 4. Edit an existing image\n\n```bash\nmj zoom        photo.png \"a wider establishing shot\" --factor 2 --wait --download ./out\nmj pan         photo.png \"more sky\"  --dir up --amount 0.5 --wait --download ./out\nmj vary-region photo.png \"a golden crown\" --region 300,40,420,300 --wait --download ./out\nmj retexture   photo.png \"oil painting, thick impasto\" --ar 1:1 --wait --download ./out\n```\n\n`mj` composites the edit the same way Midjourney's web editor does, then submits\nit. The source can be a local file or a URL.\n\n### 5. Animate a still\n\n```bash\nJOB=$(mj imagine \"a paper boat on a calm pond --ar 16:9\" --wait --json | jq -r .job_id)\nmj video \"$JOB\" --index 1 --motion low --wait --download ./clips\n```\n\nVideos download in bounded-memory chunks, so a long clip does not balloon memory.\n\n## CLI\n\nEvery command takes `--json`. Data goes to stdout, progress and warnings go to\nstderr, so pipes stay clean. Exit codes separate auth failures (3), job failures\n(4), timeouts (5), and Cloudflare blocks (6) from generic errors (1).\n\n```text\nGenerate   imagine  vary  upscale  reroll  video\nEdit       describe  retexture  zoom  pan  outpaint  vary-region\nDiscover   search  explore  likes  styles  profile  uploads  liked-styles\n           folders  profiles  queue  moodboards\nJobs       status  wait  watch  history  download\nAccount    login  logout  account  auth  doctor\nDaemon     serve  daemon\nRaw        api\n```\n\nRun `mj help \u003ccommand\u003e` for focused help on any of them. Full reference:\n[docs/cli.md](docs/cli.md).\n\nGeneration flags map straight to Midjourney parameters:\n\n```text\n--ar W:H   --version 7|8|8.1|niji 6|niji 7   --mode fast|relax|turbo   --stealth\n--stylize 0..1000   --chaos 0..100   --weird 0..3000   --quality 0.25|0.5|1|2|4\n--seed N   --no a,b   --tile   --stop 10..100   --style-raw   --raw \"...\"\n--sref U --sw N --sv N    --oref U --ow N    --cref U --cw N    --profile ID\n--image FILE|URL (repeatable; local files upload first)\n```\n\n`--mode relax|turbo` and `--stealth` need an eligible plan. `mj` checks your plan\nbefore it submits, so you get a clear error instead of a wasted job.\n\n## MCP\n\n`mj-mcp` speaks MCP over stdio, so it works with any MCP client.\n\nClaude Code:\n\n```bash\nclaude mcp add midjourney -- mj-mcp\n```\n\nCodex, in `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.midjourney]\ncommand = \"mj-mcp\"\n```\n\nCursor, Windsurf, or any other stdio client, in its MCP config:\n\n```json\n{ \"mcpServers\": { \"midjourney\": { \"command\": \"mj-mcp\" } } }\n```\n\nIt exposes 25 tools:\n\n```text\nimagine  variation  upscale  reroll  video        (generate)\ndescribe retexture  zoom  pan  vary_region         (edit)\nsearch   explore  likes  styles  profile  uploads  (discover)\nfolders  profiles  queue  moodboards               (account)\nstatus   history  account  download  api           (jobs / raw)\n```\n\nIt runs one generation at a time. It reads status, runs searches, and cancels\nwork while a generation is in flight, so the agent is never blocked. It refuses\nto start until you have run `mj login --i-understand`.\n\n### Agent safety\n\nAn agent's input can be hostile (prompt injection from a web page or an image).\nThe MCP surface is locked down for that:\n\n- `image` arguments must be public `https` URLs. Local paths are refused unless\n  you set `MJ_MCP_FILE_ROOT=/some/dir`, and then only files under that directory.\n  This stops \"describe this image: /home/you/.ssh/id_rsa\" from uploading your\n  files to a third party.\n- URLs that point at private, loopback, or cloud-metadata hosts are blocked.\n- `midjourney_api` (the raw endpoint) is read-only unless you set\n  `MJ_MCP_ALLOW_RAW_WRITE=1`.\n\nFull tool reference, schemas, and an example agent session: [docs/mcp.md](docs/mcp.md).\n\n## Daemon\n\n```bash\nmj serve                  # warm browser; keep it running (or background it)\nmj daemon status          # running (…/mj/daemon.sock)\nmj search \"cat\"           # ~0.3s instead of ~5s\nmj daemon stop\n```\n\nCommands route to the daemon when it runs and fall back to a one-off browser when\nit does not. The daemon throttles generations across every client, CLI and MCP\ntogether, through one session. That is faster and safer for your account than two\nclients submitting in parallel.\n\nSet `daemon_autostart: true` in config (or `MJ_DAEMON_AUTOSTART=1`) and the first\ncommand spawns a background daemon for you.\n\n## Ban safety\n\nAutomating Midjourney risks your account. `mj` does what it can to keep the risk\nlow:\n\n- A minimum gap between submits (12s by default), enforced at one choke point so\n  even the raw `api` tool cannot skip it.\n- Adaptive backoff: a `429` grows the gap and a success shrinks it again.\n- One submit funnel through the daemon, shared by every client.\n- The ToS gate (`--i-understand`), stored once.\n\nNone of this makes automation safe. It makes it slower, which is the point. Set a\nlarger gap with `--throttle` or the `throttle_secs` config if you want more\nheadroom. Watch traffic with `MJ_DEBUG=1`, which logs every API call (method,\npath, status, timing) with tokens redacted.\n\n## Credentials\n\n`mj` reads the Firebase refresh token from, in order:\n\n1. `MIDJOURNEY_FIREBASE_REFRESH_TOKEN` (use `hasp inject … -- mj …` to broker it).\n2. The local browser profile after `mj login`.\n\nIt never writes the token to its own config. `mj logout` removes the local\nsession and deletes the stored token.\n\n## Documentation\n\n- [docs/cli.md](docs/cli.md): every command, flag, and example.\n- [docs/mcp.md](docs/mcp.md): every MCP tool, its schema, and an agent transcript.\n- [SECURITY.md](SECURITY.md): trust boundaries and how to report an issue.\n- [CONTRIBUTING.md](CONTRIBUTING.md): build, test, and the bar for changes.\n\n## License\n\nMIT, copyright Wraxle LLC. See [LICENSE](LICENSE).\n\nCamoufox is MPL-2.0 and runs as a subprocess, downloaded at runtime, not vendored.\ngomoufox and playwright-go are MIT.\n\nThis is an unofficial, independent project. It is not affiliated with Midjourney,\nand Midjourney has not endorsed it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehmo%2Fmj","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fehmo%2Fmj","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehmo%2Fmj/lists"}