- Server name:
tasksync-server - Version:
1.0.0 - Transport: Streamable HTTP MCP
- Feedback storage: session-scoped, file-backed minimal metadata
Waits for feedback text for the current MCP session.
Behavior:
- If queued feedback exists for the session, returns immediately.
- Otherwise blocks until new feedback arrives.
- Default: waits indefinitely with SSE keepalive (
: keepalive\n\nevery 30s). - Heartbeat mode (
--heartbeat): returns[WAITING]on timeout (--timeout=<ms>).
Response format:
- Text-only feedback:
{ content: [{ type: "text", text: "..." }] } - With images:
{ content: [{ type: "text", text: "..." }, { type: "image", data: "<base64>", mimeType: "image/png" }, ...] } - Images are returned as MCP
ImageContentblocks per the MCP specification. - Image-only submissions (no text) omit the text block.
POST /mcpGET /mcpDELETE /mcpGET /health
Session semantics:
- Client initializes without
mcp-session-id. - Server issues a human-readable session ID (e.g.,
opencode-1,copilot-3) derived from the client name and a monotonic counter. - Client sends
mcp-session-idon subsequent requests. - Temporary stream reconnects can recover while the server process remains alive.
- Stale session IDs from before a server restart are still rejected; continuity is provided via fresh initialize plus reassociated persisted state.
- Sessions inactive for >4 hours (and not currently waiting) are auto-pruned every 5 minutes.
GET /GET /session/:sessionIdGET /feedback/history?sessionId=<id>POST /feedbackbody:{ "content": string, "images"?: [{ "data": string, "mimeType": string }], "sessionId"?: string }GET /sessionsPOST /sessions/defaultbody:{ "sessionId": string }POST /sessions/activebody:{ "sessionId": string }(legacy alias)POST /sessions/:sessionId/aliasbody:{ "alias": string }(empty alias clears custom name)POST /sessions/prune— removes sessions inactive for >1 hourDELETE /sessions/:sessionId
These endpoints support external clients (e.g., the OpenCode plugin) that connect via HTTP instead of MCP.
Register an external session.
Request body:
{ "sessionId": "my-session-1", "alias": "My Agent" }Response:
{ "ok": true, "sessionId": "my-session-1" }Idempotent — returns ok if session already exists. Creates a session without MCP transport.
Long-poll for feedback. Blocks until feedback is submitted or client disconnects.
Auto-registers the session if it doesn't exist.
Response (feedback received):
{ "type": "feedback", "content": "user's feedback text", "images": [] }Response (session closed):
{ "type": "closed", "reason": "Session deleted" }Behavior:
- If queued feedback exists, returns immediately
- Otherwise blocks until feedback is submitted via the web UI
- Client abort (e.g.,
AbortController.abort()) cancels the wait cleanly - No keepalive needed (designed for localhost use)
GET /sessions response fields per session include:
sessionId: canonical MCP session ID (human-readable, e.g.,opencode-1)alias: optional display label (manual alias or inferred initialize metadata)sessionUrl,createdAt,lastActivityAt,waitingForFeedback,waitStartedAt,hasQueuedFeedback
GET /feedback/history returns:
sessionId: normalized session ID used for the lookuphistory: array of submitted user feedback entries{ role, content, createdAt, images? }images(optional): array of{ data: string (base64), mimeType: string }when images were attached
--port=<port>: MCP Streamable HTTP port (default3011)--ui-port=<port>: feedback UI port (default3456)--timeout=<ms>: feedback wait timeout (0blocks forever)--no-ui: disable feedback UI
- Local persisted state path:
.tasksync/session-state.json - Persisted state includes queued/latest feedback, bounded submitted feedback history (including image attachments), session metadata, alias metadata, and active UI session.
- Live transport objects, MCP server instances, waiter resolver closures, and replay-event history are not persisted to the session file.
- On wide screens, the UI shows feedback composer/history on the left and sessions/settings in a right sidebar.
- The current session view includes latest feedback text plus submitted feedback history for that session.
- Image attachments: paste, drag-drop, or file picker. Max 10 images, 10 MB each. Supported: PNG, JPEG, GIF, WebP, SVG.
- Images are base64-encoded in the browser and sent in the
imagesarray ofPOST /feedback. - Express JSON body limit is 50 MB to accommodate base64 image payloads.