MCP Server
Pawtograder exposes a Model Context Protocol (MCP) server as a Supabase Edge Function. This page covers the implementation: how authentication works, what the RLS guarantees are, what tools are available, and how to extend the server. For instructor-facing setup (connecting Claude Desktop, creating API tokens, using the AI Help button), see AI assistance for helping students.Architecture
The MCP server is a Supabase Edge Function that speaks streamable HTTP MCP. In production it is reachable at:npx supabase start (the Supabase CLI also
prints a convenience MCP URL at http://127.0.0.1:54321/mcp).
The function shares types and helpers with the rest of Pawtograder’s
edge functions under supabase/functions/_shared/. Database queries go
through the standard typed Supabase server client, so every query
respects the same Postgres row-level security policies the rest of the
app uses.
Authentication
The server accepts long-lived JWTs issued by Pawtograder’s API token system (Settings → API Tokens) in theAuthorization: Bearer <token>
header. Token properties:
- Issued and signed by Pawtograder; carry the issuing user’s identity.
- Scoped to MCP read access (
mcp:read). - Revocable from the UI; revocation is checked on every request.
- Tracked with a
last_used_attimestamp for audit.
401.
Authorization and RLS
Authorization happens in two layers:- Role gate – Before any tool runs, the server checks that the
authenticated user has
instructororgraderrole in the class targeted by the request. Students cannot use the MCP server, even with a valid token. - Postgres RLS – Every database query runs as the authenticated user, so the same RLS policies that govern the web app also govern MCP responses. There is no service-role escalation inside tool handlers.
- The
userstable is never queried directly from tool handlers. - The
is_private_profileflag is not exposed in any tool response. - All access goes through views and tables already guarded by RLS.
Available tools
The full tool list is defined in the edge function source. At time of writing it covers: Contextget_help_request— help request plus full chat historyget_discussion_thread— thread plus repliesget_assignment— assignment spec,handout_url, and rubric
get_submission,list_submission_files,get_submission_fileslist_submission_tests,get_test_output,get_submission_build_output
list_grader_files,get_grader_fileslist_handout_files,get_handout_files
search_help_requests,search_discussion_threadsget_submissions_for_student
Assignment handout context
Assignments carry an optionalhandout_url column that points to the
spec students see. Several tools (notably get_assignment and the help
request / thread context tools) include handout_url in their response
so that an AI assistant can fetch the assignment description without
needing additional credentials.
Extension points
Common reasons to extend the MCP server:- Adding a tool — Define the tool descriptor (name, parameters,
description) and implement the handler. Read data through the
authenticated Supabase client so RLS is enforced automatically. Add
the tool to the registry so it shows up in
tools/list. - Expanding context — When you add fields to existing tools, prefer composing existing queries over loosening RLS. If a new field requires privileged access, surface it through a dedicated view with explicit RLS rather than service-role queries inside the handler.
- New auth scopes — The API token system supports multiple scopes.
If a tool needs to mutate state (e.g. posting a draft response), add a
new scope rather than overloading
mcp:read.
Troubleshooting
401 Unauthorized
- Token revoked, expired, or malformed.
- Missing
Authorization: Bearerheader.
403 Forbidden
- The user is authenticated but not an instructor or grader in the class the request targets.
404 from a tool with no data
- The query succeeded but RLS filtered the result to empty. Verify the user really has access in the web app.
Local server not reachable
- Confirm Supabase is running:
npx supabase status. - Confirm the edge function is being served (the Supabase CLI runs
edge functions automatically when you start it; if you are using
npx supabase functions servemanually, make suremcp-serveris in the served set).
Contributing
The MCP server lives undersupabase/functions/mcp-server/ in the
platform repo. When changing
tool signatures, regenerate any shared types (npm run client-local)
and update the staff-facing docs in
staff/ai-assistance.mdx if the tool list or
setup flow changes.