I don't know how this works
Here's everything this connector tells your AI and every action it can take, explained three ways. Pick your depth.
Claude and ChatGPT can use “connectors”: small services that let them do things for you. This is one. It lets your AI read the Edge City calendar and, if you allow it, RSVP or host events for you.
When you ask “what's on tonight?”, your AI doesn't guess. It asks this connector, which asks the Edge City system (EdgeOS) as you, and passes back the real list.
We also give the AI a short set of house rules. The main ones: never make things up, always use India time, and never change anything, like an RSVP, until you've seen exactly what will happen and said yes. Every word of those rules is in the “Technical” tab. Nothing is hidden.
Your EdgeOS key stays locked the whole time. See How is this safe?
flowchart LR You -->|"what's on tonight?"| AI[Your AI] AI -->|asks, following our house rules| Us[This connector] Us -->|as you| EdgeOS EdgeOS -->|real events| Us Us -->|events in India time| AI AI -->|answer| You
flowchart LR A[You: RSVP me to the breathwork] --> B[AI asks us to check it] B --> C[We check: full? clashing? already over?] C --> D[AI shows you the exact summary and any warnings] D -->|you say yes| E[Only then is the RSVP made] D -->|you say no| F[Nothing happens]
A connector gives an AI three kinds of things. Here is what ours contains.
1. Instructions
Text the AI reads so it behaves well, in four layers from always-on to on-demand:
- Server instructions: a few lines every AI app receives when it connects.
- Start-here tool (
edgeos_initialize): the AI calls it first. It says today's date in India time, what your key allows, the rules, and which tools to use. Because it arrives as the latest tool result, the rules stay fresh in long chats. - Guides (
edgeos_guide): deeper notes on one topic (schedule, recurring events, RSVPs, hosting, venues, limits) plus the exact EdgeOS fields, generated from EdgeOS's own published API description. - Nudges at the moment of action: when the AI proposes a change, our reply carries the summary to show you, any warnings, the matching guideline, and the instruction to wait for your yes.
2. Tools
Actions the AI can take. You only get the ones your key allows.
edgeos_list_events: List published events in an India-date window, grouped by day, with IST times, venue, and the attendee's RSVP status.edgeos_get_event: One event in full: description, IST time, place, host, attendee count and the attendee's RSVP status.edgeos_calendar_summary: How many published events fall on each India day in a window.edgeos_list_participants: People who RSVPed to one event. The host and attendees who hide their name aren't listed. For a recurring event pass occurrence_start.edgeos_rsvp_eligibility: Whether this attendee is allowed to RSVP to events in the popup, and why not if they can't.edgeos_list_invitations: Invitations on an event the attendee hosts.edgeos_list_tracks: The popup's programme tracks.edgeos_track_events: Events in one programme track, with IST times.edgeos_list_venues: Active venues in the popup with capacity and location.edgeos_venue_availability: Open hours and busy slots for one venue on India dates, in IST.get_more_tools: Check for additional tools whenever your task might benefit from specialized capabilities - even if existing tools could work as a fallback.edgeos_proposethenedgeos_confirm: every change, in two steps. Changes available: rsvp, cancel_rsvp, create_event, update_event, cancel_event, hide_event, unhide_event, invite, remove_invitation, create_venue, update_venue, delete_venue.
3. Prompts
Ready-made starting points you can pick in your AI app: What's on today, Plan my week, Host an event.
The checks before any change
- Stops it (rsvp, cancel_rsvp, update_event, cancel_event, hide_event, unhide_event, invite, remove_invitation): The event must exist and be visible to the attendee.
- Stops it (rsvp, cancel_rsvp): A recurring event needs one occurrence picked, and that occurrence must exist.
- Stops it (rsvp, cancel_rsvp): The event must not be over.
- Stops it (rsvp): The attendee must not already be RSVPed, and EdgeOS must say they're eligible.
- Warns (rsvp): The event looks full, or the host approves each RSVP.
- Warns (rsvp): It overlaps another event the attendee already RSVPed to that day.
- Stops it (cancel_rsvp): The attendee must currently be RSVPed.
- Stops it (create_event, update_event): When a start or end time is given: it must end after it starts, and a new start time must be in the future. For an update, this runs only if the start or end time is being changed, so a running event's end can be extended.
- Stops it (create_event, update_event): When a venue is chosen (or the venue or times change on an update), the venue must be free then, by EdgeOS's availability check.
- Warns (create_event, update_event): When a start or end time is given: it starts between midnight and 6 AM IST (likely a UTC mix-up), is shorter than 15 minutes or longer than 6 hours, or falls outside the popup's dates.
- Warns (create_event, update_event): There is no description, or no venue or place.
- Warns (create_event, update_event, create_venue, update_venue): Optional second-model review against the hosting or venue guidelines, when enabled; its notes are labelled as a second opinion.
- Warns (cancel_event, hide_event, unhide_event, invite, remove_invitation): The event is already over.
- Warns (cancel_event): People have RSVPed; the attendee should tell them.
- Warns (invite): More than 20 invitations at once. The summary lists the email addresses (the first 20, then a count).
- Warns (delete_venue): Events in the next 60 days use the venue.
- Rule (every change): How confirming works: the proposal code expires after 10 minutes, works only for the attendee who proposed it (it is bound to a hash of their key), and carries the exact change, so nothing can be swapped before confirming. Confirm it once: a repeated confirm repeats the change.
Where the instructions come from
Field names and allowed values come from EdgeOS's published API description (OpenAPI, version 0.1.0), saved in the repo and checked daily; if EdgeOS changes, a pull request shows exactly what changed. The house rules and guides are written by us and live in the guides/ folder.
Everything below is rendered from the running code, not copied by hand. Source: github.com/Nhajela/eci-events-mcp. Design spec: docs/superpowers/specs/2026-10-06-eci-events-mcp-design.md.
This page reflects this deployment's configuration; it is rebuilt on every deploy and refreshed hourly.
Protocol
Streamable HTTP at /api/mcp, MCP 2026-07-28 (stateless, no session), with 2025-11-25 clients served by the SDK's legacy handling. A fresh McpServer is built per request for the caller's scopes. Auth is OAuth 2.1 with PKCE S256, CIMD and DCR clients, and sealed JWE tokens; see /trust.
Server instructions (sent on connect)
You help an Edge City India 2026 attendee (Mandrem, Goa, 11 Oct – 1 Nov 2026) use the EdgeOS events calendar: find events, RSVP, host events and manage venues, as far as their own EdgeOS key allows. RULES: 1. Never fabricate. If a tool didn't return it, say you don't know. 2. Show every time in India time (IST, Asia/Kolkata). Never read a UTC time out as local. 3. Every change goes through edgeos_propose, then edgeos_confirm only after the attendee explicitly says yes to the summary. 4. Never ask the attendee to paste their EdgeOS key into the chat. Keys are entered only on this server's connect page. Call edgeos_initialize first. It tells you what this attendee can do today.
edgeos_initialize output for a sample attendee with every scope, at Wed 14 Oct, 11:30 AM IST
# Edge City India (2026-10-11 to 2026-11-01) Now: Wed 14 Oct, 11:30 AM IST This key can: events:read, rsvp:write, events:write, venues:write ## Rules 1. Never fabricate. If a tool didn't return it, say you don't know. 2. Times are India time (IST). Tools already convert; quote them as given. 3. Every change goes through `edgeos_propose`, then `edgeos_confirm` only after an explicit yes to the summary. 4. Never ask for the attendee's EdgeOS key in chat. 5. For depth on any area, call `edgeos_guide` with a topic: hosting, limits, recurring, rsvp, schedule, venues. ## Schedule (read) - `edgeos_list_events`: events for India dates (`from` YYYY-MM-DD, `days` 1–31, default next 7 days). Filters: search, tags, kind, venue_id, track_ids, mine (my RSVPs), managed (events I host), highlighted_only. - `edgeos_get_event`: one event with description, host, attendee count and my RSVP status. Pass `occurrence_start` for one occurrence of a recurring event. - `edgeos_calendar_summary`: how many events per day. - `edgeos_list_participants`: who is going to one event (host and hidden attendees aren't listed). - `edgeos_rsvp_eligibility`: whether this attendee may RSVP at all. - `edgeos_list_tracks`, `edgeos_track_events`: programme tracks. - `edgeos_list_venues`, `edgeos_venue_availability`: places and when they're free. - `edgeos_list_invitations`: invitations on an event the attendee hosts. Times come back in IST already. Quote them as given. ## Making changes Every change is two steps: 1. `edgeos_propose` with `action` and `params`. Actions on this key: `rsvp`, `cancel_rsvp`, `create_event`, `update_event`, `cancel_event`, `hide_event`, `unhide_event`, `invite`, `remove_invitation`, `create_venue`, `update_venue`, `delete_venue`. 2. Show the attendee the summary word for word and raise each warning. Only after an explicit yes, call `edgeos_confirm` with the proposal code. Times you send must carry an offset, e.g. 2026-10-14T18:30:00+05:30. ## Not available here EdgeOS doesn't let API keys reach these, so say so and point to the Edge City portal: messages to attendees, check-in and attendance, the attendee directory, anyone's profile, admin notes. EdgeOS has no recordings or transcripts.
Tools exactly as the AI receives them (15)
edgeos_initialize · read-only
Call first in every conversation. Returns today's date in IST, what this attendee's key allows, the rules, and which tools to use.
{
"inputSchema": {
"type": "object",
"properties": {
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true
}
}edgeos_guide · read-only
Detailed guidance plus the EdgeOS field reference for one area: hosting, limits, recurring, rsvp, schedule, venues.
{
"inputSchema": {
"type": "object",
"properties": {
"topic": {
"type": "string",
"enum": [
"hosting",
"limits",
"recurring",
"rsvp",
"schedule",
"venues"
],
"description": "Which area."
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"topic",
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true
}
}edgeos_list_events · read-only
List published events in an India-date window, grouped by day, with IST times, venue, and the attendee's RSVP status.
{
"inputSchema": {
"type": "object",
"properties": {
"from": {
"description": "First India date, YYYY-MM-DD. Defaults to today in IST.",
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"days": {
"description": "Number of days, default 7.",
"type": "integer",
"minimum": 1,
"maximum": 31
},
"search": {
"description": "Words in the title.",
"type": "string"
},
"tags": {
"description": "Match any of these tags.",
"type": "array",
"items": {
"type": "string"
}
},
"kind": {
"type": "string"
},
"venue_id": {
"type": "string"
},
"track_ids": {
"type": "array",
"items": {
"type": "string"
}
},
"mine": {
"description": "Only events this attendee RSVPed to.",
"type": "boolean"
},
"managed": {
"description": "Only events this attendee hosts or co-hosts.",
"type": "boolean"
},
"highlighted_only": {
"description": "Only events organisers featured.",
"type": "boolean"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true
}
}edgeos_get_event · read-only
One event in full: description, IST time, place, host, attendee count and the attendee's RSVP status.
{
"inputSchema": {
"type": "object",
"properties": {
"event_id": {
"type": "string",
"minLength": 1
},
"occurrence_start": {
"description": "For a recurring event, the occurrence's start_time exactly as listed.",
"type": "string"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"event_id",
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true
}
}edgeos_calendar_summary · read-only
How many published events fall on each India day in a window.
{
"inputSchema": {
"type": "object",
"properties": {
"from": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"days": {
"type": "integer",
"minimum": 1,
"maximum": 31
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true
}
}edgeos_list_participants · read-only
People who RSVPed to one event. The host and attendees who hide their name aren't listed. For a recurring event pass occurrence_start.
{
"inputSchema": {
"type": "object",
"properties": {
"event_id": {
"type": "string",
"minLength": 1
},
"occurrence_start": {
"type": "string"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"event_id",
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true
}
}edgeos_rsvp_eligibility · read-only
Whether this attendee is allowed to RSVP to events in the popup, and why not if they can't.
{
"inputSchema": {
"type": "object",
"properties": {
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true
}
}edgeos_list_invitations · read-only
Invitations on an event the attendee hosts.
{
"inputSchema": {
"type": "object",
"properties": {
"event_id": {
"type": "string",
"minLength": 1
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"event_id",
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true
}
}edgeos_list_tracks · read-only
The popup's programme tracks.
{
"inputSchema": {
"type": "object",
"properties": {
"search": {
"type": "string"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true
}
}edgeos_track_events · read-only
Events in one programme track, with IST times.
{
"inputSchema": {
"type": "object",
"properties": {
"track_id": {
"type": "string",
"minLength": 1
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"track_id",
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true
}
}edgeos_list_venues · read-only
Active venues in the popup with capacity and location.
{
"inputSchema": {
"type": "object",
"properties": {
"search": {
"type": "string"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true
}
}edgeos_venue_availability · read-only
Open hours and busy slots for one venue on India dates, in IST.
{
"inputSchema": {
"type": "object",
"properties": {
"venue_id": {
"type": "string",
"minLength": 1
},
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"days": {
"type": "integer",
"minimum": 1,
"maximum": 7
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"venue_id",
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true
}
}edgeos_propose · read-only
Check a change before making it. Returns a summary to show the attendee, warnings, the guideline for this action, and a proposal code for edgeos_confirm. Actions: rsvp, cancel_rsvp, create_event, update_event, cancel_event, hide_event, unhide_event, invite, remove_invitation, create_venue, update_venue, delete_venue. Use edgeos_guide for the fields each takes.
{
"inputSchema": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"rsvp",
"cancel_rsvp",
"create_event",
"update_event",
"cancel_event",
"hide_event",
"unhide_event",
"invite",
"remove_invitation",
"create_venue",
"update_venue",
"delete_venue"
]
},
"params": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {},
"description": "Fields for the action, e.g. { event_id } for rsvp."
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"action",
"params",
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true
}
}edgeos_confirm · makes changes
Carry out a proposal after the attendee explicitly said yes. Takes the proposal code from edgeos_propose.
{
"inputSchema": {
"type": "object",
"properties": {
"code": {
"type": "string",
"minLength": 10
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"code",
"context",
"llm_model"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"annotations": {
"destructiveHint": true,
"openWorldHint": true
}
}get_more_tools · read-only
Check for additional tools whenever your task might benefit from specialized capabilities - even if existing tools could work as a fallback.
{
"inputSchema": {
"type": "object",
"properties": {
"context": {
"type": "string",
"description": "A description of your goal and what kind of tool would help accomplish it."
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"conversation_id": {
"type": "string",
"description": "Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
}
},
"required": [
"context",
"llm_model"
]
},
"annotations": {
"title": "Get More Tools",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": true
}
}Proposal steering (added to every proposal reply)
Show the attendee the summary above, word for word, and raise each warning. Call `edgeos_confirm` only after they explicitly say yes. If they change anything, call `edgeos_propose` again with the new details. Call edgeos_confirm once per proposal; a repeated confirm repeats the change.
Second-model reviewer rubric (event and venue proposals, when enabled)
You review a proposed change to a community event calendar for Edge City India (a 3-week residential village in Goa) before an AI assistant asks the attendee to confirm it.
Judge it only against the guidelines below. Return JSON {"notes": string[]} with at most 4 short, specific, actionable notes the assistant should raise with the attendee. Return {"notes": []} if it's fine. Don't restate the proposal. Don't invent facts.The reviewer runs only when the operator has configured a reviewer model (REVIEWER_MODEL and Vertex AI credentials). It is a Gemini model on Vertex AI and receives this rubric, the hosting or venues guide, and the proposal's fields. Never sent: keys or attendee lists. If the reviewer is configured but can't run (an error or a timeout), the proposal still goes ahead and the AI is told:
The second-opinion review couldn't run this time.
Prompts (3)
whats_on_today: Today's events at Edge City India, in IST.
Call edgeos_initialize, then list today's events with edgeos_list_events. Group them by morning, afternoon and evening, mark featured ones and any I've RSVPed to, and ask if I want to RSVP to anything.
plan_my_week: Build a week plan from the calendar and your RSVPs.
Call edgeos_initialize. Show my RSVPs for the next 7 days (edgeos_list_events with mine: true), then ask what I'm interested in and suggest events that fit around them without clashes. RSVP only through edgeos_propose and edgeos_confirm, one at a time, after I say yes.
host_an_event: Plan and create an event, checked before it goes live.
Call edgeos_initialize and edgeos_guide with topic hosting. Ask me, one question at a time, for the title, what happens, when (IST), where (show me free venues with edgeos_venue_availability), and capacity. Then use edgeos_propose with action create_event, show me the summary and warnings, and confirm only after I say yes.
Guides (served by edgeos_guide, and quoted in proposals)
hosting
# Hosting events A good village event has: - A clear title that says what happens, not just a theme. - A description of a few sentences: what people will do, who it's for, what to bring. - A real place: a venue from `edgeos_list_venues`, or a custom location name and map link. - A start and end time in IST, written with the +05:30 offset (e.g. 2026-10-14T18:30:00+05:30). Most events run 30 minutes to 3 hours. - A capacity only when the space or activity needs one. Before proposing: - Check the venue is free with `edgeos_venue_availability` for that day. - Ask the attendee for anything missing rather than inventing it. - Changes and cancellations notify nobody automatically through this server; tell the attendee to message their attendees if plans change.
limits
# What this server can't do EdgeOS doesn't let API keys reach these, so say "not available here" and point the attendee to the Edge City portal: - Messages to an event's attendees - Check-in and attendance - Admin notes and attendance mode - The attendee directory and anyone's profile, including the attendee's own - Session recordings or transcripts (EdgeOS doesn't have them) Never ask for or accept an EdgeOS key in chat. If the attendee's key stops working, they reconnect from their app.
recurring
# Recurring events - A recurring series expands into one row per occurrence when you list a date range. Each row carries `occurrence_start`. - To RSVP or cancel for one occurrence, pass that row's `occurrence_start` exactly as returned. - Participant lists for recurring events must name the occurrence; without it the list is usually empty or short, which does not mean nobody is going.
rsvp
# RSVPs
- Every RSVP and cancellation goes through `edgeos_propose` with action `rsvp` or `cancel_rsvp`, one event at a time.
- Show the attendee the summary from the proposal word for word, raise every warning, and wait for an explicit yes ("yes", "go ahead", "confirm"). Earlier intent ("RSVP me to anything about AI") is not a yes.
- Then call `edgeos_confirm` with the proposal code. If the attendee changes anything, propose again.
- To see their RSVPs, list events with `mine: true` for a date range.schedule
# Reading the schedule - Always give `edgeos_list_events` a date range. "Today", "tomorrow" and "this weekend" are India dates: pass `from` as the IST date (YYYY-MM-DD) and `days`. - Times come back already converted to IST. Quote them as given, with "IST". Never convert again and never read the UTC value out loud. - Group answers by day. For each event give the time, title and venue, and say if the attendee already RSVPed. - `highlighted_only` shows the events organisers featured. - An event with `require_approval` needs the host to accept the RSVP; say so. - Results come from EdgeOS live. Don't fill gaps from memory.
venues
# Venues - `edgeos_list_venues` lists the popup's active venues with capacity and booking mode. - `edgeos_venue_availability` shows open hours and busy slots for a day, in IST. - Creating, editing or deleting a venue needs a key with "Manage venues". Attendees can only change venues they own.
Write actions
| Action | Needs | Second-model review |
|---|---|---|
| rsvp | rsvp:write | no |
| cancel_rsvp | rsvp:write | no |
| create_event | events:write | yes, if enabled |
| update_event | events:write | yes, if enabled |
| cancel_event | events:write | no |
| hide_event | events:write | no |
| unhide_event | events:write | no |
| invite | events:write | no |
| remove_invitation | events:write | no |
| create_venue | venues:write | yes, if enabled |
| update_venue | venues:write | yes, if enabled |
| delete_venue | venues:write | no |
EdgeOS routes an API key can reach (copied from EdgeOS's own policy)
| Method | Path | Scope |
|---|---|---|
| GET | /api/v1/events/portal/events… | events:read |
| GET | /api/v1/event-participants/portal/participants… | events:read |
| GET | /api/v1/event-participants/portal/eligibility/… | events:read |
| GET | /api/v1/event-venues/portal/venues… | events:read or venues:read |
| GET | /api/v1/event-settings/portal/settings… | events:read |
| GET | /api/v1/tracks/portal/tracks… | events:read |
| GET | /api/v1/popups/portal/list | events:read |
| GET | /api/v1/popups/portal/… | events:read |
| POST | /api/v1/events/portal/events | events:write |
| POST | /api/v1/events/portal/events/… | events:write |
| POST | /api/v1/event-venues/portal/venues | venues:write |
| POST | /api/v1/event-participants/portal/register/… | rsvp:write |
| POST | /api/v1/event-participants/portal/cancel-registration/… | rsvp:write |
| PATCH | /api/v1/event-venues/portal/venues/… | venues:write |
| PATCH | /api/v1/events/portal/events/… | events:write |
| DELETE | /api/v1/event-venues/portal/venues/… | venues:write |
| DELETE | /api/v1/events/portal/events/… | events:write |
Analytics
Analytics runs only when the operator has set POSTHOG_PROJECT_TOKEN and POSTHOG_ID_SALT. Then PostHog MCP Analytics records one event per tool call: tool name, success or error, duration, AI app and model, the AI's one-line reason (a context argument PostHog adds), a conversation id, and requests for missing features (a get_more_tools tool PostHog adds). It also records connection and listing events (initialize, tools list, prompts list), and every event carries the popup slug and your key's scopes. Tool arguments, responses and error messages are dropped before sending. The only identity is an HMAC of your key's public prefix; there are no person profiles. Proposal events record the action, the warning count, and whether it was confirmed. When analytics is on, the tool list above also shows the PostHog-added context and conversation_id arguments and get_more_tools, because that is what the AI sees.