@aashari/boilerplate-mcp-server 1.1.2 → 1.2.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [1.2.0](https://github.com/aashari/boilerplate-mcp-server/compare/v1.1.3...v1.2.0) (2025-04-03)
2
+
3
+
4
+ ### Features
5
+
6
+ * **boilerplate:** improve version handling and module exports ([faa1713](https://github.com/aashari/boilerplate-mcp-server/commit/faa17138ccb1b943197ae91b37a54527481ffbca))
7
+
8
+ ## [1.1.3](https://github.com/aashari/boilerplate-mcp-server/compare/v1.1.2...v1.1.3) (2025-03-28)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * correct TypeScript errors in transport utility ([573a7e6](https://github.com/aashari/boilerplate-mcp-server/commit/573a7e63e1985aa5aefd806c0902462fa34c14d7))
14
+
1
15
  ## [1.1.2](https://github.com/aashari/boilerplate-mcp-server/compare/v1.1.1...v1.1.2) (2025-03-28)
2
16
 
3
17
 
@@ -1 +1,7 @@
1
+ /**
2
+ * Run the CLI with the provided arguments
3
+ *
4
+ * @param args Command line arguments to process
5
+ * @returns Promise that resolves when CLI command execution completes
6
+ */
1
7
  export declare function runCli(args: string[]): Promise<void>;
package/dist/cli/index.js CHANGED
@@ -6,26 +6,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.runCli = runCli;
7
7
  const commander_1 = require("commander");
8
8
  const logger_util_js_1 = require("../utils/logger.util.js");
9
+ const constants_util_js_1 = require("../utils/constants.util.js");
9
10
  const ipaddress_cli_js_1 = __importDefault(require("./ipaddress.cli.js"));
10
- // Get the version from package.json
11
- const VERSION = '1.1.2'; // This should match the version in src/index.ts
12
- const NAME = '@aashari/boilerplate-mcp-server';
11
+ /**
12
+ * CLI entry point for the Boilerplate MCP Server
13
+ * Handles command registration, parsing, and execution
14
+ */
15
+ // Package description
13
16
  const DESCRIPTION = 'A boilerplate Model Context Protocol (MCP) server implementation using TypeScript';
17
+ /**
18
+ * Run the CLI with the provided arguments
19
+ *
20
+ * @param args Command line arguments to process
21
+ * @returns Promise that resolves when CLI command execution completes
22
+ */
14
23
  async function runCli(args) {
15
- const methodLogger = logger_util_js_1.Logger.forContext('cli/index.ts', 'runCli');
16
- methodLogger.debug('Processing CLI arguments', args);
24
+ const cliLogger = logger_util_js_1.Logger.forContext('cli/index.ts', 'runCli');
25
+ cliLogger.debug('Initializing CLI with arguments', args);
17
26
  const program = new commander_1.Command();
18
- program.name(NAME).description(DESCRIPTION).version(VERSION);
27
+ program.name(constants_util_js_1.CLI_NAME).description(DESCRIPTION).version(constants_util_js_1.VERSION);
19
28
  // Register CLI commands
29
+ cliLogger.debug('Registering CLI commands...');
20
30
  ipaddress_cli_js_1.default.register(program);
31
+ cliLogger.debug('CLI commands registered successfully');
21
32
  // Handle unknown commands
22
33
  program.on('command:*', (operands) => {
23
- methodLogger.error(`Unknown command: ${operands[0]}`);
34
+ cliLogger.error(`Unknown command: ${operands[0]}`);
24
35
  console.log('');
25
36
  program.help();
26
37
  process.exit(1);
27
38
  });
28
39
  // Parse arguments; default to help if no command provided
40
+ cliLogger.debug('Parsing CLI arguments');
29
41
  await program.parseAsync(args.length ? args : ['--help'], { from: 'user' });
30
- methodLogger.debug('CLI command execution completed');
42
+ cliLogger.debug('CLI command execution completed');
31
43
  }
@@ -11,8 +11,8 @@ const ipaddress_controller_js_1 = __importDefault(require("../controllers/ipaddr
11
11
  * @param program The Commander program instance
12
12
  */
13
13
  function register(program) {
14
- const methodLogger = logger_util_js_1.Logger.forContext('cli/ipaddress.cli.ts', 'register');
15
- methodLogger.debug(`Registering IP address CLI commands...`);
14
+ const cliLogger = logger_util_js_1.Logger.forContext('cli/ipaddress.cli.ts', 'register');
15
+ cliLogger.debug(`Registering IP address CLI commands...`);
16
16
  program
17
17
  .command('get-ip-details')
18
18
  .description(`Get geolocation and network details about an IP address or the current device.
@@ -31,21 +31,23 @@ function register(program) {
31
31
  .option('--extended', 'Include extended data like ASN, mobile and proxy detection')
32
32
  .option('--https', 'Use HTTPS for API requests (may require paid API key)')
33
33
  .action(async (ipAddress, cmdOptions) => {
34
- const actionLogger = logger_util_js_1.Logger.forContext('cli/ipaddress.cli.ts', 'get-ip-details');
34
+ const commandLogger = logger_util_js_1.Logger.forContext('cli/ipaddress.cli.ts', 'get-ip-details');
35
35
  try {
36
- actionLogger.debug(`Fetching IP details for ${ipAddress || 'current device'}...`, cmdOptions);
36
+ commandLogger.debug(`Processing IP details request for ${ipAddress || 'current device'}`, cmdOptions);
37
37
  // Map CLI options to controller options
38
38
  const controllerOptions = {
39
39
  includeExtendedData: cmdOptions?.extended || false,
40
40
  useHttps: cmdOptions?.https || false,
41
41
  };
42
+ commandLogger.debug('Calling controller with options', controllerOptions);
42
43
  const result = await ipaddress_controller_js_1.default.get(ipAddress, controllerOptions);
43
- actionLogger.debug(`IP details fetched successfully`, result);
44
+ commandLogger.debug(`IP details retrieved successfully`);
44
45
  console.log(result.content);
45
46
  }
46
47
  catch (error) {
47
48
  (0, error_util_js_1.handleCliError)(error);
48
49
  }
49
50
  });
51
+ cliLogger.debug('IP address CLI commands registered successfully');
50
52
  }
51
53
  exports.default = { register };
@@ -1,10 +1,20 @@
1
1
  import { ControllerResponse } from '../types/common.types.js';
2
2
  import { GetIpOptions } from './ipaddress.types.js';
3
3
  /**
4
- * Get IP address details from the IP API.
5
- * @param ipAddress Optional IP address to lookup (omit for current IP)
6
- * @param options Optional configuration for the request
7
- * @returns Controller response with formatted content
4
+ * @namespace IpAddressController
5
+ * @description Controller responsible for handling IP address lookup logic.
6
+ * It orchestrates calls to the ip-api.com service, applies defaults,
7
+ * maps options, and formats the response using the formatter.
8
+ */
9
+ /**
10
+ * @function get
11
+ * @description Fetches details for a specific IP address or the current device's IP.
12
+ * Handles mapping controller options (like includeExtendedData) to service parameters (fields).
13
+ * @memberof IpAddressController
14
+ * @param {string} [ipAddress] - Optional IP address to look up. If omitted, the service will fetch the current device's public IP.
15
+ * @param {GetIpOptions} [options={}] - Optional configuration for the request, such as `includeExtendedData` and `useHttps`.
16
+ * @returns {Promise<ControllerResponse>} A promise that resolves to the standard controller response containing the formatted IP details in Markdown.
17
+ * @throws {McpError} Throws an McpError (handled by `handleControllerError`) if the service call fails or returns an error.
8
18
  */
9
19
  declare function get(ipAddress?: string, options?: GetIpOptions): Promise<ControllerResponse>;
10
20
  declare const _default: {
@@ -9,10 +9,20 @@ const ipaddress_formatter_js_1 = require("./ipaddress.formatter.js");
9
9
  const error_handler_util_js_1 = require("../utils/error-handler.util.js");
10
10
  const defaults_util_js_1 = require("../utils/defaults.util.js");
11
11
  /**
12
- * Get IP address details from the IP API.
13
- * @param ipAddress Optional IP address to lookup (omit for current IP)
14
- * @param options Optional configuration for the request
15
- * @returns Controller response with formatted content
12
+ * @namespace IpAddressController
13
+ * @description Controller responsible for handling IP address lookup logic.
14
+ * It orchestrates calls to the ip-api.com service, applies defaults,
15
+ * maps options, and formats the response using the formatter.
16
+ */
17
+ /**
18
+ * @function get
19
+ * @description Fetches details for a specific IP address or the current device's IP.
20
+ * Handles mapping controller options (like includeExtendedData) to service parameters (fields).
21
+ * @memberof IpAddressController
22
+ * @param {string} [ipAddress] - Optional IP address to look up. If omitted, the service will fetch the current device's public IP.
23
+ * @param {GetIpOptions} [options={}] - Optional configuration for the request, such as `includeExtendedData` and `useHttps`.
24
+ * @returns {Promise<ControllerResponse>} A promise that resolves to the standard controller response containing the formatted IP details in Markdown.
25
+ * @throws {McpError} Throws an McpError (handled by `handleControllerError`) if the service call fails or returns an error.
16
26
  */
17
27
  async function get(ipAddress, options = {}) {
18
28
  const methodLogger = logger_util_js_1.Logger.forContext('controllers/ipaddress.controller.ts', 'get');
package/dist/index.d.ts CHANGED
@@ -1,6 +1,14 @@
1
1
  #!/usr/bin/env node
2
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
3
  import { Logger } from './utils/logger.util.js';
3
4
  import { config } from './utils/config.util.js';
4
- export declare function startServer(mode?: 'stdio' | 'sse'): Promise<void>;
5
+ /**
6
+ * Start the MCP server with the specified transport mode
7
+ *
8
+ * @param mode The transport mode to use (stdio or sse)
9
+ * @returns Promise that resolves to the server instance when started successfully
10
+ */
11
+ export declare function startServer(mode?: 'stdio' | 'sse'): Promise<McpServer>;
5
12
  export { config };
6
13
  export { Logger };
14
+ export { VERSION, PACKAGE_NAME } from './utils/constants.util.js';
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.Logger = exports.config = void 0;
7
+ exports.PACKAGE_NAME = exports.VERSION = exports.Logger = exports.config = void 0;
8
8
  exports.startServer = startServer;
9
9
  const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
10
10
  const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
@@ -13,70 +13,97 @@ Object.defineProperty(exports, "Logger", { enumerable: true, get: function () {
13
13
  const config_util_js_1 = require("./utils/config.util.js");
14
14
  Object.defineProperty(exports, "config", { enumerable: true, get: function () { return config_util_js_1.config; } });
15
15
  const error_util_js_1 = require("./utils/error.util.js");
16
+ const constants_util_js_1 = require("./utils/constants.util.js");
16
17
  const index_js_1 = require("./cli/index.js");
18
+ // Import tools and resources
17
19
  const ipaddress_tool_js_1 = __importDefault(require("./tools/ipaddress.tool.js"));
18
20
  const ipaddress_resource_js_1 = __importDefault(require("./resources/ipaddress.resource.js"));
21
+ /**
22
+ * Boilerplate MCP Server
23
+ *
24
+ * A template project for building MCP servers that follow best practices.
25
+ * Demonstrates proper structure, logging, error handling, and MCP protocol integration.
26
+ */
19
27
  // Create file-level logger
20
28
  const indexLogger = logger_util_js_1.Logger.forContext('index.ts');
21
- // Define version constant for easier management and consistent versioning
22
- const VERSION = '1.1.2';
29
+ // Log initialization at debug level
30
+ indexLogger.debug('Boilerplate MCP server module loaded');
23
31
  let serverInstance = null;
24
32
  let transportInstance = null;
33
+ /**
34
+ * Start the MCP server with the specified transport mode
35
+ *
36
+ * @param mode The transport mode to use (stdio or sse)
37
+ * @returns Promise that resolves to the server instance when started successfully
38
+ */
25
39
  async function startServer(mode = 'stdio') {
26
- const methodLogger = logger_util_js_1.Logger.forContext('index.ts', 'startServer');
40
+ const serverLogger = logger_util_js_1.Logger.forContext('index.ts', 'startServer');
27
41
  // Load configuration
42
+ serverLogger.info('Starting MCP server initialization...');
28
43
  config_util_js_1.config.load();
44
+ serverLogger.info('Configuration loaded successfully');
29
45
  // Enable debug logging if DEBUG is set to true
30
46
  if (config_util_js_1.config.getBoolean('DEBUG')) {
31
- methodLogger.debug('Debug mode enabled');
47
+ serverLogger.debug('Debug mode enabled');
32
48
  }
33
49
  // Log the DEBUG value to verify configuration loading
34
- methodLogger.info(`DEBUG value: ${process.env.DEBUG}`);
35
- methodLogger.info(`IPAPI_API_TOKEN value exists: ${Boolean(process.env.IPAPI_API_TOKEN)}`);
36
- methodLogger.info(`Config DEBUG value: ${config_util_js_1.config.get('DEBUG')}`);
50
+ serverLogger.debug(`DEBUG environment variable: ${process.env.DEBUG}`);
51
+ serverLogger.debug(`IPAPI_API_TOKEN value exists: ${Boolean(process.env.IPAPI_API_TOKEN)}`);
52
+ serverLogger.debug(`Config DEBUG value: ${config_util_js_1.config.get('DEBUG')}`);
53
+ serverLogger.info(`Initializing Boilerplate MCP server v${constants_util_js_1.VERSION}`);
37
54
  serverInstance = new mcp_js_1.McpServer({
38
- name: '@aashari/boilerplate-mcp-server',
39
- version: VERSION,
55
+ name: constants_util_js_1.PACKAGE_NAME,
56
+ version: constants_util_js_1.VERSION,
40
57
  });
41
58
  if (mode === 'stdio') {
59
+ serverLogger.info('Using STDIO transport for MCP communication');
42
60
  transportInstance = new stdio_js_1.StdioServerTransport();
43
61
  }
44
62
  else {
45
63
  throw (0, error_util_js_1.createUnexpectedError)('SSE mode is not supported yet');
46
64
  }
47
- methodLogger.info(`Starting server with ${mode.toUpperCase()} transport...`);
48
- // register tools
65
+ // Register tools and resources
66
+ serverLogger.info('Registering MCP tools and resources...');
49
67
  ipaddress_tool_js_1.default.register(serverInstance);
50
- methodLogger.debug('Registered IP address tools');
51
- // register resources
68
+ serverLogger.debug('Registered IP address tools');
52
69
  ipaddress_resource_js_1.default.register(serverInstance);
53
- methodLogger.debug('Registered IP lookup resources');
54
- return serverInstance.connect(transportInstance).catch((err) => {
55
- methodLogger.error(`Failed to start server`, err);
70
+ serverLogger.debug('Registered IP lookup resources');
71
+ serverLogger.info('All tools and resources registered successfully');
72
+ try {
73
+ serverLogger.info(`Connecting to ${mode.toUpperCase()} transport...`);
74
+ await serverInstance.connect(transportInstance);
75
+ serverLogger.info('MCP server started successfully and ready to process requests');
76
+ return serverInstance;
77
+ }
78
+ catch (err) {
79
+ serverLogger.error(`Failed to start server`, err);
56
80
  process.exit(1);
57
- });
81
+ }
58
82
  }
59
- // Main entry point - this will run when executed directly
83
+ /**
84
+ * Main entry point - this will run when executed directly
85
+ * Determines whether to run in CLI or server mode based on command-line arguments
86
+ */
60
87
  async function main() {
61
- const methodLogger = logger_util_js_1.Logger.forContext('index.ts', 'main');
88
+ const mainLogger = logger_util_js_1.Logger.forContext('index.ts', 'main');
62
89
  // Load configuration
63
90
  config_util_js_1.config.load();
64
91
  // Log the DEBUG value to verify configuration loading
65
- methodLogger.info(`DEBUG value: ${process.env.DEBUG}`);
66
- methodLogger.info(`IPAPI_API_TOKEN value exists: ${Boolean(process.env.IPAPI_API_TOKEN)}`);
67
- methodLogger.info(`Config DEBUG value: ${config_util_js_1.config.get('DEBUG')}`);
92
+ mainLogger.debug(`DEBUG environment variable: ${process.env.DEBUG}`);
93
+ mainLogger.debug(`IPAPI_API_TOKEN value exists: ${Boolean(process.env.IPAPI_API_TOKEN)}`);
94
+ mainLogger.debug(`Config DEBUG value: ${config_util_js_1.config.get('DEBUG')}`);
68
95
  // Check if arguments are provided (CLI mode)
69
96
  if (process.argv.length > 2) {
70
97
  // CLI mode: Pass arguments to CLI runner
71
- methodLogger.info('Starting in CLI mode');
98
+ mainLogger.info('Starting in CLI mode');
72
99
  await (0, index_js_1.runCli)(process.argv.slice(2));
73
- methodLogger.info('CLI execution completed');
100
+ mainLogger.info('CLI execution completed');
74
101
  }
75
102
  else {
76
103
  // MCP Server mode: Start server with default STDIO
77
- methodLogger.info('Starting in server mode');
104
+ mainLogger.info('Starting in server mode');
78
105
  await startServer();
79
- methodLogger.info('Server is now running');
106
+ mainLogger.info('Server is now running');
80
107
  }
81
108
  }
82
109
  // If this file is being executed directly (not imported), run the main function
@@ -86,3 +113,6 @@ if (require.main === module) {
86
113
  process.exit(1);
87
114
  });
88
115
  }
116
+ var constants_util_js_2 = require("./utils/constants.util.js");
117
+ Object.defineProperty(exports, "VERSION", { enumerable: true, get: function () { return constants_util_js_2.VERSION; } });
118
+ Object.defineProperty(exports, "PACKAGE_NAME", { enumerable: true, get: function () { return constants_util_js_2.PACKAGE_NAME; } });
@@ -1,10 +1,27 @@
1
1
  import { IPDetail, IPApiRequestOptions } from './vendor.ip-api.com.types.js';
2
2
  /**
3
- * Get details for an IP address
4
- * @param ipAddress Optional IP address to lookup (omit for current IP)
5
- * @param options Optional request options
6
- * @returns Promise containing the IP details
7
- * @throws {McpError} If the request fails or the API returns an error
3
+ * @namespace VendorIpApiService
4
+ * @description Service layer for interacting directly with the ip-api.com vendor API.
5
+ * Responsible for constructing API requests based on provided parameters
6
+ * and handling the raw response from the `fetchIpApi` utility.
7
+ */
8
+ /**
9
+ * @function get
10
+ * @description Fetches details for a specific IP address or the current device's IP from ip-api.com.
11
+ * It uses the `fetchIpApi` utility and handles the specific success/failure status returned by ip-api.com.
12
+ * @memberof VendorIpApiService
13
+ * @param {string} [ipAddress] - Optional IP address to look up. If omitted, fetches details for the current device's public IP.
14
+ * @param {IPApiRequestOptions} [options={}] - Optional request options for the ip-api.com service, such as `useHttps`, `fields`, and `lang`.
15
+ * @returns {Promise<IPDetail>} A promise that resolves to the detailed IP information if the API call is successful.
16
+ * @throws {McpError} Throws an `McpError` (specifically `ApiError` or `UnexpectedError`) if:
17
+ * - The `fetchIpApi` call fails (network error, non-2xx response).
18
+ * - The ip-api.com response status is not 'success'.
19
+ * - An unexpected error occurs during processing.
20
+ * @example
21
+ * // Get basic details for 8.8.8.8
22
+ * const details = await get('8.8.8.8');
23
+ * // Get extended details using HTTPS
24
+ * const extendedDetails = await get('1.1.1.1', { useHttps: true, fields: [...] });
8
25
  */
9
26
  declare function get(ipAddress?: string, options?: IPApiRequestOptions): Promise<IPDetail>;
10
27
  declare const _default: {
@@ -8,11 +8,28 @@ const serviceLogger = logger_util_js_1.Logger.forContext('services/vendor.ip-api
8
8
  // Log service initialization
9
9
  serviceLogger.debug('IP API service initialized');
10
10
  /**
11
- * Get details for an IP address
12
- * @param ipAddress Optional IP address to lookup (omit for current IP)
13
- * @param options Optional request options
14
- * @returns Promise containing the IP details
15
- * @throws {McpError} If the request fails or the API returns an error
11
+ * @namespace VendorIpApiService
12
+ * @description Service layer for interacting directly with the ip-api.com vendor API.
13
+ * Responsible for constructing API requests based on provided parameters
14
+ * and handling the raw response from the `fetchIpApi` utility.
15
+ */
16
+ /**
17
+ * @function get
18
+ * @description Fetches details for a specific IP address or the current device's IP from ip-api.com.
19
+ * It uses the `fetchIpApi` utility and handles the specific success/failure status returned by ip-api.com.
20
+ * @memberof VendorIpApiService
21
+ * @param {string} [ipAddress] - Optional IP address to look up. If omitted, fetches details for the current device's public IP.
22
+ * @param {IPApiRequestOptions} [options={}] - Optional request options for the ip-api.com service, such as `useHttps`, `fields`, and `lang`.
23
+ * @returns {Promise<IPDetail>} A promise that resolves to the detailed IP information if the API call is successful.
24
+ * @throws {McpError} Throws an `McpError` (specifically `ApiError` or `UnexpectedError`) if:
25
+ * - The `fetchIpApi` call fails (network error, non-2xx response).
26
+ * - The ip-api.com response status is not 'success'.
27
+ * - An unexpected error occurs during processing.
28
+ * @example
29
+ * // Get basic details for 8.8.8.8
30
+ * const details = await get('8.8.8.8');
31
+ * // Get extended details using HTTPS
32
+ * const extendedDetails = await get('1.1.1.1', { useHttps: true, fields: [...] });
16
33
  */
17
34
  async function get(ipAddress, options = {}) {
18
35
  const methodLogger = logger_util_js_1.Logger.forContext('services/vendor.ip-api.com.service.ts', 'get');
@@ -1,6 +1,9 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  /**
3
- * Register IP address tools with the MCP server
3
+ * @function register
4
+ * @description Registers the IP address lookup tool ('get-ip-details') with the MCP server.
5
+ *
6
+ * @param {McpServer} server - The MCP server instance.
4
7
  */
5
8
  declare function register(server: McpServer): void;
6
9
  declare const _default: {
@@ -8,8 +8,14 @@ const ipaddress_types_js_1 = require("./ipaddress.types.js");
8
8
  const error_util_js_1 = require("../utils/error.util.js");
9
9
  const ipaddress_controller_js_1 = __importDefault(require("../controllers/ipaddress.controller.js"));
10
10
  /**
11
- * Get IP Address details using the controller.
12
- * Maps tool arguments to controller options and formats the response.
11
+ * @function getIpAddressDetails
12
+ * @description MCP Tool handler to retrieve details for a given IP address (or the current IP).
13
+ * It calls the ipAddressController to fetch the data and formats the response for the MCP.
14
+ *
15
+ * @param {IpAddressToolArgsType} args - Arguments provided to the tool, including the optional IP address and options.
16
+ * @param {RequestHandlerExtra} _extra - Additional request context (unused).
17
+ * @returns {Promise<{ content: Array<{ type: 'text', text: string }> }>} Formatted response for the MCP.
18
+ * @throws {McpError} Formatted error if the controller or service layer encounters an issue.
13
19
  */
14
20
  async function getIpAddressDetails(args, _extra) {
15
21
  const methodLogger = logger_util_js_1.Logger.forContext('tools/ipaddress.tool.ts', 'getIpAddressDetails');
@@ -39,14 +45,18 @@ async function getIpAddressDetails(args, _extra) {
39
45
  }
40
46
  }
41
47
  /**
42
- * Register IP address tools with the MCP server
48
+ * @function register
49
+ * @description Registers the IP address lookup tool ('get-ip-details') with the MCP server.
50
+ *
51
+ * @param {McpServer} server - The MCP server instance.
43
52
  */
44
53
  function register(server) {
45
54
  const methodLogger = logger_util_js_1.Logger.forContext('tools/ipaddress.tool.ts', 'register');
46
55
  methodLogger.debug(`Registering IP address tools...`);
47
56
  server.tool('get-ip-details', `Get details about a specific IP address or the current device's public IP address.
48
57
 
49
- PURPOSE: Retrieves geolocation information (country, city, region, coordinates), ISP, and organization details associated with an IP address. Provides network and geographical context for an IP, which is useful for security analysis, debugging, or location verification.
58
+ PURPOSE:
59
+ Retrieves geolocation information (country, city, region, coordinates), ISP, and organization details associated with an IP address. Provides network and geographical context for an IP, which is useful for security analysis, debugging, or location verification.
50
60
 
51
61
  WHEN TO USE:
52
62
  - To find the geographical location of a given IP address (country, region, city, coordinates).
@@ -57,34 +67,33 @@ function register(server) {
57
67
  - When investigating suspicious IP addresses in logs.
58
68
 
59
69
  WHEN NOT TO USE:
60
- - For internal/private IP addresses (10.x.x.x, 192.168.x.x, etc.) as this tool queries a public database.
70
+ - For internal/private IP addresses (e.g., 10.x.x.x, 192.168.x.x) as this tool queries a public database.
61
71
  - When you need historical IP data (this provides current lookup only).
62
- - For precise geolocation (IP geolocation has limited accuracy, especially in rural areas).
72
+ - For precise geolocation (IP geolocation accuracy is limited).
63
73
  - For operations other than retrieving IP geolocation details.
64
- - When you need to process large batches of IPs (use appropriate rate limiting).
74
+ - When processing large batches of IPs without considering rate limits.
65
75
 
66
- RETURNS: Formatted Markdown containing:
76
+ RETURNS:
77
+ Formatted Markdown containing:
67
78
  - Location information (country, region, city, postal code, coordinates)
68
- - Network details (ISP, organization, AS number)
69
- - A link to view the location on a map
70
- - Timestamp of when the information was retrieved
71
-
72
- With extended data (when includeExtendedData=true), additional information may include:
73
- - Mobile network detection
74
- - Proxy/VPN detection
75
- - Hosting provider detection
76
- - Reverse DNS information
79
+ - Network details (ISP, organization, AS number/name)
80
+ - A link to view the location on a map.
81
+ - Timestamp of when the information was retrieved.
82
+ - With 'includeExtendedData=true', additional details like reverse DNS, mobile/proxy/hosting detection may be included.
77
83
 
78
84
  EXAMPLES:
79
85
  - Get details for a specific IP: { ipAddress: "8.8.8.8" }
80
- - Get details with extended data: { ipAddress: "8.8.8.8", includeExtendedData: true }
81
- - Get details for current device with HTTPS: { useHttps: true }
86
+ - Get details with extended data: { ipAddress: "1.1.1.1", includeExtendedData: true }
87
+ - Get details for current device using HTTPS: { useHttps: true }
82
88
  - Get basic details for current device: {}
83
89
 
84
90
  ERRORS:
85
- - Invalid IP format: If the provided 'ipAddress' is not a valid IP address format.
86
- - Private/Reserved IP: If the IP address is in a private or reserved range.
87
- - API errors: If the external ip-api.com service fails or rejects the request.
88
- - Rate limiting: If too many requests are made in a short period.`, ipaddress_types_js_1.IpAddressToolArgs.shape, getIpAddressDetails);
91
+ - Invalid IP format: If 'ipAddress' is not a valid IPv4 or IPv6 format.
92
+ - Private/Reserved IP: If the IP address is in a private or reserved range (per ip-api.com rules).
93
+ - API errors: If the external ip-api.com service fails, rejects the request (e.g., bad token), or returns an error status.
94
+ - Rate limiting: If the ip-api.com service rate limits the request.
95
+ - Network errors: If the request to ip-api.com fails due to network issues.`, // Keep Zod schema reference
96
+ ipaddress_types_js_1.IpAddressToolArgs.shape, getIpAddressDetails);
97
+ methodLogger.debug('Successfully registered get-ip-details tool.');
89
98
  }
90
99
  exports.default = { register };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Application constants
3
+ *
4
+ * This file contains constants used throughout the application.
5
+ * Centralizing these values makes them easier to maintain and update.
6
+ */
7
+ /**
8
+ * Current application version
9
+ * This should match the version in package.json
10
+ */
11
+ export declare const VERSION = "1.2.0";
12
+ /**
13
+ * Package name with scope
14
+ * Used for initialization and identification
15
+ */
16
+ export declare const PACKAGE_NAME = "@aashari/boilerplate-mcp-server";
17
+ /**
18
+ * CLI command name
19
+ * Used for binary name and CLI help text
20
+ */
21
+ export declare const CLI_NAME = "mcp-boilerplate";
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /**
3
+ * Application constants
4
+ *
5
+ * This file contains constants used throughout the application.
6
+ * Centralizing these values makes them easier to maintain and update.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.CLI_NAME = exports.PACKAGE_NAME = exports.VERSION = void 0;
10
+ /**
11
+ * Current application version
12
+ * This should match the version in package.json
13
+ */
14
+ exports.VERSION = '1.2.0';
15
+ /**
16
+ * Package name with scope
17
+ * Used for initialization and identification
18
+ */
19
+ exports.PACKAGE_NAME = '@aashari/boilerplate-mcp-server';
20
+ /**
21
+ * CLI command name
22
+ * Used for binary name and CLI help text
23
+ */
24
+ exports.CLI_NAME = 'mcp-boilerplate';
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /**
3
+ * Application constants
4
+ *
5
+ * This file contains constants used throughout the application.
6
+ * Centralizing these values makes them easier to maintain and update.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.CLI_NAME = exports.PACKAGE_NAME = exports.VERSION = void 0;
10
+ /**
11
+ * Current application version
12
+ * This should match the version in package.json
13
+ */
14
+ exports.VERSION = '1.1.3';
15
+ /**
16
+ * Package name with scope
17
+ * Used for initialization and identification
18
+ */
19
+ exports.PACKAGE_NAME = '@aashari/boilerplate-mcp-server';
20
+ /**
21
+ * CLI command name
22
+ * Used for binary name and CLI help text
23
+ */
24
+ exports.CLI_NAME = 'mcp-boilerplate';
@@ -1,8 +1,9 @@
1
1
  /**
2
- * Interface for IP API credentials
2
+ * Interface for IP API credentials.
3
+ * Note: API token is optional for the free tier.
3
4
  */
4
5
  export interface IpApiCredentials {
5
- apiToken: string | undefined;
6
+ apiToken?: string;
6
7
  }
7
8
  /**
8
9
  * Interface for HTTP request options
@@ -13,16 +14,23 @@ export interface RequestOptions {
13
14
  body?: unknown;
14
15
  }
15
16
  /**
16
- * Get IP API credentials from environment variables
17
- * @returns IpApiCredentials object containing the API token (which may be undefined if not set)
17
+ * Retrieves IP API credentials from configuration.
18
+ * Specifically checks for IPAPI_API_TOKEN.
19
+ * @returns IpApiCredentials object containing the API token if found.
18
20
  */
19
21
  export declare function getIpApiCredentials(): IpApiCredentials;
20
22
  /**
21
- * Fetch data from IP API
22
- * @param path The path/IP address to fetch data for
23
- * @param options Request options (method, headers, body, useHttps, fields, lang)
24
- * @returns Response data as type T
25
- * @throws {McpError} If the fetch fails or the response is not ok
23
+ * Fetches data specifically from the ip-api.com endpoint.
24
+ * Handles URL construction, authentication (if token provided), and query parameters.
25
+ * Relies on the generic fetchApi function for the actual HTTP request.
26
+ *
27
+ * @param path The specific IP address or path component (e.g., "8.8.8.8"). Empty string for current IP.
28
+ * @param options Additional options like HTTP method, headers, body, and ip-api specific params.
29
+ * @param options.useHttps - Use HTTPS (requires paid plan for ip-api.com). Defaults to false.
30
+ * @param options.fields - Specific fields to request from ip-api.com.
31
+ * @param options.lang - Language code for response data.
32
+ * @returns The response data parsed as type T.
33
+ * @throws {McpError} If the request fails, including network errors, API errors, or parsing issues.
26
34
  */
27
35
  export declare function fetchIpApi<T>(path: string, options?: RequestOptions & {
28
36
  useHttps?: boolean;
@@ -30,11 +38,12 @@ export declare function fetchIpApi<T>(path: string, options?: RequestOptions & {
30
38
  lang?: string;
31
39
  }): Promise<T>;
32
40
  /**
33
- * Generic function to fetch data from an API endpoint.
34
- * Handles basic HTTP error checking and logging.
41
+ * Generic and reusable function to fetch data from any API endpoint.
42
+ * Handles standard HTTP request setup, response checking, basic error handling, and logging.
43
+ *
35
44
  * @param url The full URL to fetch data from.
36
- * @param options Request options (method, headers, body).
37
- * @returns Response data as type T.
38
- * @throws {McpError} If the fetch fails or the response is not ok.
45
+ * @param options Request options including method, headers, and body.
46
+ * @returns The response data parsed as type T.
47
+ * @throws {McpError} If the request fails, including network errors, non-OK HTTP status, or JSON parsing issues.
39
48
  */
40
49
  export declare function fetchApi<T>(url: string, options?: RequestOptions): Promise<T>;
@@ -11,64 +11,69 @@ const transportLogger = logger_util_js_1.Logger.forContext('utils/transport.util
11
11
  // Log transport utility initialization
12
12
  transportLogger.debug('Transport utility initialized');
13
13
  /**
14
- * Get IP API credentials from environment variables
15
- * @returns IpApiCredentials object containing the API token (which may be undefined if not set)
14
+ * Retrieves IP API credentials from configuration.
15
+ * Specifically checks for IPAPI_API_TOKEN.
16
+ * @returns IpApiCredentials object containing the API token if found.
16
17
  */
17
18
  function getIpApiCredentials() {
18
19
  const methodLogger = logger_util_js_1.Logger.forContext('utils/transport.util.ts', 'getIpApiCredentials');
19
20
  const apiToken = config_util_js_1.config.get('IPAPI_API_TOKEN');
20
21
  if (!apiToken) {
21
- methodLogger.debug('No IP API token found. The API will be used in free tier mode.');
22
+ methodLogger.debug('No IP API token found (IPAPI_API_TOKEN). Using free tier.');
23
+ return {}; // Return empty object if no token
22
24
  }
23
25
  else {
24
- methodLogger.debug('Using IP API token from configuration');
26
+ methodLogger.debug('Using IP API token from configuration.');
27
+ return { apiToken };
25
28
  }
26
- return {
27
- apiToken,
28
- };
29
29
  }
30
30
  /**
31
- * Fetch data from IP API
32
- * @param path The path/IP address to fetch data for
33
- * @param options Request options (method, headers, body, useHttps, fields, lang)
34
- * @returns Response data as type T
35
- * @throws {McpError} If the fetch fails or the response is not ok
31
+ * Fetches data specifically from the ip-api.com endpoint.
32
+ * Handles URL construction, authentication (if token provided), and query parameters.
33
+ * Relies on the generic fetchApi function for the actual HTTP request.
34
+ *
35
+ * @param path The specific IP address or path component (e.g., "8.8.8.8"). Empty string for current IP.
36
+ * @param options Additional options like HTTP method, headers, body, and ip-api specific params.
37
+ * @param options.useHttps - Use HTTPS (requires paid plan for ip-api.com). Defaults to false.
38
+ * @param options.fields - Specific fields to request from ip-api.com.
39
+ * @param options.lang - Language code for response data.
40
+ * @returns The response data parsed as type T.
41
+ * @throws {McpError} If the request fails, including network errors, API errors, or parsing issues.
36
42
  */
37
43
  async function fetchIpApi(path, options = {}) {
38
44
  const methodLogger = logger_util_js_1.Logger.forContext('utils/transport.util.ts', 'fetchIpApi');
39
- // Get credentials
45
+ // Get credentials (token might be undefined)
40
46
  const credentials = getIpApiCredentials();
41
- // Construct the full URL
42
- // Use https if explicitly requested
47
+ // Determine protocol based on options
43
48
  const protocol = options.useHttps ? 'https' : 'http';
44
49
  const baseUrl = `${protocol}://ip-api.com/json`;
45
- // Ensure path is formatted correctly
50
+ // Format path for URL
46
51
  const normalizedPath = path ? `/${path}` : '';
47
52
  let url = `${baseUrl}${normalizedPath}`;
48
- // Prepare query parameters
53
+ // Build query parameters
49
54
  const queryParams = new URLSearchParams();
50
- // Add API token if available
55
+ // Add API token if present
51
56
  if (credentials.apiToken) {
52
57
  queryParams.set('key', credentials.apiToken);
53
- methodLogger.debug('Added API token to request');
58
+ methodLogger.debug('API token added to query parameters.');
54
59
  }
55
- // Add fields if specified
56
- if (options.fields && options.fields.length > 0) {
60
+ // Add fields parameter
61
+ if (options.fields?.length) {
57
62
  queryParams.set('fields', options.fields.join(','));
58
- methodLogger.debug(`Set fields to: ${options.fields.join(',')}`);
63
+ methodLogger.debug(`Requesting fields: ${options.fields.join(',')}`);
59
64
  }
60
- // Add language if specified
65
+ // Add language parameter
61
66
  if (options.lang) {
62
67
  queryParams.set('lang', options.lang);
63
- methodLogger.debug(`Set language to: ${options.lang}`);
68
+ methodLogger.debug(`Requesting language: ${options.lang}`);
64
69
  }
65
- // Append query parameters if any
70
+ // Append query string if needed
66
71
  const queryString = queryParams.toString();
67
72
  if (queryString) {
68
73
  url += `?${queryString}`;
69
74
  }
70
- methodLogger.debug(`Calling IP API: ${url}`);
71
- // Use the generic fetchApi function with the constructed URL
75
+ methodLogger.debug(`Constructed URL: ${url}`);
76
+ // Delegate the actual fetch call to the generic fetchApi
72
77
  return fetchApi(url, {
73
78
  method: options.method,
74
79
  headers: options.headers,
@@ -76,68 +81,83 @@ async function fetchIpApi(path, options = {}) {
76
81
  });
77
82
  }
78
83
  /**
79
- * Generic function to fetch data from an API endpoint.
80
- * Handles basic HTTP error checking and logging.
84
+ * Generic and reusable function to fetch data from any API endpoint.
85
+ * Handles standard HTTP request setup, response checking, basic error handling, and logging.
86
+ *
81
87
  * @param url The full URL to fetch data from.
82
- * @param options Request options (method, headers, body).
83
- * @returns Response data as type T.
84
- * @throws {McpError} If the fetch fails or the response is not ok.
88
+ * @param options Request options including method, headers, and body.
89
+ * @returns The response data parsed as type T.
90
+ * @throws {McpError} If the request fails, including network errors, non-OK HTTP status, or JSON parsing issues.
85
91
  */
86
92
  async function fetchApi(url, options = {}) {
87
93
  const methodLogger = logger_util_js_1.Logger.forContext('utils/transport.util.ts', 'fetchApi');
88
- // Prepare request options
94
+ // Prepare standard request options
89
95
  const requestOptions = {
90
96
  method: options.method || 'GET',
91
97
  headers: {
98
+ // Standard headers, allow overrides via options.headers
92
99
  'Content-Type': 'application/json',
93
100
  Accept: 'application/json',
94
- ...options.headers, // Allow overriding default headers
101
+ ...options.headers,
95
102
  },
96
103
  body: options.body ? JSON.stringify(options.body) : undefined,
97
104
  };
98
- methodLogger.debug(`Calling API: ${requestOptions.method} ${url}`);
105
+ methodLogger.debug(`Executing API call: ${requestOptions.method} ${url}`);
106
+ const startTime = performance.now(); // Track performance
99
107
  try {
100
108
  const response = await fetch(url, requestOptions);
101
- // Log the raw response status and headers
102
- methodLogger.debug(`Raw response received: ${response.status} ${response.statusText}`, {
103
- url,
104
- status: response.status,
105
- statusText: response.statusText,
106
- headers: {
107
- // Log simplified headers
108
- contentType: response.headers.get('content-type'),
109
- contentLength: response.headers.get('content-length'),
110
- },
111
- });
109
+ const endTime = performance.now();
110
+ const duration = (endTime - startTime).toFixed(2);
111
+ methodLogger.debug(`API call completed in ${duration}ms with status: ${response.status} ${response.statusText}`, { url, status: response.status });
112
+ // Check if the response status is OK (2xx)
112
113
  if (!response.ok) {
113
- const errorText = await response.text();
114
- methodLogger.error(`API error: ${response.status} ${response.statusText}`, errorText);
115
- // Create a generic API error
116
- throw (0, error_util_js_1.createApiError)(`API request failed: ${response.status} ${response.statusText}`, response.status, errorText);
114
+ const errorText = await response.text(); // Get error body for context
115
+ methodLogger.error(`API error response (${response.status}):`, errorText);
116
+ // Classify standard HTTP errors
117
+ if (response.status === 401) {
118
+ // Use createAuthInvalidError for consistency, even if ip-api uses keys
119
+ throw (0, error_util_js_1.createAuthInvalidError)('Authentication failed. Check API token if required.');
120
+ }
121
+ else if (response.status === 403) {
122
+ // Use createAuthInvalidError or a more specific permission error if needed
123
+ throw (0, error_util_js_1.createAuthInvalidError)('Permission denied for the requested resource.');
124
+ }
125
+ else if (response.status === 404) {
126
+ throw (0, error_util_js_1.createApiError)('Resource not found at the specified URL.', response.status, errorText);
127
+ }
128
+ else {
129
+ // Generic API error for other non-2xx statuses
130
+ throw (0, error_util_js_1.createApiError)(`API request failed with status ${response.status}: ${response.statusText}`, response.status, errorText);
131
+ }
132
+ }
133
+ // Attempt to parse the response body as JSON
134
+ try {
135
+ const responseData = await response.json();
136
+ methodLogger.debug('Response body successfully parsed as JSON.');
137
+ // methodLogger.debug('Response Data:', responseData); // Uncomment for full response logging
138
+ return responseData;
139
+ }
140
+ catch (parseError) {
141
+ methodLogger.error('Failed to parse API response JSON:', parseError);
142
+ // Throw a specific error for JSON parsing failure
143
+ throw (0, error_util_js_1.createApiError)(`Failed to parse API response JSON: ${parseError instanceof Error ? parseError.message : String(parseError)}`, response.status, // Include original status for context
144
+ parseError);
117
145
  }
118
- // Attempt to parse JSON
119
- const responseData = await response.json();
120
- methodLogger.debug(`Response body parsed successfully.`);
121
- // methodLogger.debug(`Response body:`, responseData); // Optionally log full body
122
- return responseData;
123
146
  }
124
147
  catch (error) {
125
- methodLogger.error(`Request failed for ${url}`, error);
126
- // Rethrow known McpErrors (like the one from createApiError)
148
+ const endTime = performance.now();
149
+ const duration = (endTime - startTime).toFixed(2);
150
+ methodLogger.error(`API call failed after ${duration}ms for ${url}:`, error);
151
+ // Rethrow if it's already an McpError (e.g., from status checks or parsing)
127
152
  if (error instanceof error_util_js_1.McpError) {
128
153
  throw error;
129
154
  }
130
- // Handle network or fetch-specific errors
155
+ // Handle potential network errors (TypeError in fetch)
131
156
  if (error instanceof TypeError) {
132
157
  throw (0, error_util_js_1.createApiError)(`Network error during API call: ${error.message}`, undefined, // No specific HTTP status for network errors
133
158
  error);
134
159
  }
135
- // Handle JSON parsing errors
136
- if (error instanceof SyntaxError) {
137
- throw (0, error_util_js_1.createApiError)(`Failed to parse API response JSON: ${error.message}`, undefined, // No specific HTTP status for parsing errors
138
- error);
139
- }
140
- // Wrap unknown errors
160
+ // Wrap any other unexpected errors
141
161
  throw (0, error_util_js_1.createUnexpectedError)(`Unexpected error during API call: ${error instanceof Error ? error.message : String(error)}`, error);
142
162
  }
143
163
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aashari/boilerplate-mcp-server",
3
- "version": "1.1.2",
4
- "description": "A TypeScript-based Model Context Protocol (MCP) server boilerplate for building AI-connected tools. Features IP lookup tools, CLI support, MCP Inspector integration, and extensible architecture for connecting Claude/Anthropic AI systems to external data sources.",
3
+ "version": "1.2.0",
4
+ "description": "TypeScript Model Context Protocol (MCP) server boilerplate providing IP lookup tools/resources. Includes CLI support and extensible structure for connecting AI systems (LLMs) to external data sources like ip-api.com. Ideal template for creating new MCP integrations via Node.js.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "_moduleNotes": "Although source code uses ESM syntax, the build output target is CommonJS to align with Node.js compatibility and patterns seen in related MCP servers. tsconfig.json's 'module': 'NodeNext' handles the input syntax, while tsc outputs CJS.",
package/package.json.bak CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aashari/boilerplate-mcp-server",
3
- "version": "1.1.1",
4
- "description": "A TypeScript-based Model Context Protocol (MCP) server boilerplate for building AI-connected tools. Features IP lookup tools, CLI support, MCP Inspector integration, and extensible architecture for connecting Claude/Anthropic AI systems to external data sources.",
3
+ "version": "1.1.3",
4
+ "description": "TypeScript Model Context Protocol (MCP) server boilerplate providing IP lookup tools/resources. Includes CLI support and extensible structure for connecting AI systems (LLMs) to external data sources like ip-api.com. Ideal template for creating new MCP integrations via Node.js.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "_moduleNotes": "Although source code uses ESM syntax, the build output target is CommonJS to align with Node.js compatibility and patterns seen in related MCP servers. tsconfig.json's 'module': 'NodeNext' handles the input syntax, while tsc outputs CJS.",
@@ -45,28 +45,15 @@ const versionFiles = [
45
45
  match.replace(currentVersion, newVersion),
46
46
  },
47
47
  {
48
- path: path.join(rootDir, 'src', 'cli', 'index.ts'),
49
- pattern: /const VERSION = ['"]([^'"]*)['"]/,
50
- replacement: (match, currentVersion) =>
51
- match.replace(currentVersion, newVersion),
52
- },
53
- {
54
- path: path.join(rootDir, 'src', 'index.ts'),
55
- pattern: /const VERSION = ['"]([^'"]*)['"]/,
48
+ path: path.join(rootDir, 'src', 'utils', 'constants.util.ts'),
49
+ pattern: /export const VERSION = ['"]([^'"]*)['"]/,
56
50
  replacement: (match, currentVersion) =>
57
51
  match.replace(currentVersion, newVersion),
58
52
  },
59
53
  // Also update the compiled JavaScript files if they exist
60
54
  {
61
- path: path.join(rootDir, 'dist', 'cli', 'index.js'),
62
- pattern: /const VERSION = ['"]([^'"]*)['"]/,
63
- replacement: (match, currentVersion) =>
64
- match.replace(currentVersion, newVersion),
65
- optional: true, // Mark this file as optional
66
- },
67
- {
68
- path: path.join(rootDir, 'dist', 'index.js'),
69
- pattern: /const VERSION = ['"]([^'"]*)['"]/,
55
+ path: path.join(rootDir, 'dist', 'utils', 'constants.util.js'),
56
+ pattern: /exports.VERSION = ['"]([^'"]*)['"]/,
70
57
  replacement: (match, currentVersion) =>
71
58
  match.replace(currentVersion, newVersion),
72
59
  optional: true, // Mark this file as optional
@@ -1,31 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.runCli = runCli;
7
- const commander_1 = require("commander");
8
- const logger_util_js_1 = require("../utils/logger.util.js");
9
- const ipaddress_cli_js_1 = __importDefault(require("./ipaddress.cli.js"));
10
- // Get the version from package.json
11
- const VERSION = '1.1.1'; // This should match the version in src/index.ts
12
- const NAME = '@aashari/boilerplate-mcp-server';
13
- const DESCRIPTION = 'A boilerplate Model Context Protocol (MCP) server implementation using TypeScript';
14
- async function runCli(args) {
15
- const methodLogger = logger_util_js_1.Logger.forContext('cli/index.ts', 'runCli');
16
- methodLogger.debug('Processing CLI arguments', args);
17
- const program = new commander_1.Command();
18
- program.name(NAME).description(DESCRIPTION).version(VERSION);
19
- // Register CLI commands
20
- ipaddress_cli_js_1.default.register(program);
21
- // Handle unknown commands
22
- program.on('command:*', (operands) => {
23
- methodLogger.error(`Unknown command: ${operands[0]}`);
24
- console.log('');
25
- program.help();
26
- process.exit(1);
27
- });
28
- // Parse arguments; default to help if no command provided
29
- await program.parseAsync(args.length ? args : ['--help'], { from: 'user' });
30
- methodLogger.debug('CLI command execution completed');
31
- }
package/dist/index.js.bak DELETED
@@ -1,88 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.Logger = exports.config = void 0;
8
- exports.startServer = startServer;
9
- const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
10
- const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
11
- const logger_util_js_1 = require("./utils/logger.util.js");
12
- Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_util_js_1.Logger; } });
13
- const config_util_js_1 = require("./utils/config.util.js");
14
- Object.defineProperty(exports, "config", { enumerable: true, get: function () { return config_util_js_1.config; } });
15
- const error_util_js_1 = require("./utils/error.util.js");
16
- const index_js_1 = require("./cli/index.js");
17
- const ipaddress_tool_js_1 = __importDefault(require("./tools/ipaddress.tool.js"));
18
- const ipaddress_resource_js_1 = __importDefault(require("./resources/ipaddress.resource.js"));
19
- // Create file-level logger
20
- const indexLogger = logger_util_js_1.Logger.forContext('index.ts');
21
- // Define version constant for easier management and consistent versioning
22
- const VERSION = '1.1.1';
23
- let serverInstance = null;
24
- let transportInstance = null;
25
- async function startServer(mode = 'stdio') {
26
- const methodLogger = logger_util_js_1.Logger.forContext('index.ts', 'startServer');
27
- // Load configuration
28
- config_util_js_1.config.load();
29
- // Enable debug logging if DEBUG is set to true
30
- if (config_util_js_1.config.getBoolean('DEBUG')) {
31
- methodLogger.debug('Debug mode enabled');
32
- }
33
- // Log the DEBUG value to verify configuration loading
34
- methodLogger.info(`DEBUG value: ${process.env.DEBUG}`);
35
- methodLogger.info(`IPAPI_API_TOKEN value exists: ${Boolean(process.env.IPAPI_API_TOKEN)}`);
36
- methodLogger.info(`Config DEBUG value: ${config_util_js_1.config.get('DEBUG')}`);
37
- serverInstance = new mcp_js_1.McpServer({
38
- name: '@aashari/boilerplate-mcp-server',
39
- version: VERSION,
40
- });
41
- if (mode === 'stdio') {
42
- transportInstance = new stdio_js_1.StdioServerTransport();
43
- }
44
- else {
45
- throw (0, error_util_js_1.createUnexpectedError)('SSE mode is not supported yet');
46
- }
47
- methodLogger.info(`Starting server with ${mode.toUpperCase()} transport...`);
48
- // register tools
49
- ipaddress_tool_js_1.default.register(serverInstance);
50
- methodLogger.debug('Registered IP address tools');
51
- // register resources
52
- ipaddress_resource_js_1.default.register(serverInstance);
53
- methodLogger.debug('Registered IP lookup resources');
54
- return serverInstance.connect(transportInstance).catch((err) => {
55
- methodLogger.error(`Failed to start server`, err);
56
- process.exit(1);
57
- });
58
- }
59
- // Main entry point - this will run when executed directly
60
- async function main() {
61
- const methodLogger = logger_util_js_1.Logger.forContext('index.ts', 'main');
62
- // Load configuration
63
- config_util_js_1.config.load();
64
- // Log the DEBUG value to verify configuration loading
65
- methodLogger.info(`DEBUG value: ${process.env.DEBUG}`);
66
- methodLogger.info(`IPAPI_API_TOKEN value exists: ${Boolean(process.env.IPAPI_API_TOKEN)}`);
67
- methodLogger.info(`Config DEBUG value: ${config_util_js_1.config.get('DEBUG')}`);
68
- // Check if arguments are provided (CLI mode)
69
- if (process.argv.length > 2) {
70
- // CLI mode: Pass arguments to CLI runner
71
- methodLogger.info('Starting in CLI mode');
72
- await (0, index_js_1.runCli)(process.argv.slice(2));
73
- methodLogger.info('CLI execution completed');
74
- }
75
- else {
76
- // MCP Server mode: Start server with default STDIO
77
- methodLogger.info('Starting in server mode');
78
- await startServer();
79
- methodLogger.info('Server is now running');
80
- }
81
- }
82
- // If this file is being executed directly (not imported), run the main function
83
- if (require.main === module) {
84
- main().catch((err) => {
85
- indexLogger.error('Unhandled error in main process', err);
86
- process.exit(1);
87
- });
88
- }