@aashari/boilerplate-mcp-server 1.1.0 → 1.1.1
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/.releaserc.json +6 -1
- package/CHANGELOG.md +10 -0
- package/dist/cli/index.js +5 -2
- package/dist/cli/index.js.bak +4 -1
- package/dist/cli/ipaddress.cli.js +5 -3
- package/dist/cli/ipaddress.cli.test.d.ts +1 -0
- package/dist/controllers/ipaddress.controller.d.ts +2 -3
- package/dist/controllers/ipaddress.controller.js +22 -18
- package/dist/controllers/ipaddress.formatter.d.ts +7 -0
- package/dist/controllers/ipaddress.formatter.js +22 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +26 -28
- package/dist/index.js.bak +26 -28
- package/dist/resources/ipaddress.resource.js +6 -2
- package/dist/services/vendor.ip-api.com.service.js +18 -26
- package/dist/tools/ipaddress.tool.js +30 -5
- package/dist/types/common.types.d.ts +71 -0
- package/dist/types/common.types.js +7 -0
- package/dist/utils/cli.test.util.d.ts +28 -0
- package/dist/utils/cli.test.util.js +122 -0
- package/dist/utils/config.util.js +13 -10
- package/dist/utils/defaults.util.d.ts +26 -0
- package/dist/utils/defaults.util.js +38 -0
- package/dist/utils/error-handler.util.d.ts +60 -0
- package/dist/utils/error-handler.util.js +162 -0
- package/dist/utils/error.util.js +6 -3
- package/dist/utils/formatter.util.d.ts +57 -0
- package/dist/utils/formatter.util.js +188 -0
- package/dist/utils/logger.util.d.ts +44 -2
- package/dist/utils/logger.util.js +159 -7
- package/dist/utils/pagination.util.d.ts +69 -0
- package/dist/utils/pagination.util.js +140 -0
- package/dist/utils/transport.util.d.ts +36 -0
- package/dist/utils/transport.util.js +120 -0
- package/package.json +2 -1
- package/package.json.bak +2 -1
- package/.eslintrc.json +0 -19
package/.releaserc.json
CHANGED
|
@@ -20,7 +20,12 @@
|
|
|
20
20
|
[
|
|
21
21
|
"@semantic-release/git",
|
|
22
22
|
{
|
|
23
|
-
"assets": [
|
|
23
|
+
"assets": [
|
|
24
|
+
"package.json",
|
|
25
|
+
"CHANGELOG.md",
|
|
26
|
+
"src/index.ts",
|
|
27
|
+
"src/cli/index.ts"
|
|
28
|
+
],
|
|
24
29
|
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
25
30
|
}
|
|
26
31
|
],
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## [1.1.1](https://github.com/aashari/boilerplate-mcp-server/compare/v1.1.0...v1.1.1) (2025-03-27)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Performance Improvements
|
|
5
|
+
|
|
6
|
+
* **core:** refactor code structure to align with Atlassian MCP patterns ([090fd56](https://github.com/aashari/boilerplate-mcp-server/commit/090fd5653ab62d70eb75c49828a9876f54cee6fc))
|
|
7
|
+
* **standards:** align codebase with Atlassian MCP server patterns ([8b8eb13](https://github.com/aashari/boilerplate-mcp-server/commit/8b8eb13fd4ce18158e83c4f8c7044ce06287f23e))
|
|
8
|
+
* **tests:** add CLI test infrastructure and ipaddress tests ([ccee308](https://github.com/aashari/boilerplate-mcp-server/commit/ccee308a86e076a67756e9113b481aa3848f40b7))
|
|
9
|
+
* **utils:** implement standardized core utilities and error handling ([6c14a2f](https://github.com/aashari/boilerplate-mcp-server/commit/6c14a2f83397f79cc39f0b7ec70b40e9d9755b9c))
|
|
10
|
+
|
|
1
11
|
# [1.1.0](https://github.com/aashari/boilerplate-mcp-server/compare/v1.0.3...v1.1.0) (2025-03-23)
|
|
2
12
|
|
|
3
13
|
|
package/dist/cli/index.js
CHANGED
|
@@ -8,21 +8,24 @@ const commander_1 = require("commander");
|
|
|
8
8
|
const logger_util_js_1 = require("../utils/logger.util.js");
|
|
9
9
|
const ipaddress_cli_js_1 = __importDefault(require("./ipaddress.cli.js"));
|
|
10
10
|
// Get the version from package.json
|
|
11
|
-
const VERSION = '1.1.
|
|
11
|
+
const VERSION = '1.1.1'; // This should match the version in src/index.ts
|
|
12
12
|
const NAME = '@aashari/boilerplate-mcp-server';
|
|
13
13
|
const DESCRIPTION = 'A boilerplate Model Context Protocol (MCP) server implementation using TypeScript';
|
|
14
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);
|
|
15
17
|
const program = new commander_1.Command();
|
|
16
18
|
program.name(NAME).description(DESCRIPTION).version(VERSION);
|
|
17
19
|
// Register CLI commands
|
|
18
20
|
ipaddress_cli_js_1.default.register(program);
|
|
19
21
|
// Handle unknown commands
|
|
20
22
|
program.on('command:*', (operands) => {
|
|
21
|
-
|
|
23
|
+
methodLogger.error(`Unknown command: ${operands[0]}`);
|
|
22
24
|
console.log('');
|
|
23
25
|
program.help();
|
|
24
26
|
process.exit(1);
|
|
25
27
|
});
|
|
26
28
|
// Parse arguments; default to help if no command provided
|
|
27
29
|
await program.parseAsync(args.length ? args : ['--help'], { from: 'user' });
|
|
30
|
+
methodLogger.debug('CLI command execution completed');
|
|
28
31
|
}
|
package/dist/cli/index.js.bak
CHANGED
|
@@ -12,17 +12,20 @@ const VERSION = '1.0.1'; // This should match the version in src/index.ts
|
|
|
12
12
|
const NAME = '@aashari/boilerplate-mcp-server';
|
|
13
13
|
const DESCRIPTION = 'A boilerplate Model Context Protocol (MCP) server implementation using TypeScript';
|
|
14
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);
|
|
15
17
|
const program = new commander_1.Command();
|
|
16
18
|
program.name(NAME).description(DESCRIPTION).version(VERSION);
|
|
17
19
|
// Register CLI commands
|
|
18
20
|
ipaddress_cli_js_1.default.register(program);
|
|
19
21
|
// Handle unknown commands
|
|
20
22
|
program.on('command:*', (operands) => {
|
|
21
|
-
|
|
23
|
+
methodLogger.error(`Unknown command: ${operands[0]}`);
|
|
22
24
|
console.log('');
|
|
23
25
|
program.help();
|
|
24
26
|
process.exit(1);
|
|
25
27
|
});
|
|
26
28
|
// Parse arguments; default to help if no command provided
|
|
27
29
|
await program.parseAsync(args.length ? args : ['--help'], { from: 'user' });
|
|
30
|
+
methodLogger.debug('CLI command execution completed');
|
|
28
31
|
}
|
|
@@ -11,16 +11,18 @@ 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
|
-
logger_util_js_1.
|
|
14
|
+
const methodLogger = logger_util_js_1.Logger.forContext('cli/ipaddress.cli.ts', 'register');
|
|
15
|
+
methodLogger.debug(`Registering IP address CLI commands...`);
|
|
15
16
|
program
|
|
16
17
|
.command('get-ip-details')
|
|
17
18
|
.description('Get details about a specific IP address or the current device')
|
|
18
19
|
.argument('[ipAddress]', 'IP address to lookup (optional)')
|
|
19
20
|
.action(async (ipAddress) => {
|
|
21
|
+
const actionLogger = logger_util_js_1.Logger.forContext('cli/ipaddress.cli.ts', 'get-ip-details');
|
|
20
22
|
try {
|
|
21
|
-
|
|
23
|
+
actionLogger.debug(`Fetching IP details for ${ipAddress || 'current device'}...`);
|
|
22
24
|
const result = await ipaddress_controller_js_1.default.get(ipAddress);
|
|
23
|
-
|
|
25
|
+
actionLogger.debug(`IP details fetched successfully`, result);
|
|
24
26
|
console.log(result.content);
|
|
25
27
|
}
|
|
26
28
|
catch (error) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
}>;
|
|
1
|
+
import { ControllerResponse } from '../types/common.types.js';
|
|
2
|
+
declare function get(ipAddress?: string): Promise<ControllerResponse>;
|
|
4
3
|
declare const _default: {
|
|
5
4
|
get: typeof get;
|
|
6
5
|
};
|
|
@@ -5,29 +5,33 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const vendor_ip_api_com_service_js_1 = __importDefault(require("../services/vendor.ip-api.com.service.js"));
|
|
7
7
|
const logger_util_js_1 = require("../utils/logger.util.js");
|
|
8
|
-
const
|
|
8
|
+
const ipaddress_formatter_js_1 = require("./ipaddress.formatter.js");
|
|
9
|
+
const error_handler_util_js_1 = require("../utils/error-handler.util.js");
|
|
10
|
+
const defaults_util_js_1 = require("../utils/defaults.util.js");
|
|
9
11
|
async function get(ipAddress) {
|
|
10
|
-
logger_util_js_1.
|
|
12
|
+
const methodLogger = logger_util_js_1.Logger.forContext('controllers/ipaddress.controller.ts', 'get');
|
|
13
|
+
methodLogger.debug(`Getting IP address details...`);
|
|
11
14
|
try {
|
|
15
|
+
// Create defaults object (even if empty now)
|
|
16
|
+
const defaults = {}; // Placeholder
|
|
17
|
+
// Apply defaults (will just return the empty options object for now)
|
|
18
|
+
const mergedOptions = (0, defaults_util_js_1.applyDefaults)({}, defaults);
|
|
19
|
+
methodLogger.debug('Using options after defaults:', mergedOptions); // Log merged options
|
|
12
20
|
const ipData = await vendor_ip_api_com_service_js_1.default.get(ipAddress);
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
content: lines.join('\n'),
|
|
20
|
-
};
|
|
21
|
+
methodLogger.debug(`Got the response from the service`, ipData);
|
|
22
|
+
const formattedContent = (0, ipaddress_formatter_js_1.formatIpDetails)(ipData);
|
|
23
|
+
// Return the standard ControllerResponse structure
|
|
24
|
+
return { content: formattedContent };
|
|
21
25
|
}
|
|
22
26
|
catch (error) {
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
// Use the standardized error handler
|
|
28
|
+
(0, error_handler_util_js_1.handleControllerError)(error, {
|
|
29
|
+
entityType: 'IP Address Details',
|
|
30
|
+
operation: 'retrieving',
|
|
31
|
+
source: 'controllers/ipaddress.controller.ts@get',
|
|
32
|
+
additionalInfo: { ipAddress },
|
|
33
|
+
});
|
|
34
|
+
// handleControllerError always throws, so no return/throw is needed after it.
|
|
31
35
|
}
|
|
32
36
|
}
|
|
33
37
|
exports.default = { get };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IPDetail } from '../services/vendor.ip-api.com.type.js';
|
|
2
|
+
/**
|
|
3
|
+
* Format IP address details into Markdown.
|
|
4
|
+
* @param ipData - Raw IP details from the ip-api.com service.
|
|
5
|
+
* @returns Formatted Markdown string.
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatIpDetails(ipData: IPDetail): string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatIpDetails = formatIpDetails;
|
|
4
|
+
const formatter_util_js_1 = require("../utils/formatter.util.js"); // Import from the newly created util
|
|
5
|
+
/**
|
|
6
|
+
* Format IP address details into Markdown.
|
|
7
|
+
* @param ipData - Raw IP details from the ip-api.com service.
|
|
8
|
+
* @returns Formatted Markdown string.
|
|
9
|
+
*/
|
|
10
|
+
function formatIpDetails(ipData) {
|
|
11
|
+
const lines = [];
|
|
12
|
+
// Add a main heading
|
|
13
|
+
lines.push((0, formatter_util_js_1.formatHeading)(`IP Address Details: ${ipData.query}`, 1));
|
|
14
|
+
lines.push('');
|
|
15
|
+
// Use formatBulletList for the properties
|
|
16
|
+
// First cast to unknown, then to Record<string, unknown> to avoid TypeScript error
|
|
17
|
+
lines.push((0, formatter_util_js_1.formatBulletList)(ipData));
|
|
18
|
+
// Add a timestamp footer
|
|
19
|
+
lines.push('');
|
|
20
|
+
lines.push(`*Details retrieved at ${(0, formatter_util_js_1.formatDate)(new Date())}*`);
|
|
21
|
+
return lines.join('\n');
|
|
22
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { Logger } from './utils/logger.util.js';
|
|
3
3
|
import { config } from './utils/config.util.js';
|
|
4
4
|
export declare function startServer(mode?: 'stdio' | 'sse'): Promise<void>;
|
|
5
|
-
export {
|
|
6
|
-
export
|
|
5
|
+
export { config };
|
|
6
|
+
export { Logger };
|
package/dist/index.js
CHANGED
|
@@ -1,50 +1,39 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
-
if (k2 === undefined) k2 = k;
|
|
5
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
-
}
|
|
9
|
-
Object.defineProperty(o, k2, desc);
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
16
|
-
};
|
|
17
3
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
5
|
};
|
|
20
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.
|
|
7
|
+
exports.Logger = exports.config = void 0;
|
|
22
8
|
exports.startServer = startServer;
|
|
23
9
|
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
24
10
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
25
11
|
const logger_util_js_1 = require("./utils/logger.util.js");
|
|
26
|
-
Object.defineProperty(exports, "
|
|
12
|
+
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_util_js_1.Logger; } });
|
|
27
13
|
const config_util_js_1 = require("./utils/config.util.js");
|
|
28
14
|
Object.defineProperty(exports, "config", { enumerable: true, get: function () { return config_util_js_1.config; } });
|
|
29
15
|
const error_util_js_1 = require("./utils/error.util.js");
|
|
30
16
|
const index_js_1 = require("./cli/index.js");
|
|
31
17
|
const ipaddress_tool_js_1 = __importDefault(require("./tools/ipaddress.tool.js"));
|
|
32
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');
|
|
33
21
|
// Define version constant for easier management and consistent versioning
|
|
34
|
-
const VERSION = '1.1.
|
|
22
|
+
const VERSION = '1.1.1';
|
|
35
23
|
let serverInstance = null;
|
|
36
24
|
let transportInstance = null;
|
|
37
25
|
async function startServer(mode = 'stdio') {
|
|
26
|
+
const methodLogger = logger_util_js_1.Logger.forContext('index.ts', 'startServer');
|
|
38
27
|
// Load configuration
|
|
39
28
|
config_util_js_1.config.load();
|
|
40
29
|
// Enable debug logging if DEBUG is set to true
|
|
41
30
|
if (config_util_js_1.config.getBoolean('DEBUG')) {
|
|
42
|
-
|
|
31
|
+
methodLogger.debug('Debug mode enabled');
|
|
43
32
|
}
|
|
44
33
|
// Log the DEBUG value to verify configuration loading
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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')}`);
|
|
48
37
|
serverInstance = new mcp_js_1.McpServer({
|
|
49
38
|
name: '@aashari/boilerplate-mcp-server',
|
|
50
39
|
version: VERSION,
|
|
@@ -55,36 +44,45 @@ async function startServer(mode = 'stdio') {
|
|
|
55
44
|
else {
|
|
56
45
|
throw (0, error_util_js_1.createUnexpectedError)('SSE mode is not supported yet');
|
|
57
46
|
}
|
|
58
|
-
|
|
47
|
+
methodLogger.info(`Starting server with ${mode.toUpperCase()} transport...`);
|
|
59
48
|
// register tools
|
|
60
49
|
ipaddress_tool_js_1.default.register(serverInstance);
|
|
50
|
+
methodLogger.debug('Registered IP address tools');
|
|
61
51
|
// register resources
|
|
62
52
|
ipaddress_resource_js_1.default.register(serverInstance);
|
|
53
|
+
methodLogger.debug('Registered IP lookup resources');
|
|
63
54
|
return serverInstance.connect(transportInstance).catch((err) => {
|
|
64
|
-
|
|
55
|
+
methodLogger.error(`Failed to start server`, err);
|
|
65
56
|
process.exit(1);
|
|
66
57
|
});
|
|
67
58
|
}
|
|
68
59
|
// Main entry point - this will run when executed directly
|
|
69
60
|
async function main() {
|
|
61
|
+
const methodLogger = logger_util_js_1.Logger.forContext('index.ts', 'main');
|
|
70
62
|
// Load configuration
|
|
71
63
|
config_util_js_1.config.load();
|
|
72
64
|
// Log the DEBUG value to verify configuration loading
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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')}`);
|
|
76
68
|
// Check if arguments are provided (CLI mode)
|
|
77
69
|
if (process.argv.length > 2) {
|
|
78
70
|
// CLI mode: Pass arguments to CLI runner
|
|
71
|
+
methodLogger.info('Starting in CLI mode');
|
|
79
72
|
await (0, index_js_1.runCli)(process.argv.slice(2));
|
|
73
|
+
methodLogger.info('CLI execution completed');
|
|
80
74
|
}
|
|
81
75
|
else {
|
|
82
76
|
// MCP Server mode: Start server with default STDIO
|
|
77
|
+
methodLogger.info('Starting in server mode');
|
|
83
78
|
await startServer();
|
|
79
|
+
methodLogger.info('Server is now running');
|
|
84
80
|
}
|
|
85
81
|
}
|
|
86
82
|
// If this file is being executed directly (not imported), run the main function
|
|
87
83
|
if (require.main === module) {
|
|
88
|
-
main()
|
|
84
|
+
main().catch((err) => {
|
|
85
|
+
indexLogger.error('Unhandled error in main process', err);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
});
|
|
89
88
|
}
|
|
90
|
-
__exportStar(require("./utils/error.util.js"), exports);
|
package/dist/index.js.bak
CHANGED
|
@@ -1,50 +1,39 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
-
if (k2 === undefined) k2 = k;
|
|
5
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
-
}
|
|
9
|
-
Object.defineProperty(o, k2, desc);
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
16
|
-
};
|
|
17
3
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
5
|
};
|
|
20
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.
|
|
7
|
+
exports.Logger = exports.config = void 0;
|
|
22
8
|
exports.startServer = startServer;
|
|
23
9
|
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
24
10
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
25
11
|
const logger_util_js_1 = require("./utils/logger.util.js");
|
|
26
|
-
Object.defineProperty(exports, "
|
|
12
|
+
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_util_js_1.Logger; } });
|
|
27
13
|
const config_util_js_1 = require("./utils/config.util.js");
|
|
28
14
|
Object.defineProperty(exports, "config", { enumerable: true, get: function () { return config_util_js_1.config; } });
|
|
29
15
|
const error_util_js_1 = require("./utils/error.util.js");
|
|
30
16
|
const index_js_1 = require("./cli/index.js");
|
|
31
17
|
const ipaddress_tool_js_1 = __importDefault(require("./tools/ipaddress.tool.js"));
|
|
32
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');
|
|
33
21
|
// Define version constant for easier management and consistent versioning
|
|
34
|
-
const VERSION = '1.0
|
|
22
|
+
const VERSION = '1.1.0';
|
|
35
23
|
let serverInstance = null;
|
|
36
24
|
let transportInstance = null;
|
|
37
25
|
async function startServer(mode = 'stdio') {
|
|
26
|
+
const methodLogger = logger_util_js_1.Logger.forContext('index.ts', 'startServer');
|
|
38
27
|
// Load configuration
|
|
39
28
|
config_util_js_1.config.load();
|
|
40
29
|
// Enable debug logging if DEBUG is set to true
|
|
41
30
|
if (config_util_js_1.config.getBoolean('DEBUG')) {
|
|
42
|
-
|
|
31
|
+
methodLogger.debug('Debug mode enabled');
|
|
43
32
|
}
|
|
44
33
|
// Log the DEBUG value to verify configuration loading
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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')}`);
|
|
48
37
|
serverInstance = new mcp_js_1.McpServer({
|
|
49
38
|
name: '@aashari/boilerplate-mcp-server',
|
|
50
39
|
version: VERSION,
|
|
@@ -55,36 +44,45 @@ async function startServer(mode = 'stdio') {
|
|
|
55
44
|
else {
|
|
56
45
|
throw (0, error_util_js_1.createUnexpectedError)('SSE mode is not supported yet');
|
|
57
46
|
}
|
|
58
|
-
|
|
47
|
+
methodLogger.info(`Starting server with ${mode.toUpperCase()} transport...`);
|
|
59
48
|
// register tools
|
|
60
49
|
ipaddress_tool_js_1.default.register(serverInstance);
|
|
50
|
+
methodLogger.debug('Registered IP address tools');
|
|
61
51
|
// register resources
|
|
62
52
|
ipaddress_resource_js_1.default.register(serverInstance);
|
|
53
|
+
methodLogger.debug('Registered IP lookup resources');
|
|
63
54
|
return serverInstance.connect(transportInstance).catch((err) => {
|
|
64
|
-
|
|
55
|
+
methodLogger.error(`Failed to start server`, err);
|
|
65
56
|
process.exit(1);
|
|
66
57
|
});
|
|
67
58
|
}
|
|
68
59
|
// Main entry point - this will run when executed directly
|
|
69
60
|
async function main() {
|
|
61
|
+
const methodLogger = logger_util_js_1.Logger.forContext('index.ts', 'main');
|
|
70
62
|
// Load configuration
|
|
71
63
|
config_util_js_1.config.load();
|
|
72
64
|
// Log the DEBUG value to verify configuration loading
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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')}`);
|
|
76
68
|
// Check if arguments are provided (CLI mode)
|
|
77
69
|
if (process.argv.length > 2) {
|
|
78
70
|
// CLI mode: Pass arguments to CLI runner
|
|
71
|
+
methodLogger.info('Starting in CLI mode');
|
|
79
72
|
await (0, index_js_1.runCli)(process.argv.slice(2));
|
|
73
|
+
methodLogger.info('CLI execution completed');
|
|
80
74
|
}
|
|
81
75
|
else {
|
|
82
76
|
// MCP Server mode: Start server with default STDIO
|
|
77
|
+
methodLogger.info('Starting in server mode');
|
|
83
78
|
await startServer();
|
|
79
|
+
methodLogger.info('Server is now running');
|
|
84
80
|
}
|
|
85
81
|
}
|
|
86
82
|
// If this file is being executed directly (not imported), run the main function
|
|
87
83
|
if (require.main === module) {
|
|
88
|
-
main()
|
|
84
|
+
main().catch((err) => {
|
|
85
|
+
indexLogger.error('Unhandled error in main process', err);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
});
|
|
89
88
|
}
|
|
90
|
-
__exportStar(require("./utils/error.util.js"), exports);
|
|
@@ -11,12 +11,16 @@ const ipaddress_controller_js_1 = __importDefault(require("../controllers/ipaddr
|
|
|
11
11
|
* @param server The MCP server instance
|
|
12
12
|
*/
|
|
13
13
|
function register(server) {
|
|
14
|
-
logger_util_js_1.
|
|
14
|
+
const methodLogger = logger_util_js_1.Logger.forContext('resources/ipaddress.resource.ts', 'register');
|
|
15
|
+
methodLogger.debug(`Registering IP lookup resources...`);
|
|
15
16
|
server.resource('Current Device IP', 'ip://current', {
|
|
16
17
|
description: 'Details about your current IP address',
|
|
17
18
|
}, async (_uri, _extra) => {
|
|
19
|
+
const resourceMethodLogger = logger_util_js_1.Logger.forContext('resources/ipaddress.resource.ts', 'resourceHandler');
|
|
18
20
|
try {
|
|
21
|
+
resourceMethodLogger.debug('Handling request for current IP details');
|
|
19
22
|
const resourceContent = await ipaddress_controller_js_1.default.get();
|
|
23
|
+
resourceMethodLogger.debug('Successfully retrieved IP details');
|
|
20
24
|
return {
|
|
21
25
|
contents: [
|
|
22
26
|
{
|
|
@@ -29,7 +33,7 @@ function register(server) {
|
|
|
29
33
|
};
|
|
30
34
|
}
|
|
31
35
|
catch (error) {
|
|
32
|
-
|
|
36
|
+
resourceMethodLogger.error(`Error getting IP details`, error);
|
|
33
37
|
return (0, error_util_js_1.formatErrorForMcpResource)(error, 'ip://current');
|
|
34
38
|
}
|
|
35
39
|
});
|
|
@@ -1,43 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const logger_util_js_1 = require("../utils/logger.util.js");
|
|
4
|
-
const config_util_js_1 = require("../utils/config.util.js");
|
|
5
4
|
const error_util_js_1 = require("../utils/error.util.js");
|
|
6
|
-
const
|
|
5
|
+
const transport_util_js_1 = require("../utils/transport.util.js");
|
|
6
|
+
// Create a contextualized logger for this file
|
|
7
|
+
const serviceLogger = logger_util_js_1.Logger.forContext('services/vendor.ip-api.com.service.ts');
|
|
8
|
+
// Log service initialization
|
|
9
|
+
serviceLogger.debug('IP API service initialized');
|
|
7
10
|
async function get(ipAddress) {
|
|
8
|
-
logger_util_js_1.
|
|
9
|
-
|
|
10
|
-
const apiToken = config_util_js_1.config.get('IPAPI_API_TOKEN');
|
|
11
|
-
// Build URL with token if available
|
|
12
|
-
let url = `${ENDPOINT}/${ipAddress ?? ''}`;
|
|
13
|
-
if (apiToken) {
|
|
14
|
-
url += `?key=${apiToken}`;
|
|
15
|
-
logger_util_js_1.logger.debug(`[src/services/vendor.ip-api.com.ts@get] Using API token`);
|
|
16
|
-
}
|
|
11
|
+
const methodLogger = logger_util_js_1.Logger.forContext('services/vendor.ip-api.com.service.ts', 'get');
|
|
12
|
+
methodLogger.debug(`Calling IP API for IP: ${ipAddress || 'current'}`);
|
|
17
13
|
try {
|
|
18
|
-
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
const data = (await response.json());
|
|
24
|
-
// Handle API-level errors
|
|
14
|
+
// Use the centralized fetchIpApi utility
|
|
15
|
+
// Explicitly type the expected response structure
|
|
16
|
+
const data = await (0, transport_util_js_1.fetchIpApi)(ipAddress || '');
|
|
17
|
+
// Handle API-level success/failure specific to ip-api.com
|
|
25
18
|
if (data.status !== 'success') {
|
|
26
19
|
throw (0, error_util_js_1.createApiError)(`IP API error: ${data.message || 'Unknown error'}`);
|
|
27
20
|
}
|
|
28
|
-
|
|
21
|
+
methodLogger.debug(`Received successful data from IP API`);
|
|
22
|
+
return data; // Already validated as IPDetail structure implicitly by status check
|
|
29
23
|
}
|
|
30
24
|
catch (error) {
|
|
31
|
-
//
|
|
25
|
+
// Log the error caught at the service level
|
|
26
|
+
methodLogger.error(`Service error fetching IP data`, error);
|
|
27
|
+
// Rethrow McpErrors (could be from fetchApi or the status check)
|
|
32
28
|
if (error instanceof error_util_js_1.McpError) {
|
|
33
29
|
throw error;
|
|
34
30
|
}
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
throw (0, error_util_js_1.createApiError)('Network error while contacting IP API', undefined, error);
|
|
38
|
-
}
|
|
39
|
-
// Handle unexpected errors
|
|
40
|
-
throw (0, error_util_js_1.createUnexpectedError)('Unexpected error while fetching IP data', error);
|
|
31
|
+
// Wrap any other unexpected errors
|
|
32
|
+
throw (0, error_util_js_1.createUnexpectedError)('Unexpected service error while fetching IP data', error);
|
|
41
33
|
}
|
|
42
34
|
}
|
|
43
35
|
exports.default = { get };
|
|
@@ -8,10 +8,11 @@ const ipaddress_type_js_1 = require("./ipaddress.type.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
|
async function getIpAddressDetails(args, _extra) {
|
|
11
|
-
logger_util_js_1.
|
|
11
|
+
const methodLogger = logger_util_js_1.Logger.forContext('tools/ipaddress.tool.ts', 'getIpAddressDetails');
|
|
12
|
+
methodLogger.debug(`Getting IP address details...`);
|
|
12
13
|
try {
|
|
13
14
|
const message = await ipaddress_controller_js_1.default.get(args.ipAddress);
|
|
14
|
-
|
|
15
|
+
methodLogger.debug(`Got the response from the controller`, message);
|
|
15
16
|
return {
|
|
16
17
|
content: [
|
|
17
18
|
{
|
|
@@ -22,12 +23,36 @@ async function getIpAddressDetails(args, _extra) {
|
|
|
22
23
|
};
|
|
23
24
|
}
|
|
24
25
|
catch (error) {
|
|
25
|
-
|
|
26
|
+
methodLogger.error(`Error getting details for IP: ${args.ipAddress || 'current IP'}`, error);
|
|
26
27
|
return (0, error_util_js_1.formatErrorForMcpTool)(error);
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
function register(server) {
|
|
30
|
-
logger_util_js_1.
|
|
31
|
-
|
|
31
|
+
const methodLogger = logger_util_js_1.Logger.forContext('tools/ipaddress.tool.ts', 'register');
|
|
32
|
+
methodLogger.debug(`Registering tools...`);
|
|
33
|
+
server.tool('get-ip-details', `Get details about a specific IP address or the current device's public IP address.
|
|
34
|
+
|
|
35
|
+
PURPOSE: Retrieves geolocation information (country, city, region, coordinates), ISP, and organization details associated with an IP address.
|
|
36
|
+
|
|
37
|
+
WHEN TO USE:
|
|
38
|
+
- To find the geographical location of a given IP address.
|
|
39
|
+
- To identify the ISP or organization owning an IP address.
|
|
40
|
+
- To get your own public IP address details (by omitting the 'ipAddress' argument).
|
|
41
|
+
|
|
42
|
+
WHEN NOT TO USE:
|
|
43
|
+
- For internal/private IP addresses (this tool queries a public database).
|
|
44
|
+
- When you need historical IP data (this provides current lookup).
|
|
45
|
+
- For operations other than retrieving IP geolocation details.
|
|
46
|
+
|
|
47
|
+
RETURNS: Formatted Markdown containing details such as country, city, region, latitude, longitude, ISP, organization, and the queried IP itself.
|
|
48
|
+
|
|
49
|
+
EXAMPLES:
|
|
50
|
+
- Get details for a specific IP: { ipAddress: "8.8.8.8" }
|
|
51
|
+
- Get details for the current device's IP: {}
|
|
52
|
+
|
|
53
|
+
ERRORS:
|
|
54
|
+
- Invalid IP format: If the provided 'ipAddress' is not a valid IP.
|
|
55
|
+
- Private/Reserved IP: If the IP address is in a private range.
|
|
56
|
+
- API errors: If the external ip-api.com service fails.`, ipaddress_type_js_1.IpAddressToolArgs.shape, getIpAddressDetails);
|
|
32
57
|
}
|
|
33
58
|
exports.default = { register };
|