feat: add MCP server for AI assistant integration (#5882)
This commit is contained in:
1 parent
d77c6f8d4e
commit
6baff7be3d
47 files changed
+5722
-12624
No files matched your search
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user