Skip to main content
Glama
akutishevsky

LunchMoney MCP Server

create_category

Create a new transaction category in LunchMoney to organize and classify financial transactions with customizable settings for budgeting, income tracking, and totals calculation.

Instructions

Create a single category.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
inputYes

Implementation Reference

  • The handler function for the 'create_category' tool. It extracts input parameters, constructs a request body, makes a POST request to the Lunchmoney API /categories endpoint, handles errors, and returns the created category as JSON.
    async ({ input }) => {
        const {
            name,
            description,
            is_income,
            exclude_from_budget,
            exclude_from_totals,
            archived,
            group_id,
        } = input;
        const { baseUrl, lunchmoneyApiToken } = getConfig();
        const requestBody: any = {
            name,
            description,
            is_income,
            exclude_from_budget,
            exclude_from_totals,
            archived,
        };
    
        if (group_id !== undefined) {
            requestBody.group_id = group_id;
        }
    
        const response = await fetch(`${baseUrl}/categories`, {
            method: "POST",
            headers: {
                Authorization: `Bearer ${lunchmoneyApiToken}`,
                "Content-Type": "application/json",
            },
            body: JSON.stringify(requestBody),
        });
    
        if (!response.ok) {
            return {
                content: [
                    {
                        type: "text",
                        text: `Failed to create a single category: ${response.statusText}`,
                    },
                ],
            };
        }
    
        const category: Category = await response.json();
        
        return {
            content: [
                {
                    type: "text",
                    text: JSON.stringify(category),
                },
            ],
        };
    }
  • The Zod input schema for the 'create_category' tool, defining parameters like name, description, various boolean flags, and optional group_id.
    input: z.object({
        name: z
            .string()
            .describe(
                "Name of category. Must be between 1 and 40 characters."
            ),
        description: z
            .string()
            .optional()
            .default("")
            .describe(
                "Description of category. Must be less than 140 characters."
            ),
        is_income: z
            .boolean()
            .optional()
            .default(false)
            .describe(
                "Whether or not transactions in this category should be treated as income."
            ),
        exclude_from_budget: z
            .boolean()
            .optional()
            .default(false)
            .describe(
                "Whether or not transactions in this category should be excluded from budgets."
            ),
        exclude_from_totals: z
            .boolean()
            .optional()
            .default(false)
            .describe(
                "Whether or not transactions in this category should be excluded from calculated totals."
            ),
        archived: z
            .boolean()
            .optional()
            .default(false)
            .describe("Whether or not category should be archived."),
        group_id: z
            .number()
            .optional()
            .describe(
                "Assigns the newly-created category to an existing category group."
            ),
    }),
  • The registration of the 'create_category' tool via server.tool(), which includes the tool name, description, input schema, and handler function. This is called within the registerCategoryTools function.
    server.tool(
        "create_category",
        "Create a single category.",
        {
            input: z.object({
                name: z
                    .string()
                    .describe(
                        "Name of category. Must be between 1 and 40 characters."
                    ),
                description: z
                    .string()
                    .optional()
                    .default("")
                    .describe(
                        "Description of category. Must be less than 140 characters."
                    ),
                is_income: z
                    .boolean()
                    .optional()
                    .default(false)
                    .describe(
                        "Whether or not transactions in this category should be treated as income."
                    ),
                exclude_from_budget: z
                    .boolean()
                    .optional()
                    .default(false)
                    .describe(
                        "Whether or not transactions in this category should be excluded from budgets."
                    ),
                exclude_from_totals: z
                    .boolean()
                    .optional()
                    .default(false)
                    .describe(
                        "Whether or not transactions in this category should be excluded from calculated totals."
                    ),
                archived: z
                    .boolean()
                    .optional()
                    .default(false)
                    .describe("Whether or not category should be archived."),
                group_id: z
                    .number()
                    .optional()
                    .describe(
                        "Assigns the newly-created category to an existing category group."
                    ),
            }),
        },
        async ({ input }) => {
            const {
                name,
                description,
                is_income,
                exclude_from_budget,
                exclude_from_totals,
                archived,
                group_id,
            } = input;
            const { baseUrl, lunchmoneyApiToken } = getConfig();
            const requestBody: any = {
                name,
                description,
                is_income,
                exclude_from_budget,
                exclude_from_totals,
                archived,
            };
    
            if (group_id !== undefined) {
                requestBody.group_id = group_id;
            }
    
            const response = await fetch(`${baseUrl}/categories`, {
                method: "POST",
                headers: {
                    Authorization: `Bearer ${lunchmoneyApiToken}`,
                    "Content-Type": "application/json",
                },
                body: JSON.stringify(requestBody),
            });
    
            if (!response.ok) {
                return {
                    content: [
                        {
                            type: "text",
                            text: `Failed to create a single category: ${response.statusText}`,
                        },
                    ],
                };
            }
    
            const category: Category = await response.json();
            
            return {
                content: [
                    {
                        type: "text",
                        text: JSON.stringify(category),
                    },
                ],
            };
        }
    );
  • src/index.ts:24-24 (registration)
    Invocation of registerCategoryTools(server) in the main server setup, which registers the create_category tool among others.
    registerCategoryTools(server);
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. 'Create' implies a write/mutation operation, but the description doesn't disclose behavioral traits like permission requirements, whether creation is idempotent, error conditions, or what happens on success. It mentions 'single' which hints at batch limitations, but this is minimal context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise with a single sentence. It's front-loaded with the core action and resource, with no wasted words. For a simple creation tool, this brevity is appropriate and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (a write operation with 1 parameter containing 7 nested properties), no annotations, and no output schema, the description is incomplete. It doesn't address what the tool returns, error handling, or how it fits into the broader system with siblings like 'get_single_category'. The schema handles parameters well, but the description lacks necessary context for safe invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds no parameter information beyond the schema. With 0% schema description coverage (the schema has detailed descriptions for all properties), the baseline is 3. The description doesn't compensate by explaining parameter relationships or usage, but the schema adequately covers semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Create a single category' states the basic action (create) and resource (category), but it's vague about what a 'category' represents in this context. It doesn't differentiate from sibling tools like 'create_category_group' or 'add_to_category_group', leaving ambiguity about the specific type of entity being created.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives. With siblings like 'create_category_group' and 'update_category', the description offers no context about prerequisites, when this creation is appropriate, or what distinguishes it from related operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/akutishevsky/lunchmoney-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server