Taxmeter

Išgalvotas 2026-09 mėnuo / Fictional 2026-09 worked month

Vykdomas pavyzdys nuo tuščios darbo erdvės iki savininko peržiūros prašymo. / Executable example from an empty workspace to an owner review request.

Tik išgalvotai darbo erdvei / Fictional workspace only

Visi pavadinimai, skaičiai ir dokumentai šiame pavyzdyje išgalvoti. Sukurkite naują tuščią bandomąją darbo erdvę. Niekada neperrašykite tikro mokesčių mokėtojo profilio. Leiskite read, prepare ir configure visiems mėnesiams, nes save_profile keičia visos darbo erdvės profilį. approve nereikia.

Every name, number and document in this example is fictional. Create a fresh empty demo workspace. Never overwrite a real taxpayer profile. Grant read, prepare and configure for all months because save_profile configures the entire workspace. approve is unnecessary.

Pavyzdžio dydžiai / Example amounts

Viena 2026-09-03 vietinė EUR pirkimo sąskaita: 100,00 EUR be PVM, 21,00 EUR PVM, iš viso 121,00 EUR. API dydžiai sveikais centais: 10000, 2100, 12100; tarifai baziniais punktais: 2100 reiškia 21 %. Tai nėra rekomendacija tikram sandoriui.

One fictional domestic EUR purchase invoice dated 2026-09-03: net EUR 100.00, VAT EUR 21.00, total EUR 121.00. API amounts use integer cents: 10000, 2100, 12100; rates use basis points: 2100 means 21%. This is not advice for an actual transaction.

Kaip vykdyti / How to run

Toliau pateiktą scenarijų naudokite kaip tikslią MCP įrankių seką. call(name,args) turi grąžinti MCP structuredContent arba iš text iškoduotą JSON, o klaidos atveju sustoti. upload(url,headers,bytes) siunčia PUT ir grąžina JSON. Modeliui parodykite tik būtinus dokumentus, ne žetonus.

Follow the exact MCP sequence in the source below. Supply call(name,args) returning MCP structuredContent or parsed text JSON and stopping on errors. Supply upload(url,headers,bytes) that PUTs the bytes and returns JSON. Expose only the necessary documents to the model, never tokens.

Sąžininga pabaiga / Honest stopping point

review_period pateikia blockers ir digest. Šis pavyzdys palieka originalo patikros blokatorių ir siunčia request_owner_approval; get_request iš pradžių grąžina pending. Užklausa yra susieta su expectedDigest ir nesuteikia patvirtinimo. Savininkas turi peržiūrėti originalą, išspręsti blokatorius ir patvirtinti pilnumą įprastame lange.

review_period returns blockers and digest. This example leaves the original review blocker and calls request_owner_approval; get_request initially returns pending. The request binds expectedDigest and does not grant approval. The owner must view the original, resolve blockers and confirm completeness in the normal workspace UI.

Po savininko patvirtinimo / After owner approval

Dar kartą tikrinkite get_request. Tik completed rezultatas su tiksliu paketu įrodo patvirtinimą. Net faktų patikra keičia digest: savininkui peržiūrėjus originalą ir patikrinus įrašą, ankstesnis prašymas tampa stale. Iš naujo kvieskite review_period ir request_owner_approval prieš savininko patvirtinimą. Agentui tiesiogiai tvirtinti reikia aiškių review ir approve teisių, visų originalų view_source_page ir approve_period su naujausiais expectedRevision bei expectedDigest. Patvirtinimas žymimas kaip agento, ne žmogaus.

Poll get_request again. Only a completed result referring to the exact package establishes approval. Even checking source facts changes the digest: after the owner views the original and checks the record, the earlier request becomes stale. Rerun review_period and request_owner_approval before the owner approves. Direct agent approval requires explicit review and approve scopes, view_source_page for every original, and approve_period with current expectedRevision and expectedDigest. It is recorded as agent approval, never human approval.

Paketai / Packages

Tik gavus export teisę ir galiojantį patvirtinimą, get_test_package({periodId:"2026-09"}) grąžina TEST-NOT-FOR-SUBMISSION paketą. Nepateikite jo VMI ar EDS. FR0600 yra tik darbo lapas.

With export scope and a current approval, get_test_package({periodId:"2026-09"}) returns a TEST-NOT-FOR-SUBMISSION package. Never submit it to VMI or EDS. FR0600 remains a worksheet.

import { createHash } from 'node:crypto';

