mcp-core
Auth, billing, and logging infrastructure for MCP-first servers. Sits between your product code and fastapi-mcp, with provider-aware auth for Logto and Supabase.
Your MCP Server (product-specific tool handlers)
mcp-core (auth, billing, logging, health)
fastapi-mcp (MCP protocol: JSON-RPC, SSE, tool discovery)
FastAPI
Install
pip install mcp-core-auth
The package is published as mcp-core-auth on PyPI (the bare mcp-core name is held by an unrelated project), but the import path is unchanged:
from mcp_core import MCPCore
Quick Start
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from mcp_core import MCPCore
core = MCPCore(
product_name="my-product",
auth_provider="logto",
logto_endpoint="https://your-tenant.logto.app",
logto_api_resource="https://api.my-product.app",
mongodb_uri="mongodb+srv://...",
stripe_secret_key="sk_test_...",
stripe_price_id="price_...",
free_credits=30,
tool_costs={"browse": 0, "generate": 5},
read_only_tools={"browse"},
)
@asynccontextmanager
async def lifespan(app: FastAPI):
await core.connect_db()
yield
app = FastAPI(lifespan=lifespan)
core.install_routes(app) # /health, /api/billing/credits, webhook, OAuth metadata
@app.post("/api/mcp/generate")
async def generate(request: Request):
user = await core.auth_and_bill(request, "generate")
result = do_generation()
await core.log_tool_call(request, "generate", user=user, duration_ms=1200)
return result
All config can also come from MCP_CORE_* environment variables.
To use Supabase Auth instead, switch the provider and pass your Supabase URL and anon key:
core = MCPCore(
product_name="my-product",
auth_provider="supabase",
supabase_url="https://your-project.supabase.co",
supabase_anon_key="sb_publishable_...",
supabase_api_resource="https://api.my-product.app",
mongodb_uri="mongodb+srv://...",
free_credits=30,
tool_costs={"browse": 0, "generate": 5},
read_only_tools={"browse"},
)
If auth_provider is omitted, mcp-core infers Supabase when both
MCP_CORE_SUPABASE_URL and MCP_CORE_SUPABASE_ANON_KEY are present;
otherwise it preserves the existing Logto default.
Modules
Auth (mcp_core.auth)
Provider-aware bearer-token auth. Creates MongoDB user records on first auth
using a neutral auth_user_id while preserving legacy logto_user_id fields
for existing Logto apps.
- Logto JWT validation via JWKS
- Supabase access-token validation through Supabase Auth
- Cloud or self-hosted provider URLs
- 30s clock skew tolerance
- Race-condition-safe user upsert
- Dev bypass (
Bearer dev-bypass) for local development - M2M token rejection for paid tools
Billing (mcp_core.billing.StripeBilling)
Stripe billing for credit-based products and all-access subscription products.
- Credit mode deducts free credits first, then falls back to Stripe metered billing.
- Subscription mode (
BILLING_MODE=subscription) requires an active subscription for paid tools and never consumes credits. - Standard billing routes include
/api/billing/credits,/api/billing/checkout-subscription,/api/billing/sync,/api/billing/portal, and/api/stripe/webhook. - Subscription webhooks track
checkout.session.completed,customer.subscription.created,customer.subscription.updated,customer.subscription.paused,customer.subscription.resumed,customer.subscription.deleted,invoice.payment_failed,invoice.payment_action_required, andinvoice.paid. - Access defaults to
active,trialing, andpast_due;unpaid,paused,incomplete,incomplete_expired, andcanceleddo not grant subscription access. - Stripe Customer Portal should handle payment methods, invoices, receipts, and cancellation self-service. Stripe Billing customer-email settings should handle invoice, receipt, failed-payment, and renewal emails; auth providers such as Supabase should remain responsible for auth and security emails.
Useful subscription env vars:
BILLING_MODE=subscription
STRIPE_SECRET_KEY=sk_live_or_test_...
STRIPE_PRICE_ID=price_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PORTAL_CONFIGURATION_ID=bpc_...
SUBSCRIPTION_PLAN_NAME="Pro"
SUBSCRIPTION_PRICE_LABEL="$20/month"
Store billing and plans (mcp_core.store)
App Store subscriptions through RevenueCat, next to Stripe:
PlanCatalog/Plan: map Stripe prices and store entitlements to plans.require_plan(core, user, "pro")reads both, and the highest plan wins.RevenueCatBilling: webhook (constant-timeAuthorizationcheck, idempotent event log),reconcile(user)through the v1 REST API behindRevenueCatClient, a sandbox allowlist, and anon_changehook for product-owned allowances.core.install_store_routes(app)andcore.install_account_routes(app, before_delete=...)(POST /api/account/delete).
See integration guide section 10.
Tool Logging (mcp_core.tool_logging.ToolLogger)
Audit trail for every MCP tool call. Writes to MongoDB tool_logs collection.
Health (mcp_core.health.HealthCheck)
Composable health check builder. Supports sync and async checks with timeouts.
Readiness (mcp_core.readiness)
Provider-aware MCP OAuth onboarding diagnostics. The bundled CLI follows the same discovery path as RFC 9728 clients:
mcp-core-check-readiness https://your-app.example.com/mcp/v2/
It checks protected-resource metadata, authorization-server discovery, Dynamic
Client Registration, unauthenticated MCP bearer challenges, and provider-specific
behavior for Logto and Supabase. For Supabase, it also verifies that the
authorize endpoint redirects back to your app's consent UI with an
authorization_id.
Client auth matrix (operators / products)
Server readiness is not enough for release confidence. Use the client auth matrix to verify real MCP clients (Claude Code, OpenCode, Grok, Cursor, …):
- docs/client-auth-matrix.md — OAuth primary vs optional PAT fallback; operator checklist; anti-patterns
- docs/templates/connect.md.template —
plain-text connect guide products can serve at
/.well-known/mcp/connect.md
Product-specific eval harnesses (isolated CLI profiles, Windows runners, etc.) belong in the product repo, not in mcp-core.
Testing
# Mock tests (no external services)
pip install -e ".[dev]"
pytest tests/ -v
# Live tests (requires .env.live with real credentials)
RUN_LIVE_TESTS=1 pytest tests/live/ -v
Contributing
Bug reports and PRs welcome. See CONTRIBUTING.md for the workflow and SECURITY.md for vulnerability reporting.
The multi-provider auth design reference lives in docs/multi-provider-auth-plan.md.
License
MIT
Metadata
Release files for mcp-core-auth 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mcp_core_auth-0.6.0.tar.gz | 641.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mcp_core_auth-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 707.6 kB
Release files / mcp_core_auth-0.6.0.tar.gz
| Download URL | mcp_core_auth-0.6.0.tar.gz |
|---|---|
| Size | 641.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
55288ac954afe5c97810d2864c79a9e9dd21d1c7dca91e5fe2f4745890fe624d
|
|
BLAKE2b-256 checksum How to use checksums |
58434cbac7d90e5a0f05d635b62a41c4e5bedfdff4dd64b75c570103724d73ac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / mcp_core_auth-0.6.0-py3-none-any.whl
| Download URL | mcp_core_auth-0.6.0-py3-none-any.whl |
|---|---|
| Size | 66.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6a8a4ac08ca1e715b1dc7f581ecd3993cc3ab7ff1822865120a5d3e44ee319ba
|
|
BLAKE2b-256 checksum How to use checksums |
0d60547fe919b0e7150cf46066a4200b48c86518ded4d8fb999c6ee2dc3df579
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|