@evantahler/mcpx 0.18.3 → 0.18.5

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.
Files changed (53) hide show
  1. package/package.json +63 -63
  2. package/src/cli.ts +46 -54
  3. package/src/client/browser.ts +15 -15
  4. package/src/client/debug-fetch.ts +53 -56
  5. package/src/client/elicitation.ts +279 -291
  6. package/src/client/http.ts +1 -1
  7. package/src/client/manager.ts +481 -514
  8. package/src/client/oauth.ts +272 -282
  9. package/src/client/sse.ts +1 -1
  10. package/src/client/stdio.ts +7 -7
  11. package/src/client/trace.ts +146 -152
  12. package/src/client/transport-options.ts +20 -20
  13. package/src/commands/add.ts +160 -165
  14. package/src/commands/allow.ts +141 -142
  15. package/src/commands/auth.ts +86 -90
  16. package/src/commands/check-update.ts +49 -53
  17. package/src/commands/deny.ts +114 -117
  18. package/src/commands/exec.ts +218 -222
  19. package/src/commands/index.ts +41 -41
  20. package/src/commands/info.ts +48 -50
  21. package/src/commands/list.ts +49 -49
  22. package/src/commands/ping.ts +47 -50
  23. package/src/commands/prompt.ts +40 -50
  24. package/src/commands/remove.ts +54 -56
  25. package/src/commands/resource.ts +31 -36
  26. package/src/commands/search.ts +35 -39
  27. package/src/commands/servers.ts +44 -48
  28. package/src/commands/skill.ts +89 -95
  29. package/src/commands/task.ts +50 -60
  30. package/src/commands/upgrade.ts +191 -208
  31. package/src/commands/with-command.ts +27 -29
  32. package/src/config/env.ts +26 -28
  33. package/src/config/loader.ts +99 -102
  34. package/src/config/schemas.ts +78 -87
  35. package/src/constants.ts +17 -17
  36. package/src/context.ts +51 -51
  37. package/src/lib/client-settings.ts +127 -140
  38. package/src/lib/input.ts +23 -26
  39. package/src/output/format-output.ts +12 -16
  40. package/src/output/format-table.ts +39 -42
  41. package/src/output/formatter.ts +790 -814
  42. package/src/output/logger.ts +140 -152
  43. package/src/sdk.ts +283 -291
  44. package/src/search/index.ts +50 -54
  45. package/src/search/indexer.ts +65 -65
  46. package/src/search/keyword.ts +54 -54
  47. package/src/search/semantic.ts +39 -39
  48. package/src/search/staleness.ts +3 -3
  49. package/src/search/types.ts +4 -4
  50. package/src/update/background.ts +51 -51
  51. package/src/update/cache.ts +21 -21
  52. package/src/update/checker.ts +81 -86
  53. package/src/validation/schema.ts +52 -58
@@ -1,58 +1,56 @@
1
1
  import type { Command } from "commander";
2
- import type { Tool, Resource, Prompt } from "../config/schemas.ts";
3
- import { formatServerOverview, formatToolSchema, formatError } from "../output/formatter.ts";
2
+ import type { Prompt, Resource, Tool } from "../config/schemas.ts";
3
+ import { formatError, formatServerOverview, formatToolSchema } from "../output/formatter.ts";
4
4
  import { withCommand } from "./with-command.ts";
5
5
 
