sync-day
Free no-signup group scheduling; share a link and rank times by who's free.
Should I use this
Quality & Safety
Based on automated analysis of tool definitions and protocol compliance.
Context Cost
This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.
Install
One-Click Install
Add this to your `claude_desktop_config.json` file:
{
"mcpServers": {
"sync-day": {
"url": "https://sync.day/mcp/mcp"
}
}
}Remote endpoints
https://sync.day/mcp/mcpstreamable-httpWhat it can do
Tool inventory
Tools (8)
đ´create_event(title, question, startDate, endDate, days, ...)
Create a sync.day availability poll and get its share link. Candidate days run from startDate to endDate (inclusive; or give days instead). Each day offers candidate START times from hourFrom, every startStepMinutes, as long as start + durationMinutes <= hourTo. Returns slug, public url (share this), adminUrl and adminKey (keep private; needed for update_event / remove_participant). Example: ĺ¨ĺ ĺ¨ćĽä¸ĺčé¤ 3 ĺ°ćś -> {title:'ĺ¨ćŤčé¤', startDate:'2026-09-05', endDate:'2026-09-06', hourFrom:13, hourTo:18, durationMinutes:180, startStepMinutes:60}.
Input Schema
{
"type": "object",
"properties": {
"title": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"description": "Event name, max 60 chars. e.g. ĺ¨ćŤčé¤, Team sync"
},
"question": {
"description": "Optional prompt shown to participants, max 200 chars. e.g. ĺŞĺ¤Šćä¸ć犺ďź",
"type": "string",
"maxLength": 200
},
"startDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First candidate day, YYYY-MM-DD. e.g. 2026-09-05"
},
"endDate": {
"description": "Last candidate day, inclusive, YYYY-MM-DD (same as startDate for a single day; at most 21 days). Give this or days; endDate wins when both are set.",
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"days": {
"description": "Number of consecutive days from startDate (1-21); alternative to endDate.",
"type": "integer",
"minimum": 1,
"maximum": 21
},
"hourFrom": {
"type": "integer",
"minimum": 0,
"maximum": 23,
"description": "Earliest hour of each day (0-23). e.g. 9"
},
"hourTo": {
"type": "integer",
"minimum": 1,
"maximum": 24,
"description": "End of each day's window, exclusive (1-24), must be > hourFrom. e.g. 22"
},
"durationMinutes": {
"anyOf": [
{
"type": "number",
"const": 30
},
{
"type": "number",
"const": 60
},
{
"type": "number",
"const": 90
},
{
"type": "number",
"const": 120
},
{
"type": "number",
"const": 180
},
{
"type": "number",
"const": 240
},
{
"type": "number",
"const": 480
}
],
"description": "Event length in minutes. One of 30, 60, 90, 120, 180, 240, 480."
},
"startStepMinutes": {
"default": 60,
"anyOf": [
{
"type": "number",
"const": 30
},
{
"type": "number",
"const": 60
}
],
"description": "Gap between candidate start times in minutes: 30 or 60 (default 60)."
}
},
"required": [
"title",
"startDate",
"hourFrom",
"hourTo",
"durationMinutes"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}đ˘parse_event_text(text, today)
Turn a natural-language sentence (Chinese works best) into create_event input using sync.day's AI parser. Does NOT create anything; review the result, then call create_event. Example: 'ä¸ĺ¨ĺ ćĺ¨ćĽä¸ĺčé¤ďźĺ¤§ćŚ 3 ĺ°ćś'.
Input Schema
{
"type": "object",
"properties": {
"text": {
"type": "string",
"minLength": 1,
"maxLength": 300,
"description": "One sentence describing the event, max 300 chars."
},
"today": {
"description": "Reference date for relative words like ć夊/ä¸ĺ¨, YYYY-MM-DD. Defaults to today in Asia/Shanghai.",
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
}
},
"required": [
"text"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}đ˘get_event(slug)
Read an event: settings, every candidate start key per day (startOptions), who has answered (participants with their start keys; names may repeat), the top 10 start times by head-count (ranked), the starts EVERYONE with picks can make with their votes (voteOptions), each person's vote (votes) and decidedStart. No key needed.
Input Schema
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"pattern": "^(?:[a-z]{3,7}-[a-z]{3,7}(?:-\\d{2}|-\\d{4})?|[A-Za-z0-9_-]{10})$",
"description": "Event slug from the URL, e.g. calm-otter-4821 (sync.day/calm-otter-4821)"
}
},
"required": [
"slug"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}đĄsubmit_availability(slug, identity, name, starts)
Save (or replace) one person's availability: the candidate start keys they can make, from get_event.startOptions. The person is identified by `identity`, not by name: the same identity later overwrites the same row (and can rename it), a different identity with the same name is a second participant. Keys outside the event's start options are rejected. Returns the updated ranking.
Input Schema
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"pattern": "^(?:[a-z]{3,7}-[a-z]{3,7}(?:-\\d{2}|-\\d{4})?|[A-Za-z0-9_-]{10})$",
"description": "Event slug from the URL, e.g. calm-otter-4821 (sync.day/calm-otter-4821)"
},
"identity": {
"type": "string",
"minLength": 16,
"maxLength": 256,
"description": "Random secret for this person that you generate and keep per person, 16-256 chars (e.g. 32 hex chars; NOT a plain user id or name, since anyone who guesses it can act as them). Same identity = same participant; the server stores only a hash. Example: 3f9a1c77b2e04d5e8a61f0c9d2b7e415"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 20,
"description": "Display name, 1-20 chars, may repeat. e.g. ĺ°ć"
},
"starts": {
"maxItems": 1008,
"type": "array",
"items": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$"
},
"description": "Start keys like 2026-09-05T14:00. Empty array clears this person's picks."
}
},
"required": [
"slug",
"identity",
"name",
"starts"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}đ´remove_participant(slug, name, adminKey)
Organiser only: remove one participant by name (the oldest row with that name when it repeats), together with their vote. Requires the adminKey from create_event.
Input Schema
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"pattern": "^(?:[a-z]{3,7}-[a-z]{3,7}(?:-\\d{2}|-\\d{4})?|[A-Za-z0-9_-]{10})$",
"description": "Event slug from the URL, e.g. calm-otter-4821 (sync.day/calm-otter-4821)"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 20,
"description": "Exact participant name to remove."
},
"adminKey": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{12}(?:[A-Za-z0-9_-]{12})?$",
"description": "Organiser key returned by create_event (the ?key= part of adminUrl)."
}
},
"required": [
"slug",
"name",
"adminKey"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}đĄupdate_event(slug, adminKey, title, question, startDate, ...)
Organiser only: change any event settings (same fields and rules as create_event; omitted fields keep their current value; endDate wins over days). Existing picks are kept; those no longer valid starts are just hidden.
Input Schema
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"pattern": "^(?:[a-z]{3,7}-[a-z]{3,7}(?:-\\d{2}|-\\d{4})?|[A-Za-z0-9_-]{10})$",
"description": "Event slug from the URL, e.g. calm-otter-4821 (sync.day/calm-otter-4821)"
},
"adminKey": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{12}(?:[A-Za-z0-9_-]{12})?$",
"description": "Organiser key returned by create_event (the ?key= part of adminUrl)."
},
"title": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"description": "Event name, max 60 chars. e.g. ĺ¨ćŤčé¤, Team sync"
},
"question": {
"description": "Optional prompt shown to participants, max 200 chars. e.g. ĺŞĺ¤Šćä¸ć犺ďź",
"type": "string",
"maxLength": 200
},
"startDate": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First candidate day, YYYY-MM-DD. e.g. 2026-09-05"
},
"endDate": {
"description": "Last candidate day, inclusive, YYYY-MM-DD (same as startDate for a single day; at most 21 days). Give this or days; endDate wins when both are set.",
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"days": {
"description": "Number of consecutive days from startDate (1-21); alternative to endDate.",
"type": "integer",
"minimum": 1,
"maximum": 21
},
"hourFrom": {
"type": "integer",
"minimum": 0,
"maximum": 23,
"description": "Earliest hour of each day (0-23). e.g. 9"
},
"hourTo": {
"type": "integer",
"minimum": 1,
"maximum": 24,
"description": "End of each day's window, exclusive (1-24), must be > hourFrom. e.g. 22"
},
"durationMinutes": {
"anyOf": [
{
"type": "number",
"const": 30
},
{
"type": "number",
"const": 60
},
{
"type": "number",
"const": 90
},
{
"type": "number",
"const": 120
},
{
"type": "number",
"const": 180
},
{
"type": "number",
"const": 240
},
{
"type": "number",
"const": 480
}
],
"description": "Event length in minutes. One of 30, 60, 90, 120, 180, 240, 480."
},
"startStepMinutes": {
"default": 60,
"anyOf": [
{
"type": "number",
"const": 30
},
{
"type": "number",
"const": 60
}
],
"description": "Gap between candidate start times in minutes: 30 or 60 (default 60)."
}
},
"required": [
"slug",
"adminKey"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}đĄvote_time(slug, identity, starts, start)
Approval voting: set every start one person accepts (replaces their earlier approvals; an empty list clears them). The voter is the `identity` used in submit_availability and must have at least one start saved. Only keys listed in get_event.voteOptions are accepted; the error lists the current options otherwise. Rejected once the organiser decided. Example: {slug:'calm-otter-4821', identity:'3f9a1c77b2e04d5e8a61f0c9d2b7e415', starts:['2026-09-05T15:00','2026-09-06T10:00']}. `start` is shorthand for a single-item `starts`.
Input Schema
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"pattern": "^(?:[a-z]{3,7}-[a-z]{3,7}(?:-\\d{2}|-\\d{4})?|[A-Za-z0-9_-]{10})$",
"description": "Event slug from the URL, e.g. calm-otter-4821 (sync.day/calm-otter-4821)"
},
"identity": {
"type": "string",
"minLength": 16,
"maxLength": 256,
"description": "Random secret for this person that you generate and keep per person, 16-256 chars (e.g. 32 hex chars; NOT a plain user id or name, since anyone who guesses it can act as them). Same identity = same participant; the server stores only a hash. Example: 3f9a1c77b2e04d5e8a61f0c9d2b7e415"
},
"starts": {
"description": "All start keys this person accepts (from get_event.voteOptions); [] clears their approvals",
"maxItems": 500,
"type": "array",
"items": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$",
"description": "Start key, e.g. 2026-09-05T15:00"
}
},
"start": {
"description": "Shorthand for starts: [start]",
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$"
}
},
"required": [
"slug",
"identity"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}đĄdecide_time(slug, adminKey, start)
Organiser only: settle on a start time (locks availability picking and voting; the page shows 塲ĺŽ). Pass start=null to reopen. Requires the adminKey from create_event.
Input Schema
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"pattern": "^(?:[a-z]{3,7}-[a-z]{3,7}(?:-\\d{2}|-\\d{4})?|[A-Za-z0-9_-]{10})$",
"description": "Event slug from the URL, e.g. calm-otter-4821 (sync.day/calm-otter-4821)"
},
"adminKey": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{12}(?:[A-Za-z0-9_-]{12})?$",
"description": "Organiser key returned by create_event (the ?key= part of adminUrl)."
},
"start": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$"
},
{
"type": "null"
}
],
"description": "A candidate start key of the event (normally one of voteOptions), or null to reopen."
}
},
"required": [
"slug",
"adminKey",
"start"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}Community
Evidence