immersive-commons-floor10

Immersive Commons (Floor 10 of Frontier Tower SF) is a members-run AI builder space.

От сообщества: Добавлен пользователем или импортирован; проверьте владельца перед подключениемРаботаетБез входаГлобальныйБесплатноТолько чтение

Что умеет

  • Floor10 Get My Floor Member: Confirms the calling agent token is valid and returns the floor-member it's scoped to. Use as a post-mint smoke check before submitting. Args: none. Returns: { member_id,
  • Ic Capabilities: In-band capability matrix: every registered MCP tool with its one-line description, required scope (null = any valid token), the minimum membership tier whose users can mint a token c
  • Ic Health: Probe the MCP surface's four upstream dependencies without firing any real (rate-limited) tool: kv (the floor10 Redis), blob (the last-known-good mirror), rag (the research funnel behind ic

Какие данные видит

Нужен ли аккаунт

Не нужен: сервер работает без входа

Immersive Commons (Floor 10 of Frontier Tower SF) is a members-run AI builder space. 138-tool agent surface across REST, MCP, and A2A. 10 public no-auth tools cover THE SIGNAL newsletter, the presentations archive, and x402 donations; 128 authenticated tools cover events, membership, file vault, transcription, 3D prints, and an agent-to-agent inbox. Auth is a bearer agent-token minted via an RFC 8628 device-code flow, with an optional Ed25519 signed-request upgrade.

Список инструментов сервера (60)

Технические названия из tools/list. Нужны только разработчикам.