6
6
  export function registerInfoCommand(program: Command) {
7
- program
8
- .command("info <server> [tool]")
9
- .description("show server overview, or schema for a specific tool")
10
- .action(
11
- withCommand(
12
- program,
13
- { spinnerText: "Connecting..." },
14
- async ({ manager, formatOptions, spinner }, server: string, tool?: string) => {
15
- const target = tool ? `${server}/${tool}` : server;
16
- spinner.update(`Connecting to ${target}...`);
7
+ program
8
+ .command("info <server> [tool]")
9
+ .description("show server overview, or schema for a specific tool")
10
+ .action(
11
+ withCommand(
12
+ program,
13
+ { spinnerText: "Connecting..." },
14
+ async ({ manager, formatOptions, spinner }, server: string, tool?: string) => {
15
+ const target = tool ? `${server}/${tool}` : server;
16
+ spinner.update(`Connecting to ${target}...`);
17
17
 
18
- if (tool) {
19
- const toolSchema = await manager.getToolSchema(server, tool);
20
- spinner.stop();
21
- if (!toolSchema) {
22
- console.error(
23
- formatError(`Tool "${tool}" not found on server "${server}"`, formatOptions),
24
- );
25
- process.exit(1);
26
- }
27
- console.log(formatToolSchema(server, toolSchema, formatOptions));
28
- } else {
29
- const serverInfo = await manager.getServerInfo(server);
30
- const caps = serverInfo.capabilities as Record<string, unknown> | undefined;
18
+ if (tool) {
19
+ const toolSchema = await manager.getToolSchema(server, tool);
20
+ spinner.stop();
21
+ if (!toolSchema) {
22
+ console.error(formatError(`Tool "${tool}" not found on server "${server}"`, formatOptions));
23
+ process.exit(1);
24
+ }
25
+ console.log(formatToolSchema(server, toolSchema, formatOptions));
26
+ } else {
27
+ const serverInfo = await manager.getServerInfo(server);
28
+ const caps = serverInfo.capabilities as Record<string, unknown> | undefined;
31
29
 
32
- const fetches: [Promise<Tool[]>, Promise<Resource[]>, Promise<Prompt[]>] = [
33
- caps?.tools !== undefined ? manager.listTools(server) : Promise.resolve([]),
34
- caps?.resources !== undefined ? manager.listResources(server) : Promise.resolve([]),
35
- caps?.prompts !== undefined ? manager.listPrompts(server) : Promise.resolve([]),
36
- ];
37
- const [tools, resources, prompts] = await Promise.all(fetches);
30
+ const fetches: [Promise<Tool[]>, Promise<Resource[]>, Promise<Prompt[]>] = [
31
+ caps?.tools !== undefined ? manager.listTools(server) : Promise.resolve([]),
32
+ caps?.resources !== undefined ? manager.listResources(server) : Promise.resolve([]),
33
+ caps?.prompts !== undefined ? manager.listPrompts(server) : Promise.resolve([]),
34
+ ];
35
+ const [tools, resources, prompts] = await Promise.all(fetches);
38
36
 
39
- spinner.stop();
40
- console.log(
41
- formatServerOverview(
42
- {
43
- serverName: server,
44
- version: serverInfo.version,
45
- capabilities: caps,
46
- instructions: serverInfo.instructions,
47
- tools,
48
- resourceCount: resources.length,
49
- promptCount: prompts.length,
50
- },
51
- formatOptions,
52
- ),
53
- );
54
- }
55
- },
56
- ),
57
- );
37
+ spinner.stop();
38
+ console.log(
39
+ formatServerOverview(
40
+ {
41
+ serverName: server,
42
+ version: serverInfo.version,
43
+ capabilities: caps,
44
+ instructions: serverInfo.instructions,
45
+ tools,
46
+ resourceCount: resources.length,
47
+ promptCount: prompts.length,
48
+ },
49
+ formatOptions,
50
+ ),
51
+ );
52
+ }
53
+ },
54
+ ),
55
+ );
58
56
  }
@@ -1,59 +1,59 @@
1
1
  import type { Command } from "commander";
2
- import { formatUnifiedList } from "../output/formatter.ts";
3
2
  import type { UnifiedItem } from "../output/formatter.ts";
3
+ import { formatUnifiedList } from "../output/formatter.ts";
4
4
  import { withCommand } from "./with-command.ts";
5
5
 
