Skip to content

Commit 39b2f56

Browse files
mantrakp04claude
andauthored
mcp / tools update + internal tool (#1283)
- Added new internal API endpoint for documentation tools, allowing actions such as listing available docs, searching, and fetching specific documentation by ID. - Updated environment configuration to support optional internal secret for enhanced security. - Refactored existing search functionality to utilize the new docs tools API instead of the previous MCP server. - Improved error handling and response parsing for documentation-related requests. - Expanded documentation to clarify the relationship between the new tools and existing API functionalities. This update streamlines the documentation access process and enhances the overall developer experience. <!-- Make sure you've read the CONTRIBUTING.md guidelines: https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Non-stream AI responses now include a consolidated finalText for clearer answers. * Added an internal docs-tools HTTP API to power doc listing, search, and fetch with optional header-based access control and configurable service origin. * **Refinement** * Consolidated multiple doc tooling paths into a single question-focused flow; backend now routes to the unified docs-tools endpoint. * **Documentation** * Updated guides and knowledge base to describe the new docs query flow and optional env configuration. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 328fd02 commit 39b2f56

13 files changed

Lines changed: 752 additions & 699 deletions

File tree

apps/backend/.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,6 @@ STACK_STRIPE_SECRET_KEY=# enter your stripe api key
115115
STACK_STRIPE_WEBHOOK_SECRET=# enter your stripe webhook secret
116116
STACK_TELEGRAM_BOT_TOKEN= # enter you telegram bot token
117117
STACK_TELEGRAM_CHAT_ID=# enter your telegram chat id
118+
119+
# Docs AI tool bundle
120+
STACK_DOCS_INTERNAL_BASE_URL=# override the docs origin used by the backend's AI tool bundle to call the docs app's `/api/internal/docs-tools` endpoint. Defaults to http://localhost:${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}04 in dev, https://mcp.stack-auth.com in prod

apps/backend/.env.development

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ STACK_OPENAI_API_KEY=mock_openai_api_key
7777
STACK_STRIPE_SECRET_KEY=sk_test_mockstripekey
7878
STACK_STRIPE_WEBHOOK_SECRET=mock_stripe_webhook_secret
7979
STACK_OPENROUTER_API_KEY=FORWARD_TO_PRODUCTION
80+
# STACK_DOCS_INTERNAL_BASE_URL=http://localhost:8104
8081
# Email monitor configuration for tests
8182
STACK_EMAIL_MONITOR_VERIFICATION_CALLBACK_URL=http://localhost:8101/handler/email-verification
8283
STACK_EMAIL_MONITOR_PROJECT_ID=internal

apps/backend/src/app/api/latest/ai/query/[mode]/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export const POST = createSmartRouteHandler({
118118
return {
119119
statusCode: 200,
120120
bodyType: "json" as const,
121-
body: { content: contentBlocks },
121+
body: { content: contentBlocks, finalText: result.text },
122122
};
123123
}
124124
},
Lines changed: 118 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,126 @@
1-
import { createMCPClient } from "@ai-sdk/mcp";
2-
import { getNodeEnvironment } from "@stackframe/stack-shared/dist/utils/env";
1+
import { tool } from "ai";
2+
import { getEnvVariable, getNodeEnvironment } from "@stackframe/stack-shared/dist/utils/env";
3+
import { captureError } from "@stackframe/stack-shared/dist/utils/errors";
4+
import { z } from "zod";
5+
6+
type DocsToolHttpResult = {
7+
content?: Array<{ type: string, text?: string }>,
8+
isError?: boolean,
9+
};
10+
11+
function getDocsToolsBaseUrl(): string {
12+
const fromEnv = getEnvVariable("STACK_DOCS_INTERNAL_BASE_URL", "");
13+
if (fromEnv !== "") {
14+
return fromEnv.replace(/\/$/, "");
15+
}
16+
if (getNodeEnvironment() === "development") {
17+
const portPrefix = getEnvVariable("NEXT_PUBLIC_STACK_PORT_PREFIX", "81");
18+
return `http://localhost:${portPrefix}04`;
19+
}
20+
return "https://mcp.stack-auth.com";
21+
}
22+
23+
async function postDocsToolAction(action: Record<string, unknown>): Promise<string> {
24+
const base = getDocsToolsBaseUrl();
25+
26+
const res = await fetch(`${base}/api/internal/docs-tools`, {
27+
method: "POST",
28+
headers: { "Content-Type": "application/json" },
29+
body: JSON.stringify(action),
30+
});
31+
32+
if (!res.ok) {
33+
const errBody = await res.text();
34+
captureError("docs-tools-http-error", new Error(`Stack Auth docs tools error (${res.status}): ${errBody}`));
35+
return `Stack Auth docs tools error (${res.status}): ${errBody}`;
36+
}
37+
38+
const data = (await res.json()) as DocsToolHttpResult;
39+
const text = data.content
40+
?.filter((c): c is { type: "text", text: string } => c.type === "text" && typeof c.text === "string")
41+
.map((c) => c.text)
42+
.join("\n") ?? "";
43+
44+
if (data.isError === true) {
45+
return text || "Unknown docs tool error";
46+
}
47+
48+
return text;
49+
}
350

451
/**
5-
* Creates an MCP client connected to the Stack Auth documentation server.
52+
* Documentation tools backed by the docs app's `/api/internal/docs-tools` endpoint.
653
*
7-
* In development: connects to local docs server at http://localhost:8126
8-
* In production: connects to production docs server at https://mcp.stack-auth.com
54+
* The public MCP server at the same docs origin exposes only `ask_stack_auth`, which proxies to
55+
* `/api/latest/ai/query/generate`; these tools avoid MCP recursion by calling the HTTP API directly.
956
*/
1057
export async function createDocsTools() {
11-
const mcpUrl =
12-
getNodeEnvironment() === "development"
13-
? new URL("/api/internal/mcp", "http://localhost:8126")
14-
: new URL("/api/internal/mcp", "https://mcp.stack-auth.com");
58+
return {
59+
list_available_docs: tool({
60+
description:
61+
"Use this tool to learn about what Stack Auth is, available documentation, and see if you can use it for what you're working on. It returns a list of all available Stack Auth Documentation pages.",
62+
inputSchema: z.object({}),
63+
execute: async () => {
64+
return await postDocsToolAction({ action: "list_available_docs" });
65+
},
66+
}),
1567

16-
const stackAuthMcp = await createMCPClient({
17-
transport: { type: "http", url: mcpUrl.toString() },
18-
});
68+
search_docs: tool({
69+
description:
70+
"Search through all Stack Auth documentation including API docs, guides, and examples. Returns ranked results with snippets and relevance scores.",
71+
inputSchema: z.object({
72+
search_query: z.string().describe("The search query to find relevant documentation"),
73+
result_limit: z.number().optional().describe("Maximum number of results to return (default: 50)"),
74+
}),
75+
execute: async ({ search_query, result_limit = 50 }) => {
76+
return await postDocsToolAction({
77+
action: "search_docs",
78+
search_query,
79+
result_limit,
80+
});
81+
},
82+
}),
83+
84+
get_docs_by_id: tool({
85+
description:
86+
"Use this tool to retrieve a specific Stack Auth Documentation page by its ID. It gives you the full content of the page so you can know exactly how to use specific Stack Auth APIs. Whenever using Stack Auth, you should always check the documentation first to have the most up-to-date information. When you write code using Stack Auth documentation you should reference the content you used in your comments.",
87+
inputSchema: z.object({
88+
id: z.string(),
89+
}),
90+
execute: async ({ id }) => {
91+
return await postDocsToolAction({ action: "get_docs_by_id", id });
92+
},
93+
}),
94+
95+
get_stack_auth_setup_instructions: tool({
96+
description:
97+
"Use this tool when the user wants to set up authentication in a new project. It provides step-by-step instructions for installing and configuring Stack Auth authentication.",
98+
inputSchema: z.object({}),
99+
execute: async () => {
100+
return await postDocsToolAction({ action: "get_stack_auth_setup_instructions" });
101+
},
102+
}),
103+
104+
search: tool({
105+
description:
106+
"Search for Stack Auth documentation pages.\n\nUse this tool to find documentation pages that contain a specific keyword or phrase.",
107+
inputSchema: z.object({
108+
query: z.string(),
109+
}),
110+
execute: async ({ query }) => {
111+
return await postDocsToolAction({ action: "search", query });
112+
},
113+
}),
19114

20-
return await stackAuthMcp.tools();
115+
fetch: tool({
116+
description:
117+
"Fetch a particular Stack Auth Documentation page by its ID.\n\nThis tool is identical to `get_docs_by_id`.",
118+
inputSchema: z.object({
119+
id: z.string(),
120+
}),
121+
execute: async ({ id }) => {
122+
return await postDocsToolAction({ action: "fetch", id });
123+
},
124+
}),
125+
};
21126
}

claude/CLAUDE-KNOWLEDGE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ A: Update affected inline snapshots in `apps/e2e/tests/backend/endpoints/api/v1/
139139
Q: How should `createOrUpdateProjectWithLegacyConfig` handle `onboardingStatus` for forward-compat checks?
140140
A: Only write `onboardingStatus` when the `Project.onboardingStatus` column exists (for example by checking `information_schema.columns` in-transaction) so current code can still run against older schemas where that column is absent.
141141

142+
Q: How does the Stack Auth docs MCP relate to the ask-chat API and doc tools?
143+
A: The public MCP (`/api/internal/mcp` on the docs site) exposes only `ask_stack_auth`, which POSTs to `/api/latest/ai/query/generate` with `tools: ["docs"]` and `systemPrompt: "docs-ask-ai"`. The backend no longer loads doc tools via MCP; `createDocsTools()` calls the docs app `POST /api/internal/docs-tools` with typed actions (same behavior as before). Optional `STACK_INTERNAL_DOCS_TOOLS_SECRET` gates the internal route; `STACK_DOCS_INTERNAL_BASE_URL` overrides the docs origin for the backend.
142144
Q: What caused the March 19, 2026 QEMU local emulator deps startup regression?
143145
A: The QEMU runtime path regressed when it switched from mounting `docker/local-emulator/base.env` into the runtime ISO to mounting the generated hidden file `docker/local-emulator/.env.development` instead. In testing, the `.env.development` QEMU path left cold boot stuck with only PostgreSQL healthy, while restoring the runtime ISO back to `base.env` brought deps startup back to about 12-13 seconds. The env payloads were effectively the same, so the likely issue was the QEMU runtime bundle/path handling for `.env.development`, not the actual env values.
144146
Q: Where is the private sign-up risk engine generated entrypoint in backend now?

docs/.env

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Basic
2+
NEXT_PUBLIC_STACK_API_URL=# the base URL of Stack's backend/API
3+
NEXT_PUBLIC_STACK_PROJECT_ID=# the project ID to use
4+
NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=# publishable client key for the project
5+
STACK_SECRET_SERVER_KEY=# secret server key for the project
6+
STACK_OPENROUTER_API_KEY=# OpenRouter API key for AI-enabled chat

docs/content/docs/(guides)/others/mcp-setup.mdx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ title: MCP Setup
1010

1111
Set up Stack Auth's Model Context Protocol (MCP) server to get intelligent code assistance in your development environment.
1212

13+
The MCP server exposes a single tool, **`ask_stack_auth`**, which sends your question to the same Stack Auth documentation AI used on [docs.stack-auth.com](https://docs.stack-auth.com).
14+
1315
<Tabs defaultValue="cursor">
1416
<TabsList>
1517
<TabsTrigger value="cursor">Cursor</TabsTrigger>
@@ -231,10 +233,9 @@ by [![Hypr MCP](https://hyprmcp.com/hyprmcp_20px.svg)](https://hyprmcp.com/)`}</
231233

232234
## Features
233235

234-
The Stack Auth MCP server provides:
236+
The Stack Auth MCP server exposes **`ask_stack_auth`**, which answers questions using live documentation retrieval and the docs-site AI assistant. It can help with:
235237

236-
- **Authentication Flow Assistance**: Get help implementing sign-in, sign-up, and user management
237-
- **API Documentation**: Access Stack Auth API documentation and examples
238-
- **Code Generation**: Generate boilerplate code for common authentication patterns
239-
- **Best Practices**: Receive guidance on security best practices and implementation patterns
238+
- **Authentication flows**: Sign-in, sign-up, and user management
239+
- **APIs and SDKs**: Endpoints, examples, and framework integration
240+
- **Best practices**: Security and configuration guidance
240241

0 commit comments

Comments
 (0)