Remote Study Hub MCP¶
Study Hub exposes a guarded Model Context Protocol endpoint for compatible remote AI clients. It lets a signed-in learner search canonical course material, inspect their synchronized AI history and progress, continue the same Tutor session used by the native app, and explicitly save personal notes or source-grounded flashcards. The connector is disabled by default and never grants owner, publication, plugin-administration, filesystem, or provider-credential access.
Endpoint and authentication¶
The production resource URL is https://tuestudyhub.xyz/mcp; isolated acceptance uses
https://test.tuestudyhub.xyz/mcp. A client that receives 401 discovers OAuth through
/.well-known/oauth-protected-resource/mcp, whose authorization server is the configured Supabase
Auth origin. The endpoint uses stateless Streamable HTTP and accepts bearer tokens in the
Authorization header.
Before enabling the route, configure the hosted Supabase project as an OAuth 2.1 authorization
server and set its application authorization path to /oauth/consent. Supabase combines this path
with the project's production Site URL, so the consent UI remains
https://tuestudyhub.xyz/oauth/consent during isolated acceptance while only the test MCP resource
is enabled. Do not change the shared project's Site URL to the test origin: that would disrupt
production authentication. Register each client's exact redirect URI, or enable dynamic client
registration only for clients and redirect policies that have been reviewed. Keep Google as the
Study Hub identity provider. The issued access token must contain the configured Supabase issuer, the authenticated
audience, an unexpired session, and an OAuth client_id. An ordinary Study Hub browser session token
has no OAuth client_id and is deliberately rejected. The server validates the token and its current
user through Supabase on every request, then derives the account identity from verified claims;
account IDs supplied in tool arguments are never accepted.
The connector requires these runtime values:
NEXT_PUBLIC_SUPABASE_URL=https://PROJECT_REF.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=...
STUDYHUB_MCP_ENABLED=1
The isolated test app keeps ACCOUNT_SYNC_ENABLED=0 and
NEXT_PUBLIC_ACCOUNT_SYNC_ENABLED=0; the MCP server uses the verified bearer token directly and
does not enable browser sync in a second environment. Production account sync can therefore remain
available while MCP acceptance runs on the test resource. The production consent UI uses the
already-enabled production browser configuration.
Do not add Claude, OpenAI, or other client credentials to Study Hub. OAuth grants access only to the learner's Study Hub account. Settings → Account & sync → Connected AI clients lists active grants and revokes the selected client's OAuth sessions and refresh tokens. Signing out of the Study Hub browser alone is not a substitute for revoking a separate remote grant. Test revocation before production enablement.
Capabilities¶
Read tools are studyhub_search, studyhub_get_source, studyhub_list_courses,
studyhub_get_course, studyhub_get_topic, studyhub_export_topic_markdown,
studyhub_get_course_graph, studyhub_list_conversations, studyhub_get_conversation,
studyhub_get_tutor_state, studyhub_get_progress, studyhub_list_personal_records,
studyhub_get_personal_record, and studyhub_list_due_reviews. Equivalent resource templates are
available at studyhub://course/{id}, studyhub://source/{id},
studyhub://conversation/{id}, and studyhub://tutor/{id}. Course and source reads use published
canonical material. Conversation, Tutor, progress, personal-record, and review reads are restricted
to the authenticated account.
Tutor mutations are studyhub_start_tutor, studyhub_answer_tutor, studyhub_request_hint,
studyhub_request_explanation, studyhub_pause_tutor, and studyhub_resume_tutor. They call the
same application service as the native Study Hub UI. Every continuation carries both the exact
Tutor revision and canonical cloud version. If either is stale, read studyhub_get_tutor_state
again and retry from the returned versions; never guess or increment versions in the client.
Personal mutations are studyhub_create_note, studyhub_update_note, studyhub_delete_note,
studyhub_save_flashcards, studyhub_write_annotation, studyhub_grade_review, and
studyhub_record_progress_event. Update and delete operations require the current cloud version:
read it from studyhub_get_personal_record or studyhub_list_personal_records, which return
cloudVersion for exactly this purpose. Never guess or increment a version in the client.
Notes and highlights share the annotation domain and differ only by anchor:
studyhub_create_note writes a block anchor, while studyhub_write_annotation writes a text anchor.
Both must point to a canonical internal block. studyhub_delete_note therefore deletes either one
and remains the only destructive tool. Flashcard decks use a strict versioned schema, bounded text
and card counts, and validated Study Hub source IDs. Progress events are immutable: the server owns
their IDs and timestamps and accepts only canonical course scopes.
studyhub_grade_review schedules through the same SM-2 function as the native review session, with
one difference: exam-date compression reads browser storage and is unavailable server-side, so an
item graded over MCP is scheduled without the exam-date pullback it would receive in the app. All
MCP writes enter the ordinary account sync stream, so native browser repositories see them on their
next pull without an import step.
The persistent per-account limits are 120 read operations, 30 Tutor operations, and 30 personal writes per minute. Families and accounts are isolated. Tool results expose safe application data, not Supabase rows, access tokens, provider errors, or hidden model reasoning.
Connecting a client¶
Add https://tuestudyhub.xyz/mcp as a remote MCP server in the client. The client calls /mcp,
receives 401, and discovers OAuth through /.well-known/oauth-protected-resource/mcp, so no
server-side registration is required. A browser then opens to Supabase, asks for Google sign-in
into the learner's Study Hub account, and shows the Study Hub consent screen at /oauth/consent.
Review the listed capabilities and choose Allow connection; the client receives an access token
and connects. The grant is per-account, not a shared credential.
- Claude Desktop: Settings → Connectors (or Developer → MCP servers) → add a remote MCP server and paste the URL.
- Claude Code:
claude mcp add --transport http studyhub https://tuestudyhub.xyz/mcp. - ChatGPT desktop app: Settings → Connected apps (or Connectors) → MCP → connect to a remote MCP server and paste the URL.
Revoke a grant later from Settings → Account & sync → Connected AI clients; signing out of the browser alone does not revoke the client's OAuth grant. Custom remote MCP and OAuth availability varies by client and plan, so a client that cannot run the OAuth flow cannot connect.
Client differences¶
Clients differ in whether custom remote MCP, OAuth, resource templates, and write tools are available on a particular account plan. A client that cannot invoke writes can still use the read-only tools. Claude or ChatGPT supplies the model that decides when to call MCP; its conversation is not copied into Study Hub automatically. Only explicit tool calls create or change Study Hub records. Do not describe subscription-backed usage as unlimited or as provider API access.
Record exact client names, versions, plan restrictions, OAuth behavior, resource support, and tool approval behavior during isolated acceptance. These observations are deployment evidence, not a portable server contract.
Guarded rollout and rollback¶
As of 2026-08-28 the hosted project runs its OAuth 2.1 authorization server with the authorization
path /oauth/consent and dynamic client registration enabled, the MCP migrations are applied, and
both the isolated test resource https://test.tuestudyhub.xyz/mcp and the production resource
https://tuestudyhub.xyz/mcp are enabled. Each returns 401 with OAuth discovery metadata until a
verified bearer token is presented. Dynamic registration lets a remote client register itself, so
the acceptance evidence below must include the exact client name and redirect URI observed on the
consent screen.
Apply the reviewed Supabase migrations and run database tests before enabling any environment. Keep
production off while setting STUDYHUB_MCP_ENABLED=1 only in the isolated test environment, rebuild
the container, and verify with one supported Claude client and one supported ChatGPT client:
- OAuth discovery, login, disconnect, and revocation.
- Search, source, conversation, Tutor-state, and progress reads.
- Native Tutor start, MCP continuation, then native continuation with one coherent revision chain.
- Note and flashcard writes becoming visible through ordinary browser sync.
- Stale Tutor and cloud-version rejection, cross-account isolation, rate-limit isolation, and the
disabled route returning
404.
If any check fails, set STUDYHUB_MCP_ENABLED=0 in that environment and recreate the app container.
This removes endpoint discovery without deleting synchronized records already created by accepted
tool calls.
Production MCP was enabled on 2026-08-28 after the isolated test acceptance above passed, so the
production environment now also carries STUDYHUB_MCP_ENABLED=1. To disable it, set
STUDYHUB_MCP_ENABLED=0 in the production environment file and rebuild the production container;
the same flag governs the test resource in its own environment file. Disabling one environment does
not disable the other.
Verification¶
npm exec vitest run src/mcp src/ai/application src/app/mcp src/app/api/ai
npm run test:db
npm run check
The database command needs the local Supabase Docker stack. A unit-test pass is not a substitute for the pgTAP authorization, compare-and-swap, and rate-limit checks.