mcp-test-kits 0.0.0

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 (69) hide show
  1. package/README.md +94 -0
  2. package/dist/capabilities/prompts.d.ts +9 -0
  3. package/dist/capabilities/prompts.d.ts.map +1 -0
  4. package/dist/capabilities/prompts.js +76 -0
  5. package/dist/capabilities/prompts.js.map +1 -0
  6. package/dist/capabilities/resources.d.ts +9 -0
  7. package/dist/capabilities/resources.d.ts.map +1 -0
  8. package/dist/capabilities/resources.js +76 -0
  9. package/dist/capabilities/resources.js.map +1 -0
  10. package/dist/capabilities/tools.d.ts +9 -0
  11. package/dist/capabilities/tools.d.ts.map +1 -0
  12. package/dist/capabilities/tools.js +77 -0
  13. package/dist/capabilities/tools.js.map +1 -0
  14. package/dist/config.d.ts +35 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +30 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/extract-spec.d.ts +14 -0
  19. package/dist/extract-spec.d.ts.map +1 -0
  20. package/dist/extract-spec.js +117 -0
  21. package/dist/extract-spec.js.map +1 -0
  22. package/dist/index.d.ts +6 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +97 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/introspection.d.ts +68 -0
  27. package/dist/introspection.d.ts.map +1 -0
  28. package/dist/introspection.js +135 -0
  29. package/dist/introspection.js.map +1 -0
  30. package/dist/server.d.ts +10 -0
  31. package/dist/server.d.ts.map +1 -0
  32. package/dist/server.js +28 -0
  33. package/dist/server.js.map +1 -0
  34. package/dist/transports/http.d.ts +10 -0
  35. package/dist/transports/http.d.ts.map +1 -0
  36. package/dist/transports/http.js +31 -0
  37. package/dist/transports/http.js.map +1 -0
  38. package/dist/transports/index.d.ts +7 -0
  39. package/dist/transports/index.d.ts.map +1 -0
  40. package/dist/transports/index.js +7 -0
  41. package/dist/transports/index.js.map +1 -0
  42. package/dist/transports/sse.d.ts +10 -0
  43. package/dist/transports/sse.d.ts.map +1 -0
  44. package/dist/transports/sse.js +44 -0
  45. package/dist/transports/sse.js.map +1 -0
  46. package/dist/transports/stdio.d.ts +10 -0
  47. package/dist/transports/stdio.d.ts.map +1 -0
  48. package/dist/transports/stdio.js +14 -0
  49. package/dist/transports/stdio.js.map +1 -0
  50. package/eslint.config.js +22 -0
  51. package/package.json +51 -0
  52. package/src/capabilities/prompts.ts +108 -0
  53. package/src/capabilities/resources.ts +108 -0
  54. package/src/capabilities/tools.ts +124 -0
  55. package/src/config.ts +60 -0
  56. package/src/extract-spec.ts +189 -0
  57. package/src/index.ts +110 -0
  58. package/src/introspection.ts +216 -0
  59. package/src/server.ts +34 -0
  60. package/src/transports/http.ts +42 -0
  61. package/src/transports/index.ts +7 -0
  62. package/src/transports/sse.ts +60 -0
  63. package/src/transports/stdio.ts +21 -0
  64. package/tests/fixtures.ts +146 -0
  65. package/tests/http.test.ts +34 -0
  66. package/tests/sse.test.ts +34 -0
  67. package/tests/stdio.test.ts +98 -0
  68. package/tsconfig.json +27 -0
  69. package/vitest.config.ts +8 -0
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Prompt implementations for MCP Test Kits
3
+ */
4
+
5
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { z } from "zod";
7
+
8
+ /**
9
+ * Register all prompts with the MCP server
10
+ */
11
+ export function registerPrompts(server: McpServer): void {
12
+ // Simple prompt
13
+ server.prompt(
14
+ "simple_prompt",
15
+ "A basic prompt with no arguments",
16
+ async () => ({
17
+ messages: [
18
+ {
19
+ role: "user",
20
+ content: {
21
+ type: "text",
22
+ text: "You are a helpful assistant. Please respond concisely and accurately.",
23
+ },
24
+ },
25
+ ],
26
+ }),
27
+ );
28
+
29
+ // Greeting prompt
30
+ server.prompt(
31
+ "greeting_prompt",
32
+ "Generate a greeting message",
33
+ {
34
+ name: z.string().describe("Name of the person to greet"),
35
+ style: z
36
+ .string()
37
+ .optional()
38
+ .describe("Greeting style (formal, casual, friendly)"),
39
+ },
40
+ async ({ name, style }: { name: string; style?: string }) => ({
41
+ messages: [
42
+ {
43
+ role: "user",
44
+ content: {
45
+ type: "text",
46
+ text: `Generate a ${style ?? "friendly"} greeting for ${name}.`,
47
+ },
48
+ },
49
+ ],
50
+ }),
51
+ );
52
+
53
+ // Template prompt
54
+ server.prompt(
55
+ "template_prompt",
56
+ "A template with multiple arguments",
57
+ {
58
+ topic: z.string().describe("Main topic"),
59
+ context: z.string().optional().describe("Additional context"),
60
+ length: z
61
+ .string()
62
+ .optional()
63
+ .describe("Desired length (short, medium, long)"),
64
+ },
65
+ async ({
66
+ topic,
67
+ context,
68
+ length,
69
+ }: {
70
+ topic: string;
71
+ context?: string;
72
+ length?: string;
73
+ }) => {
74
+ let text = `Write a ${length ?? "medium"} explanation about ${topic}.`;
75
+ if (context) {
76
+ text += ` Context: ${context}`;
77
+ }
78
+ return {
79
+ messages: [
80
+ {
81
+ role: "user",
82
+ content: { type: "text", text },
83
+ },
84
+ ],
85
+ };
86
+ },
87
+ );
88
+
89
+ // Multi-message prompt
90
+ server.prompt(
91
+ "multi_message_prompt",
92
+ "Prompt that returns multiple messages",
93
+ {
94
+ count: z.string().describe("Number of messages to generate"),
95
+ },
96
+ async ({ count }: { count: string }) => {
97
+ const numMessages = Math.max(1, Math.min(parseInt(count, 10) || 1, 10));
98
+ const messages = Array.from({ length: numMessages }, (_, i) => ({
99
+ role: "user" as const,
100
+ content: {
101
+ type: "text" as const,
102
+ text: `Message ${i + 1} of ${numMessages}: Generate a helpful response.`,
103
+ },
104
+ }));
105
+ return { messages };
106
+ },
107
+ );
108
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Resource implementations for MCP Test Kits
3
+ */
4
+
5
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+
7
+ // Large text content for testing
8
+ const LARGE_TEXT_CONTENT = `
9
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor
10
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
11
+ nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
12
+
13
+ Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
14
+ fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
15
+ culpa qui officia deserunt mollit anim id est laborum.
16
+
17
+ `.repeat(100);
18
+
19
+ /**
20
+ * Register all resources with the MCP server
21
+ */
22
+ export function registerResources(server: McpServer): void {
23
+ // Static greeting resource
24
+ server.registerResource(
25
+ "static-greeting",
26
+ "test://static/greeting",
27
+ { title: "Static Greeting", mimeType: "text/plain" },
28
+ async () => ({
29
+ contents: [
30
+ {
31
+ uri: "test://static/greeting",
32
+ mimeType: "text/plain",
33
+ text: "Hello from mcp-test-kits!",
34
+ },
35
+ ],
36
+ }),
37
+ );
38
+
39
+ // Static numbers resource
40
+ server.registerResource(
41
+ "static-numbers",
42
+ "test://static/numbers",
43
+ { title: "Number List", mimeType: "application/json" },
44
+ async () => ({
45
+ contents: [
46
+ {
47
+ uri: "test://static/numbers",
48
+ mimeType: "application/json",
49
+ text: JSON.stringify({ numbers: [1, 2, 3, 4, 5] }),
50
+ },
51
+ ],
52
+ }),
53
+ );
54
+
55
+ // Dynamic timestamp resource
56
+ server.registerResource(
57
+ "dynamic-timestamp",
58
+ "test://dynamic/timestamp",
59
+ { title: "Current Timestamp", mimeType: "application/json" },
60
+ async () => {
61
+ const now = new Date();
62
+ return {
63
+ contents: [
64
+ {
65
+ uri: "test://dynamic/timestamp",
66
+ mimeType: "application/json",
67
+ text: JSON.stringify({
68
+ timestamp: now.toISOString(),
69
+ unix: Math.floor(now.getTime() / 1000),
70
+ }),
71
+ },
72
+ ],
73
+ };
74
+ },
75
+ );
76
+
77
+ // Dynamic random resource
78
+ server.registerResource(
79
+ "dynamic-random",
80
+ "test://dynamic/random",
81
+ { title: "Random Number", mimeType: "application/json" },
82
+ async () => ({
83
+ contents: [
84
+ {
85
+ uri: "test://dynamic/random",
86
+ mimeType: "application/json",
87
+ text: JSON.stringify({ random: Math.floor(Math.random() * 101) }),
88
+ },
89
+ ],
90
+ }),
91
+ );
92
+
93
+ // Large text resource
94
+ server.registerResource(
95
+ "large-text",
96
+ "test://large-text",
97
+ { title: "Large Text Resource", mimeType: "text/plain" },
98
+ async () => ({
99
+ contents: [
100
+ {
101
+ uri: "test://large-text",
102
+ mimeType: "text/plain",
103
+ text: LARGE_TEXT_CONTENT,
104
+ },
105
+ ],
106
+ }),
107
+ );
108
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Tool implementations for MCP Test Kits
3
+ */
4
+
5
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { z } from "zod";
7
+
8
+ /**
9
+ * Register all tools with the MCP server
10
+ */
11
+ export function registerTools(server: McpServer): void {
12
+ // echo tool
13
+ server.tool(
14
+ "echo",
15
+ "Returns the input message unchanged",
16
+ { message: z.string().describe("The message to echo") },
17
+ async ({ message }: { message: string }) => ({
18
+ content: [{ type: "text", text: message }],
19
+ }),
20
+ );
21
+
22
+ // add tool
23
+ server.tool(
24
+ "add",
25
+ "Adds two numbers together",
26
+ {
27
+ a: z.number().describe("First number"),
28
+ b: z.number().describe("Second number"),
29
+ },
30
+ async ({ a, b }: { a: number; b: number }) => ({
31
+ content: [{ type: "text", text: String(a + b) }],
32
+ }),
33
+ );
34
+
35
+ // multiply tool
36
+ server.tool(
37
+ "multiply",
38
+ "Multiplies two numbers",
39
+ {
40
+ x: z.number().describe("First number"),
41
+ y: z.number().describe("Second number"),
42
+ },
43
+ async ({ x, y }: { x: number; y: number }) => ({
44
+ content: [{ type: "text", text: String(x * y) }],
45
+ }),
46
+ );
47
+
48
+ // reverse_string tool
49
+ server.tool(
50
+ "reverse_string",
51
+ "Reverses a string",
52
+ { text: z.string().describe("Text to reverse") },
53
+ async ({ text }: { text: string }) => ({
54
+ content: [{ type: "text", text: text.split("").reverse().join("") }],
55
+ }),
56
+ );
57
+
58
+ // generate_uuid tool
59
+ server.tool("generate_uuid", "Generates a random UUID", {}, async () => ({
60
+ content: [{ type: "text", text: crypto.randomUUID() }],
61
+ }));
62
+
63
+ // get_timestamp tool
64
+ server.tool(
65
+ "get_timestamp",
66
+ "Returns the current timestamp",
67
+ {
68
+ format: z
69
+ .enum(["unix", "iso"])
70
+ .default("iso")
71
+ .describe("Format: 'unix' or 'iso'"),
72
+ },
73
+ async ({ format }: { format: string }) => {
74
+ const now = new Date();
75
+ const result =
76
+ format === "unix"
77
+ ? String(Math.floor(now.getTime() / 1000))
78
+ : now.toISOString();
79
+ return { content: [{ type: "text", text: result }] };
80
+ },
81
+ );
82
+
83
+ // sample_error tool
84
+ server.tool(
85
+ "sample_error",
86
+ "Always throws an error (for testing error handling)",
87
+ {
88
+ error_message: z
89
+ .string()
90
+ .default("This is a test error")
91
+ .describe("Custom error message"),
92
+ },
93
+ async ({ error_message }: { error_message: string }) => {
94
+ throw new Error(error_message);
95
+ },
96
+ );
97
+
98
+ // long_running_task tool
99
+ server.tool(
100
+ "long_running_task",
101
+ "Simulates a long-running operation",
102
+ {
103
+ duration: z
104
+ .number()
105
+ .min(0)
106
+ .max(10)
107
+ .describe("Duration in seconds (max 10)"),
108
+ },
109
+ async ({ duration }: { duration: number }) => {
110
+ const actualDuration = Math.min(Math.max(duration, 0), 10);
111
+ await new Promise((resolve) =>
112
+ setTimeout(resolve, actualDuration * 1000),
113
+ );
114
+ return {
115
+ content: [
116
+ {
117
+ type: "text",
118
+ text: `Task completed after ${actualDuration} seconds`,
119
+ },
120
+ ],
121
+ };
122
+ },
123
+ );
124
+ }
package/src/config.ts ADDED
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Configuration types for MCP Test Kits
3
+ */
4
+
5
+ export interface ServerConfig {
6
+ name: string;
7
+ version: string;
8
+ }
9
+
10
+ export interface NetworkConfig {
11
+ host: string;
12
+ port: number;
13
+ }
14
+
15
+ export interface TransportConfig {
16
+ type: "stdio" | "http" | "sse";
17
+ network: NetworkConfig;
18
+ }
19
+
20
+ export interface CapabilitiesConfig {
21
+ tools: boolean;
22
+ resources: boolean;
23
+ prompts: boolean;
24
+ }
25
+
26
+ export interface ConfigOptions {
27
+ server: ServerConfig;
28
+ transport: TransportConfig;
29
+ capabilities: CapabilitiesConfig;
30
+ }
31
+
32
+ /**
33
+ * Configuration class with default values
34
+ */
35
+ export class Config implements ConfigOptions {
36
+ server: ServerConfig;
37
+ transport: TransportConfig;
38
+ capabilities: CapabilitiesConfig;
39
+
40
+ constructor(options?: Partial<ConfigOptions>) {
41
+ this.server = {
42
+ name: options?.server?.name ?? "mcp-test-kits",
43
+ version: options?.server?.version ?? "1.0.0",
44
+ };
45
+
46
+ this.transport = {
47
+ type: options?.transport?.type ?? "stdio",
48
+ network: {
49
+ host: options?.transport?.network?.host ?? "127.0.0.1",
50
+ port: options?.transport?.network?.port ?? 3000,
51
+ },
52
+ };
53
+
54
+ this.capabilities = {
55
+ tools: options?.capabilities?.tools ?? true,
56
+ resources: options?.capabilities?.resources ?? true,
57
+ prompts: options?.capabilities?.prompts ?? true,
58
+ };
59
+ }
60
+ }
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Extract specification from MCP Test Kits server.
4
+ *
5
+ * This script extracts the tools, resources, and prompts specification
6
+ * from the TypeScript implementation and outputs JSON that can be compared
7
+ * against the shared specification.
8
+ *
9
+ * Usage:
10
+ * node dist/extract-spec.js > extracted_spec.json
11
+ * node dist/extract-spec.js --compare
12
+ */
13
+
14
+ import { readFileSync, existsSync } from "node:fs";
15
+ import { join, dirname } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+ import { parseArgs } from "node:util";
18
+ import { Config } from "./config.js";
19
+ import { createServer } from "./server.js";
20
+ import { extractSpec } from "./introspection.js";
21
+
22
+ const __dirname = dirname(fileURLToPath(import.meta.url));
23
+
24
+ interface ToolSpec {
25
+ name: string;
26
+ description: string;
27
+ }
28
+
29
+ interface ResourceSpec {
30
+ name: string;
31
+ uri: string;
32
+ description?: string;
33
+ mimeType?: string;
34
+ }
35
+
36
+ interface PromptSpec {
37
+ name: string;
38
+ description: string;
39
+ arguments?: Array<{ name: string; description?: string; required?: boolean }>;
40
+ }
41
+
42
+ interface Spec {
43
+ tools: ToolSpec[];
44
+ resources: ResourceSpec[];
45
+ prompts: PromptSpec[];
46
+ }
47
+
48
+ /**
49
+ * Load shared specification from JSON files
50
+ */
51
+ function loadSharedSpec(): Spec {
52
+ // Navigate from dist/ to project root, then to shared/
53
+ const projectRoot = join(__dirname, "..", "..");
54
+ const sharedDir = join(projectRoot, "shared", "test-data");
55
+
56
+ const tools: ToolSpec[] = [];
57
+ const resources: ResourceSpec[] = [];
58
+ const prompts: PromptSpec[] = [];
59
+
60
+ const toolsFile = join(sharedDir, "tools.json");
61
+ if (existsSync(toolsFile)) {
62
+ const data = JSON.parse(readFileSync(toolsFile, "utf-8"));
63
+ tools.push(...(data.tools || []));
64
+ }
65
+
66
+ const resourcesFile = join(sharedDir, "resources.json");
67
+ if (existsSync(resourcesFile)) {
68
+ const data = JSON.parse(readFileSync(resourcesFile, "utf-8"));
69
+ resources.push(...(data.resources || []));
70
+ }
71
+
72
+ const promptsFile = join(sharedDir, "prompts.json");
73
+ if (existsSync(promptsFile)) {
74
+ const data = JSON.parse(readFileSync(promptsFile, "utf-8"));
75
+ prompts.push(...(data.prompts || []));
76
+ }
77
+
78
+ return {
79
+ tools: tools.sort((a, b) => a.name.localeCompare(b.name)),
80
+ resources: resources.sort((a, b) => a.uri.localeCompare(b.uri)),
81
+ prompts: prompts.sort((a, b) => a.name.localeCompare(b.name)),
82
+ };
83
+ }
84
+
85
+ interface ComparisonResult {
86
+ match: boolean;
87
+ missing: string[];
88
+ extra: string[];
89
+ }
90
+
91
+ /**
92
+ * Compare extracted spec against shared spec
93
+ */
94
+ function compareSpecs(
95
+ extracted: Spec,
96
+ shared: Spec,
97
+ ): {
98
+ tools: ComparisonResult;
99
+ resources: ComparisonResult;
100
+ prompts: ComparisonResult;
101
+ } {
102
+ const results = {
103
+ tools: { match: true, missing: [] as string[], extra: [] as string[] },
104
+ resources: { match: true, missing: [] as string[], extra: [] as string[] },
105
+ prompts: { match: true, missing: [] as string[], extra: [] as string[] },
106
+ };
107
+
108
+ // Compare tools by name
109
+ const extractedToolNames = new Set(extracted.tools.map((t) => t.name));
110
+ const sharedToolNames = new Set(shared.tools.map((t) => t.name));
111
+
112
+ results.tools.missing = [...sharedToolNames].filter(
113
+ (n) => !extractedToolNames.has(n),
114
+ );
115
+ results.tools.extra = [...extractedToolNames].filter(
116
+ (n) => !sharedToolNames.has(n),
117
+ );
118
+ results.tools.match =
119
+ results.tools.missing.length === 0 && results.tools.extra.length === 0;
120
+
121
+ // Compare resources by URI
122
+ const extractedResourceUris = new Set(extracted.resources.map((r) => r.uri));
123
+ const sharedResourceUris = new Set(shared.resources.map((r) => r.uri));
124
+
125
+ results.resources.missing = [...sharedResourceUris].filter(
126
+ (u) => !extractedResourceUris.has(u),
127
+ );
128
+ results.resources.extra = [...extractedResourceUris].filter(
129
+ (u) => !sharedResourceUris.has(u),
130
+ );
131
+ results.resources.match =
132
+ results.resources.missing.length === 0 &&
133
+ results.resources.extra.length === 0;
134
+
135
+ // Compare prompts by name
136
+ const extractedPromptNames = new Set(extracted.prompts.map((p) => p.name));
137
+ const sharedPromptNames = new Set(shared.prompts.map((p) => p.name));
138
+
139
+ results.prompts.missing = [...sharedPromptNames].filter(
140
+ (n) => !extractedPromptNames.has(n),
141
+ );
142
+ results.prompts.extra = [...extractedPromptNames].filter(
143
+ (n) => !sharedPromptNames.has(n),
144
+ );
145
+ results.prompts.match =
146
+ results.prompts.missing.length === 0 && results.prompts.extra.length === 0;
147
+
148
+ return results;
149
+ }
150
+
151
+ async function main(): Promise<void> {
152
+ const { values } = parseArgs({
153
+ options: {
154
+ compare: { type: "boolean" },
155
+ output: { type: "string", short: "o" },
156
+ },
157
+ allowPositionals: true,
158
+ });
159
+
160
+ // Create server instance with default config
161
+ const config = new Config();
162
+ const server = createServer(config);
163
+
164
+ // Extract specifications automatically via introspection
165
+ const extracted = extractSpec(server);
166
+
167
+ if (values.compare) {
168
+ const shared = loadSharedSpec();
169
+ const results = compareSpecs(extracted, shared);
170
+
171
+ const allMatch =
172
+ results.tools.match && results.resources.match && results.prompts.match;
173
+
174
+ const output = {
175
+ status: allMatch ? "pass" : "fail",
176
+ comparison: results,
177
+ };
178
+
179
+ console.log(JSON.stringify(output, null, 2));
180
+ process.exit(allMatch ? 0 : 1);
181
+ } else {
182
+ console.log(JSON.stringify(extracted, null, 2));
183
+ }
184
+ }
185
+
186
+ main().catch((error) => {
187
+ console.error("Error:", error);
188
+ process.exit(1);
189
+ });
package/src/index.ts ADDED
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Entry point for MCP Test Kits server (TypeScript)
4
+ */
5
+
6
+ import { parseArgs } from "node:util";
7
+ import { Config } from "./config.js";
8
+ import { createServer } from "./server.js";
9
+ import {
10
+ runStdioServer,
11
+ runHttpServer,
12
+ runSseServer,
13
+ } from "./transports/index.js";
14
+
15
+ function printHelp(): void {
16
+ console.log(`
17
+ MCP Test Kits - A comprehensive MCP testing server
18
+
19
+ Usage:
20
+ mcp-test-kits [options]
21
+
22
+ Options:
23
+ -t, --transport <type> Transport type: stdio, http, sse (default: stdio)
24
+ --host <host> Host to bind to (default: localhost)
25
+ -p, --port <port> Port to listen on (default: 3000)
26
+ -l, --log-level <level> Log level: debug, info, warn, error (default: info)
27
+ --no-tools Disable tools capability
28
+ --no-resources Disable resources capability
29
+ --no-prompts Disable prompts capability
30
+ -v, --version Show version
31
+ -h, --help Show this help
32
+
33
+ Examples:
34
+ # Run with stdio (default)
35
+ mcp-test-kits
36
+
37
+ # Run with HTTP transport
38
+ mcp-test-kits --transport http --port 3000
39
+
40
+ # Run with only tools (no resources or prompts)
41
+ mcp-test-kits --no-resources --no-prompts
42
+ `);
43
+ }
44
+
45
+ async function main(): Promise<void> {
46
+ // Parse command line arguments
47
+ const { values } = parseArgs({
48
+ options: {
49
+ transport: { type: "string", short: "t", default: "stdio" },
50
+ host: { type: "string", default: "localhost" },
51
+ port: { type: "string", short: "p", default: "3000" },
52
+ "log-level": { type: "string", short: "l", default: "info" },
53
+ "no-tools": { type: "boolean", default: false },
54
+ "no-resources": { type: "boolean", default: false },
55
+ "no-prompts": { type: "boolean", default: false },
56
+ version: { type: "boolean", short: "v" },
57
+ help: { type: "boolean", short: "h" },
58
+ },
59
+ allowPositionals: true,
60
+ });
61
+
62
+ if (values.help) {
63
+ printHelp();
64
+ process.exit(0);
65
+ }
66
+
67
+ if (values.version) {
68
+ console.log("mcp-test-kits 1.0.0");
69
+ process.exit(0);
70
+ }
71
+
72
+ // Build config from CLI args
73
+ const transport = values.transport as "stdio" | "http" | "sse";
74
+ const host = values.host as string;
75
+ const port = parseInt(values.port as string, 10);
76
+
77
+ const config = new Config({
78
+ server: { name: "mcp-test-kits", version: "1.0.0" },
79
+ transport: { type: transport, network: { host, port } },
80
+ capabilities: {
81
+ tools: !values["no-tools"],
82
+ resources: !values["no-resources"],
83
+ prompts: !values["no-prompts"],
84
+ },
85
+ });
86
+
87
+ // Create server
88
+ const server = createServer(config);
89
+
90
+ // Run with appropriate transport
91
+ switch (transport) {
92
+ case "stdio":
93
+ await runStdioServer(server, config);
94
+ break;
95
+ case "http":
96
+ await runHttpServer(server, config);
97
+ break;
98
+ case "sse":
99
+ await runSseServer(server, config);
100
+ break;
101
+ default:
102
+ console.error(`Unknown transport type: ${transport}`);
103
+ process.exit(1);
104
+ }
105
+ }
106
+
107
+ main().catch((error) => {
108
+ console.error("Fatal error:", error);
109
+ process.exit(1);
110
+ });