@ledgerful/mcp-server 0.1.8

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.
@@ -0,0 +1,4 @@
1
+ # Binary license notice
2
+
3
+ The Ledgerful binary downloaded by this package is licensed under the terms in
4
+ `LICENSE`, with the additional permissions in `COMMERCIAL-EXCEPTION.md`.
@@ -0,0 +1,120 @@
1
+ # Ledgerful Small-Entity Commercial Exception (v1.0)
2
+
3
+ > This file is the additional permission referenced by the `Required Notice:` line in `LICENSE`.
4
+ > Keep the PolyForm base text verbatim; this Exception only *adds* permissions.
5
+
6
+ Licensor: **Ledgerful, LLC**. "Software" refers to the software identified by the repository's
7
+ PolyForm `Required Notice:` (Ledgerful, as distributed under the PolyForm Noncommercial License).
8
+
9
+ ## Grant
10
+
11
+ In addition to the rights granted by the PolyForm Noncommercial License 1.0.0, the Licensor grants a
12
+ **Qualified Small Entity** a royalty-free, worldwide, non-exclusive license to make **Internal
13
+ Business Use** of the Software, subject to all other terms of the PolyForm Noncommercial License and
14
+ the definitions and conditions below.
15
+
16
+ > **Core constraint: others may not commercialize the new-license Ledgerful.** This Exception grants
17
+ > Internal Business Use only and grants no right to (a) offer the Software itself, (b) offer modified
18
+ > versions or derivative works, (c) provide hosted access to the Software to third parties, or (d)
19
+ > distribute products incorporating substantial portions of it. Commercializing the Software requires
20
+ > a separate written OEM/redistribution agreement.
21
+
22
+ ## Definitions
23
+
24
+ - **"Entity"** means a corporation, LLC, partnership, sole proprietorship, unincorporated
25
+ association, or other legal or commercial organization.
26
+ - **"Affiliate"** means any Entity that directly or indirectly Controls, is Controlled by, or is
27
+ under common Control with another Entity. *(The Affiliate and Control definitions here apply only
28
+ to eligibility and revenue aggregation under this Exception and do not modify the base PolyForm
29
+ license, including PolyForm's "Your company.")*
30
+ - **"Control"** means the direct or indirect power to direct or cause the direction of an Entity's
31
+ management or policies, whether through ownership, voting rights, contract, or otherwise. Control
32
+ is presumed where a person or Entity (a) owns or controls at least 50% of voting power or equity,
33
+ (b) may appoint or remove a majority of the governing body, or (c) otherwise has the practical
34
+ power to direct management or policies. Control may exist below 50%.
35
+ - **"Change of Control"** means a merger, acquisition, sale of substantially all assets, or any
36
+ transaction or series of transactions that changes which person or Entity Controls You.
37
+ - **"Measurement Date"** means the last day of each calendar month and the effective date of any
38
+ Change of Control.
39
+ - **"Measurement Period"** means: for a month-end Measurement Date, the twelve completed calendar
40
+ months ending on that date; for a Change-of-Control Measurement Date, the twelve completed calendar
41
+ months ending before the transaction date. If an Entity has existed fewer than twelve months, the
42
+ period begins on its formation date and its Gross Revenue is not annualized (actual revenue only).
43
+ - **"Gross Revenue"** means all revenue, receipts, and other income from any source recognized or
44
+ accrued under the accounting method the Entity uses consistently in its financial statements or tax
45
+ returns, before deduction of costs, reduced only by bona fide returns, refunds, and allowances. It
46
+ excludes: (a) sales/VAT/similar taxes collected for and remitted to a government; (b) proceeds of
47
+ equity investment or borrowing; (c) capital contributions; (d) proceeds from sales of capital
48
+ assets outside the ordinary course; and (e) inter-Affiliate amounts eliminated in Aggregated Gross
49
+ Revenue. An Entity may not change its accounting method primarily to qualify for this Exception;
50
+ any change must be required by law, applicable accounting standards, or a consistently applied bona
51
+ fide business practice.
52
+ - **"Aggregated Gross Revenue"** means the sum of Gross Revenue for You and every Entity that is Your
53
+ Affiliate on the Measurement Date, for the same Measurement Period, eliminating inter-Affiliate
54
+ transactions. Following an acquisition or Change of Control, it includes the full Measurement-Period
55
+ Gross Revenue of every current Affiliate. Revenue in a currency other than U.S. dollars is
56
+ converted using the average exchange rate for the Measurement Period published by the U.S. Federal
57
+ Reserve (or, if unavailable, another nationally recognized central bank, selected reasonably and
58
+ applied consistently).
59
+ - **"Qualified Small Entity"** means You and Your Affiliates collectively, provided Aggregated Gross
60
+ Revenue is less than US$1,000,000 on the applicable Measurement Date. (Eligibility is revenue-based
61
+ only — available funding, capital raised, or valuation do not affect it.)
62
+ - **"Internal Business Use"** means use of the Software for Your own internal operations (including on
63
+ Your own or a third-party-managed VM, private CI runner, or cloud environment used for Your
64
+ internal operations), or to support professional or consulting services You provide, but excludes:
65
+ (a) offering the Software itself; (b) offering modified versions or derivative works; (c) providing
66
+ hosted access to the Software to third parties; and (d) distributing products incorporating
67
+ substantial portions of the Software.
68
+ - **"Authorized Contractor"** means a third party engaged to provide services to a Qualified Small
69
+ Entity, acting solely for that entity's benefit under written obligations at least as protective as
70
+ these terms.
71
+ - **"Written Authorization"** means a written Commercial License or other written permission from the
72
+ Licensor.
73
+ - **"Production Use"** means use of the Software in live operations or to process real or business
74
+ data, as distinct from testing or evaluation in a non-live environment.
75
+ - **"Evaluation Use"** means internal, non-Production Use to assess commercial fit.
76
+
77
+ ## Conditions and lifecycle
78
+
79
+ - For a Qualified Small Entity, Internal Business Use is a permitted purpose under the PolyForm
80
+ Noncommercial License 1.0.0.
81
+ - Eligibility is determined on each Measurement Date. At exactly US$1,000,000 Aggregated Gross
82
+ Revenue, You are no longer a Qualified Small Entity.
83
+ - **Continuing grant during transition:** if You cease to qualify solely because Aggregated Gross
84
+ Revenue reaches or exceeds US$1,000,000, or because of a Change of Control, this Exception remains
85
+ effective for 90 days after the applicable Measurement Date. Before that period expires You must
86
+ obtain Written Authorization or cease all commercial use.
87
+ - **Requalification:** an Entity that later falls below US$1,000,000 requalifies only after 12
88
+ consecutive months with Aggregated Gross Revenue below the threshold, and is not entitled to a
89
+ second 90-day transition within any 24-month period.
90
+ - **Authorized Contractor:** an Authorized Contractor may exercise a Qualified Small Entity's rights
91
+ solely while providing services to that Qualified Small Entity and solely for its benefit. The
92
+ Qualified Small Entity remains responsible for the contractor's compliance. No contractor receives
93
+ rights for its own independent business use.
94
+ - **Eligibility records:** You must make a good-faith eligibility determination on each Measurement
95
+ Date and retain records reasonably sufficient to support it for three years. No financial
96
+ disclosure is required unless reasonably requested in connection with a specific eligibility
97
+ dispute, subject to confidentiality protections.
98
+ - **Effect of breach:** if You breach this Exception, the additional permissions it grants terminate;
99
+ Your rights under the base PolyForm Noncommercial License continue to the extent independently
100
+ available. Revenue-based expiration (crossing the threshold) is not a breach and receives the
101
+ 90-day transition above.
102
+ - This Exception adds permissions only; all other terms of the PolyForm Noncommercial License
103
+ continue to apply.
104
+
105
+ ## Evaluation Exception
106
+
107
+ The Licensor grants an Entity that is not otherwise eligible (a commercial Entity at or above the
108
+ threshold) a non-exclusive license for Evaluation Use of the Software for 30 days, once per Entity
109
+ and its Affiliate group. The period begins on the Entity's first use of a version distributed under
110
+ this license, does not reset upon
111
+ upgrades, new versions, or Affiliate transfers, and permits internal, non-Production Use only. It
112
+ ends after 30 days unless Written Authorization is obtained. Qualified Small Entities and permitted
113
+ noncommercial users do not need this — they are already licensed.
114
+
115
+ ## Commercial use beyond this Exception
116
+
117
+ Commercial use at or above the threshold requires a separate written Commercial License. Reselling,
118
+ hosting the Software as a service for third parties, OEM embedding, or distributing products
119
+ incorporating substantial portions of the Software requires a separate written OEM/redistribution
120
+ agreement, regardless of size. Contact: legal@ledgerful.dev
package/LICENSE ADDED
@@ -0,0 +1,76 @@
1
+ Required Notice: Copyright 2026 Ledgerful, LLC; additional permissions are stated in COMMERCIAL-EXCEPTION.md.
2
+
3
+ ----------------------------------------------------------------------
4
+
5
+ PolyForm Noncommercial License 1.0.0
6
+ <https://polyformproject.org/licenses/noncommercial/1.0.0>
7
+
8
+ ## Acceptance
9
+
10
+ In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
11
+
12
+ ## Copyright License
13
+
14
+ The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it for any permitted purpose. However, you may only distribute the software according to Distribution License and make changes or new works based on the software according to Changes and New Works License.
15
+
16
+ ## Distribution License
17
+
18
+ The licensor grants you an additional copyright license to distribute copies of the software. Your license to distribute covers distributing the software with changes and new works permitted by Changes and New Works License.
19
+
20
+ ## Notices
21
+
22
+ You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above, as well as copies of any plain-text lines beginning with `Required Notice:` that the licensor provided with the software. For example:
23
+
24
+ Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
25
+
26
+ ## Changes and New Works License
27
+
28
+ The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
29
+
30
+ ## Patent License
31
+
32
+ The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
33
+
34
+ ## Noncommercial Purposes
35
+
36
+ Any noncommercial purpose is a permitted purpose.
37
+
38
+ ## Personal Uses
39
+
40
+ Personal use for research, experiment, and testing for the benefit of public knowledge, personal study, private entertainment, hobby projects, amateur pursuits, or religious observance, without any anticipated commercial application, is use for a permitted purpose.
41
+
42
+ ## Noncommercial Organizations
43
+
44
+ Use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization, or government institution is use for a permitted purpose regardless of the source of funding or obligations resulting from the funding.
45
+
46
+ ## Fair Use
47
+
48
+ You may have "fair use" rights for the software under the law. These terms do not limit them.
49
+
50
+ ## No Other Rights
51
+
52
+ These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
53
+
54
+ ## Patent Defense
55
+
56
+ If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
57
+
58
+ ## Violations
59
+
60
+ The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
61
+
62
+ ## No Liability
63
+
64
+ As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
65
+
66
+ ## Definitions
67
+
68
+ The licensor is the individual or entity offering these terms, and the software is the software the licensor makes available under these terms.
69
+
70
+ You refers to the individual or entity agreeing to these terms.
71
+
72
+ Your company is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. Control means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
73
+
74
+ Your licenses are all the licenses granted to you for the software under these terms.
75
+
76
+ Use means anything you do with the software requiring one of your licenses.
package/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Ledgerful MCP Server
2
+
3
+ `@ledgerful/mcp-server` wraps the Ledgerful CLI's existing `ledgerful mcp`
4
+ stdio server so AI coding agents can install it through npm without building
5
+ Rust locally.
6
+
7
+ ```sh
8
+ npx @ledgerful/mcp-server
9
+ npm install -g @ledgerful/mcp-server
10
+ ledgerful-mcp
11
+ ```
12
+
13
+ The package downloads the matching `ledgerful-{target}` release asset,
14
+ verifies the adjacent `.sha256` checksum file, caches the binary, and launches:
15
+
16
+ ```sh
17
+ ledgerful mcp
18
+ ```
19
+
20
+ Existing `ledgerful` binary naming is intentional: Ledgerful keeps the
21
+ backward-compatible CLI alias while the npm package carries the Ledgerful brand.
22
+
23
+ ## Agent Configuration
24
+
25
+ Use the installed bin as the MCP command:
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "ledgerful": {
31
+ "command": "ledgerful-mcp"
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ ## Tools
38
+
39
+ The tool table is cross-checked against `src/commands/mcp/manifest.rs`.
40
+
41
+ | Tool | Description |
42
+ |---|---|
43
+ | `scan` | Assess the impact and risk of uncommitted changes in the repository. |
44
+ | `search` | High-precision regex and text discovery for code symbols. |
45
+ | `ask` | Conceptual and semantic natural language queries about the codebase. |
46
+ | `ledger_status` | Get the current provenance status, including pending transactions and unaudited drift. |
47
+ | `ledger_search` | Search the architectural history and transaction ledger. |
48
+ | `hotspots` | Identify brittle files with high change frequency or complexity. |
49
+ | `endpoints_changed` | List API endpoints affected by current changes. |
50
+ | `security_boundaries` | Inspect security policy boundaries and their risk status. |
51
+ | `dead_code` | Identify likely unused functions and types based on graph reachability. |
52
+ | `verify_plan` | Predict the verification plan for current changes. |
53
+
54
+ ## Environment
55
+
56
+ | Variable | Purpose |
57
+ |---|---|
58
+ | `LEDGERFUL_MCP_BIN_OVERRIDE` | Use a local Ledgerful/Ledgerful binary instead of downloading a release asset. Useful for CI and development. |
59
+ | `LEDGERFUL_MCP_CACHE_DIR` | Override the binary cache directory. |
60
+ | `LEDGERFUL_MCP_RELEASE_TAG` | Download from a specific GitHub release tag instead of `latest`. |
61
+ | `LEDGERFUL_MCP_RELEASE_BASE_URL` | Override the complete GitHub release asset base URL. |
62
+ | `LEDGERFUL_MCP_SKIP_DOWNLOAD=1` | Skip the best-effort postinstall download. First run will still need a binary or override. |
63
+
64
+ ## Troubleshooting
65
+
66
+ - Unsupported platform: the loader supports `linux:x64`, `win32:x64`,
67
+ `darwin:x64`, and `darwin:arm64`.
68
+ - Download failure: check that the GitHub release has the expected archive and
69
+ adjacent `.sha256` file, or set `LEDGERFUL_MCP_BIN_OVERRIDE`.
70
+ - Checksum mismatch: the loader refuses to execute the downloaded archive. Clear
71
+ the cache and verify the release asset was not replaced.
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const { spawn } = require("node:child_process");
5
+ const { ensureBinary } = require("../lib/install");
6
+
7
+ async function main() {
8
+ const binary = await ensureBinary({ quiet: false });
9
+ const child = spawn(binary, ["mcp", ...process.argv.slice(2)], {
10
+ stdio: "inherit",
11
+ windowsHide: true
12
+ });
13
+
14
+ child.on("error", (error) => {
15
+ console.error(`ledgerful-mcp: failed to launch ${binary}: ${error.message}`);
16
+ process.exitCode = 1;
17
+ });
18
+
19
+ child.on("exit", (code, signal) => {
20
+ if (signal) {
21
+ process.kill(process.pid, signal);
22
+ return;
23
+ }
24
+ process.exit(code ?? 1);
25
+ });
26
+ }
27
+
28
+ main().catch((error) => {
29
+ console.error(`ledgerful-mcp: ${error.message}`);
30
+ process.exit(1);
31
+ });
package/lib/install.js ADDED
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+
3
+ const crypto = require("node:crypto");
4
+ const fs = require("node:fs");
5
+ const os = require("node:os");
6
+ const path = require("node:path");
7
+ const { spawnFile } = require("./process");
8
+ const { resolveTarget } = require("./platform");
9
+
10
+ const OWNER = "Ryan-AI-Studios";
11
+ const REPO = "Ledgerful";
12
+
13
+ function packageVersion() {
14
+ const packageJson = require("../package.json");
15
+ return packageJson.version;
16
+ }
17
+
18
+ function cacheRoot() {
19
+ if (process.env.LEDGERFUL_MCP_CACHE_DIR) {
20
+ return process.env.LEDGERFUL_MCP_CACHE_DIR;
21
+ }
22
+ if (process.platform === "win32" && process.env.LOCALAPPDATA) {
23
+ return path.join(process.env.LOCALAPPDATA, "Ledgerful", "mcp-server");
24
+ }
25
+ if (process.platform === "darwin") {
26
+ return path.join(os.homedir(), "Library", "Caches", "ledgerful-mcp-server");
27
+ }
28
+ return path.join(process.env.XDG_CACHE_HOME || path.join(os.homedir(), ".cache"), "ledgerful-mcp-server");
29
+ }
30
+
31
+ function releaseBaseUrl() {
32
+ if (process.env.LEDGERFUL_MCP_RELEASE_BASE_URL) {
33
+ return process.env.LEDGERFUL_MCP_RELEASE_BASE_URL.replace(/\/+$/, "");
34
+ }
35
+ if (process.env.LEDGERFUL_MCP_RELEASE_TAG) {
36
+ return `https://github.com/${OWNER}/${REPO}/releases/download/${process.env.LEDGERFUL_MCP_RELEASE_TAG}`;
37
+ }
38
+ return `https://github.com/${OWNER}/${REPO}/releases/download/v${packageVersion()}`;
39
+ }
40
+
41
+ function parseChecksum(text) {
42
+ const match = text.match(/\b([a-fA-F0-9]{64})\b/);
43
+ if (!match) {
44
+ throw new Error("checksum file did not contain a SHA-256 digest");
45
+ }
46
+ return match[1].toLowerCase();
47
+ }
48
+
49
+ function sha256File(filePath) {
50
+ const hash = crypto.createHash("sha256");
51
+ hash.update(fs.readFileSync(filePath));
52
+ return hash.digest("hex");
53
+ }
54
+
55
+ async function downloadToFile(url, destination) {
56
+ const response = await fetch(url, {
57
+ headers: {
58
+ "user-agent": `ledgerful-mcp-server/${packageVersion()}`
59
+ }
60
+ });
61
+ if (!response.ok) {
62
+ throw new Error(`download failed for ${url}: HTTP ${response.status}`);
63
+ }
64
+ const buffer = Buffer.from(await response.arrayBuffer());
65
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
66
+ fs.writeFileSync(destination, buffer);
67
+ }
68
+
69
+ function findBinary(root, binaryName) {
70
+ const entries = fs.readdirSync(root, { withFileTypes: true });
71
+ for (const entry of entries) {
72
+ const fullPath = path.join(root, entry.name);
73
+ if (entry.isDirectory()) {
74
+ const nested = findBinary(fullPath, binaryName);
75
+ if (nested) {
76
+ return nested;
77
+ }
78
+ } else if (entry.name === binaryName) {
79
+ return fullPath;
80
+ }
81
+ }
82
+ return null;
83
+ }
84
+
85
+ async function extractArchive(archivePath, destination, target) {
86
+ fs.rmSync(destination, { recursive: true, force: true });
87
+ fs.mkdirSync(destination, { recursive: true });
88
+ if (target.extension === ".zip") {
89
+ await spawnFile("powershell", [
90
+ "-NoLogo",
91
+ "-NoProfile",
92
+ "-ExecutionPolicy",
93
+ "Bypass",
94
+ "-Command",
95
+ "Expand-Archive -LiteralPath $args[0] -DestinationPath $args[1] -Force",
96
+ archivePath,
97
+ destination
98
+ ]);
99
+ } else {
100
+ await spawnFile("tar", ["-xzf", archivePath, "-C", destination]);
101
+ }
102
+ }
103
+
104
+ async function installFromRelease(target, installDir, options = {}) {
105
+ const baseUrl = releaseBaseUrl();
106
+ const archiveUrl = `${baseUrl}/${target.archive}`;
107
+ const checksumUrl = `${archiveUrl}.sha256`;
108
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "ledgerful-mcp-"));
109
+ try {
110
+ const archivePath = path.join(tempDir, target.archive);
111
+ const checksumPath = `${archivePath}.sha256`;
112
+ await downloadToFile(archiveUrl, archivePath);
113
+ await downloadToFile(checksumUrl, checksumPath);
114
+
115
+ const expected = parseChecksum(fs.readFileSync(checksumPath, "utf8"));
116
+ const actual = sha256File(archivePath);
117
+ if (actual !== expected) {
118
+ throw new Error(`checksum mismatch for ${target.archive}: expected ${expected}, got ${actual}`);
119
+ }
120
+
121
+ const extractDir = path.join(tempDir, "extract");
122
+ await extractArchive(archivePath, extractDir, target);
123
+ const extractedBinary = findBinary(extractDir, target.binary);
124
+ if (!extractedBinary) {
125
+ throw new Error(`archive ${target.archive} did not contain ${target.binary}`);
126
+ }
127
+
128
+ fs.mkdirSync(installDir, { recursive: true });
129
+ const installedBinary = path.join(installDir, target.binary);
130
+ fs.copyFileSync(extractedBinary, installedBinary);
131
+ if (process.platform !== "win32") {
132
+ fs.chmodSync(installedBinary, 0o755);
133
+ }
134
+ return installedBinary;
135
+ } catch (error) {
136
+ if (!options.quiet) {
137
+ console.error(`ledgerful-mcp: ${error.message}`);
138
+ }
139
+ throw error;
140
+ } finally {
141
+ fs.rmSync(tempDir, { recursive: true, force: true });
142
+ }
143
+ }
144
+
145
+ async function ensureBinary(options = {}) {
146
+ if (process.env.LEDGERFUL_MCP_BIN_OVERRIDE) {
147
+ const override = path.resolve(process.env.LEDGERFUL_MCP_BIN_OVERRIDE);
148
+ if (!fs.existsSync(override)) {
149
+ throw new Error(`LEDGERFUL_MCP_BIN_OVERRIDE does not exist: ${override}`);
150
+ }
151
+ return override;
152
+ }
153
+
154
+ const target = resolveTarget();
155
+ const installDir = path.join(cacheRoot(), packageVersion(), target.asset);
156
+ const binaryPath = path.join(installDir, target.binary);
157
+ if (fs.existsSync(binaryPath)) {
158
+ return binaryPath;
159
+ }
160
+ return installFromRelease(target, installDir, options);
161
+ }
162
+
163
+ module.exports = {
164
+ cacheRoot,
165
+ ensureBinary,
166
+ installFromRelease,
167
+ packageVersion,
168
+ parseChecksum,
169
+ releaseBaseUrl,
170
+ sha256File
171
+ };
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ const TARGETS = {
4
+ "linux:x64": {
5
+ asset: "ledgerful-x86_64-unknown-linux-gnu",
6
+ extension: ".tar.gz",
7
+ binary: "ledgerful"
8
+ },
9
+ "win32:x64": {
10
+ asset: "ledgerful-x86_64-pc-windows-msvc",
11
+ extension: ".zip",
12
+ binary: "ledgerful.exe"
13
+ },
14
+ "darwin:x64": {
15
+ asset: "ledgerful-x86_64-apple-darwin",
16
+ extension: ".tar.gz",
17
+ binary: "ledgerful"
18
+ },
19
+ "darwin:arm64": {
20
+ asset: "ledgerful-aarch64-apple-darwin",
21
+ extension: ".tar.gz",
22
+ binary: "ledgerful"
23
+ }
24
+ };
25
+
26
+ function resolveTarget(platform = process.platform, arch = process.arch) {
27
+ const key = `${platform}:${arch}`;
28
+ const target = TARGETS[key];
29
+ if (!target) {
30
+ const supported = Object.keys(TARGETS).join(", ");
31
+ throw new Error(`unsupported platform ${key}; supported targets: ${supported}`);
32
+ }
33
+ return { ...target, key, archive: `${target.asset}${target.extension}` };
34
+ }
35
+
36
+ module.exports = { TARGETS, resolveTarget };
package/lib/process.js ADDED
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ const { spawn } = require("node:child_process");
4
+
5
+ function spawnFile(command, args, options = {}) {
6
+ return new Promise((resolve, reject) => {
7
+ const child = spawn(command, args, {
8
+ stdio: options.stdio || "pipe",
9
+ windowsHide: true,
10
+ ...options
11
+ });
12
+ let stderr = "";
13
+ child.stderr?.on("data", (chunk) => {
14
+ stderr += chunk.toString();
15
+ });
16
+ child.on("error", reject);
17
+ child.on("exit", (code) => {
18
+ if (code === 0) {
19
+ resolve();
20
+ return;
21
+ }
22
+ reject(new Error(`${command} exited with ${code}${stderr ? `: ${stderr.trim()}` : ""}`));
23
+ });
24
+ });
25
+ }
26
+
27
+ module.exports = { spawnFile };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@ledgerful/mcp-server",
3
+ "version": "0.1.8",
4
+ "description": "Ledgerful MCP stdio server wrapper for AI coding agents",
5
+ "license": "SEE LICENSE IN LICENSE",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Ryan-AI-Studios/Ledgerful.git",
9
+ "directory": "mcp-server"
10
+ },
11
+ "homepage": "https://github.com/Ryan-AI-Studios/Ledgerful#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/Ryan-AI-Studios/Ledgerful/issues"
14
+ },
15
+ "bin": {
16
+ "ledgerful-mcp": "bin/ledgerful-mcp.js"
17
+ },
18
+ "files": [
19
+ "bin/",
20
+ "lib/",
21
+ "scripts/",
22
+ "README.md",
23
+ "LICENSE",
24
+ "COMMERCIAL-EXCEPTION.md",
25
+ "BINARY-LICENSE-NOTICE.md"
26
+ ],
27
+ "scripts": {
28
+ "postinstall": "node scripts/postinstall.js",
29
+ "test": "node --test test/*.test.js",
30
+ "smoke:local": "node test/smoke-local.js",
31
+ "pack:dry": "npm pack --dry-run"
32
+ },
33
+ "engines": {
34
+ "node": ">=18.18"
35
+ }
36
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ const { ensureBinary } = require("../lib/install");
4
+
5
+ if (process.env.LEDGERFUL_MCP_SKIP_DOWNLOAD === "1" || process.env.LEDGERFUL_MCP_BIN_OVERRIDE) {
6
+ process.exit(0);
7
+ }
8
+
9
+ ensureBinary({ quiet: true }).catch((error) => {
10
+ console.warn(`ledgerful-mcp: binary prefetch skipped: ${error.message}`);
11
+ console.warn("ledgerful-mcp: the first run will retry the download unless LEDGERFUL_MCP_BIN_OVERRIDE is set.");
12
+ });