@aipermission/mcp 0.2.32 → 0.2.34

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
@@ -42,7 +42,7 @@ The generated MCP config contains a bearer token. Keep it private. For project-l
42
42
  "mcpServers": {
43
43
  "aipermission": {
44
44
  "command": "npx",
45
- "args": ["-y", "@aipermission/mcp@0.2.32"],
45
+ "args": ["-y", "@aipermission/mcp@0.2.34"],
46
46
  "env": {
47
47
  "NODE_ENV": "production",
48
48
  "AIPERMISSION_API_URL": "http://localhost:3210",
package/dist/init.js CHANGED
@@ -1,13 +1,16 @@
1
1
  import fs from "node:fs/promises";
2
+ import { execFile } from "node:child_process";
2
3
  import { createRequire } from "node:module";
3
4
  import os from "node:os";
4
5
  import path from "node:path";
5
6
  import readline from "node:readline/promises";
7
+ import { promisify } from "node:util";
6
8
  import { pathToFileURL } from "node:url";
7
9
  import { stdin as input, stdout as output } from "node:process";
8
10
  import { DEFAULT_API_URL, normalizeLocalAPIURL } from "./local-url.js";
9
11
 
10
12
  const require = createRequire(import.meta.url);
13
+ const execFileAsync = promisify(execFile);
11
14
  const packageMetadata = require("../package.json");
12
15
 
13
16
  export const PACKAGE_NAME = packageMetadata.name;
@@ -68,6 +71,7 @@ const providers = [
68
71
 
69
72
  export async function runInit(argv = []) {
70
73
  const flags = parseFlags(argv);
74
+ assertProviderSelectionAvailable(flags.provider, Boolean(input.isTTY && output.isTTY));
71
75
  const stdinToken = flags.tokenStdin ? (await readStdin()).trim() : "";
72
76
  const rl = readline.createInterface({ input, output });
73
77
  try {
@@ -107,6 +111,12 @@ export async function runInit(argv = []) {
107
111
  }
108
112
  }
109
113
 
114
+ export function assertProviderSelectionAvailable(provider, interactive) {
115
+ if (!provider && !interactive) {
116
+ throw new Error("Non-interactive setup requires an explicit --provider.");
117
+ }
118
+ }
119
+
110
120
  export function parseFlags(argv) {
111
121
  const result = {};
112
122
  for (let i = 0; i < argv.length; i += 1) {
@@ -403,15 +413,15 @@ async function assertProjectConfigWritable(filePath, options = {}) {
403
413
  }
404
414
 
405
415
  async function protectGitIgnoredConfig(filePath) {
406
- const gitRoot = await findGitRoot(process.cwd());
407
- if (!gitRoot) {
416
+ const repository = await discoverGitRepository(process.cwd());
417
+ if (!repository) {
408
418
  return {};
409
419
  }
410
- const relativePath = path.relative(gitRoot, filePath).split(path.sep).join("/");
420
+ const relativePath = path.relative(repository.workTree, filePath).split(path.sep).join("/");
411
421
  if (relativePath.startsWith("../") || path.isAbsolute(relativePath)) {
412
422
  return {};
413
423
  }
414
- const excludePath = path.join(gitRoot, ".git", "info", "exclude");
424
+ const excludePath = path.join(repository.gitDir, "info", "exclude");
415
425
  let current = "";
416
426
  try {
417
427
  current = await fs.readFile(excludePath, "utf8");
@@ -434,54 +444,36 @@ async function protectGitIgnoredConfig(filePath) {
434
444
  }
435
445
 
436
446
  async function gitTrackedPath(filePath) {
437
- const gitRoot = await findGitRoot(process.cwd());
438
- if (!gitRoot) {
447
+ const repository = await discoverGitRepository(process.cwd());
448
+ if (!repository) {
439
449
  return "";
440
450
  }
441
- const relativePath = path.relative(gitRoot, filePath).split(path.sep).join("/");
451
+ const relativePath = path.relative(repository.workTree, filePath).split(path.sep).join("/");
442
452
  if (relativePath.startsWith("../") || path.isAbsolute(relativePath)) {
443
453
  return "";
444
454
  }
445
- const gitDir = path.join(gitRoot, ".git");
446
- const args = ["--git-dir", gitDir, "--work-tree", gitRoot, "ls-files", "--error-unmatch", "--", relativePath];
447
455
  try {
448
- const { spawn } = await import("node:child_process");
449
- await new Promise((resolve, reject) => {
450
- const child = spawn("git", args, { stdio: "ignore" });
451
- child.on("error", reject);
452
- child.on("exit", (code) => {
453
- if (code === 0) {
454
- resolve();
455
- return;
456
- }
457
- reject(Object.assign(new Error("not tracked"), { code }));
458
- });
459
- });
456
+ await execFileAsync("git", ["-C", repository.workTree, "ls-files", "--error-unmatch", "--", relativePath], { windowsHide: true });
460
457
  return relativePath;
461
458
  } catch {
462
459
  return "";
463
460
  }
464
461
  }
465
462
 
466
- async function findGitRoot(startDir) {
467
- let current = path.resolve(startDir);
468
- for (;;) {
469
- const gitPath = path.join(current, ".git");
470
- try {
471
- const stat = await fs.stat(gitPath);
472
- if (stat.isDirectory()) {
473
- return current;
474
- }
475
- } catch (error) {
476
- if (error.code !== "ENOENT") {
477
- return null;
478
- }
479
- }
480
- const parent = path.dirname(current);
481
- if (parent === current) {
463
+ async function discoverGitRepository(startDir) {
464
+ try {
465
+ const { stdout } = await execFileAsync(
466
+ "git",
467
+ ["-C", path.resolve(startDir), "rev-parse", "--show-toplevel", "--absolute-git-dir"],
468
+ { encoding: "utf8", windowsHide: true }
469
+ );
470
+ const [workTree, gitDir] = stdout.trim().split(/\r?\n/);
471
+ if (!workTree || !gitDir) {
482
472
  return null;
483
473
  }
484
- current = parent;
474
+ return { workTree: path.resolve(workTree), gitDir: path.resolve(gitDir) };
475
+ } catch {
476
+ return null;
485
477
  }
486
478
  }
487
479
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aipermission/mcp",
3
- "version": "0.2.32",
3
+ "version": "0.2.34",
4
4
  "mcpName": "io.github.aipermission/aipermission-mcp",
5
5
  "description": "Local-first MCP bridge for the aipermission gateway.",
6
6
  "license": "AGPL-3.0-only",
package/server.json CHANGED
@@ -3,12 +3,12 @@
3
3
  "name": "io.github.aipermission/aipermission-mcp",
4
4
  "title": "AIPermission",
5
5
  "description": "Local-first MCP bridge for the AIPermission gateway.",
6
- "version": "0.2.32",
6
+ "version": "0.2.34",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "identifier": "@aipermission/mcp",
11
- "version": "0.2.32",
11
+ "version": "0.2.34",
12
12
  "transport": {
13
13
  "type": "stdio"
14
14
  }