v2: fix simpleStreamableHttp auth example for inspector connect flow (#1427)

Co-authored-by: Paul Carleton <paulcarletonjr@gmail.com>
Co-authored-by: Cliff Hall <cliff@futurescale.com>
This commit is contained in:
Konstantin Konstantinov 2026-01-28 19:11:56 +02:00 • committed by GitHub
commit b0ef89ffaf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 173 additions and 101 deletions

View file

@ -5,6 +5,7 @@
Respect capability negotiation in list methods by returning empty lists when server lacks capability
The Client now returns empty lists instead of sending requests to servers that don't advertise the corresponding capability:
- `listPrompts()` returns `{ prompts: [] }` if server lacks prompts capability
- `listResources()` returns `{ resources: [] }` if server lacks resources capability
- `listResourceTemplates()` returns `{ resourceTemplates: [] }` if server lacks resources capability

View file

@ -40,7 +40,7 @@
"@modelcontextprotocol/server": "workspace:^",
"@modelcontextprotocol/express": "workspace:^",
"@modelcontextprotocol/hono": "workspace:^",
"better-auth": "^1.4.7",
"better-auth": "^1.4.17",
"cors": "catalog:runtimeServerOnly",
"express": "catalog:runtimeServerOnly",
"hono": "catalog:runtimeServerOnly",

View file

@ -239,7 +239,8 @@ setupAuthServer({ authServerUrl, mcpServerUrl, strictResource: true, demoMode: t
// Add protected resource metadata route to the MCP server
// This allows clients to discover the auth server
app.use(createProtectedResourceMetadataRouter());
// Pass the resource path so metadata is served at /.well-known/oauth-protected-resource/mcp
app.use(createProtectedResourceMetadataRouter('/mcp'));
authMiddleware = requireBearerAuth({
requiredScopes: [],
@ -709,6 +710,7 @@ app.listen(MCP_PORT, error => {
process.exit(1);
}
console.log(`MCP Streamable HTTP Server listening on port ${MCP_PORT}`);
console.log(` Protected Resource Metadata: http://localhost:${MCP_PORT}/.well-known/oauth-protected-resource/mcp`);
});
// Handle server shutdown

View file

@ -22,6 +22,7 @@ import {
isInitializeRequest,
McpServer
} from '@modelcontextprotocol/server';
import cors from 'cors';
import type { Request, Response } from 'express';
import * as z from 'zod/v4';
@ -30,6 +31,7 @@ import { InMemoryEventStore } from './inMemoryEventStore.js';
// Check for OAuth flag
const useOAuth = process.argv.includes('--oauth');
const strictOAuth = process.argv.includes('--oauth-strict');
const dangerousLoggingEnabled = process.argv.includes('--dangerous-logging-enabled');
// Create shared task store for demonstration
const taskStore = new InMemoryTaskStore();
@ -524,6 +526,16 @@ const AUTH_PORT = process.env.MCP_AUTH_PORT ? Number.parseInt(process.env.MCP_AU
const app = createMcpExpressApp();
// Enable CORS for browser-based clients (demo only)
// This allows cross-origin requests and exposes WWW-Authenticate header for OAuth
// WARNING: This configuration is for demo purposes only. In production, you should restrict this to specific origins and configure CORS yourself.
app.use(
cors({
exposedHeaders: ['WWW-Authenticate', 'Mcp-Session-Id', 'Last-Event-Id', 'Mcp-Protocol-Version'],
origin: '*' // WARNING: This allows all origins to access the MCP server. In production, you should restrict this to specific origins.
})
);
// Set up OAuth if enabled
let authMiddleware = null;
if (useOAuth) {
@ -531,11 +543,12 @@ if (useOAuth) {
const mcpServerUrl = new URL(`http://localhost:${MCP_PORT}/mcp`);
const authServerUrl = new URL(`http://localhost:${AUTH_PORT}`);
setupAuthServer({ authServerUrl, mcpServerUrl, strictResource: strictOAuth, demoMode: true });
setupAuthServer({ authServerUrl, mcpServerUrl, strictResource: strictOAuth, demoMode: true, dangerousLoggingEnabled });
// Add protected resource metadata route to the MCP server
// This allows clients to discover the auth server
app.use(createProtectedResourceMetadataRouter());
// Pass the resource path so metadata is served at /.well-known/oauth-protected-resource/mcp
app.use(createProtectedResourceMetadataRouter('/mcp'));
authMiddleware = requireBearerAuth({
requiredScopes: [],
@ -699,6 +712,9 @@ app.listen(MCP_PORT, error => {
process.exit(1);
}
console.log(`MCP Streamable HTTP Server listening on port ${MCP_PORT}`);
if (useOAuth) {
console.log(` Protected Resource Metadata: http://localhost:${MCP_PORT}/.well-known/oauth-protected-resource/mcp`);
}
});
// Handle server shutdown

View file

@ -37,8 +37,9 @@
"@modelcontextprotocol/core": "workspace:^",
"@modelcontextprotocol/server": "workspace:^",
"@modelcontextprotocol/express": "workspace:^",
"better-auth": "1.4.7",
"better-sqlite3": "^12.4.1",
"better-auth": "^1.4.17",
"better-sqlite3": "^12.6.2",
"cors": "catalog:runtimeServerOnly",
"express": "catalog:runtimeServerOnly"
},
"devDependencies": {
@ -48,6 +49,7 @@
"@modelcontextprotocol/tsconfig": "workspace:^",
"@modelcontextprotocol/vitest-config": "workspace:^",
"@types/better-sqlite3": "^7.6.13",
"@types/cors": "catalog:devTools",
"@types/express": "catalog:devTools",
"@typescript/native-preview": "catalog:devTools",
"eslint": "catalog:devTools",

View file

@ -26,16 +26,26 @@ export function requireBearerAuth(
): (req: Request, res: Response, next: NextFunction) => Promise<void> {
const { requiredScopes = [], resourceMetadataUrl, strictResource = false, expectedResource } = options;
// Build WWW-Authenticate header matching v1.x format
const buildWwwAuthHeader = (errorCode: string, message: string): string => {
let header = `Bearer error="${errorCode}", error_description="${message}"`;
if (requiredScopes.length > 0) {
header += `, scope="${requiredScopes.join(' ')}"`;
}
if (resourceMetadataUrl) {
header += `, resource_metadata="${resourceMetadataUrl.toString()}"`;
}
return header;
};
return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
const wwwAuthenticate = resourceMetadataUrl ? `Bearer resource_metadata="${resourceMetadataUrl.toString()}"` : 'Bearer';
res.set('WWW-Authenticate', wwwAuthenticate);
res.set('WWW-Authenticate', buildWwwAuthHeader('invalid_token', 'Missing Authorization header'));
res.status(401).json({
error: 'unauthorized',
error_description: 'Missing or invalid Authorization header'
error: 'invalid_token',
error_description: 'Missing Authorization header'
});
return;
}
@ -52,6 +62,7 @@ export function requireBearerAuth(
if (requiredScopes.length > 0) {
const hasAllScopes = requiredScopes.every(scope => authInfo.scopes.includes(scope));
if (!hasAllScopes) {
res.set('WWW-Authenticate', buildWwwAuthHeader('insufficient_scope', `Required scopes: ${requiredScopes.join(', ')}`));
res.status(403).json({
error: 'insufficient_scope',
error_description: `Required scopes: ${requiredScopes.join(', ')}`
@ -63,14 +74,11 @@ export function requireBearerAuth(
req.app.locals.auth = authInfo;
next();
} catch (error) {
const wwwAuthenticate = resourceMetadataUrl
? `Bearer error="invalid_token", resource_metadata="${resourceMetadataUrl.toString()}"`
: 'Bearer error="invalid_token"';
res.set('WWW-Authenticate', wwwAuthenticate);
const message = error instanceof Error ? error.message : 'Invalid token';
res.set('WWW-Authenticate', buildWwwAuthHeader('invalid_token', message));
res.status(401).json({
error: 'invalid_token',
error_description: error instanceof Error ? error.message : 'Invalid token'
error_description: message
});
}
};

View file

@ -11,6 +11,7 @@
import { toNodeHandler } from 'better-auth/node';
import { oAuthDiscoveryMetadata, oAuthProtectedResourceMetadata } from 'better-auth/plugins';
import cors from 'cors';
import type { Request, Response as ExpressResponse, Router } from 'express';
import express from 'express';
@ -25,6 +26,12 @@ export interface SetupAuthServerOptions {
* Examples should be used for **demo** only and not for production purposes, however this mode disables some logging and other features.
*/
demoMode: boolean;
/**
* Enable verbose logging of better-auth requests/responses.
* WARNING: This may log sensitive information like tokens and cookies.
* Only use for debugging purposes.
*/
dangerousLoggingEnabled?: boolean;
}
// Store auth instance globally so it can be used for token verification
@ -79,7 +86,7 @@ async function ensureDemoUserExists(auth: DemoAuth): Promise<void> {
* @param options - Server configuration
*/
export function setupAuthServer(options: SetupAuthServerOptions): void {
const { authServerUrl, mcpServerUrl, demoMode } = options;
const { authServerUrl, mcpServerUrl, demoMode, dangerousLoggingEnabled = false } = options;
// Create better-auth instance with MCP plugin
const auth = createDemoAuth({
@ -96,54 +103,68 @@ export function setupAuthServer(options: SetupAuthServerOptions): void {
const authApp = express();
// Enable CORS for all origins (demo only) - must be before other middleware
authApp.use((_req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Expose-Headers', 'WWW-Authenticate');
if (_req.method === 'OPTIONS') {
res.sendStatus(200);
return;
}
next();
});
// WARNING: This configuration is for demo purposes only. In production, you should restrict this to specific origins and configure CORS yourself.
authApp.use(
cors({
origin: '*' // WARNING: This allows all origins to access the auth server. In production, you should restrict this to specific origins.
})
);
// Request logging middleware for OAuth endpoints
authApp.use('/api/auth', (req, res, next) => {
const timestamp = new Date().toISOString();
console.log(`${timestamp} [Auth Request] ${req.method} ${req.url}`);
if (req.method === 'POST') {
console.log(`${timestamp} [Auth Request] Content-Type: ${req.headers['content-type']}`);
}
if (demoMode) {
// Log response when it finishes
const originalSend = res.send.bind(res);
res.send = function (body) {
console.log(`${timestamp} [Auth Response] ${res.statusCode} ${req.url}`);
if (res.statusCode >= 400 && body) {
try {
const parsed = typeof body === 'string' ? JSON.parse(body) : body;
console.log(`${timestamp} [Auth Response] Error:`, parsed);
} catch {
// Not JSON, log as-is if short
if (typeof body === 'string' && body.length < 200) {
console.log(`${timestamp} [Auth Response] Body: ${body}`);
}
}
}
return originalSend(body);
};
}
next();
});
// Create better-auth handler
// toNodeHandler bypasses Express methods
const betterAuthHandler = toNodeHandler(auth);
// Mount better-auth handler BEFORE body parsers
// toNodeHandler reads the raw request body, so Express must not consume it first
authApp.all('/api/auth/{*splat}', toNodeHandler(auth));
if (dangerousLoggingEnabled) {
// Verbose logging mode - intercept at Node.js level to see all requests/responses
// WARNING: This may log sensitive information like tokens and cookies
authApp.all('/api/auth/{*splat}', (req, res) => {
const ts = new Date().toISOString();
console.log(`\n${'='.repeat(60)}`);
console.log(`${ts} [AUTH] ${req.method} ${req.originalUrl}`);
console.log(`${ts} [AUTH] Query:`, JSON.stringify(req.query));
console.log(`${ts} [AUTH] Headers.Cookie:`, req.headers.cookie?.slice(0, 100));
// Intercept writeHead to capture status and headers (including redirects)
const originalWriteHead = res.writeHead.bind(res);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
res.writeHead = function (statusCode: number, ...args: any[]) {
console.log(`${ts} [AUTH] >>> Response Status: ${statusCode}`);
// Headers can be in different positions depending on the overload
const headers = args.find(a => typeof a === 'object' && a !== null);
if (headers) {
if (headers.location || headers.Location) {
console.log(`${ts} [AUTH] >>> Location (redirect): ${headers.location || headers.Location}`);
}
console.log(`${ts} [AUTH] >>> Headers:`, JSON.stringify(headers));
}
return originalWriteHead(statusCode, ...args);
};
// Intercept write to capture response body
const originalWrite = res.write.bind(res);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
res.write = function (chunk: any, ...args: any[]) {
if (chunk) {
const bodyPreview = typeof chunk === 'string' ? chunk.slice(0, 500) : chunk.toString().slice(0, 500);
console.log(`${ts} [AUTH] >>> Body: ${bodyPreview}`);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return originalWrite(chunk, ...(args as [any]));
};
return betterAuthHandler(req, res);
});
} else {
// Normal mode - no verbose logging
authApp.all('/api/auth/{*splat}', toNodeHandler(auth));
}
// OAuth metadata endpoints using better-auth's built-in handlers
authApp.get('/.well-known/oauth-authorization-server', toNodeHandler(oAuthDiscoveryMetadata(auth)));
// Add explicit OPTIONS handler for CORS preflight
authApp.options('/.well-known/oauth-authorization-server', cors());
authApp.get('/.well-known/oauth-authorization-server', cors(), toNodeHandler(oAuthDiscoveryMetadata(auth)));
// Body parsers for non-better-auth routes (like /sign-in)
authApp.use(express.json());
@ -239,14 +260,25 @@ export function setupAuthServer(options: SetupAuthServerOptions): void {
* This is needed because MCP clients discover the auth server by first
* fetching protected resource metadata from the MCP server.
*
* Per RFC 9728 Section 3, the metadata URL includes the resource path.
* E.g., for resource http://localhost:3000/mcp, metadata is at
* http://localhost:3000/.well-known/oauth-protected-resource/mcp
*
* See: https://www.better-auth.com/docs/plugins/mcp#oauth-protected-resource-metadata
*
* @param resourcePath - The path of the MCP resource (e.g., '/mcp'). Defaults to '/mcp'.
*/
export function createProtectedResourceMetadataRouter(): Router {
export function createProtectedResourceMetadataRouter(resourcePath = '/mcp'): Router {
const auth = getAuth();
const router = express.Router();
// Serve at the standard well-known path
router.get('/.well-known/oauth-protected-resource', toNodeHandler(oAuthProtectedResourceMetadata(auth)));
// Construct the metadata path per RFC 9728 Section 3
const metadataPath = `/.well-known/oauth-protected-resource${resourcePath}`;
// Enable CORS for browser-based clients to discover the auth server
// Add explicit OPTIONS handler for CORS preflight
router.options(metadataPath, cors());
router.get(metadataPath, cors(), toNodeHandler(oAuthProtectedResourceMetadata(auth)));
return router;
}

View file

@ -3,6 +3,8 @@
"include": ["./"],
"exclude": ["node_modules", "dist"],
"compilerOptions": {
"declaration": false,
"declarationMap": false,
"paths": {
"*": ["./*"],
"@modelcontextprotocol/server": ["./node_modules/@modelcontextprotocol/server/src/index.ts"],

85
pnpm-lock.yaml generated
View file

@ -342,8 +342,8 @@ importers:
specifier: workspace:^
version: link:../../packages/server
better-auth:
specifier: ^1.4.7
version: 1.4.7(better-sqlite3@12.5.0)(vitest@4.0.16(@types/node@24.10.4)(tsx@4.21.0)(yaml@2.8.2))
specifier: ^1.4.17
version: 1.4.17(better-sqlite3@12.6.2)(vitest@4.0.16(@types/node@24.10.4)(tsx@4.21.0)(yaml@2.8.2))
cors:
specifier: catalog:runtimeServerOnly
version: 2.8.5
@ -388,11 +388,14 @@ importers:
specifier: workspace:^
version: link:../../packages/server
better-auth:
specifier: 1.4.7
version: 1.4.7(better-sqlite3@12.5.0)(vitest@4.0.16(@types/node@24.10.4)(tsx@4.21.0)(yaml@2.8.2))
specifier: ^1.4.17
version: 1.4.17(better-sqlite3@12.6.2)(vitest@4.0.16(@types/node@24.10.4)(tsx@4.21.0)(yaml@2.8.2))
better-sqlite3:
specifier: ^12.4.1
version: 12.5.0
specifier: ^12.6.2
version: 12.6.2
cors:
specifier: catalog:runtimeServerOnly
version: 2.8.5
express:
specifier: catalog:runtimeServerOnly
version: 5.2.1
@ -415,6 +418,9 @@ importers:
'@types/better-sqlite3':
specifier: ^7.6.13
version: 7.6.13
'@types/cors':
specifier: catalog:devTools
version: 2.8.19
'@types/express':
specifier: catalog:devTools
version: 5.0.6
@ -932,20 +938,20 @@ packages:
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
engines: {node: '>=6.9.0'}
'@better-auth/core@1.4.7':
resolution: {integrity: sha512-rNfj8aNFwPwAMYo+ahoWDsqKrV7svD3jhHSC6+A77xxKodbgV0UgH+RO21GMaZ0PPAibEl851nw5e3bsNslW/w==}
'@better-auth/core@1.4.17':
resolution: {integrity: sha512-WSaEQDdUO6B1CzAmissN6j0lx9fM9lcslEYzlApB5UzFaBeAOHNUONTdglSyUs6/idiZBoRvt0t/qMXCgIU8ug==}
peerDependencies:
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
better-call: 1.1.5
better-call: 1.1.8
jose: ^6.1.0
kysely: ^0.28.5
nanostores: ^1.0.1
'@better-auth/telemetry@1.4.7':
resolution: {integrity: sha512-k07C/FWnX6m+IxLruNkCweIxuaIwVTB2X40EqwamRVhYNBAhOYZFGLHH+PtQyM+Yf1Z4+8H6MugLOXSreXNAjQ==}
'@better-auth/telemetry@1.4.17':
resolution: {integrity: sha512-R1BC4e/bNjQbXu7lG6ubpgmsPj7IMqky5DvMlzAtnAJWJhh99pMh/n6w5gOHa0cqDZgEAuj75IPTxv+q3YiInA==}
peerDependencies:
'@better-auth/core': 1.4.7
'@better-auth/core': 1.4.17
'@better-auth/utils@0.3.0':
resolution: {integrity: sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==}
@ -2083,26 +2089,27 @@ packages:
resolution: {integrity: sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==}
hasBin: true
better-auth@1.4.7:
resolution: {integrity: sha512-kVmDQxzqGwP4FFMOYpS5I7oAaoFW3hwooUAAtcbb2DrOYv5EUvRUDJbTMaPoMTj7URjNDQ6vG9gcCS1Q+0aVBw==}
better-auth@1.4.17:
resolution: {integrity: sha512-VmHGQyKsEahkEs37qguROKg/6ypYpNF13D7v/lkbO7w7Aivz0Bv2h+VyUkH4NzrGY0QBKXi1577mGhDCVwp0ew==}
peerDependencies:
'@lynx-js/react': '*'
'@prisma/client': ^5.22.0
'@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0
'@sveltejs/kit': ^2.0.0
'@tanstack/react-start': ^1.0.0
better-sqlite3: ^12.4.1
drizzle-kit: ^0.31.4
drizzle-orm: ^0.41.0
mongodb: ^6.18.0
mysql2: ^3.14.4
'@tanstack/solid-start': ^1.0.0
better-sqlite3: ^12.0.0
drizzle-kit: '>=0.31.4'
drizzle-orm: '>=0.41.0'
mongodb: ^6.0.0 || ^7.0.0
mysql2: ^3.0.0
next: ^14.0.0 || ^15.0.0 || ^16.0.0
pg: ^8.16.3
prisma: ^5.22.0
pg: ^8.0.0
prisma: ^5.0.0 || ^6.0.0 || ^7.0.0
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
solid-js: ^1.0.0
svelte: ^4.0.0 || ^5.0.0
vitest: ^4.0.15
vitest: ^2.0.0 || ^3.0.0 || ^4.0.0
vue: ^3.0.0
peerDependenciesMeta:
'@lynx-js/react':
@ -2113,6 +2120,8 @@ packages:
optional: true
'@tanstack/react-start':
optional: true
'@tanstack/solid-start':
optional: true
better-sqlite3:
optional: true
drizzle-kit:
@ -2142,8 +2151,8 @@ packages:
vue:
optional: true
better-call@1.1.5:
resolution: {integrity: sha512-nQJ3S87v6wApbDwbZ++FrQiSiVxWvZdjaO+2v6lZJAG2WWggkB2CziUDjPciz3eAt9TqfRursIQMZIcpkBnvlw==}
better-call@1.1.8:
resolution: {integrity: sha512-XMQ2rs6FNXasGNfMjzbyroSwKwYbZ/T3IxruSS6U2MJRsSYh3wYtG3o6H00ZlKZ/C/UPOAD97tqgQJNsxyeTXw==}
peerDependencies:
zod: ^4.0.0
peerDependenciesMeta:
@ -2154,8 +2163,8 @@ packages:
resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
engines: {node: '>=4'}
better-sqlite3@12.5.0:
resolution: {integrity: sha512-WwCZ/5Diz7rsF29o27o0Gcc1Du+l7Zsv7SYtVPG0X3G/uUI1LqdxrQI7c9Hs2FWpqXXERjW9hp6g3/tH7DlVKg==}
better-sqlite3@12.6.2:
resolution: {integrity: sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA==}
engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x}
bindings@1.5.0:
@ -4069,20 +4078,20 @@ snapshots:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
'@better-auth/core@1.4.7(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.5(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)':
'@better-auth/core@1.4.17(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)':
dependencies:
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
'@standard-schema/spec': 1.1.0
better-call: 1.1.5(zod@4.3.5)
better-call: 1.1.8(zod@4.3.5)
jose: 6.1.3
kysely: 0.28.9
nanostores: 1.1.0
zod: 4.3.5
'@better-auth/telemetry@1.4.7(@better-auth/core@1.4.7(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.5(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0))':
'@better-auth/telemetry@1.4.17(@better-auth/core@1.4.17(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0))':
dependencies:
'@better-auth/core': 1.4.7(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.5(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)
'@better-auth/core': 1.4.17(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
@ -5160,25 +5169,25 @@ snapshots:
baseline-browser-mapping@2.9.14: {}
better-auth@1.4.7(better-sqlite3@12.5.0)(vitest@4.0.16(@types/node@24.10.4)(tsx@4.21.0)(yaml@2.8.2)):
better-auth@1.4.17(better-sqlite3@12.6.2)(vitest@4.0.16(@types/node@24.10.4)(tsx@4.21.0)(yaml@2.8.2)):
dependencies:
'@better-auth/core': 1.4.7(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.5(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)
'@better-auth/telemetry': 1.4.7(@better-auth/core@1.4.7(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.5(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0))
'@better-auth/core': 1.4.17(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0)
'@better-auth/telemetry': 1.4.17(@better-auth/core@1.4.17(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.5))(jose@6.1.3)(kysely@0.28.9)(nanostores@1.1.0))
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
'@noble/ciphers': 2.1.1
'@noble/hashes': 2.0.1
better-call: 1.1.5(zod@4.3.5)
better-call: 1.1.8(zod@4.3.5)
defu: 6.1.4
jose: 6.1.3
kysely: 0.28.9
nanostores: 1.1.0
zod: 4.3.5
optionalDependencies:
better-sqlite3: 12.5.0
better-sqlite3: 12.6.2
vitest: 4.0.16(@types/node@24.10.4)(tsx@4.21.0)(yaml@2.8.2)
better-call@1.1.5(zod@4.3.5):
better-call@1.1.8(zod@4.3.5):
dependencies:
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
@ -5191,7 +5200,7 @@ snapshots:
dependencies:
is-windows: 1.0.2
better-sqlite3@12.5.0:
better-sqlite3@12.6.2:
dependencies:
bindings: 1.5.0
prebuild-install: 7.1.3

View file

@ -57,8 +57,8 @@ linkWorkspacePackages: deep
minimumReleaseAge: 10080 # 7 days
minimumReleaseAgeExclude:
- '@modelcontextprotocol/conformance'
- hono@4.11.4 # fixes https://github.com/advisories/GHSA-3vhc-576x-3qv4 https://github.com/advisories/GHSA-f67f-6cw9-8mq4
- '@hono/node-server@1.19.9' # https://github.com/honojs/node-server/pull/295
- hono@4.11.4 # fixes https://github.com/advisories/GHSA-3vhc-576x-3qv4 https://github.com/advisories/GHSA-f67f-6cw9-8mq4
- '@hono/node-server@1.19.9' # https://github.com/honojs/node-server/pull/295
onlyBuiltDependencies:
- better-sqlite3