Merge dcy-015 monthly settlement dashboard delivery after local and GitHub Actions verification.
15 KiB
15 KiB
Jarca Ledger MCP Project Structure
- Baseline Mode: observed
- Baseline Seed:
.stage-pilot/bootstrap/baseline.yaml - Status: draft
- Owner: Jarca / project maintainer
- Last Updated (KST): 2026-07-09
- Source Discovery / Batch: bootstrap-baseline, BAT-006, BAT-007, BAT-010, BAT-012, BAT-013, BAT-014, dcy-013/BAT-015, dcy-012/REQ-020/BAT-016, REQ-021/BAT-017
Project Summary
- Jarca 가계부 전용 MCP 서버와 Streamlit 대시보드로 계좌/카드 거래, 예산, 분류 규칙, import, 자산/스냅샷, 현금흐름 분석을 SQLite에 저장하고 운영한다.
Primary Domain
- Korean household finance ledger, reconciliation, and household asset tracking
Tech Stack
- Python >=3.11
- FastMCP / MCP server (stdio and streamable-http)
- SQLite
- Streamlit
- pandas / plotly
- PyMuPDF, openpyxl, msoffcrypto-tool
- pytest
- ruff
Primary Runtime
- Type: mixed
- Planned Entry Points:
jarca-ledger-mcp:: MCP stdio server for local Hermes Agent tools and streamable-http server when configured by env.jarca-ledgerDocker container :: independent Streamable HTTP MCP service on:8000/mcp.dashboard/app.py:: Streamlit dashboard for local ledger operations.pytest:: Regression test entry point.
Purpose
- This document is the current repository and package structure baseline.
- It is a cross-cutting reference document for Discovery, REQ, Batch Design, Batch Verification, and implementation updates.
Scope
- Covers top-level repository layout and package/module boundaries.
- Does not duplicate detailed business rules, acceptance criteria, or implementation-only function signatures.
Top-Level Structure
jarca-ledger-mcp/
├── README.md
├── Dockerfile
├── docker-compose.yml
├── .dockerignore
├── pyproject.toml
├── uv.lock
├── .env.example
├── .github/
│ └── workflows/
│ └── ci.yml
├── dashboard/
│ └── app.py
├── jarca_ledger_mcp/
│ ├── __init__.py
│ ├── service.py # compatibility facade
│ ├── db.py # compatibility shim
│ ├── server.py # compatibility shim / CLI entrypoint
│ ├── application/
│ │ ├── __init__.py
│ │ ├── shared.py
│ │ ├── system_services.py
│ │ ├── asset_account_services.py
│ │ ├── assets_service.py
│ │ ├── transaction_report_services.py
│ │ ├── import_transfer_services.py
│ │ ├── imports_service.py
│ │ ├── cross_transfer_service.py
│ │ ├── reconciliation_service.py
│ │ ├── review_decision_service.py
│ │ ├── categorization_services.py
│ │ └── uncategorized_workbench_service.py
│ ├── infrastructure/
│ │ ├── parsers/
│ │ │ ├── __init__.py
│ │ │ ├── kb_bank_pdf.py
│ │ │ ├── toss_bank_pdf.py
│ │ │ ├── toss_securities_pdf.py
│ │ │ └── seoulpay_xlsx.py
│ │ └── sqlite/
│ │ ├── __init__.py
│ │ ├── connection.py
│ │ ├── schema.py
│ │ └── migrations.py
│ ├── adapters/
│ │ ├── mcp/
│ │ │ ├── tool_contracts.py
│ │ │ └── server.py
│ │ └── streamlit/
│ │ ├── __init__.py
│ │ ├── overview_gateway.py
│ │ ├── assets_gateway.py
│ │ ├── transactions_gateway.py
│ │ ├── categorization_gateway.py
│ │ ├── transfers_gateway.py
│ │ ├── imports_gateway.py
│ │ ├── accounts_gateway.py
│ │ ├── reconciliation_gateway.py
│ │ └── service_gateway.py
│ ├── kb_bank_pdf.py
│ ├── toss_bank_pdf.py
│ ├── toss_securities_pdf.py
│ └── seoulpay_xlsx.py
├── tests/
│ ├── contract_snapshots/
│ │ └── response_contract_v1_0.json
│ ├── test_contract_regression.py
│ ├── test_mcp_http_runtime.py
│ ├── test_dashboard_app.py
│ ├── test_service.py
│ ├── test_asset_snapshots.py
│ ├── test_categorization.py
│ ├── test_category_rule_filters.py
│ ├── test_cross_account_transfer_matching.py
│ ├── test_kb_bank_pdf.py
│ ├── test_toss_securities_pdf.py
│ ├── test_seoulpay_xlsx.py
│ └── test_ledger_categories.py
├── scripts/
│ ├── ci_fixture_db.py
│ ├── ci_dashboard_http_smoke.py
│ ├── ci_db_safety_smoke.py
│ ├── ledger_restore_smoke.py
│ └── streamlit_browser_evidence.py
├── docs/
│ ├── discovery/
│ ├── srs/
│ ├── batches/
│ ├── runbooks/
│ │ └── docker-network-mcp-deploy.md
│ ├── releases/
│ ├── project-structure.md
│ ├── runtime-flows.md
│ ├── interface-contract.md
│ └── data-model.md
└── .stage-pilot/
└── bootstrap/baseline.yaml
Package / Module Responsibilities
jarca_ledger_mcp/service.py- Legacy-compatible top-level service facade. Public call sites continue to import from here while implementation lives in application modules.
jarca_ledger_mcp/db.py- Legacy-compatible top-level DB shim. Public call sites continue to import
init_db,db,resolve_db_pathfrom here.
- Legacy-compatible top-level DB shim. Public call sites continue to import
jarca_ledger_mcp/server.py- Legacy-compatible MCP entrypoint shim that delegates to
adapters.mcp.server.
- Legacy-compatible MCP entrypoint shim that delegates to
jarca_ledger_mcp/application/shared.py- Shared helpers, validation, KST clock, dedupe policy, parser seam imports, and cross-domain constants.
jarca_ledger_mcp/application/system_services.py- Health/status/backup/account create-list/update and persistence-adjacent service behavior.
jarca_ledger_mcp/application/asset_account_services.py- Legacy-compatible asset/account facade that preserves older import paths while delegating asset ownership to
assets_service.pyand account mutation to write services.
- Legacy-compatible asset/account facade that preserves older import paths while delegating asset ownership to
jarca_ledger_mcp/application/assets_service.py- Manual asset CRUD, snapshot close/report, liquidity, and net-worth workflow ownership.
jarca_ledger_mcp/application/transaction_report_services.py- Transaction CRUD, budgets, monthly/category/fixed-cost/investable cashflow reports, with reconciliation delegated to
reconciliation_service.py.
- Transaction CRUD, budgets, monthly/category/fixed-cost/investable cashflow reports, with reconciliation delegated to
jarca_ledger_mcp/application/import_transfer_services.py- Legacy-compatible import/transfer facade that preserves prior import paths while delegating to
imports_service.pyandcross_transfer_service.py.
- Legacy-compatible import/transfer facade that preserves prior import paths while delegating to
jarca_ledger_mcp/application/imports_service.py- Import preview/import/rollback orchestration and import batch workflow ownership.
jarca_ledger_mcp/application/cross_transfer_service.py- Cross-account/self-transfer/cancel-original matching workflow ownership.
jarca_ledger_mcp/application/reconciliation_service.py- Manual/partial-import balance reconciliation preview ownership.
jarca_ledger_mcp/application/review_decision_service.py- Persistent review-decision and reconciliation-session workflow ownership. Provides safe non-destructive create/update/hold/recheck/release/close helpers shared by Streamlit and MCP adapters.
jarca_ledger_mcp/application/categorization_services.py- Category rules, categorization preview/apply, ledger categories, and compatibility delegation to
uncategorized_workbench_service.py.
- Category rules, categorization preview/apply, ledger categories, and compatibility delegation to
jarca_ledger_mcp/application/uncategorized_workbench_service.py- Uncategorized inbox/workbench queries and recommendation-apply workflow ownership.
jarca_ledger_mcp/infrastructure/parsers/*- Import parser seam that keeps file-source parsing under infrastructure while preserving legacy top-level parser modules.
jarca_ledger_mcp/infrastructure/sqlite/connection.py- DB path resolution, sqlite connection setup, context manager semantics.
jarca_ledger_mcp/infrastructure/sqlite/schema.py- Schema version, DDL, additive column definitions.
jarca_ledger_mcp/infrastructure/sqlite/migrations.py- Additive/idempotent migration routines and DB initialization.
jarca_ledger_mcp/adapters/mcp/tool_contracts.py- Narrow MCP adapter contract surface that re-exports only the public tool callables consumed by the FastMCP server.
jarca_ledger_mcp/adapters/mcp/server.py- FastMCP tool registration layer that depends on
tool_contracts.pyinstead of broad direct service imports. Runtime transport is configurable: stdio by default, or streamable-http throughJARCA_MCP_TRANSPORT=streamable-httpwith host/port/path env settings.
- FastMCP tool registration layer that depends on
jarca_ledger_mcp/adapters/streamlit/service_gateway.py- Compatibility aggregator over page/domain gateway modules.
jarca_ledger_mcp/adapters/streamlit/*_gateway.py- Page/domain-sized dashboard service surfaces (
overview,assets,transactions,categorization,transfers,imports,accounts,reconciliation).
- Page/domain-sized dashboard service surfaces (
- Parser modules (
kb_bank_pdf.py,toss_bank_pdf.py,toss_securities_pdf.py,seoulpay_xlsx.py)- Source-file parsing and preview conversion only.
dashboard/app.py- Streamlit operator UI for the operations hub summary, 자산/마감, 거래내역, 확인필요 큐, 미분류, 분류 규칙, 카테고리, 계좌, Import pages, wired through page/domain gateways instead of a flat broad service namespace.
- 월정산 페이지는
자산 / 순자산 마감 상태이후 읽기 전용 Evidence 및 다음 액션 체크리스트 영역을 렌더링한다.
tests/- Regression tests for facade compatibility, service behavior, parser behavior, categorization, transfer matching, MCP contract compatibility, and Streamlit AppTest smoke.
.github/workflows/ci.yml- GitHub Actions workflow for
pull_request,pushtomain, andworkflow_dispatch; stable required gate jobs arepytest-regression,dashboard-app-test,dashboard-http-smoke,db-safety-smoke,contract-regression, andlint.
- GitHub Actions workflow for
scripts/ci_fixture_db.py- Synthetic fixture DB builder for CI/AppTest/browser smoke.
scripts/ci_dashboard_http_smoke.py- Synthetic-db Streamlit readiness smoke wrapper.
scripts/ci_db_safety_smoke.py- Synthetic-db backup/restore safety smoke wrapper.
scripts/streamlit_browser_evidence.py- Local browser evidence helper using synthetic/validation DBs only.
scripts/ledger_restore_smoke.py- Script-only restore smoke helper; restore remains outside the MCP tool surface.
Dockerfile/docker-compose.yml- Build and run the independent
jarca-ledgerDocker service. Compose fixescontainer_name=jarca-ledger,restart=unless-stopped, port8000:8000, and bind mount/volume1/docker/jarca-ledger/data:/data.
- Build and run the independent
docs/runbooks/docker-network-mcp-deploy.md- Operator runbook for building, starting, and verifying the Docker Streamable HTTP MCP deployment and DB path.
Dependency Rules
adapters/mcp/server.pyshould remain a thin tool adapter and delegate business logic toservice.pyfacade/application modules.dashboard/app.pyshould calladapters/streamlit/service_gateway.py, not giant implementation modules directly.service.py/db.py/server.pyshims preserve public import paths while new implementation lives underapplication/,infrastructure/,adapters/.- Parser modules should parse source documents into structured records and avoid direct UI responsibilities.
- DB schema migrations should be additive and idempotent by default.
Shared Boundaries
cashflow_kindis the boundary between actual household income/expense and account movement/exclusion semantics.liquidity_bucketis the account/manual-asset boundary for liquidity/composition/debt/net-worth views.- Import evidence fields (
source,external_id,raw_summary,raw_payload,counterparty,import_batch_id) are audit boundaries and should be preserved, but BAT-017 constrains new persistence/response behavior to normalized provenance plus source-specific minimized payload allowlists. import_batches.filenameis an operator-correlation field, not a raw path cache: new writes must use masked basename plus source-hash prefix, and read surfaces must expose provenance atminimalby default unless an explicit operator/debug path is invoked.- Manual reconciliation is represented through memo tags and narrow transaction updates, not broad rewrites.
- Browser evidence artifacts are generated from synthetic/validation DBs and should not embed real financial identifiers or raw source payloads.
- CI gate fixtures are generated at runtime under temp space by
scripts/ci_fixture_db.py; CI/AppTest/browser smoke must not read the default operating DB path.
Current Gaps / Planned Changes
- Application modules are now separated by phase-0~3 domain seams, but deeper repository/use-case split remains future Phase 4+ work.
- Streamlit now uses page/domain gateways; deeper presenter/view-model extraction remains future work.
- Network MCP over FastMCP streamable-http is now available for internal Synology operation; broader HTTP/REST business API, external exposure, reverse proxy/TLS/auth, and remote ops re-architecture remain future work.
Update Triggers
- Update this document when package boundaries change.
- Update this document when new top-level runtime or domain modules are added.
- Update this document when a batch changes the approved structure baseline.
Change Log
- 2026-07-12 KST: REQ-025/BAT-020 기준으로 월정산 페이지 Read-only Evidence / 다음 액션 하드닝과 테스트 검증 항목을 반영.
- 2026-07-09 KST: REQ-021/BAT-017 기준으로 import provenance sanitizer 경계, masked filename persistence, explicit debug gate wiring, and baseline doc ownership을 반영.
- 2026-06-26 22:24 KST: Created by
bootstrap-baselinefrom repository observation. - 2026-06-29 KST: REQ-004/BAT-004 기준으로
scripts/streamlit_browser_evidence.py및 browser evidence artifact 구조 추가. - 2026-06-29 KST: REQ-005/BAT-005 기준으로 dashboard operations hub와 service asset liquidity aggregation 책임 추가.
- 2026-06-30 KST: REQ-006/BAT-006 기준으로 GitHub Actions CI workflow, synthetic fixture DB builder, AppTest/HTTP/DB safety smoke wrappers 추가.
- 2026-06-30 KST: REQ-007/REQ-008/BAT-007 기준으로 MCP response contract snapshot/test 위치와 required-check job 계약 추가.
- 2026-07-03 KST: REQ-013/REQ-014/BAT-010 기준으로 application / infrastructure / adapter layering, compatibility facade/shim, Streamlit gateway 구조를 반영했다.
- 2026-07-03 KST: REQ-016/REQ-017/REQ-018 및 BAT-012/BAT-013/BAT-014 기준으로 import/advanced owning services, parser seam, MCP contract helper, page/domain Streamlit gateways를 반영했다.
- 2026-07-07 KST: REQ-019/BAT-015 기준으로 Dockerfile/compose,
jarca-ledgerindependent container, streamable-http MCP endpoint, Synology volume/volume1/docker/jarca-ledger/data, and Docker deployment runbook을 반영했다. - 2026-07-08 KST: REQ-020/BAT-016 기준으로 review decision service, schema version 11, MCP/Streamlit review workflow integration을 반영했다.