// These names, numbers and document bytes are deliberately fictional. Never replace them with a
// customer's data. The public page prints this exact source and the hosted MCP test executes it.
export const PERIOD='2026-09';
export const DEMO_PROFILE={name:'Fictional Demo Buyer',registrationId:'123456789',vatId:'LT123456789',fxPolicy:'transaction_day',annualDeductionPercent:100,monthlyVatPeriod:true,noProRata:true,noMarginScheme:true,noOss:true,noCustomsAdjustments:true};
export const DEMO_RECORD={kind:'invoice',direction:'purchase',invoiceNumber:'FICTIONAL-DOCS-1',date:'2026-09-03',taxPointDate:'2026-09-03',registrationDate:'2026-09-03',periodBasis:'Fictional invoice received during September 2026.',supplier:{name:'Fictional Demo Supplier',country:'LT',vatId:'LT987654321',registrationId:'987654321'},customer:{name:DEMO_PROFILE.name,country:'LT',vatId:DEMO_PROFILE.vatId,registrationId:DEMO_PROFILE.registrationId},currency:'EUR',totalMinor:12100,lines:[{netMinor:10000,vatMinor:2100,statedRateBps:2100,treatment:'lt_purchase_2100',deductionBps:10000,deductionReason:'Fictional purchase used entirely for taxable business.'}],originalInvoice:null,evidence:'Net 100.00 VAT 21.00 Total 121.00',notes:'Fictional documentation example only; no actual business or taxpayer.'};
export const DEMO_TEXT='Fictional Demo Supplier LT987654321 987654321 Fictional Demo Buyer LT123456789 123456789 Invoice FICTIONAL-DOCS-1 2026-09-03 EUR Net 100.00 VAT 21.00 Total 121.00';
export function fictionalDocument(){
  const stream=`BT /F1 10 Tf 20 100 Td (${DEMO_TEXT}) Tj ET`;
  const objects=['<< /Type /Catalog /Pages 2 0 R >>','<< /Type /Pages /Kids [3 0 R] /Count 1 >>','<< /Type /Page /Parent 2 0 R /MediaBox [0 0 2000 200] /Resources << /Font << /F1 4 0 R >> >> /Contents 5 0 R >>','<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>',`<< /Length ${Buffer.byteLength(stream)} >>\nstream\n${stream}\nendstream`];
  let text='%PDF-1.4\n';const offsets=[];
  for(const [index,object] of objects.entries()){offsets.push(Buffer.byteLength(text));text+=`${index+1} 0 obj\n${object}\nendobj\n`;}
  const start=Buffer.byteLength(text);
  return Buffer.from(text+`xref\n0 6\n0000000000 65535 f \n${offsets.map(n=>`${String(n).padStart(10,'0')} 00000 n \n`).join('')}trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${start}\n%%EOF\n`);
}
export const MONTH_STEPS=['agent_access','pipeline_state','save_profile','create_period','set_period_status','create_upload','pipeline_state','read_source','ocr_page','read_source','split_source','propose_record','review_period','request_owner_approval','get_request'];

// call(name,args) returns the tool's JSON result, unwrapping MCP structuredContent or text JSON.
// upload(url,headers,bytes) PUTs the exact bytes and returns the HTTP response JSON.
// Start with an EMPTY fictional workspace. Do not overwrite a real taxpayer profile.
export async function runWorkedMonth({call,upload,bytes=fictionalDocument()}){
  const access=await call('agent_access',{});
  for(const scope of ['read','prepare','configure'])if(!access.agent.scopes.includes(scope))throw new Error('DEMO_SCOPE_REQUIRED: '+scope);
  let state=await call('pipeline_state',{});
  if(state.periods.length||state.documents.length)throw new Error('DEMO_REQUIRES_EMPTY_WORKSPACE');
  let revision=state.revision;
  const write=async(name,args)=>{const result=await call(name,{...args,expectedRevision:revision});revision=result.revision;return result;};
  await write('save_profile',{profile:DEMO_PROFILE}); // requires the owner's all-month grant
  await write('create_period',{periodId:PERIOD});
  await write('set_period_status',{periodId:PERIOD,status:'open',reference:'Fictional new month, no external filing.'});
  const sha256=createHash('sha256').update(bytes).digest('hex');
  const ticket=await call('create_upload',{periodId:PERIOD,name:'fictional-docs.pdf',sha256,bytes:bytes.length,expectedRevision:revision});
  const imported=await upload(ticket.uploadUrl,ticket.headers,bytes);
  // The PUT changes the workspace revision; create_upload itself does not import a document.
  state=await call('pipeline_state',{});revision=state.revision;
  const documentId=imported.id;
  let source=await call('read_source',{documentId});
  await write('ocr_page',{documentId,page:0}); // exercise OCR; compare the result with the original
  source=await call('read_source',{documentId}); // OCR creates a new extractionId
  const split=await write('split_source',{documentId,extractionId:source.extraction.id,segments:[{start:0,end:source.extraction.text.length}]});
  const proposed=await write('propose_record',{segmentId:split.segmentIds[0],periodId:PERIOD,record:DEMO_RECORD});
  const review=await call('review_period',{periodId:PERIOD});
  // The owner must resolve blockers and check every original before approving. A request is not approval.
  const request=await call('request_owner_approval',{periodId:PERIOD,reason:'Prašome peržiūrėti išgalvoto mėnesio originalą ir blokatorius. / Please review the fictional month original and blockers.'});
  const polled=await call('get_request',{requestId:request.id});
  // request.expectedDigest binds this request to review.digest; later changes require a fresh request.
  return {documentId,recordId:proposed.recordId,review,request,polled};
}