6
6
  export function registerListCommand(program: Command) {
7
- program.action(
8
- withCommand(
9
- program,
10
- { spinnerText: "Connecting to servers...", errorLabel: "Failed to list servers" },
11
- async ({ manager, formatOptions, spinner }) => {
12
- const [toolsResult, resourcesResult, promptsResult] = await Promise.all([
13
- manager.getAllTools(),
14
- manager.getAllResources(),
15
- manager.getAllPrompts(),
16
- ]);
17
- spinner.stop();
7
+ program.action(
8
+ withCommand(
9
+ program,
10
+ { spinnerText: "Connecting to servers...", errorLabel: "Failed to list servers" },
11
+ async ({ manager, formatOptions, spinner }) => {
12
+ const [toolsResult, resourcesResult, promptsResult] = await Promise.all([
13
+ manager.getAllTools(),
14
+ manager.getAllResources(),
15
+ manager.getAllPrompts(),
16
+ ]);
17
+ spinner.stop();
18
18
 
19
- const items: UnifiedItem[] = [
20
- ...toolsResult.tools.map((t) => ({
21
- server: t.server,
22
- type: "tool" as const,
23
- name: t.tool.name,
24
- description: t.tool.description,
25
- })),
26
- ...resourcesResult.resources.map((r) => ({
27
- server: r.server,
28
- type: "resource" as const,
29
- name: r.resource.uri,
30
- description: r.resource.description,
31
- })),
32
- ...promptsResult.prompts.map((p) => ({
33
- server: p.server,
34
- type: "prompt" as const,
35
- name: p.prompt.name,
36
- description: p.prompt.description,
37
- })),
38
- ];
19
+ const items: UnifiedItem[] = [
20
+ ...toolsResult.tools.map((t) => ({
21
+ server: t.server,
22
+ type: "tool" as const,
23
+ name: t.tool.name,
24
+ description: t.tool.description,
25
+ })),
26
+ ...resourcesResult.resources.map((r) => ({
27
+ server: r.server,
28
+ type: "resource" as const,
29
+ name: r.resource.uri,
30
+ description: r.resource.description,
31
+ })),
32
+ ...promptsResult.prompts.map((p) => ({
33
+ server: p.server,
34
+ type: "prompt" as const,
35
+ name: p.prompt.name,
36
+ description: p.prompt.description,
37
+ })),
38
+ ];
39
39
 
40
- const typeOrder = { tool: 0, resource: 1, prompt: 2 };
41
- items.sort((a, b) => {
42
- if (a.server !== b.server) return a.server.localeCompare(b.server);
43
- if (a.type !== b.type) return typeOrder[a.type] - typeOrder[b.type];
44
- return a.name.localeCompare(b.name);
45
- });
40
+ const typeOrder = { tool: 0, resource: 1, prompt: 2 };
41
+ items.sort((a, b) => {
42
+ if (a.server !== b.server) return a.server.localeCompare(b.server);
43
+ if (a.type !== b.type) return typeOrder[a.type] - typeOrder[b.type];
44
+ return a.name.localeCompare(b.name);
45
+ });
46
46
 
47
- const errors = [...toolsResult.errors, ...resourcesResult.errors, ...promptsResult.errors];
48
- if (errors.length > 0) {
49
- for (const err of errors) {
50
- console.error(`"${err.server}": ${err.message}`);
51
- }
52
- if (items.length > 0) console.log("");
53
- }
47
+ const errors = [...toolsResult.errors, ...resourcesResult.errors, ...promptsResult.errors];
48
+ if (errors.length > 0) {
49
+ for (const err of errors) {
50
+ console.error(`"${err.server}": ${err.message}`);
51
+ }
52
+ if (items.length > 0) console.log("");
53
+ }
54
54
 
55
- console.log(formatUnifiedList(items, formatOptions));
56
- },
57
- ),
58
- );
55
+ console.log(formatUnifiedList(items, formatOptions));
56
+ },
57
+ ),
58
+ );
59
59
  }
@@ -5,65 +5,62 @@ import { formatError } from "../output/formatter.ts";
5
5
  import { logger } from "../output/logger.ts";
6
6
 
