How is this safe?
Your EdgeOS key lets an AI act as you on the Edge City calendar. Here's exactly what happens to it, at whatever depth you like.
Every instruction we give the AI is public on How it works.
You make a key in the Edge City portal and paste it once, on this site. Not into a chat.
We lock the key inside a token right away and hand the token to your AI app. We don't keep a copy. There's no database.
When your AI asks “what's on tonight?”, the app sends the token back. We unlock it for that one request, ask EdgeOS as you, send the answer, and forget the key.
Your AI only ever sees the answers. If you want to stop, delete the key in the Edge City portal. Everything stops working at once.
flowchart LR You[You] -->|paste key once| Page[Our connect page] Page -->|locked token| App[Claude / ChatGPT] App -->|locked token with each question| Server[Our server] Server -->|your key, for one request| EdgeOS[EdgeOS] EdgeOS -->|events| Server -->|answer, no key| App
Think of your key as a letter. On the connect page you seal it in an envelope that only our letter opener can open.
Your AI app keeps the sealed envelope. We keep the letter opener, but no envelopes: we have nowhere to store them.
Each time your AI needs something, it hands us the envelope. We open it, use the letter for that one errand, and give the envelope back. Nothing is filed away.
Your AI carries the envelope but can't open it. We could read a letter only if someone handed us the envelope, and the only way to collect envelopes would be to change the code, in public, where anyone can see it.
sequenceDiagram participant A as Your AI app participant S as Our server (has the opener) participant E as EdgeOS A->>S: here's the sealed envelope + question S->>S: open, read the letter S->>E: errand, as you E-->>S: result S-->>A: answer (envelope stays with the app)
This server is its own OAuth 2.1 authorization server, with no storage. Every artifact it issues is a compact JWE (alg: dir, enc: A256GCM) under TOKEN_SECRETS, with a typ claim so a code can't pass as a token:
- DCR
client_id: redirect URIs and app type (CIMD clients use their metadata URL instead) - Auth code (60 s): key, scopes, popup, client, redirect URI, PKCE challenge
- Access token (1 h, audience
/api/mcp) and refresh token (until 15 Nov 2026) - Proposal code (10 min): the exact write the attendee will confirm
PKCE S256 is required; the authorize redirect includes iss (RFC 9207). The secret is generated by a script that writes it to the host's write-only env, so the operator never holds it.
| Who | Can they see your key? |
|---|---|
| The AI model | No. Tools return results only; keys are scrubbed from errors. |
| Your AI app (claude.ai, ChatGPT) | No. It stores a sealed token it can't open. |
| The operator, from logs or a database | No. There is no database, and nothing logs headers or keys. |
| The operator holding the secret alone | No. Tokens exist only in your app; the secret opens nothing by itself. |
| The operator changing the code | Only by deploying code that captures keys, visible in this public repo's history. |
Trade-offs we accept: a 60-second code could be replayed, but redeeming it also needs the PKCE verifier only your app holds; a single token can't be revoked server-side, so revoke the key in EdgeOS instead.
sequenceDiagram participant C as MCP client participant B as Your browser participant S as This server participant E as EdgeOS C->>S: POST /api/mcp (no token) S-->>C: 401 + resource metadata C->>S: metadata, CIMD or DCR C->>B: open /oauth/authorize (PKCE) B->>S: paste key on /connect S->>E: validate key, detect scopes S-->>B: redirect: sealed code + iss B->>C: code C->>S: /oauth/token + verifier S-->>C: sealed access + refresh C->>S: tool call with sealed token S->>E: Bearer eos_live_… (in memory only)
Read the code that handles your key yourself, or ask your AI to. These links point at the exact commit running now:
- src/lib/seal.ts: The only code that locks and unlocks your key.
- src/lib/oauth/authorize.ts: Takes your key from the connect page, checks it with EdgeOS, seals it.
- src/lib/edgeos/client.ts: The only place your key is sent anywhere: to EdgeOS, as you.
- src/lib/scrub.ts: Removes any key from error messages before a model sees them.
- src/mcp/lib/tool-wrapper.ts: Logs each call without arguments, bodies or keys.
flowchart LR R[Public repo on GitHub] --> C[Commit 2631192947cc] C -->|built and deployed| S[This server] S -->|shows its commit| Y[You or your AI] Y -->|read the key files| C
Paste this into your AI:
Audit these files from https://github.com/Nhajela/eci-events-mcp at commit 2631192947ccbdc11390fa0ce593c984db5f2d6f. Tell me whether an EdgeOS key (eos_live_…) could be stored, logged, returned to an AI, or sent anywhere other than api.edgeos.world: https://github.com/Nhajela/eci-events-mcp/blob/2631192947ccbdc11390fa0ce593c984db5f2d6f/src/lib/seal.ts https://github.com/Nhajela/eci-events-mcp/blob/2631192947ccbdc11390fa0ce593c984db5f2d6f/src/lib/oauth/authorize.ts https://github.com/Nhajela/eci-events-mcp/blob/2631192947ccbdc11390fa0ce593c984db5f2d6f/src/lib/edgeos/client.ts https://github.com/Nhajela/eci-events-mcp/blob/2631192947ccbdc11390fa0ce593c984db5f2d6f/src/lib/scrub.ts https://github.com/Nhajela/eci-events-mcp/blob/2631192947ccbdc11390fa0ce593c984db5f2d6f/src/mcp/lib/tool-wrapper.ts
What is proven, and what you still trust
Proven by the public code: how the key is handled, if the running commit is the one shown.
Still trusted: that the host really runs that commit. We hold the host login, so we could deploy something else. Next steps we plan: deploys only from GitHub's CI with signed build records, and later a hardware enclave that proves which code is running.
What we measure
Analytics only runs when it is configured. Per tool call: tool name, success or error, duration, which AI app, the AI's one-line reason for the call, the popup slug, your key's scopes, a conversation id the AI passes back so calls in one chat group together, and a hashed id that can't be turned back into your key or name. PostHog also records requests the AI makes for features we don't have. The reason and those requests are both short texts written by the AI. Never: what you asked, event details, error text, names, or your key. Hosting reviews, only when enabled, send the proposed event's text (not your key, not attendee lists) to a second AI model to check it against our guidelines.
Web pages: these pages send landing_viewed, trust_viewed, how_it_works_viewed, connect_viewed, setup_path_selected (new or techy), client_tab_selected (which app guide you opened), tutorial_step_viewed (which step number), connect_started, key_accepted (your key's scopes) and key_rejected (a short reason such as invalid_key). Page URLs are sent with query strings and fragments stripped. No cookies (memory only), no session recordings, no heatmaps, no autocapture.
Where this runs
- Code
- github.com/Nhajela/eci-events-mcp (public)
- Running commit
- 2631192947cc
- Built
- 2026-10-06T14:54:25.440Z
- Host
- Vercel
- Deployed by
- git push to main (Vercel Git integration)
- EdgeOS API
- https://api.edgeos.world/api/v1
Live data: /api/build-info