Dalan
Allows Meta's Muse Spark client to connect as an AI worker that can claim queued Dalan jobs, work on granted tasks, report progress, and return results for acceptance or rejection.
Allows OpenAI-based worker clients such as Codex CLI and ChatGPT to connect as AI workers that claim queued Dalan jobs, perform requested tasks, and return reports or patches for review.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Dalan
Dalan is a job queue between your shell or coding agent and a separate AI worker. A small local service, the bridge, holds the jobs; the worker connects to it over MCP. You submit a bounded task, follow its progress, and review the worker's report or patch before you accept it. Start with a local demo that needs no account, then connect your own worker.
Use it when you want a second agent, a second account or another computer to do a job while you keep the accept or reject decision: for example, your coding agent hands a code review to an agent signed in to another account, and you read its report before you accept it.
Repository access starts denied. A new worker can read no repository until you grant one, and a finished job counts as accepted only after you run
dalan decideor answery.Any MCP client can be the worker. Claude Code, Codex CLI, ChatGPT, Muse Spark (Meta) or your own agent connect over MCP (Model Context Protocol) with OAuth sign-in. Dalan does not run a model itself. See Connect any MCP worker and Connect ChatGPT. T3 Code can delegate to any of them.
The bridge listens only on your computer until you choose to expose it.
Not for: Dalan does not run, schedule or start agents for you, and it does not merge code. It queues work and returns reports for you to review.
Help: see Still stuck? for the recovery steps and how to open an issue.
Quick start
You need:
Linux or macOS. On Windows, install WSL and run every command in the WSL shell.
Node.js 24 or newer. Run
node --version; it must printv24or higher. If it does not, install Node.js from the official download page and open a new shell.Optional: Git and Python 3.8 or newer, for the repository part of the demo. Run
git --versionandpython3 --version. Without them, the demo skips that part and says so.
The demo needs no AI account and no MCP client. The shell examples in this README use POSIX shell syntax (bash or zsh). Start the demo with one command:
npx dalan tryTo run from a checkout instead, see Install from source.
try starts a bridge on 127.0.0.1 and runs a built-in demo worker against it. The first run takes about half a minute. npx asks once to install the package; answer y. A first run prints this (the request ID is shortened):
$ npx dalan try
Need to install the following packages:
dalan@0.5.0
Ok to proceed? (y) y
npm notice run npx
npm notice run 'dalan' try
Dalan trial. Home: /home/you/.local/share/dalan-trial
✔ Bridge up on http://127.0.0.1:8799. Loopback only. Log: /home/you/.local/share/dalan-trial/server.log
✔ Self-check passed in 2.6 s: a demo worker, approved by this command, finished a job; the repository grant works and a second repository is refused.
Connect your worker as an HTTP MCP server with OAuth:
MCP URL file: /home/you/.local/share/dalan-trial/resource-url
MCP URL (secret hidden): http://127.0.0.1:8799/<secret>/mcp
Keep the URL private.
How to connect Claude Code, Codex or another client: https://github.com/tnunamak/dalan/blob/v0.5.0/README.md#connect-your-own-worker
Callbacks: http://127.0.0.1/callback, http://localhost/callback. To add one, restart with:
npx dalan try --home '/home/you/.local/share/dalan-trial' --callback PATTERN
Job req_01234567… is queued for your worker. When it is connected, send it:
"Request req_01234567… is your only job: claim it with Dalan, do what its brief asks, report progress and finish it with the claim_id. Stop if it is missing or cancelled. Claim no other job."
Waiting for your worker. Ctrl-C stops the bridge.Check: look for the ✔ Self-check passed line. The demo worker signed in through OAuth, finished a text job, read the one demo repository that it was granted and was refused another. The demo repository is local, so no network or GitHub login is used.
try now keeps the bridge running and has queued a second job for your own worker. Leave this terminal open and continue below. Ctrl-C stops the bridge and keeps the trial home for the next run (The trial home).
Related MCP server: coder-worker-mcp
Connect your own worker
This step proves that your own client can do a job. You need a worker client installed and signed in on this computer, such as Claude Code, Codex CLI or opencode. A client that runs on its provider's servers (ChatGPT, Claude on the web) cannot reach 127.0.0.1; see Expose the bridge instead.
Cost. The built-in demo uses no AI model or account. Your own worker runs on the account signed in to Claude Code or Codex CLI, and is subject to that provider's access rules, usage limits and charges. Dalan runs no model and adds no charge.
Who can connect. The bridge listens only on 127.0.0.1. A client needs the secret URL from the private file and your y at sign-in before it can act as a worker. These checks do not separate programs that run as your own Unix user: such a program can read the bridge's private files and use its admin socket. Connect only clients that you trust with your account, and run untrusted workers as a different Unix user or on another computer (see Operations).
Add the bridge to your client. In a second terminal, register the MCP URL from the private file that
tryprinted, under the namelocal. The URL contains a secret. The commands read it from the file, so it does not go into your shell history, but the client may print it: keep that output private. If you passed--home DIRtotry, use that directory in place of~/.local/share/dalan-trial.With Claude Code, register the server and sign in:
claude mcp add --transport http --scope user local "$(cat ~/.local/share/dalan-trial/resource-url)" claude mcp login localclaude mcp loginopens the sign-in page and waits until you approve it in step 3. In an interactiveclaudesession,/mcp, thenlocal, then Authenticate does the same.With Codex CLI, register the server; Codex starts the sign-in at once and waits until it is approved:
codex mcp add local --url "$(cat ~/.local/share/dalan-trial/resource-url)"Open the sign-in page. The client opens a browser tab, or prints a URL for you to open once in a browser on this computer. Leave the tab open. It is titled "Connect to Dalan" and shows a pairing code such as
ABCD-1234. The page also shows adalan connect approvecommand: you do not need it, becausetryasks you instead.Approve in the
tryterminal. A block of lines appears there withcode,client_name,redirectandscopes. Check thatcodeis the code in the browser tab and thatscopesaredalan.read dalan.work. (Claude Code also asks fort3.read t3.write, optional integration scopes that give no extra access in this version.) Then answerytoApprove this connection for worker "local"? [y/N].Check:
tryprintsApproved. Waiting for the worker to finish the job.claude mcp loginprintsAuthenticated with "local". Its tools are now available in Claude Code.;codex mcp addreturns withSuccessfully logged in.Give the worker its job. Queuing a job does not start a worker, so you start it. Open an interactive session (
claudeorcodex), paste the prompt thattryprinted, and allow the Dalan tool calls when the client asks. To run it without an interactive session, Claude Code takesclaude -p "PROMPT" --allowedTools mcp__local, which approves this server's tool calls in advance; in this mode Claude Code does not prompt, so it does not use tools that need approval.Check:
tryprints✔ Your worker finished req_…. Report:with the worker's report, then asksAccept this result? [y/N]. Answery;tryprintsRecorded as accepted.
You have now done the whole loop: a job was queued, your worker claimed and finished it, and you reviewed and accepted the result.
If a step fails, look for its message here:
The browser shows
Connection attempt invalid or expired. Each visit to the sign-in URL starts a new attempt with a new code, and only a live attempt can be approved. Start the sign-in again in the client and approve the new code.No approval block appears in the
tryterminal. After a while,tryprints thedalan connect pendinganddalan statuscommands to run in another terminal, and it shows each new attempt as it arrives.npx dalan tryfails with an npm error such asECONNREFUSED,ETIMEDOUTorENOTFOUND. npm cannot reach the registry. Check the network or proxy withnpm config get registryandnpm config get proxy, then run the command again.Your client uses a different callback.
tryallowshttp://127.0.0.1/callbackandhttp://localhost/callbackon any port. Stoptryand start it again with--callback PATTERN(pattern rules).
Still stuck? With DALAN_HOME set as in Next steps, run dalan status and dalan doctor, and match their messages against the list above. If that does not help, open an issue with the Dalan version, your OS, your worker client and its version, the command that you ran and the error with private values removed. Never include the private MCP URL, tokens or sign-in links. Report a vulnerability through the security policy, not in an issue.
The worker guide has the full Claude Code and Codex CLI recipes, including running Codex without a screen (codex exec).
Next steps
Each row starts from a working trial.
To do this | Go to |
Run | Run |
Give your worker a task of your own, with no file to write | |
Give your worker a job on a real repository | |
Let a coding agent submit and read jobs as tool calls | |
Connect a worker on another computer, or a hosted client such as ChatGPT | |
Keep a bridge running as a service | |
Delegate T3 Code tasks to your worker, or give a worker T3 tools | |
See every command |
|
Your own first job
This gives your connected worker a task of your own, with no file to write and no JSON. Leave try running, and use a second shell. First install the CLI, select the trial home and type your task:
npm install -g dalan
export DALAN_HOME=~/.local/share/dalan-trial
printf 'Your task, on one line: '; IFS= read -r taskIf npm install -g dalan fails with EACCES, your global npm directory belongs to root. Do not use sudo; change npm's default directory, or skip the install and write npx dalan wherever this section says dalan.
Type the task and press Enter. The shell stores it as plain text, so quotes, $ and backticks in it are safe. Then submit it:
dalan submit --worker local --execution none --deliver none --brief "$task Do not read files, run commands or call external services."--brief makes a read-only job from the text. submit prints a Request ID: line and a Send your worker: line. Paste that prompt into your worker's session, then wait for the result in the same shell. Replace REQUEST_ID with the ID that submit printed:
dalan wait REQUEST_ID --timeout 3600 && dalan get REQUEST_IDCheck: dalan get prints Job REQUEST_ID: finished, then Summary: and your worker's answer. It then prints Next: dalan decide REQUEST_ID accepted, and its last line is Full record: dalan get REQUEST_ID --json. It may also print an Outcome: line. Review the answer, then run the Next: command to record your decision. If wait times out, the job is still open: check it with dalan get REQUEST_ID and ask the worker to check Dalan again. If you passed --home DIR to try, export that directory as DALAN_HOME instead.
How Dalan works
Dalan has three roles, and one person can hold all three:
The owner runs the bridge, a small Node.js service that stores jobs and results in SQLite. The owner decides which workers may connect and which repositories each worker may use.
The requester submits jobs with the
dalancommand and reads the results. A requester can be you in a shell, a script, or a coding agent.The worker is an MCP client that signs in to the bridge with OAuth. It calls
list_pendingto find work,claimto take a job,progressto report, andfinishto send the result.
Workers pull jobs; Dalan never starts a worker. You prompt or schedule the worker in its own client. The pull-worker guide describes schedules and wake signals once the first job works.
A worker name, such as local or chatgpt, is a label that you choose for a connection. It does not select a vendor adapter: every worker uses the same job tools. A finished job and an accepted job are separate facts. Dalan returns reports and patches; it never pushes or merges them.
Give a worker a repository job
The first job needs no repository. A repository job needs Git and Python 3.8 or newer on the bridge computer, because the bridge fetches the repository with them. The bridge also needs workspaces turned on, the worker needs a grant for that one repository, and the bridge needs a way to fetch it.
A bridge started by dalan try already has workspaces on. Leave try running and use a second shell with DALAN_HOME set (Next steps). For a bridge you started by hand, add DALAN_ENABLE_WORKSPACE=1 to the server command from step 3 of the manual setup and restart it. Without that setting, repository calls fail with capability_not_enabled.
The repository can come from GitHub or from a clone on this computer:
A GitHub repository. The bridge fetches with
gh auth token. Install the GitHub CLI and rungh auth loginas the user who runs the bridge. A service with its own home needs its own GitHub access.A clone on this computer (no GitHub login). Pick a name
OWNER/REPOfor it, for examplelocal/my-project. Start the bridge with a variable namedDALAN_GITHUB_URL_plus that name in capitals, with every other character replaced by_, set to the clone's absolute path. Forlocal/my-projectthe variable isDALAN_GITHUB_URL_LOCAL_MY_PROJECT. To use the trial bridge, stoptrywith Ctrl-C and start it again with the variable:DALAN_GITHUB_URL_LOCAL_MY_PROJECT=/path/to/my-project npx dalan tryThe restart replaces your worker's connection with the demo worker again, so sign your worker in again as in Connect your own worker. For a bridge you started by hand, add the same variable to the server command instead. Use
local/my-projectwherever the steps below sayOWNER/REPO. The clone needs at least one commit.
As owner, grant the worker one exact repository, then check the grant.
dalan worker allow local OWNER/REPO dalan worker list local --jsonCheck: the list contains only the repositories that you intend to allow. A new worker can use no repository; a grant for one repository does not grant its owner's other repositories. Grants take effect without a restart.
As requester, find the commit to pin. For a GitHub repository,
git ls-remote https://github.com/OWNER/REPO HEADprints it in the first column; for a local clone, rungit -C /path/to/my-project rev-parse HEAD. Make a new request ID withnode -e "console.log(require('node:crypto').randomUUID())".Save this job as
repository-job.json, with your repository, commit and request ID. The job readsREADME.md; if the repository has none in its top directory, name another file.{ "schema_version": 1, "request_id": "req_<new UUID>", "brief": "Read README.md at the pinned commit and report its title. Do not run checks or change files.", "inputs": [{"github_repo": "OWNER/REPO", "base_sha": "<full 40-character commit SHA>"}], "expected_output": "README title and pinned revision; no patch or check claim.", "scope_paths": ["README.md"], "execution_scope": "read-only" }Submit the job.
dalan submit --worker local --execution none --deliver none --file repository-job.json --jsonIn your worker's client, send this prompt with your request ID:
Request REQUEST_ID is your only job: claim it with Dalan, do what its brief asks, report progress and finish it with the claim_id. Stop if it is missing or cancelled. Claim no other job.
Then wait for the result, read it and record your decision:
dalan wait REQUEST_ID dalan get REQUEST_ID dalan decide REQUEST_ID acceptedCheck: the report names the file's title and the exact commit that you pinned. Each repository job takes one repository; submit separate jobs for more.
If submission or claim says the repository is not allowed, run dalan paths --json to confirm that you are in the bridge's home, then dalan worker list local --json, and grant the exact repository. A queued job that loses its grant stays queued until the grant returns or you cancel the job. A GitHub authentication error means the bridge's home has no working GitHub credential.
Repository workspaces and host checks (tests that the bridge runs) are separate capabilities. try does not turn on host checks. They need Linux, explicit owner opt-in, an allowlisted repository and check, and resource budgets; see execution and evidence. A finished job or a passing check never authorizes a merge.
Expose the bridge to other machines
A worker connects from wherever its MCP client runs. 127.0.0.1 reaches only the bridge computer. A worker on another computer needs a network route to the bridge, and a hosted client such as ChatGPT needs a public HTTPS address.
For this, set up a separate, long-running bridge with a stable HTTPS address. The setup script writes a systemd user service (Linux) or a launchd agent (macOS). The default route is Tailscale Funnel, which needs no reverse proxy and no domain of your own:
Complete the Tailscale Funnel prerequisites.
Run the setup script from the installed package (
npm install -g dalan):node "$(npm root -g)/dalan/scripts/worker-bridge-setup.mjs" --worker NAME --port PORT --home HOME_PATH --expose tailscale --startFrom a checkout, run
node scripts/worker-bridge-setup.mjswith the same options.Setup picks the first free Funnel port (443, 8443 or 10000); add
--funnel-port Nto choose one.Connect the worker: a native client on another computer follows Native client on a remote HTTPS bridge; a hosted client follows its recipe in Connect any MCP worker.
If you already run an HTTPS reverse proxy, pass --public-url https://bridge.example.com instead of --expose tailscale; the service guide lists the routes to forward. A successful network check only shows that the address answers: run a first job through the new connection to prove that the worker can work.
Connect any MCP worker
Any client that speaks HTTP MCP and completes the bridge's OAuth sign-in can be a worker. Start with the worker guide; it applies to Claude Code, Codex CLI, a script or a hosted chat client. The recipes add only the registration details of one client; the job tools and grant rules stay the same.
Client | Guide |
Any MCP client | Connect a worker client: the common protocol and client requirements |
Codex CLI | |
Claude Code | |
opencode | CLI worker: opencode, with a model that supports tool calls |
ChatGPT | |
Muse Spark (Meta) | Connects like any remote MCP client: follow Expose the bridge and the worker guide; there is no client-specific recipe. |
Claude on the web (hosted) | Claude cloud worker; separate from Claude Code |
Start each new worker by hand for its first job. Dalan never starts a worker, including after a reboot.
The trial home
try keeps everything in one private directory, the trial home: --home DIR if you pass it, else DALAN_HOME if it is set, else ~/.local/share/dalan-trial.
What
tryrefuses. It refuses your real home directory and any non-empty directory without a.dalan-trialmarker file, so it cannot take over an existing bridge home.Keep it dedicated. A directory that has the marker is reused without checking its other files. On exit,
trydeletesdemo/and everyreq_*.jsonrequest file in the home, revokes the demo grant and deletes the demo repository. A run that was killed is cleaned up at the next start.Use a short path on a local disk. The bridge's admin socket path has a length limit, and network or FUSE file systems are not supported. If a home is too long or not on a local disk, use a new short directory:
npx dalan try --home /short/local/path. Do not use an existing bridge home.A second run reuses the home, its worker profile, job history and port. It first replaces the worker's connection with the demo worker, so sign in again in your client and approve it again after the demo.
To start over, stop
tryand delete the trial home.For scripts, run
dalan try < /dev/null: with standard input closed,tryruns the self-check and stops.
try takes three options:
--home DIR: the trial home.--port N: the bridge port. The default is the port that the home used before, otherwise 8799 or the next free port. A home keeps its port; for another port, start a separate trial with--home NEW_DIR --port N.--callback PATTERN: allow one more OAuth callback pattern; repeatable.
try turns repository workspaces on (with at least 256 MiB of free disk) and makes only the demo repository available locally. Every other repository stays denied until you grant it. try does not turn on host checks.
Commands against the trial. Set DALAN_HOME as in Next steps. While the default trial home ~/.local/share/dalan-trial exists and DALAN_HOME is unset, every command except dalan help, dalan paths, dalan doctor, dalan try, dalan mcp, dalan --version and dalan -v stops with DALAN_HOME is not set and prints the export line to run, so it cannot use your normal home by mistake. dalan doctor runs instead, reports that no bridge home is selected and prints the export line to run. Without that trial home, an unset DALAN_HOME means your normal home.
If the bridge does not start or stops. try prints the path of server.log and three commands: one to read the log, one to retry the same home and port, and one to start in a new home with a free port. Read the log before you retry. --port alone cannot move an existing trial to another port.
Advanced: the same setup by hand
try runs ordinary dalan commands in a private trial home. To run each piece yourself (a foreground bridge, your own worker name, or a client that try does not cover), follow Manual setup.
It has three parts: owner and requester setup, worker setup, and submit, finish and read the result, which has a complete first job in first-job.json. To give a job to the trial bridge with no file, see Your own first job.
Operate and recover
Settings and commands. The setup reference lists environment settings and requester commands. The protocol defines the worker tools and lease rules.
Before you change a deployed bridge, read operations. Before an upgrade, read the release notes and follow upgrade and rollback: older code can refuse an upgraded database.
Backups. Stop every process that writes to the bridge, then follow the backup checklist. Back up receipts, artifacts and encryption keys with the databases. After a restore of older authorization state, a worker's newer token can fail with
invalid_grant; connect that worker again.Optional integrations. Besides T3 Code, the setup reference lists the other optional integrations, and ordinary jobs need none of them.
Uninstall a trial. Stop
dalan try(Ctrl-C) and remove the connection from your client:claude mcp remove --scope user localorcodex mcp remove local. Remove thedalancommand as the removal table describes. The trial home holds private keys, connections and receipts: delete it only when you no longer need them. For a generated service, follow service removal.
Names you may see
Earlier versions of Dalan used other names, and some remain so that existing installations keep working. Use dalan and DALAN_* names for anything new. The setup reference lists the older names and the optional integrations.
Install from source
To work on Dalan, or to run the bridge by hand from a checkout:
git clone https://github.com/tnunamak/dalan.git
cd dalan
npm ci
node bin/dalan.mjs tryTo put dalan on your PATH from the checkout, run npm link once (undo it with npm unlink -g dalan). Without it, write node bin/dalan.mjs wherever this README says dalan. Installing from npm instead: npm install -g dalan (remove it with npm uninstall -g dalan).
Read the contributing guide before you open a pull request, and the security policy to report a vulnerability.
Licensed under the Apache License 2.0.
This server cannot be deployed
Maintenance
Related MCP Connectors
Public MCP for agent verification, work discovery and governed interoperability.
Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.
Agent-first task marketplace MCP — discover, claim, and deliver paid workspace tasks.
MCP Server for an Agent Task Marketplace
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceLets coding agents delegate bounded background tasks to OMP models via an MCP server, with job control, custom roles and agents.87 npmMIT
- -licenseNot gradedqualityNot gradedmaintenanceEnables MCP clients to securely execute bounded coding tasks through registered backends, with idempotent job submission, status polling, and artifact retrieval. It isolates each job in Git worktrees and supports optional branch publishing and pull request creation under strict policy constraints.-
- AlicenseNot gradedqualityBmaintenanceEnables repository-aware lifecycle management and controlled delegation of coding tasks to trusted worker harnesses via MCP, with execution isolation, recovery, and verified handoff.32 npm8Apache 2.0
- AlicenseBqualityBmaintenanceEnables AI agents to submit GPU job requests, select eligible workers, track execution, and retrieve results via MCP.1421MIT