Skip to main content
Glama
hlebtkachenko

POHODA MCP Server

pohoda_create_internal_doc

Create internal documents in POHODA accounting software by specifying date, text, variable symbols, notes, and line items with pricing and VAT rates.

Instructions

Create an internal document in POHODA. Requires date. Optional: text, variable symbol, note, and line items.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
dateYesDocument date (DD.MM.YYYY or YYYY-MM-DD)
textNoDocument text/description
symVarNoVariable symbol
noteNoNote
itemsNoLine items: text, quantity, unitPrice, rateVAT (none|low|high)

Implementation Reference

  • Implementation of the `pohoda_create_internal_doc` MCP tool, which registers the tool and defines the handler that constructs and sends the XML request to create an internal document.
    server.tool(
      "pohoda_create_internal_doc",
      "Create an internal document in POHODA. Requires date. Optional: text, variable symbol, note, and line items.",
      {
        date: z.string().describe("Document date (DD.MM.YYYY or YYYY-MM-DD)"),
        text: z.string().optional().describe("Document text/description"),
        symVar: z.string().optional().describe("Variable symbol"),
        note: z.string().optional().describe("Note"),
        items: z
          .array(intDocItemSchema)
          .optional()
          .describe("Line items: text, quantity, unitPrice, rateVAT (none|low|high)"),
      },
      async (params) => {
        try {
          const xml = buildImportDoc({ ico: client.ico }, (item) => {
            const intDoc = item.ele(NS.int, "int:intDoc").att("version", "2.0");
            const header = intDoc.ele(NS.int, "int:intDocHeader");
    
            header.ele(NS.int, "int:date").txt(toIsoDate(params.date));
            if (params.text) header.ele(NS.int, "int:text").txt(params.text);
            if (params.symVar) header.ele(NS.int, "int:symVar").txt(params.symVar);
            if (params.note) header.ele(NS.int, "int:note").txt(params.note);
    
            if (params.items && params.items.length > 0) {
              const detail = intDoc.ele(NS.int, "int:intDocDetail");
              for (const it of params.items) {
                const intItem = detail.ele(NS.int, "int:intDocItem");
                intItem.ele(NS.int, "int:text").txt(it.text);
                intItem.ele(NS.int, "int:quantity").txt(String(it.quantity));
                intItem.ele(NS.int, "int:rateVAT").txt(it.rateVAT);
                intItem
                  .ele(NS.int, "int:homeCurrency")
                  .ele(NS.typ, "typ:unitPrice")
                  .txt(String(it.unitPrice));
              }
            }
          });
          const response = await client.sendXml(xml);
          const result = extractImportResult(parseResponse(response));
          return result.success
            ? ok(
                `Internal document created successfully.${result.producedId != null ? ` ID: ${result.producedId}` : ""} ${result.message}`
              )
            : err(result.message);
        } catch (e) {
          return err((e as Error).message);
        }
      }
    );
  • Zod schema `intDocItemSchema` used for validating line items in the internal document creation tool.
    const intDocItemSchema = z.object({
      text: z.string(),
      quantity: z.number(),
      unitPrice: z.number(),
      rateVAT: z.enum(["none", "low", "high"]),
    });
  • Registration function `registerInternalDocTools` that installs the `pohoda_create_internal_doc` tool into the MCP server.
    export function registerInternalDocTools(server: McpServer, client: PohodaClient): void {
      server.tool(
        "pohoda_list_internal_docs",
        "List internal documents from POHODA. Supports filtering by ID, date range, or last changes. Returns JSON array of matching records.",
        {
          id: z.number().optional().describe("Filter by internal document ID"),
          dateFrom: z.string().optional().describe("Filter from date (DD.MM.YYYY or YYYY-MM-DD)"),
          dateTill: z.string().optional().describe("Filter till date (DD.MM.YYYY or YYYY-MM-DD)"),
          lastChanges: z.string().optional().describe("Filter by last changes date"),
        },
        async (params) => {
          try {
            const xml = buildExportRequest(
              { ico: client.ico },
              "lst:listIntDocRequest",
              NS.lst,
              "lst:requestIntDoc",
              (req) => applyFilter(req, params)
            );
            const response = await client.sendXml(xml);
            const parsed = parseResponse(response);
            const data = extractListData(parsed);
            return jsonResult("Internal documents", data, Array.isArray(data) ? data.length : 0);
          } catch (e) {
            return err((e as Error).message);
          }
        }
      );
    
      server.tool(
        "pohoda_create_internal_doc",
        "Create an internal document in POHODA. Requires date. Optional: text, variable symbol, note, and line items.",
        {
          date: z.string().describe("Document date (DD.MM.YYYY or YYYY-MM-DD)"),
          text: z.string().optional().describe("Document text/description"),
          symVar: z.string().optional().describe("Variable symbol"),
          note: z.string().optional().describe("Note"),
          items: z
            .array(intDocItemSchema)
            .optional()
            .describe("Line items: text, quantity, unitPrice, rateVAT (none|low|high)"),
        },
        async (params) => {
          try {
            const xml = buildImportDoc({ ico: client.ico }, (item) => {
              const intDoc = item.ele(NS.int, "int:intDoc").att("version", "2.0");
              const header = intDoc.ele(NS.int, "int:intDocHeader");
    
              header.ele(NS.int, "int:date").txt(toIsoDate(params.date));
              if (params.text) header.ele(NS.int, "int:text").txt(params.text);
              if (params.symVar) header.ele(NS.int, "int:symVar").txt(params.symVar);
              if (params.note) header.ele(NS.int, "int:note").txt(params.note);
    
              if (params.items && params.items.length > 0) {
                const detail = intDoc.ele(NS.int, "int:intDocDetail");
                for (const it of params.items) {
                  const intItem = detail.ele(NS.int, "int:intDocItem");
                  intItem.ele(NS.int, "int:text").txt(it.text);
                  intItem.ele(NS.int, "int:quantity").txt(String(it.quantity));
                  intItem.ele(NS.int, "int:rateVAT").txt(it.rateVAT);
                  intItem
                    .ele(NS.int, "int:homeCurrency")
                    .ele(NS.typ, "typ:unitPrice")
                    .txt(String(it.unitPrice));
                }
              }
            });
            const response = await client.sendXml(xml);
            const result = extractImportResult(parseResponse(response));
            return result.success
              ? ok(
                  `Internal document created successfully.${result.producedId != null ? ` ID: ${result.producedId}` : ""} ${result.message}`
                )
              : err(result.message);
          } catch (e) {
            return err((e as Error).message);
          }
        }
      );
    }

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/hlebtkachenko/pohoda-mcp'

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