finizi-app 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- finizi_app-0.1.0/.dockerignore +14 -0
- finizi_app-0.1.0/.gitignore +111 -0
- finizi_app-0.1.0/CHANGELOG.md +26 -0
- finizi_app-0.1.0/LICENSE +9 -0
- finizi_app-0.1.0/PKG-INFO +254 -0
- finizi_app-0.1.0/README.md +207 -0
- finizi_app-0.1.0/docs/api-key-auth.md +119 -0
- finizi_app-0.1.0/docs/architecture.md +110 -0
- finizi_app-0.1.0/docs/cli.md +286 -0
- finizi_app-0.1.0/docs/contributing.md +110 -0
- finizi_app-0.1.0/docs/glossary.md +156 -0
- finizi_app-0.1.0/docs/install.md +310 -0
- finizi_app-0.1.0/docs/mcp.md +134 -0
- finizi_app-0.1.0/docs/security.md +106 -0
- finizi_app-0.1.0/finizi_app/__init__.py +3 -0
- finizi_app-0.1.0/finizi_app/cli/__init__.py +12 -0
- finizi_app-0.1.0/finizi_app/cli/__main__.py +11 -0
- finizi_app-0.1.0/finizi_app/cli/commands/__init__.py +37 -0
- finizi_app-0.1.0/finizi_app/cli/commands/_cashbook_impl.py +180 -0
- finizi_app-0.1.0/finizi_app/cli/commands/api_keys.py +44 -0
- finizi_app-0.1.0/finizi_app/cli/commands/auth.py +200 -0
- finizi_app-0.1.0/finizi_app/cli/commands/banks.py +36 -0
- finizi_app-0.1.0/finizi_app/cli/commands/bhxh.py +31 -0
- finizi_app-0.1.0/finizi_app/cli/commands/cashbooks.py +38 -0
- finizi_app-0.1.0/finizi_app/cli/commands/celery.py +31 -0
- finizi_app-0.1.0/finizi_app/cli/commands/coa.py +90 -0
- finizi_app-0.1.0/finizi_app/cli/commands/company.py +26 -0
- finizi_app-0.1.0/finizi_app/cli/commands/doctor.py +25 -0
- finizi_app-0.1.0/finizi_app/cli/commands/documents.py +42 -0
- finizi_app-0.1.0/finizi_app/cli/commands/einvoice.py +45 -0
- finizi_app-0.1.0/finizi_app/cli/commands/entities.py +30 -0
- finizi_app-0.1.0/finizi_app/cli/commands/inventory.py +26 -0
- finizi_app-0.1.0/finizi_app/cli/commands/invoices.py +122 -0
- finizi_app-0.1.0/finizi_app/cli/commands/journal.py +49 -0
- finizi_app-0.1.0/finizi_app/cli/commands/ledger.py +31 -0
- finizi_app-0.1.0/finizi_app/cli/commands/memory.py +28 -0
- finizi_app-0.1.0/finizi_app/cli/commands/payments.py +494 -0
- finizi_app-0.1.0/finizi_app/cli/commands/payroll.py +50 -0
- finizi_app-0.1.0/finizi_app/cli/commands/products.py +56 -0
- finizi_app-0.1.0/finizi_app/cli/commands/purchase_orders.py +652 -0
- finizi_app-0.1.0/finizi_app/cli/commands/reports.py +30 -0
- finizi_app-0.1.0/finizi_app/cli/commands/sale_orders.py +249 -0
- finizi_app-0.1.0/finizi_app/cli/commands/tax.py +31 -0
- finizi_app-0.1.0/finizi_app/cli/commands/vendors.py +65 -0
- finizi_app-0.1.0/finizi_app/cli/main.py +234 -0
- finizi_app-0.1.0/finizi_app/core/__init__.py +19 -0
- finizi_app-0.1.0/finizi_app/core/apikeystore.py +40 -0
- finizi_app-0.1.0/finizi_app/core/clients.py +414 -0
- finizi_app-0.1.0/finizi_app/core/credentials.py +347 -0
- finizi_app-0.1.0/finizi_app/core/errors.py +108 -0
- finizi_app-0.1.0/finizi_app/core/filters.py +37 -0
- finizi_app-0.1.0/finizi_app/core/models.py +50 -0
- finizi_app-0.1.0/finizi_app/core/workflows/__init__.py +92 -0
- finizi_app-0.1.0/finizi_app/core/workflows/ai_classify_journal.py +59 -0
- finizi_app-0.1.0/finizi_app/core/workflows/auth_login.py +179 -0
- finizi_app-0.1.0/finizi_app/core/workflows/auth_logout.py +50 -0
- finizi_app-0.1.0/finizi_app/core/workflows/bank_transactions.py +146 -0
- finizi_app-0.1.0/finizi_app/core/workflows/bulk_dispatch.py +47 -0
- finizi_app-0.1.0/finizi_app/core/workflows/calculate_payroll.py +54 -0
- finizi_app-0.1.0/finizi_app/core/workflows/cancel_einvoice.py +33 -0
- finizi_app-0.1.0/finizi_app/core/workflows/cash_bank_payments.py +594 -0
- finizi_app-0.1.0/finizi_app/core/workflows/check_tax_status.py +76 -0
- finizi_app-0.1.0/finizi_app/core/workflows/create_product.py +76 -0
- finizi_app-0.1.0/finizi_app/core/workflows/dispatch_job.py +62 -0
- finizi_app-0.1.0/finizi_app/core/workflows/generate_tax_report.py +46 -0
- finizi_app-0.1.0/finizi_app/core/workflows/get_coa.py +236 -0
- finizi_app-0.1.0/finizi_app/core/workflows/get_company.py +73 -0
- finizi_app-0.1.0/finizi_app/core/workflows/get_inventory_receipt.py +54 -0
- finizi_app-0.1.0/finizi_app/core/workflows/get_invoice.py +39 -0
- finizi_app-0.1.0/finizi_app/core/workflows/get_ledger_entries.py +112 -0
- finizi_app-0.1.0/finizi_app/core/workflows/get_vendor.py +52 -0
- finizi_app-0.1.0/finizi_app/core/workflows/health_check.py +55 -0
- finizi_app-0.1.0/finizi_app/core/workflows/import_invoice_pdf.py +50 -0
- finizi_app-0.1.0/finizi_app/core/workflows/import_invoice_xml.py +48 -0
- finizi_app-0.1.0/finizi_app/core/workflows/issue_einvoice.py +56 -0
- finizi_app-0.1.0/finizi_app/core/workflows/list_documents.py +92 -0
- finizi_app-0.1.0/finizi_app/core/workflows/list_entities.py +30 -0
- finizi_app-0.1.0/finizi_app/core/workflows/list_invoices.py +75 -0
- finizi_app-0.1.0/finizi_app/core/workflows/list_payrolls.py +92 -0
- finizi_app-0.1.0/finizi_app/core/workflows/manage_api_keys.py +55 -0
- finizi_app-0.1.0/finizi_app/core/workflows/manage_vendor.py +97 -0
- finizi_app-0.1.0/finizi_app/core/workflows/match_products.py +75 -0
- finizi_app-0.1.0/finizi_app/core/workflows/parse_bank_statement.py +50 -0
- finizi_app-0.1.0/finizi_app/core/workflows/pay_invoice.py +57 -0
- finizi_app-0.1.0/finizi_app/core/workflows/purchase_orders.py +497 -0
- finizi_app-0.1.0/finizi_app/core/workflows/reverse_journal.py +96 -0
- finizi_app-0.1.0/finizi_app/core/workflows/sale_orders.py +213 -0
- finizi_app-0.1.0/finizi_app/core/workflows/search_memory.py +55 -0
- finizi_app-0.1.0/finizi_app/core/workflows/search_vendor.py +41 -0
- finizi_app-0.1.0/finizi_app/core/workflows/switch_entity.py +38 -0
- finizi_app-0.1.0/finizi_app/core/workflows/sync_bhxh.py +88 -0
- finizi_app-0.1.0/finizi_app/core/workflows/workflow_errors.py +20 -0
- finizi_app-0.1.0/finizi_app/mcp/__init__.py +13 -0
- finizi_app-0.1.0/finizi_app/mcp/__main__.py +6 -0
- finizi_app-0.1.0/finizi_app/mcp/server.py +276 -0
- finizi_app-0.1.0/finizi_app/mcp/transports/__init__.py +1 -0
- finizi_app-0.1.0/finizi_app/mcp/transports/http.py +85 -0
- finizi_app-0.1.0/pyproject.toml +109 -0
- finizi_app-0.1.0/tests/__init__.py +0 -0
- finizi_app-0.1.0/tests/conftest.py +61 -0
- finizi_app-0.1.0/tests/e2e/__init__.py +0 -0
- finizi_app-0.1.0/tests/integration/__init__.py +0 -0
- finizi_app-0.1.0/tests/integration/test_cli_smoke.py +1078 -0
- finizi_app-0.1.0/tests/integration/test_mcp_server.py +147 -0
- finizi_app-0.1.0/tests/unit/__init__.py +0 -0
- finizi_app-0.1.0/tests/unit/test_apikeystore.py +48 -0
- finizi_app-0.1.0/tests/unit/test_auth_status.py +89 -0
- finizi_app-0.1.0/tests/unit/test_clients.py +115 -0
- finizi_app-0.1.0/tests/unit/test_credentials.py +246 -0
- finizi_app-0.1.0/tests/unit/test_mcp_server.py +81 -0
- finizi_app-0.1.0/tests/unit/test_workflows.py +2615 -0
- finizi_app-0.1.0/uv.lock +1517 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
2
|
+
|
|
3
|
+
# dependencies
|
|
4
|
+
/node_modules
|
|
5
|
+
/.pnp
|
|
6
|
+
.pnp.*
|
|
7
|
+
.yarn/*
|
|
8
|
+
!.yarn/patches
|
|
9
|
+
!.yarn/plugins
|
|
10
|
+
!.yarn/releases
|
|
11
|
+
!.yarn/versions
|
|
12
|
+
|
|
13
|
+
# testing
|
|
14
|
+
/coverage
|
|
15
|
+
|
|
16
|
+
# next.js
|
|
17
|
+
/.next/
|
|
18
|
+
/out/
|
|
19
|
+
dist/
|
|
20
|
+
bin/
|
|
21
|
+
|
|
22
|
+
# production
|
|
23
|
+
/build
|
|
24
|
+
|
|
25
|
+
# misc
|
|
26
|
+
.DS_Store
|
|
27
|
+
*.pem
|
|
28
|
+
|
|
29
|
+
# debug
|
|
30
|
+
npm-debug.log*
|
|
31
|
+
yarn-debug.log*
|
|
32
|
+
yarn-error.log*
|
|
33
|
+
.pnpm-debug.log*
|
|
34
|
+
|
|
35
|
+
# package manager
|
|
36
|
+
package-lock.json
|
|
37
|
+
yarn.lock
|
|
38
|
+
pnpm-lock.yaml
|
|
39
|
+
|
|
40
|
+
# semantic-release
|
|
41
|
+
.nyc_output
|
|
42
|
+
|
|
43
|
+
# env files (can opt-in for committing if needed)
|
|
44
|
+
.env*
|
|
45
|
+
!.env.example
|
|
46
|
+
|
|
47
|
+
# vercel
|
|
48
|
+
.vercel
|
|
49
|
+
|
|
50
|
+
# typescript
|
|
51
|
+
*.tsbuildinfo
|
|
52
|
+
next-env.d.ts
|
|
53
|
+
|
|
54
|
+
# flutter
|
|
55
|
+
.dart_tool
|
|
56
|
+
build
|
|
57
|
+
GoogleService-Info.plist
|
|
58
|
+
|
|
59
|
+
repomix-output.xml
|
|
60
|
+
.serena/cache
|
|
61
|
+
plans/**/*
|
|
62
|
+
!plans/templates/*
|
|
63
|
+
screenshots/*
|
|
64
|
+
docs/screenshots/*
|
|
65
|
+
logs.txt
|
|
66
|
+
test-ck
|
|
67
|
+
__pycache__
|
|
68
|
+
|
|
69
|
+
# CK meta commands
|
|
70
|
+
prompt.md
|
|
71
|
+
ck.md
|
|
72
|
+
|
|
73
|
+
# Generated runtime layout for release/install smoke tests
|
|
74
|
+
/.claude/
|
|
75
|
+
# But track repo-level rules that Claude Code reads
|
|
76
|
+
!/.claude/rules/
|
|
77
|
+
|
|
78
|
+
# Local-only state inside tracked claude source
|
|
79
|
+
claude/agent-memory/
|
|
80
|
+
claude/hooks/.logs/
|
|
81
|
+
claude/session-state/latest.md
|
|
82
|
+
claude/session-state/archive/
|
|
83
|
+
claude/settings.bak.json
|
|
84
|
+
claude/skills/ai-multimodal/assets/demo-*.claude/session-state/*.tmp
|
|
85
|
+
|
|
86
|
+
# Gemini CLI settings (symlink to staged .claude/.mcp.json)
|
|
87
|
+
.gemini/settings.json
|
|
88
|
+
# Showoff/marketing assets (images, showcases)
|
|
89
|
+
assets/
|
|
90
|
+
# Exception: use-mcp ships a persistent tool catalog at assets/tools.json
|
|
91
|
+
!claude/skills/use-mcp/assets/
|
|
92
|
+
!claude/skills/use-mcp/assets/**
|
|
93
|
+
|
|
94
|
+
# External repos for study/reference
|
|
95
|
+
external/
|
|
96
|
+
|
|
97
|
+
# Git worktrees (local development only)
|
|
98
|
+
worktrees/
|
|
99
|
+
|
|
100
|
+
# Local credential files (never commit) — covers apikeys, secrets.txt, *.pem,
|
|
101
|
+
# and any *.key / *.token that land at the repo root or in dev folders.
|
|
102
|
+
apikeys
|
|
103
|
+
secrets.txt
|
|
104
|
+
*.pem
|
|
105
|
+
*.key
|
|
106
|
+
*.token
|
|
107
|
+
|
|
108
|
+
# Per-package virtualenvs (created when running `python -m venv .venv`
|
|
109
|
+
# inside finizi-app/ or other packages)
|
|
110
|
+
finizi-app/.venv
|
|
111
|
+
**/.venv
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `finizi-app invoices list`: new `--invoice-series TEXT` and
|
|
8
|
+
`--invoice-number INTEGER` filter flags. Use them to look up an
|
|
9
|
+
invoice by its Vietnamese (series, number) tuple (e.g. `C26MAP-842`)
|
|
10
|
+
in O(1) without paginating. Both flags can be set standalone or
|
|
11
|
+
together, and AND-combine with the existing `--status`, `--date-from`,
|
|
12
|
+
`--date-to`, `--query`, and `--vendor-id` filters. The matching
|
|
13
|
+
backend support is pending in the upstream `b4b-api` list endpoint
|
|
14
|
+
(issue #18) — once it lands, `bank-reconciler` and other skills can
|
|
15
|
+
use the new flags directly.
|
|
16
|
+
|
|
17
|
+
### Breaking changes
|
|
18
|
+
|
|
19
|
+
- `finizi-app payments list`: CLI flags renamed to match the server schema.
|
|
20
|
+
Use `--date-from` / `--date-to` / `--partner-id` (was `--from-date` /
|
|
21
|
+
`--to-date` / `--vendor-id`). The MCP `Params` fields are now
|
|
22
|
+
`date_from` / `date_to` / `partner_id` (was `from_date` / `to_date` /
|
|
23
|
+
`vendor_id`). The old flags are rejected by Typer and the old field
|
|
24
|
+
names by Pydantic — no shim is provided because the previous values
|
|
25
|
+
were silently dropped by the server. Update scripts and MCP callers
|
|
26
|
+
before upgrading.
|
finizi_app-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Finizi Engineering. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This software is proprietary and confidential. Unauthorized copying,
|
|
6
|
+
distribution, modification, or use of this software, via any medium, is
|
|
7
|
+
strictly prohibited.
|
|
8
|
+
|
|
9
|
+
For licensing inquiries, contact engineering@finizi.app.
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: finizi-app
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI + MCP server for the Finizi.AI Vietnamese accounting/tax platform
|
|
5
|
+
Project-URL: Homepage, https://github.com/finizi-app/finizi-agentize
|
|
6
|
+
Project-URL: Repository, https://github.com/finizi-app/finizi-agentize.git
|
|
7
|
+
Project-URL: Issues, https://github.com/finizi-app/finizi-agentize/issues
|
|
8
|
+
Author-email: Finizi Engineering <engineering@finizi.app>
|
|
9
|
+
License-Expression: LicenseRef-Proprietary
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
15
|
+
Classifier: License :: Other/Proprietary License
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
22
|
+
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Requires-Dist: httpx>=0.28.1
|
|
26
|
+
Requires-Dist: keyring>=25.0.0
|
|
27
|
+
Requires-Dist: keytar>=0.1.0; sys_platform == 'darwin' or sys_platform == 'linux'
|
|
28
|
+
Requires-Dist: mcp<3,>=2
|
|
29
|
+
Requires-Dist: pydantic-settings>=2.10.1
|
|
30
|
+
Requires-Dist: pydantic>=2.11.7
|
|
31
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
32
|
+
Requires-Dist: rich>=13.9.0
|
|
33
|
+
Requires-Dist: starlette>=0.41.0
|
|
34
|
+
Requires-Dist: tenacity>=9.0.0
|
|
35
|
+
Requires-Dist: typer>=0.15.0
|
|
36
|
+
Requires-Dist: uvicorn>=0.35.0
|
|
37
|
+
Provides-Extra: dev
|
|
38
|
+
Requires-Dist: anyio>=4.6.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: mypy>=1.13.0; extra == 'dev'
|
|
40
|
+
Requires-Dist: pytest-asyncio>=1.1.0; extra == 'dev'
|
|
41
|
+
Requires-Dist: pytest-cov>=6.0.0; extra == 'dev'
|
|
42
|
+
Requires-Dist: pytest>=8.4.1; extra == 'dev'
|
|
43
|
+
Requires-Dist: respx>=0.21.0; extra == 'dev'
|
|
44
|
+
Requires-Dist: ruff>=0.7.0; extra == 'dev'
|
|
45
|
+
Requires-Dist: trustme>=1.2.0; extra == 'dev'
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
|
|
48
|
+
# finizi-app-agent
|
|
49
|
+
|
|
50
|
+
CLI + MCP server for the [finizi-app-api](../README.md) Vietnamese
|
|
51
|
+
accounting, tax, payroll, and operations platform — built to work with the
|
|
52
|
+
[admin.finizi.ai](https://admin.finizi.ai) application.
|
|
53
|
+
|
|
54
|
+
**Private distribution only** — not published to public PyPI.
|
|
55
|
+
|
|
56
|
+
## What it is
|
|
57
|
+
|
|
58
|
+
`finizi-app-agent` is a thin wrapper that exposes **96** carefully-chosen
|
|
59
|
+
workflows of the finizi-app-api as:
|
|
60
|
+
|
|
61
|
+
1. **`finizi-app` CLI** — a scriptable command-line tool with stable JSON
|
|
62
|
+
output
|
|
63
|
+
2. **MCP server** — agent-callable tools via stdio or Streamable HTTP
|
|
64
|
+
|
|
65
|
+
Both surfaces share a single `core/` package, so the same business logic
|
|
66
|
+
is exercised in tests, CLI, and MCP.
|
|
67
|
+
|
|
68
|
+
The wrapper targets the **production admin.finizi.ai application by
|
|
69
|
+
default** but every endpoint is fully configurable through the credential
|
|
70
|
+
resolution chain.
|
|
71
|
+
|
|
72
|
+
## Install
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Editable install (development)
|
|
76
|
+
uv pip install -e .
|
|
77
|
+
|
|
78
|
+
# Internal distribution (from this monorepo's git URL)
|
|
79
|
+
pip install "git+ssh://git@github.com/finizi-app/finizi-agentize.git@<SHA>#subdirectory=finizi-app"
|
|
80
|
+
|
|
81
|
+
# With dev extras (pytest, ruff, mypy)
|
|
82
|
+
pip install "git+ssh://git@github.com/finizi-app/finizi-agentize.git@<SHA>#subdirectory=finizi-app[dev]"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The `finizi-app` CLI and `finizi-app-mcp` entry points are auto-installed.
|
|
86
|
+
|
|
87
|
+
## What's new (2026-06-30 session)
|
|
88
|
+
|
|
89
|
+
Three additive CLI usability improvements:
|
|
90
|
+
|
|
91
|
+
| Change | Purpose |
|
|
92
|
+
|--------|---------|
|
|
93
|
+
| `finizi-app --version` flag | Print finizi-app + python version, exit 0 |
|
|
94
|
+
| `finizi-app auth status [--json]` | Show masked credentials + source layer (no API call) |
|
|
95
|
+
| `apikeys` file at CWD | New resolution layer for `api_key` (single-line raw key, `# comments` and blank lines tolerated; override via `FINIZI_APIKEYS_PATH`) |
|
|
96
|
+
|
|
97
|
+
Run `finizi-app --version` and `finizi-app auth status` after install to verify
|
|
98
|
+
the upgrade took effect.
|
|
99
|
+
|
|
100
|
+
## What's new (2026-06-27 session)
|
|
101
|
+
|
|
102
|
+
8 new audit-skill read-only commands were added to support the
|
|
103
|
+
`review-invoice-and-entries` skill workflow:
|
|
104
|
+
|
|
105
|
+
| Command | Purpose | Phase |
|
|
106
|
+
|---------|---------|-------|
|
|
107
|
+
| `finizi-app invoices get` | Invoice detail by id | 01 |
|
|
108
|
+
| `finizi-app vendors get` | Vendor detail by tax_id (entity-scoped) | 01 |
|
|
109
|
+
| `finizi-app tax check-status` | Tax-code status (currently mock; backend B5 pending) | 01 |
|
|
110
|
+
| `finizi-app ledger get-entries` | GL (journal) entries for an invoice | 01 |
|
|
111
|
+
| `finizi-app documents list` | Documents attached to an entity | 01 |
|
|
112
|
+
| `finizi-app company get` | Buyer company record by tax code (B1 backend) | 02 |
|
|
113
|
+
| `finizi-app payments get-by-invoice` | All payments against an invoice (B2 backend) | 02 |
|
|
114
|
+
| `finizi-app inventory get-receipt` | GRN linked to an invoice (B4 backend) | 02 |
|
|
115
|
+
|
|
116
|
+
All 8 are read-only. All 8 honor `--json`. All 8 use the standard exit
|
|
117
|
+
codes (0/1/2/3/4) defined in [`docs/cli.md`](docs/cli.md).
|
|
118
|
+
|
|
119
|
+
Backend ticket [#1443](https://github.com/finizi-app/b4b-api/issues/1443)
|
|
120
|
+
fixed the `documents list --ref-id` filter; flag is exposed in the CLI.
|
|
121
|
+
|
|
122
|
+
## What's new (2026-06-28, slice 3)
|
|
123
|
+
|
|
124
|
+
`finizi-app coa get` now returns **raw account state only** — no
|
|
125
|
+
regulatory classification. Closes issue #9.
|
|
126
|
+
|
|
127
|
+
**BREAKING**: removed `source`, `account_regime` (per account), and the
|
|
128
|
+
top-level `regime` field. Renamed `is_custom_account` →
|
|
129
|
+
`is_entity_specific_account` in the response. The wrapper no longer
|
|
130
|
+
performs the second round trip to `/accounting-models`. Finizi is a
|
|
131
|
+
data transport, not a regulatory authority; auditors / skill agents
|
|
132
|
+
apply their own classification against Vietnamese accounting
|
|
133
|
+
regulations.
|
|
134
|
+
|
|
135
|
+
## What's new (2026-06-28, slice 2)
|
|
136
|
+
|
|
137
|
+
`finizi-app coa get` upgraded to return **all postable accounts** (cấp 1 +
|
|
138
|
+
cấp 2/3 sub-accounts like TK 3311, 3318, 13311-13313) with correct
|
|
139
|
+
`parent_account_id` linking. Backed by `/chart-of-accounts/postable` (slice 1
|
|
140
|
+
used `/chart-of-accounts` which only returned cấp 1).
|
|
141
|
+
|
|
142
|
+
**BREAKING**: `--page` and `--per-page` flags were removed (pagination is
|
|
143
|
+
trivial now — `/postable` returns the full set in one round trip). Users
|
|
144
|
+
who scripted `coa get --page 2` should remove the flag.
|
|
145
|
+
|
|
146
|
+
Adds:
|
|
147
|
+
- `--levels 1,2,3|all` filter (default = all)
|
|
148
|
+
- `--include-inactive` flag (forward-compatible; backend doesn't expose
|
|
149
|
+
inactive accounts yet — see [b4b-api#1483](https://github.com/finizi-app/b4b-api/issues/1483))
|
|
150
|
+
- `source` field now returns `"standard_tt<regime>"` for non-custom accounts
|
|
151
|
+
(was `"unknown"`); `"custom_entity"` for `is_custom_account=true`
|
|
152
|
+
- Pagination metadata: `total`, `page`, `per_page`, `pages`, `has_next`,
|
|
153
|
+
`has_prev` (always single-page; backend returns full set in one shot)
|
|
154
|
+
|
|
155
|
+
Closes gaps 1, 2, 3, 4 from issue #5 against PATEDELI (110 accounts, 73
|
|
156
|
+
sub-accounts, all properly tagged). Gap 5 (true `regime_mismatch`) partially
|
|
157
|
+
addressed — full support pending [b4b-api#1482](https://github.com/finizi-app/b4b-api/issues/1482)
|
|
158
|
+
(`linked_regime` field per account).
|
|
159
|
+
|
|
160
|
+
## What's new (2026-06-28, slice 1)
|
|
161
|
+
|
|
162
|
+
Added `finizi-app coa get` for the `audit-coa-organization` skill in
|
|
163
|
+
`finizi_bpo_knowledge`. Returns the entity's Chart of Accounts with
|
|
164
|
+
`account_regime` derived from the assigned accounting model. Read-only;
|
|
165
|
+
2 backend round trips composed client-side.
|
|
166
|
+
|
|
167
|
+
Backend ticket [b4b-api#1479](https://github.com/finizi-app/b4b-api/issues/1479)
|
|
168
|
+
filed for `type` / `source` / `linked_regime` tagging per account — wrapper
|
|
169
|
+
emits `null` / `unknown` until that lands.
|
|
170
|
+
|
|
171
|
+
## Endpoint configuration
|
|
172
|
+
|
|
173
|
+
The CLI/MCP client talks to a finizi-app-api backend. By default it
|
|
174
|
+
targets the production admin.finizi.ai application. Override through
|
|
175
|
+
any of:
|
|
176
|
+
|
|
177
|
+
| Layer | Variable | Example |
|
|
178
|
+
|-------|----------|---------|
|
|
179
|
+
| Flag (CLI) | `--api-url` | `finizi-app doctor --api-url https://staging.admin.finizi.ai` |
|
|
180
|
+
| Process env | `FINIZI_API_URL` | `export FINIZI_API_URL=https://staging.admin.finizi.ai` |
|
|
181
|
+
| `.env.local` | `FINIZI_API_URL=...` | per-developer override |
|
|
182
|
+
| `.env.<FINIZI_ENV>` | same | per-environment |
|
|
183
|
+
| `.env` | same | shared default |
|
|
184
|
+
| User config | `~/.config/finizi-app/credentials.json` | `{"api_url": "..."}` |
|
|
185
|
+
| Project config | `./.finizi-app/credentials.json` | same |
|
|
186
|
+
| OS keychain | `finizi-app-agent/api_url` | `security add-generic-password -s finizi-app-agent -a api_url -w 'https://...'` |
|
|
187
|
+
| **Default** | built-in | `https://admin.finizi.ai` |
|
|
188
|
+
|
|
189
|
+
`FINIZI_MCP_URL` is also configurable; it defaults to `{api_url}/mcp`.
|
|
190
|
+
|
|
191
|
+
`finizi-app doctor --json` reports which layer resolved without printing
|
|
192
|
+
values.
|
|
193
|
+
|
|
194
|
+
## Quick start
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# Check the API is reachable (uses default https://admin.finizi.ai)
|
|
198
|
+
finizi-app doctor
|
|
199
|
+
|
|
200
|
+
# Override for staging
|
|
201
|
+
FINIZI_API_URL=https://staging.admin.finizi.ai finizi-app doctor
|
|
202
|
+
|
|
203
|
+
# Authenticate (caches to OS keychain)
|
|
204
|
+
finizi-app auth login --phone +84xxxxxxxxx --password '...'
|
|
205
|
+
|
|
206
|
+
# Pick a tenant
|
|
207
|
+
finizi-app entities use --entity-id 42
|
|
208
|
+
|
|
209
|
+
# Run a workflow
|
|
210
|
+
finizi-app invoices list --entity-id 42 --page 1
|
|
211
|
+
finizi-app invoices import-xml --entity-id 42 ./invoice.xml
|
|
212
|
+
finizi-app einvoice issue --entity-id 42 --invoice-id 1234
|
|
213
|
+
|
|
214
|
+
# Audit-skill workflows
|
|
215
|
+
finizi-app invoices get --entity-id 42 --invoice-id 1234
|
|
216
|
+
finizi-app ledger get-entries --entity-id 42 --invoice-id 1234
|
|
217
|
+
finizi-app tax check-status --tax-code 0123456789 --date 2026-01-15
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## MCP server
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# stdio (for local Claude Code / Cursor) — connects to admin.finizi.ai by default
|
|
224
|
+
finizi-app-mcp --transport stdio
|
|
225
|
+
|
|
226
|
+
# Streamable HTTP (self-hosted MCP server, e.g. alongside the admin app)
|
|
227
|
+
finizi-app-mcp --transport http --host 0.0.0.0 --port 8080 --bearer-token "$FINIZI_MCP_BEARER_TOKEN"
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
See [`docs/cli.md`](docs/cli.md) and [`docs/mcp.md`](docs/mcp.md) for full reference.
|
|
231
|
+
|
|
232
|
+
## Architecture
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
finizi-app-agent/
|
|
236
|
+
├── core/ # framework-agnostic (no typer, no mcp)
|
|
237
|
+
├── cli/ # Typer app, thin adapter over core
|
|
238
|
+
├── mcp/ # FastMCP server, thin adapter over core
|
|
239
|
+
└── tests/
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
See [`docs/architecture.md`](docs/architecture.md) for details.
|
|
243
|
+
|
|
244
|
+
## Naming
|
|
245
|
+
|
|
246
|
+
| What | Name |
|
|
247
|
+
|------|------|
|
|
248
|
+
| Python import package | `finizi_app` |
|
|
249
|
+
| CLI entry point | `finizi-app` |
|
|
250
|
+
| MCP server entry point | `finizi-app-mcp` |
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
Proprietary — Finizi Engineering. Internal use only.
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# finizi-app-agent
|
|
2
|
+
|
|
3
|
+
CLI + MCP server for the [finizi-app-api](../README.md) Vietnamese
|
|
4
|
+
accounting, tax, payroll, and operations platform — built to work with the
|
|
5
|
+
[admin.finizi.ai](https://admin.finizi.ai) application.
|
|
6
|
+
|
|
7
|
+
**Private distribution only** — not published to public PyPI.
|
|
8
|
+
|
|
9
|
+
## What it is
|
|
10
|
+
|
|
11
|
+
`finizi-app-agent` is a thin wrapper that exposes **96** carefully-chosen
|
|
12
|
+
workflows of the finizi-app-api as:
|
|
13
|
+
|
|
14
|
+
1. **`finizi-app` CLI** — a scriptable command-line tool with stable JSON
|
|
15
|
+
output
|
|
16
|
+
2. **MCP server** — agent-callable tools via stdio or Streamable HTTP
|
|
17
|
+
|
|
18
|
+
Both surfaces share a single `core/` package, so the same business logic
|
|
19
|
+
is exercised in tests, CLI, and MCP.
|
|
20
|
+
|
|
21
|
+
The wrapper targets the **production admin.finizi.ai application by
|
|
22
|
+
default** but every endpoint is fully configurable through the credential
|
|
23
|
+
resolution chain.
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Editable install (development)
|
|
29
|
+
uv pip install -e .
|
|
30
|
+
|
|
31
|
+
# Internal distribution (from this monorepo's git URL)
|
|
32
|
+
pip install "git+ssh://git@github.com/finizi-app/finizi-agentize.git@<SHA>#subdirectory=finizi-app"
|
|
33
|
+
|
|
34
|
+
# With dev extras (pytest, ruff, mypy)
|
|
35
|
+
pip install "git+ssh://git@github.com/finizi-app/finizi-agentize.git@<SHA>#subdirectory=finizi-app[dev]"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The `finizi-app` CLI and `finizi-app-mcp` entry points are auto-installed.
|
|
39
|
+
|
|
40
|
+
## What's new (2026-06-30 session)
|
|
41
|
+
|
|
42
|
+
Three additive CLI usability improvements:
|
|
43
|
+
|
|
44
|
+
| Change | Purpose |
|
|
45
|
+
|--------|---------|
|
|
46
|
+
| `finizi-app --version` flag | Print finizi-app + python version, exit 0 |
|
|
47
|
+
| `finizi-app auth status [--json]` | Show masked credentials + source layer (no API call) |
|
|
48
|
+
| `apikeys` file at CWD | New resolution layer for `api_key` (single-line raw key, `# comments` and blank lines tolerated; override via `FINIZI_APIKEYS_PATH`) |
|
|
49
|
+
|
|
50
|
+
Run `finizi-app --version` and `finizi-app auth status` after install to verify
|
|
51
|
+
the upgrade took effect.
|
|
52
|
+
|
|
53
|
+
## What's new (2026-06-27 session)
|
|
54
|
+
|
|
55
|
+
8 new audit-skill read-only commands were added to support the
|
|
56
|
+
`review-invoice-and-entries` skill workflow:
|
|
57
|
+
|
|
58
|
+
| Command | Purpose | Phase |
|
|
59
|
+
|---------|---------|-------|
|
|
60
|
+
| `finizi-app invoices get` | Invoice detail by id | 01 |
|
|
61
|
+
| `finizi-app vendors get` | Vendor detail by tax_id (entity-scoped) | 01 |
|
|
62
|
+
| `finizi-app tax check-status` | Tax-code status (currently mock; backend B5 pending) | 01 |
|
|
63
|
+
| `finizi-app ledger get-entries` | GL (journal) entries for an invoice | 01 |
|
|
64
|
+
| `finizi-app documents list` | Documents attached to an entity | 01 |
|
|
65
|
+
| `finizi-app company get` | Buyer company record by tax code (B1 backend) | 02 |
|
|
66
|
+
| `finizi-app payments get-by-invoice` | All payments against an invoice (B2 backend) | 02 |
|
|
67
|
+
| `finizi-app inventory get-receipt` | GRN linked to an invoice (B4 backend) | 02 |
|
|
68
|
+
|
|
69
|
+
All 8 are read-only. All 8 honor `--json`. All 8 use the standard exit
|
|
70
|
+
codes (0/1/2/3/4) defined in [`docs/cli.md`](docs/cli.md).
|
|
71
|
+
|
|
72
|
+
Backend ticket [#1443](https://github.com/finizi-app/b4b-api/issues/1443)
|
|
73
|
+
fixed the `documents list --ref-id` filter; flag is exposed in the CLI.
|
|
74
|
+
|
|
75
|
+
## What's new (2026-06-28, slice 3)
|
|
76
|
+
|
|
77
|
+
`finizi-app coa get` now returns **raw account state only** — no
|
|
78
|
+
regulatory classification. Closes issue #9.
|
|
79
|
+
|
|
80
|
+
**BREAKING**: removed `source`, `account_regime` (per account), and the
|
|
81
|
+
top-level `regime` field. Renamed `is_custom_account` →
|
|
82
|
+
`is_entity_specific_account` in the response. The wrapper no longer
|
|
83
|
+
performs the second round trip to `/accounting-models`. Finizi is a
|
|
84
|
+
data transport, not a regulatory authority; auditors / skill agents
|
|
85
|
+
apply their own classification against Vietnamese accounting
|
|
86
|
+
regulations.
|
|
87
|
+
|
|
88
|
+
## What's new (2026-06-28, slice 2)
|
|
89
|
+
|
|
90
|
+
`finizi-app coa get` upgraded to return **all postable accounts** (cấp 1 +
|
|
91
|
+
cấp 2/3 sub-accounts like TK 3311, 3318, 13311-13313) with correct
|
|
92
|
+
`parent_account_id` linking. Backed by `/chart-of-accounts/postable` (slice 1
|
|
93
|
+
used `/chart-of-accounts` which only returned cấp 1).
|
|
94
|
+
|
|
95
|
+
**BREAKING**: `--page` and `--per-page` flags were removed (pagination is
|
|
96
|
+
trivial now — `/postable` returns the full set in one round trip). Users
|
|
97
|
+
who scripted `coa get --page 2` should remove the flag.
|
|
98
|
+
|
|
99
|
+
Adds:
|
|
100
|
+
- `--levels 1,2,3|all` filter (default = all)
|
|
101
|
+
- `--include-inactive` flag (forward-compatible; backend doesn't expose
|
|
102
|
+
inactive accounts yet — see [b4b-api#1483](https://github.com/finizi-app/b4b-api/issues/1483))
|
|
103
|
+
- `source` field now returns `"standard_tt<regime>"` for non-custom accounts
|
|
104
|
+
(was `"unknown"`); `"custom_entity"` for `is_custom_account=true`
|
|
105
|
+
- Pagination metadata: `total`, `page`, `per_page`, `pages`, `has_next`,
|
|
106
|
+
`has_prev` (always single-page; backend returns full set in one shot)
|
|
107
|
+
|
|
108
|
+
Closes gaps 1, 2, 3, 4 from issue #5 against PATEDELI (110 accounts, 73
|
|
109
|
+
sub-accounts, all properly tagged). Gap 5 (true `regime_mismatch`) partially
|
|
110
|
+
addressed — full support pending [b4b-api#1482](https://github.com/finizi-app/b4b-api/issues/1482)
|
|
111
|
+
(`linked_regime` field per account).
|
|
112
|
+
|
|
113
|
+
## What's new (2026-06-28, slice 1)
|
|
114
|
+
|
|
115
|
+
Added `finizi-app coa get` for the `audit-coa-organization` skill in
|
|
116
|
+
`finizi_bpo_knowledge`. Returns the entity's Chart of Accounts with
|
|
117
|
+
`account_regime` derived from the assigned accounting model. Read-only;
|
|
118
|
+
2 backend round trips composed client-side.
|
|
119
|
+
|
|
120
|
+
Backend ticket [b4b-api#1479](https://github.com/finizi-app/b4b-api/issues/1479)
|
|
121
|
+
filed for `type` / `source` / `linked_regime` tagging per account — wrapper
|
|
122
|
+
emits `null` / `unknown` until that lands.
|
|
123
|
+
|
|
124
|
+
## Endpoint configuration
|
|
125
|
+
|
|
126
|
+
The CLI/MCP client talks to a finizi-app-api backend. By default it
|
|
127
|
+
targets the production admin.finizi.ai application. Override through
|
|
128
|
+
any of:
|
|
129
|
+
|
|
130
|
+
| Layer | Variable | Example |
|
|
131
|
+
|-------|----------|---------|
|
|
132
|
+
| Flag (CLI) | `--api-url` | `finizi-app doctor --api-url https://staging.admin.finizi.ai` |
|
|
133
|
+
| Process env | `FINIZI_API_URL` | `export FINIZI_API_URL=https://staging.admin.finizi.ai` |
|
|
134
|
+
| `.env.local` | `FINIZI_API_URL=...` | per-developer override |
|
|
135
|
+
| `.env.<FINIZI_ENV>` | same | per-environment |
|
|
136
|
+
| `.env` | same | shared default |
|
|
137
|
+
| User config | `~/.config/finizi-app/credentials.json` | `{"api_url": "..."}` |
|
|
138
|
+
| Project config | `./.finizi-app/credentials.json` | same |
|
|
139
|
+
| OS keychain | `finizi-app-agent/api_url` | `security add-generic-password -s finizi-app-agent -a api_url -w 'https://...'` |
|
|
140
|
+
| **Default** | built-in | `https://admin.finizi.ai` |
|
|
141
|
+
|
|
142
|
+
`FINIZI_MCP_URL` is also configurable; it defaults to `{api_url}/mcp`.
|
|
143
|
+
|
|
144
|
+
`finizi-app doctor --json` reports which layer resolved without printing
|
|
145
|
+
values.
|
|
146
|
+
|
|
147
|
+
## Quick start
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Check the API is reachable (uses default https://admin.finizi.ai)
|
|
151
|
+
finizi-app doctor
|
|
152
|
+
|
|
153
|
+
# Override for staging
|
|
154
|
+
FINIZI_API_URL=https://staging.admin.finizi.ai finizi-app doctor
|
|
155
|
+
|
|
156
|
+
# Authenticate (caches to OS keychain)
|
|
157
|
+
finizi-app auth login --phone +84xxxxxxxxx --password '...'
|
|
158
|
+
|
|
159
|
+
# Pick a tenant
|
|
160
|
+
finizi-app entities use --entity-id 42
|
|
161
|
+
|
|
162
|
+
# Run a workflow
|
|
163
|
+
finizi-app invoices list --entity-id 42 --page 1
|
|
164
|
+
finizi-app invoices import-xml --entity-id 42 ./invoice.xml
|
|
165
|
+
finizi-app einvoice issue --entity-id 42 --invoice-id 1234
|
|
166
|
+
|
|
167
|
+
# Audit-skill workflows
|
|
168
|
+
finizi-app invoices get --entity-id 42 --invoice-id 1234
|
|
169
|
+
finizi-app ledger get-entries --entity-id 42 --invoice-id 1234
|
|
170
|
+
finizi-app tax check-status --tax-code 0123456789 --date 2026-01-15
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## MCP server
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# stdio (for local Claude Code / Cursor) — connects to admin.finizi.ai by default
|
|
177
|
+
finizi-app-mcp --transport stdio
|
|
178
|
+
|
|
179
|
+
# Streamable HTTP (self-hosted MCP server, e.g. alongside the admin app)
|
|
180
|
+
finizi-app-mcp --transport http --host 0.0.0.0 --port 8080 --bearer-token "$FINIZI_MCP_BEARER_TOKEN"
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
See [`docs/cli.md`](docs/cli.md) and [`docs/mcp.md`](docs/mcp.md) for full reference.
|
|
184
|
+
|
|
185
|
+
## Architecture
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
finizi-app-agent/
|
|
189
|
+
├── core/ # framework-agnostic (no typer, no mcp)
|
|
190
|
+
├── cli/ # Typer app, thin adapter over core
|
|
191
|
+
├── mcp/ # FastMCP server, thin adapter over core
|
|
192
|
+
└── tests/
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
See [`docs/architecture.md`](docs/architecture.md) for details.
|
|
196
|
+
|
|
197
|
+
## Naming
|
|
198
|
+
|
|
199
|
+
| What | Name |
|
|
200
|
+
|------|------|
|
|
201
|
+
| Python import package | `finizi_app` |
|
|
202
|
+
| CLI entry point | `finizi-app` |
|
|
203
|
+
| MCP server entry point | `finizi-app-mcp` |
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
Proprietary — Finizi Engineering. Internal use only.
|