mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-19 21:00:40 +08:00
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:
parent
be01ae733e
commit
74c888fed7
@ -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,
|
||||
});
|
||||
|
||||
@ -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,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -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: {
|
||||
|
||||
@ -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).
|
||||
|
||||
@ -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
|
||||
}),
|
||||
}
|
||||
```
|
||||
|
||||
@ -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).
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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
|
||||
}),
|
||||
}
|
||||
```
|
||||
|
||||
Loading…
Reference in New Issue
Block a user