Public API And MCP Platform Plan
Status
Current recommendation.
This plan expands the completed public API posture work from #39, the agent integration roadmap from #73, and the open read-only MCP prototype from #78 into one executable platform backlog chunk.
The intended delivery shape is one implementation PR with internally testable slices. The PR can carry multiple commits and checkpoints, but the product surface should review as one coherent API, auth, docs, and MCP platform foundation.
Goals
- make VRDex usable outside the web app without scraping
- publish a documented
/api/v0HTTP API with generated Swagger/OpenAPI reference - support anonymous public reads, minted API tokens, OAuth user-delegated flows, and OAuth application flows
- expose a hosted public MCP that can use OAuth
- expose a private/local MCP path that can use API tokens or OAuth against hosted and self-hosted deployments
- keep public data safety, trust labels, provenance, opt-out, and suppression rules identical across web, API, OpenAPI examples, and MCP tools
- keep the implementation self-hostable and reproducible through docs, checked-in config, and environment-variable inventory
Non-goals
- a permanently stable
v1API contract before launch - raw VRChat cookie automation or private VRChat account bridging inside the default VRDex MCP
- broad partner sync contracts for every external provider
- unrestricted public write APIs
- billing-tier enforcement beyond the rate-limit and capability hooks needed for this platform foundation
- one giant role/permission matrix for every future tool
Product Thesis
VRDex's API and MCP are product surfaces, not internal plumbing. They should let communities, partner sites, bots, and coding agents use VRDex data without pretending that public web pages are the integration contract.
The first useful version should feel small and sharp:
- public reads are easy and safe
- authenticated access is explicit and revocable
- OAuth apps are understandable to normal developers
- Swagger docs and MCP tools agree on the same data model
- self-hosted operators can run the same shape without hidden dashboard-only steps
Locked Decisions
Locked decision: The HTTP API starts under/api/v0/....Locked decision:v0is explicitly unstable until public launch, but breaking changes still require docs and changelog updates.Locked decision: Public API, MCP, and Swagger examples must preserve trust, provenance, claim, visibility, opt-out, and suppression semantics.Locked decision: Structured integrations should prefer public API or MCP tools over website scraping.Locked decision: OpenAPI artifacts must be generated from shared API contract schemas, not hand-rolled as a parallel source of truth.Locked decision: Hosted MCP should expose anonymous public read tools on day one, with anonymous callers treated as a distinct rate-limit class.Locked decision: Hosted public read tools must remain genuinely callable without login in clients that support anonymous/no-auth MCP tools.Locked decision: Token values must never be stored in plaintext. Display newly minted API tokens and OAuth client secrets only once, then store verifier hashes plus metadata.Locked decision: Bearer tokens must not be accepted from URL query parameters.Locked decision: OAuth access tokens must be audience/resource-bound. VRDex must not accept or pass through tokens minted for another resource.Locked decision: Hosted MCP over HTTP follows the current MCP authorization model and Streamable HTTP transport.Locked decision: Hosted MCP readiness requires OAuth protected-resource metadata, authorization-server metadata, constrained Dynamic Client Registration, and public-client Client ID Metadata Document support.Locked decision: Local stdio MCP uses environment or local config credentials and does not try to run the HTTP MCP authorization handshake over stdio.Locked decision: Normal developer apps support user-owned apps plus owner-managed community-owned apps. Staff/admin delegation for community-owned apps is a later capability.Locked decision: Day-one MCP support targets every major MCP client available at implementation time, with required matrix evidence before external readiness.
Current Recommendations
Current recommendation: Treat this asEPIC-12 Public API foundationplus the first implementation wave for#78.Current recommendation: Use one developer platform model for API tokens, OAuth applications, OAuth grants, dynamic MCP client registrations, and MCP access.Current recommendation: Keep anonymous public reads first, then authenticated reads, then narrow audited writes.Current recommendation: Use Convex as the authoritative application data and policy layer, with Next.js route handlers as the public HTTP gateway.Current recommendation: Put the VRDex OAuth authorization server in Next.js route handlers backed by Convex tables and internal Convex functions. Convex remains the data/control plane; Next owns browser redirects, consent UX, metadata endpoints, token routes, CORS, and HTTP semantics.Current recommendation: Do not treat the inbound sign-in providers as the third-party developer OAuth issuer. Clerk remains first-party account authentication — Convex Auth filled that role before the cutover, and the separation is unchanged by the swap; the VRDex developer platform issues its own tokens for external clients.Current recommendation: Keep the first issuer in the web app instead of adding a separate identity provider. VRDex needs app-specific developer ownership, dynamic MCP client handling, self-hosted behavior, quota policy, audit records, and product checks in the same deployment boundary; an external IdP can be revisited only if it cleanly owns those custom platform rules.Current recommendation: Treat the in-app issuer as narrow platform security code, not a broad replacement for first-party login providers. Current MCP/OpenAI guidance favors established identity providers for generic apps, so the VRDex issuer must stay intentionally small, heavily tested, and limited to the OAuth subset this platform needs: metadata discovery, Authorization Code with PKCE, Client Credentials, refresh-token rotation, revocation, constrained DCR, public-client CIMD, resource-bound JWT access tokens, and exact redirect validation.Current recommendation: Use shared TypeScript API contract schemas as the source of truth for runtime validation, response typing, example generation, and OpenAPI generation. Convex validators remain the database/function boundary.Current recommendation: Keep the generated artifact on OpenAPI 3.1.x for Swagger UI andzod-openapicompatibility, even though OpenAPI 3.2.0 is the latest published spec. Track 3.2.0 as a later generator/tooling upgrade, not a launch blocker.Current recommendation: Use Zod 4 pluszod-openapias the first contract toolchain. The implementation spike has validated the route shape enough to keep this as the current path.Current recommendation: Use opaque hashed personal API tokens. Use short-lived RFC 9068-style JWT OAuth access tokens with audience/resource binding, plus opaque refresh-token rotation for user-delegated OAuth flows.Current recommendation: Support OAuth Authorization Code with PKCE for user-delegated apps and Client Credentials for app-only access.Current recommendation: Start normal developer apps with manual OAuth app registration in the VRDex developer dashboard and API. Include constrained Dynamic Client Registration for hosted MCP OAuth on day one, stored separately from user/community-owned apps until reviewed or promoted.Current recommendation: Support Client ID Metadata Documents for hosted MCP public clients that prefer URL-form client IDs over Dynamic Client Registration. Keep DCR available for clients that register automatically, and defer confidential-client CIMD until a real client requires public-key client authentication.Current recommendation: Rate-limit by route class, IP, token, OAuth client, user, app owner, and dynamic MCP client. Do not use one global bucket for every caller.Current recommendation: Use a Redis-compatible TTL counter store for high-volume hosted anonymous public API and MCP traffic. Keep Convex as the durable source for policy, app/token ownership, partner overrides, coarse usage summaries, and audit events.Current recommendation: Use Upstash Redis through the Redis REST adapter for the first BASIC BIT hosted deployment, while keeping the runtime contract vendor-neutral behindVRDEX_RATE_LIMIT_STORE=redis-rest/upstash.Current recommendation: Launch the hosted MCP as read-oriented first, even if the auth platform already supports scopes that make later write tools possible.Current recommendation: Treat anonymous hosted MCP reads as a first-class no-auth tool path. Where a client or SDK supports per-tool auth metadata, public read tools should advertise no-auth access and OAuth as an optional or later privileged path; the server still enforces scopes, audience/resource binding, and rate limits on every request.Current recommendation: For OpenAI/ChatGPT-style MCP clients, advertise public read tools with per-toolnoauthplus optionaloauth2security metadata. The current MCP SDK emits this through the_meta["securitySchemes"]descriptor extension; do not add non-standard top-level tool fields unless the SDK or a verified client surface requires a compatible extension point.Current recommendation: Trusted partner access is a manual review tier with very high quotas compared with normal personal tokens. In the current implementation, atrusted_partnercredential gets a 100x effective quota on authenticated API/MCP traffic classes while credential-management and OAuth handshake routes stay on standard limits.
Candidate Directions
Candidate direction: Add a dedicated API hostname later, but keep the first public route shape under the web app until operational pressure justifies a split.Candidate direction: Keep the adapter interface for rate-limit storage so hosted deployments can move to another Redis-compatible provider later, local development can use an in-memory adapter, and self-hosted production can bring its own Redis-compatible store.Candidate direction: Add an optional generated MCP coverage layer from OpenAPI only after curated tools prove useful.Candidate direction: If OAuth implementation complexity grows beyond the narrow platform subset, revisit an external IdP or adapter-backed issuer before hardeningv1. That revisit should preserve VRDex-owned developer app ownership, community-owner rules, quota tiers, audit events, DCR/CIMD policy, and self-hosted setup.
Interview Later
Interview later: Final default quota numbers for anonymous, personal-token, trusted-partner, and self-hosted callers after production traffic and cost signals exist.Interview later: Whether partner application flows can access anything beyond public data before formal partner contracts exist.Interview later: Whether self-hosted deployments need built-in multi-tenant OAuth issuer support or only one issuer per deployment.Interview later: Whether paid tiers should raise API and MCP limits at launch or only after organic demand appears.Interview later: Which staff/admin delegation workflows are needed for community-owned OAuth apps after the owner-only first pass.
Recommended Backlog Chunk
Deliver this as EPIC-12 Public API foundation and MCP platform: one coherent
PR with commit-level checkpoints for API contracts, generated OpenAPI, auth,
OAuth apps, hosted MCP, local MCP, rate limits, docs, and rollout evidence.
The highest-leverage remaining checkpoint is the major-client MCP matrix, not choosing the final Redis-compatible vendor. The rate-limit vendor choice is intentionally hidden behind the Redis-compatible adapter; the hosted MCP production-like protocol evidence is now available from the staging target, so client compatibility is what unlocks external launch confidence.
Next execution checkpoint:
- Keep the recorded hosted evidence rows for data-backed anonymous reads,
Dynamic Client Registration, and public-client Client ID Metadata Documents
in
docs/developers/mcp-client-smoke-results.json. Current state: data-backed anonymous read, DCR, and CIMD all pass against the same-branch Vercel and Convex preview at0dd64b2in Hosted MCP Preview Smoke run29311948404, job87018585252. Shared staging remains the selected production-like promotion target after the Redis variables are applied. - Complete the remaining installed-client matrix batch against the same
selected target. VS Code local stdio and hosted anonymous reads pass. Cursor
and Windsurf still need real-client evidence. Prefer
pnpm smoke:mcp-cursor-agentfor Cursor local and hosted-anonymous rows when the standalone Agent CLI is installed; keep Cursor IDE and Windsurf on the generated manual session-pack path. Record a row only after the client lists tools and completesvrdex_search. - Complete the Gemini hosted OAuth row with native OAuth or a reviewed-token fallback. Gemini CLI local stdio and hosted anonymous reads already pass through the repeatable CLI harness.
- Complete hosted OAuth coverage for Claude Code, Gemini CLI, MCP Inspector, and OpenAI/ChatGPT product surfaces after a complete credential path exists. Current official docs keep OAuth/DCR/CIMD support in scope, but the rows are blocked on credentials or product-surface access rather than platform design.
- Before hosted-OAuth rows are recorded, rerun
pnpm ops:mcp-hosted-oauth-prereqs. The 2026-07-14 PR #159 audit passes the temporary credential-generation path: hosted auth helpers and developer credentials are enabled and the browser-token secret is present. Reviewed long-lived OAuth smoke secrets and the Inspector token fallback remain optional. Existing hosted targets still need a deployment with the runtime developer-credential gate enabled before temporary credentials can be minted there. - Use
pnpm smoke:mcp-openai -- --hosted-url https://staging.vrdex.net/mcp --hosted-datawithOPENAI_API_KEYfor OpenAI Responses API hosted anonymous-read evidence. The smoke now loads repo-root.env.localif present and directly preflights the hosted MCP target before calling OpenAI, so a local operator key can be durable without being committed or printed and wrong-target runs fail before spending a model call. Keep ChatGPT Apps/Connectors UI and hosted OAuth as product-surface evidence; do not mark those rows ready from local CLI or API-only checks. Current 2026-07-09 evidence is pass against staging after the PR branch staging deploy run29037734496:pnpm smoke:mcp-openaireached the Responses API and the model called both hosted MCPsearchandfetch. The PR preview remains useful as transport evidence, but staging is the current production-like data-backed target for this row.
Client Classes
Anonymous Public Clients
Use cases:
- public profile lookup
- search
- public event discovery
- public world/event association reads
- OpenAPI and docs examples
Properties:
- no bearer credential
- conservative IP and route limits
- cache-friendly responses where visibility rules allow
- no private, unlisted, suppressed, or moderation-only data
Personal API Tokens
Use cases:
- personal scripts
- private MCP configuration
- self-hosted operator workflows
- trusted automation owned by a VRDex user
Properties:
- minted from account developer settings
- scoped
- optionally expires
- revocable
- last-used timestamp and coarse usage metadata
- cannot bypass profile visibility, ownership, or opt-out rules
OAuth User-Delegated Apps
Use cases:
- partner apps acting for a signed-in VRDex user
- desktop clients
- agents that need user approval for scoped access
- hosted MCP user sessions
Properties:
- Authorization Code with PKCE
- explicit user consent screen
- exact redirect URI matching
- short-lived access tokens
- refresh token rotation
- revocable per user and app
- scoped to user-authorized capabilities
OAuth Application Apps
Use cases:
- server-to-server integrations
- partner jobs
- application-owned public data reads
- future approved partner syncs
Properties:
- Client Credentials grant
- no implied user authority
- limited scopes until partner contracts exist
- rate limits tied to OAuth client and owning user/community
- secrets rotatable from the developer dashboard
Dynamic MCP Clients
Use cases:
- hosted MCP clients that need OAuth registration without a hand-created client id
- broad day-one compatibility across major MCP clients
Properties:
- registered through constrained Dynamic Client Registration
- public client type by default
- no client secret unless the client is manually promoted
- limited to MCP resource access
- anonymous/public read and user-delegated read scopes only at first
- lower default trust than manually reviewed developer apps
- rate-limited by dynamic client id, IP, user grant, and route class
First-Party Web App
Use cases:
- normal VRDex product usage
- owner editing flows
- internal admin screens
Properties:
- may share service functions with public API routes
- uses first-party session auth instead of public API tokens
- still goes through the same visibility and permission policy helpers
Hosted MCP
Use cases:
- remote agent integrations
- partner coding agents
- docs-aware public queries
- anonymous search/browser-like public data reads
- user-authorized workflows later
Properties:
- Streamable HTTP transport
- protected by OAuth when a tool needs auth
- public read tools are available without auth where the same data is already safely public
- anonymous callers use the anonymous MCP rate-limit class
- uses MCP resource metadata and audience/resource-bound tokens
Private Or Local MCP
Use cases:
- local developer use
- self-hosted deployment automation
- private community operations
- MCP clients that prefer stdio
Properties:
- package candidate:
@basicbit/vrdex-mcp - stdio transport by default
- configured with
VRDEX_API_BASE_URL - configured with
VRDEX_API_TOKENor a local OAuth token file - no website scraping
- no raw VRChat credential dependency
API Surface Plan
API-0: Anonymous Public Reads
Purpose:
- give public clients and agents stable read endpoints before any write surface exists
Candidate endpoints:
GET /api/v0/profiles/:slugGET /api/v0/profiles/:slug/assetsGET /api/v0/profiles/:slug/logosGET /api/v0/profiles/:slug/logos.zipGET /api/v0/people/:slugGET /api/v0/communities/:slugGET /api/v0/search?q=GET /api/v0/cards/:slugGET /api/v0/worlds/:slugGET /api/v0/worlds/:slug/eventsGET /api/v0/worlds/activeGET /api/v0/events/:slugGET /api/v0/events/upcomingGET /api/v0/people/:slug/eventsGET /api/v0/communities/:slug/eventsGET /api/v0/claims/:slug/status
GET /api/v0/cards/:slug remains explicitly deferred. The compact card
schema, visibility behavior, and relationship to the existing profile response
need a shared contract before this route is implemented; consumers should use
the shipped profile endpoints in the meantime.
Acceptance criteria:
- every response has a documented schema
- not-found, private, opted-out, and suppressed records collapse to a public-safe absence unless a route deliberately exposes a safer status
- examples include trust/provenance labels when data may be mistaken as owner-confirmed
- public pages, API responses, and MCP tools use the same local-time event presentation rules where applicable
API-1: Authenticated Reads
Purpose:
- let users and trusted apps read scoped account-owned or partner-approved data without creating write risk
Candidate endpoints:
GET /api/v0/meGET /api/v0/me/profilesGET /api/v0/me/communitiesGET /api/v0/me/eventsGET /api/v0/developer/tokensGET /api/v0/developer/oauth-appsGET /api/v0/usage/rate-limit
Acceptance criteria:
- API tokens and OAuth access tokens both work through a shared credential validation layer
- responses are scoped by user/app authority
- authenticated reads do not leak unrelated private profile, claim, or moderation state
API-2: Narrow Authenticated Writes
Purpose:
- support the first useful external automation without making claims, moderation, or ownership unsafe
Candidate endpoints:
POST /api/v0/developer/tokensDELETE /api/v0/developer/tokens/:tokenIdPOST /api/v0/developer/oauth-appsPATCH /api/v0/developer/oauth-apps/:clientIdPOST /api/v0/developer/oauth-apps/:clientId/secretsPOST /api/v0/eventsPATCH /api/v0/events/:slugPOST /api/v0/events/:id/assets/upload-intentPATCH /api/v0/profiles/:slugPOST /api/v0/profiles/:slug/assets/upload-intent
Acceptance criteria:
- every write has scope, permission, audit, abuse, and rollback behavior
- ownership or staff capability checks are explicit
- writes that affect public pages have validation and moderation hooks
- claim-level actions still require verified email and product-specific claim checks
Implementation checkpoint:
PATCH /api/v0/profiles/:slugnow updates claimed-owner profile metadata for active owners withprofile:write, refreshes search/vocabulary projections, and writes a profile audit event. Slug changes, claims, publication state, field visibility, outbound links, media-kit assets, and page-builder settings remain out of this checkpoint.POST /api/v0/profiles/:slug/assets/upload-intentnow creates one-time profile media upload intents for active claimed-profile owners withassets:write. Completed uploads are consumed into active public profile assets and optional media-kit placements through the existing upload-token transport.POST /api/v0/profile-assets/upload-intents/:intentIdis now described in the generated OpenAPI contract as the one-time upload-token transport that completes direct file uploads or source imports.POST /api/v0/events/:id/assets/upload-intentremains deferred until event asset storage and placement semantics exist; the profile media-kit path uses existing storage primitives and does not invent an event asset model.
Auth Platform
Data Model
Candidate Convex tables:
apiTokensapiTokenEventsoauthApplicationsoauthApplicationRedirectUrisoauthApplicationSecretsoauthDynamicClientRegistrationsoauthAuthorizationsoauthAccessTokensoauthRefreshTokensoauthConsentsoauthAuthorizationCodesoauthClientEventsmcpToolEventsapiRateLimitEvents
API token fields:
- internal token id
- token prefix for display and lookup
- hashed token verifier
- owner user id
- optional owner community id
- label
- scopes
- status
- expiry
- created at
- last used at
- last used route class
- revoke reason
OAuth application fields:
- client id
- hashed current secret for confidential clients
- client type: public or confidential
- app owner: user or community
- display name
- description
- logo URL
- docs URL
- privacy URL
- terms URL
- redirect URIs
- allowed grants
- allowed scopes
- status
- created at
- reviewed at, if trusted-partner status is later added
Dynamic MCP client registration fields:
- client id
- registration access token hash, if supported
- client name
- client URI
- logo URI
- redirect URIs
- grant types
- response types
- token endpoint auth method
- contacts
- software id/version, if supplied
- allowed scopes
- status
- created at
- last used at
- promoted app id, if manually reviewed later
OAuth grant fields:
- authorization code hash
- PKCE challenge and method
- redirect URI
- user id
- client id
- requested scopes
- approved scopes
- resource indicator
- expiry
- consumed at
Token event fields:
- credential id
- user id, if user-bound
- client id, if OAuth-bound
- route class
- validation result for accepted, revoked, expired, missing-scope, wrong-resource, or not-found credentials
- scope result
- rate-limit result
- status code class
- timestamp
Do not store raw bearer tokens, raw client secrets, or full Authorization headers.
API Token Flow
User flow:
- User opens account developer settings.
- User creates a token with label, scopes, and optional expiry.
- VRDex displays the token value once.
- User copies it into a script, CI secret, or local MCP config.
- API requests use
Authorization: Bearer <token>. - User can see last-used metadata and revoke the token.
Implementation requirements:
- generate high-entropy opaque token values
- include a recognizable prefix such as
vrdx_ - hash the verifier portion before storage
- support immediate revocation
- reject query-string token usage
- add scope checks before data access
- update last-used metadata without logging secrets
OAuth App Registration
User flow:
- Developer creates an OAuth app.
- Developer chooses public or confidential client type.
- Developer registers exact redirect URIs.
- VRDex issues a client id.
- Confidential clients can mint and rotate client secrets.
- Developers can revoke the app or rotate secrets without deleting usage history.
Implementation requirements:
- exact redirect URI matching
- HTTPS redirect URIs except localhost loopback development redirects
- public clients require PKCE
- confidential clients store hashed secrets only
- app ownership supports user-owned apps and owner-managed community apps
- community-owned staff/admin delegation is deferred until broader community authority is stable enough
- reviewed/trusted partner status is a manual operator decision with explicit contact ownership, quota class, monitoring, and revocation
Issuer placement:
- Next.js route handlers own the OAuth HTTP surface.
- Convex stores applications, grants, consents, tokens, rotation state, revocation state, and audit events.
- Next route handlers call Convex queries/mutations/actions for durable state changes.
- Clerk authenticates the signed-in VRDex account during authorization and consent. The route handlers mint a Convex credential from the session with
convexAuthToken(); this was Convex Auth before the Clerk cutover. - A separate OAuth service is deferred until scale, compliance, or cross-app reuse justifies the operational cost.
Rationale:
- OAuth has browser-facing redirects, consent screens, metadata endpoints, token responses, CORS, cookies, and HTTP error semantics that are natural in the web app.
- Convex is still the best place for transactional application state, ownership policy, and audit records.
- A dedicated service would add deployment and self-hosting surface before the product has proven it needs that boundary.
OAuth User-Delegated Flow
Required grant:
- Authorization Code with PKCE
Required endpoints:
GET /.well-known/oauth-authorization-serverGET /oauth/authorizePOST /oauth/tokenPOST /oauth/revokeGET /oauth/jwks.json, if JWT access tokens are used
Candidate optional endpoints:
POST /oauth/introspect, if trusted partners, self-hosted components, or future opaque-token use cases need resource-server lookupPOST /oauth/register, for constrained MCP Dynamic Client Registration if required for major client compatibility- Client ID Metadata Document support for MCP public clients that prefer URL-form client IDs instead of Dynamic Client Registration
Behavior:
- consent screen shows app name, owner, scopes, redirect host, and resource
- auth codes are single-use and short-lived
- access tokens are short-lived
- refresh tokens rotate
- scope downgrades are supported
/oauth/revokesupports JWT access-token revocation and opaque refresh-token revocation; refresh-token revocation also invalidates active access tokens for the same client, user, and resource where stored token state supports that relationship
Token format:
- OAuth access tokens are short-lived JWTs following the OAuth JWT access token profile.
- Required claims include issuer, subject or application subject, audience/resource, client id, scope, issued-at, expiry, and token id.
- Resource servers validate issuer, audience/resource, expiry, signature, scopes, and revoked token ids where needed.
- OAuth refresh tokens remain opaque, hashed, rotated, and stored server-side.
- Personal API tokens remain opaque and hashed; they are not JWTs.
OAuth Application Flow
Required grant:
- Client Credentials
Behavior:
- no user identity is implied
- allowed scopes are constrained by app status
- first version should usually allow public reads and maybe partner-approved ingestion or export scopes only after review
- rate limits bind to client id and owner
Dynamic Client Registration For MCP
Purpose:
- make hosted MCP OAuth work with major MCP clients that cannot rely on a preconfigured VRDex client id
Current recommendation:
- include
POST /oauth/registerfor hosted MCP clients in the first MCP OAuth implementation - support Client ID Metadata Document compatibility for hosted MCP public clients that prefer CIMD as an alternative to Dynamic Client Registration
- restrict dynamically registered clients to public-client behavior until manually reviewed
- allow only exact redirect URIs and localhost loopback development redirects
- allow only MCP resource access and the initial public/read-oriented scopes
- rate-limit registrations by IP, software metadata, and redirect host
- expose dynamic clients separately from manually created normal developer apps in admin/ops views
- allow manual promotion from dynamic MCP client to reviewed developer app later
Implementation checkpoint:
/oauth/registerstores dynamic MCP clients in a separate Convex table from user- and community-owned OAuth applications.- Client ID Metadata Document authorization requests fetch and validate the
client_idURL, then store accepted metadata in the same dynamic MCP client table. - registration is public-client-only and returns no client secret.
/oauth/authorizesupports Authorization Code with PKCE usingcode_challenge_method=S256for public apps, confidential apps, and dynamic MCP clients./oauth/tokenexchanges authorization codes for short-lived resource-bound JWT access tokens and rotating opaque refresh tokens. Confidential apps must authenticate with an active client secret during code exchange and refresh; dynamic MCP clients remain public/no-secret clients.
Scopes
Candidate initial scopes:
public:readprofile:readprofile:writecommunity:readcommunity:writeevents:readevents:writeassets:readassets:writedeveloper:readdeveloper:writemcp:readmcp:write
Scope rules:
- public data still obeys public visibility and suppression rules
- write scopes are necessary but never sufficient
- ownership, staff capability, verified-email state, and object-level policy still run after scope validation
- app-only scopes cannot perform user-owned actions unless an explicit product grant exists
Rate Limiting And Abuse Controls
Rate Limit Dimensions
Use layered identity keys:
- route class
- IP address
- bearer token id
- OAuth client id
- user id
- app owner id
- dynamic MCP client id
- self-hosted deployment id, if introduced later
Route classes:
- anonymous public reads
- authenticated public reads
- developer token/app management
- OAuth authorize/token/revoke
- asset upload intent creation
- public writes
- anonymous MCP public read tool calls
- authenticated MCP tool calls
Backend choice:
- the backend is the storage/execution path for hot per-window request counters, not the source of quota policy or durable audit history
- high-volume hosted anonymous API and hosted MCP counters should use a Redis-compatible TTL counter store
- Convex should store quota policy, token/app ownership, trusted partner overrides, coarse usage summaries, and durable audit events
- local development can use an in-memory adapter
- self-hosted production should document a Redis-compatible option, with Convex-only counters allowed only for low-traffic deployments that accept the cost and write-load tradeoff
Why this is a separate question:
- anonymous public reads can create high-cardinality counters keyed by IP, route class, and window
- those counters expire quickly and do not need to be part of the core product database
- Redis-style increment-plus-expiry counters are a standard fit for public API rate limiting because the data is intentionally short-lived
- trusted app/token policy and audit data are durable business records and do belong in Convex
- separating hot TTL counters from durable policy avoids turning every anonymous search/MCP request into a Convex write
Recommended response behavior:
- include rate-limit headers on public API responses once the header shape is chosen
- use
Retry-Afterfor blocked requests - do not reveal whether a suppressed private record exists while explaining rate-limit state
- log enough metadata to debug abuse without retaining secrets
Quota values:
Interview later: choose real numbers after API endpoint shape and hosting cost are clearerCurrent recommendation: document placeholder classes before implementation, then set conservative defaults in codeCurrent recommendation: trusted partners should have very high practical quotas compared with normal personal tokens, high enough that normal partner workloads do not feel personal-token capsCurrent recommendation: trusted partner access is not literally unmetered; it remains controlled by manual review, contact ownership, monitoring, cost guardrails, and fast revocation instead of a self-serve automatic upgrade
Abuse Rules
- repeated invalid-token usage should produce credential events and eventually temporary blocks
- high-cardinality anonymous search should have stricter limits than direct profile lookup
- token creation and OAuth app creation need lower write limits than normal public reads
- dynamic MCP client registration needs stricter limits than anonymous read tools
- suspicious OAuth redirect changes should require app-owner action and audit history
- revoked, expired, or scope-insufficient credentials should fail before data access
OpenAPI And Swagger Docs
Documentation Surfaces
Required surfaces:
- checked-in OpenAPI description
- generated JSON at a public route
- Swagger UI page in developer docs or the web app
- Docusaurus developer guide with task examples
- API changelog
Candidate paths:
packages/api-contracts/src/schemas.tspackages/api-contracts/src/openapi.tsdocs/api/openapi.yamlapps/web/src/app/api/v0/openapi.json/route.tsapps/web/src/app/developers/api/page.tsxdocs/developers/public-api.mddocs/developers/api-auth.mddocs/developers/api-rate-limits.mddocs/developers/mcp.md
Spec Rules
- generate the OpenAPI document from shared API contract schemas
- keep the generated artifact on OpenAPI 3.1.x until the selected generator and Swagger tooling have stable 3.2.0 support
- describe request and response schemas for every public route
- document auth requirements per operation
- document rate-limit behavior per route class
- include public-safe not-found behavior
- include trust/provenance fields in examples
- keep example payloads short and realistic
- validate the spec in CI
- smoke-test the Swagger UI route visually when UI changes are made
Source Of Truth
Current recommendation: make shared TypeScript API contract schemas the source of truth for the external contract. Generate OpenAPI from those schemas and make route handlers validate requests and representative responses against the same contract layer.
Convex validators remain the database and Convex function boundary. The API contract layer should sit at the public HTTP boundary and translate Convex return values into public response shapes.
Candidate toolchain:
- Zod 4 schemas for public API request/response contracts
zod-openapifor OpenAPI 3.1.x document generation- generated
openapi.jsonandopenapi.yamlchecked in or generated in CI, with a drift check - route tests that validate representative payloads against the shared schemas
- type exports that can be reused by the MCP package
Implementation checkpoint:
- do a short spike before the full implementation PR to prove the chosen generator handles unions, branded IDs, nullable fields, examples, and response variants cleanly
- if Zod/OpenAPI generation creates awkward schema output, choose the next simplest schema-first toolchain rather than falling back to hand-written OpenAPI
MCP Platform
Hosted Public MCP
Transport:
- Streamable HTTP
Candidate endpoint:
/mcp
Current checkpoint:
- implemented in the web app with
@modelcontextprotocol/server - anonymous public read tools are served through the
anonymous_mcp_public_readrate-limit class - OAuth access tokens issued for the MCP resource are accepted for the authenticated MCP rate-limit class
- OAuth protected-resource metadata includes the required
mcp:readscope; non-public OAuth-protected MCP tools remain a later checkpoint
Required metadata:
- OAuth protected resource metadata
- authorization server metadata
- resource indicator support in authorization and token requests
Auth behavior:
- anonymous read tools are required for public-safe search/browser-like read operations
- anonymous read tools must not trigger OAuth or client registration prompts
- clients that support tool-level auth metadata should see these public read tools as callable without auth, while authenticated or future write tools advertise OAuth scopes explicitly
- anonymous MCP callers use separate route classes and quotas from anonymous HTTP API callers
- authenticated tools require
Authorization: Bearer <access-token> - MCP tokens must be issued for the VRDex MCP resource
- do not accept tokens issued for the plain web app, another MCP, or another resource
- return
WWW-Authenticatewith protected resource metadata and required scope hints when bearer tokens are invalid or under-scoped - support constrained Dynamic Client Registration if required by major MCP clients
Day-one client compatibility:
- support Streamable HTTP for hosted MCP
- support stdio for private/local MCP
- maintain an implementation-time compatibility matrix for the major MCP clients available then, including Claude Desktop, Claude Code, Gemini CLI, VS Code/Copilot surfaces, Cursor, OpenAI/ChatGPT MCP-capable surfaces, Devin/Windsurf, and MCP Inspector unless the current ecosystem has shifted
- test anonymous hosted read tools, OAuth hosted tools, and local stdio token configuration separately
- do not declare hosted MCP ready until the matrix covers the mainstream clients VRDex users and partner agents are likely to use
First hosted tools:
vrdex_searchvrdex_get_profilevrdex_get_eventvrdex_list_upcoming_eventsvrdex_get_worldvrdex_list_active_worlds
Later hosted tools:
vrdex_my_profilesvrdex_my_eventsvrdex_event_createvrdex_event_updatevrdex_profile_updatevrdex_asset_upload_intent_create
Safety rules:
- tool outputs are compact by default
- outputs include stable IDs/slugs for follow-up
- provenance is included when needed to avoid false authority
- no private owner account fields
- no moderation-only notes
- no write tool without scope, product permission, audit, and human-approval-friendly design
Private Or Local MCP
Package candidate:
@basicbit/vrdex-mcp
Current checkpoint:
- implemented as the
packages/vrdex-mcpworkspace package - starts a stdio MCP server with the same six curated read tools as hosted MCP
- calls
/api/v0public API routes and validates responses with@vrdex/api-contracts - supports anonymous public reads, personal API tokens, OAuth access tokens, and OAuth token files
- normalizes hosted and self-hosted
VRDEX_API_BASE_URLvalues to the/api/v0route prefix - requires API-resource OAuth tokens because the stdio package calls
/api/v0; hosted Streamable HTTP MCP continues to use MCP-resource OAuth tokens
Transports:
- stdio first
- Streamable HTTP client mode only if useful later
Configuration:
VRDEX_API_BASE_URLVRDEX_API_TOKENVRDEX_OAUTH_ACCESS_TOKENVRDEX_OAUTH_TOKEN_FILEVRDEX_MCP_OUTPUT_MODE, optional compact/detail switch
Behavior:
- uses public API routes, not website scraping
- works against hosted VRDex and self-hosted deployments
- supports personal API tokens from the start
- supports OAuth access tokens directly or from local token files
- does not require private VRChat cookies
Distribution:
- publish local workspace package instructions in developer docs
- include MCP client configuration snippets
- keep install snippets free of real token values
- include self-hosted base URL examples
- add registry publishing instructions after the package is ready to ship outside the monorepo
Private Hosted MCP For Self-Hosting
Self-hosted operators may want a deployment-private MCP endpoint for staff or community automation.
Current recommendation:
- use the same MCP server codepath
- use the deployment's own OAuth issuer and API tokens
- allow operators to disable public anonymous tools
- document environment variables and reverse-proxy requirements
- do not create a separate unaudited admin MCP surface
Developer And Admin UX
Developer Dashboard
Candidate routes:
/account/developers/account/developers/tokens/account/developers/apps/account/developers/apps/:clientId/account/developers/usage
Required capabilities:
- create API token
- revoke API token
- inspect token last-used metadata
- create OAuth app
- edit OAuth app metadata
- manage redirect URIs
- rotate client secret
- revoke OAuth app
- view active user grants for owned apps
Implemented in the platform foundation: owners can list and revoke API tokens and OAuth apps. Active user-grant visibility and management UI is deferred from this foundation; the OAuth grant and revocation primitives remain available for a later account surface.
First ownership pass:
- user-owned developer apps
- community-owned developer apps for claimed community profiles managed by the active singleton owner
- staff/admin delegation for community-owned developer apps after broader community authority is stable enough
- dynamically registered MCP clients visible to admins/operators, not normal self-serve developer app management at first
UX rules:
- use crisp labels, not explanatory filler
- show token values only once
- show redirect URI validation errors inline
- keep scopes human-readable
- separate app ownership, app identity, and credential management
- show destructive actions with clear confirmation
Consent Screen
Required display:
- app name
- app owner
- requested scopes
- redirect host
- whether the app is reviewed/trusted, if that concept exists
- what VRDex account is authorizing the request
Required actions:
- approve
- cancel
- scope downgrade if supported
Admin And Operations
Required capabilities:
- inspect suspicious API clients
- revoke API tokens and OAuth apps
- suspend token creation for an abusive account
- view rate-limit events
- view OAuth app metadata history
- audit write actions performed through API or MCP
Implemented in the platform foundation: owner revocation for API tokens and OAuth apps; route-class rate limiting; durable rate-limit, credential, and OAuth grant events; MCP tool-call events; and API write-audit events with sanitized operator summaries.
Explicitly deferred from this foundation:
- active user-grant UI
- suspicious API-client detail views
- account-level API token-creation suspension
- OAuth app metadata history
Infrastructure And Self-Hosting
Candidate Environment Variables
Public URLs:
VRDEX_PUBLIC_APP_URLVRDEX_PUBLIC_API_BASE_URLVRDEX_OAUTH_ISSUER_URLVRDEX_MCP_RESOURCE_URI
Secrets and signing:
VRDEX_API_TOKEN_PEPPERVRDEX_OAUTH_ACCESS_TOKEN_SIGNING_KEY, if JWT access tokens are usedVRDEX_OAUTH_ACCESS_TOKEN_SIGNING_KID, optional JWT key idVRDEX_OAUTH_REFRESH_TOKEN_PEPPERVRDEX_OAUTH_CLIENT_SECRET_PEPPER
Rate limiting:
VRDEX_RATE_LIMIT_STORE, currentlymemory,redis-rest,upstash, ordisabledVRDEX_RATE_LIMIT_REDIS_REST_URL, if a Redis-compatible REST adapter is selectedVRDEX_RATE_LIMIT_REDIS_REST_TOKEN, if a Redis-compatible REST adapter is selectedVRDEX_RATE_LIMIT_REDIS_URL, if a direct Redis adapter is added laterVRDEX_RATE_LIMIT_REDIS_PREFIX, if shared Redis infrastructure is used
Feature flags:
VRDEX_PUBLIC_API_ENABLEDVRDEX_DEVELOPER_DASHBOARD_ENABLEDVRDEX_HOSTED_MCP_ENABLEDVRDEX_OAUTH_DYNAMIC_CLIENT_REGISTRATION_ENABLED
Docs:
- each variable needs owner, scope, default, hosted value source, self-hosted setup path, and rotation notes where applicable
Deployment Requirements
- HTTPS for production OAuth and MCP endpoints
- loopback redirect support for local OAuth clients
- documented Convex environment variables
- checked-in route and environment inventory
- no dashboard-only required variables without docs
- self-hosted base URL examples in API, Swagger, and MCP docs
Security Requirements
- reject bearer tokens in query strings
- exact-match OAuth redirect URIs
- PKCE for public clients
- HTTPS for production OAuth endpoints
- audience/resource validation for OAuth access tokens
- refresh-token rotation
- token revocation
- client-secret rotation
- least-privilege scopes
- object-level authorization after scope validation
- audit logs for write actions
- secret redaction in logs
- CORS rules for public API routes
- CSRF protection for browser-based OAuth and developer dashboard actions
Observability
Required signals:
- API request counts by route class, currently backed by hot aggregate route-class counter keys in the active rate-limit backend rather than Convex per-request writes
- rate-limit blocks by route class and identity type, currently backed by
apiRateLimitEventsrows that omit raw identity values and rate-limit keys - OAuth grant success/failure counts, currently summarized from
oauthClientEvents - token validation failures, currently summarized from
apiTokenEventsandoauthClientEvents - MCP tool invocation counts, currently backed by
mcpToolEventsrows keyed by curated tool name and accepted MCP route class - write action audit trails, currently backed by
apiWriteAuditEventsfor public API profile writes, event writes, upload-intent creation, and upload completion - revoked credential usage attempts, currently backed by rejected validation
rows in
apiTokenEventsandoauthClientEvents
pnpm ops:api-platform-observability prints a bounded-window summary of these
durable Convex event rows. Hot request-count totals by route class remain in
the active rate-limit backend and are read with pnpm ops:api-rate-limit-counts.
Do not log:
- bearer token values
- OAuth client secrets
- full authorization headers
- private profile fields returned only to authorized users
Delivery Plan For One PR
Slice 1: Contracts And Route Helpers
Deliverables:
- shared API contract schema package or module
- shared public API response helpers
- auth error helpers
- public-safe not-found helper
- scope and route-class definitions
- generated OpenAPI skeleton
- docs links from existing public API and MCP pages
Validation:
- unit tests for response helpers and scope parsing
- OpenAPI lint or schema validation
- generated OpenAPI drift check
git diff --check
Slice 2: Anonymous Public Reads And Swagger
Deliverables:
- public read endpoints for profiles, search, events, worlds, and claim status
- OpenAPI operation definitions generated from shared contract schemas
- Swagger UI route/page
- public API examples
Validation:
- route integration tests
- schema/example validation
- visual screenshot review for Swagger/developer docs UI
Slice 3: API Tokens
Deliverables:
apiTokensstorage- token mint/revoke routes
- developer dashboard token UI
- bearer token validation
- route-class rate-limit hook
- token docs
Validation:
- token generation/hash/revocation tests
- E2E token mint and API call
- query-string token rejection test
- visual review for token UI
Slice 4: OAuth Apps And Grants
Deliverables:
- Next.js OAuth route handlers backed by Convex state
- OAuth app registration UI
- Authorization Code with PKCE
- Client Credentials
- constrained Dynamic Client Registration for hosted MCP if required by compatibility testing
- token, revoke, and metadata endpoints
- consent screen
- OAuth docs
Validation:
- PKCE tests
- redirect URI tests
- consent flow E2E with test client
- token audience/resource tests
- revocation tests
- dynamic MCP client registration tests if enabled
Slice 5: Hosted MCP
Deliverables:
- Streamable HTTP MCP endpoint
- MCP resource metadata
- read-only curated tools
- anonymous public read tool access
- OAuth-protected tool path
- major MCP client compatibility matrix
- MCP docs
Validation:
- MCP handshake tests
- tool contract tests
- anonymous public read tool tests
- invalid audience/resource test
- auth-required
WWW-Authenticatetest - compatibility smoke tests for major hosted MCP clients available at implementation time
Slice 6: Private/Local MCP Package
Deliverables:
@basicbit/vrdex-mcppackage or workspace- stdio transport
- API token config
- hosted and self-hosted base URL config
- MCP client install snippets
Validation:
- package smoke test
- local stdio tool call test
- self-hosted base URL fixture test
Implementation checkpoint:
packages/vrdex-mcpnow provides the stdio workspace package- package tests cover config loading, API route calls with bearer credentials,
self-hosted base URL normalization, and a JSON-RPC stdio
vrdex_searchcall against a local API fixture
Slice 7: Rate Limits, Audit, And Operations
Deliverables:
- configured default rate-limit classes
- Redis-compatible TTL counter adapter for hosted high-volume anonymous API/MCP traffic
- in-memory adapter for local development
- usage metadata
- credential event logs
- operational admin views or scripts
- docs for quota classes and escalation
Validation:
- rate-limit tests by identity type
- revoked token usage event test
- Redis adapter TTL/window tests
- admin/ops docs review
Implementation checkpoint:
- default route-class policies are exported from the web rate-limit helper
pnpm ops:api-rate-limitsprints standard and trusted-partner policy tables for operators- Redis REST fixed-window counter behavior is covered by direct TTL/window tests
- revoked API-token validation maps to a rejected usage-event metadata shape in backend tests
docs/developers/api-rate-limits.mddocuments store modes, standard and trusted-partner quotas, response headers, credential events, and trusted-partner escalation
Slice 8: Final Docs And Rollout
Deliverables:
- public API guide
- auth guide
- rate-limit guide
- OAuth app guide
- MCP guide
- self-hosted environment inventory
- changelog entry
- issue/PR checklist
Validation:
- docs build
- docs link check if available
- visual screenshot evidence for any changed UI
- all lint/type/test jobs required by repo merge policy
Implementation checkpoint:
- final developer docs now include API auth, OAuth apps, rate limits, MCP read tools, an MCP client compatibility matrix, an API/MCP changelog, and a rollout checklist
- self-hosting docs include the current API, OAuth, hosted MCP, rate-limit, and local stdio MCP environment inventory
- production-like hosted MCP evidence is now tracked as structured matrix rows for data-backed anonymous reads, Dynamic Client Registration, and Client ID Metadata Document coverage, separate from manual client UI smoke rows
Suggested Issue Slices
If this epic is split before implementation, keep the issue count small:
- Public API contracts, OpenAPI, and Swagger docs.
- API token auth, developer token UI, and Redis-compatible rate limits.
- OAuth app registry, Next.js-backed issuer routes, Authorization Code with PKCE, Client Credentials, and metadata endpoints.
- Hosted VRDex MCP with anonymous public reads, OAuth, Dynamic Client Registration, public-client Client ID Metadata Documents, major-client compatibility evidence, and read-only curated tools.
- Private/local
@basicbit/vrdex-mcppackage with token and OAuth configuration. - Developer docs, self-hosting docs, observability, and rollout checks.
For a single PR, these become commit-level checkpoints instead of separate merge units.
Verification Matrix
Required before green PR implementation readiness:
- lint
- typecheck
- unit tests for token, OAuth, scope, rate-limit, and schema helpers
- route integration tests for anonymous and authenticated API requests
- route-handler tests for OAuth Dynamic Client Registration, including schema normalization, rate-limit errors, and backend failures
- OpenAPI validation
- Swagger UI smoke test
- API token E2E
- OAuth test-client E2E
- hosted MCP handshake/tool tests
- hosted MCP data-backed public read smoke against a same-branch or production-like backend
- hosted MCP tool descriptor auth metadata tests
- stdio MCP smoke test
- MCP tool auth metadata verification for anonymous/no-auth public reads where a major client requires per-tool declarations
- docs build
- visual verification for developer dashboard, consent screen, and Swagger docs
Required before external readiness:
- every representative launch-gating MCP client row is
pass, with at least two distinct clients for stdio, two for hosted anonymous HTTP, and one for authenticated hosted HTTP - named non-gating client rows remain tracked but may be
pending; only a passing row supports a client-specific compatibility claim - production-like hosted data-backed read, DCR, CIMD, and OAuth evidence is
pass pnpm verify:api-mcp-rollout:externalpasses- the manual
External API and MCP Readinessworkflow is green and its client session pack is retained with the launch evidence
Security-specific tests:
- revoked token is rejected
- expired token is rejected
- missing scope is rejected
- invalid OAuth audience/resource is rejected
- redirect URI mismatch is rejected
- PKCE verifier mismatch is rejected
- bearer token in query string is rejected
- private/suppressed record reads return public-safe absence
- rate-limited requests do not leak object existence
Documentation Updates Required With Implementation
docs/developers/public-api.mddocs/developers/vrdex-mcp-read-tools.mddocs/developers/self-hosting-and-iac.mddocs/deployment/convex-environments.md- Docusaurus API reference pages
- OpenAPI description
- MCP install/config guide
- environment variable inventory
- changelog or release note
Source Trail
- MCP Authorization
- MCP Transports
- MCP remote server guide
- MCP Inspector
- Claude Code MCP docs
- Gemini CLI MCP servers
- VS Code MCP servers
- Devin Desktop / Windsurf Cascade MCP
- OpenAI MCP and Connectors
- OpenAI Apps SDK authentication
- OpenAI Apps SDK reference
- OpenAPI Specification
- Zod 4 JSON Schema conversion
- zod-openapi
- Convex HTTP actions and server APIs
- Convex function auth
- Convex Auth
- OAuth 2.1 draft
- RFC 9700: Best Current Practice for OAuth 2.0 Security
- RFC 8414: OAuth 2.0 Authorization Server Metadata
- RFC 7591: OAuth 2.0 Dynamic Client Registration Protocol
- OAuth Client ID Metadata Document draft
- RFC 9728: OAuth 2.0 Protected Resource Metadata
- RFC 8707: Resource Indicators for OAuth 2.0
- RFC 9068: JSON Web Token Profile for OAuth 2.0 Access Tokens
- RFC 7009: OAuth 2.0 Token Revocation
- RFC 7662: OAuth 2.0 Token Introspection
- RFC 6585: 429 Too Many Requests
- RFC 9457: Problem Details for HTTP APIs
- Redis rate limiter pattern
- Upstash Redis REST API
- Upstash Terraform provider
- Vercel Redis
Follow-Up Decisions From Maintainer Review
- OpenAPI should be generated from shared schemas rather than hand-rolled.
- OAuth issuer placement is a technical design decision; current recommendation is Next.js route handlers backed by Convex state because VRDex needs self-hostable, app-specific ownership, dynamic MCP client handling, and product policy checks in the same deployment boundary.
- OAuth access token format is a technical design decision; current recommendation is short-lived RFC 9068-style JWT access tokens plus opaque rotated refresh tokens.
- The rate-limit backend question means where high-cardinality request counters live. This is not a question about whether Convex owns developer apps, quotas, trust policy, or audit state.
- Hosted production should use Redis-compatible TTL counters for anonymous/high-volume API and MCP traffic. Convex keeps durable ownership, policy, review, summary, and audit records.
- Hosted MCP should support anonymous public read tools from day one, and anonymous callers should be treated as anonymous accounts for rate-limiting purposes.
- Day-one MCP support should target every major MCP client available at implementation time through a compatibility matrix.
- Current recommendation: external readiness uses representative client and protocol evidence rather than exhaustive confirmation in every named product. Require at least two passing clients for stdio, two for hosted anonymous HTTP, one for authenticated hosted HTTP, plus hosted data, DCR, and CIMD evidence. Keep other named clients as nonblocking follow-ups and make no client-specific claim until its row passes.
- Current client research keeps Gemini CLI in the day-one MCP matrix because its official docs cover stdio, SSE, Streamable HTTP, OAuth discovery, Dynamic Client Registration, and
/mcp auth; its passing stdio and hosted-anonymous rows are part of the representative launch evidence. - First-pass developer apps support user-owned apps and owner-managed community-owned apps.
- Community-owned OAuth app staff/admin delegation should be considered after broader community authority is stable enough.
- Trusted partner access is manually reviewed by BASIC BIT operators and gets much higher practical quotas than normal personal tokens for authenticated API/MCP traffic, while retaining monitoring, cost controls, and revocation.
- Current MCP/OAuth research says DCR and public-client CIMD should both remain in the hosted MCP path. OpenAI/ChatGPT-style clients prefer CIMD when available, while Claude Code and other clients can use DCR or preconfigured OAuth credentials.
- Confidential-client CIMD with public-key client authentication remains deferred until a concrete major-client requirement appears.
- OAuth signing-key rotation keeps the active private signing key in
VRDEX_OAUTH_ACCESS_TOKEN_SIGNING_KEY, advertises the active key id throughVRDEX_OAUTH_ACCESS_TOKEN_SIGNING_KID, and retains previous public keys throughVRDEX_OAUTH_ACCESS_TOKEN_ADDITIONAL_PUBLIC_JWKSuntil outstanding access tokens expire. - Hosted MCP auth metadata should make anonymous public read tools genuinely usable without login in clients that distinguish
noauthfrom OAuth tools. The current hosted MCP tool descriptors expose_meta["securitySchemes"]withnoauthplus optionaloauth2/mcp:read; client-specific UI behavior remains part of the manual matrix. - Hosted MCP smoke coverage is split into lightweight transport/descriptor coverage and production-like data-backed coverage. The data-backed path is gated by
VRDEX_MCP_SMOKE_DATA/--hosted-dataand requires nonemptyvrdex_searchresults plus OpenAI-compatiblesearch/fetchevidence from the same target. Current PR #159 same-branch evidence at8144d47passes data-backed anonymous read, DCR, CIMD, authenticated bootstraptools/list, and MCP Inspector OAuth in Deployed Health Checks run29288588007. Shared staging promotion still waits on the Terraform-owned Redis rate-limit variables; historical transport-level passes do not satisfy production-like readiness.
Remaining Open Research
- Track OpenAPI 3.2.0 generator and Swagger UI support. The current checked-in artifact stays on 3.1.x.
- Automate OAuth signing-key rotation in deployment secret management after the hosted secret store workflow is wired. The current checkpoint documents and supports manual current-key plus retained-previous-public-key rotation.
- Apply the first BASIC BIT hosted rate-limit store through
infra/terraform/rate-limit-redisonce operator Upstash credentials are available. The stack now owns the Upstash Redis database plus hosted Vercel rate-limit variables; Vercel KV is not a new-project option, and any Marketplace Redis integration should still wire VRDex through the Redis REST adapter variables. - Continue the named-client smoke matrix against deployed preview or production-like environments as product access permits. Track results in
docs/developers/mcp-client-smoke-results.json; treat reproducible protocol incompatibilities as release bugs while leaving unexercised non-gating product rows as follow-up evidence. - Build active user-grant management UI, suspicious-client detail views, account-level API token-creation suspension, and OAuth app metadata history after the platform foundation.
- Verify OpenAI/ChatGPT-style client behavior against the hosted MCP tool descriptors. The current SDK supports
_meta["securitySchemes"]; if a verified client surface requires a different standard field later, add that through an SDK-supported path or a narrow compatibility shim. - Decide whether confidential-client CIMD is needed after the deployed major-client smoke matrix. If yes, add public-key client authentication rather than shared-secret behavior.
- Choose final default quota numbers and partner escalation thresholds after initial traffic and operator cost signals exist.