@pi-unipi/mcp 2.6.1 → 2.6.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/mcp",
3
- "version": "2.6.1",
3
+ "version": "2.6.2",
4
4
  "description": "MCP server management extension for Pi coding agent — browse, add, configure, and use MCP servers",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -41,8 +41,12 @@
41
41
  "@types/node": "^25.6.0"
42
42
  },
43
43
  "pi": {
44
- "extensions": [],
45
- "skills": [],
44
+ "extensions": [
45
+ "./src/index.ts"
46
+ ],
47
+ "skills": [
48
+ "./skills"
49
+ ],
46
50
  "prompts": [],
47
51
  "themes": []
48
52
  }
@@ -47,8 +47,6 @@ interface PendingRequest {
47
47
  export interface McpClientOptions {
48
48
  /** Per-request timeout in ms (default: MCP_DEFAULTS.STARTUP_TIMEOUT_MS) */
49
49
  timeoutMs?: number;
50
- /** Working directory for the spawned process */
51
- cwd?: string;
52
50
  }
53
51
 
54
52
  /**
@@ -65,11 +63,9 @@ export class McpClient {
65
63
  private connected = false;
66
64
  private stderrBuffer = "";
67
65
  private readonly timeoutMs: number;
68
- private readonly cwd?: string;
69
66
 
70
67
  constructor(options?: McpClientOptions) {
71
68
  this.timeoutMs = options?.timeoutMs ?? MCP_DEFAULTS.STARTUP_TIMEOUT_MS;
72
- this.cwd = options?.cwd;
73
69
  }
74
70
 
75
71
  /**
@@ -91,7 +87,6 @@ export class McpClient {
91
87
  this.process = spawn(command, args, {
92
88
  stdio: ["pipe", "pipe", "pipe"],
93
89
  env: mergedEnv,
94
- cwd: this.cwd,
95
90
  });
96
91
 
97
92
  this.process.on("error", (err) => {
@@ -230,21 +225,11 @@ export class McpClient {
230
225
  this.cleanup();
231
226
  }
232
227
 
233
- /** Whether the client is currently connected */
234
- get isConnected(): boolean {
235
- return this.connected;
236
- }
237
-
238
228
  /** Process ID of the spawned MCP server, or undefined if not connected */
239
229
  get pid(): number | undefined {
240
230
  return this.process?.pid;
241
231
  }
242
232
 
243
- /** Captured stderr output */
244
- get stderr(): string {
245
- return this.stderrBuffer;
246
- }
247
-
248
233
  // ── Internal methods ────────────────────────────────────────────
249
234
 
250
235
  private ensureConnected(): void {
@@ -11,7 +11,6 @@ import * as os from "node:os";
11
11
  import type {
12
12
  McpConfig,
13
13
  McpMetadata,
14
- McpAuth,
15
14
  ResolvedServer,
16
15
  ServerSource,
17
16
  } from "../types.js";
@@ -123,15 +122,6 @@ export function loadMetadata(dir: string): McpMetadata {
123
122
  };
124
123
  }
125
124
 
126
- /**
127
- * Load auth data (auth.json) from a directory.
128
- * Returns empty object if file doesn't exist.
129
- */
130
- export function loadAuth(dir: string): McpAuth {
131
- const filePath = path.join(dir, "auth.json");
132
- return readJsonFile<McpAuth>(filePath) ?? {};
133
- }
134
-
135
125
  // ── Config saving ─────────────────────────────────────────────────
136
126
 
137
127
  /**
@@ -150,14 +140,6 @@ export function saveMetadata(dir: string, meta: McpMetadata): void {
150
140
  writeJsonFile(filePath, meta);
151
141
  }
152
142
 
153
- /**
154
- * Save auth data (auth.json) with chmod 600.
155
- */
156
- export function saveAuth(dir: string, auth: McpAuth): void {
157
- const filePath = path.join(dir, "auth.json");
158
- writeJsonFile(filePath, auth, 0o600);
159
- }
160
-
161
143
  // ── Config merging ────────────────────────────────────────────────
162
144
 
163
145
  /**
@@ -220,26 +202,6 @@ export function resolveServers(
220
202
  }));
221
203
  }
222
204
 
223
- /**
224
- * Merge auth.json env vars into a server definition at spawn time.
225
- * Auth env vars are added to the server's env, but don't override
226
- * explicitly set values in mcp-config.json.
227
- */
228
- export function mergeEnvWithAuth(
229
- serverDef: McpConfig["mcpServers"][string],
230
- auth: Record<string, string>,
231
- ): McpConfig["mcpServers"][string] {
232
- if (Object.keys(auth).length === 0) return serverDef;
233
-
234
- return {
235
- ...serverDef,
236
- env: {
237
- ...auth,
238
- ...(serverDef.env ?? {}),
239
- },
240
- };
241
- }
242
-
243
205
  /**
244
206
  * Load both global and project configs and resolve servers.
245
207
  * Convenience wrapper around the individual load + resolve functions.
@@ -85,30 +85,3 @@ export function validateMcpConfig(config: unknown): ValidationResult {
85
85
 
86
86
  return { valid: errors.length === 0, errors };
87
87
  }
88
-
89
- /**
90
- * Create a minimal server definition template for a new server.
91
- */
92
- export function createServerTemplate(
93
- name: string,
94
- command: string,
95
- args: string[],
96
- envVars?: string[],
97
- ): McpConfig {
98
- const env: Record<string, string> = {};
99
- if (envVars) {
100
- for (const v of envVars) {
101
- env[v] = "";
102
- }
103
- }
104
-
105
- return {
106
- mcpServers: {
107
- [name]: {
108
- command,
109
- args,
110
- env: Object.keys(env).length > 0 ? env : undefined,
111
- },
112
- },
113
- };
114
- }
@@ -319,15 +319,6 @@ function enrichWithInstallInfo(entries: CatalogEntry[]): CatalogEntry[] {
319
319
  });
320
320
  }
321
321
 
322
- /**
323
- * Check if enough time has passed since last sync.
324
- */
325
- function shouldSync(lastSyncAt: string | null, intervalMs: number): boolean {
326
- if (!lastSyncAt) return true;
327
- const elapsed = Date.now() - new Date(lastSyncAt).getTime();
328
- return elapsed >= intervalMs;
329
- }
330
-
331
322
  /**
332
323
  * Sync the MCP server catalog from GitHub.
333
324
  * Parses the awesome-mcp-servers README, enriches with install info,
@@ -394,23 +385,3 @@ export function loadCatalog(): CatalogData {
394
385
  };
395
386
  }
396
387
  }
397
-
398
- /**
399
- * Sync if enough time has passed since last sync.
400
- * Returns null if no sync was needed, or the catalog data if synced.
401
- */
402
- export async function syncIfNeeded(): Promise<CatalogData | null> {
403
- const configDir = getGlobalConfigDir();
404
- const meta = loadMetadata(configDir);
405
-
406
- if (!shouldSync(meta.sync.lastSyncAt, meta.sync.syncIntervalMs)) {
407
- return null;
408
- }
409
-
410
- try {
411
- return await syncCatalog();
412
- } catch {
413
- // Sync failed — return null, will use cached/seed data
414
- return null;
415
- }
416
- }
package/src/index.ts CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  } from "@pi-unipi/core";
17
17
  import type { ResolvedServer } from "./types.js";
18
18
  import { loadAndResolve, getGlobalConfigDir } from "./config/manager.js";
19
- import { syncCatalog, loadCatalog } from "./config/sync.js";
19
+ import { syncCatalog } from "./config/sync.js";
20
20
  import { ServerRegistry } from "./bridge/registry.js";
21
21
  import { compareCodeUnits } from "./bridge/translator.js";
22
22
  import { renderMcpAddOverlay } from "./tui/add-overlay.js";
@@ -353,7 +353,7 @@ export function renderMcpAddOverlay(params?: {
353
353
  return;
354
354
  }
355
355
  // Arrow keys + j/k navigate list while searching
356
- if (matchesKey(data, Key.down) || data === "\x1b[B" || data === "j") {
356
+ if (matchesKey(data, Key.down) || data === "j") {
357
357
  if (state.selectedIndex < state.filteredServers.length - 1) {
358
358
  state.selectedIndex++;
359
359
  ensureVisible();
@@ -361,7 +361,7 @@ export function renderMcpAddOverlay(params?: {
361
361
  }
362
362
  return;
363
363
  }
364
- if (matchesKey(data, Key.up) || data === "\x1b[A" || data === "k") {
364
+ if (matchesKey(data, Key.up) || data === "k") {
365
365
  if (state.selectedIndex > 0) {
366
366
  state.selectedIndex--;
367
367
  ensureVisible();
@@ -370,13 +370,13 @@ export function renderMcpAddOverlay(params?: {
370
370
  return;
371
371
  }
372
372
  // PgUp/PgDn also work in search
373
- if (data === "\x1b[6~") {
373
+ if (matchesKey(data, Key.pageDown)) {
374
374
  state.selectedIndex = Math.min(state.filteredServers.length - 1, state.selectedIndex + lastListHeight);
375
375
  ensureVisible();
376
376
  refresh();
377
377
  return;
378
378
  }
379
- if (data === "\x1b[5~") {
379
+ if (matchesKey(data, Key.pageUp)) {
380
380
  state.selectedIndex = Math.max(0, state.selectedIndex - lastListHeight);
381
381
  ensureVisible();
382
382
  refresh();
@@ -463,13 +463,13 @@ export function renderMcpAddOverlay(params?: {
463
463
  return;
464
464
  }
465
465
  // PageDown / PageUp
466
- if (data === "\x1b[6~") {
466
+ if (matchesKey(data, Key.pageDown)) {
467
467
  state.selectedIndex = Math.min(listLen - 1, state.selectedIndex + lastListHeight);
468
468
  ensureVisible();
469
469
  refresh();
470
470
  return;
471
471
  }
472
- if (data === "\x1b[5~") {
472
+ if (matchesKey(data, Key.pageUp)) {
473
473
  state.selectedIndex = Math.max(0, state.selectedIndex - lastListHeight);
474
474
  ensureVisible();
475
475
  refresh();
package/src/types.ts CHANGED
@@ -46,12 +46,6 @@ export interface McpMetadata {
46
46
  sync: SyncConfig;
47
47
  }
48
48
 
49
- /** Per-server auth data (auth.json) */
50
- export interface McpAuth {
51
- /** Map of server name → environment variable key-value pairs */
52
- [serverName: string]: Record<string, string>;
53
- }
54
-
55
49
  /** Single entry from the MCP server catalog */
56
50
  export interface CatalogEntry {
57
51
  /** Unique identifier (e.g. "github/github-mcp-server") */