7
7
  interface PingResult {
8
- server: string;
9
- success: boolean;
10
- latencyMs?: number;
11
- error?: string;
8
+ server: string;
9
+ success: boolean;
10
+ latencyMs?: number;
11
+ error?: string;
12
12
  }
13
13
 
14
14
  export function registerPingCommand(program: Command) {
15
- program
16
- .command("ping [servers...]")
17
- .description("Check connectivity to MCP servers")
18
- .action(async (servers: string[]) => {
19
- const { manager, formatOptions } = await getContext(program);
15
+ program
16
+ .command("ping [servers...]")
17
+ .description("Check connectivity to MCP servers")
18
+ .action(async (servers: string[]) => {
19
+ const { manager, formatOptions } = await getContext(program);
20
20
 
21
- const targetServers = servers.length > 0 ? servers : manager.getServerNames();
21
+ const targetServers = servers.length > 0 ? servers : manager.getServerNames();
22
22
 
23
- if (targetServers.length === 0) {
24
- console.error(formatError("No servers configured", formatOptions));
25
- await manager.close();
26
- process.exit(1);
27
- }
23
+ if (targetServers.length === 0) {
24
+ console.error(formatError("No servers configured", formatOptions));
25
+ await manager.close();
26
+ process.exit(1);
27
+ }
28
28
 
29
- const spinner = logger.startSpinner(
30
- `Pinging ${targetServers.length} server(s)...`,
31
- formatOptions,
32
- );
29
+ const spinner = logger.startSpinner(`Pinging ${targetServers.length} server(s)...`, formatOptions);
33
30
 
34
- const results: PingResult[] = [];
31
+ const results: PingResult[] = [];
35
32
 
36
- try {
37
- await Promise.all(
38
- targetServers.map(async (serverName) => {
39
- const start = Date.now();
40
- try {
41
- await manager.getClient(serverName);
42
- results.push({ server: serverName, success: true, latencyMs: Date.now() - start });
43
- } catch (err) {
44
- results.push({ server: serverName, success: false, error: String(err) });
45
- }
46
- }),
47
- );
33
+ try {
34
+ await Promise.all(
35
+ targetServers.map(async (serverName) => {
36
+ const start = Date.now();
37
+ try {
38
+ await manager.getClient(serverName);
39
+ results.push({ server: serverName, success: true, latencyMs: Date.now() - start });
40
+ } catch (err) {
41
+ results.push({ server: serverName, success: false, error: String(err) });
42
+ }
43
+ }),
44
+ );
48
45
 
49
- spinner.stop();
46
+ spinner.stop();
50
47
 
51
- if (formatOptions.json) {
52
- console.log(JSON.stringify(results, null, 2));
53
- } else {
54
- for (const r of results) {
55
- if (r.success) {
56
- console.log(`${green("✔")} ${r.server} connected (${r.latencyMs}ms)`);
57
- } else {
58
- console.log(`${red("✖")} ${r.server} failed: ${r.error}`);
59
- }
60
- }
61
- }
62
- } finally {
63
- await manager.close();
64
- }
48
+ if (formatOptions.json) {
49
+ console.log(JSON.stringify(results, null, 2));
50
+ } else {
51
+ for (const r of results) {
52
+ if (r.success) {
53
+ console.log(`${green("✔")} ${r.server} connected (${r.latencyMs}ms)`);
54
+ } else {
55
+ console.log(`${red("✖")} ${r.server} failed: ${r.error}`);
56
+ }
57
+ }
58
+ }
59
+ } finally {
60
+ await manager.close();
61
+ }
65
62
 
66
- const anyFailed = results.some((r) => !r.success);
67
- if (anyFailed) process.exit(1);
68
- });
63
+ const anyFailed = results.some((r) => !r.success);
64
+ if (anyFailed) process.exit(1);
65
+ });
69
66
  }
@@ -1,59 +1,49 @@
1
1
  import type { Command } from "commander";
