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
| Tool | Parameters | Description |
|---|---|---|
get_schedule | workspace_id, weeks? | List posts scheduled in the next N weeks (default 2) |
get_schedule
get_schedule(workspace_id: str, weeks: int = 2) -> strReturns 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.