chore(mcp/docs): canonicalize HEXCLAVE_ env vars in docs + raise ask_hexclave step limit & timeout (#1571)

## Summary

Follow-up from analyzing the dogfooding report on the `ask_hexclave` MCP
tool. Two root causes were confirmed against source:

1. **The "`STACK_` vs `HEXCLAVE_` env var hallucination" wasn't a
hallucination** — it's an incomplete Stack Auth → Hexclave rebrand. The
SDK resolves both prefixes (`packages/js/src/generated/env.ts`), with
`HEXCLAVE_*` canonical and `STACK_*` a legacy fallback, but several
docs/examples still showed the old `STACK_*` names. That inconsistency
is what misled agents into thinking `HEXCLAVE_*` was made up.
2. **`ask_hexclave` timeouts** — the tool proxies to a `quality:
"smart"` agentic docs-search loop. The agent step budget (50) and the
120s timeouts were too tight; broad/multi-part questions blew the budget
(reproduced 3× while investigating).

## Changes

### Docs: canonicalize client SDK auth env vars to `HEXCLAVE_*`
Converted `PROJECT_ID`, `PUBLISHABLE_CLIENT_KEY`, `SECRET_SERVER_KEY`,
`API_URL` (+ `NEXT_PUBLIC_` / `VITE_` forms) from `STACK_*` →
`HEXCLAVE_*` in app-setup docs + the package template:

-
`docs-mintlify/guides/integrations/{convex,tanstack-start,vercel}/overview.mdx`
- `docs-mintlify/guides/going-further/local-vs-cloud-dashboard.mdx`
- `docs-mintlify/guides/apps/analytics/overview.mdx`
- `docs-mintlify/guides/other/tutorials/ship-production-ready-auth.mdx`
- `docs-mintlify/sdk/objects/hexclave-app.mdx`
- `packages/template/src/integrations/convex/component/README.md` (the
tracked source of the generated `@hexclave/js` + `@hexclave/next` copies
— the generated copies are git-ignored)

**Deliberately left untouched** — read literally by the backend/CLI (no
`HEXCLAVE_` alias) or user-defined: `STACK_CLICKHOUSE_*`,
`STACK_DATABASE_*`, `STACK_OPENROUTER_*`, `STACK_CLI_*`, `STACK_SEED_*`,
`STACK_WEBHOOK_SECRET`, `STACK_DATA_VAULT_SECRET`, and the `x-stack-*`
HTTP headers. So `self-host.mdx`, `cli.mdx`, `jwts.mdx`, `webhooks`, and
`data-vault` docs are intentionally unchanged.

### Reliability: raise `ask_hexclave` step limit + timeout
- `apps/backend/src/app/api/latest/ai/query/[mode]/route.ts`:
docs/search agent step limit **50 → 75** (+50%); AI generation abort
**120s → 180s**
- `apps/mcp/src/mcp-handler.ts`: MCP function `maxDuration` **120 →
180** (kept ≥ backend timeout so the proxy doesn't die before the
backend finishes)

## Notes
- Also includes a small pre-existing `run pnpm fml` commit (regenerated
docs snippets / `llms-full.txt`).
- The step/timeout bumps address the *symptom*. The durable reliability
fix is streaming/keepalive on the MCP proxy so the client never idles
out mid-query — proposed as a follow-up.
- **Not** included: the separate `sendEmail` doc-vs-SDK drift (docs
declare `Promise<Result<void, KnownErrors>>` in
`sdk/objects/hexclave-app.mdx`, but the SDK returns `Promise<void>` and
throws). That's a docs *correctness* bug deserving its own PR.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Canonicalized auth env vars in docs/templates to `HEXCLAVE_*`, raised
docs/search step limits and timeouts, and clarified `HexclaveApp`
defaults. MCP tool and server instructions now require loading the
`skill` resource before queries.

- **Bug Fixes**
- Docs: Use `HEXCLAVE_PROJECT_ID`, `HEXCLAVE_PUBLISHABLE_CLIENT_KEY`,
`HEXCLAVE_SECRET_SERVER_KEY`, and optional `HEXCLAVE_API_URL` across
guides/templates (Vercel, Convex, TanStack Start, analytics). In SDK
docs, `secretServerKey` defaults to `HEXCLAVE_SECRET_SERVER_KEY`, and
client defaults use `NEXT_PUBLIC_HEXCLAVE_*`. Backend-only `STACK_*`
vars (`STACK_CLICKHOUSE_*`, `STACK_DATABASE_*`, `STACK_OPENROUTER_*`,
CLI/data-vault/webhook headers) unchanged.
- Reliability: Increase docs/search step limit 50→75 and timeouts
120s→180s; set MCP `maxDuration` to 180s; use `performance.now()` for
duration logging. MCP instructions updated to require loading the
`skill` resource before using tools.

<sup>Written for commit f6be2c3162.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1571?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Performance & Reliability**
* Increased AI operation timeouts and step limits for certain prompts;
improved generate-mode duration measurement for more accurate logging.
* **Documentation**
* Replaced Stack-branded environment variable names with Hexclave
equivalents across guides and examples.
* Clarified that hexclave dev injects required environment variables
automatically.
  * Added guidance on configuring custom authentication redirect URLs.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Mantra 2026-06-11 10:53:53 -07:00 committed by GitHub
parent be01ae733e
commit 74c888fed7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 35 additions and 35 deletions

View File

@ -68,7 +68,7 @@ export const POST = createSmartRouteHandler({
const stepLimit = toolsArg == null
? 1
: isDocsOrSearch
? 50
? 75
: isCreateDashboard
? 12
: isBuildAnalyticsQuery
@ -95,9 +95,9 @@ export const POST = createSmartRouteHandler({
body: result.toUIMessageStreamResponse(),
};
} else {
const startedAt = Date.now();
const startedAt = performance.now();
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 120_000);
const timeoutId = setTimeout(() => controller.abort(), 180_000);
const result = await generateText({
model,
system: systemPrompt,
@ -148,7 +148,7 @@ export const POST = createSmartRouteHandler({
response: result.text,
stepCount: result.steps.length,
innerToolCallsJson,
durationMs: BigInt(Date.now() - startedAt),
durationMs: BigInt(Math.round(performance.now() - startedAt)),
modelId: String(model.modelId),
errorMessage: undefined,
});

View File

@ -107,7 +107,7 @@ export function createHexclaveMcpHandler(config: { streamableHttpEndpoint: strin
server.tool(
"ask_hexclave",
"Ask the Hexclave documentation assistant. Use this for any question about Hexclave: setup, APIs, SDK usage, configuration, or troubleshooting. The assistant searches official documentation and answers with citations. Always set `reason` to a short explanation of why you are calling this tool (for product analytics and debugging).",
"Ask the Hexclave documentation assistant. Use this for any question about Hexclave: setup, APIs, SDK usage, configuration, or troubleshooting. If you haven't already, load the `skill` resource first — it provides the baseline Hexclave context this tool assumes. The assistant searches official documentation and answers with citations. Always set `reason` to a short explanation of why you are calling this tool (for product analytics and debugging).",
{
question: z.string().describe("The full question to ask about Hexclave."),
reason: z
@ -177,14 +177,14 @@ export function createHexclaveMcpHandler(config: { streamableHttpEndpoint: strin
name: "hexclave-mcp",
version: packageJson.version,
},
instructions: `Hexclave's official MCP server. Prefer the \`ask_hexclave\` tool for any question about Hexclave — setup, SDKs (Next.js, React, JS), APIs, configuration, OAuth, teams/permissions, or troubleshooting. It searches the official docs and answers with citations, and should be your first stop over web search or training data since Hexclave changes frequently. The \`skill\` resource/tool loads SKILL.md (the canonical Hexclave agent skill) — pull it in when you need a quick reference for project setup, CLI usage, or wiring conventions, but always use \`ask_hexclave\` first.
instructions: `Hexclave's official MCP server. ALWAYS load the \`skill\` resource/prompt before calling any Hexclave tool — it contains SKILL.md (the canonical Hexclave agent skill) with project setup, CLI usage, and wiring conventions that the tools assume you already know. After loading the skill, use the \`ask_hexclave\` tool for any question about Hexclave — setup, SDKs (Next.js, React, JS), APIs, configuration, OAuth, teams/permissions, or troubleshooting. It searches the official docs and answers with citations, and should be your first stop over web search or training data since Hexclave changes frequently.
${remindersPrompt}`,
},
{
streamableHttpEndpoint: config.streamableHttpEndpoint,
verboseLogs: true,
maxDuration: 120,
maxDuration: 180,
},
);
}

View File

@ -89,8 +89,8 @@ Session replay recording is disabled by default. To enable it, pass `analytics.r
import { HexclaveClientApp } from "@hexclave/next";
export const hexclaveClientApp = new HexclaveClientApp({
projectId: process.env.NEXT_PUBLIC_STACK_PROJECT_ID!,
publishableClientKey: process.env.NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY!,
projectId: process.env.NEXT_PUBLIC_HEXCLAVE_PROJECT_ID!,
publishableClientKey: process.env.NEXT_PUBLIC_HEXCLAVE_PUBLISHABLE_CLIENT_KEY!,
tokenStore: "nextjs-cookie",
analytics: {
replays: {

View File

@ -55,14 +55,14 @@ Use the cloud dashboard when you want to:
For a frontend-only app, connect to a cloud project with the project ID:
```env title=".env.local"
STACK_PROJECT_ID=<your-project-id>
HEXCLAVE_PROJECT_ID=<your-project-id>
```
For a backend, or an app that has both frontend and backend code, also add a secret server key:
```env title=".env.local"
STACK_PROJECT_ID=<your-project-id>
STACK_SECRET_SERVER_KEY=<your-secret-server-key>
HEXCLAVE_PROJECT_ID=<your-project-id>
HEXCLAVE_SECRET_SERVER_KEY=<your-secret-server-key>
```
You can get these values from the cloud dashboard. The project ID appears in the project URL, and server keys are generated from the Project Keys page.
@ -106,7 +106,7 @@ stack --project-id <project-id> config push --config-file ./hexclave.config.ts
```
<Info>
`config pull` requires `stack login`. `config push` supports either `stack login` or `STACK_SECRET_SERVER_KEY`.
`config pull` requires `stack login`. `config push` supports either `stack login` or `HEXCLAVE_SECRET_SERVER_KEY`.
</Info>
For the full setup flow by framework, see [Setup](/guides/getting-started/setup).

View File

@ -42,7 +42,7 @@ import { getConvexProvidersConfig } from "@hexclave/js"; // Vanilla JS
export default {
providers: getConvexProvidersConfig({
projectId: process.env.STACK_PROJECT_ID, // or: process.env.NEXT_PUBLIC_STACK_PROJECT_ID
projectId: process.env.HEXCLAVE_PROJECT_ID, // or: process.env.NEXT_PUBLIC_HEXCLAVE_PROJECT_ID
}),
}
```

View File

@ -34,11 +34,11 @@ TanStack Start is a full-stack React framework built on TanStack Router and Vite
In the [Hexclave dashboard](https://app.hexclave.com/projects), create a project and add these variables to your TanStack Start environment:
```bash title=".env"
VITE_STACK_PROJECT_ID=<your-project-id>
STACK_SECRET_SERVER_KEY=<your-secret-server-key>
VITE_HEXCLAVE_PROJECT_ID=<your-project-id>
HEXCLAVE_SECRET_SERVER_KEY=<your-secret-server-key>
```
Keep `STACK_SECRET_SERVER_KEY` server-only. Do not expose it to client code.
Keep `HEXCLAVE_SECRET_SERVER_KEY` server-only. Do not expose it to client code.
</Step>
<Step title="Create a Stack client app">
@ -48,7 +48,7 @@ TanStack Start is a full-stack React framework built on TanStack Router and Vite
import { HexclaveClientApp } from "@hexclave/tanstack-start";
export const hexclaveClientApp = new HexclaveClientApp({
projectId: import.meta.env.VITE_STACK_PROJECT_ID,
projectId: import.meta.env.VITE_HEXCLAVE_PROJECT_ID,
tokenStore: "cookie",
redirectMethod: "window",
});
@ -161,6 +161,6 @@ TanStack Start is a full-stack React framework built on TanStack Router and Vite
- Render routes that rely on `useUser({ or: "redirect" })` on the client (`ssr: false`) when using `redirectMethod: "window"`.
- Use `redirectMethod: "window"` unless you explicitly wire a TanStack Router navigation adapter.
- If you change auth routes, configure the matching `urls` on `HexclaveClientApp`.
- For server-only logic, use TanStack Start server functions and keep `STACK_SECRET_SERVER_KEY` out of client modules.
- For server-only logic, use TanStack Start server functions and keep `HEXCLAVE_SECRET_SERVER_KEY` out of client modules.
For TanStack Start framework details, see the [TanStack Start quick start](https://tanstack.com/start/latest/docs/framework/react/quick-start) and [server functions guide](https://tanstack.com/start/latest/docs/framework/react/guide/server-functions).

View File

@ -21,7 +21,7 @@ This guide mirrors the Vercel integration flow in the Hexclave dashboard app.
</Step>
<Step title="Generate keys from Hexclave">
In your Stack dashboard, open the **Vercel Integration** app and generate keys for your project.
In your Hexclave dashboard, open the **Vercel Integration** app and generate keys for your project.
This produces a project ID plus API keys that you can paste into Vercel.
</Step>
@ -29,11 +29,11 @@ This guide mirrors the Vercel integration flow in the Hexclave dashboard app.
<Step title="Add environment variables in Vercel">
In Vercel, go to **Project -> Settings -> Environment Variables** and add:
- `NEXT_PUBLIC_STACK_PROJECT_ID`
- `NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY`
- `STACK_SECRET_SERVER_KEY`
- `NEXT_PUBLIC_HEXCLAVE_PROJECT_ID`
- `NEXT_PUBLIC_HEXCLAVE_PUBLISHABLE_CLIENT_KEY`
- `HEXCLAVE_SECRET_SERVER_KEY`
Add `NEXT_PUBLIC_STACK_API_URL` only if you are not using the default hosted Stack API.
Add `NEXT_PUBLIC_HEXCLAVE_API_URL` only if you are not using the default hosted Hexclave API.
</Step>
<Step title="Redeploy">

View File

@ -106,16 +106,16 @@ Read the full discussion in [User fundamentals — Protecting a page](/guides/ge
## 2. Secrets, keys, and environments
<Warning>
**`STACK_SECRET_SERVER_KEY`** (or `ssk_...`) must **only** exist in server-side environments (SSR, route handlers, server actions, your backend). Never prefix it with `NEXT_PUBLIC_`, never import it from code that runs in the browser, and never log it. See the [HexclaveApp SDK reference](/sdk/objects/hexclave-app) and the [REST API overview](/api/overview).
**`HEXCLAVE_SECRET_SERVER_KEY`** (or `ssk_...`) must **only** exist in server-side environments (SSR, route handlers, server actions, your backend). Never prefix it with `NEXT_PUBLIC_`, never import it from code that runs in the browser, and never log it. See the [HexclaveApp SDK reference](/sdk/objects/hexclave-app) and the [REST API overview](/api/overview).
</Warning>
Practical split:
| Variable | Typical exposure | Use |
|----------|------------------|-----|
| `NEXT_PUBLIC_STACK_PROJECT_ID` | Browser + server | Identifies the project to the hosted UI and client SDK. |
| `NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY` (if used) | Browser + server | Client-safe key where your project uses publishable keys. |
| `STACK_SECRET_SERVER_KEY` | **Server only** | Elevated server SDK and REST **server** API. |
| `NEXT_PUBLIC_HEXCLAVE_PROJECT_ID` | Browser + server | Identifies the project to the hosted UI and client SDK. |
| `NEXT_PUBLIC_HEXCLAVE_PUBLISHABLE_CLIENT_KEY` (if used) | Browser + server | Client-safe key where your project uses publishable keys. |
| `HEXCLAVE_SECRET_SERVER_KEY` | **Server only** | Elevated server SDK and REST **server** API. |
Use **separate** Stack projects or at least **separate** env values for production vs staging when possible. Rotate keys from the dashboard if a secret is exposed.

View File

@ -59,7 +59,7 @@ This object is not usually constructed directly. More commonly, you would constr
The [setup wizard](/guides/getting-started/setup) does these steps for you, so you don't need to worry about it unless you are manually setting up Hexclave.
If you're building a client-only app and don't have a `SECRET_SERVER_KEY`, you can construct a `HexclaveClientApp` directly.
If you're building a client-only app and don't have a `HEXCLAVE_SECRET_SERVER_KEY`, you can construct a `HexclaveClientApp` directly.
</Info>
@ -75,11 +75,11 @@ If you're building a client-only app and don't have a `SECRET_SERVER_KEY`, you c
</ParamField>
<ParamField body="projectId" type="string">
Project ID. Defaults to the `NEXT_PUBLIC_STACK_PROJECT_ID` environment variable.
Project ID. Defaults to the `NEXT_PUBLIC_HEXCLAVE_PROJECT_ID` environment variable.
</ParamField>
<ParamField body="publishableClientKey" type="string">
Publishable client key. Defaults to the `NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY` environment variable.
Publishable client key. Defaults to the `NEXT_PUBLIC_HEXCLAVE_PUBLISHABLE_CLIENT_KEY` environment variable.
</ParamField>
<ParamField body="urls" type="object">
@ -505,11 +505,11 @@ Like `HexclaveClientApp`, but with server permissions. Has full read and write a
<Warning>
Since this functionality should only be available in environments you trust
(ie. your own server), it requires a `SECRET_SERVER_KEY`. In some cases, you
(ie. your own server), it requires a `HEXCLAVE_SECRET_SERVER_KEY`. In some cases, you
may want to use a `HexclaveServerApp` on the client; an example for this is an
internal dashboard that only your own employees have access to. We generally
recommend against doing this unless you are aware of and protected against the
(potentially severe) security implications of exposing `SECRET_SERVER_KEY` on
(potentially severe) security implications of exposing `HEXCLAVE_SECRET_SERVER_KEY` on
the client.
</Warning>
@ -563,7 +563,7 @@ Creates a new `HexclaveServerApp` instance.
</ParamField>
<ParamField body="secretServerKey" type="string">
Secret server key. Defaults to the `SECRET_SERVER_KEY` environment variable.
Secret server key. Defaults to the `HEXCLAVE_SECRET_SERVER_KEY` environment variable.
</ParamField>
<ParamField body="urls" type="object">

View File

@ -23,7 +23,7 @@ import { getConvexProvidersConfig } from "@hexclave/js/convex-auth.config"; //
export default {
providers: getConvexProvidersConfig({
projectId: process.env.STACK_PROJECT_ID, // or: process.env.NEXT_PUBLIC_STACK_PROJECT_ID
projectId: process.env.HEXCLAVE_PROJECT_ID, // or: process.env.NEXT_PUBLIC_HEXCLAVE_PROJECT_ID
}),
}
```