2
- import {
3
- formatPromptList,
4
- formatServerPrompts,
5
- formatPromptMessages,
6
- formatError,
7
- } from "../output/formatter.ts";
8
2
  import { parseJsonArgs, readStdin } from "../lib/input.ts";
3
+ import { formatError, formatPromptList, formatPromptMessages, formatServerPrompts } from "../output/formatter.ts";
9
4
  import { withCommand } from "./with-command.ts";
10
5
 
11
6
  export function registerPromptCommand(program: Command) {
12
- program
13
- .command("prompt [server] [name] [args]")
14
- .description("list prompts for a server, or get a specific prompt")
15
- .action(
16
- withCommand(
17
- program,
18
- { spinnerText: "Connecting to servers..." },
19
- async (
20
- { manager, formatOptions, spinner },
21
- server?: string,
22
- name?: string,
23
- argsStr?: string,
24
- ) => {
25
- if (server) {
26
- spinner.update(`Connecting to ${server}...`);
27
- }
7
+ program
8
+ .command("prompt [server] [name] [args]")
9
+ .description("list prompts for a server, or get a specific prompt")
10
+ .action(
11
+ withCommand(
12
+ program,
13
+ { spinnerText: "Connecting to servers..." },
14
+ async ({ manager, formatOptions, spinner }, server?: string, name?: string, argsStr?: string) => {
15
+ if (server) {
16
+ spinner.update(`Connecting to ${server}...`);
17
+ }
28
18
 
29
- if (server && name) {
30
- let args: Record<string, string> | undefined;
19
+ if (server && name) {
20
+ let args: Record<string, string> | undefined;
31
21
 
32
- if (argsStr) {
33
- args = parseJsonArgs(argsStr, { coerceToString: true }) as Record<string, string>;
34
- } else if (!process.stdin.isTTY) {
35
- const stdin = await readStdin();
36
- if (stdin.trim()) {
37
- args = parseJsonArgs(stdin, { coerceToString: true }) as Record<string, string>;
38
- }
39
- }
22
+ if (argsStr) {
23
+ args = parseJsonArgs(argsStr, { coerceToString: true }) as Record<string, string>;
24
+ } else if (!process.stdin.isTTY) {
25
+ const stdin = await readStdin();
26
+ if (stdin.trim()) {
27
+ args = parseJsonArgs(stdin, { coerceToString: true }) as Record<string, string>;
28
+ }
29
+ }
40
30
 
41
- const result = await manager.getPrompt(server, name, args);
42
- spinner.stop();
43
- console.log(formatPromptMessages(server, name, result, formatOptions));
44
- } else if (server) {
45
- const prompts = await manager.listPrompts(server);
46
- spinner.stop();
47
- console.log(formatServerPrompts(server, prompts, formatOptions));
48
- } else {
49
- const { prompts, errors } = await manager.getAllPrompts();
50
- spinner.stop();
51
- console.log(formatPromptList(prompts, formatOptions));
52
- for (const err of errors) {
53
- console.error(formatError(`${err.server}: ${err.message}`, formatOptions));
54
- }
55
- }
56
- },
57
- ),
58
- );
31
+ const result = await manager.getPrompt(server, name, args);
32
+ spinner.stop();
33
+ console.log(formatPromptMessages(server, name, result, formatOptions));
34
+ } else if (server) {
35
+ const prompts = await manager.listPrompts(server);
36
+ spinner.stop();
37
+ console.log(formatServerPrompts(server, prompts, formatOptions));
38
+ } else {
39
+ const { prompts, errors } = await manager.getAllPrompts();
40
+ spinner.stop();
41
+ console.log(formatPromptList(prompts, formatOptions));
42
+ for (const err of errors) {
43
+ console.error(formatError(`${err.server}: ${err.message}`, formatOptions));
44
+ }
45
+ }
46
+ },
47
+ ),
48
+ );
59
49
  }
@@ -1,67 +1,65 @@
1
1
  import type { Command } from "commander";
