Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.lucenthq.com/llms.txt

Use this file to discover all available pages before exploring further.

Lucent’s MCP endpoint is fronted by an OAuth 2.1 authorization server that conforms to the MCP specification. For the user-facing setup walkthrough, see the quickstart. This page documents the protocol surface for client implementers.

Discovery

Both metadata documents are publicly readable and CORS-open.

Protected resource metadata

GET https://app.lucenthq.com/.well-known/oauth-protected-resource Returns the resource server’s identity and which authorization servers issue tokens for it.
{
  "resource": "https://app.lucenthq.com/api/mcp",
  "authorization_servers": ["https://app.lucenthq.com"],
  "scopes_supported": ["read:lucent"]
}

Authorization server metadata

GET https://app.lucenthq.com/.well-known/oauth-authorization-server Returns the endpoints, supported parameters, and capabilities.
{
  "issuer": "https://app.lucenthq.com",
  "authorization_endpoint": "https://app.lucenthq.com/oauth/authorize",
  "token_endpoint": "https://app.lucenthq.com/api/oauth/token",
  "registration_endpoint": "https://app.lucenthq.com/api/oauth/register",
  "revocation_endpoint": "https://app.lucenthq.com/api/oauth/revoke",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_methods_supported": ["none", "client_secret_post"],
  "revocation_endpoint_auth_methods_supported": ["none", "client_secret_post"],
  "code_challenge_methods_supported": ["S256"],
  "scopes_supported": ["read:lucent"]
}
The only supported grant flow is authorization code with PKCE (S256). Implicit, password, and client_credentials are not supported. plain PKCE is rejected.

Dynamic Client Registration

POST https://app.lucenthq.com/api/oauth/register Implements RFC 7591. Rate-limited per IP — busy clients should cache the resulting client_id rather than re-register. Request
{
  "client_name": "Acme Connector",
  "redirect_uris": ["https://claude.ai/api/mcp/auth_callback"],
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "scope": "read:lucent"
}
FieldRequiredNotes
redirect_urisyesAt least one. Each must be in the allowlist. HTTPS or loopback only.
client_nameno≤ 64 chars; letters, numbers, spaces, -_.(). Defaults to Unnamed Client.
token_endpoint_auth_methodnonone (public client + PKCE, default) or client_secret_post.
grant_typesnoSubset of ["authorization_code", "refresh_token"]. Defaults to both.
response_typesnoMust include code. Defaults to ["code"].
scopenoDefaults to read:lucent.
Response (201 Created)
{
  "client_id": "luc_client_…",
  "client_secret": "…",
  "client_name": "Acme Connector",
  "redirect_uris": ["https://claude.ai/api/mcp/auth_callback"],
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "scope": "read:lucent"
}
client_secret is only present when token_endpoint_auth_method is client_secret_post. Public clients (the default for native MCP clients) get client_id only and authenticate with PKCE.

Allowed redirect URIs

The redirect allowlist defends against open-redirect and auth-code injection. Registration rejects URIs outside this list with an InvalidClientMetadataError and an opaque message.
TypeAllowed values
Hosted (HTTPS)https://claude.ai, https://claude.com
Loopback (HTTP)http://127.0.0.1, http://[::1], http://localhost — any port and path
URIs with embedded credentials (https://user:pass@…) or fragments (#…) are rejected per RFC 6749 §3.1.2. To add another hosted origin, email [email protected].

Authorization request

GET https://app.lucenthq.com/oauth/authorize?… Standard OAuth 2.1 authorization-code request with PKCE:
ParamRequiredNotes
response_typeyesMust be code.
client_idyesFrom registration.
redirect_uriyesMust exactly match one of the registered redirect_uris.
code_challengeyes43–128 chars, base64url-encoded SHA-256 of the verifier.
code_challenge_methodyesMust be S256.
staterec.Opaque value the client uses for CSRF protection.
scopenoDefaults to read:lucent.
If the user isn’t signed in to Lucent, they’re routed through /login and returned to the consent screen after authentication. If a consent record already exists for this (client_id, scope) and hasn’t been revoked, the consent screen is bypassed and the browser is redirected back to redirect_uri with ?code=…&state=… immediately. If anything is wrong (unknown client, revoked client, redirect_uri mismatch, malformed PKCE), the user sees a single opaque error page — no detail is leaked that would let an unauthenticated probe enumerate client state.

Token endpoint

POST https://app.lucenthq.com/api/oauth/token Content-Type: application/x-www-form-urlencoded. Returns Cache-Control: no-store.

grant_type=authorization_code

POST /api/oauth/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=luc_oac_…
&redirect_uri=https://claude.ai/api/mcp/auth_callback
&client_id=luc_client_…
&code_verifier=
&client_secret=…   (only if token_endpoint_auth_method=client_secret_post)
The redirect_uri must match the value sent at authorize time (RFC 6749 §4.1.3 / OAuth 2.1 §4.1.3). Codes are single-use and expire after 60 seconds. Reuse of an already-redeemed code revokes any tokens previously issued from it.

grant_type=refresh_token

grant_type=refresh_token
&refresh_token=luc_ort_…
&client_id=luc_client_…
&scope=read:lucent          (optional, must be ⊆ originally granted)
&client_secret=…            (only if confidential client)
Refresh tokens rotate on every exchange — the old refresh token is marked rotated and a new pair is returned. If a rotated refresh token is presented again, the entire token chain (access + refresh) for that session is revoked as a reuse-detection cascade.

Response

{
  "access_token": "luc_oat_…",
  "refresh_token": "luc_ort_…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "read:lucent"
}
TTLDefaultEnv var
Access token1 hourOAUTH_ACCESS_TOKEN_TTL_SECONDS
Refresh token30 daysOAUTH_REFRESH_TOKEN_TTL_DAYS
Authorization code60 secondsOAUTH_AUTHORIZATION_CODE_TTL_SECONDS

Revocation endpoint

POST https://app.lucenthq.com/api/oauth/revoke Implements RFC 7009 and is idempotent — always returns 200 even for unknown tokens.
POST /api/oauth/revoke HTTP/1.1
Content-Type: application/x-www-form-urlencoded

token=luc_oat_… or luc_ort_…
&token_type_hint=access_token | refresh_token   (optional)
&client_id=luc_client_…
&client_secret=…   (only if confidential client)
Use this when a user signs out of your client. Lucent also exposes a Connected apps section in the dashboard so end users can unilaterally revoke any registered client.

Tools and scopes

Every token currently carries the single read:lucent scope. The four read-only tools (list_signals, list_issues, get_issue, list_insights) are gated behind that scope at the MCP handler level via withMcpAuth({ requiredScopes: ["read:lucent"] }). See the tool reference for arguments and return shapes.

Errors

OAuth-protocol errors follow the RFC 6749 §5.2 JSON shape:
{ "error": "invalid_grant", "error_description": "PKCE verification failed" }
User-visible authorize-page failures collapse to a single opaque message. Token-endpoint client-auth failures are also opaque (no distinction between “unknown client_id” and “wrong secret”) — both defenses are deliberate and prevent enumeration of registered clients.