rowpipe 2.10.2 → 2.10.4

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.
package/README.md CHANGED
@@ -56,14 +56,14 @@ brew install litepacks/rowpipe/rowpipe
56
56
 
57
57
  #### 📦 Debian / Ubuntu (`apt` / `.deb`)
58
58
  ```bash
59
- curl -sLO https://github.com/litepacks/rowpipe/releases/latest/download/rowpipe_2.10.1_amd64.deb
60
- sudo apt install -y ./rowpipe_2.10.1_amd64.deb
59
+ curl -sLO https://github.com/litepacks/rowpipe/releases/latest/download/rowpipe_2.10.4_amd64.deb
60
+ sudo apt install -y ./rowpipe_2.10.4_amd64.deb
61
61
  ```
62
62
 
63
63
  #### 🪟 Windows & GitHub Releases
64
64
  Pre-compiled standalone binaries for **macOS (Apple Silicon)**, **Linux (x64)**, and **Windows (x64)** are available on the [GitHub Releases](https://github.com/litepacks/rowpipe/releases) page:
65
65
  * `rowpipe-darwin-arm64.tar.gz` (macOS Apple Silicon M1/M2/M3/M4)
66
- * `rowpipe-linux-x64.tar.gz` / `rowpipe_2.10.1_amd64.deb` (Linux)
66
+ * `rowpipe-linux-x64.tar.gz` / `rowpipe_2.10.4_amd64.deb` (Linux)
67
67
  * `rowpipe-win32-x64.zip` (Windows)
68
68
 
69
69
  ---
@@ -83,6 +83,126 @@ npm install rowpipe
83
83
 
84
84
  ---
85
85
 
86
+ ## Model Context Protocol (MCP) Server
87
+
88
+ Rowpipe includes a native, production-ready **Model Context Protocol (MCP)** server powered by `mcponce`, enabling AI coding assistants and agents (Claude Desktop, Cursor, Antigravity, OpenDevin, etc.) to inspect, query, transform, convert, and diff massive tabular datasets with bounded $O(1)$ memory.
89
+
90
+ ### 🤖 9 Core Tabular Tools
91
+ 1. **`rowpipe_inspect`**: Inspect file size, row/column counts, types, null percentages, approximate distinct rates, and XLSX sheet breakdowns.
92
+ 2. **`rowpipe_query`**: Stream-query with filter expressions, column selection, renaming, maps, casting, sorting, and pagination.
93
+ 3. **`rowpipe_schema`**: Infer accurate schemas, SQL data types, null rates, and semantic types (`email`, `url`, `uuid`, etc.).
94
+ 4. **`rowpipe_stats`**: Calculate summary statistics (min, max, mean, sum, quantiles, approx distinct) for numeric and string columns.
95
+ 5. **`rowpipe_sample`**: Reservoir sampling with bounded $O(k)$ memory and deterministic random seeds.
96
+ 6. **`rowpipe_convert`**: High-throughput format conversion across CSV, TSV, JSON, JSONL, Parquet, XLSX, and Markdown.
97
+ 7. **`rowpipe_diff`**: Key-based row-level dataset diffing with added/removed/changed metrics and schema diffing.
98
+ 8. **`rowpipe_profile`**: Deep data profiling, distributions, and quality warnings.
99
+ 9. **`rowpipe_table`**: Render clean, aligned Unicode/ASCII preview tables.
100
+
101
+ ### 🌐 Dynamic Resource Templates
102
+ - `rowpipe://metadata/{filePath}`: Returns dataset metadata, size, format, and sheet summaries.
103
+ - `rowpipe://schema/{filePath}`: Returns inferred schema and semantic classifications.
104
+
105
+ ### 💻 MCP CLI Usage
106
+ ```bash
107
+ # Start standard MCP stdio server
108
+ rowpipe mcp
109
+
110
+ # List all registered tools and parameter schemas
111
+ rowpipe mcp tools
112
+
113
+ # Execute any tool directly from CLI
114
+ rowpipe mcp call rowpipe_inspect --filePath ./sales.csv
115
+ rowpipe mcp call rowpipe_query --filePath ./sales.csv --filter "revenue > 1000" --select "name,revenue"
116
+
117
+ # Run in background daemon mode
118
+ rowpipe mcp -b
119
+
120
+ # Install into Claude Desktop or Cursor configuration automatically
121
+ rowpipe mcp install claude
122
+ rowpipe mcp install cursor
123
+
124
+ # Check server status and view logs
125
+ rowpipe mcp status
126
+ rowpipe mcp logs
127
+ ```
128
+
129
+ ### ⚙️ Manual MCP Client Configuration
130
+
131
+ You can configure `rowpipe` manually in any MCP-compatible client:
132
+
133
+ #### 1. Claude Desktop
134
+ Add `rowpipe` under `mcpServers` in your Claude Desktop configuration file:
135
+ * **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
136
+ * **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
137
+ * **Linux**: `~/.config/Claude/claude_desktop_config.json`
138
+
139
+ **Using installed `rowpipe` binary (Standalone or Global npm):**
140
+ ```json
141
+ {
142
+ "mcpServers": {
143
+ "rowpipe": {
144
+ "command": "rowpipe",
145
+ "args": ["mcp"]
146
+ }
147
+ }
148
+ }
149
+ ```
150
+
151
+ **Using `npx` (No installation needed):**
152
+ ```json
153
+ {
154
+ "mcpServers": {
155
+ "rowpipe": {
156
+ "command": "npx",
157
+ "args": ["-y", "rowpipe", "mcp"]
158
+ }
159
+ }
160
+ }
161
+ ```
162
+
163
+ #### 2. Cursor
164
+ * **UI**: Go to **Settings** (`Cmd+,` or `Ctrl+,`) → **Features** → **MCP Servers** → **Add New MCP Server**:
165
+ * **Type**: `command`
166
+ * **Name**: `rowpipe`
167
+ * **Command**: `rowpipe mcp` (or `npx -y rowpipe mcp`)
168
+ * **Project Configuration**: Create `.cursor/mcp.json` in your workspace root:
169
+ ```json
170
+ {
171
+ "mcpServers": {
172
+ "rowpipe": {
173
+ "command": "rowpipe",
174
+ "args": ["mcp"]
175
+ }
176
+ }
177
+ }
178
+ ```
179
+
180
+ #### 3. Windsurf, Antigravity & VS Code (Cline / Roo Code)
181
+ Add to your client's MCP settings (`mcp_config.json` or `cline_mcp_settings.json`):
182
+ ```json
183
+ {
184
+ "mcpServers": {
185
+ "rowpipe": {
186
+ "command": "rowpipe",
187
+ "args": ["mcp"]
188
+ }
189
+ }
190
+ }
191
+ ```
192
+
193
+ ### 📦 Programmatic Usage (Node.js / TypeScript)
194
+ ```typescript
195
+ import { createRowpipeMcpServer } from "rowpipe";
196
+
197
+ const server = createRowpipeMcpServer();
198
+ const result = await server.callTool("rowpipe_inspect", {
199
+ filePath: "./large_dataset.parquet"
200
+ });
201
+ console.log(result.data);
202
+ ```
203
+
204
+ ---
205
+
86
206
  ## CLI Usage & Examples
87
207
 
88
208
  ### 1. Inspect Dataset & Multi-Sheet Excel / Parquet Analysis
@@ -0,0 +1,17 @@
1
+ export interface McpCliCommandOptions {
2
+ background?: boolean;
3
+ dev?: boolean;
4
+ }
5
+ /**
6
+ * Handles `rowpipe mcp [args...]`
7
+ *
8
+ * Forwards arguments to the mcponce MCP application runner, enabling:
9
+ * - stdio bridge mode (`rowpipe mcp`)
10
+ * - daemon background mode (`rowpipe mcp --background`)
11
+ * - developer mode with stderr logging (`rowpipe mcp --dev`)
12
+ * - tool listings and cli invocations (`rowpipe mcp tools`, `rowpipe mcp call ...`)
13
+ * - client installation (`rowpipe mcp install claude`, etc.)
14
+ * - server status, logs, stop, restart (`rowpipe mcp status`, `rowpipe mcp logs`, etc.)
15
+ */
16
+ export declare function mcpCommand(args?: string[]): Promise<void>;
17
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/mcp.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BnE"}
@@ -0,0 +1,40 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import { createRowpipeMcpServer } from "../../mcp/server.js";
3
+ /**
4
+ * Handles `rowpipe mcp [args...]`
5
+ *
6
+ * Forwards arguments to the mcponce MCP application runner, enabling:
7
+ * - stdio bridge mode (`rowpipe mcp`)
8
+ * - daemon background mode (`rowpipe mcp --background`)
9
+ * - developer mode with stderr logging (`rowpipe mcp --dev`)
10
+ * - tool listings and cli invocations (`rowpipe mcp tools`, `rowpipe mcp call ...`)
11
+ * - client installation (`rowpipe mcp install claude`, etc.)
12
+ * - server status, logs, stop, restart (`rowpipe mcp status`, `rowpipe mcp logs`, etc.)
13
+ */
14
+ export async function mcpCommand(args = []) {
15
+ const mcpEntrypoint = fileURLToPath(new URL("../../mcp/index.js", import.meta.url));
16
+ const app = createRowpipeMcpServer({
17
+ name: "rowpipe",
18
+ background: args.includes("--background") || args.includes("-b"),
19
+ });
20
+ // Adjust process.argv for mcponce CLI parsing
21
+ // mcponce inspects process.argv.slice(2)
22
+ const nodeExec = process.argv[0] ?? process.execPath;
23
+ const mcpIdx = process.argv.findIndex((a) => a === "mcp");
24
+ if (mcpIdx !== -1) {
25
+ process.argv = [
26
+ nodeExec,
27
+ mcpEntrypoint,
28
+ ...process.argv.slice(mcpIdx + 1),
29
+ ];
30
+ }
31
+ else {
32
+ process.argv = [
33
+ nodeExec,
34
+ mcpEntrypoint,
35
+ ...args,
36
+ ];
37
+ }
38
+ await app.run();
39
+ }
40
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../../src/cli/commands/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAO7D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAiB,EAAE;IAClD,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAEpF,MAAM,GAAG,GAAG,sBAAsB,CAAC;QACjC,IAAI,EAAE,SAAS;QACf,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;KACjE,CAAC,CAAC;IAEH,8CAA8C;IAC9C,yCAAyC;IACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC;IAC1D,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,GAAG;YACb,QAAQ;YACR,aAAa;YACb,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;SAClC,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,GAAG;YACb,QAAQ;YACR,aAAa;YACb,GAAG,IAAI;SACR,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC;AAClB,CAAC"}
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ export declare function getCliVersion(): string;
3
+ export declare function isStdinInteractive(): boolean;
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AA+FA,wBAAgB,aAAa,IAAI,MAAM,CAWtC;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAa5C"}
package/dist/cli/index.js CHANGED
@@ -10,8 +10,9 @@ process.emitWarning = function (warning, ...args) {
10
10
  }
11
11
  return Reflect.apply(_origEmitWarning, process, [warning, ...args]);
12
12
  };
