Merge branch 'main' into dev/eh/tool-meta-support
This commit is contained in:
commit
413db00785
6 changed files with 75 additions and 24 deletions
41
.github/workflows/cli_tests.yml
vendored
Normal file
41
.github/workflows/cli_tests.yml
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
name: CLI Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- "cli/**"
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "cli/**"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ./cli
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: package.json
|
||||||
|
cache: npm
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
cd ..
|
||||||
|
npm ci --ignore-scripts
|
||||||
|
|
||||||
|
- name: Build CLI
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Explicitly pre-install test dependencies
|
||||||
|
run: npx -y @modelcontextprotocol/server-everything --help || true
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: npm test
|
||||||
|
env:
|
||||||
|
NPM_CONFIG_YES: true
|
||||||
|
CI: true
|
||||||
|
|
@ -315,7 +315,7 @@ npx @modelcontextprotocol/inspector --cli node build/index.js --method prompts/l
|
||||||
npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com
|
npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com
|
||||||
|
|
||||||
# Connect to a remote MCP server (with Streamable HTTP transport)
|
# Connect to a remote MCP server (with Streamable HTTP transport)
|
||||||
npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --transport http
|
npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --transport http --method tools/list
|
||||||
|
|
||||||
# Call a tool on a remote server
|
# Call a tool on a remote server
|
||||||
npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --method tools/call --tool-name remotetool --tool-arg param=value
|
npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --method tools/call --tool-name remotetool --tool-arg param=value
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ const colors = {
|
||||||
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { execSync, spawn } from "child_process";
|
import { spawn } from "child_process";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
|
|
@ -680,7 +680,7 @@ async function runTests() {
|
||||||
// Test 26: HTTP transport with explicit --transport http flag
|
// Test 26: HTTP transport with explicit --transport http flag
|
||||||
await runBasicTest(
|
await runBasicTest(
|
||||||
"http_transport_with_explicit_flag",
|
"http_transport_with_explicit_flag",
|
||||||
"http://127.0.0.1:3001",
|
"http://127.0.0.1:3001/mcp",
|
||||||
"--transport",
|
"--transport",
|
||||||
"http",
|
"http",
|
||||||
"--cli",
|
"--cli",
|
||||||
|
|
@ -710,6 +710,26 @@ async function runTests() {
|
||||||
"tools/list",
|
"tools/list",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Test 29: HTTP transport without URL (should fail)
|
||||||
|
await runErrorTest(
|
||||||
|
"http_transport_without_url",
|
||||||
|
"--transport",
|
||||||
|
"http",
|
||||||
|
"--cli",
|
||||||
|
"--method",
|
||||||
|
"tools/list",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test 30: SSE transport without URL (should fail)
|
||||||
|
await runErrorTest(
|
||||||
|
"sse_transport_without_url",
|
||||||
|
"--transport",
|
||||||
|
"sse",
|
||||||
|
"--cli",
|
||||||
|
"--method",
|
||||||
|
"tools/list",
|
||||||
|
);
|
||||||
|
|
||||||
// Kill HTTP server
|
// Kill HTTP server
|
||||||
try {
|
try {
|
||||||
process.kill(-httpServer.pid);
|
process.kill(-httpServer.pid);
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ async function main(): Promise<void> {
|
||||||
const args = parseArgs();
|
const args = parseArgs();
|
||||||
|
|
||||||
if (args.cli) {
|
if (args.cli) {
|
||||||
runCli(args);
|
await runCli(args);
|
||||||
} else {
|
} else {
|
||||||
await runWebClient(args);
|
await runWebClient(args);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -287,6 +287,8 @@ async function main(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const args = parseArgs();
|
const args = parseArgs();
|
||||||
await callMethod(args);
|
await callMethod(args);
|
||||||
|
// Explicitly exit to ensure process terminates in CI
|
||||||
|
process.exit(0);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error);
|
handleError(error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,24 +14,6 @@ export type TransportOptions = {
|
||||||
url?: string;
|
url?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function createSSETransport(options: TransportOptions): Transport {
|
|
||||||
const baseUrl = new URL(options.url ?? "");
|
|
||||||
const sseUrl = baseUrl.pathname.endsWith("/sse")
|
|
||||||
? baseUrl
|
|
||||||
: new URL("/sse", baseUrl);
|
|
||||||
|
|
||||||
return new SSEClientTransport(sseUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createHTTPTransport(options: TransportOptions): Transport {
|
|
||||||
const baseUrl = new URL(options.url ?? "");
|
|
||||||
const mcpUrl = baseUrl.pathname.endsWith("/mcp")
|
|
||||||
? baseUrl
|
|
||||||
: new URL("/mcp", baseUrl);
|
|
||||||
|
|
||||||
return new StreamableHTTPClientTransport(mcpUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createStdioTransport(options: TransportOptions): Transport {
|
function createStdioTransport(options: TransportOptions): Transport {
|
||||||
let args: string[] = [];
|
let args: string[] = [];
|
||||||
|
|
||||||
|
|
@ -75,12 +57,18 @@ export function createTransport(options: TransportOptions): Transport {
|
||||||
return createStdioTransport(options);
|
return createStdioTransport(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If not STDIO, then it must be either SSE or HTTP.
|
||||||
|
if (!options.url) {
|
||||||
|
throw new Error("URL must be provided for SSE or HTTP transport types.");
|
||||||
|
}
|
||||||
|
const url = new URL(options.url);
|
||||||
|
|
||||||
if (transportType === "sse") {
|
if (transportType === "sse") {
|
||||||
return createSSETransport(options);
|
return new SSEClientTransport(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transportType === "http") {
|
if (transportType === "http") {
|
||||||
return createHTTPTransport(options);
|
return new StreamableHTTPClientTransport(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`Unsupported transport type: ${transportType}`);
|
throw new Error(`Unsupported transport type: ${transportType}`);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue