Auth & credentials

We never ask for your keys. We never see them.

Joshua provides auth context: where your credential lives and how the target API expects it to be used. Your agent follows the auth context to make the call. The credential itself never enters our system, our database, or our logs — we stay out of the auth-cycle entirely.

The promise, in one line

Joshua provides the auth context. We store a pointer to where your credential lives — not the credential itself. Your agent follows the auth context and makes the API request directly.

What Joshua does

  • Stores an auth_block — the auth context for one tool. It describes the scheme (bearer, basic, OAuth, none) and a pointer to where your credential lives — e.g. STRIPE_SECRET_KEY or op://Personal/Stripe/credential.
  • Hands that auth context to your agent on fetch_user_tool so it knows how to authenticate the call and where to find the secret.
  • For OAuth tools, the auth context is the OAuth metadata embedded in the spec — your agent runs the flow, holds the tokens, and refreshes them.

What Joshua never does

  • Never asks you to paste a credential into a Joshua form. The registration UI accepts a pointer, not a secret.
  • Never stores credentials at rest. Our database has no field for them.
  • Never proxies API calls. Your agent talks to Stripe, Notion, or your internal service directly — Joshua is not on the request path.
  • Never sees OAuth tokens. The flow happens between your agent and the provider; tokens live wherever your agent stores them.
  • Never logs credential values. We can't log what we don't receive.

One tool, many instances — each with its own auth context

You can register the same underlying tool any number of times under different names. Each registration is its own instance with its own auth context — its own pointer, its own scheme, its own notes. The agent picks between them at call time using the names and notes you provide.

  • Stripe (test)STRIPE_TEST_KEY
  • Stripe (live)op://Prod/Stripe/credential
  • Notion (personal) and Notion (work) — same spec, two different OAuth clients

One spec, many auth contexts. Joshua keeps them separated by registration, scoped to your account.

What the pointer half of the auth context looks like

When you register a tool, you pick a source and a pointer. That string — and nothing else — is what we hand back as part of the auth context. Examples:

  • Environment variable — STRIPE_SECRET_KEY
  • 1Password — op://Personal/Stripe/credential
  • Doppler — doppler://prod/STRIPE_SECRET_KEY
  • Infisical — infisical://prod/STRIPE_SECRET_KEY
  • AWS Secrets Manager — aws-sm://prod/stripe/secret

Rotating the secret in your vault is enough. You don't have to update Joshua — the pointer is unchanged.

The flow at call time

  1. Agent calls fetch_user_tool on Joshua.
  2. Joshua returns the spec and the auth context (scheme + pointer + your notes).
  3. Agent follows the auth context — resolves the pointer (e.g. STRIPE_SECRET_KEY) from its own environment, vault, or secret store.
  4. Agent makes the HTTPS request to the target API directly, attaching the credential per the scheme.

Joshua sees step 1 and step 2. We are not in steps 3 or 4.

The one credential we do hold

Your Joshua API key. It's how the MCP server knows which entries belong to you. It only authorizes reads of your own catalog — it cannot be used to call Stripe, Notion, or any other downstream API. Rotate it anytime from your dashboard.