Paxaver MCP Server
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
> AI-facing adapter over the Paxaver school community platform.
> Implements the Model Context Protocol (MCP) on Cloudflare Workers with RS256 JWT
> validation, capability-first authorization, and Streamable HTTP transport.
---
What this is
The Paxaver MCP server lets AI assistants (ChatGPT, Claude, Perplexity, and any
MCP-compatible client) act on behalf of a Paxaver user: check a lunch menu, order
lunch, review wallet balance and transaction history, register for fundraising
events, enroll students in school programs, volunteer, and — for school
administrators — manage restaurants, menu items, events, attendee check-in,
volunteer shifts, program waitlists, and daily orders.
It is a **thin adapter**. It contains no business logic and never touches the
database, Stripe, or email directly. Every action is delegated to the private
Paxaver backend API over a Cloudflare **service binding** (same region, no public
network hop). The MCP server's only responsibilities are:
- MCP protocol handling (JSON-RPC 2.0, Streamable HTTP)
- RS256 JWT validation via JWKS from the centralized Paxaver auth worker
- Per-tool capability policy and role gating
- Sanitized, user-safe error mapping
Authentication is handled by the regional Paxaver auth servers
(paxaver.ca/auth, paxaver.com/auth, paxaver.mx/auth), which issue the
OAuth 2.0 / OIDC tokens. The MCP server shows one facade authorization server
on its own origin: the user picks the country of their account at login, and
the facade routes each OAuth call to that region. The MCP server validates the
resulting RS256 JWTs and forwards them to the backend.
---
Architecture
The MCP worker **never** binds D1, Stripe, or SES. The service binding forwards
the caller's OAuth access token (RS256 JWT) as Authorization: Bearer; the
backend validates it via JWKS and runs its own authorization pipeline, so every
action is attributed to the authenticated Paxaver user. See
docs/architecture.md for the full picture.
---
Quick start
Install
Develop locally
The local dev server starts on http://localhost:8787. Discovery endpoints live
under /.well-known/; the MCP endpoint is POST /mcp.
> **Note:** Local development without the PAXAVER_API_* service bindings falls
> back to authenticated HTTPS against API_BASE_URL_CA, API_BASE_URL_US, and
> API_BASE_URL_MX (default http://localhost:8787). For full integration
> testing, run the Paxaver backend worker locally; the defaults already point at
> it.
---
Deployment
Two environments, each a separate Worker with its own custom domain:
| Environment | Worker name | Domain |
| ------------ | --------------------- | ----------------- |
| staging | paxaver-mcp-staging | mcp.paxaver.dev |
| production | paxaver-mcp | mcp.paxaver.com |
The production worker serves CA, US and MX users through a single endpoint
(mcp.paxaver.com). User region is resolved from the JWT issuer (iss),
and the worker routes to the correct regional backend via service bindings
(PAXAVER_API_CA, PAXAVER_API_US, PAXAVER_API_MX). Currency is determined by the user's
school, not by the MCP endpoint.
Docker
The Dockerfile runs the worker locally via wrangler dev, proxying the
production backends over HTTPS:
The image sets REVOCATION_CHECK=skip, because a self-hosted server does not
have INTERNAL_SERVICE_SECRET. Tokens are still checked by signature, expiry
and a live user-context load, but the internal token revocation check does not
run: a revoked token stays valid until it expires. The container runs as the
unprivileged node user. ALLOWED_ORIGINS keeps the localhost defaults; add