subiekt123-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@subiekt123-mcppreview the monthly invoice for August"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
subiekt123-mcp
Stateless MCP server for invoicing in Subiekt 123 (InsERT API).
SDK:
@modelcontextprotocol/server2.0.0, spec 2026-07-28Transport: stateless Streamable HTTP (
createMcpHandler) and stdioNode ≥ 20, zod v4, ESM
The server keeps no state between requests - createMcpHandler builds a fresh McpServer instance per
HTTP request, so it scales horizontally without session affinity and without Mcp-Session-Id.
New here? Start with GETTING-STARTED.md - credentials, first run, connecting a client, and issuing your first invoice. This README covers architecture and reference detail.
Safety gate: HMAC token
create_invoice does not accept an invoice payload - only a token issued by a preview_* tool.
preview_<template>_invoice({month:"2026-08"})
→ preview (buyer, line items, totals, rate, warnings)
→ token: <payload>.<HMAC-SHA256> (valid for 10 minutes)
create_invoice({token})
→ signature + TTL verification
→ POST /documentsWhy: in MCP it is the model that invokes a tool, and annotations.destructiveHint is only a hint to the
client - the spec states plainly that annotations do not change how the SDK runs a tool. The token binds
issuance to one specific, previously displayed document: changing even a single amount invalidates the
signature. The token carries the whole payload, so the server stays stateless.
HMAC key: ~/.config/subiekt123/preview-hmac.key (32 random bytes, generated on first use, chmod 600).
It lives outside credentials.json - a token leaked from a conversation transcript is not enough to
forge approval.
Related MCP server: mcp-server-smallinvoice
Installation
cd subiekt123 && npm installThe repository contains no business data - no account numbers, no tax IDs, no amounts, no client
names. All of that lives in two files under ~/.config/subiekt123/ (chmod 600).
1. Secrets - credentials.json
{
"clientId": "<Client ID from the InsERT developer portal>",
"clientSecret": "<Client Secret>",
"redirectUri": "http://localhost:53682/callback",
"subscriptionKey": "<Subiekt 123 API subscription key>",
"subscriptionHeader": "Ocp-Apim-Subscription-Key"
}Where to get them: konto.insert.com.pl → Moje produkty → InsERT API →
"Uzyskaj dostęp" → the Aplikacje menu → InsERT API
(developers.insert.com.pl). There you will find Moje aplikacje
(registration: scope subiekt123, return address = redirectUri) and Subskrypcje.
One-time OAuth consent:
npm run authThe refreshToken rotates on every refresh and is persisted automatically. Inactivity for more than 90
days, or more than 365 days since the first consent, requires running npm run auth again.
2. Invoicing profile - profile.json
cp profile.example.json ~/.config/subiekt123/profile.json
chmod 600 ~/.config/subiekt123/profile.jsonThe profile describes the issuer, bank accounts, clients and invoice templates. Every template becomes an
MCP tool named preview_<key>_invoice, so the tool set depends on the profile rather than on the code.
The profile is validated at startup; a missing field or a reference to a non-existent client stops the
server with a specific message.
Template field | Meaning |
| becomes part of the tool name: |
| date rule: |
| tool title and description as seen by the model |
| keys from the |
|
|
| payment term in days, defaults to 14 |
| default amount; omit it to force the model to pass an amount explicitly |
| optional document fields |
| the single line item: name, |
Running
npm start # stdio - the MCP client spawns the process itself
npm run start:http # stateless HTTP on 127.0.0.1:3123/mcp
npm run inspect # MCP InspectorClaude Code / Claude Desktop (stdio)
{
"mcpServers": {
"subiekt123": {
"command": "node",
"args": ["/path/to/subiekt123/src/stdio.mjs"]
}
}
}HTTP
Bound to 127.0.0.1, with Host and Origin validation ahead of the handler
(localhostHostValidation, localhostOriginValidation) - a defence against DNS rebinding, where a
malicious site points its own domain at 127.0.0.1 so the browser treats the server as same-origin.
A foreign Origin gets 403. PORT changes the port, HOST the address.
Tools
Tool | Annotations | Description |
| read-only | Document list (0-indexed paging, |
| read-only | Full document with line items |
| read-only | Clients ( |
| read-only | Products |
| read-only | NBP rate from the business day before the issue date |
| read-only | One per profile template - dates and rate resolved automatically |
| read-only | Arbitrary payload, outside the templates |
| destructive | Issues a document - from a token only |
| destructive | Deletes a document (blocked once submitted to KSeF) |
| read-only | PDF as base64, optionally duplicate / ecoMode |
Date rules (template.kind)
The rule lives in code (dates.mjs); a profile template merely selects it.
monthlyRecurring - recurring monthly invoice
Field | Rule |
| today (overridable via the |
| last day of the billed month (the |
| + |
| NBP rate from the last business day before the issue date |
Never backdate the issue date - KSeF reports an error when issueDate precedes the day of
submission. Hence the default of today rather than the 1st of the month (user's decision, 2026-08-03).
For the same reason a foreign-currency invoice cannot be issued ahead of time - the rate from the day
before the issue date does not exist yet.
sameDay - one-off invoice
Issue date = sale date = the given date (defaults to today), due +dueDays with the weekend adjustment.
prepaid - invoice for a payment already received
Due date = issue date, and payments is filled automatically with the full amount.
Always confirm the sale date with the user - it is the day the payment arrived, which may be earlier
than the issue date. A sale date later than the issue date is rejected.
Public holidays are not shifted - weekends only (user's decision, 2026-07-31).
API pitfalls (confirmed empirically)
calculationMethodmust match the company's "Licz od" setting - otherwise the fiscalization status diverges. WithNetpassnetPrice, withGrosspassgrossPrice.exchangeRateis mandatory for foreign currencies. The API does not fetch the rate itself (the UI does) - without it you getEXCHANGE_RATE_MUST_BE_SET_ON_DOCUMENT_IN_FOREIGN_CURRENCY.items[].symbolconflicts withsourceProductId-DOCUMENT_ITEM_SYMBOL_MUST_BE_EMPTY. The symbol comes from the product record.vatRateis a string:"23%"or a non-percentage rate such as"o.o."(reverse charge).eInvoiceis a document type, not a KSeF submission. AfterPOSTthe invoice hasinvoiceMode: "Ksef"butksefNumber: null. Submission happens in the UI - the public API has no endpoint for it.A KSeF invoice cannot be printed before submission -
DOCUMENT_MUST_BE_PROCESSED_BY_KSEF_BEFORE_PRINTING. The same error is returned for a non-existentid.An invoice for a natural person requires a PESEL (
tinKind: "Pesel"+tin), otherwise it is created as a company. The UI does not require it - the discrepancy was reported to InsERT, with no response.pageNumberis 0-indexed,pageSizemaxes out at 50 (60 → 400).POST /documentsreturns a nested{"id":{"value":"..."}}, without the document number./printingrequiresContent-Type: application/jsoneven with an empty body - otherwise 415. It returns a binary PDF.Numbers freed by deleted documents are reused.
The public API does not list correction invoices (KFS) - they are visible only in the internal
gw/api.
Layout
src/
├── server.mjs McpServer factory - tool registration
├── stdio.mjs stdio entry point
├── http.mjs stateless HTTP entry point
├── auth.mjs one-time OAuth PKCE consent
└── lib/
├── config.mjs credentials.json
├── profile.mjs profile.json - reading and validation
├── api.mjs OAuth + HTTP client (JSON and binary)
├── token.mjs HMAC preview → create
├── dates.mjs date rules, weekend adjustment
├── nbp.mjs NBP exchange rates
├── invoice.mjs validation, totals, preview
└── templates.mjs assembling a payload from a profile template
profile.example.json profile template (placeholders, no real data)
GETTING-STARTED.md setup walkthrough, client wiring, troubleshooting
docs/api-notes.md full API documentation gathered empiricallyThis server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityFmaintenanceFree Polish VAT invoice generation MCP server with PDF output and preview. No API key required.Last updated481MIT
- AlicenseBqualityCmaintenanceMCP server for smallinvoice.ch — Swiss SME invoicing and accounting with 146 tools and OAuth2 BYOC authentication.Last updated10030MIT
- FlicenseBqualityAmaintenanceSingle-tenant MCP server for Polish KSeF e-invoice workflows, supporting local stdio testing, draft management, and invoice submission with safety gates.Last updated23
- Alicense-qualityDmaintenanceMCP server for the Billingo V3 Hungarian invoicing API. Manage invoices, partners, products, spendings, and bank accounts from any MCP client.Last updated14MIT
Related MCP Connectors
Hosted MCP server for Mini Accountant: invoices, expenses, customers, analytics, tax estimates.
Brazilian fiscal MCP server - issue NF-e, NFC-e, NFS-e, CT-e, MDF-e and DC-e via SEFAZ.
MCP Server for agents to onboard, pay, and provision services autonomously with InFlow
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/szlaskidaniel/subiekt123-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server