task-mcp
Agent-safe task runner MCP server backed by just.
Exposes predefined justfile recipes as MCP tools, with access control via the [group('allow-agent')] attribute (or the legacy # [allow-agent] doc comment).
allow-agent is a security boundary: in the default agent-only mode, recipes without an allow-agent marker are NEVER exposed via MCP. The mode is selected by the TASK_MCP_MODE environment variable, set OUTSIDE the MCP. Reading the justfile directly bypasses this guard, but is not the canonical path for agent interaction.
Tools
| Tool | Description | Annotations |
|---|---|---|
session_start |
Set the working directory for this session. Must be called before run or list (unless list is given an explicit justfile path). |
destructive |
list |
List available tasks from justfile. Returns names, descriptions, parameters, and groups. Requires session_start when no justfile parameter is given. |
read-only, idempotent |
run |
Execute a predefined task. Only tasks visible in list can be run. Requires session_start. |
destructive |
logs |
Retrieve execution logs of recent runs. Returns summary list or full output by task ID. | read-only, idempotent |
info |
Show current session state: active workdir, resolved justfile path, and task mode. | read-only, idempotent |
Installation
Requires just to be installed and available on PATH.
Usage
Start as MCP server (stdio transport):
Claude Code integration
Add to your Claude Code MCP configuration:
Configuration
Configuration is loaded from .task-mcp.env in the current directory (if present), then from environment variables.
| Variable | Default | Description |
|---|---|---|
TASK_MCP_MODE |
agent-only |
agent-only: only allow-agent tagged recipes (Pattern A [group('allow-agent')] or Pattern B # [allow-agent]); all: all non-private recipes. This is the security guard switch — set it OUTSIDE the MCP. |
TASK_MCP_JUSTFILE |
auto-detect | Path to justfile (relative or absolute) |
TASK_MCP_ALLOWED_DIRS |
(any) | Comma-separated list of directories allowed as session working directories. If unset, any directory is accepted. Paths are canonicalized on parse. |
.task-mcp.env example:
TASK_MCP_MODE=agent-only
TASK_MCP_JUSTFILE=./justfile
TASK_MCP_ALLOWED_DIRS=/home/user/projects/my-project,/home/user/projects/other-project
Justfile setup
Two equivalent markers are supported for tagging recipes as agent-safe.
Pattern A (recommended): [group('allow-agent')] attribute
This is the just-native form. Stack additional [group('...')] attributes on separate lines if you also want functional grouping.
# Build the project
[group('allow-agent')]
build:
cargo build --release
# Run tests
[group('allow-agent')]
test filter="":
cargo test {{filter}}
# Profile build — agent-safe AND in the `profile` functional group
[group('allow-agent')]
[group('profile')]
profile-build:
cargo build --profile=release-with-debug
# Deploy to production — NOT exposed to agent
deploy:
./scripts/deploy.sh
Pattern B (legacy): # [allow-agent] doc comment
Supported for compatibility. Caveat: just only keeps the comment line immediately before a recipe as its doc, so combining # [allow-agent] with a descriptive doc comment causes one of the two to be dropped (the marker becomes invisible). Prefer Pattern A in new recipes.
# [allow-agent]
info:
echo "task-mcp"
Mode behavior
In agent-only mode (default), only allow-agent tagged recipes are returned by list and executable via run. Untagged recipes are hidden — they never enter the agent context via MCP.
In all mode, all non-private recipes are exposed. Reading the justfile directly always shows everything, but that bypasses the MCP guard and is not the canonical path.
Workflow
The typical agent workflow is:
- Call
session_startwith the project directory to establish the working context. - Call
listto discover available tasks. - Call
runto execute a task. - Call
logsto inspect output of a past run. - Call
infoat any point to confirm the current session state.
list can also be called without a prior session_start when an explicit justfile path is provided — this is useful for exploration before committing to a working directory.
Tool details
session_start
workdir: absolute path to the project directory; must be accessible and, ifTASK_MCP_ALLOWED_DIRSis set, must fall within one of the allowed directories- Returns a confirmation message with the resolved path on success
info
No parameters required. Returns:
workdir: active working directory (ornullifsession_starthas not been called)justfile: resolved justfile path (ornullif not resolvable from the current session state)mode: current task mode (agent-onlyorall)
list
filter: optional functional group name (e.g.profile,release) to narrow results. Supports glob wildcards (*,?). Filtering byallow-agentis not meaningful inagent-onlymode (every visible recipe already carries it).justfile: optional path override
run
task_name: must appear inlistoutputargs: named arguments matching recipe parameter namestimeout_secs: default 60
Returns a TaskExecution object with id, exit_code, stdout, stderr, duration_ms, and truncated fields.
logs
task_id: omit to get summary of the 10 most recent executions; provide to get full outputtail: restrict stdout to the last N lines (only whentask_idis provided)
In-memory only; logs are lost on server restart.
Output truncation
stdout and stderr are capped at 100 KB per execution. When truncated, the truncated field is true and the head and tail of the output are preserved. Use logs with tail to retrieve specific portions.
Security
- Only recipes whitelisted by
listcan be executed viarun session_startvalidates the requested directory againstTASK_MCP_ALLOWED_DIRSusing canonicalizedPath::starts_with; symlinks are resolved before comparison to prevent traversal attacks- Argument values are validated to reject shell metacharacters
- Execution timeout is enforced (default: 60 s)
open_world_hint = falseon all tools: no external network calls
License
MIT OR Apache-2.0