Skip to content

Commit 0e2906c

Browse files
Implement default-server support
- Auto-select server when --config is used without --server - Use 'default-server' if it exists in config - Use single server if only one is defined - Show helpful error if multiple servers exist without default - Add tests for all default-server scenarios
1 parent a7675d1 commit 0e2906c

File tree

2 files changed

+132
-12
lines changed

2 files changed

+132
-12
lines changed

cli/scripts/cli-tests.js

Lines changed: 102 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,102 @@ async function runTests() {
780780
"tools/list",
781781
);
782782

783+
console.log(
784+
`\n${colors.YELLOW}=== Running Default Server Tests ===${colors.NC}`,
785+
);
786+
787+
// Create config with single server for auto-selection
788+
const singleServerConfigPath = path.join(TEMP_DIR, "single-server-config.json");
789+
fs.writeFileSync(
790+
singleServerConfigPath,
791+
JSON.stringify(
792+
{
793+
mcpServers: {
794+
"only-server": {
795+
command: "npx",
796+
args: ["@modelcontextprotocol/server-everything"],
797+
},
798+
},
799+
},
800+
null,
801+
2,
802+
),
803+
);
804+
805+
// Create config with default-server
806+
const defaultServerConfigPath = path.join(TEMP_DIR, "default-server-config.json");
807+
fs.writeFileSync(
808+
defaultServerConfigPath,
809+
JSON.stringify(
810+
{
811+
mcpServers: {
812+
"default-server": {
813+
command: "npx",
814+
args: ["@modelcontextprotocol/server-everything"],
815+
},
816+
"other-server": {
817+
command: "node",
818+
args: ["other.js"],
819+
},
820+
},
821+
},
822+
null,
823+
2,
824+
),
825+
);
826+
827+
// Create config with multiple servers (no default)
828+
const multiServerConfigPath = path.join(TEMP_DIR, "multi-server-config.json");
829+
fs.writeFileSync(
830+
multiServerConfigPath,
831+
JSON.stringify(
832+
{
833+
mcpServers: {
834+
"server1": {
835+
command: "npx",
836+
args: ["@modelcontextprotocol/server-everything"],
837+
},
838+
"server2": {
839+
command: "node",
840+
args: ["other.js"],
841+
},
842+
},
843+
},
844+
null,
845+
2,
846+
),
847+
);
848+
849+
// Test 29: Config with single server auto-selection
850+
await runBasicTest(
851+
"single_server_auto_select",
852+
"--config",
853+
singleServerConfigPath,
854+
"--cli",
855+
"--method",
856+
"tools/list",
857+
);
858+
859+
// Test 30: Config with default-server auto-selection
860+
await runBasicTest(
861+
"default_server_auto_select",
862+
"--config",
863+
defaultServerConfigPath,
864+
"--cli",
865+
"--method",
866+
"tools/list",
867+
);
868+
869+
// Test 31: Config with multiple servers and no default (should fail)
870+
await runErrorTest(
871+
"multi_server_no_default",
872+
"--config",
873+
multiServerConfigPath,
874+
"--cli",
875+
"--method",
876+
"tools/list",
877+
);
878+
783879
console.log(
784880
`\n${colors.YELLOW}=== Running HTTP Transport Tests ===${colors.NC}`,
785881
);
@@ -799,7 +895,7 @@ async function runTests() {
799895

800896
await new Promise((resolve) => setTimeout(resolve, 3000));
801897

802-
// Test 29: HTTP transport inferred from URL ending with /mcp
898+
// Test 32: HTTP transport inferred from URL ending with /mcp
803899
await runBasicTest(
804900
"http_transport_inferred",
805901
"http://127.0.0.1:3001/mcp",
@@ -808,7 +904,7 @@ async function runTests() {
808904
"tools/list",
809905
);
810906

811-
// Test 30: HTTP transport with explicit --transport http flag
907+
// Test 33: HTTP transport with explicit --transport http flag
812908
await runBasicTest(
813909
"http_transport_with_explicit_flag",
814910
"http://127.0.0.1:3001/mcp",
@@ -819,7 +915,7 @@ async function runTests() {
819915
"tools/list",
820916
);
821917

822-
// Test 31: HTTP transport with suffix and --transport http flag
918+
// Test 34: HTTP transport with suffix and --transport http flag
823919
await runBasicTest(
824920
"http_transport_with_explicit_flag_and_suffix",
825921
"http://127.0.0.1:3001/mcp",
@@ -830,7 +926,7 @@ async function runTests() {
830926
"tools/list",
831927
);
832928

833-
// Test 32: SSE transport given to HTTP server (should fail)
929+
// Test 35: SSE transport given to HTTP server (should fail)
834930
await runErrorTest(
835931
"sse_transport_given_to_http_server",
836932
"http://127.0.0.1:3001",
@@ -841,7 +937,7 @@ async function runTests() {
841937
"tools/list",
842938
);
843939

844-
// Test 33: HTTP transport without URL (should fail)
940+
// Test 36: HTTP transport without URL (should fail)
845941
await runErrorTest(
846942
"http_transport_without_url",
847943
"--transport",
@@ -851,7 +947,7 @@ async function runTests() {
851947
"tools/list",
852948
);
853949

854-
// Test 34: SSE transport without URL (should fail)
950+
// Test 37: SSE transport without URL (should fail)
855951
await runErrorTest(
856952
"sse_transport_without_url",
857953
"--transport",

cli/src/cli.ts

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,16 +220,40 @@ function parseArgs(): Args {
220220
// Add back any arguments that came after --
221221
const finalArgs = [...remainingArgs, ...postArgs];
222222

223-
// Validate that config and server are provided together
224-
if (
225-
(options.config && !options.server) ||
226-
(!options.config && options.server)
227-
) {
223+
// Validate config and server options
224+
if (!options.config && options.server) {
228225
throw new Error(
229-
"Both --config and --server must be provided together. If you specify one, you must specify the other.",
226+
"--server requires --config to be specified",
230227
);
231228
}
232229

230+
// If config is provided without server, try to auto-select
231+
if (options.config && !options.server) {
232+
const configContent = fs.readFileSync(
233+
path.isAbsolute(options.config)
234+
? options.config
235+
: path.resolve(process.cwd(), options.config),
236+
"utf8"
237+
);
238+
const parsedConfig = JSON.parse(configContent);
239+
const servers = Object.keys(parsedConfig.mcpServers || {});
240+
241+
if (servers.includes("default-server")) {
242+
// Use default-server if it exists
243+
options.server = "default-server";
244+
} else if (servers.length === 1) {
245+
// Use the only server if there's just one
246+
options.server = servers[0];
247+
} else if (servers.length === 0) {
248+
throw new Error("No servers found in config file");
249+
} else {
250+
// Multiple servers, no default-server
251+
throw new Error(
252+
`Multiple servers found in config file. Please specify one with --server.\nAvailable servers: ${servers.join(", ")}`
253+
);
254+
}
255+
}
256+
233257
// If config file is specified, load and use the options from the file. We must merge the args
234258
// from the command line and the file together, or we will miss the method options (--method,
235259
// etc.)

0 commit comments

Comments
 (0)