Skip to main content
Glama
XeroAPI

Xero MCP Server

Official

update-credit-note

Modify draft credit notes in Xero by updating line items, reference, date, or contact. All line items must be provided as unspecified items will be removed. Returns a direct link to view the updated credit note.

Instructions

Update a credit note in Xero. Only works on draft credit notes. All line items must be provided. Any line items not provided will be removed. Including existing line items. Do not modify line items that have not been specified by the user. When a credit note is updated, a deep link to the credit note in Xero is returned. This deep link can be used to view the credit note in Xero directly. This link should be displayed to the user.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
creditNoteIdYes
lineItemsNoAll line items must be provided. Any line items not provided will be removed. Including existing line items. Do not modify line items that have not been specified by the user
referenceNo
dateNo
contactIdNo

Implementation Reference

  • Primary handler implementation for the 'update-credit-note' MCP tool. Defines the tool using CreateXeroTool, including schema, description, and the async executor that calls the Xero-specific handler and formats the MCP response with deep link.
    const UpdateCreditNoteTool = CreateXeroTool(
      "update-credit-note",
      "Update a credit note in Xero. Only works on draft credit notes.\
      All line items must be provided. Any line items not provided will be removed. Including existing line items.\
      Do not modify line items that have not been specified by the user.\
     When a credit note is updated, a deep link to the credit note in Xero is returned.\
     This deep link can be used to view the credit note in Xero directly.\
     This link should be displayed to the user.",
      {
        creditNoteId: z.string(),
        lineItems: z.array(lineItemSchema).optional().describe(
          "All line items must be provided. Any line items not provided will be removed. Including existing line items.\
          Do not modify line items that have not been specified by the user",
        ),
        reference: z.string().optional(),
        date: z.string().optional(),
        contactId: z.string().optional(),
      },
      async (
        {
          creditNoteId,
          lineItems,
          reference,
          date,
          contactId,
        }: {
          creditNoteId: string;
          lineItems?: Array<{
            description: string;
            quantity: number;
            unitAmount: number;
            accountCode: string;
            taxType: string;
          }>;
          reference?: string;
          date?: string;
          contactId?: string;
        },
      ) => {
        const result = await updateXeroCreditNote(
          creditNoteId,
          lineItems,
          reference,
          contactId,
          date,
        );
        if (result.isError) {
          return {
            content: [
              {
                type: "text" as const,
                text: `Error updating credit note: ${result.error}`,
              },
            ],
          };
        }
    
        const creditNote = result.result;
    
        const deepLink = creditNote.creditNoteID
          ? await getDeepLink(DeepLinkType.CREDIT_NOTE, creditNote.creditNoteID)
          : null;
    
        return {
          content: [
            {
              type: "text" as const,
              text: [
                "Credit note updated successfully:",
                `ID: ${creditNote?.creditNoteID}`,
                `Contact: ${creditNote?.contact?.name}`,
                `Total: ${creditNote?.total}`,
                `Status: ${creditNote?.status}`,
                deepLink ? `Link to view: ${deepLink}` : null,
              ].join("\n"),
            },
          ],
        };
      },
    );
  • Core business logic handler updateXeroCreditNote: authenticates, checks if credit note is DRAFT, updates via Xero API, handles errors.
    export async function updateXeroCreditNote(
      creditNoteId: string,
      lineItems?: CreditNoteLineItem[],
      reference?: string,
      contactId?: string,
      date?: string,
    ): Promise<XeroClientResponse<CreditNote>> {
      try {
        const existingCreditNote = await getCreditNote(creditNoteId);
    
        const creditNoteStatus = existingCreditNote?.status;
    
        // Only allow updates to DRAFT credit notes
        if (creditNoteStatus !== CreditNote.StatusEnum.DRAFT) {
          return {
            result: null,
            isError: true,
            error: `Cannot update credit note because it is not a draft. Current status: ${creditNoteStatus}`,
          };
        }
    
        const updatedCreditNote = await updateCreditNote(
          creditNoteId,
          lineItems,
          reference,
          contactId,
          date,
        );
    
        if (!updatedCreditNote) {
          throw new Error("Credit note update failed.");
        }
    
        return {
          result: updatedCreditNote,
          isError: false,
          error: null,
        };
      } catch (error) {
        return {
          result: null,
          isError: true,
          error: formatError(error),
        };
      }
    } 
  • Zod schema for credit note line items used in the tool input validation.
    const lineItemSchema = z.object({
      description: z.string(),
      quantity: z.number(),
      unitAmount: z.number(),
      accountCode: z.string(),
      taxType: z.string(),
    });
  • Registration of the UpdateCreditNoteTool in the UpdateTools array, which collects all update tools for further registration in tool-factory.ts.
    export const UpdateTools = [
      UpdateContactTool,
      UpdateCreditNoteTool,
      UpdateInvoiceTool,
      UpdateManualJournalTool,
      UpdateQuoteTool,
      UpdateItemTool,
      UpdateBankTransactionTool,
      ApprovePayrollTimesheetTool,
      AddTimesheetLineTool,
      UpdatePayrollTimesheetLineTool,
      RevertPayrollTimesheetTool,
      UpdateTrackingCategoryTool,
      UpdateTrackingOptionsTool
    ];
  • Final registration of UpdateTools (including update-credit-note) into the main tools list in tool-factory.ts, which is likely used by the MCP server.
    UpdateTools.map((tool) => tool()).forEach((tool) =>
Behavior4/5

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

With no annotations provided, the description carries the full burden and does well by disclosing key behavioral traits: it specifies the tool only works on draft credit notes, warns that missing line items will be removed, advises not to modify unspecified line items, and describes the return value (a deep link to view in Xero). However, it lacks details on permissions, rate limits, or error handling.

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

Conciseness4/5

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

The description is appropriately sized and front-loaded with key information (purpose and constraints). Sentences are efficient, but some redundancy exists (e.g., repeating line item warnings from the schema description), slightly reducing conciseness.

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

Completeness3/5

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

Given the complexity (a mutation tool with 5 parameters, no annotations, and no output schema), the description is moderately complete. It covers purpose, constraints, and return behavior but lacks details on parameter specifics beyond line items, error cases, or full output explanation, leaving room for improvement.

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?

Schema description coverage is low at 20%, but the description adds some meaning by explaining the 'lineItems' parameter behavior (all must be provided, omissions cause removal). It doesn't cover other parameters like 'creditNoteId', 'reference', 'date', or 'contactId', so it partially compensates but leaves gaps, aligning with the baseline for moderate schema coverage.

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

Purpose4/5

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

The description clearly states the action ('Update a credit note in Xero') and specifies the resource ('credit note'), making the purpose evident. However, it doesn't explicitly differentiate from sibling tools like 'create-credit-note' or other update tools, though the context of 'update' implies modification versus creation.

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

Usage Guidelines4/5

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

The description provides clear context for when to use this tool: 'Only works on draft credit notes.' It also implies usage by specifying constraints like requiring all line items, but it doesn't explicitly mention when not to use it or name alternatives (e.g., using 'create-credit-note' for new ones).

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/XeroAPI/xero-mcp-server'

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