KSeF 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., "@KSeF MCPlist my last 5 sales invoices"
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.
KSeF MCP
Single-tenant MCP server for Polish KSeF e-invoice workflows.
The implementation follows docs/main_spec.md. The first usable path is local stdio against KSeF TEST. Production sends remain disabled unless explicitly opted in.
Current Status
The local implementation now includes the TEST-first stdio path, durable draft/write state, mocked KSeF gateway coverage, and remote HTTP/OAuth resource-server plumbing. Automated checks cover:
project scaffold;
settings and SQLite state;
MCP tool registration surface;
TEST-readiness gate shape;
red-green tests for the initial safety gates;
automated stdio MCP subprocess smoke coverage and executable
ksef-mcp-stdio-smoke.Dockerfile and SQLite migrations for the initial durable state.
executable
ksef-mcp-claude-config-previewcoverage for a redacted Claude Desktop config block.executable
ksef-mcp-manual-smoke-templatecoverage for redaction-safe manual evidence notes.executable
ksef-mcp-manual-smoke-evidence-checkcoverage for scanning manual notes before sharing or committing them.executable
ksef-mcp-local-preflightcoverage for strict config, stdio, and first-draft checks.executable
ksef-mcp-test-readiness-smokecoverage for the pre-invoice TEST readiness path.executable
ksef-mcp-first-draft-dry-runcoverage for the no-network first invoice preflight.guarded executable
ksef-mcp-test-submit-smokecoverage for optional live TEST submit runs.executable
ksef-mcp-remote-preflightcoverage for no-network HTTP/OAuth setup checks before a hosted smoke.readiness/completion audit documentation in
docs/READINESS_AUDIT.md.MCP
ksef://first-use-checklistresource andfirst-use-setupprompt for TEST-first personal setup inside connected clients.
Manual Claude Desktop stdio, live KSeF TEST, and live HTTP OAuth smokes are still pending; use docs/MANUAL_SMOKE_RUNBOOK.md for pass criteria.
The ksef2 TEST readiness gateway is implemented behind an injectable client factory and covered
with mocked tests. Token auth and certificate/XAdES auth share the same gateway path; TEST
certificate mode can use the SDK-generated test certificate when KSEF_CERT_PATH is not set, while
configured DEMO/PROD certificate mode currently expects a PKCS#12 .p12/.pfx file. Live KSeF
TEST smoke testing still requires real TEST credentials or an explicit test-certificate context.
The ksef-mcp-test-readiness-smoke command runs the same harmless readiness path from a terminal
and persists readiness only after successful TEST authentication. Missing required settings, such
as KSEF_NIP, are reported as JSON with next steps rather than a traceback.
KSeF invoice listing/download are gateway-backed and covered with mocked SDK tests.
ksef_list_invoices supports seller (sales), buyer (purchase), third_subject, and
authorized_subject metadata roles. ksef_get_invoice(include_xml=true) returns downloaded FA(3)
XML as an explicitly delimited UNTRUSTED_KSEF_INVOICE_XML block. FA(3) validation uses vendored
XSD files from the current ksef2 schema package and runs offline with network access disabled in
the XML parser.
ksef_download_upo is implemented for the current KSeF API shape: it requires a
session_reference plus exactly one selector (ksef_reference_number, invoice_reference_number,
or upo_reference_number). UPO XML returned by download or submit flows is also exposed through
an explicitly delimited UNTRUSTED_KSEF_UPO_XML block; raw XML fields remain for compatibility.
The invoice draft workflow is now SQLite-backed. ksef_start_invoice_draft,
ksef_update_invoice_draft, and ksef_validate_invoice_draft return deterministic missing-field
and blocking-error checklists. ksef_prepare_invoice builds and validates FA(3) XML for standard
and simplified invoices, final settlement invoices in PLN or confirmed foreign currency, plus
advance and standard correction invoices in PLN or confirmed foreign currency and PLN tax-ID
zero-value corrections.
Draft start fills missing seller/payment defaults from SELLER_PROFILE_PATH when the profile file
is present; seed fields supplied by the user take precedence.
When an MCP client advertises form elicitation, the start/update draft wrappers can ask once for a
bounded set of common primitive starter fields and apply accepted values through the same validated
draft patch path. Unsupported clients, declined/cancelled forms, invalid values, and complex nested
fields continue through the structured missing_fields response.
ksef_submit_invoice now enforces the server-side write-safety state machine: valid unexpired
confirmation token, production opt-in, durable payload-hash ledger idempotency, token consumption,
and gateway-backed online session send/UPO retrieval. This path is covered with mocked SDK tests;
live KSeF TEST invoice submission still requires real TEST credentials and a manual smoke.
Foreign-currency standard and final settlement invoices require a confirmed exchange-rate basis
before prepare. When the currency is not PLN, the draft must include rate, source, effective date,
and confirmed basis; the FA(3) builder emits KursWalutyZ and PLN VAT summary amounts.
Standard invoice drafts preserve payment state and split-payment facts. payment.split_payment=true
marks P_18A=1; payment.settlement_status="paid" with payment.payment_date emits
Zaplacono/DataZaplaty and does not require a payment method or due date; partial and
final_partial emit ZnacznikZaplatyCzesciowej plus ZaplataCzesciowa rows. Rich bank-account
entries and skonto terms are emitted as
RachunekBankowy, RachunekBankowyFaktora, and Skonto. Standard payment methods are cash,
card, voucher, check, credit, bank_transfer, mobile, plus the transfer alias for
bank_transfer; unsupported values block draft validation. When a standard payment method or
concrete due date is not the right source fact, payment.other_method=true plus
payment.description emits PlatnoscInna/OpisPlatnosci, and payment.payment_terms can emit
FA(3) TerminOpis descriptive deadlines. Confirmed online payment references can use
payment.payment_link and payment.ipksef; the link must include a valid matching IPKSeF query
parameter before prepare emits LinkDoPlatnosci and IPKSeF.
Domestic consumer/no-identifier buyers are supported by setting buyer.identifier_type="None" and
leaving buyer.identifier_value empty. The generated FA(3) XML marks BrakID=1; contradictory
no-ID drafts that also provide an identifier value are blocked before prepare.
Seller and buyer party metadata can be carried through draft, source extraction, and prepare.
Seller metadata supports seller.gln, correspondence address fields, seller.vat_prefix,
seller.eori_number, seller.email, seller.phone, and seller-only seller.taxpayer_status
for FA(3) StatusInfoPodatnika; these can also default from SELLER_PROFILE_PATH. Buyer
metadata supports separate buyer.identity_country_code for Other identifiers, primary and
correspondence address fields, buyer.gln, buyer.eori_number, buyer.customer_number,
buyer.buyer_id, buyer.email, and buyer.phone. The MCP validates buyer NIP, EU VAT, Other
ID country/length, and no-ID contradictions before prepare.
FA(3) third-party subjects are supported through third_parties. Each entry must include a name,
explicit identity choice, and role; optional primary/correspondence addresses, GLN, contacts,
customer number, EORI, buyer ID, and share fields are preserved when confirmed. The generated XML
emits a Podmiot3 block with the matching Rola, AdresKoresp, and DaneKontaktowe data.
Third-party NIP values must match the FA(3) NIP lexical shape; internal identifiers emit IDWew
and must use the NIP-00000 pattern; EU VAT IDs must match the FA(3) KodUE/NrVatUE
shape; Other IDs require a valid FA(3) country code and a max-50-character NrID; no-ID
third parties must leave identifier_value and identity_country_code empty.
Custom third-party roles use other_role=true plus role_description; they are mutually exclusive
with the predefined role enum. third_parties.*.share_percentage emits FA(3) Udzial only for
additional-buyer rows. third_parties.*.contacts is limited to the FA(3) maximum of three contact
rows.
Authorized subjects are supported through authorized_subject; the generated XML emits
PodmiotUpowazniony with role codes for enforcement authority, court bailiff, or tax
representative, optional EORI/contact data, primary address GLN, and correspondence address data.
The shorthand authorized_subject.email/phone emits one contact row; explicit
authorized_subject.contacts entries can emit up to three FA(3) DaneKontaktowe rows in total.
FA(3) attachments are supported through attachment.data_blocks. Each block must include metadata
and either one to ten short paragraphs or one or more tables. Table attachments declare column
types/names and rows; every row must match the declared columns, and blank numeric cells require an
explicit summary. The generated XML emits Zalacznik/BlokDanych/Tabela. ksef_prepare_invoice
checks the current KSeF attachment-permission status before issuing a confirmation token for any
draft that contains attachment; ksef_check_attachment_permission exposes the same read-only
gateway check directly.
Standard invoice drafts support public/relationship markers as explicit user-confirmed fields:
buyer.jst_subordinate_unit emits JST, buyer.vat_group_member emits GV, fp_invoice emits
FP, and related_party_transaction emits TP. When JST=1 or GV=1 applies to the buyer,
the draft must also include the actual Podmiot3 recipient entity with role jst_recipient or
vat_group_recipient and a NIP or internal ID, so KSeF can make the invoice available to that
unit/member.
Special invoice annotations are explicit draft flags: cash_accounting emits P_16=1,
self_billing emits P_17=1, and simplified_procedure emits P_23=1. Confirmed
new_transport_supply emits FA(3) NoweSrodkiTransportu with P_22, P_42_5, and one or more
NowySrodekTransportu items for land, vessel, or aircraft details. They remain user-confirmed
facts; the MCP does not infer that these procedures or new-means-of-transport rules apply.
Simplified invoices use invoice_type="simplified" and emit FA(3) RodzajFaktury=UPR. This is
separate from the simplified_procedure annotation flag. For simplified invoices, buyer
name/address can be omitted for NIP, EU VAT, or no-ID buyer identity branches. Standard invoices
still require buyer name/address, and buyer.identifier_type="Other" still requires
buyer.country_code and buyer.address_line_1 so FA(3) can emit the alternate ID country.
Transaction contract/order references are represented with
transaction_conditions.contracts.*.{contract_date,contract_number} and
transaction_conditions.orders.*.{order_date,order_number}. They emit FA(3)
WarunkiTransakcji/Umowy and WarunkiTransakcji/Zamowienia and are separate from advance-invoice
order rows. The same block supports confirmed lot_numbers, delivery_terms,
contract_exchange_rate plus non-PLN contract_currency, and intermediary_entity. It also
supports bounded transport facts under transaction_conditions.transports.*: a standard
transport_type or confirmed other_transport_description, a standard cargo_type or confirmed
other_cargo_description, optional transport order number, packaging unit, and start/end
timestamps. Transport timestamps are validated against the FA(3) TDataCzas range after the same
UTC normalization used by the SDK. The same transport object can carry confirmed carrier
identity/address and shipment route addresses: carrier_identity, carrier_address,
shipping_from, shipping_via.*, and shipping_to.
Common FA(3) body metadata is supported when it is explicitly confirmed: issue_place emits
P_1M, warehouse_documents.* emits repeated WZ, additional_descriptions.* emits
DodatkowyOpis, and return_of_excise=true emits ZwrotAkcyzy=1. When
billing_period_start is present, the existing required sale_date is treated as the billing
period end and the XML emits OkresFa instead of the shared supply date P_6.
Line discounts, amount bases, GTU markers, FA(3) procedure markers, and optional line detail
metadata are preserved in generated XML. InvoiceLine.discount reduces the emitted line and
summary totals. FA(3) invoice rows accept either lines.*.unit_net_price (P_9A) or
lines.*.unit_price_gross (P_9B), but not both; source-confirmed explicit net_amount,
gross_amount, and vat_amount map to P_11, explicit P_11A, and explicit P_11Vat.
Advance/order rows support explicit net_amount, gross_amount, and vat_amount as
P_11NettoZ/P_11VatZ; unit_price_gross is accepted as an input basis and converted to the
FA(3) net order-row fields because the schema has no gross-unit order-row element.
When a source system provides authoritative FA(3) summary buckets, confirmed
summary_overrides.* can emit explicit P_13_*, P_14_*, and P_15 values. The MCP requires
summary_overrides.total_gross and blocks the draft unless it equals the supplied summary net and
VAT buckets; the prepare preview uses the same explicit totals that the XML emits.
invoice_type="correction", invoice_type="advance_correction", and
invoice_type="final_correction" drafts may use summary_overrides without lines for
summary-only corrections where the source provides corrected FA(3) summary totals.
InvoiceLine.gtu_code is emitted as GTU, InvoiceLine.procedure is emitted as Procedura
or advance-order ProceduraZ, and lines.*.annex_15_marker=true emits P_12_Zal_15 or
P_12Z_Zal_15. lines.*.supply_date emits standard-row P_6A only; advance/order
rows block it because FA(3) has no order-line supply-date field. Confirmed unique_id, sku,
gtin, pkwiu, cn, pkob, and excise_amount emit the matching invoice-row tags and their
advance-order Z variants. Confirmed lines.*.currency_exchange_rate emits row-level
KursWaluty on non-PLN standard/final/correction invoice rows; PLN invoices and advance/order rows
block it. Advance/order rows also block I_42 and I_63, which are valid only for invoice rows.
Margin-procedure invoices are represented by confirmed margin_procedure plus margin-designated
lines (lines.*.tax_regime="margin"). Margin lines must not carry vat_rate or vat_treatment;
they emit FA(3) P_13_11 and the selected PMarzy branch. The MCP does not calculate the taxable
margin from purchase costs; the user/accountant must confirm the values being invoiced.
Taxi flat-rate lines use lines.*.tax_regime="taxi_flat_rate" with vat_rate=4. They emit FA(3)
summary buckets P_13_4 and P_14_4; any other rate or vat_treatment is blocked before prepare.
Special Title XII lines use lines.*.tax_regime="special_xii" with vat_rate_xii. They emit
FA(3) P_12_XII/P_12Z_XII and summary buckets P_13_5/P_14_5; ordinary vat_rate and
vat_treatment are blocked before prepare.
Line VAT treatments can be provided instead of a numeric VAT rate for non-standard cases:
zero_domestic, zero_wdt, zero_export, exempt, reverse_charge,
out_of_scope_outside_territory, and out_of_scope_article_100. The builder emits the matching
FA(3) P_12/P_12Z code and summary bucket. exempt lines require exactly one confirmed
vat_exemption.legal_basis_act, vat_exemption.legal_basis_eu_directive, or
vat_exemption.legal_basis_other and emit P_19 plus P_19A, P_19B, or P_19C;
reverse-charge lines also mark P_18=1. These classifications remain user-confirmed facts, not
automatic tax advice.
When an accounting export already carries the FA(3) row classification, lines.*.sale_category
can preserve the source-confirmed P_12/P_12Z category directly. It must match any supplied
vat_rate or vat_treatment and is not used for margin, taxi flat-rate, or special Title XII
rows.
Use ksef_advise_vat_treatment before setting cross-border VAT fields. It is read-only and returns
status="needs_facts" when buyer country/status, goods movement, place-of-supply, VIES, export, or
exemption-basis evidence is missing. For cross-border consumer sales it now pushes back for the
OSS/IOSS, distance-sale, local-registration, destination VAT-rate, or consumer service
place-of-supply facts instead of hard-refusing the case. Any status="suggested" candidate still
requires user/accountant confirmation before ksef_update_invoice_draft.
Advance invoices use invoice_type="advance" and support PLN or confirmed foreign currency. Draft
lines are emitted as the FA(3) Zamowienie block, while advance_payments are emitted as
ZaliczkaCzesciowa; the MCP blocks prepare unless the received advance-payment sum equals the draft
gross total. Foreign-currency advance payments also require currency_exchange_rate, emitted as
KursWalutyZW. When a source system provides an authoritative order/contract total, optional
advance_order_total preserves FA(3) Zamowienie/WartoscZamowienia; it must be greater than zero,
is allowed only on advance or advance-correction invoices with order rows, is blocked for rowless
summary corrections, and does not change preview totals or P_15Z.
Final settlement invoices use invoice_type="final" and support PLN or confirmed foreign currency.
Draft lines are emitted as normal FaWiersz rows, while advance_invoice_references are emitted
as FakturaZaliczkowa; optional deduction amounts/reasons on those references are emitted in
Rozliczenie/Odliczenia.
Generic FA(3) settlement adjustments are supported on standard, simplified, advance, correction,
tax-ID zero-value correction, advance-correction, final, and final-correction invoices through
settlement.charges and settlement.deductions, emitted as Rozliczenie/Obciazenia and
Rozliczenie/Odliczenia with computed totals and DoZaplaty or DoRozliczenia. Optional explicit
settlement.amount_due or settlement.amount_to_settle is accepted only when it matches the
computed balance.
FA(3) footer data is supported through footer.additional_informations and footer.registries.
Footer text emits Stopka/Informacje/StopkaFaktury; registry rows emit Stopka/Rejestry fields
for PelnaNazwa, KRS, REGON, and BDO. The MCP validates KRS, REGON, BDO length, and blocks
empty registry rows before prepare.
Correction invoices use invoice_type="correction", invoice_type="advance_correction",
invoice_type="final_correction", or invoice_type="tax_id_zero_correction". Standard, advance,
final, and tax-ID zero-value corrections support PLN or confirmed foreign currency. Tax-ID
zero-value corrections require original positive before_correction rows plus zero-value after
rows.
Historical party data can be emitted with corrected_seller as Podmiot1K and corrected_buyers
as Podmiot2K only when the buyer identifier is unchanged; corrected buyer data requires matching
buyer.buyer_id and corrected_buyers.*.buyer_id linkage. Corrected-party address gln values
are emitted inside those historical address blocks. tax_id_zero_correction uses corrected-party
data to confirm the original wrong tax ID but does not emit Podmiot1K/Podmiot2K.
Correction metadata can also include corrected_invoice_period for OkresFaKorygowanej and
corrected_invoice_number_override for NrFaKorygowany. Advance and final-settlement corrections
support advance_amount_before_correction as P_15ZK; non-PLN advance/final corrections with
that amount also require advance_currency_exchange_rate_before_correction, emitted as
KursWalutyZK.
Representative live KSeF smoke execution with real credentials remains a separate manual slice.
ksef_lookup_exchange_rate is implemented against the official NBP Web API. It returns the rate,
table number, effective date, source URL, and lookup mode. For non-publication dates it falls back
to the latest NBP table on or before the requested date within a bounded lookback window. The result
is advisory and still requires explicit user confirmation before it can be used as a draft
exchange-rate basis.
ksef_lookup_counterparty is implemented for Polish domestic NIP and REGON lookups against the
official MF VAT whitelist API. It returns candidate legal/VAT data, request provenance, and account
number metadata as advisory data only; the MCP does not silently copy names or addresses into a
draft.
The same tool now supports EU VAT/VIES validation for identifier_type=VatUe through the official
European Commission VIES REST endpoint. It accepts either a prefixed value such as IE6388047V or
a split country_code plus VAT number, returns a separate eu_vat_verification block, and marks
any source-provided name/address as advisory. VIES is a current-state validation source; as_of_date
is not a historical VIES query.
identifier_type=KRS is also supported through the official open KRS API from the Portal Rejestrów
Sądowych. It returns current KRS register details such as legal name, KRS, NIP, REGON, legal form,
status, registration date, and registered address as advisory candidate data.
GUS REGON/BIR enrichment is available through explicit identifier_type=GUS_REGON,
GUS_NIP, or GUS_KRS lookups when GUS_REGON_API_KEY is configured. The tool logs in to the
official BIR SOAP service, sends the session id only as the required sid header, logs out
best-effort, caches parsed search results in SQLite for 24 hours by default, and returns GUS name,
NIP, REGON/KRS, legal-form hint, and address as advisory candidate data.
When bank_account is provided, ksef_lookup_counterparty also calls the MF whitelist account
check endpoint and returns a separate bank_account_verification block with TAK/NIE, request
ID, and source URL. Bank-account verification remains Polish/MF-only.
MF VAT whitelist 200 responses are cached in SQLite for 24 hours by default
(MF_VAT_CACHE_TTL_SECONDS=86400) using separate cache entries for the subject lookup and optional
bank-account check.
Source-document support is implemented with SQLite FTS plus optional local vector retrieval.
ksef_add_source_document stores untrusted source text and, when KNOWLEDGE_MODE=vector|hybrid
and LOCAL_LLM_BASE_URL points at an OpenAI-compatible local embedding endpoint, stores a durable
source-document embedding. ksef_search_source_documents supports search_mode=fts|vector|hybrid;
all results are advisory snippets. ksef_extract_invoice_source can call a configured local
OpenAI-compatible chat model (LOCAL_LLM_BASE_URL + LOCAL_LLM_MODEL) to propose source-backed
invoice fields, but it is read-only and does not mutate drafts. ksef_attach_field_provenance
links a suggested draft field to a source document only for supported invoice field paths while
marking that field unconfirmed until the user explicitly confirms it. Draft confirmations only
apply to existing supported advisory fields, so arbitrary keys cannot create or clear confirmation
state. ksef_start_invoice_draft(source_document_ids=[...]) can store existing source documents as
draft context; missing ids are returned as warnings and no field values are extracted or confirmed
automatically. See docs/LOCAL_KNOWLEDGE.md for the current laptop
profile guidance: 16 GB starts with FTS, while 32 GB can add hybrid retrieval and a small local
extractor/advisor.
ksef_get_capabilities and the ksef://capabilities resource expose the deterministic supported,
advisory, unsupported, and manual-smoke workflow surface. Clients should use it before rare FA(3),
attachment, correction, cross-border, or non-standard tax paths so the MCP can refuse unsupported
cases instead of generating partial XML. The capability surface also lists current MCP resources,
including ksef://first-use-checklist, and the terminal preflight commands used before manual
external gates.
MCP resources and prompts are registered for client guidance: FA(3) schema, glossary, invoice field checklist, capabilities, sanitized seller profile, knowledge-source catalog, first-use checklist, and guided prompts for first-use setup, issuing an invoice, monthly review, VAT treatment explanation, and source extraction.
Remote Streamable HTTP transport is available behind explicit OAuth resource-server settings.
MCP_TRANSPORT=http binds the configured MCP_HTTP_HOST/MCP_HTTP_PORT and refuses startup unless
MCP_PUBLIC_URL, OAUTH_ISSUER, OAUTH_AUDIENCE, and OAUTH_JWKS_URL are set. HTTP bearer tokens
are validated against the configured JWKS with issuer/audience checks and must include the configured
scope, OAUTH_REQUIRED_SCOPES=ksef.mcp by default. Public remote URLs must be HTTPS. Stdio remains
the default personal/local path. Run ksef-mcp-remote-preflight before a hosted smoke to check
HTTP/OAuth settings without starting the server, using network, writing files, or touching KSeF;
live remote deployment smoke and provider-specific onboarding notes are covered in
docs/REMOTE_DEPLOYMENT.md, while live HTTP OAuth smoke remains a
manual external gate.
See docs/IMPLEMENTATION_PLAN.md, TODO.md, docs/READINESS_AUDIT.md, and docs/MANUAL_SMOKE_RUNBOOK.md.
Local Development
UV_CACHE_DIR=/tmp/uv-cache uv sync --extra dev
UV_CACHE_DIR=/tmp/uv-cache uv run pytestRun the stdio MCP server:
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcpCreate your local seller defaults before the first real draft if you want the MCP to fill seller and payment fields automatically:
cp seller_profile.example.yaml seller_profile.yamlThen edit seller_profile.yaml; it is ignored by git because it contains personal/company data.
Check local configuration before starting the MCP. This validates required env, placeholder NIPs,
NIP checksums, auth material, real-NIP TEST acknowledgment, seller-profile placeholders, and
seller_profile.yaml seller NIP consistency with KSEF_NIP without network access:
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcp-config-checkTo run the local first-use preflight in one command, use:
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcp-local-preflight \
--seed docs/examples/first_standard_invoice_seed.example.jsonThis command performs strict config check, stdio MCP handshake, and first-draft dry-run. It does
not use the KSeF network and does not submit invoices; its JSON output reports
network_used=false, ksef_touched=false, live_submit_attempted=false, and
configured_ledger_may_be_touched_by_stdio=true because the stdio server may initialize the
configured SQLite ledger.
Before editing a desktop client's MCP config, you can run the same stdio handshake path from a
terminal. It starts the server as a subprocess, initializes an MCP client session, lists
tools/resources/prompts, calls ksef_session_status, and prints JSON:
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcp-stdio-smokeFor Claude Desktop, use the stdio setup guide in docs/CLAUDE_DESKTOP.md. Generate the redacted config block with:
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcp-claude-config-previewThe preview does not write files, call KSeF, or include KSeF tokens/NIPs in the config JSON; it
reports secrets_included=false, writes_files=false, and network_used=false.
Before running manual/external gates, generate a local evidence template. The command prints to
stdout and does not write files, load settings, or call KSeF; redirect it to data/ if you want a
private ignored notes file:
mkdir -p data
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcp-manual-smoke-template --format markdown \
> data/manual_smoke_evidence.mdBefore sharing or committing manual notes, scan them for high-risk unredacted patterns:
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcp-manual-smoke-evidence-check \
--path data/manual_smoke_evidence.mdBefore preparing your first invoice for a configured TEST NIP, you can run the same harmless readiness path outside the chat client:
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcp-test-readiness-smokeBefore creating a real draft in your MCP client, validate the first-draft shape locally. This uses
seller_profile.yaml, validates the seed, writes only a temporary SQLite file, and prints
real_ledger_touched=false, network_used=false, ksef_touched=false,
generated_xml=false, and confirmation_token_created=false:
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcp-first-draft-dry-run \
--seed docs/examples/first_standard_invoice_seed.example.jsonThe dry-run can pass without KSEF_TOKEN; the TEST readiness smoke still needs the configured KSeF
auth material before any prepare/submit flow.
For an optional end-to-end TEST send outside the chat client, use the guarded live submit smoke.
This command requires persisted TEST readiness, uses the configured SQLite ledger, creates a draft
and confirmation token, and submits the seed to KSeF TEST only when
--confirm-submit-to-ksef-test is present:
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcp-test-submit-smoke \
--seed docs/examples/first_standard_invoice_seed.example.json \
--confirm-submit-to-ksef-testIf KSEF_TEST_NIP equals KSEF_NIP, also pass --use-real-nip-ack or keep
KSEF_ALLOW_REAL_NIP_IN_TEST=true. The JSON output reports readiness_ok, draft_created,
confirmation_token_created, confirmation_token_consumed, submitted, gateway_called, and
idempotent_replay.
After the dry-run and readiness pass, a minimal standard-invoice seed is available at
docs/examples/first_standard_invoice_seed.example.json.
Use it as the seed argument to ksef_start_invoice_draft; it assumes seller_profile.yaml
already supplies seller and payment defaults.
Inside an MCP client, read ksef://first-use-checklist or run the first-use-setup prompt for the
same TEST-first sequence, source-data pushback rules, and prepare/submit gating reminders.
First call:
{
"seed": {
"...": "contents of docs/examples/first_standard_invoice_seed.example.json"
}
}If the response has missing_fields, each value is a field path to provide before prepare. Patch
the returned draft and validate again:
{
"draft_id": "returned-draft-id",
"patch": {
"buyer": {
"name": "Corrected buyer name"
}
}
}Then call ksef_validate_invoice_draft with {"draft_id": "returned-draft-id"}. Only call
ksef_prepare_invoice when ready_for_prepare=true, missing_fields=[], and
blocking_errors=[].
If KSEF_TEST_NIP intentionally equals your real KSEF_NIP, prefer a synthetic TEST identifier
where possible. Otherwise rerun with --use-real-nip-ack or set
KSEF_ALLOW_REAL_NIP_IN_TEST=true after accepting that official TEST data is not isolated.
Use certificate/XAdES mode by setting KSEF_AUTH_MODE=certificate. In TEST, omitting
KSEF_CERT_PATH uses the SDK-generated test certificate for the configured KSEF_TEST_NIP.
For DEMO/PROD, set KSEF_CERT_PATH to a PKCS#12 .p12/.pfx file and
KSEF_CERT_PASSWORD when the archive is encrypted.
Before a remote hosted smoke, validate local HTTP/OAuth settings without starting the server, fetching JWKS, calling OAuth, writing files, or touching KSeF:
MCP_TRANSPORT=http \
MCP_PUBLIC_URL=https://your-mcp.example.com \
OAUTH_ISSUER=https://issuer.example.com/ \
OAUTH_AUDIENCE=https://your-mcp.example.com \
OAUTH_JWKS_URL=https://issuer.example.com/.well-known/jwks.json \
OAUTH_REQUIRED_SCOPES=ksef.mcp \
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcp-remote-preflightThe expected success output includes server_started=false, network_used=false,
oauth_network_used=false, ksef_touched=false, writes_files=false, and
secrets_included=false.
Run the Streamable HTTP server with external OAuth/JWKS verification:
MCP_TRANSPORT=http \
MCP_PUBLIC_URL=https://your-mcp.example.com \
OAUTH_ISSUER=https://issuer.example.com/ \
OAUTH_AUDIENCE=https://your-mcp.example.com \
OAUTH_JWKS_URL=https://issuer.example.com/.well-known/jwks.json \
OAUTH_REQUIRED_SCOPES=ksef.mcp \
UV_CACHE_DIR=/tmp/uv-cache uv run ksef-mcpRun the containerized Streamable HTTP service:
cp .env.example .env
# Fill KSEF_* and OAuth values in .env first.
docker compose up --build ksef-mcpThe compose service mounts ./data for the SQLite ledger/drafts and
./seller_profile.yaml read-only for local seller defaults. Create it from
seller_profile.example.yaml before starting compose if you want profile defaults:
cp seller_profile.example.yaml seller_profile.yamlFor ChatGPT Apps, Claude.ai, Cloudflare, Auth0, Clerk, Stytch, WorkOS, OAuth client-registration choices, and live smoke expectations, see docs/REMOTE_DEPLOYMENT.md.
Seller profile defaults can be JSON or a conservative key: value YAML subset. Draft start fills
only missing fields:
seller:
name: Example Sp. z o.o.
nip: REPLACE_WITH_YOUR_NIP
country_code: PL
address_line_1: ul. Przykladowa 1
address_line_2: 00-001 Warszawa
payment:
method: transfer
bank_account: 10101010101010101010101010
due_days: 14Safety Defaults
KSEF_ENVdefaults totest.KSEF_AUTH_MODEdefaults totoken; certificate mode is explicit.KSEF_REQUIRE_TEST_READYdefaults totrue.ksef_prepare_invoicemust refuse untilksef_test_connection_checkpasses.Source/RAG/LLM suggestions stay unconfirmed unless confirmed through the explicit
confirmationsargument; draft patches cannot directly set advisory confirmation state.Direct provenance attachment and confirmation keys are restricted to supported invoice field paths; unsupported paths cannot mutate draft advisory state.
KSEF_ENV=proddoes not allow production sends unlessKSEF_ALLOW_PROD=true.MCP_TRANSPORT=httprefuses startup unless OAuth/JWKS resource-server settings are complete.KSeF TEST should use synthetic/test identifiers where possible.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
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/olegtyshcneko/ksef-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server