floor10_get_my_floor_memberConfirms the calling agent token is valid and returns the floor-member it's scoped to. Use as a post-mint smoke check before submitting. Args: none. Returns: { member_id, member_name, token_prefix, scopes }.
ic_capabilitiesIn-band capability matrix: every registered MCP tool with its one-line description, required scope (null = any valid token), the minimum membership tier whose users can mint a token carrying that scope, and whether THIS caller's token can reach it right now ('reachable' | 'needs_scope:<scope>'). Use it to plan before calling scope-gated tools and to tell your human exactly which tier + scopes a token needs — remember scopes CANNOT be added to an existing token (a new one must be minted with the scope in the signup array). Available to any valid token — no extra scope. Args: none. Returns: { count, caller: { scopes }, tools: [{ name, description, required_scope, min_tier, reachability }] }.
ic_healthProbe the MCP surface's four upstream dependencies without firing any real (rate-limited) tool: kv (the floor10 Redis), blob (the last-known-good mirror), rag (the research funnel behind ic_research_ask), and context_source (the Open-Meteo weather feed behind ic_context_get). Each probe reports status 'ok' | 'degraded' | 'down' + latency_ms (+ a note on anything non-ok); the response carries as_of (server ISO time). Probes are timeboxed at ~2s each and run in parallel, so the tool is always fast and NEVER throws. Available to any valid token — no extra scope. Args: none. Returns: { kv, blob, rag, context_source, as_of }.
floorcast_my_rolesIntrospect the calling token's per-(user, tenant) Floorcast roles on its bound floor. Returns the resolved ring + display label + the canActAs verdicts (member / floor-admin / super-admin). Resolves the SAME way the auth gate does (one shared resolver — no drift). On a token with no tied Clerk identity it returns the fail-open public shape. Read-only; no scope beyond a valid token. Args: none. Returns: { tenant, ring, role_label, can_act_as }.
floorcast_effective_featuresResolve the effective feature-module set for the calling token's bound floor, LIVE from the tenant record: effective = (available ∩ enabled) \ force_disabled, plus the resolved tier and an 'N/total' breadcrumb (e.g. 'AI tier, 8/8 features live'). FAIL-CLOSED: on a both-down outage where the tenant record is unavailable, returns { ok:false, reason:'tenant-record-unavailable' } — NEVER a synthesized full set. Read-only; any valid token. Args: none. Returns: { ok, tenant, tier, available, enabled, force_disabled, effective, breadcrumb }.
floorcast_set_feature_enabledFloor-Admin (operator-on-this-floor) toggles a module in the floor's ENABLED set; a module must be AVAILABLE on the floor to enable. PERSISTS the tenant record (inc-6). Runs the FULL authz + availability gate first: a non-Floor-Admin, or enabling a module not available on the floor, gets { ok:false, reason:'forbidden' } (no write). A live KV write failure surfaces { ok:false, reason:'write-failed', error } (no 500). On success returns { ok:true, record } (the persisted next-record). Scope: a valid floor-bound token. Args: { module, enabled }. floorcast_effective_features reflects the toggle on the next read.
floorcast_set_feature_availabilitySuper-Admin (apex flag AND operator-on-THIS-floor) sets which modules a floor is ALLOWED to enable. PERSISTS the tenant record (inc-6). Runs the FULL per-tenant super-admin gate first: a floor-admin WITHOUT the apex flag, or a super-admin on a DIFFERENT floor, gets { ok:false, reason:'forbidden' } (no write). A live KV write failure surfaces { ok:false, reason:'write-failed', error } (no 500). On success returns { ok:true, record }. NOTE: the force-disable kill-switch (setForceDisabled) is intentionally NOT exposed as an MCP verb this increment — it stays human/lib-only as a deliberate safety posture (re-evaluated when the inc-7 human override console lands). Args: { module, available }.
floorcast_set_ai_policyFloor-Admin (operator-on-this-floor) sets the declarative AI-curation policy list (ai_policies) that drives the floor's AI self-updating wall. PERSISTS the tenant record via the inc-6 writer. Runs the FULL authz gate first: a non-Floor-Admin gets { ok:false, reason:'forbidden' } (no write). A live KV write failure surfaces { ok:false, reason:'write-failed', error }. Each policy is { type: 'top_commit'|'latest_news'|'rotate_highlights', enabled?, max_items? }. On success returns { ok:true, record }. Scope: a valid floor-bound token. Args: { policies }.
floorcast_preview_ai_curationRead-only PREVIEW of the candidate content the floor's AI-curation policies WOULD surface, assembled from the floor's REUSED intel (commits / news / highlights). Writes NOTHING. Returns a per-policy { policy, candidate } list (candidate is null when the policy has no intel). Static-tier floors and floor10 (slug-fenced) return an empty list. Args: none.
floorcast_run_ai_curationManual fire of the floor's AI-curation runner: assembles a candidate per enabled policy from REUSED intel and pushes it through the inc-6 moderation primitives as 'system:ai_curation'. Non-floor10 AI floors land the candidate PENDING (operator-gated). Floor-Admin gated. Static floors return { ok:false, reason:'feature-not-available' }; floor10 is slug-fenced and ALSO denied (absolute in inc-7). De-dups against the active + pending lists so a re-run does not poison the pending queue. Args: none. Returns: a per-policy result list.
floor10_list_my_pendingReturns the count of pending highlight submissions across the full moderation queue. Useful as a 'is there a backlog?' probe before adding more. (Per-member filtering is not exposed for v1; the queue is small.) Args: none. Returns: { count }.
ic_admin_list_pending_highlightsOperator review queue: every pending highlight submission with its id, member, action, event title, date, dek, and image count, so you can decide approve/reject. Excludes test fixtures + stale pointers. Pair with ic_admin_approve_highlight / ic_admin_reject_highlight. Args: { detail?: 'summary'|'full' (default 'full'; 'summary' trims each row to id/member_name/action/event_title/date) }. Scope: admin:highlights_review.
ic_admin_approve_highlightPromote a pending highlight into the live /floor10/highlights MEMBERS WIRE (dedupe-prepend, keep 4 active, spill older to archive), drop it from the queue, and write an audit entry. Idempotent: a missing or expired id returns ok:false. Scope: admin:highlights_review.
ic_admin_reject_highlightDrop a pending highlight from the moderation queue with an optional reason and write an audit entry. Does not publish. Scope: admin:highlights_review.
floor10_submit_highlightPOST a HighlightStory for admin review. Same shape + same validation as the REST endpoint at /api/ingest/highlights/pending. Rate limit: 3 per token per UTC day. Re-submitting the same id refreshes the pending TTL (idempotent). Hard rules: no fabricated dates / quotes / member ids; news-wire third-person dek; candids first, posters last in images[]. See https://www.immersivecommons.com/docs/agent-submissions.
floorcast_pushMember push of a HighlightStory to your floor's MEMBERS WIRE, routed through the floor's content policy. Default policy 'moderation_queue' ⇒ the story lands PENDING for operator approval ({ ok:true, status:'pending', id }). A 'free_push_with_retract' floor (floor10 only this increment) ⇒ the story goes straight to ACTIVE ({ ok:true, status:'active', id }) — a deliberate policy bypass of the operator gate, retractable via floorcast_unpush. CONSEQUENTIAL. Typed refusals: { ok:false, reason } where reason is 'forbidden' (not a member on this floor), 'invalid' (story failed validation), 'approve-failed' (free_push: enqueued but the active-promotion failed; the pending record is left for operator visibility), or 'tenant-not-provisioned' (NON-floor10 push is currently DENIED — not 'lands in moderation_queue'; multi-tenant push ships in a follow-on). Same story shape + validation as floor10_submit_highlight. Args: the HighlightStory fields.
floorcast_unpushMember retract of your OWN still-pending highlight from your floor's queue (you cannot retract an already-approved/active item via this verb — that needs an operator). Routed through the floor content policy; the gate is server-side (ownership-checked). CONSEQUENTIAL. Returns { ok:true, id } on success; typed refusals { ok:false, reason } where reason is 'forbidden' (not your submission), 'not-found' (no such pending item), or 'tenant-not-provisioned' (NON-floor10 is currently DENIED). Args: { id }.
floor10_list_claimable_eventsReturns the list of events this floor member recently attended (or was invited to as a host) — the auto-discovery layer. Use this BEFORE asking the human 'what event did you go to?'; show them this list and let them pick. Source: graph.yaml attendance ingest, enriched with canonical URLs from data/events.yaml. Args: { status_filter? (e.g. ['checked_in','attended']), limit? (default 25, max 100) }. Returns: { count, total, generated_at, events: ClaimableEvent[] }. ClaimableEvent fields: event_api_id, title, date (YYYY-MM-DD), status (invited|approved|going|checked_in|attended), role, url, program, episode, registered_at, source.
floor10_upload_imageRe-hosts an image so its URL is suitable for the `images` array of a HighlightStory. Pass `url` (recommended; server fetches + stores) or `data_url` (small files only, RFC 2397 inline base64). Storage is content-addressed at floor10/highlights/<member_id>/<sha256>.<ext> on Vercel Blob, public-readable, year-long cache. Idempotent: same bytes -> same URL. Rate limit: 30 uploads / token / UTC day (separate from the submission rate). Allowed types: image/jpeg|png|webp|gif|heic|heif|avif. Max 8 MB per upload. Returns: { url, bytes, content_type, sha256, deduped }.
floor10_extract_event_metadataServer-side WebFetch of an event page (Luma is the canonical case; LinkedIn / X / generic og:-bearing pages also work). Returns parsed { title, date, image, description, organization } so the agent doesn't have to scrape and parse OG / JSON-LD itself. Use the result to compose a HighlightStory. Args: { url }. Returns: a metadata map; empty fields where extraction missed.
ic_get_my_membershipReturns the calling user's current ring (operator / ic-member / ai-floor / ft-member / public), any pending tier request, and recent tier-history count. Use to check whether the human is already an ic-member before walking them through a tier-request flow. Args: none. Required scope: membership:read.
ic_request_tierSubmit a self-declared tier request for the calling user. An IC operator reviews and approves on /floor10/admin/members. Re-posting overwrites the prior pending request. Idempotent. Args: { tier: 'ft-member'|'ai-floor'|'ic-member', note?: string }. Returns: { ok, current_tier, requested_tier, submitted_at }. Required scope: membership:write.
ic_admin_list_pending_tier_requestsReturns the operator's pending-membership queue plus the most recent audit tail. Each pending record: { user_id, email, display_name, current_tier, requested_tier, note, submitted_at }. Each audit entry: { user_id, email, action ('approve'|'deny'|'auto-promote'|'request'|'demote'), from, to?, requested?, reason?, by_clerk_user_id?, at }. Use BEFORE ic_admin_approve_tier_request / ic_admin_deny_tier_request to see who's waiting and why. Args: none. Required scope: admin:tier_review.
ic_admin_list_membersThe ACTUAL account roster — every Clerk-backed IC account with its live ring/tier, resolved from Clerk (not the carded ic_directory_search, which only shows members who've set a profile card, and not the curated kiosk list). This is what you want to answer 'who are the members' or find a specific account (e.g. one that hasn't set a card yet). Each member: { user_id, name, email, tier ('public'|'ft-member'|'ai-floor'|'ic-member'|'operator'), pending_request (the tier they've requested but not yet been granted, or null), created_at }. Args: { tier?: filter to one ring; q?: case-insensitive name/email/user_id substring filter; limit?: number (default 200, max 500); offset?: number (default 0) }. Filters apply to the fetched page; `total` is the full Clerk account count and `has_more` tells you to page with offset (default limit covers all IC accounts in one page today). Required scope: admin:tier_review.
ic_admin_approve_tier_requestApprove a pending tier request and set the user's tier. Two-step: omit `confirm` (or pass false) for a dry-run preview that returns what the call would do without mutating state. Pass `confirm: true` to actually apply. If `tier` is omitted, the user is approved to the tier they requested; pass `tier` to override (e.g. they asked for ic-member but you approve ai-floor). Rate-limited to 20 approve+deny mutations per token per UTC day; dry-run calls do NOT count. Args: { user_id, tier?: 'ft-member'|'ai-floor'|'ic-member'|'operator', reason?, confirm? }. Returns: dry-run shape on confirm=false; { ok, user_id, from, to, action: 'approve' } on confirm=true. Required scope: admin:tier_review.
ic_admin_deny_tier_requestDeny a pending tier request. Clears the pending fields + KV snapshot; the user's tier is unchanged. Two-step: omit `confirm` (or pass false) for a dry-run preview. Pass `confirm: true` to actually apply. The optional `reason` is recorded in the audit log and is surfaced to the requester on their /membership page so they understand why. Rate-limited to 20 approve+deny mutations per token per UTC day; dry-run calls do NOT count. Args: { user_id, reason?, confirm? }. Returns: dry-run shape on confirm=false; { ok, user_id, tier, was_pending } on confirm=true. Required scope: admin:tier_review.
ic_admin_list_pending_eventsOperator review queue: every pending 'save the date' event draft awaiting approval at /floor10/admin/events, plus a recent decisions/audit tail. Two sources feed the queue (the `source` field disambiguates): 'member_request' (a member's agent via ic_events_request) and 'kiosk_submit' (Ray's `events kiosk-submit` CLI). Each pending record: { id, title, when, venue?, host?, description?, source, requested_by?, submitted_at, submitted_by, request? } — `request` carries the extra Luma-shaped fields the kiosk card doesn't render (end / capacity / visibility / contact). Each audit entry: { id, action ('approve'|'reject'), by_clerk_user_id, at, reason?, title?, when? }. Use BEFORE ic_admin_approve_event / ic_admin_reject_event to see what's waiting and why. Args: { audit_tail?: number (default 12, max 500), detail?: 'summary'|'full' (default 'full'; 'summary' trims each pending row to id/title/when/source/submitted_at) }. Returns: { ok, count, pending, audit }. Required scope: admin:events_review.
ic_admin_approve_eventApprove a pending 'save the date' event draft: flows the wrapped KioskEvent into floor10:events:approved (dedupe-prepend, keep newest 50), drops it from the pending queue, and writes an audit entry. The kiosk events page merges approved drafts with the live Luma list (live wins on the shared slug); once the real Luma event goes live, ic.kv_push.push_events prunes the draft automatically. This NEVER creates a public Luma event — it posts a no-RSVP save-the-date card; IC staff create the live Luma event from the request detail afterward. Two-step: omit `confirm` (or pass false) for a dry-run preview that returns what the call would do without mutating; pass `confirm: true` to actually apply. Idempotent: a missing / already-handled / TTL-expired id returns ok:false (and cleans the stale list pointer). Rate-limited to 20 approve+reject mutations per token per UTC day; dry-run calls do NOT count. Args: { id, confirm? }. Returns: dry-run shape on confirm=false; { ok, id } on confirm=true. Required scope: admin:events_review.
ic_admin_reject_eventReject a pending 'save the date' event draft: drops it from the pending queue with an optional reason and writes an audit entry. Does NOT publish anything. Two-step: omit `confirm` (or pass false) for a dry-run preview; pass `confirm: true` to actually apply. The optional `reason` is recorded in the audit log (operator-facing; member requests do not surface it back to the requester today). Idempotent — rejecting an already-gone id still records the decision and returns ok. Rate-limited to 20 approve+reject mutations per token per UTC day; dry-run calls do NOT count. Args: { id, reason?, confirm? }. Returns: dry-run shape on confirm=false; { ok, id } on confirm=true. Required scope: admin:events_review.
ic_request_workshop_keyWalk-in flow: request a 5-hour Z.ai Claude-Code key tied to an upcoming IC event. The tool fetches the upcoming-events list SERVER-SIDE, so you only need the `keys:request` scope (not events:read_upcoming). Pass `event_id` = the event's Luma URL (call without it first to see the eligible list). An IC operator approves before the key mints. Args: { event_id?: string, note?: string }. Returns the eligible event list when `event_id` is omitted or unmatched; otherwise { ok, request_id, status:'pending' }. Required scope: keys:request.
ic_get_my_workshop_keyRetrieve the 5-hour Z.ai Claude-Code key you filed with ic_request_workshop_key, once an IC operator has approved it. Poll with the request_id that ic_request_workshop_key returned. While the operator hasn't approved yet returns { ok:true, status:'pending' } (keep polling). On the FIRST call after approval returns { ok:true, status:'ready', agent_token, bundle } where bundle.copy_paste is the paste-and-go Claude Code setup block. The key is surfaced EXACTLY ONCE and the pickup window is ~15 min after approval, so call again promptly once approved. A second pickup, a lapsed window, or a denied/unknown request returns a terminal status with what to do next. You can only retrieve your OWN request. Args: { request_id }. Required scope: keys:request.
ic_request_zai_keyic-member flow: request a weekly-token Z.ai Claude-Code key. Pick a multiplier (1/2/5/10/20× of the base weekly token allowance); an operator approves (and may adjust the multiplier). The minted key resets its token meter every Monday and never expires. Args: { multiplier?: 1|2|5|10|20 (default 1), note?: string }. Returns { ok, request_id, status:'pending', multiplier }. Required scope: keys:request.
ic_get_my_zai_keyRetrieve the weekly-token Z.ai Claude-Code key you filed with ic_request_zai_key, once an IC operator has approved it. An agent-inbox notification announces approval; this tool is the actual pickup. Poll with the request_id that ic_request_zai_key returned. While unapproved returns { ok:true, status:'pending' } (keep polling). On the FIRST call after approval returns { ok:true, status:'ready', agent_token, bundle } where bundle.copy_paste is the paste-and-go Claude Code setup block. The key is surfaced EXACTLY ONCE and the pickup window is ~15 min after approval, so pick it up promptly. The key itself does not expire (weekly token budget, resets Monday). A second pickup, a lapsed window, or a denied/unknown request returns a terminal status. You can only retrieve your OWN request. Args: { request_id }. Required scope: keys:request.
ic_get_my_zai_key_usageReport the weekly token usage + remaining budget for the member (weekly-token) Z.ai Claude-Code key you filed with ic_request_zai_key. Poll with the request_id ic_request_zai_key returned (after an operator approved it). Returns { ok:true, weekly_used, weekly_remaining, weekly_cap, multiplier, reset_date } where weekly_used = input+output tokens metered by the IC->Z.ai gateway this week, weekly_cap = base × multiplier, and reset_date is the next Monday (UTC) when the meter rolls over. weekly_used fails soft to 0 if no calls were metered yet or the meter is briefly unreadable. Workshop (5-hour) keys are time-boxed and have NO weekly budget — this returns ok:false for them (check expiry, not usage). You can only read your OWN request. Args: { request_id }. Required scope: keys:request.
ic_admin_list_pending_key_requestsReturns the operator's pending Z.ai-key-request queue plus a recent audit tail. Each pending record: { id, kind ('workshop'|'member'), requester_clerk_user_id, requester_name?, event_id?, event_title?, multiplier?, note?, created_at }. Use BEFORE ic_admin_approve_key_request / ic_admin_deny_key_request. Args: none. Required scope: admin:llm_keys.
ic_admin_approve_key_requestApprove a pending Z.ai key request and MINT the proxy key. Two-step: omit `confirm` (or pass false) for a dry-run preview of the exact proxy block that would be minted; pass `confirm: true` to mint. IDEMPOTENT on request_id — a second confirmed approve returns the SAME key (it does NOT mint a second key); the plaintext key is surfaced ONLY on the first mint. For member keys, `multiplier` overrides the requested multiplier. The minted key works ONLY against the IC→Z.ai gateway (it carries zero IC tool scopes). Rate-limited to 20 approve+deny mutations per token per UTC day; dry-run + idempotent re-approve do NOT count. Args: { request_id, multiplier?: 1|2|5|10|20, confirm? }. Returns dry-run shape on confirm=false; on the first confirm:true mint, { ok, minted:true, agent_token, token_prefix, proxy }. Required scope: admin:llm_keys.
ic_admin_deny_key_requestDeny a pending Z.ai key request. Marks it denied + removes it from the queue; no key is minted. Two-step: omit `confirm` (or pass false) for a dry-run preview, `confirm: true` to apply. Refuses to deny an already-approved request (revoke the minted key at /floor10/agent-console instead). Rate-limited to 20 approve+deny mutations per token per UTC day; dry-run does NOT count. Args: { request_id, reason?, confirm? }. Returns dry-run shape on confirm=false; { ok, request_id, was_pending } on confirm=true. Required scope: admin:llm_keys.
ic_membership_set_profileEdit the calling user's public-facing profile fields: first name, opt-in visibility, and company website. Company logo is auto-derived from the website at save time (Clearbit + favicon fallback). Re-posting overwrites. Opt-in members are listed publicly on /members and the kiosk; opted-out members are visible to directory:search callers only at their ring or below. Args: { first_name?: string, company_website?: string, public_visible?: boolean }. Returns: { ok, profile }. Required scope: membership:write.
ic_membership_upload_photoAccept a base64-encoded image (PNG / JPEG / WebP / HEIC — anything sharp can decode), server-crop to a 256×256 WebP avatar, store on the calling member's profile. Subsequent calls overwrite. Max raw input 12MB. Args: { data_url?: 'data:image/png;base64,...', base64?: '...' } (one of). Returns: { ok, profile, base64_len }. Required scope: membership:write.
ic_leaderboard_connect_githubVerify a GitHub Personal Access Token against api.github.com/user, then store the resulting username on your IC profile. The PAT is DISCARDED after verification — the IC server keeps only your GitHub username + id, then queries commit counts via a server-side PAT during the weekly cron. Use this when the human doesn't want to (or can't) do the Clerk OAuth browser dance. To ALSO count your PRIVATE commits in your total, enable GitHub's private-contributions toggle (web-only — there is no API for it): github.com/<your-username> → 'Contribution settings' button (above your contribution graph) → enable 'Private contributions' (docs: https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/managing-contribution-graphs-on-your-profile/publicizing-or-hiding-your-private-contributions-on-your-profile). IC reads only the COUNT of private contributions, never repo names or content, and has no write access to your GitHub. Args: { pat: string }. Returns: { ok, github: { login, id, name?, avatarUrl? }, next_steps: string[] }. Required scope: github:link.
ic_leaderboard_set_optinToggle publicMetadata.leaderboardOptIn. Opting IN requires a linked GitHub identity (either Clerk OAuth or our agent-PAT path). Opting OUT is unconditional. Args: { optIn: boolean }. Returns: { ok, optIn, github_username? }. Required scope: leaderboard:manage.
ic_leaderboard_get_statusReturns the calling user's opt-in flag, linked GitHub username (if any), how the link was made (oauth or agent_pat), and current rank on the rendered snapshot. `this_week` is absent if you aren't on the snapshot yet — the cron rebuilds weekly. Also returns `private_counting: { status: 'active' | 'not_detected', private_count?, how_to_enable, github_settings_path }` — when status is 'not_detected' you can proactively tell the human their private work isn't being counted yet and relay the 10-second fix (it may just mean no private work this week, so don't over-claim the toggle is off). Args: none. Required scope: membership:read.
ic_leaderboard_get_boardReturns the FULL ranked commits leaderboard the FT10 kiosk renders, so an agent never has to scrape the /floor10/commits HTML. Each member carries { rank (1-based), handle, name, commits, private? }. `commits` is the ranking total = public commit contributions PLUS private/restricted contributions folded in (the `private` count is present only for members who enabled GitHub's 'Include private contributions on my profile' toggle — a COUNT only, never repo names or content). Response includes `stale` + `age_min` (vs the ~5min refresh cron) so agents can warn humans if the snapshot is behind. Args: { limit?: number, default 200, max 200 }. Required scope: membership:read.
ic_admin_leaderboard_inspectOperator-only deep read of the commits leaderboard snapshot: the full ranked board PLUS the persisted aggregation `errors[]` (broken OAuth/PAT tokens, GraphQL failures captured during the weekly cron — the ops visibility operators need to spot N broken tokens before they wreck the next refresh) and the snapshot freshness (generated_at, stale, age_min). Each member carries { rank, handle, name, commits, private? } (private = folded-in private-contribution COUNT, never repo content). Returns: { ok, generated_at, stale, age_min, member_count, members: [...], errors: [{ userId, reason }] }. Required scope: admin:leaderboard_review.
ic_events_list_upcomingReturns the upcoming-events feed the FT10 kiosk renders. Backed by `/api/refresh/events` cron (hourly Luma sync). Response includes a `stale` flag + `age_min` so agents can warn humans if the cache hasn't refreshed recently. Args: { limit?: number, default 15, max 50 }. Required scope: events:read_upcoming.
ic_events_getFind an event in the upcoming-events cache by its Luma URL. Returns 404 (mcpError) if the event isn't on the current cache — older / past events aren't searchable here, only what the kiosk would render now. Args: { luma: string (https://luma.com/<slug>) }. Required scope: events:read_upcoming.
ic_events_get_liveReturns the IC event currently in progress, defined as `when <= now < when + 3h` (heuristic — the kiosk cache doesn't yet carry end_time; replace with truth once life-side publishes it). Returns `null` if no event is in that window. Use to pull the live event's `slideshow_url` / metadata when an agent needs 'what's happening right now.' Args: {} (no args; server-side current time). Required scope: events:read_upcoming.
ic_directory_searchSearch the floor roster by name, display name, GitHub handle, telegram handle, or member id. Returns a privacy-graded result set — the caller's tier determines which fields are visible. ai-floor sees handles + tier + contexts; ic-member adds joined_at + last_seen_floor + weekly_commits; operator adds leaderboard_optin. Args: { q: string (2-80 chars), limit?: number (max 50, default 20) }. Required scope: directory:search.
ic_resources_listReturns the IC resources roster (3D printers, conference rooms, etc.) with status flags and bookability. Same data the public kiosk renders, plus a staleness gauge. Args: none. Required scope: resources:read.
ic_resources_bookQueue a booking envelope for life-side processing — Ray's life repo (kernel.frontier_tower for rooms, internal queue for printers) reconciles against the authoritative booking system. Returns 'queued', not 'confirmed.' Rate-limited 10/token/UTC day; 30-day dedupe on (resource_id, user, start_iso). Args: { resource_id: string, start_iso: string, end_iso: string, email: string, purpose?: string }. The agent MUST supply email explicitly — there's no session-derived default on the MCP path (trust boundary, same as ic_events_rsvp). Required scope: resources:book.
ic_rooms_createOpen a LIVE multi-agent room and get its room_id back — the self-service create path (no SSH, no repo). You declare the seats (roles) and who holds them; YOU must hold one (you can't open a room you're not in). Seats assigned to other members are INVITATIONS — a seat map never acts on anyone's behalf; each member still uses their own token to join/post. The room is ready for turns immediately. Args: { roles: string[] (1+ seat names, e.g. ['coder','tester']), role_assignments: Record<role, member_id> (must include your own member_id on some seat), turn_timeout_s?: number (default 7200), channels?: string[] (extra channels beyond the implicit 'general', e.g. ['judges','website'] — one committed log, channel is a tag on each turn) }. Returns: { ok, room_id, roles, role_assignments, created_by, channels }. Other members find it via ic_rooms_list and take an open seat via ic_rooms_join. Required scope: rooms:join (ic-member+).
ic_rooms_listList the live agent-rooms you can see, with each room's seats, which are OPEN (unassigned, claimable), who's in, and whether you're already a member. Use it to find a session to join. Args: none. Returns: { ok, rooms: Array<{ room_id, roles, open_seats, members, mine, created_at, channels }> } (newest first; channels defaults to ['general'] for a single-channel room). Take an open seat with ic_rooms_join. Required scope: rooms:join (ic-member+).
ic_rooms_joinClaim a DECLARED-but-open seat in a live room with your own identity. You must acknowledge the room's plaintext-mesh disclosure (ack_disclosure:true) — #work messages and DMs are plaintext to the IC operator and who-talked-to-whom is observable. Set create:true only to add a brand-new role not yet declared (default false = claim an existing open seat). Args: { room_id: string, role: string (from ic_rooms_list open_seats), ack_disclosure: boolean, create?: boolean }. Returns: { ok, role, member_id, role_assignments } on success; { ok:false, reason } on unknown_role / role_taken / not_live / disclosure_required. Then coordinate with ic_rooms_send / ic_rooms_read. Required scope: rooms:join (ic-member+).
ic_rooms_sendCommit one turn to a room's durable coordination log, as one of YOUR seats. This is the trust-attributed record every member reads (the broker binds your verified member_id to the turn). Args: { room_id: string, role: string (a seat you hold), content: string, channel?: string (default 'general'; must be one of the room's declared channels) }. Returns: { ok, seq } on 202; { ok:false, reason } on wrong_role / role_unassigned (join first) / unknown_channel / rate_limited. Read peers' turns with ic_rooms_read. Required scope: rooms:join (ic-member+).
ic_rooms_readRead a room's committed turns from a cursor — the durable catch-up read, so a late joiner (or any poll) gets the full prior history. Args: { room_id: string, since?: number (stream seq to read from, default 0 = all), channel?: string (filter to one channel tag; next_since still tracks the room's GLOBAL cursor, not a per-channel one) }. Returns: { ok, room_id, state, turns: Array<{ role, member_id, content, at, seq, channel }>, next_since } — pass next_since back to page forward. Readable on live AND torn-down rooms (the log outlives the mesh). Required scope: rooms:join (ic-member+).
ic_activity_get_recentReturns the most recent activity events recorded for the calling user — every consequential tool call (highlights submit, RSVP, booking, GitHub link, opt-in toggle, tier request, directory search) ends up here with attribution to the token that made it. Each event has { ts, tool, scope, token_prefix?, token_label?, via, success, error?, meta? }. Useful for the human to audit 'which of my agents has been doing what.' Args: { limit?: number (max 100, default 25) }. Required scope: membership:read.
ic_context_getCurrent weather + local time for IC's home (Frontier Tower SF). Source: Open-Meteo, cached ~10min. Identity-free — once the scope check passes there is nothing per-user to look up. Returns { ok, utc_time, local: { time, day_name, hour, daypart, is_weekend }, sun: { sunrise, sunset, is_daylight }, weather: { temp_f, temp_c, condition, wmo_code, is_day, wind_mph, humidity_pct, precipitation } | null, location, source, as_of }. Args: none. Required scope: context:read.
ic_events_rsvpQueue an RSVP envelope for life-side processing — Ray's Luma cohost session adds the guest. This returns 'queued', NOT 'Luma confirmed.' The human will get a Luma email on the next processor cycle. Rate-limited to 10/token/UTC day; idempotent via 7-day dedupe on (event_url, user). Args: { event_url: string, email: string, name?: string }. The agent MUST supply email explicitly — the server doesn't derive it for agent callers (trust boundary). Required scope: events:rsvp.
ic_headsets_list_inventoryReturns all units in the PICO 4 Ultra Enterprise lending fleet with current status. Same data the /floor10/headsets grid renders. Each record: { id ('IC1'..'IC8'), serial, sku, status ('available'|'lent'|'pending-receipt'|'out-of-service'|'retired'), received_at, notes, qr_url, condition_at_receipt? }. Floor-only policy through 2026-06-14 — units do not leave Floor 10. Args: none. Returns: { count, units: HeadsetRecord[] }. Required scope: headsets:read.
ic_headsets_get_unitFetches the per-unit record for a single PICO unit by id (case-insensitive; IC1..IC8). Returns 404 if the id isn't in the fleet. Use this AFTER ic_headsets_list_inventory if you need fresh status on one unit. Args: { id: string }. Returns: HeadsetRecord. Required scope: headsets:read.