2
2
  import {
3
- loadRawServers,
4
- loadRawAuth,
5
- loadSearchIndex,
6
- saveServers,
7
- saveAuth,
8
- saveSearchIndex,
3
+ loadRawAuth,
4
+ loadRawServers,
5
+ loadSearchIndex,
6
+ saveAuth,
7
+ saveSearchIndex,
8
+ saveServers,
9
9
  } from "../config/loader.ts";
10
10
 
11
11
  export function registerRemoveCommand(program: Command) {
12
- program
13
- .command("remove <name>")
14
- .description("remove an MCP server from your config")
15
- .option("--keep-auth", "keep stored authentication credentials")
16
- .option("--dry-run", "show what would be removed without changing files")
17
- .action(async (name: string, options: { keepAuth?: boolean; dryRun?: boolean }) => {
18
- const configFlag = program.opts().config;
19
- const { configDir, servers } = await loadRawServers(configFlag);
12
+ program
13
+ .command("remove <name>")
14
+ .description("remove an MCP server from your config")
15
+ .option("--keep-auth", "keep stored authentication credentials")
16
+ .option("--dry-run", "show what would be removed without changing files")
17
+ .action(async (name: string, options: { keepAuth?: boolean; dryRun?: boolean }) => {
18
+ const configFlag = program.opts().config;
19
+ const { configDir, servers } = await loadRawServers(configFlag);
20
20
 
21
- if (!servers.mcpServers[name]) {
22
- console.error(`Unknown server: "${name}"`);
23
- process.exit(1);
24
- }
21
+ if (!servers.mcpServers[name]) {
22
+ console.error(`Unknown server: "${name}"`);
23
+ process.exit(1);
24
+ }
25
25
 
26
- if (options.dryRun) {
27
- console.log(`Would remove server "${name}" from ${configDir}/servers.json`);
28
- if (!options.keepAuth) {
29
- const auth = await loadRawAuth(configDir);
30
- if (auth[name]) {
31
- console.log(`Would remove auth for "${name}" from ${configDir}/auth.json`);
32
- }
33
- }
34
- const searchIndex = await loadSearchIndex(configDir);
35
- const indexedCount = searchIndex.tools.filter((t) => t.server === name).length;
36
- if (indexedCount > 0) {
37
- console.log(
38
- `Would remove ${indexedCount} tool(s) for "${name}" from ${configDir}/search.json`,
39
- );
40
- }
41
- return;
42
- }
26
+ if (options.dryRun) {
27
+ console.log(`Would remove server "${name}" from ${configDir}/servers.json`);
28
+ if (!options.keepAuth) {
29
+ const auth = await loadRawAuth(configDir);
30
+ if (auth[name]) {
31
+ console.log(`Would remove auth for "${name}" from ${configDir}/auth.json`);
32
+ }
33
+ }
34
+ const searchIndex = await loadSearchIndex(configDir);
35
+ const indexedCount = searchIndex.tools.filter((t) => t.server === name).length;
36
+ if (indexedCount > 0) {
37
+ console.log(`Would remove ${indexedCount} tool(s) for "${name}" from ${configDir}/search.json`);
38
+ }
39
+ return;
40
+ }
43
41
 
44
- delete servers.mcpServers[name];
45
- await saveServers(configDir, servers);
46
- console.log(`Removed server "${name}" from ${configDir}/servers.json`);
42
+ delete servers.mcpServers[name];
43
+ await saveServers(configDir, servers);
44
+ console.log(`Removed server "${name}" from ${configDir}/servers.json`);
47
45
 
48
- if (!options.keepAuth) {
49
- const auth = await loadRawAuth(configDir);
50
- if (auth[name]) {
51
- delete auth[name];
52
- await saveAuth(configDir, auth);
53
- console.log(`Removed auth for "${name}" from ${configDir}/auth.json`);
54
- }
55
- }
46
+ if (!options.keepAuth) {
47
+ const auth = await loadRawAuth(configDir);
48
+ if (auth[name]) {
49
+ delete auth[name];
50
+ await saveAuth(configDir, auth);
51
+ console.log(`Removed auth for "${name}" from ${configDir}/auth.json`);
52
+ }
53
+ }
56
54
 
57
- // Remove tools for this server from the search index
58
- const searchIndex = await loadSearchIndex(configDir);
59
- const before = searchIndex.tools.length;
60
- searchIndex.tools = searchIndex.tools.filter((t) => t.server !== name);
61
- const removed = before - searchIndex.tools.length;
62
- if (removed > 0) {
63
- await saveSearchIndex(configDir, searchIndex);
64
- console.log(`Removed ${removed} tool(s) for "${name}" from ${configDir}/search.json`);
65
- }
66
- });
55
+ // Remove tools for this server from the search index
56
+ const searchIndex = await loadSearchIndex(configDir);
57
+ const before = searchIndex.tools.length;
58
+ searchIndex.tools = searchIndex.tools.filter((t) => t.server !== name);
59
+ const removed = before - searchIndex.tools.length;
60
+ if (removed > 0) {
61
+ await saveSearchIndex(configDir, searchIndex);
62
+ console.log(`Removed ${removed} tool(s) for "${name}" from ${configDir}/search.json`);
63
+ }
64
+ });
67
65
  }
