Complete MCP coverage: 58 tools, invoice filters, templates, email config, profile

MCP expanded from 49 to 58 tools:
- templates_list, templates_list_by_type, templates_create, templates_update,
  templates_delete — full invoice template CRUD
- businesses_get_email_config, businesses_update_email_config — configure
  per-business Resend API key and sending domain
- profile_get, profile_update — user profile read/write

invoices_list now accepts optional status and clientId filters (e.g. list
all draft invoices, or all invoices for a specific client). Backed by a
new optional input on invoices.getAll in the tRPC router.

https://claude.ai/code/session_014126WHVRT8mftmqkU6dajG
This commit is contained in:
Claude
2026-06-11 05:33:13 +00:00
parent c6b6641dfa
commit c0a333710f
2 changed files with 162 additions and 24 deletions
+31 -20
View File
@@ -1,5 +1,5 @@
import { z } from "zod";
import { desc, eq, inArray } from "drizzle-orm";
import { and, desc, eq, inArray } from "drizzle-orm";
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
import {
invoices,
@@ -114,25 +114,36 @@ const calculateInvoiceTotal = (
};
export const invoicesRouter = createTRPCRouter({
getAll: protectedProcedure.query(async ({ ctx }) => {
try {
return await ctx.db.query.invoices.findMany({
where: eq(invoices.createdById, ctx.session.user.id),
with: {
business: true,
client: true,
items: true,
},
orderBy: (invoices, { desc }) => [desc(invoices.issueDate)],
});
} catch (error) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "Failed to fetch invoices",
cause: error,
});
}
}),
getAll: protectedProcedure
.input(
z.object({
status: z.enum(["draft", "sent", "paid"]).optional(),
clientId: z.string().optional(),
}).optional(),
)
.query(async ({ ctx, input }) => {
try {
const conditions = [eq(invoices.createdById, ctx.session.user.id)];
if (input?.status) conditions.push(eq(invoices.status, input.status));
if (input?.clientId) conditions.push(eq(invoices.clientId, input.clientId));
return await ctx.db.query.invoices.findMany({
where: and(...conditions),
with: {
business: true,
client: true,
items: true,
},
orderBy: (invoices, { desc }) => [desc(invoices.issueDate)],
});
} catch (error) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "Failed to fetch invoices",
cause: error,
});
}
}),
getLineItemHistory: protectedProcedure.query(async ({ ctx }) => {
const userInvoices = await ctx.db