Taskeristl

Centralized task tracking API/MCP server for people and agents.

You have reached the home page of the Taskeristl service. It tracks tasks across people and tools in one shared MySQL database, behind a small HTTP API and a Model Context Protocol (MCP) endpoint for LLM clients. Two front doors, one task list.

Where would you like to go?

Quick links: openapi.yaml · openapi.json · SKILL.md · healthz


What is a task?

Every task carries the following fields:

Field Type Notes
idintegerAuto-assigned. Read-only.
titlestringRequired. 1–500 characters.
ownerstringRequired. Who the task belongs to, e.g. juan.perez.
assigneestring or nullOptional. Who is currently working on it. Distinct from owner.
statusenumOne of open, in_progress, waiting, deferred, closed. Defaults to open. See Status meanings.
descriptionstring or nullFree-form long text.
labelsarray of stringsUp to 64 tags, ≤ 100 chars each.
metadataobjectArbitrary JSON for extras.
notesstring or nullFree-form notes.
is_meetingbooleanDefaults to false. Set true when a row represents a meeting rather than a unit of work.
is_starredbooleanDefaults to false. Set true to flag a task as important. Drives the starred workflow.
hoursnumber or nullEstimated units of effort in hours. null when unknown.
customerstring or nullFree-text customer this task is for. null when internal or unspecified.
created_atISO-8601 datetimeRead-only.
last_updated_atISO-8601 datetimeRead-only. Auto-updates on every content change. Not bumped by /touch.
closed_atISO-8601 datetime or nullAuto-stamped when status becomes closed; cleared on transition away. Writable on create/PATCH for backdating (must be ≤ now; only with status=closed). May be earlier than created_at for retroactive ingestion.
last_checked_atISO-8601 datetime or nullBumped to now by POST /v1/tasks/{id}/touch for polling agents to mark "I reviewed this." Writable on create/PATCH for backdating (must be ≤ now). Unlike /touch, a PATCH also bumps last_updated_at.

Status meanings

Status Meaning
openReady to be worked on; no progress yet.
in_progressSome work has been started.
waitingBlocked on action from a third party.
closedSuccessfully completed. Sets closed_at automatically.
deferredCreated for the owner but does not belong to them; no work needs to be done or tracked on it.

Workflows

Canonical filter combinations callers compose from primitives. Replace ME with the user's identifier (e.g. juan.perez).

Workflow What it answers Filters
activeOpen or in-progress tasks assigned to me.status=open,in_progress&assignee=ME
mineEverything on my plate (open + in_progress + waiting), assigned to me.status=open,in_progress,waiting&assignee=ME
triageOpen tasks I own that nobody is doing yet.status=open&owner=ME&assignee_is_null=true
waitingTasks I own that are blocked on a third party.status=waiting&owner=ME
on_othersOpen, in-progress, or waiting tasks I own that someone else is doing.status=open,in_progress,waiting&owner=ME&assignee_not=ME
closedEverything I've completed.status=closed&owner=ME
recently_closedClosed tasks I own from the last 3 workdays (caller computes cutoff).status=closed&owner=ME&closed_after=<ISO>
deferredTasks created for me but not mine to do.status=deferred&owner=ME
starredTasks I own that I've flagged as important.is_starred=true&owner=ME

The server has no concept of workdays or holidays. For recently_closed, the caller computes the ISO cutoff and passes it as closed_after.


The plain HTTP API

Authentication is one header on every request:

X-API-Key: your-key-here

Endpoints:

Method Path What it does
GET/v1/tasksList tasks. Filters: status, owner, assignee, customer, label, is_meeting, is_starred, closed_after/closed_before, updated_after/updated_before, checked_after/checked_before, plus limit and offset.
POST/v1/tasksCreate a task. Body must include title and owner.
GET/v1/tasks/{id}Fetch one task by id.
PATCH/v1/tasks/{id}Partial update. Pass null to clear nullable fields.
POST/v1/tasks/{id}/touchBump last_checked_at without changing content (no body).
DELETE/v1/tasks/{id}Permanently delete a task.
GET/v1/tasks/{id}/subtasksList a task's subtasks (ordered by seq).
POST/v1/tasks/{id}/subtasksCreate a subtask. Body must include title; seq is assigned automatically.
GET/v1/tasks/{id}/subtasks/{seq}Fetch one subtask.
PATCH/v1/tasks/{id}/subtasks/{seq}Partial update of a subtask.
DELETE/v1/tasks/{id}/subtasks/{seq}Permanently delete a subtask.

