MCP / AI
Schedule MCP Tools

Schedule MCP Tools

One read-only tool gives an AI client (Claude Desktop, Claude Code, or any MCP-speaking assistant) visibility into a workspace's near-term publishing schedule — every scheduled post whose slot falls within a configurable lookahead window. There is no MCP tool to create or move a schedule slot; use the REST API (POST /api/posts/{id}/schedule) or the app's Schedule page for writes.

For the underlying scheduling model (weekly slots, auto-scheduling, reminders, Zoho Social handoff), see Features — Scheduling & Publishing and Features — Posts § Publish. This page is based on specs/mcp/schedule.md in the repo — see that spec for the exact JSON shape and DynamoDB access pattern behind the tool.

Access model

Like the Posts MCP tools, every call is scoped to a workspace_id and enforces membership with a direct DynamoDB lookup on WS#{workspace_id} / MEMBER#{user_id}. If the authenticated MCP user isn't a member, the tool raises and the client sees a tool error, not an empty result. Unlike the REST /schedule and /publish actions (which require an author/editor/owner/member role), get_schedule has no additional role gate — any workspace member, including viewer, can call it.

⚠️

The tool returns a JSON string, not a structured object — parse it before use, same as every other lkwiz_mcp tool.

Tools

ToolParametersDescription
get_scheduleworkspace_id, weeks?List posts scheduled in the next N weeks (default 2)

get_schedule

get_schedule(workspace_id: str, weeks: int = 2) -> str

Returns every post in status = "scheduled" whose scheduled_at falls between now and now + weeks weeks, sorted ascending by scheduled_at.

{
  "workspace_id": "ws_123",
  "from": "2026-07-17T10:00:00+00:00",
  "until": "2026-07-31T10:00:00+00:00",
  "scheduled_posts": [
    {
      "post_id": "post_abc",
      "workspace_id": "ws_123",
      "title": "Why observability matters",
      "status": "scheduled",
      "scheduled_at": "2026-07-20T09:00:00+00:00"
    }
  ]
}

scheduled_posts entries are a reduced projection — only post_id, workspace_id, title, status, scheduled_at. Fields not present on the underlying DynamoDB item render as "" rather than being omitted. An empty window returns "scheduled_posts": [], not an error.

weeks is not validated or clamped — passing 0 or a negative number produces an empty or inverted window instead of a rejection.

⚠️

This tool hand-rolls its own query — it does not reuse posts_service or scheduler_service. It runs a Query on the workspace's own partition key (pk = WS#{workspace_id}, sk prefix POST#) and applies a DynamoDB FilterExpression for status = "scheduled" and the date window. A FilterExpression is evaluated after DynamoDB reads the item, so this reads (and is billed for) every post in the workspace, not just the scheduled ones in range. The daily EventBridge scheduler job instead queries the purpose-built GSI2 index (gsi2pk = "SCHED#PENDING", gsi2sk = scheduled_at) for the same kind of date-range lookup — get_schedule is a separate, less efficient code path that happens to read the same underlying data.

⚠️

No pagination. The tool reads a single DynamoDB Query page and does not follow LastEvaluatedKey. A workspace with enough posts to exceed one page (~1 MB) can get a silently incomplete scheduled_posts list, with no truncation signal in the response. This is a known gap shared with the other hand-rolled query tools in lkwiz_mcp (list_posts, get_pipeline_status — see MCP — Posts).

⚠️

Lexical date comparison. The BETWEEN filter on scheduled_at is a string comparison, not a temporal one. It only works because every writer of scheduled_at in this codebase uses datetime.isoformat() with a +00:00 UTC offset, which happens to sort identically to chronological order. This is an implementation detail, not a documented guarantee.