@aashari/boilerplate-mcp-server 1.15.0 → 1.16.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,15 @@
1
+ # [1.16.0](https://github.com/aashari/boilerplate-mcp-server/compare/v1.15.0...v1.16.0) (2025-12-01)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * regenerate package-lock.json to fix CI dependency resolution ([a0225a8](https://github.com/aashari/boilerplate-mcp-server/commit/a0225a8f9bb0bb5b27a436099d0b131fa47e8cbc))
7
+
8
+
9
+ ### Features
10
+
11
+ * modernize SDK usage and update dependencies ([#127](https://github.com/aashari/boilerplate-mcp-server/issues/127)) ([a36c9f6](https://github.com/aashari/boilerplate-mcp-server/commit/a36c9f644d842e9c5360d4ed2f207ada18d97ebd))
12
+
1
13
  # [1.15.0](https://github.com/aashari/boilerplate-mcp-server/compare/v1.14.0...v1.15.0) (2025-12-01)
2
14
 
3
15
 
package/README.md CHANGED
@@ -9,7 +9,10 @@ A production-ready foundation for developing custom Model Context Protocol (MCP)
9
9
 
10
10
  - **Dual Transport Support**: STDIO and Streamable HTTP transports with automatic fallback
11
11
  - **5-Layer Architecture**: Clean separation between CLI, tools, controllers, services, and utilities
12
- - **Type Safety**: Full TypeScript implementation with Zod schema validation
12
+ - **Type Safety**: Full TypeScript implementation with Zod v4 schema validation
13
+ - **TOON Output Format**: Token-Oriented Object Notation for 30-60% fewer tokens than JSON
14
+ - **JMESPath Filtering**: Extract only needed fields from responses to reduce token costs
15
+ - **Modern SDK**: Uses MCP SDK v1.23.0 with `registerTool` API pattern
13
16
  - **Complete IP Address Example**: Tools, resources, and CLI commands for IP geolocation
14
17
  - **Comprehensive Testing**: Unit and integration tests with coverage reporting
15
18
  - **Production Tooling**: ESLint, Prettier, semantic-release, and MCP Inspector integration
@@ -43,6 +46,8 @@ npm run build
43
46
  npm run cli -- get-ip-details 8.8.8.8
44
47
  npm run cli -- get-ip-details # Get your current IP
45
48
  npm run cli -- get-ip-details 1.1.1.1 --include-extended-data
49
+ npm run cli -- get-ip-details 8.8.8.8 --jq "{ip: query, country: country}" # JQ filter
50
+ npm run cli -- get-ip-details 8.8.8.8 --output-format json # JSON output
46
51
 
47
52
  # 2. STDIO Transport - For AI assistant integration (Claude Desktop, Cursor)
48
53
  npm run mcp:stdio
@@ -69,6 +74,52 @@ npm run mcp:inspect # Auto-opens browser with debugging
69
74
  - Health Check: `http://localhost:3000/` → Returns server version
70
75
  - Run with: `TRANSPORT_MODE=http node dist/index.js`
71
76
 
77
+ ## Output Formats
78
+
79
+ ### TOON Format (Default)
80
+
81
+ TOON (Token-Oriented Object Notation) is a human-readable format optimized for LLMs, reducing token usage by 30-60% compared to JSON:
82
+
83
+ ```
84
+ status: success
85
+ query: 8.8.8.8
86
+ country: United States
87
+ city: Ashburn
88
+ lat: 39.03
89
+ lon: -77.5
90
+ ```
91
+
92
+ ### JSON Format
93
+
94
+ Standard JSON output when `--output-format json` is specified:
95
+
96
+ ```json
97
+ {
98
+ "status": "success",
99
+ "query": "8.8.8.8",
100
+ "country": "United States",
101
+ "city": "Ashburn"
102
+ }
103
+ ```
104
+
105
+ ### JMESPath Filtering
106
+
107
+ Use `--jq` to extract only needed fields, reducing token costs:
108
+
109
+ ```bash
110
+ # Extract specific fields
111
+ npm run cli -- get-ip-details 8.8.8.8 --jq "{ip: query, country: country}"
112
+
113
+ # Output:
114
+ # ip: 8.8.8.8
115
+ # country: United States
116
+
117
+ # Nested structure
118
+ npm run cli -- get-ip-details 8.8.8.8 --jq "{location: {city: city, coords: {lat: lat, lon: lon}}}"
119
+ ```
120
+
121
+ See [JMESPath documentation](https://jmespath.org) for more filter examples.
122
+
72
123
  ## Architecture Overview
73
124
 
74
125
  <details>
@@ -99,6 +150,8 @@ src/
99
150
  │ ├── config.util.ts # Environment configuration
100
151
  │ ├── constants.util.ts # Version and package constants
101
152
  │ ├── formatter.util.ts # Markdown formatting
153
+ │ ├── toon.util.ts # TOON format encoding
154
+ │ ├── jq.util.ts # JMESPath filtering
102
155
  │ └── transport.util.ts # HTTP transport utilities
103
156
  └── index.ts # Server entry point (dual transport)
104
157
  ```
@@ -126,9 +179,9 @@ The boilerplate follows a clean, layered architecture that promotes maintainabil
126
179
  ### 3. Resources Layer (`src/resources/`)
127
180
 
128
181
  - **Purpose**: MCP resources providing contextual data accessible via URIs
129
- - **Implementation**: Resource handlers that respond to URI-based requests
130
- - **Example**: `ip://8.8.8.8` resource providing IP geolocation data
131
- - **Pattern**: Register URI patternsParse requests → Return formatted content
182
+ - **Implementation**: Uses `registerResource` API with `ResourceTemplate` for parameterized URIs
183
+ - **Example**: `ip://{ipAddress}` resource template providing IP geolocation data
184
+ - **Pattern**: Register URI templateExtract variables → Return formatted content
132
185
 
133
186
  ### 4. Controllers Layer (`src/controllers/`)
134
187
 
@@ -147,11 +200,13 @@ The boilerplate follows a clean, layered architecture that promotes maintainabil
147
200
  ### 6. Utils Layer (`src/utils/`)
148
201
 
149
202
  - **Purpose**: Shared functionality across all layers
150
- - **Key Components**:
203
+ - **Key Components**:
151
204
  - `logger.util.ts`: Contextual logging (file:method context)
152
205
  - `error.util.ts`: MCP-specific error formatting
153
206
  - `transport.util.ts`: HTTP/API utilities with retry logic
154
207
  - `config.util.ts`: Environment configuration management
208
+ - `toon.util.ts`: TOON format encoding (token-efficient output)
209
+ - `jq.util.ts`: JMESPath filtering for response transformation
155
210
 
156
211
  ## Developer Guide
157
212
 
@@ -396,16 +451,20 @@ async function handleGetData(args: Record<string, unknown>) {
396
451
  }
397
452
  }
398
453
 
399
- // Registration function following the pattern used by existing tools
454
+ // Registration function using the modern registerTool API (SDK v1.22.0+)
400
455
  function registerTools(server: McpServer) {
401
456
  const registerLogger = logger.forMethod('registerTools');
402
457
  registerLogger.debug('Registering example tools...');
403
458
 
404
- server.tool(
459
+ // SDK best practices: 'title' for UI display name, 'description' for detailed info
460
+ server.registerTool(
405
461
  'example_get_data',
406
- `Gets data from the Example API with optional parameter.
462
+ {
463
+ title: 'Get Example Data', // Display name for UI (e.g., 'Get Example Data')
464
+ description: `Gets data from the Example API with optional parameter.
407
465
  Use this tool to fetch example data. Returns formatted data as Markdown.`,
408
- GetDataSchema.shape,
466
+ inputSchema: GetDataSchema,
467
+ },
409
468
  handleGetData
410
469
  );
411
470
 
@@ -484,6 +543,63 @@ import exampleTools from './tools/example.tool.js';
484
543
  exampleTools.registerTools(serverInstance);
485
544
  ```
486
545
 
546
+ ### 6. Add MCP Resource (Optional)
547
+
548
+ Create a resource in `src/resources/` using the modern `registerResource` API:
549
+
550
+ ```typescript
551
+ // src/resources/example.resource.ts
552
+ import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
553
+ import { Logger } from '../utils/logger.util.js';
554
+ import exampleController from '../controllers/example.controller.js';
555
+ import { formatErrorForMcpResource } from '../utils/error.util.js';
556
+
557
+ const logger = Logger.forContext('resources/example.resource.ts');
558
+
559
+ function registerResources(server: McpServer) {
560
+ const registerLogger = logger.forMethod('registerResources');
561
+ registerLogger.debug('Registering example resources...');
562
+
563
+ // Use registerResource with ResourceTemplate for parameterized URIs (SDK v1.22.0+)
564
+ server.registerResource(
565
+ 'example-data',
566
+ new ResourceTemplate('example://{param}', { list: undefined }),
567
+ {
568
+ title: 'Example Data', // Display name for UI
569
+ description: 'Retrieve example data by parameter'
570
+ },
571
+ async (uri, variables) => {
572
+ const methodLogger = logger.forMethod('exampleResource');
573
+ try {
574
+ // Extract parameter from template variables
575
+ const param = variables.param as string | undefined;
576
+
577
+ methodLogger.debug('Example resource called', { uri: uri.href, param });
578
+
579
+ const result = await exampleController.getData({ param });
580
+
581
+ return {
582
+ contents: [
583
+ {
584
+ uri: uri.href,
585
+ text: result.content,
586
+ mimeType: 'text/markdown'
587
+ }
588
+ ]
589
+ };
590
+ } catch (error) {
591
+ methodLogger.error('Resource error', error);
592
+ return formatErrorForMcpResource(error, uri.href);
593
+ }
594
+ }
595
+ );
596
+
597
+ registerLogger.debug('Example resources registered successfully');
598
+ }
599
+
600
+ export default { registerResources };
601
+ ```
602
+
487
603
  </details>
488
604
 
489
605
  ## IP Address Example Implementation
@@ -494,26 +610,30 @@ The boilerplate includes a complete IP address geolocation example demonstrating
494
610
 
495
611
  **CLI Commands:**
496
612
  ```bash
497
- npm run cli -- get-ip-details # Get current public IP
498
- npm run cli -- get-ip-details 8.8.8.8 # Get details for specific IP
613
+ npm run cli -- get-ip-details # Get current public IP (TOON format)
614
+ npm run cli -- get-ip-details 8.8.8.8 # Get details for specific IP
499
615
  npm run cli -- get-ip-details 1.1.1.1 --include-extended-data # With extended data
500
- npm run cli -- get-ip-details 8.8.8.8 --no-use-https # Force HTTP (for free tier)
616
+ npm run cli -- get-ip-details 8.8.8.8 --no-use-https # Force HTTP (for free tier)
617
+ npm run cli -- get-ip-details 8.8.8.8 --output-format json # JSON output
618
+ npm run cli -- get-ip-details 8.8.8.8 --jq "{ip: query, country: country}" # Filtered output
501
619
  ```
502
620
 
503
621
  **MCP Tools:**
504
622
  - `ip_get_details` - IP geolocation lookup for AI assistants
623
+ - Supports `outputFormat`: "toon" (default) or "json"
624
+ - Supports `jq`: JMESPath expression for filtering
505
625
 
506
626
  **MCP Resources:**
507
- - `ip://` - Current IP details
508
- - `ip://8.8.8.8` - Specific IP details
627
+ - `ip://{ipAddress}` - IP details resource template (e.g., `ip://8.8.8.8`)
509
628
 
510
629
  ### Features Demonstrated
511
630
 
631
+ - **TOON Output**: Token-efficient format (30-60% fewer tokens than JSON)
632
+ - **JMESPath Filtering**: Extract only needed fields to reduce costs
512
633
  - **Fallback Logic**: HTTPS → HTTP fallback for free tier users
513
634
  - **Environment Detection**: Different behavior in test vs production
514
635
  - **API Token Support**: Optional token for extended data (ASN, mobile detection, etc.)
515
636
  - **Error Handling**: Structured errors for private/reserved IP addresses
516
- - **Response Formatting**: Clean Markdown output with geolocation data
517
637
 
518
638
  ### Configuration Options
519
639
 
@@ -592,9 +712,10 @@ npm run test:cli # CLI-specific tests only
592
712
  ## Resources & Documentation
593
713
 
594
714
  ### MCP Protocol Resources
595
- - [MCP Specification](https://modelcontextprotocol.io/specification/2025-06-18)
596
- - [MCP SDK Documentation](https://github.com/modelcontextprotocol/sdk)
715
+ - [MCP Specification](https://modelcontextprotocol.io/specification) - Latest protocol specification
716
+ - [MCP SDK Documentation](https://github.com/modelcontextprotocol/typescript-sdk) - TypeScript SDK v1.23.0+
597
717
  - [MCP Inspector](https://github.com/modelcontextprotocol/inspector) - Visual debugging tool
718
+ - [MCP Concepts](https://modelcontextprotocol.io/docs/concepts) - Tools, resources, transports
598
719
 
599
720
  ### Implementation References
600
721
  - [Anthropic MCP Announcement](https://www.anthropic.com/news/model-context-protocol)
package/STYLE_GUIDE.md CHANGED
@@ -1,12 +1,15 @@
1
1
  # MCP Server Style Guide
2
2
 
3
- Based on the patterns observed and best practices, I recommend adopting the following consistent style guide across all your MCP servers:
3
+ Based on the MCP SDK v1.22.0+ best practices and observed patterns, this guide ensures consistency across all MCP servers.
4
+
5
+ ## Naming Conventions
4
6
 
5
7
  | Element | Convention | Rationale / Examples |
6
8
  | :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ |
7
9
  | **CLI Commands** | `verb-noun` in `kebab-case`. Use the shortest unambiguous verb (`ls`, `get`, `create`, `add`, `exec`, `search`). | `ls-repos`, `get-pr`, `create-comment`, `exec-command` |
8
10
  | **CLI Options** | `--kebab-case`. Be specific (e.g., `--workspace-slug`, not just `--slug`). | `--project-key-or-id`, `--source-branch` |
9
11
  | **MCP Tool Names** | `<namespace>_<verb>_<noun>` in `snake_case`. Use a concise 2-4 char namespace. Avoid noun repetition. | `bb_ls_repos` (Bitbucket list repos), `conf_get_page` (Confluence get page), `aws_exec_command` (AWS execute command). Avoid `ip_ip_get_details`. |
12
+ | **MCP Resource Names**| `kebab-case`. Descriptive identifier for the resource type. | `ip-lookup`, `user-profile`, `config-data` |
10
13
  | **MCP Arguments** | `camelCase`. Suffix identifiers consistently (e.g., `Id`, `Key`, `Slug`). Avoid abbreviations unless universal. | `workspaceSlug`, `pullRequestId`, `sourceBranch`, `pageId`. |
11
14
  | **Boolean Args** | Use verb prefixes for clarity (`includeXxx`, `launchBrowser`). Avoid bare adjectives (`--https`). | `includeExtendedData: boolean`, `launchBrowser: boolean` |
12
15
  | **Array Args** | Use plural names (`spaceIds`, `labels`, `statuses`). | `spaceIds: string[]`, `labels: string[]` |
@@ -14,4 +17,60 @@ Based on the patterns observed and best practices, I recommend adopting the foll
14
17
  | **Arg Descriptions** | Start lowercase, explain purpose clearly. Mention defaults or constraints. | `numeric ID of the page to retrieve (e.g., "456789"). Required.` |
15
18
  | **ID/Key Naming** | Use consistent suffixes like `Id`, `Key`, `Slug`, `KeyOrId` where appropriate. | `pageId`, `projectKeyOrId`, `workspaceSlug` |
16
19
 
20
+ ## SDK Best Practices (v1.22.0+)
21
+
22
+ ### Title vs Name
23
+
24
+ All registrations (`registerTool`, `registerResource`, `registerPrompt`) support both `name` and `title`:
25
+
26
+ | Field | Purpose | Example |
27
+ | :---- | :------ | :------ |
28
+ | `name` | Unique identifier for programmatic use | `ip_get_details` |
29
+ | `title` | Human-readable display name for UI | `IP Address Lookup` |
30
+
31
+ **Always provide both** - `name` for code, `title` for user interfaces.
32
+
33
+ ### Modern Registration APIs
34
+
35
+ Use the modern `register*` methods instead of deprecated alternatives:
36
+
37
+ | Deprecated | Modern (SDK v1.22.0+) |
38
+ | :--------- | :-------------------- |
39
+ | `server.tool()` | `server.registerTool()` |
40
+ | `server.resource()` | `server.registerResource()` |
41
+ | `server.prompt()` | `server.registerPrompt()` |
42
+
43
+ ### Resource Templates
44
+
45
+ Use `ResourceTemplate` for parameterized resource URIs:
46
+
47
+ ```typescript
48
+ import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
49
+
50
+ // Static resource - fixed URI
51
+ server.registerResource('config', 'config://app', { ... }, handler);
52
+
53
+ // Dynamic resource - parameterized URI
54
+ server.registerResource(
55
+ 'user-profile',
56
+ new ResourceTemplate('users://{userId}/profile', { list: undefined }),
57
+ { title: 'User Profile', description: '...' },
58
+ async (uri, variables) => {
59
+ const userId = variables.userId as string;
60
+ // ...
61
+ }
62
+ );
63
+ ```
64
+
65
+ ### Error Handling
66
+
67
+ Use `isError: true` for tool execution failures:
68
+
69
+ ```typescript
70
+ return {
71
+ content: [{ type: 'text', text: 'Error: Something went wrong' }],
72
+ isError: true
73
+ };
74
+ ```
75
+
17
76
  Adopting this guide will make the tools more predictable and easier for both humans and AI agents to understand and use correctly.
@@ -1,6 +1,7 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  /**
3
3
  * Register an IP address lookup resource with the MCP server
4
+ * Uses the modern registerResource API (SDK v1.22.0+) with ResourceTemplate
4
5
  *
5
6
  * @param server The MCP server instance
6
7
  */
@@ -3,29 +3,34 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
6
7
  const logger_util_js_1 = require("../utils/logger.util.js");
7
8
  const ipaddress_controller_js_1 = __importDefault(require("../controllers/ipaddress.controller.js"));
8
9
  const error_util_js_1 = require("../utils/error.util.js");
9
10
  const logger = logger_util_js_1.Logger.forContext('resources/ipaddress.resource.ts');
10
11
  /**
11
12
  * Register an IP address lookup resource with the MCP server
13
+ * Uses the modern registerResource API (SDK v1.22.0+) with ResourceTemplate
12
14
  *
13
15
  * @param server The MCP server instance
14
16
  */
15
17
  function registerResources(server) {
16
18
  const registerLogger = logger.forMethod('registerResources');
17
19
  registerLogger.debug('Registering IP lookup resources...');
18
- // Register the IP lookup resource
19
- server.resource('ip-lookup', 'Lookup IP address details, returning formatted text result', async (uri) => {
20
+ // Register the IP lookup resource using modern registerResource API
21
+ // ResourceTemplate enables parameterized URIs with {ipAddress} placeholder
22
+ server.registerResource('ip-lookup', new mcp_js_1.ResourceTemplate('ip://{ipAddress}', { list: undefined }), {
23
+ title: 'IP Address Lookup', // Display name for UI
24
+ description: 'Retrieve geolocation and network information for a public IP address',
25
+ }, async (uri, variables) => {
20
26
  const methodLogger = logger.forMethod('ipLookupResource');
21
27
  try {
22
- // Extract the IP address from the request path (if present)
23
- // Format of the URI would be ip://<ip-address> or ip://
28
+ // Extract ipAddress from template variables
29
+ const ipAddress = variables.ipAddress;
24
30
  methodLogger.debug('IP lookup resource called', {
25
- uri: uri.toString(),
31
+ uri: uri.href,
32
+ ipAddress,
26
33
  });
27
- // Get everything after the ip:// protocol
28
- const ipAddress = uri.toString().replace(/^ip:\/\//, '');
29
34
  // Call the controller to get the IP details
30
35
  const result = await ipaddress_controller_js_1.default.get({
31
36
  ipAddress: ipAddress || undefined,
@@ -36,17 +41,16 @@ function registerResources(server) {
36
41
  return {
37
42
  contents: [
38
43
  {
39
- uri: uri.toString(),
44
+ uri: uri.href,
40
45
  text: result.content,
41
46
  mimeType: 'text/markdown',
42
- description: `IP Details for ${ipAddress || 'current'}`,
43
47
  },
44
48
  ],
45
49
  };
46
50
  }
47
51
  catch (error) {
48
52
  methodLogger.error('Resource error', error);
49
- return (0, error_util_js_1.formatErrorForMcpResource)(error, uri.toString());
53
+ return (0, error_util_js_1.formatErrorForMcpResource)(error, uri.href);
50
54
  }
51
55
  });
52
56
  registerLogger.debug('IP lookup resources registered successfully');
@@ -24,49 +24,7 @@ export declare const IPDetailSchema: z.ZodObject<{
24
24
  mobile: z.ZodOptional<z.ZodBoolean>;
25
25
  proxy: z.ZodOptional<z.ZodBoolean>;
26
26
  hosting: z.ZodOptional<z.ZodBoolean>;
27
- }, "strip", z.ZodTypeAny, {
28
- status: string;
29
- message?: string | undefined;
30
- query?: string | undefined;
31
- country?: string | undefined;
32
- countryCode?: string | undefined;
33
- region?: string | undefined;
34
- regionName?: string | undefined;
35
- city?: string | undefined;
36
- zip?: string | undefined;
37
- lat?: number | undefined;
38
- lon?: number | undefined;
39
- timezone?: string | undefined;
40
- isp?: string | undefined;
41
- org?: string | undefined;
42
- as?: string | undefined;
43
- asname?: string | undefined;
44
- reverse?: string | undefined;
45
- mobile?: boolean | undefined;
46
- proxy?: boolean | undefined;
47
- hosting?: boolean | undefined;
48
- }, {
49
- status: string;
50
- message?: string | undefined;
51
- query?: string | undefined;
52
- country?: string | undefined;
53
- countryCode?: string | undefined;
54
- region?: string | undefined;
55
- regionName?: string | undefined;
56
- city?: string | undefined;
57
- zip?: string | undefined;
58
- lat?: number | undefined;
59
- lon?: number | undefined;
60
- timezone?: string | undefined;
61
- isp?: string | undefined;
62
- org?: string | undefined;
63
- as?: string | undefined;
64
- asname?: string | undefined;
65
- reverse?: string | undefined;
66
- mobile?: boolean | undefined;
67
- proxy?: boolean | undefined;
68
- hosting?: boolean | undefined;
69
- }>;
27
+ }, z.core.$strip>;
70
28
  /**
71
29
  * TypeScript type inferred from the IPDetailSchema.
72
30
  * Represents the expected structure of a successful ip-api.com response.
@@ -2,6 +2,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  /**
3
3
  * @function registerTools
4
4
  * @description Registers the IP address lookup tool ('ip_get_details') with the MCP server.
5
+ * Uses the modern registerTool API (SDK v1.22.0+) instead of deprecated tool() method.
5
6
  *
6
7
  * @param {McpServer} server - The MCP server instance.
7
8
  */
@@ -19,10 +19,6 @@ const GetIpDetailsToolSchema = zod_1.z.object({
19
19
  .describe('IP address to lookup (omit for current IP)'),
20
20
  ...ipaddress_types_js_1.IpAddressToolArgs.shape, // Merge options schema
21
21
  });
22
- /**
23
- * TypeScript type inferred from the combined tool arguments schema.
24
- */
25
- // type GetIpDetailsToolArgsType = z.infer<typeof GetIpDetailsToolSchema>;
26
22
  /**
27
23
  * @function handleGetIpDetails
28
24
  * @description MCP Tool handler to retrieve details for a given IP address (or the current IP).
@@ -55,15 +51,9 @@ async function handleGetIpDetails(args) {
55
51
  }
56
52
  }
57
53
  /**
58
- * @function registerTools
59
- * @description Registers the IP address lookup tool ('ip_get_details') with the MCP server.
60
- *
61
- * @param {McpServer} server - The MCP server instance.
54
+ * Tool description for ip_get_details
62
55
  */
63
- function registerTools(server) {
64
- const methodLogger = logger_util_js_1.Logger.forContext('tools/ipaddress.tool.ts', 'registerTools');
65
- methodLogger.debug(`Registering IP address tools...`);
66
- server.tool('ip_get_details', `Retrieve geolocation and network information for a public IP address. Returns TOON format by default (30-60% fewer tokens than JSON).
56
+ const IP_GET_DETAILS_DESCRIPTION = `Retrieve geolocation and network information for a public IP address. Returns TOON format by default (30-60% fewer tokens than JSON).
67
57
 
68
58
  **IMPORTANT - Cost Optimization:**
69
59
  - Use \`jq\` param to extract only needed fields. Unfiltered responses are expensive!
@@ -85,7 +75,24 @@ function registerTools(server) {
85
75
 
86
76
  **JQ examples:** \`query\` (IP only), \`{ip: query, country: country}\`, \`{location: {lat: lat, lon: lon}}\`
87
77
 
88
- **Note:** Cannot lookup private IPs (192.168.x.x, 10.x.x.x). Powered by ip-api.com.`, GetIpDetailsToolSchema.shape, handleGetIpDetails);
78
+ **Note:** Cannot lookup private IPs (192.168.x.x, 10.x.x.x). Powered by ip-api.com.`;
79
+ /**
80
+ * @function registerTools
81
+ * @description Registers the IP address lookup tool ('ip_get_details') with the MCP server.
82
+ * Uses the modern registerTool API (SDK v1.22.0+) instead of deprecated tool() method.
83
+ *
84
+ * @param {McpServer} server - The MCP server instance.
85
+ */
86
+ function registerTools(server) {
87
+ const methodLogger = logger_util_js_1.Logger.forContext('tools/ipaddress.tool.ts', 'registerTools');
88
+ methodLogger.debug(`Registering IP address tools...`);
89
+ // Use the modern registerTool API (SDK v1.22.0+)
90
+ // Following SDK best practices: title for UI display, description for details
91
+ server.registerTool('ip_get_details', {
92
+ title: 'IP Address Lookup',
93
+ description: IP_GET_DETAILS_DESCRIPTION,
94
+ inputSchema: GetIpDetailsToolSchema,
95
+ }, handleGetIpDetails);
89
96
  methodLogger.debug('Successfully registered ip_get_details tool.');
90
97
  }
91
98
  exports.default = { registerTools };
@@ -4,7 +4,10 @@ import { z } from 'zod';
4
4
  * - toon: Token-Oriented Object Notation (default, more token-efficient for LLMs)
5
5
  * - json: Standard JSON format
6
6
  */
7
- export declare const OutputFormat: z.ZodOptional<z.ZodEnum<["toon", "json"]>>;
7
+ export declare const OutputFormat: z.ZodOptional<z.ZodEnum<{
8
+ toon: "toon";
9
+ json: "json";
10
+ }>>;
8
11
  /**
9
12
  * Zod schema for the IP address tool arguments.
10
13
  */
@@ -12,18 +15,11 @@ export declare const IpAddressToolArgs: z.ZodObject<{
12
15
  includeExtendedData: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
13
16
  useHttps: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
14
17
  jq: z.ZodOptional<z.ZodString>;
15
- outputFormat: z.ZodOptional<z.ZodEnum<["toon", "json"]>>;
16
- }, "strict", z.ZodTypeAny, {
17
- useHttps: boolean;
18
- includeExtendedData: boolean;
19
- jq?: string | undefined;
20
- outputFormat?: "toon" | "json" | undefined;
21
- }, {
22
- useHttps?: boolean | undefined;
23
- includeExtendedData?: boolean | undefined;
24
- jq?: string | undefined;
25
- outputFormat?: "toon" | "json" | undefined;
26
- }>;
18
+ outputFormat: z.ZodOptional<z.ZodEnum<{
19
+ toon: "toon";
20
+ json: "json";
21
+ }>>;
22
+ }, z.core.$strict>;
27
23
  /**
28
24
  * TypeScript type inferred from the IpAddressToolArgs Zod schema.
29
25
  * This represents the optional arguments passed to the tool handler and controller.
@@ -8,7 +8,7 @@
8
8
  * Current application version
9
9
  * This should match the version in package.json
10
10
  */
11
- export declare const VERSION = "1.15.0";
11
+ export declare const VERSION = "1.16.0";
12
12
  /**
13
13
  * Package name with scope
14
14
  * Used for initialization and identification
@@ -11,7 +11,7 @@ exports.CLI_NAME = exports.PACKAGE_NAME = exports.VERSION = void 0;
11
11
  * Current application version
12
12
  * This should match the version in package.json
13
13
  */
14
- exports.VERSION = '1.15.0';
14
+ exports.VERSION = '1.16.0';
15
15
  /**
16
16
  * Package name with scope
17
17
  * Used for initialization and identification
@@ -134,7 +134,6 @@ async function fetchApi(url, options = {}) {
134
134
  try {
135
135
  const responseData = await response.json();
136
136
  methodLogger.debug('Response body successfully parsed as JSON.');
137
- // methodLogger.debug('Response Data:', responseData); // Uncomment for full response logging
138
137
  return responseData;
139
138
  }
140
139
  catch (parseError) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aashari/boilerplate-mcp-server",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
4
  "description": "TypeScript MCP server boilerplate with STDIO and HTTP transport support, CLI tools, and extensible architecture",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -51,38 +51,38 @@
51
51
  "node": ">=18.0.0"
52
52
  },
53
53
  "devDependencies": {
54
- "@eslint/js": "^9.35.0",
54
+ "@eslint/js": "^9.39.1",
55
55
  "@semantic-release/changelog": "^6.0.3",
56
56
  "@semantic-release/exec": "^7.1.0",
57
57
  "@semantic-release/git": "^10.0.1",
58
- "@semantic-release/github": "^11.0.5",
59
- "@semantic-release/npm": "^12.0.2",
58
+ "@semantic-release/github": "^12.0.2",
59
+ "@semantic-release/npm": "^13.1.2",
60
60
  "@types/cors": "^2.8.19",
61
- "@types/express": "^5.0.3",
61
+ "@types/express": "^5.0.5",
62
62
  "@types/jest": "^30.0.0",
63
63
  "@types/jmespath": "^0.15.2",
64
- "@types/node": "^24.3.1",
65
- "@typescript-eslint/eslint-plugin": "^8.43.0",
66
- "@typescript-eslint/parser": "^8.43.0",
67
- "eslint": "^9.35.0",
64
+ "@types/node": "^24.10.1",
65
+ "@typescript-eslint/eslint-plugin": "^8.48.0",
66
+ "@typescript-eslint/parser": "^8.48.0",
67
+ "eslint": "^9.39.1",
68
68
  "eslint-config-prettier": "^10.1.8",
69
69
  "eslint-plugin-prettier": "^5.5.4",
70
- "jest": "^30.1.3",
71
- "prettier": "^3.6.2",
72
- "semantic-release": "^24.2.7",
73
- "ts-jest": "^29.4.1",
74
- "typescript": "^5.9.2",
75
- "typescript-eslint": "^8.43.0"
70
+ "jest": "^30.2.0",
71
+ "prettier": "^3.7.3",
72
+ "semantic-release": "^25.0.2",
73
+ "ts-jest": "^29.4.5",
74
+ "typescript": "^5.9.3",
75
+ "typescript-eslint": "^8.48.0"
76
76
  },
77
77
  "dependencies": {
78
- "@modelcontextprotocol/sdk": "^1.17.5",
78
+ "@modelcontextprotocol/sdk": "^1.23.0",
79
79
  "@toon-format/toon": "^2.0.1",
80
- "commander": "^14.0.0",
80
+ "commander": "^14.0.2",
81
81
  "cors": "^2.8.5",
82
- "dotenv": "^17.2.2",
82
+ "dotenv": "^17.2.3",
83
83
  "express": "^5.1.0",
84
84
  "jmespath": "^0.16.0",
85
- "zod": "^3.25.76"
85
+ "zod": "^4.1.13"
86
86
  },
87
87
  "publishConfig": {
88
88
  "registry": "https://registry.npmjs.org/",
package/package.json.bak CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aashari/boilerplate-mcp-server",
3
- "version": "1.14.0",
3
+ "version": "1.15.0",
4
4
  "description": "TypeScript MCP server boilerplate with STDIO and HTTP transport support, CLI tools, and extensible architecture",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -51,38 +51,38 @@
51
51
  "node": ">=18.0.0"
52
52
  },
53
53
  "devDependencies": {
54
- "@eslint/js": "^9.35.0",
54
+ "@eslint/js": "^9.39.1",
55
55
  "@semantic-release/changelog": "^6.0.3",
56
56
  "@semantic-release/exec": "^7.1.0",
57
57
  "@semantic-release/git": "^10.0.1",
58
- "@semantic-release/github": "^11.0.5",
59
- "@semantic-release/npm": "^12.0.2",
58
+ "@semantic-release/github": "^12.0.2",
59
+ "@semantic-release/npm": "^13.1.2",
60
60
  "@types/cors": "^2.8.19",
61
- "@types/express": "^5.0.3",
61
+ "@types/express": "^5.0.5",
62
62
  "@types/jest": "^30.0.0",
63
63
  "@types/jmespath": "^0.15.2",
64
- "@types/node": "^24.3.1",
65
- "@typescript-eslint/eslint-plugin": "^8.43.0",
66
- "@typescript-eslint/parser": "^8.43.0",
67
- "eslint": "^9.35.0",
64
+ "@types/node": "^24.10.1",
65
+ "@typescript-eslint/eslint-plugin": "^8.48.0",
66
+ "@typescript-eslint/parser": "^8.48.0",
67
+ "eslint": "^9.39.1",
68
68
  "eslint-config-prettier": "^10.1.8",
69
69
  "eslint-plugin-prettier": "^5.5.4",
70
- "jest": "^30.1.3",
71
- "prettier": "^3.6.2",
72
- "semantic-release": "^24.2.7",
73
- "ts-jest": "^29.4.1",
74
- "typescript": "^5.9.2",
75
- "typescript-eslint": "^8.43.0"
70
+ "jest": "^30.2.0",
71
+ "prettier": "^3.7.3",
72
+ "semantic-release": "^25.0.2",
73
+ "ts-jest": "^29.4.5",
74
+ "typescript": "^5.9.3",
75
+ "typescript-eslint": "^8.48.0"
76
76
  },
77
77
  "dependencies": {
78
- "@modelcontextprotocol/sdk": "^1.17.5",
78
+ "@modelcontextprotocol/sdk": "^1.23.0",
79
79
  "@toon-format/toon": "^2.0.1",
80
- "commander": "^14.0.0",
80
+ "commander": "^14.0.2",
81
81
  "cors": "^2.8.5",
82
- "dotenv": "^17.2.2",
82
+ "dotenv": "^17.2.3",
83
83
  "express": "^5.1.0",
84
84
  "jmespath": "^0.16.0",
85
- "zod": "^3.25.76"
85
+ "zod": "^4.1.13"
86
86
  },
87
87
  "publishConfig": {
88
88
  "registry": "https://registry.npmjs.org/",