Skip to main content
Glama
hlebtkachenko

POHODA MCP Server

pohoda_create_bank

Create bank documents (receipts or expenses) in POHODA accounting software. Specify document type, date, and optional details like partner information, symbols, and line items.

Instructions

Create a bank document (receipt or expense) in POHODA. Requires bankType and date. Optional: text, account, bankCode, symbols, partner details, note, and line items.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bankTypeYesBank document type: receipt or expense (required)
dateYesDocument date (DD.MM.YYYY or YYYY-MM-DD)
textNoDocument text/description
accountNoBank account identifier
bankCodeNoBank code
symVarNoVariable symbol
symConstNoConstant symbol
symSpecNoSpecific symbol
partnerNameNoPartner company name
partnerStreetNoPartner street
partnerCityNoPartner city
partnerZipNoPartner ZIP code
partnerIcoNoPartner IČO
noteNoNote
itemsNoLine items: text, quantity, unitPrice, rateVAT (none|low|high)

Implementation Reference

  • The handler logic for creating bank documents (receipts or expenses) in POHODA, including input parameter mapping and XML construction.
    server.tool(
      "pohoda_create_bank",
      "Create a bank document (receipt or expense) in POHODA. Requires bankType and date. Optional: text, account, bankCode, symbols, partner details, note, and line items.",
      {
        bankType: bankTypeEnum.describe("Bank document type: receipt or expense (required)"),
        date: z.string().describe("Document date (DD.MM.YYYY or YYYY-MM-DD)"),
        text: z.string().optional().describe("Document text/description"),
        account: z.string().optional().describe("Bank account identifier"),
        bankCode: z.string().optional().describe("Bank code"),
        symVar: z.string().optional().describe("Variable symbol"),
        symConst: z.string().optional().describe("Constant symbol"),
        symSpec: z.string().optional().describe("Specific symbol"),
        partnerName: z.string().optional().describe("Partner company name"),
        partnerStreet: z.string().optional().describe("Partner street"),
        partnerCity: z.string().optional().describe("Partner city"),
        partnerZip: z.string().optional().describe("Partner ZIP code"),
        partnerIco: z.string().optional().describe("Partner IČO"),
        note: z.string().optional().describe("Note"),
        items: z
          .array(bankItemSchema)
          .optional()
          .describe("Line items: text, quantity, unitPrice, rateVAT (none|low|high)"),
      },
      async (params) => {
        try {
          const xml = buildImportDoc({ ico: client.ico }, (item) => {
            const bank = item.ele(NS.bnk, "bnk:bank").att("version", "2.0");
            const header = bank.ele(NS.bnk, "bnk:bankHeader");
    
            header.ele(NS.bnk, "bnk:bankType").txt(params.bankType);
            if (params.account) {
              header.ele(NS.bnk, "bnk:account").ele(NS.typ, "typ:ids").txt(params.account);
            }
            if (params.bankCode) header.ele(NS.bnk, "bnk:bankCode").txt(params.bankCode);
            header.ele(NS.bnk, "bnk:date").txt(toIsoDate(params.date));
            if (params.text) header.ele(NS.bnk, "bnk:text").txt(params.text);
            if (params.symVar) header.ele(NS.bnk, "bnk:symVar").txt(params.symVar);
            if (params.symConst) header.ele(NS.bnk, "bnk:symConst").txt(params.symConst);
            if (params.symSpec) header.ele(NS.bnk, "bnk:symSpec").txt(params.symSpec);
    
            const hasPartner =
              params.partnerName ?? params.partnerStreet ?? params.partnerCity ?? params.partnerZip ?? params.partnerIco;
            if (hasPartner) {
              const identity = header.ele(NS.bnk, "bnk:partnerIdentity");
              const typAddr = identity.ele(NS.typ, "typ:address");
              if (params.partnerName) typAddr.ele(NS.typ, "typ:name").txt(params.partnerName);
              if (params.partnerStreet) typAddr.ele(NS.typ, "typ:street").txt(params.partnerStreet);
              if (params.partnerCity) typAddr.ele(NS.typ, "typ:city").txt(params.partnerCity);
              if (params.partnerZip) typAddr.ele(NS.typ, "typ:zip").txt(params.partnerZip);
              if (params.partnerIco) typAddr.ele(NS.typ, "typ:ico").txt(params.partnerIco);
            }
    
            if (params.note) header.ele(NS.bnk, "bnk:note").txt(params.note);
    
            if (params.items && params.items.length > 0) {
              const detail = bank.ele(NS.bnk, "bnk:bankDetail");
              for (const it of params.items) {
                const bankItem = detail.ele(NS.bnk, "bnk:bankItem");
                bankItem.ele(NS.bnk, "bnk:text").txt(it.text);
                bankItem.ele(NS.bnk, "bnk:quantity").txt(String(it.quantity));
                bankItem.ele(NS.bnk, "bnk:rateVAT").txt(it.rateVAT);
                bankItem
                  .ele(NS.bnk, "bnk: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(
                `Bank document created successfully.${result.producedId != null ? ` ID: ${result.producedId}` : ""} ${result.message}`
              )
            : err(result.message);
        } catch (e) {
          return err((e as Error).message);
        }
      }
    );
  • Registration function that exposes 'pohoda_create_bank' (and other bank tools) to the MCP server.
    export function registerBankTools(server: McpServer, client: PohodaClient): void {
      server.tool(
        "pohoda_list_bank",
        "List bank documents (receipts and expenses) from POHODA. Supports filtering by ID, date range, company name, or last changes. Returns JSON array of matching records.",
        {
          id: z.number().optional().describe("Filter by bank 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)"),
          companyName: z.string().optional().describe("Filter by company name"),
          lastChanges: z.string().optional().describe("Filter by last changes date"),
        },
        async (params) => {
          try {
            const xml = buildExportRequest(
              { ico: client.ico },
              "lst:listBankRequest",
              NS.lst,
              "lst:requestBank",
              (req) => applyFilter(req, params)
            );
            const response = await client.sendXml(xml);
            const parsed = parseResponse(response);
            const data = extractListData(parsed);
            return jsonResult("Bank documents", data, Array.isArray(data) ? data.length : 0);
          } catch (e) {
            return err((e as Error).message);
          }
        }
      );
    
      server.tool(
        "pohoda_create_bank",
        "Create a bank document (receipt or expense) in POHODA. Requires bankType and date. Optional: text, account, bankCode, symbols, partner details, note, and line items.",
        {
          bankType: bankTypeEnum.describe("Bank document type: receipt or expense (required)"),
          date: z.string().describe("Document date (DD.MM.YYYY or YYYY-MM-DD)"),
          text: z.string().optional().describe("Document text/description"),
          account: z.string().optional().describe("Bank account identifier"),
          bankCode: z.string().optional().describe("Bank code"),
          symVar: z.string().optional().describe("Variable symbol"),
          symConst: z.string().optional().describe("Constant symbol"),
          symSpec: z.string().optional().describe("Specific symbol"),
          partnerName: z.string().optional().describe("Partner company name"),
          partnerStreet: z.string().optional().describe("Partner street"),
          partnerCity: z.string().optional().describe("Partner city"),
          partnerZip: z.string().optional().describe("Partner ZIP code"),
          partnerIco: z.string().optional().describe("Partner IČO"),
          note: z.string().optional().describe("Note"),
          items: z
            .array(bankItemSchema)
            .optional()
            .describe("Line items: text, quantity, unitPrice, rateVAT (none|low|high)"),
        },
        async (params) => {
          try {
            const xml = buildImportDoc({ ico: client.ico }, (item) => {
              const bank = item.ele(NS.bnk, "bnk:bank").att("version", "2.0");
              const header = bank.ele(NS.bnk, "bnk:bankHeader");
    
              header.ele(NS.bnk, "bnk:bankType").txt(params.bankType);
              if (params.account) {
                header.ele(NS.bnk, "bnk:account").ele(NS.typ, "typ:ids").txt(params.account);
              }
              if (params.bankCode) header.ele(NS.bnk, "bnk:bankCode").txt(params.bankCode);
              header.ele(NS.bnk, "bnk:date").txt(toIsoDate(params.date));
              if (params.text) header.ele(NS.bnk, "bnk:text").txt(params.text);
              if (params.symVar) header.ele(NS.bnk, "bnk:symVar").txt(params.symVar);
              if (params.symConst) header.ele(NS.bnk, "bnk:symConst").txt(params.symConst);
              if (params.symSpec) header.ele(NS.bnk, "bnk:symSpec").txt(params.symSpec);
    
              const hasPartner =
                params.partnerName ?? params.partnerStreet ?? params.partnerCity ?? params.partnerZip ?? params.partnerIco;
              if (hasPartner) {
                const identity = header.ele(NS.bnk, "bnk:partnerIdentity");
                const typAddr = identity.ele(NS.typ, "typ:address");
                if (params.partnerName) typAddr.ele(NS.typ, "typ:name").txt(params.partnerName);
                if (params.partnerStreet) typAddr.ele(NS.typ, "typ:street").txt(params.partnerStreet);
                if (params.partnerCity) typAddr.ele(NS.typ, "typ:city").txt(params.partnerCity);
                if (params.partnerZip) typAddr.ele(NS.typ, "typ:zip").txt(params.partnerZip);
                if (params.partnerIco) typAddr.ele(NS.typ, "typ:ico").txt(params.partnerIco);
              }
    
              if (params.note) header.ele(NS.bnk, "bnk:note").txt(params.note);
    
              if (params.items && params.items.length > 0) {
                const detail = bank.ele(NS.bnk, "bnk:bankDetail");
                for (const it of params.items) {
                  const bankItem = detail.ele(NS.bnk, "bnk:bankItem");
                  bankItem.ele(NS.bnk, "bnk:text").txt(it.text);
                  bankItem.ele(NS.bnk, "bnk:quantity").txt(String(it.quantity));
                  bankItem.ele(NS.bnk, "bnk:rateVAT").txt(it.rateVAT);
                  bankItem
                    .ele(NS.bnk, "bnk: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(
                  `Bank document created successfully.${result.producedId != null ? ` ID: ${result.producedId}` : ""} ${result.message}`
                )
              : err(result.message);
          } catch (e) {
            return err((e as Error).message);
          }
        }
      );
    }
  • Zod schema for bank items used in the 'pohoda_create_bank' tool.
    const bankItemSchema = z.object({
      text: z.string(),
      quantity: z.number(),
      unitPrice: z.number(),
      rateVAT: z.enum(["none", "low", "high"]),
    });
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It fails to mention whether the operation is idempotent, what side effects occur (e.g., accounting entry creation), error handling behavior, or the format of return values for this write operation.

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 two efficient sentences. The first states purpose; the second summarizes requirements and options. Every word earns its place with no redundancy or filler content.

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?

For a complex creation tool with 15 parameters and nested line items, the description covers the essential parameter groupings but omits critical context expected for a write operation: error scenarios, idempotency guarantees, or confirmation of what constitutes a successful creation (especially given no output schema exists).

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 input schema has 100% description coverage, establishing a baseline of 3. The description adds value by grouping related parameters ('symbols', 'partner details', 'line items') and explicitly calling out required fields, but does not add semantic depth beyond what the schema already provides (e.g., business context for 'rateVAT' values).

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 identifies the action ('Create') and resource ('bank document'), specifying the two sub-types ('receipt or expense'). However, it does not explicitly differentiate from sibling tools like pohoda_create_voucher or pohoda_create_invoice, leaving some ambiguity about when to select this specific tool.

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?

The description lists required and optional parameters but provides no guidance on when to use this tool versus alternatives (e.g., when to use bank documents vs. invoices or vouchers). It states 'Requires bankType and date' which is parameter-level usage, not tool-selection logic.

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

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