feat: add MCP server for AI assistant integration (#5882)

This commit is contained in:
Thomas authored and GitHub committed 2026-06-10 18:28:34 +02:00
1 parent d77c6f8d4e
commit 6baff7be3d
47 files changed
+5722 -12624

No files matched your search

+49 -29
View File
@@ -1,7 +1,8 @@
import { z } from "zod/v4";
import { randomBytes } from "crypto";
import { hashPasswordAsync } from "@homarr/auth";
import { createId } from "@homarr/common";
import { generateSecureRandomToken } from "@homarr/common/server";
import { db, eq } from "@homarr/db";
import { apiKeys } from "@homarr/db/schema";
@@ -9,39 +10,58 @@ import { apiKeys } from "@homarr/db/schema";
import { createTRPCRouter, permissionRequiredProcedure } from "../trpc";
export const apiKeysRouter = createTRPCRouter({
getAll: permissionRequiredProcedure.requiresPermission("admin").query(() => {
return db.query.apiKeys.findMany({
columns: {
id: true,
apiKey: false,
},
with: {
user: {
columns: {
id: true,
name: true,
image: true,
email: true,
getAll: permissionRequiredProcedure
.requiresPermission("admin")
.meta({
mcp: { enabled: true, description: "List all API keys (admin only)" },
})
.query(() => {
return db.query.apiKeys.findMany({
columns: {
id: true,
apiKey: false,
},
with: {
user: {
columns: {
id: true,
name: true,
image: true,
email: true,
},
},
},
});
}),
create: permissionRequiredProcedure
.requiresPermission("admin")
.meta({
mcp: {
enabled: true,
description: "Create a new API key for the current user (admin only)",
},
});
}),
create: permissionRequiredProcedure.requiresPermission("admin").mutation(async ({ ctx }) => {
const randomToken = generateSecureRandomToken(64);
const hashedRandomToken = await hashPasswordAsync(randomToken);
const id = createId();
await db.insert(apiKeys).values({
id,
apiKey: hashedRandomToken,
userId: ctx.session.user.id,
});
return {
apiKey: `${id}.${randomToken}`,
};
}),
})
.mutation(async ({ ctx }) => {
const id = randomBytes(4).toString("hex");
const token = generateSecureRandomToken(24);
const hashedToken = await hashPasswordAsync(token);
await db.insert(apiKeys).values({
id,
apiKey: hashedToken,
userId: ctx.session.user.id,
});
return {
apiKey: `${id}.${token}`,
};
}),
delete: permissionRequiredProcedure
.requiresPermission("admin")
.meta({
mcp: {
enabled: true,
description: "Delete an API key by ID (admin only). REQUIRED: apiKeyId (string)",
},
})
.input(z.object({ apiKeyId: z.string() }))
.mutation(async ({ ctx, input }) => {
await ctx.db.delete(apiKeys).where(eq(apiKeys.id, input.apiKeyId)).limit(1);