@@ -1,42 +1,37 @@
1
1
  import type { Command } from "commander";
2
- import {
3
- formatResourceList,
4
- formatServerResources,
5
- formatResourceContents,
6
- formatError,
7
- } from "../output/formatter.ts";
2
+ import { formatError, formatResourceContents, formatResourceList, formatServerResources } from "../output/formatter.ts";
8
3
  import { withCommand } from "./with-command.ts";
9
4
 
10
5
  export function registerResourceCommand(program: Command) {
11
- program
12
- .command("resource [server] [uri]")
13
- .description("list resources for a server, or read a specific resource")
14
- .action(
15
- withCommand(
16
- program,
17
- { spinnerText: "Connecting to servers..." },
18
- async ({ manager, formatOptions, spinner }, server?: string, uri?: string) => {
19
- if (server) {
20
- spinner.update(`Connecting to ${server}...`);
21
- }
6
+ program
7
+ .command("resource [server] [uri]")
8
+ .description("list resources for a server, or read a specific resource")
9
+ .action(
10
+ withCommand(
11
+ program,
12
+ { spinnerText: "Connecting to servers..." },
13
+ async ({ manager, formatOptions, spinner }, server?: string, uri?: string) => {
14
+ if (server) {
15
+ spinner.update(`Connecting to ${server}...`);
16
+ }
22
17
 
23
- if (server && uri) {
24
- const result = await manager.readResource(server, uri);
25
- spinner.stop();
26
- console.log(formatResourceContents(server, uri, result, formatOptions));
27
- } else if (server) {
28
- const resources = await manager.listResources(server);
29
- spinner.stop();
30
- console.log(formatServerResources(server, resources, formatOptions));
31
- } else {
32
- const { resources, errors } = await manager.getAllResources();
33
- spinner.stop();
34
- console.log(formatResourceList(resources, formatOptions));
35
- for (const err of errors) {
36
- console.error(formatError(`${err.server}: ${err.message}`, formatOptions));
37
- }
38
- }
39
- },
40
- ),
41
- );
18
+ if (server && uri) {
19
+ const result = await manager.readResource(server, uri);
20
+ spinner.stop();
21
+ console.log(formatResourceContents(server, uri, result, formatOptions));
22
+ } else if (server) {
23
+ const resources = await manager.listResources(server);
24
+ spinner.stop();
25
+ console.log(formatServerResources(server, resources, formatOptions));
26
+ } else {
27
+ const { resources, errors } = await manager.getAllResources();
28
+ spinner.stop();
29
+ console.log(formatResourceList(resources, formatOptions));
30
+ for (const err of errors) {
31
+ console.error(formatError(`${err.server}: ${err.message}`, formatOptions));
32
+ }
33
+ }
34
+ },
35
+ ),
36
+ );
42
37
  }