Guests
A guest is an external collaborator who needs access to a specific subset of your tools through mcpgate — without being added to your identity provider, without an employee account, and without inheriting any role grant from your team.
The shape of the problem
You have an MCP gateway connected to Jira, Confluence, Slack, GitLab and a handful of other services. Your employees sign in through your IdP (Microsoft Entra, Google Workspace, Okta) and get the broad access an employee gets. That works for people on the payroll.
Then an outside collaborator shows up — a contractor for a six-week engagement, an auditor who needs read-only access to Confluence for two days, a partner-org engineer working on a shared project. They need to use Claude or ChatGPT against one of your services, not all of them. None of the standard options are good:
- Provision them in your IdP as a B2B guest. Now they show up in your directory, count against license caps in some IdPs, and inherit whatever role grants you give to "external" — which in practice is often "the same as an employee minus a few things."
- Share an employee account. Self-evidently wrong. Audit trail collapses, MFA breaks, key rotation becomes a coordination problem.
- Stand up a second gateway instance for outsiders. Two installations to maintain, two sets of OAuth client credentials per upstream service, two audit logs to reconcile.
The guest model is mcpgate's third option: a separate authentication and authorization path that lives inside the same gateway instance, with a per-service allowlist as the gate.
What a guest gets
- One login flow. The guest receives a magic-link email, clicks it, and lands in a signed-in session. No password, no IdP enrolment. The link is single-use and expires after 15 minutes.
- A scoped service list. When the guest's AI client (Claude, ChatGPT, Codex) discovers tools through the gateway, it sees only the services the admin granted — for example,
jiraandconfluencebut notgitlab,slack, ordrive. Calls to any other service are denied at the gateway, not just hidden in the tool list. - The same audit trail. Every guest action goes into the same audit log as employee actions, with the guest's email hash as the actor. See Compliance for what the log captures.
- Their own session lifetime. Sessions are bound to the gateway's session config, not the upstream service's token TTL. When you revoke the guest, the session is invalid on the next request.
What the admin does
Guest management lives at /admin/team on the gateway UI. Five actions, all reversible:
- Invite. Enter the guest's email, tick the services they should reach, optionally set an expiry date and a free-form note ("Q3 audit", "vendor onboarding handoff"). The gateway records the invitation and sends the magic link.
- Update services. Change the service list on an existing guest. Takes effect on the next request — in-flight calls finish under the old policy, the next one is evaluated against the new list.
- Resend the link. If the guest missed the original mail or the link expired, resend without re-creating the record.
- Export / import. CSV round-trip for migrating guests between staging and prod, or backing up the list before a major change.
- Revoke. Removes the guest record. The next request from that email is denied. There is no soft-delete state — if you want time-bounded access, use the expiry date on the invite.
How authorization works under the hood
The mechanics are intentionally simple. When a request arrives, the gateway:
- Resolves the actor's email from the session.
- Hashes the email with SHA-256.
- Looks up
tool_guest:{email_hash}in Redis. If present, the actor is a guest; if absent, they fall through to the normal employee path. - If the actor is a guest, the requested service is checked against the record's
serviceslist. Anything outside the list returns a 403 at the gateway boundary — the upstream API is never touched.
Two consequences worth knowing:
- The email plaintext is never a Redis key — only the hash is. The plaintext is envelope-encrypted on the JSON record so the admin UI can show recognisable addresses in the team list. This is the same no-PII-in-keys rule the rest of the gateway follows.
- The read path is hot —
is_authorized_email()lands here on every request — so the lookup uses a small in-process cache (TTL 30 seconds) backed by Redis. Writes invalidate the cache immediately.
Login through your IdP (when the guest happens to have one)
Magic-link is the floor — it works for any email address, no IdP needed on the guest's side. But if the guest happens to use a SaaS IdP you have configured on the gateway (Google, Microsoft, Okta …), they can click the corresponding sign-in button on the login page and bypass the magic-link round trip. The gateway still authorizes them against their guest record — the IdP just replaces the magic link as the "this email actually owns this inbox" proof.
The point: the per-service allowlist is what makes them a guest, not the login mechanism. OIDC sign-in does not promote a guest to employee. This was a real bug we shipped and reverted — if you OIDC sign-in matches an email in the guest store, you remain a guest with the scoped allowlist intact.
What guests are not
- Not a role. There is no "guest role" with predefined permissions. The allowlist is the permission. Two guests can have completely different service lists.
- Not a license tier. Guests are not counted, throttled, or billed differently from employees on the gateway. Upstream services may treat the guest's OAuth identity differently — that is the upstream's policy, not the gateway's.
- Not a sandbox. Guests act against the real upstream services with the gateway's configured OAuth credentials. Audit, hooks, and PII sanitization apply identically.
Limits and what is open
Two things to call out.
One identity provider on the guest's side at a time. Today the magic-link flow is the primary path, with OIDC sign-in working only when the guest's email is on a provider you have already configured on the gateway. A design for letting guests bring their own corporate IdP (the "MS Entra customer A signs into our gateway with their own tenant" case) is being worked on but not shipped.
No nested allowlists. The allowlist is service-level. You can grant a guest jira, but not "jira, only project PBE, only ticket-creation". For that granularity, use a policy hook — hooks see the actor's email and can branch on it.
Related
- Compliance — admin reference — how audit, PII sanitization, throughput, and hooks all see guest activity.
- Hooks — how to add per-guest policy beyond the service-level allowlist.
- Blog: External collaborators without IdP sprawl — the story of why we built it this way and the pitfall we hit on the way.