Control Token + MCP Tool Surface
JobCache's Core API separates public legacy reads, general control operations, and participant lifecycle authority. The new App MCP has no bearer at all: it calls only the App API, and scoped operations require the caller to present the opaque session link capability explicitly.
The credentials
JOBCACHE_CONTROL_TOKEN gates JobCache's general control routes:
| Endpoint | Caller |
|---|---|
POST /api/corpus/search |
careervector-api server-side corpus gateway |
GET /api/ads/lookup |
careervector-api worker during workspace hydration |
POST /api/ads/resolve |
careervector-api worker (when a workspace imports a new job URL) |
POST /api/commands/drain |
Operator / scheduled drainer |
POST /api/catalog/sync |
Operator |
POST /api/corpus/erasures/drain |
Operator / explicit control-plane call |
Two narrower credentials are intentionally not aliases for the control token:
JOBCACHE_CORPUS_LIFECYCLE_TOKENauthorizes direct inboundPOST /api/corpus/participants/erasecalls.JOBCACHE_CORPUS_WORKER_TOKENis outbound only. The manual erasure drain sends it to CareerVector's/internal/corpus/erasures/claimand/ackroutes, where that worker is granted only theerasecapability.
Browsers never receive any of these values.
Every configured bearer must contain at least 24 characters after trimming, and the control, lifecycle, and worker values must be pairwise different. Core enforces this itself and returns 503 before authorization or database access when the credential set is weak or aliases two capabilities.
The erasure worker sends its bearer only to an HTTPS CareerVector base URL. Plain HTTP is accepted solely for loopback development addresses; URL-embedded credentials, query strings, and fragments are rejected.
POST /api/corpus/search is read-only but intentionally belongs to the authenticated
internal boundary: it is the stable role/snapshot contract between products, not the
public ad-browsing API. CareerVector sends the bearer from its server-side
JOBCACHE_CONTROL_TOKEN binding. Browsers never receive it.
Legacy read endpoints stay open
GET /api/search, GET /api/postings, GET /healthz, and GET /metrics remain
public on the Core origin. The authenticated Core route does not replace or
silently tighten those legacy surfaces. Product MCP tools live only in
jobcache/mcp/ and reach the App API rather than this compatibility process.
MCP tool surface
jobcache/mcp/ is the standalone Worker for mcp.jobcache.corbet.ch.
It mirrors public App search/evidence plus link-scoped session, saved-view,
snapshot and reduction operations. It may create or delete App-local state, but
it never exposes Core delivery, erasure-drain or other internal administration.
Destructive tools are annotated accordingly.
The App owns its protected Core connection. MCP neither stores nor forwards a
Core/App control token, and caller Authorization headers are discarded. The
old MCP mounted inside the provider-suspended Render interface has been deleted.
The App and standalone MCP Workers are the live boundary.
See also
api/README.md— full route reference.architecture/host-routing.md— suspended compatibility host routing.jobcache/api/README.md— target App API credentials and routes.