refactor(cli): align mcp add args help
This commit is contained in:
parent
2ca7478b8a
commit
ebb101bd54
4 changed files with 81 additions and 55 deletions
|
|
@ -59,7 +59,7 @@ type McpAddArgs = {
|
||||||
_?: Array<string | number>
|
_?: Array<string | number>
|
||||||
"--"?: string[]
|
"--"?: string[]
|
||||||
name?: string
|
name?: string
|
||||||
urlOrCommand?: string[]
|
args?: string[]
|
||||||
type?: "local" | "remote"
|
type?: "local" | "remote"
|
||||||
env?: string[]
|
env?: string[]
|
||||||
header?: string[]
|
header?: string[]
|
||||||
|
|
@ -456,7 +456,7 @@ async function addMcpToConfig(name: string, mcpConfig: ConfigMCP.Info, configPat
|
||||||
}
|
}
|
||||||
|
|
||||||
export const McpAddCommand = effectCmd({
|
export const McpAddCommand = effectCmd({
|
||||||
command: "add [name] [urlOrCommand..]",
|
command: "add [name] [args..]",
|
||||||
describe: "add an MCP server",
|
describe: "add an MCP server",
|
||||||
builder: (yargs) =>
|
builder: (yargs) =>
|
||||||
yargs
|
yargs
|
||||||
|
|
@ -465,8 +465,8 @@ export const McpAddCommand = effectCmd({
|
||||||
describe: "name of the MCP server",
|
describe: "name of the MCP server",
|
||||||
type: "string",
|
type: "string",
|
||||||
})
|
})
|
||||||
.positional("urlOrCommand", {
|
.positional("args", {
|
||||||
describe: "URL for remote servers or command for local servers",
|
describe: "URL for remote servers or command and arguments for local servers",
|
||||||
type: "string",
|
type: "string",
|
||||||
array: true,
|
array: true,
|
||||||
default: [],
|
default: [],
|
||||||
|
|
@ -527,15 +527,27 @@ export const McpAddCommand = effectCmd({
|
||||||
.option("oauth-redirect-uri", {
|
.option("oauth-redirect-uri", {
|
||||||
describe: "OAuth redirect URI for remote servers",
|
describe: "OAuth redirect URI for remote servers",
|
||||||
type: "string",
|
type: "string",
|
||||||
}),
|
}).epilogue(`Usage:
|
||||||
handler: Effect.fn("Cli.mcp.add")(function* (args: McpAddArgs) {
|
opencode mcp add <name> -- <command> [args...] (local MCP server)
|
||||||
|
opencode mcp add <name> --env KEY=VALUE -- <command> [args...] (local MCP server with env vars)
|
||||||
|
opencode mcp add <name> <url> (remote MCP server)
|
||||||
|
opencode mcp add <name> --header KEY=VALUE <url> (remote MCP server with headers)
|
||||||
|
opencode mcp add <name> --scope project -- <command> [args...] (save to project config)
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
opencode mcp add context7 -- npx -y @upstash/context7-mcp
|
||||||
|
opencode mcp add local-env --env FOO=bar -- node server.js
|
||||||
|
opencode mcp add sg --header Authorization=token https://sg.example/mcp
|
||||||
|
opencode mcp add hugging-face https://huggingface.co/mcp`),
|
||||||
|
handler: Effect.fn("Cli.mcp.add")(function* (input: McpAddArgs) {
|
||||||
const maybeCtx = yield* InstanceRef
|
const maybeCtx = yield* InstanceRef
|
||||||
if (!maybeCtx) return yield* Effect.die("InstanceRef not provided")
|
if (!maybeCtx) return yield* Effect.die("InstanceRef not provided")
|
||||||
const ctx = maybeCtx
|
const ctx = maybeCtx
|
||||||
const urlOrCommand = mcpAddUrlOrCommand(args)
|
const inlineArgs = mcpAddArgs(input)
|
||||||
const inlineConfig = parseInlineMcpAdd(args, urlOrCommand)
|
const inlineConfig = parseInlineMcpAdd(input, inlineArgs)
|
||||||
if (inlineConfig && "error" in inlineConfig) return yield* fail(inlineConfig.error)
|
if (inlineConfig && "error" in inlineConfig) return yield* fail(inlineConfig.error)
|
||||||
if (args.global && args.scope === "project") return yield* fail("--global cannot be combined with --scope project")
|
if (input.global && input.scope === "project")
|
||||||
|
return yield* fail("--global cannot be combined with --scope project")
|
||||||
yield* Effect.promise(async () => {
|
yield* Effect.promise(async () => {
|
||||||
UI.empty()
|
UI.empty()
|
||||||
prompts.intro("Add MCP server")
|
prompts.intro("Add MCP server")
|
||||||
|
|
@ -548,8 +560,8 @@ export const McpAddCommand = effectCmd({
|
||||||
])
|
])
|
||||||
|
|
||||||
const configPath = await (async () => {
|
const configPath = await (async () => {
|
||||||
if (args.global || args.scope === "global") return globalConfigPath
|
if (input.global || input.scope === "global") return globalConfigPath
|
||||||
if (args.scope === "project") return projectConfigPath
|
if (input.scope === "project") return projectConfigPath
|
||||||
if (inlineConfig) return project.vcs === "git" ? projectConfigPath : globalConfigPath
|
if (inlineConfig) return project.vcs === "git" ? projectConfigPath : globalConfigPath
|
||||||
if (project.vcs !== "git") return globalConfigPath
|
if (project.vcs !== "git") return globalConfigPath
|
||||||
const scopeResult = await prompts.select({
|
const scopeResult = await prompts.select({
|
||||||
|
|
@ -572,8 +584,8 @@ export const McpAddCommand = effectCmd({
|
||||||
})()
|
})()
|
||||||
|
|
||||||
if (inlineConfig) {
|
if (inlineConfig) {
|
||||||
await addMcpToConfig(args.name!.trim(), inlineConfig.config, configPath)
|
await addMcpToConfig(input.name!.trim(), inlineConfig.config, configPath)
|
||||||
prompts.log.success(`MCP server "${args.name!.trim()}" added to ${configPath}`)
|
prompts.log.success(`MCP server "${input.name!.trim()}" added to ${configPath}`)
|
||||||
prompts.outro("MCP server added successfully")
|
prompts.outro("MCP server added successfully")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -701,47 +713,47 @@ export const McpAddCommand = effectCmd({
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
function mcpAddUrlOrCommand(args: McpAddArgs) {
|
function mcpAddArgs(input: McpAddArgs) {
|
||||||
const addIndex = args._?.lastIndexOf("add") ?? -1
|
const addIndex = input._?.lastIndexOf("add") ?? -1
|
||||||
return [
|
return [
|
||||||
...(args.urlOrCommand ?? []),
|
...(input.args ?? []),
|
||||||
...(addIndex === -1 || !args._ ? [] : args._.slice(addIndex + 1).map(String)),
|
...(addIndex === -1 || !input._ ? [] : input._.slice(addIndex + 1).map(String)),
|
||||||
...(args["--"] ?? []),
|
...(input["--"] ?? []),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseInlineMcpAdd(
|
function parseInlineMcpAdd(
|
||||||
args: McpAddArgs,
|
input: McpAddArgs,
|
||||||
urlOrCommand: string[],
|
inlineArgs: string[],
|
||||||
): { config: ConfigMCP.Info } | { error: string } | undefined {
|
): { config: ConfigMCP.Info } | { error: string } | undefined {
|
||||||
if (!hasInlineMcpAdd(args, urlOrCommand)) return undefined
|
if (!hasInlineMcpAdd(input, inlineArgs)) return undefined
|
||||||
const name = args.name?.trim()
|
const name = input.name?.trim()
|
||||||
if (!name) return { error: "MCP server name is required" }
|
if (!name) return { error: "MCP server name is required" }
|
||||||
if (urlOrCommand.length === 0) return { error: "URL or command is required" }
|
if (inlineArgs.length === 0) return { error: "URL or command is required" }
|
||||||
if (args.timeout !== undefined && (!Number.isInteger(args.timeout) || args.timeout <= 0)) {
|
if (input.timeout !== undefined && (!Number.isInteger(input.timeout) || input.timeout <= 0)) {
|
||||||
return { error: "--timeout must be a positive integer" }
|
return { error: "--timeout must be a positive integer" }
|
||||||
}
|
}
|
||||||
|
|
||||||
const type = args.type ?? (urlOrCommand.length === 1 && URL.canParse(urlOrCommand[0]) ? "remote" : "local")
|
const type = input.type ?? (inlineArgs.length === 1 && URL.canParse(inlineArgs[0]) ? "remote" : "local")
|
||||||
if (type === "local") return parseInlineLocalMcp(args, urlOrCommand)
|
if (type === "local") return parseInlineLocalMcp(input, inlineArgs)
|
||||||
return parseInlineRemoteMcp(args, urlOrCommand)
|
return parseInlineRemoteMcp(input, inlineArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasInlineMcpAdd(args: McpAddArgs, urlOrCommand: string[]) {
|
function hasInlineMcpAdd(input: McpAddArgs, inlineArgs: string[]) {
|
||||||
return !!(
|
return !!(
|
||||||
args.name ||
|
input.name ||
|
||||||
urlOrCommand.length > 0 ||
|
inlineArgs.length > 0 ||
|
||||||
args.type ||
|
input.type ||
|
||||||
args.env?.length ||
|
input.env?.length ||
|
||||||
args.header?.length ||
|
input.header?.length ||
|
||||||
args.enabled !== undefined ||
|
input.enabled !== undefined ||
|
||||||
args.timeout !== undefined ||
|
input.timeout !== undefined ||
|
||||||
args.oauth !== undefined ||
|
input.oauth !== undefined ||
|
||||||
args.oauthClientId ||
|
input.oauthClientId ||
|
||||||
args.oauthClientSecret ||
|
input.oauthClientSecret ||
|
||||||
args.oauthScope ||
|
input.oauthScope ||
|
||||||
args.oauthCallbackPort !== undefined ||
|
input.oauthCallbackPort !== undefined ||
|
||||||
args.oauthRedirectUri
|
input.oauthRedirectUri
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,11 @@ exports[`opencode CLI help-text snapshots every documented command emits stable
|
||||||
manage MCP (Model Context Protocol) servers
|
manage MCP (Model Context Protocol) servers
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
opencode mcp add [name] [urlOrCommand..] add an MCP server
|
opencode mcp add [name] [args..] add an MCP server
|
||||||
opencode mcp list list MCP servers and their status [aliases: ls]
|
opencode mcp list list MCP servers and their status [aliases: ls]
|
||||||
opencode mcp auth [name] authenticate with an OAuth-enabled MCP server
|
opencode mcp auth [name] authenticate with an OAuth-enabled MCP server
|
||||||
opencode mcp logout [name] remove OAuth credentials for an MCP server
|
opencode mcp logout [name] remove OAuth credentials for an MCP server
|
||||||
opencode mcp debug <name> debug OAuth connection for an MCP server
|
opencode mcp debug <name> debug OAuth connection for an MCP server
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-h, --help show help [boolean]
|
-h, --help show help [boolean]
|
||||||
|
|
@ -425,13 +425,13 @@ Options:
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode mcp add --help 1`] = `
|
exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode mcp add --help 1`] = `
|
||||||
"opencode mcp add [name] [urlOrCommand..]
|
"opencode mcp add [name] [args..]
|
||||||
|
|
||||||
add an MCP server
|
add an MCP server
|
||||||
|
|
||||||
Positionals:
|
Positionals:
|
||||||
name name of the MCP server [string]
|
name name of the MCP server [string]
|
||||||
urlOrCommand URL for remote servers or command for local servers [array] [default: []]
|
args URL for remote servers or command and arguments for local servers [array] [default: []]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-h, --help show help [boolean]
|
-h, --help show help [boolean]
|
||||||
|
|
@ -452,7 +452,20 @@ Options:
|
||||||
--oauth-client-secret OAuth client secret for remote servers [string]
|
--oauth-client-secret OAuth client secret for remote servers [string]
|
||||||
--oauth-scope OAuth scopes to request for remote servers [string]
|
--oauth-scope OAuth scopes to request for remote servers [string]
|
||||||
--oauth-callback-port OAuth local callback port for remote servers [number]
|
--oauth-callback-port OAuth local callback port for remote servers [number]
|
||||||
--oauth-redirect-uri OAuth redirect URI for remote servers [string]"
|
--oauth-redirect-uri OAuth redirect URI for remote servers [string]
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
opencode mcp add <name> -- <command> [args...] (local MCP server)
|
||||||
|
opencode mcp add <name> --env KEY=VALUE -- <command> [args...] (local MCP server with env vars)
|
||||||
|
opencode mcp add <name> <url> (remote MCP server)
|
||||||
|
opencode mcp add <name> --header KEY=VALUE <url> (remote MCP server with headers)
|
||||||
|
opencode mcp add <name> --scope project -- <command> [args...] (save to project config)
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
opencode mcp add context7 -- npx -y @upstash/context7-mcp
|
||||||
|
opencode mcp add local-env --env FOO=bar -- node server.js
|
||||||
|
opencode mcp add sg --header Authorization=token https://sg.example/mcp
|
||||||
|
opencode mcp add hugging-face https://huggingface.co/mcp"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode mcp auth --help 1`] = `
|
exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode mcp auth --help 1`] = `
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,13 @@ describe("opencode mcp", () => {
|
||||||
"mcp",
|
"mcp",
|
||||||
"add",
|
"add",
|
||||||
"everything",
|
"everything",
|
||||||
"npx",
|
|
||||||
"-y",
|
|
||||||
"@modelcontextprotocol/server-everything",
|
|
||||||
"--env",
|
"--env",
|
||||||
"FOO=bar",
|
"FOO=bar",
|
||||||
"--global",
|
"--global",
|
||||||
|
"--",
|
||||||
|
"npx",
|
||||||
|
"-y",
|
||||||
|
"@modelcontextprotocol/server-everything",
|
||||||
])
|
])
|
||||||
opencode.expectExit(local, 0, "opencode mcp add local")
|
opencode.expectExit(local, 0, "opencode mcp add local")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ You can add MCP servers from the command line with `opencode mcp add`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Local server
|
# Local server
|
||||||
opencode mcp add mcp_everything npx -y @modelcontextprotocol/server-everything
|
opencode mcp add mcp_everything -- npx -y @modelcontextprotocol/server-everything
|
||||||
|
|
||||||
# Remote server
|
# Remote server
|
||||||
opencode mcp add github https://api.githubcopilot.com/mcp \
|
opencode mcp add github https://api.githubcopilot.com/mcp \
|
||||||
|
|
@ -58,7 +58,7 @@ opencode mcp add github https://api.githubcopilot.com/mcp \
|
||||||
--header "Authorization: Bearer YOUR_GITHUB_PAT"
|
--header "Authorization: Bearer YOUR_GITHUB_PAT"
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `--env KEY=VALUE` for local server environment variables and repeat it for multiple values. Use `--global` to save to global config; otherwise the command saves to the current project when run inside a git repository.
|
Use `--env KEY=VALUE` for local server environment variables and repeat it for multiple values. Use `--scope project` or `--global` to choose where the server is saved.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue