@evantahler/mcpcli 0.4.0 → 0.5.1

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.
@@ -90,3 +90,4 @@ mcpcli deauth <server> # remove stored auth
90
90
  | `mcpcli add <name> --command <cmd>` | Add a stdio MCP server |
91
91
  | `mcpcli add <name> --url <url>` | Add an HTTP MCP server |
92
92
  | `mcpcli remove <name>` | Remove an MCP server |
93
+ | `mcpcli skill install --claude` | Install mcpcli skill for Claude |
package/README.md CHANGED
@@ -68,6 +68,7 @@ mcpcli search -q "manage pull requests"
68
68
  | `mcpcli add <name> --command <cmd>` | Add a stdio MCP server to your config |
69
69
  | `mcpcli add <name> --url <url>` | Add an HTTP MCP server to your config |
70
70
  | `mcpcli remove <name>` | Remove an MCP server from your config |
71
+ | `mcpcli skill install --claude` | Install the mcpcli skill for Claude Code |
71
72
 
72
73
  ## Options
73
74
 
@@ -134,7 +135,7 @@ mcpcli remove my-api --dry-run
134
135
 
135
136
  ## Configuration
136
137
 
137
- Config lives in `~/.config/mcpcli/` (or the current directory). Three files:
138
+ Config lives in `~/.mcpcli/` (or the current directory). Three files:
138
139
 
139
140
  ### `servers.json` — MCP Server Definitions
140
141
 
@@ -231,18 +232,18 @@ Scenarios and keywords are extracted heuristically from tool names and descripti
231
232
  1. `MCP_CONFIG_PATH` environment variable
232
233
  2. `-c / --config` flag
233
234
  3. `./servers.json` (current directory)
234
- 4. `~/.config/mcpcli/servers.json`
235
+ 4. `~/.mcpcli/servers.json`
235
236
 
236
237
  ## Environment Variables
237
238
 
238
- | Variable | Purpose | Default |
239
- | ----------------- | --------------------------- | ------------------- |
240
- | `MCP_CONFIG_PATH` | Config directory path | `~/.config/mcpcli/` |
241
- | `MCP_DEBUG` | Enable debug output | `false` |
242
- | `MCP_TIMEOUT` | Request timeout (seconds) | `1800` |
243
- | `MCP_CONCURRENCY` | Parallel server connections | `5` |
244
- | `MCP_MAX_RETRIES` | Retry attempts | `3` |
245
- | `MCP_STRICT_ENV` | Error on missing `${VAR}` | `true` |
239
+ | Variable | Purpose | Default |
240
+ | ----------------- | --------------------------- | ------------ |
241
+ | `MCP_CONFIG_PATH` | Config directory path | `~/.mcpcli/` |
242
+ | `MCP_DEBUG` | Enable debug output | `false` |
243
+ | `MCP_TIMEOUT` | Request timeout (seconds) | `1800` |
244
+ | `MCP_CONCURRENCY` | Parallel server connections | `5` |
245
+ | `MCP_MAX_RETRIES` | Retry attempts | `3` |
246
+ | `MCP_STRICT_ENV` | Error on missing `${VAR}` | `true` |
246
247
 
247
248
  ## OAuth Flow
248
249
 
@@ -405,11 +406,20 @@ cat params.json | mcpcli exec server tool
405
406
 
406
407
  ### Claude Code Skill
407
408
 
408
- mcpcli ships a Claude Code skill at `skills/mcpcli.md` that teaches Claude Code how to discover and use MCP tools. Install it:
409
+ mcpcli ships a Claude Code skill at `.claude/skills/mcpcli.md` that teaches Claude Code how to discover and use MCP tools. Install it:
409
410
 
410
411
  ```bash
411
- # Copy the skill to your global Claude Code skills
412
- cp skills/mcpcli.md ~/.claude/skills/mcpcli.md
412
+ # Install to the current project (.claude/skills/mcpcli.md)
413
+ mcpcli skill install --claude
414
+
415
+ # Install globally (~/.claude/skills/mcpcli.md)
416
+ mcpcli skill install --claude --global
417
+
418
+ # Install to both locations
419
+ mcpcli skill install --claude --global --project
420
+
421
+ # Overwrite an existing skill file
422
+ mcpcli skill install --claude --force
413
423
  ```
414
424
 
415
425
  Then in any Claude Code session, the agent can use `/mcpcli` or the skill triggers automatically when the agent needs to interact with external services. The skill instructs the agent to:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evantahler/mcpcli",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "A command-line interface for MCP servers. curl for MCP.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "files": [
10
10
  "src",
11
- "skills",
11
+ ".claude",
12
12
  "README.md",
13
13
  "LICENSE"
14
14
  ],
package/src/cli.ts CHANGED
@@ -9,6 +9,7 @@ import { registerAuthCommand, registerDeauthCommand } from "./commands/auth.ts";
9
9
  import { registerIndexCommand } from "./commands/index.ts";
10
10
  import { registerAddCommand } from "./commands/add.ts";
11
11
  import { registerRemoveCommand } from "./commands/remove.ts";
12
+ import { registerSkillCommand } from "./commands/skill.ts";
12
13
 
13
14
  declare const BUILD_VERSION: string | undefined;
14
15
 
@@ -33,5 +34,6 @@ registerDeauthCommand(program);
33
34
  registerIndexCommand(program);
34
35
  registerAddCommand(program);
35
36
  registerRemoveCommand(program);
37
+ registerSkillCommand(program);
36
38
 
37
39
  program.parse();
@@ -0,0 +1,70 @@
1
+ import type { Command } from "commander";
2
+ import { resolve, dirname, join } from "path";
3
+ import { readFile, mkdir, writeFile, access } from "fs/promises";
4
+ import { homedir } from "os";
5
+
6
+ export function registerSkillCommand(program: Command) {
7
+ const skill = program.command("skill").description("manage mcpcli skills");
8
+
9
+ skill
10
+ .command("install")
11
+ .description("install the mcpcli skill for an AI agent")
12
+ .requiredOption("--claude", "install for Claude Code")
13
+ .option("--global", "install to ~/.claude/skills/")
14
+ .option("--project", "install to ./.claude/skills/ (default)")
15
+ .option("-f, --force", "overwrite if file already exists")
16
+ .action(
17
+ async (options: {
18
+ claude?: boolean;
19
+ global?: boolean;
20
+ project?: boolean;
21
+ force?: boolean;
22
+ }) => {
23
+ // Resolve the bundled skill file
24
+ const skillSource = resolve(dirname(Bun.main), "..", ".claude", "skills", "mcpcli.md");
25
+
26
+ let content: string;
27
+ try {
28
+ content = await readFile(skillSource, "utf-8");
29
+ } catch {
30
+ console.error(`Could not read skill file: ${skillSource}`);
31
+ process.exit(1);
32
+ }
33
+
34
+ // Determine targets — default to project if neither flag is set
35
+ const targets: { label: string; dir: string }[] = [];
36
+
37
+ if (options.global) {
38
+ targets.push({
39
+ label: "global",
40
+ dir: join(homedir(), ".claude", "skills"),
41
+ });
42
+ }
43
+ if (options.project || !options.global) {
44
+ targets.push({
45
+ label: "project",
46
+ dir: resolve(".claude", "skills"),
47
+ });
48
+ }
49
+
50
+ for (const target of targets) {
51
+ const dest = join(target.dir, "mcpcli.md");
52
+
53
+ // Check if file already exists
54
+ if (!options.force) {
55
+ try {
56
+ await access(dest);
57
+ console.error(`${dest} already exists (use --force to overwrite)`);
58
+ process.exit(1);
59
+ } catch {
60
+ // File doesn't exist — good
61
+ }
62
+ }
63
+
64
+ await mkdir(target.dir, { recursive: true });
65
+ await writeFile(dest, content, "utf-8");
66
+ console.log(`Installed mcpcli skill (${target.label}): ${dest}`);
67
+ }
68
+ },
69
+ );
70
+ }
@@ -11,7 +11,7 @@ import {
11
11
  validateSearchIndex,
12
12
  } from "./schemas.ts";
13
13
 
14
- const DEFAULT_CONFIG_DIR = join(homedir(), ".config", "mcpcli");
14
+ const DEFAULT_CONFIG_DIR = join(homedir(), ".mcpcli");
15
15
 
16
16
  const EMPTY_SERVERS: ServersFile = { mcpServers: {} };
17
17
  const EMPTY_AUTH: AuthFile = {};
@@ -42,7 +42,7 @@ function resolveConfigDir(configFlag?: string): string {
42
42
  // 3. ./servers.json exists in cwd → use cwd
43
43
  // (checked at load time, not here — we return the candidate dir)
44
44
 
45
- // 4. Default ~/.config/mcpcli/
45
+ // 4. Default ~/.mcpcli/
46
46
  return DEFAULT_CONFIG_DIR;
47
47
  }
48
48