mcptask-rails-runner
Rails distribution of the mcptask.online autonomous
runner, and the way a Rails app installs it. A thin Ruby wrapper around the
mcptask_runner Go binary: the gem ships the platform-specific binary inside
itself (libexec/) and exposes the same rake tasks as the legacy
mcptask_runner gem, delegating 1:1 to the CLI.
The legacy gem is retired. It gets critical fixes only, and it stays in
existence as the reference implementation the Go runner's conformance suite
measures against; everything new is written in Go. What you gain by moving:
Linux and Windows hosts, a scheduled job with no bundler in its path, and a
handful of places where the old implementation was simply wrong (its token
resolution read a different half of .mcp.json in each of three places, and
its stream reader died mid-run on an API error envelope).
One gem version carries exactly one binary version — mcptask-rails-runner X.Y.Z contains the binary from the vX.Y.Z release of
jchsoft/mcptask-releases.
mcptask_runner:install and :update copy that binary out of the gem to
~/.mcptask/bin/mcptask_runner and run it from there. The scheduled job runs
that copy, because a job pointing inside a gem directory dies at the next
bundle update — at 08:00, in a log nobody reads. So the pin is per project:
the Gemfile decides what a foreground rake mcptask_runner:* runs, while the
machine has one installed binary however many projects it carries, and the
newest version any of them offers is the one that stays. Install and update
print which version they wrote, and never replace a newer installed binary
with an older one.
Requirements
- Ruby >= 3.0, Rails >= 6.0
- Claude Code CLI
- An mcptask.online account
Installation
# Gemfile
gem "mcptask-rails-runner"
bundle install
bundle exec rake mcptask_runner:install
Migrating from the legacy mcptask_runner gem
The rake surface is identical — the migration is one Gemfile line:
- gem "mcptask_runner", git: "git@github.com:jchsoft/mcptask_runner.git"
+ gem "mcptask-rails-runner"
Then:
bundle install
FORCE=1 bundle exec rake mcptask_runner:install
Re-running install is what regenerates the scheduled job. The legacy launcher
runs bundle exec rake and logs the active version by grepping Gemfile.lock
for the old gem name — neither survives the rename, so a job left as it is
keeps working but stops recording what it ran. The regenerated one execs
~/.mcptask/bin/mcptask_runner directly, with no bundler in the 08:00 path.
Every rake mcptask_runner:* invocation and shell alias keeps working
unchanged. Your existing
config/mcptask_runner.yml, .mcp.json and .claude/ setup are read by the
Go binary as-is. The only legacy task without a counterpart is
mcptask_runner:prepare:permissions — permission sync is part of
mcptask_runner:install now.
Tasks
| Task | Delegates to |
|---|---|
mcptask_runner:install |
mcptask_runner init (from ~/.mcptask/bin) |
mcptask_runner:update |
mcptask_runner update (from ~/.mcptask/bin) |
mcptask_runner:bug_report |
mcptask_runner bug-report |
mcptask_runner:version |
mcptask_runner version |
mcptask_runner:manual:once (once_dry, today, daily, review, reviews, workflow, queue) |
mcptask_runner run <mode> |
mcptask_runner:manual:story[123] / manual:task[123] |
run story_manual --story-id 123 / run task_manual --task-id 123 |
mcptask_runner:auto:once |
run once_auto_squash |
mcptask_runner:auto:squash:today (queue, story[123], task[123]) |
run <mode>_auto_squash |
verbose=true and ignore_quota=true environment variables are honored by
the binary itself, exactly as before.
Supported platforms
Platform gems exist for arm64-darwin, x86_64-darwin, aarch64-linux,
x86_64-linux and x64-mingw-ucrt. On anything else bundler falls back to
the binary-less ruby platform gem, which fails at run time with
instructions: install the binary from
mcptask-releases (or via
install.sh / npm @mcptask/cli) and point MCPTASK_RUNNER_BIN at it. The
same variable also serves offline or air-gapped installs.
The wrapper always executes the binary through an absolute path — inside the
gem for the run tasks, ~/.mcptask/bin for install and update — and never
through PATH: the binary shares its name with the legacy tooling, and a PATH
lookup could pick up the wrong install. MCPTASK_RUNNER_BIN overrides both,
and install leaves ~/.mcptask/bin untouched while it is set.
Development
bundle install
bundle exec rake test # unit tests (binary resolution + task mapping)
bin/fetch-binaries # stage release binaries into tmp/binaries/
bundle exec rake package:all # build all platform gems into pkg/
Releasing
Releases are cut by tagging, twice — the binaries come from the Go repository and the gems from this one:
# 1. bump lib/mcptask_rails_runner/version.rb, commit, push
# 2. in mcptask_go_runner:
git tag -a v0.3.0 -m v0.3.0 && git push origin v0.3.0
# 3. here, straight after — no waiting:
git tag -a v0.3.0 -m v0.3.0 && git push origin v0.3.0
Step 3 needs no waiting because the Release workflow's fetch waits for the
binaries itself (MCPTASK_WAIT_FOR_RELEASE, 15 minutes against a Go release
that takes about four). It then verifies each archive against the release's
checksums.txt, builds the platform gems and publishes them to rubygems.org
through OIDC trusted publishing. A tag that disagrees with version.rb is
refused before anything is downloaded. See .github/workflows/release.yml.
One-time setup on rubygems.org, before the first tag can publish anything — the gem name has to exist as a trusted-publisher entry:
- Sign in on rubygems.org, open Profile → Trusted publishers → Create.
- For a gem that has never been pushed, use Create a pending trusted
publisher with gem name
mcptask-rails-runner; for an existing gem, add the publisher on the gem's own page. - Repository owner
jchsoft, repository namemcptask-rails-runner, workflow filenamerelease.yml, environment empty.
No API key is stored anywhere: rubygems/configure-rubygems-credentials
exchanges the workflow's OIDC token for a short-lived credential at push time.
The same model as the npm publish in the Go repository.
License
MIT