Skip to content

Commit 01e13d7

Browse files
committed
Add admin db-info endpoint for debugging
1 parent 3afcdb4 commit 01e13d7

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

  • packages/mcp-server/app/api/db-info
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Database info endpoint (Admin only)
3+
*
4+
* Returns sanitized DB connection info + a simple SELECT 1.
5+
*/
6+
7+
import { createDatabase } from "@effect-patterns/toolkit";
8+
import { sql } from "drizzle-orm";
9+
import { Effect } from "effect";
10+
import { type NextRequest, NextResponse } from "next/server";
11+
import { validateAdminKey } from "../../../src/auth/adminAuth";
12+
import { runWithRuntime } from "../../../src/server/init";
13+
import { errorHandler } from "../../../src/server/errorHandler";
14+
15+
function sanitizeDatabaseUrl(url: string) {
16+
try {
17+
const parsed = new URL(url);
18+
return {
19+
protocol: parsed.protocol.replace(":", ""),
20+
host: parsed.host,
21+
database: parsed.pathname.replace("/", "") || undefined,
22+
search: parsed.search || undefined,
23+
};
24+
} catch {
25+
return { host: "invalid-url" };
26+
}
27+
}
28+
29+
const handleDbInfo = Effect.fn("db-info")(function* (request: NextRequest) {
30+
yield* validateAdminKey(request);
31+
32+
const dbUrl = process.env.DATABASE_URL;
33+
if (!dbUrl) {
34+
return yield* Effect.fail(
35+
new Error("DATABASE_URL not configured on server")
36+
);
37+
}
38+
39+
const result = yield* Effect.gen(function* () {
40+
const { db, close } = createDatabase(dbUrl);
41+
const testQuery = yield* Effect.tryPromise(async () => {
42+
return await db.execute(sql`SELECT 1 as test`);
43+
});
44+
yield* Effect.promise(() => close());
45+
return testQuery;
46+
});
47+
48+
return {
49+
success: true,
50+
database: sanitizeDatabaseUrl(dbUrl),
51+
testResult: result,
52+
};
53+
});
54+
55+
export async function GET(request: NextRequest) {
56+
const result = await runWithRuntime(
57+
handleDbInfo(request).pipe(Effect.catchAll((error) => errorHandler(error)))
58+
);
59+
60+
if (result instanceof Response) {
61+
return result;
62+
}
63+
64+
return NextResponse.json(result, { status: 200 });
65+
}

0 commit comments

Comments
 (0)