13
- import { existsSync } from "node:fs";
13
+ import { existsSync, readFileSync, fstatSync } from "node:fs";
14
14
  import { Command } from "commander";
15
+ import { VERSION } from "../version.js";
15
16
  import { RowpipeError } from "../core/errors.js";
16
17
  import { castCommand } from "./commands/cast.js";
17
18
  import { cleanCommand } from "./commands/clean.js";
@@ -77,6 +78,7 @@ import { testCommand } from "./commands/test.js";
77
78
  import { serveCommand } from "./commands/serve.js";
78
79
  import { reportCommand } from "./commands/report.js";
79
80
  import { fetchCommand } from "./commands/fetch.js";
81
+ import { mcpCommand } from "./commands/mcp.js";
80
82
  // Handle broken pipe gracefully when piping to head/less
81
83
  process.stdout.on("error", (err) => {
82
84
  if (err.code === "EPIPE") {
@@ -84,10 +86,89 @@ process.stdout.on("error", (err) => {
84
86
  }
85
87
  });
86
88
  const program = new Command();
89
+ export function getCliVersion() {
90
+ try {
91
+ const pkgUrl = new URL("../../package.json", import.meta.url);
92
+ if (existsSync(pkgUrl)) {
93
+ const pkg = JSON.parse(readFileSync(pkgUrl, "utf-8"));
94
+ if (pkg.version)
95
+ return pkg.version;
96
+ }
97
+ }
98
+ catch {
99
+ // fallback
100
+ }
101
+ return VERSION;
102
+ }
103
+ export function isStdinInteractive() {
104
+ if (process.stdin.isTTY) {
105
+ return true;
106
+ }
107
+ try {
108
+ const stat = fstatSync(0);
109
+ if (stat.isCharacterDevice() && !stat.isFIFO() && !stat.isFile() && !stat.isSocket()) {
110
+ return true;
111
+ }
112
+ }
113
+ catch {
114
+ // ignore
115
+ }
116
+ return false;
117
+ }
118
+ const currentVersion = getCliVersion();
87
119
  program
88
120
  .name("rowpipe")
89
- .description("Stream-first tabular data toolkit for CSV, TSV, JSON, JSONL, XLSX, Parquet, and Markdown")
90
- .version("2.10.0");
121
+ .description("Stream-first tabular data toolkit for CSV, TSV, JSON, JSONL, XLSX, Apache Parquet, and Markdown")
122
+ .version(currentVersion, "-v, --version", "Output the current version")
123
+ .option("-V", "Output the current version", () => {
124
+ console.log(currentVersion);
125
+ process.exit(0);
126
+ });
127
+ program
128
+ .command("version")
129
+ .description("Output version information")
130
+ .action(() => {
131
+ console.log(currentVersion);
132
+ process.exit(0);
133
+ });
134
+ program.hook("preAction", (thisCommand, actionCommand) => {
135
+ const isRoot = actionCommand === program || actionCommand.name() === "rowpipe";
136
+ const firstArg = actionCommand.args[0];
137
+ // If explicit empty string argument was passed (e.g. rowpipe "" or rowpipe inspect "")
138
+ if (firstArg !== undefined && typeof firstArg === "string" && firstArg.trim() === "") {
139
+ actionCommand.outputHelp();
140
+ process.exit(0);
141
+ }
142
+ // If interactive terminal (no piped stdin data), prevent hanging waiting for stdin
143
+ if (isStdinInteractive()) {
144
+ if (isRoot) {
145
+ if (!firstArg || firstArg === "-") {
146
+ actionCommand.outputHelp();
147
+ process.exit(0);
148
+ }
149
+ }
150
+ else {
151
+ const nonStreamCommands = new Set([
152
+ "db",
153
+ "diff",
154
+ "diff-files",
155
+ "join",
156
+ "fuzzy-join",
157
+ "concat",
158
+ "generate",
159
+ "completion",
160
+ "version",
161
+ "fetch",
162
+ ]);
163
+ if (!nonStreamCommands.has(actionCommand.name())) {
164
+ if (!firstArg || firstArg === "-") {
165
+ actionCommand.outputHelp();
166
+ process.exit(0);
167
+ }
168
+ }
169
+ }
170
+ }
171
+ });
91
172
  // Global & Pipeline options on root command
92
173
  program
93
174
  .argument("[input]", "Input dataset file path or '-' for stdin")
@@ -149,10 +230,16 @@ program
149
230
  .option("--on-error <strategy>", "Error handling strategy: abort (default), skip, or log", "abort")
150
231
  .option("--bad-rows-log <file>", "Write malformed or rejected rows to dead-letter log file")
151
232
  .action(async (input = "-", cmdOptions) => {
152
- // If running root command with no input file and stdin is an interactive TTY, display help
153
- if (input === "-" && process.stdin.isTTY) {
154
- program.outputHelp();
155
- return;
233
+ const rawInput = typeof input === "string" ? input.trim() : "";
234
+ if (!rawInput || rawInput === "-") {
235
+ if (isStdinInteractive()) {
236
+ program.outputHelp();
237
+ return;
238
+ }
239
+ input = "-";
240
+ }
241
+ else {
242
+ input = rawInput;
156
243
  }
157
244
  await unifiedPipelineCommand(input, cmdOptions);
158
245
  });
@@ -1569,6 +1656,14 @@ program
1569
1656
  opts.maxPages = parseInt(cmdOptions.maxPages, 10);
1570
1657
  await fetchCommand(url, opts);
1571
1658
  });
1659
+ // 65. mcp
1660
+ program
1661
+ .command("mcp [args...]")
1662
+ .description("Model Context Protocol (MCP) server for Claude Desktop, Cursor, Antigravity, and AI agents")
1663
+ .allowUnknownOption(true)
1664
+ .action(async (args) => {
1665
+ await mcpCommand(args || []);
1666
+ });
1572
1667
  async function main() {
1573
1668
  if (process.argv.length <= 2 && process.stdin.isTTY) {
1574
1669
  program.outputHelp();