Subtasks

Large tasks can hold a checklist of subtasks: lightweight children with just a title, a simple lifecycle (open / in_progress / done), and tracking timestamps (created_at, last_updated_at, closed_at). closed_at is stamped when a subtask becomes done and cleared if reopened.

Subtasks are numbered per parentseq starts at 1 for each task and each subtask gets a display name like #43-2 (#<task-id>-<seq>). Seqs are stable: deleting one leaves a gap and never renumbers the rest. Deleting a task deletes its subtasks.

Examples

Create a task:

curl -X POST http://localhost:3000/v1/tasks \
  -H "X-API-Key: your-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Wire up the MCP client",
    "owner": "juan.perez",
    "labels": ["mcp","setup"]
  }'

List tasks you own:

curl -H "X-API-Key: your-key-here" \
  "http://localhost:3000/v1/tasks?owner=juan.perez"

Filter by label:

curl -H "X-API-Key: your-key-here" \
  "http://localhost:3000/v1/tasks?label=mcp"

Move a task forward:

curl -X PATCH http://localhost:3000/v1/tasks/42 \
  -H "X-API-Key: your-key-here" \
  -H "Content-Type: application/json" \
  -d '{"status":"in_progress","notes":"started today"}'

Transfer ownership:

curl -X PATCH http://localhost:3000/v1/tasks/42 \
  -H "X-API-Key: your-key-here" \
  -H "Content-Type: application/json" \
  -d '{"owner":"new.owner"}'

Delete:

curl -X DELETE http://localhost:3000/v1/tasks/42 \
  -H "X-API-Key: your-key-here"

The full machine-readable contract lives at /openapi.yaml (and /openapi.json). Feed it to your favorite client generator and you are off.


The MCP endpoint

Have an LLM driving the work? Point any MCP-aware client (Claude Code, Claude Desktop, custom agents) at POST /mcp. The transport is Streamable HTTP (JSON-RPC over HTTP); authentication is the same X-API-Key header used by the plain API.

The MCP server exposes seven tools:

Tool Purpose
health_checkConfirm the service is reachable.
list_tasksList tasks. Filters: status, owner, assignee, customer, label, is_meeting, is_starred, closed_after/closed_before, updated_after/updated_before, checked_after/checked_before, plus limit and offset.
get_taskFetch a single task by id.
create_taskCreate a new task. title and owner are required.
update_taskPartial update. Pass null to clear nullable fields.
touch_taskBump last_checked_at for a task without changing content.
delete_taskPermanently delete a task by id.

Wire it up — Claude Code

Add this to ~/.claude/settings.json (global) or your project's .mcp.json:

{
  "mcpServers": {
    "taskeristl": {
      "type": "http",
      "url": "http://localhost:3000/mcp",
      "headers": {
        "X-API-Key": "your-key-here"
      }
    }
  }
}

Or via the Claude Code CLI:

claude mcp add task-database \
  --transport http \
  --url http://localhost:3000/mcp \
  --header "X-API-Key: your-key-here"

Wire it up — Claude Desktop

Same JSON, dropped into the mcpServers section of:

Restart the client and the six tools above will appear in the tool catalog. Speak to them by name (or just describe what you want — the model will pick the right tool).

Tip: when the server is deployed remotely, swap http://localhost:3000 for the real address and use https:// in any non-local environment.


The Claude Skill

Want Claude to know how to drive taskeristl — the data model, the workflow filters, subtasks, backdating — without you explaining it each time? Download the Skill and drop it into your Claude skills directory. Claude loads it automatically when a task-management request comes up.

↓ Download SKILL.md

Install it as a personal skill (available across all your projects):

mkdir -p ~/.claude/skills/taskeristl
curl -s https://gkeakzm5hy.us-east-1.awsapprunner.com/SKILL.md \
  -o ~/.claude/skills/taskeristl/SKILL.md

Or commit it to a project at .claude/skills/taskeristl/SKILL.md to share it with your repo. Either way, pair it with the MCP endpoint (preferred) or the HTTP API and an X-API-Key.


Errors

All errors return JSON with this shape:

{
  "error": {
    "code": "validation_error",
    "message": "Request body failed validation",
    "details": [ ... ]
  }
}

The HTTP status code is the source of truth.

StatusMeaning
400Validation error or malformed input.
401Missing or invalid X-API-Key.
404Task id (or path) does not exist.
405Wrong method on /mcp (must be POST).
500Something exploded server-side.

Taskeristl  |  openapi.yaml · openapi.json · SKILL.md · healthz