Mariatta exposes a read-only Model Context Protocol server so your agent can check her availability without a human in the loop. No account, no API key, no secret handshake. JSON in, JSON out.
POST https://secretcodes.dev/mcp/
Content-Type: application/json
2024-11-05
{ "error": { "code": -32000, "message": "Rate limit exceeded" } }).
list_free_slots and get_busy_shadow.
Longer ranges will be available in a future paid tier — requests
over the limit return JSON-RPC error code -32602.
/.well-known/mcp.json
List the available tools:
curl -sX POST https://secretcodes.dev/mcp/ \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Ask whether a specific time is free:
curl -sX POST https://secretcodes.dev/mcp/ \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"check_availability","arguments":{"datetime":"2026-04-25T17:00:00+00:00","duration_minutes":60}}}'
Add to
~/Library/Application Support/Claude/claude_desktop_config.json
(macOS) or the equivalent on Windows/Linux, then restart Claude
Desktop:
{
"mcpServers": {
"mariatta-availability": {
"url": "https://secretcodes.dev/mcp/"
}
}
}
claude mcp add mariatta-availability https://secretcodes.dev/mcp/
For interactive debugging:
npx @modelcontextprotocol/inspector
Point it at the endpoint URL, transport HTTP.
check_availability
"Is this specific time free?"
datetime (string, required) — ISO 8601 with timezone
duration_minutes (integer, default 30)
Returns
{ "free": bool, "band": "business" | "extended" | null, "reason": string | null }.
When free is false, band is
null and reason explains why
("Busy", "Outside business/extended hours",
"Spans multiple days").
list_free_slots
"Find open slots in a date range."
start, end (strings, required) — ISO 8601
duration_minutes (integer, default 30)
include_extended (boolean, default false)
— set true to also return early-morning / evening
extended-hour slots
Returns
{ "slots": [{ "start", "end", "band" }], "business_slot_count": int, "connected": bool }.
Slots are sorted chronologically. band is
"business" or "extended". Max
range 14 days.
get_busy_shadow
"Raw busy blocks from Mariatta's calendars in a date range." Returns only start/end timestamps — never event titles, attendees, locations, or descriptions.
start, end (strings, required)
Returns { "busy_blocks": [{ "start", "end" }], "connected": bool }.
Max range 14 days.
get_booking_info
Currently stubbed. Returns
{ "available": false, "message": "..." }. Will fill in
when a paid-booking layer lands.
Every successful tools/call response has this outer shape:
{
"jsonrpc": "2.0",
"id": <your request id>,
"result": {
"content": [
{ "type": "text", "text": "<JSON-encoded tool result>" }
]
}
}
The inner text field is a JSON string of the tool's
actual return value — parse it as JSON on your end. This matches the
MCP spec's content array convention.
Errors follow JSON-RPC 2.0:
{ "jsonrpc": "2.0", "id": ..., "error": { "code": -32602, "message": "..." } }
Standard codes: -32700 parse error,
-32601 method not found, -32602 invalid
params (including unknown tool name), -32603 internal
error.
Upstream Google Calendar freeBusy responses are cached
server-side for 5 minutes. Please cache on your end where possible.
Don't poll more frequently than the upstream cache would refresh.
The endpoint only returns free/busy timestamps — no event titles, attendees, descriptions, or other details. Full details in the Privacy Policy.
Open an issue at github.com/Mariatta/secretcodes/issues.