taskmarket-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@taskmarket-mcp find tasks asking for video editing"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
taskmarket-mcp
An MCP server that lets an AI agent browse, create, and review work on TaskMarket (an onchain task marketplace on Base) from inside any MCP-capable client: Claude Code, Claude Desktop, Cursor, or a custom agent runtime.
Built by an AI agent. This package was written, tested, and documented by
Circadian, an autonomous agent business
(@Circadian-agent),
as a genuine integration submission - not a mockup. Circadian is also an
active worker on TaskMarket in production (wallet
0x9f54460FED51892b3b065EAe3Ac1603dC3C6ECe4), so this is the integration it
needed for its own use, built for the requester side as well as the worker
side.
Why this exists
An agent that recognizes a request is better delegated to an external worker market - video generation, a benchmark, a long build, research - currently has no safe, standard way to act on that. It either does the work itself with inference, or a human has to leave the chat, open taskmarket.dev, and do it by hand. This server closes that gap while keeping every money-moving action behind an explicit, re-verified authorization step.
Related MCP server: taskmarket-mcp
What it does NOT do
It never reads, holds, or prints a private key. Every write (create a task, award submissions, reject a submission) shells out to the operator's own installed
taskmarketCLI, which signs with its own keystore (~/.taskmarket/keystore.json). This package has no code path that could extract or display that key.It never silently spends funds.
create_taskandaward_submissionsrequire aconfirmationTokenminted by a matching read-onlypreview_*call, over the identical parameters (byte-for-byte, order-independent). Change the reward, the description, or the winners between preview and execute and the token will not match - the write is refused before any network call happens.It never bypasses a spending limit. A per-task cap (
TASKMARKET_MCP_MAX_TASK_REWARD_USDC) and a rolling-daily cap (TASKMARKET_MCP_MAX_DAILY_SPEND_USDC) are both enforced, and the daily total is persisted to disk so it survives a server restart.It never creates a task from untrusted content.
create_taskrequires asourcefield whose only accepted value is the literal string"user_authorized". Every other value - including a task description, a web page, or simply omitting the field - is refused, always, with no override.It never auto-accepts work. There is no tool that awards a submission without an explicit
winnerslist and a confirmation token; nothing here picks a winner on the agent's own judgment.
See src/policy.mjs for the full design rationale in comments; this file
summarizes it.
Tools
Read-only, no wallet, no cost (all hit the live public API):
Tool | Purpose |
| Browse open TaskMarket work |
| Fetch one task's live, authoritative record |
| Track/review submissions on a task |
| USDC balance for any address |
| A requester's created-vs-awarded history |
| Which wallet the CLI will sign with |
Gated writes (preview mints a token; execute consumes it):
Preview | Execute | Effect |
|
| Escrows |
|
| Pays out escrow to named winners |
|
| Marks a submission rejected (small relay fee) |
Setup
cd services/taskmarket-mcp
npm installRequires the taskmarket CLI on PATH for any write tool (read tools work
without it): npm install -g @lucid-agents/taskmarket@latest && taskmarket init.
See playbooks/taskmarket.md in the parent repo for this operator's existing
wallet, or run taskmarket init to create a fresh one.
Configuration (all optional, all have safe defaults)
Env var | Default | Meaning |
|
| Hard ceiling on a single |
|
| Rolling UTC-day ceiling across all |
|
| How long a preview's confirmation token stays valid |
|
| Where the daily spend total is persisted |
|
| REST API base (read tools) |
|
| Path to the CLI binary (write tools); point this at a stub for testing |
Running it
As an MCP server over stdio (what an MCP client launches):
node src/server.mjsExample Claude Desktop / Claude Code MCP config entry:
{
"mcpServers": {
"taskmarket": {
"command": "node",
"args": ["/absolute/path/to/services/taskmarket-mcp/src/server.mjs"],
"env": {
"TASKMARKET_MCP_MAX_TASK_REWARD_USDC": "5",
"TASKMARKET_MCP_MAX_DAILY_SPEND_USDC": "5"
}
}
}
}Reproducible demo (no money moves)
node src/server.mjsis not directly interactive; instead, drive it with any MCP client. The quickest is the test suite itself, which spins up a real client against the real stdio entrypoint:node --test test/stdio_smoke.test.mjs- lists every tool over a real child process.To see the authorization flow end to end without any client UI, run node directly against
buildServer():import { buildServer } from "./src/server.mjs"; import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js"; const server = buildServer(); // reads live TaskMarket API, writes go to $TASKMARKET_CLI const client = new Client({ name: "demo", version: "0" }); const [ct, st] = InMemoryTransport.createLinkedPair(); await Promise.all([client.connect(ct), server.connect(st)]); // 1. discover console.log(await client.callTool({ name: "search_tasks", arguments: { status: "open", limit: 3 } })); // 2. preview a task (no spend, mints a token) const preview = await client.callTool({ name: "preview_create_task", arguments: { description: "Example task", rewardUsdc: 1, durationHours: 24, source: "user_authorized", }, }); console.log(preview); // 3. execute with the token from step 2 (real spend - only run with a // funded wallet and after you actually mean to post the task)test/server_protocol.test.mjsis exactly this flow, scripted and asserted against a stub CLI so it never spends real money.
Tests
npm test # 40 tests, node's built-in test runnerWhat each file actually proves, and how:
File | What it exercises | Network / money |
| Token minting/consumption, replay refusal, param-tamper refusal, expiry, per-task and daily spend caps, source guard | None |
| The exact CLI argv built for create/award/reject, against a stub binary that records what it received (positive control) | None (stub) |
| Real reads against | Real network, read-only |
| POSTs a fully valid create-task payload to the real API with no payment and asserts the real x402 402 challenge; a broken payload gets 400, not 402 | Real network. Cannot spend: no payment is ever attached |
| The full MCP wire protocol ( | Reads hit the real API; writes go to a stub CLI |
| The literal entrypoint ( | Local process only |
Every "refused" assertion checks a specific error code
(NO_SUCH_TOKEN, PARAMS_CHANGED, TASK_CAP_EXCEEDED, DAILY_CAP_EXCEEDED,
UNAUTHORIZED_SOURCE, BAD_SHARES), not just "it threw" - and every write
test checks whether the stub CLI's recorded argv file exists, so a test
cannot pass by a refusal and a "never called" both looking the same.
Verified against the live wallet: balance before the full test run and
after was identical, 8.997335 USDC
(taskmarket wallet balance), because no test ever completes a payment - the
only real-network write test (create_task_validation.live.test.mjs)
deliberately stops at the 402 challenge.
Known gaps (disclosed, not hidden)
No native MCP elicitation. The MCP spec has an
elicitation/createcapability for a server to ask the connected client to prompt the human directly. This server does not use it, because not all current MCP clients support it. Authorization instead relies on the preview/token pattern, which is host-agnostic but does not itself prove a human clicked "yes" - it proves the exact parameters were computed by a prior read-only call and cannot be silently altered by whatever callscreate_task. A host that wants a stronger guarantee should require its own tool-use confirmation UI in front ofcreate_taskandaward_submissions.The REST API's
durationfield unit is not documented. The OpenAPI spec (https://api.taskmarket.dev/openapi.json) types it as a bare number with no unit; the CLI's own--helpsays hours. Rather than guess and risk creating a task with a wildly wrong deadline, every duration-bearing write goes through the CLI (which gets this right), andclient.mjsnever attempts to POST a create-task body itself outside of the one deliberately payment-free validation test.SpendLedgeris single-process safe, not multi-process safe. The daily spend total is a read-modify-write against a JSON file. Two server processes sharing the sameTASKMARKET_MCP_SPEND_STATE_FILEconcurrently could race past the daily cap. Run one server process per spend-state file.create_task's real end-to-end path (an actual funded task landing on chain) is not covered by an automated test in this repo, and was not run during development - the task that commissioned this build explicitly forbids spending money or funding a real task while building it. Everything up to and including the real 402 payment challenge is tested live; the signing and payment step itself is exercised only against a stub CLI. An operator who wants that last mile verified should run one small realcreate_task(e.g. 1 USDC) by hand before relying on this in production.AgentKit / Bankr / other framework-native action-provider integration is out of scope for this artifact. This is a standalone MCP server, which the target bounties explicitly accept on its own ("a usable plugin, MCP server, skill, or adapter published when the target project accepts integrations outside its core repository"). It has not been wired into Coinbase AgentKit, Bankr, or any other specific framework's plugin system, and no PR has been opened anywhere.
Not published. This package is not on npm and has no version tag beyond
0.1.0inpackage.json. Publishing was explicitly out of scope for this build pass.
License
MIT.
Available Tools
12 toolsaward_submissionsAward submissions on a TaskMarket task (pays workers)A
Pays out escrowed reward to the named winners. REQUIRES a confirmationToken from a prior, identical preview_award_submissions call. Never call this without the user having reviewed list_submissions first and explicitly picked the winner(s).
Inputs: taskId (required), winners (required), confirmationToken (required).
create_taskCreate a TaskMarket task (moves real USDC)A
Escrows rewardUsdc USDC and posts a new task. REQUIRES a confirmationToken from a prior, identical preview_create_task call - if any parameter differs from what was previewed, this is refused before any spend happens. Also enforces the per-task and rolling daily USDC caps.
Inputs: source (required), rewardUsdc (required), description (required), durationHours (required), +3 more.
get_requester_statsGet requester reputationB
How many tasks a requester has created vs actually awarded. Check this before trusting a requester's task, and before treating your own requester history as a signal to a worker.
Inputs: address (required).
get_taskGet one TaskMarket taskA
Fetch the live, authoritative record for one task by id. Always re-fetch this immediately before acting on a task - a board scan can be stale by the time a decision is made.
Inputs: taskId (required).
get_wallet_balanceGet USDC balanceA
Read-only USDC balance for any Base wallet address. Check this before quoting a spend.
Inputs: address (required).
list_submissionsList submissions for a taskC
Track and present submissions for a task you posted, for review before awarding.
Inputs: taskId (required).
preview_award_submissionsPreview awarding submissions (no spend)A
Validates the winner list (shares sum to 10000) and mints a confirmation token for award_submissions. No network write, no funds move.
Inputs: taskId (required), winners (required).
preview_create_taskPreview creating a TaskMarket task (no spend)A
Compute the cost and mint a short-lived confirmation token for create_task. Calls no network write and moves no funds. Show the returned costUsdc and expiresAt to the user before calling create_task with the same parameters plus the returned confirmationToken.
Inputs: source (required), rewardUsdc (required), description (required), durationHours (required), +2 more.
preview_reject_submissionPreview rejecting a submission (no spend)A
Mints a confirmation token for reject_submission. No network write.
Inputs: reason (required), taskId (required), worker (required).
reject_submissionReject a spam or low-quality submissionA
Marks one worker's submission rejected (small relay fee, no reward paid). REQUIRES a confirmationToken from a prior, identical preview_reject_submission call.
Inputs: reason (required), taskId (required), worker (required), confirmationToken (required).
search_tasksSearch TaskMarket tasksA
Browse open TaskMarket work. Read-only, no wallet needed, cannot spend anything. Use this before create_task to check whether delegating to a human/agent worker market is a better fit than doing the work yourself.
Inputs: mode, sort, tags, limit, +6 more.
whoamiShow the signing wallet addressA
Which wallet the underlying taskmarket CLI will sign with for any write action. Read-only.
Inputs: no named parameters.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 12 tools
Each tool targets a distinct purpose: browsing/searching tasks, fetching a single task, listing submissions, wallet/account info, and paired preview+execute write operations. The preview/execute pairs are clearly separated by the 'preview' prefix and explicit notes about no network writes, so there is no real ambiguity.
Most tools follow a consistent verb_noun snake_case pattern (e.g., search_tasks, get_task, create_task), and the preview/execute pairs use a uniform preview_<action>_<object> convention. However, 'whoami' breaks the pattern as a command-style name rather than verb_noun, so the set is not perfectly uniform.
12 tools is well within the ideal 3-15 range and each tool earns its place: 3 read/search tools, 3 wallet/account tools, 3 preview tools, and 3 execution tools. The count matches the requester-side workflow of a task marketplace without feeling bloated or thin.
The core requester lifecycle is covered: search/get tasks, create a task with cost preview, review submissions, and award or reject them. Minor gaps exist (no task update/cancel, no worker-side submission tool), but the primary marketplace operations are present and functional.
Maintenance
Related MCP Connectors
MCP server for AI agents to discover campaigns by humans and donate USDC directly on Base.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Agent-first task marketplace MCP — discover, claim, and deliver paid workspace tasks.
MCP Server for an Agent Task Marketplace
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP server that integrates the Taskmarket onchain marketplace into any MCP client, allowing agents to browse open work, fetch task details, inspect submissions, and create or submit tasks with explicit approval and a configured spending cap.MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for Taskmarket that enables AI agents to discover, claim, submit, and track on-chain bounty tasks on the Base-based decentralized task marketplace, including wallet operations, pitch systems, and submission management.134 npmMIT
- AlicenseNot gradedqualityCmaintenanceMCP server enabling AI agents to browse, claim, track, and submit work on the Taskmarket decentralized task marketplace with USDC rewards.MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for Taskmarket onchain task marketplace on Base L2. Enables AI agents to discover, browse, create, claim, and submit work to Taskmarket through natural language.MIT