@aashari/boilerplate-mcp-server 1.13.4 → 1.14.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 +14 -0
- package/README.md +385 -163
- package/dist/utils/config.util.js +7 -1
- package/dist/utils/constants.util.d.ts +1 -1
- package/dist/utils/constants.util.js +1 -1
- package/dist/utils/jest.setup.d.ts +5 -0
- package/dist/utils/jest.setup.js +36 -0
- package/dist/utils/logger.util.js +8 -5
- package/package.json +20 -16
- package/package.json.bak +20 -16
- package/.node-version +0 -1
- package/GEMINI.md +0 -280
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [1.14.0](https://github.com/aashari/boilerplate-mcp-server/compare/v1.13.5...v1.14.0) (2025-09-09)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* modernize dependencies and enhance testing infrastructure ([#67](https://github.com/aashari/boilerplate-mcp-server/issues/67)) ([a74f114](https://github.com/aashari/boilerplate-mcp-server/commit/a74f1145b7e80615a9a0c907b9d19eb5e4fbd2e8))
|
|
7
|
+
|
|
8
|
+
## [1.13.5](https://github.com/aashari/boilerplate-mcp-server/compare/v1.13.4...v1.13.5) (2025-08-02)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* allow Gemini to run even if build fails to catch PR issues ([c7b31b3](https://github.com/aashari/boilerplate-mcp-server/commit/c7b31b33674b4ef458d6d201aa22673f13a5247a))
|
|
14
|
+
|
|
1
15
|
## [1.13.4](https://github.com/aashari/boilerplate-mcp-server/compare/v1.13.3...v1.13.4) (2025-08-02)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
# Boilerplate MCP Server
|
|
2
2
|
|
|
3
|
-
A foundation for developing custom Model Context Protocol (MCP) servers in TypeScript. Provides a complete layered architecture pattern, working example
|
|
3
|
+
A production-ready foundation for developing custom Model Context Protocol (MCP) servers in TypeScript. Provides a complete layered architecture pattern, working example implementation, and comprehensive developer infrastructure to connect AI assistants with external APIs and data sources.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@aashari/boilerplate-mcp-server)
|
|
6
|
-
[](https://github.com/aashari/boilerplate-mcp-server/actions)
|
|
7
|
-
[](https://www.typescriptlang.org/)
|
|
8
6
|
[](https://opensource.org/licenses/ISC)
|
|
9
7
|
|
|
10
8
|
## Features
|
|
11
9
|
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **Type Safety**:
|
|
15
|
-
- **
|
|
16
|
-
- **Testing
|
|
17
|
-
- **
|
|
10
|
+
- **Dual Transport Support**: STDIO and Streamable HTTP transports with automatic fallback
|
|
11
|
+
- **5-Layer Architecture**: Clean separation between CLI, tools, controllers, services, and utilities
|
|
12
|
+
- **Type Safety**: Full TypeScript implementation with Zod schema validation
|
|
13
|
+
- **Complete IP Address Example**: Tools, resources, and CLI commands for IP geolocation
|
|
14
|
+
- **Comprehensive Testing**: Unit and integration tests with coverage reporting
|
|
15
|
+
- **Production Tooling**: ESLint, Prettier, semantic-release, and MCP Inspector integration
|
|
16
|
+
- **Error Handling**: Structured error handling with contextual logging
|
|
18
17
|
|
|
19
18
|
## What is MCP?
|
|
20
19
|
|
|
@@ -35,35 +34,40 @@ cd boilerplate-mcp-server
|
|
|
35
34
|
# Install dependencies
|
|
36
35
|
npm install
|
|
37
36
|
|
|
37
|
+
# Build the project
|
|
38
|
+
npm run build
|
|
39
|
+
|
|
38
40
|
# Run in different modes:
|
|
39
41
|
|
|
40
42
|
# 1. CLI Mode - Execute commands directly
|
|
41
43
|
npm run cli -- get-ip-details 8.8.8.8
|
|
44
|
+
npm run cli -- get-ip-details # Get your current IP
|
|
45
|
+
npm run cli -- get-ip-details 1.1.1.1 --include-extended-data
|
|
42
46
|
|
|
43
|
-
# 2. STDIO Transport - For
|
|
47
|
+
# 2. STDIO Transport - For AI assistant integration (Claude Desktop, Cursor)
|
|
44
48
|
npm run mcp:stdio
|
|
45
49
|
|
|
46
|
-
# 3. HTTP Transport - For web-based integrations
|
|
50
|
+
# 3. HTTP Transport - For web-based integrations
|
|
47
51
|
npm run mcp:http
|
|
48
52
|
|
|
49
53
|
# 4. Development with MCP Inspector
|
|
50
|
-
npm run mcp:inspect
|
|
54
|
+
npm run mcp:inspect # Auto-opens browser with debugging UI
|
|
51
55
|
```
|
|
52
56
|
|
|
53
57
|
## Transport Modes
|
|
54
58
|
|
|
55
59
|
### STDIO Transport
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
- Run with: `TRANSPORT_MODE=stdio
|
|
59
|
-
|
|
60
|
-
### Streamable HTTP Transport
|
|
61
|
-
-
|
|
62
|
-
- Supports multiple concurrent connections
|
|
63
|
-
- Runs on port 3000 by default (configurable via PORT env var)
|
|
64
|
-
- Endpoint: `http://localhost:3000/mcp`
|
|
65
|
-
- Health
|
|
66
|
-
- Run with: `TRANSPORT_MODE=http
|
|
60
|
+
- JSON-RPC communication via stdin/stdout
|
|
61
|
+
- Used by Claude Desktop, Cursor AI, and other local AI assistants
|
|
62
|
+
- Run with: `TRANSPORT_MODE=stdio node dist/index.js`
|
|
63
|
+
|
|
64
|
+
### Streamable HTTP Transport
|
|
65
|
+
- HTTP-based transport with Server-Sent Events (SSE)
|
|
66
|
+
- Supports multiple concurrent connections and web integrations
|
|
67
|
+
- Runs on port 3000 by default (configurable via `PORT` env var)
|
|
68
|
+
- MCP Endpoint: `http://localhost:3000/mcp`
|
|
69
|
+
- Health Check: `http://localhost:3000/` → Returns server version
|
|
70
|
+
- Run with: `TRANSPORT_MODE=http node dist/index.js`
|
|
67
71
|
|
|
68
72
|
## Architecture Overview
|
|
69
73
|
|
|
@@ -72,96 +76,138 @@ npm run mcp:inspect
|
|
|
72
76
|
|
|
73
77
|
```
|
|
74
78
|
src/
|
|
75
|
-
├── cli/
|
|
76
|
-
│ ├── index.ts
|
|
77
|
-
│ └──
|
|
78
|
-
├── controllers/
|
|
79
|
-
│
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
├──
|
|
83
|
-
│
|
|
84
|
-
|
|
85
|
-
├──
|
|
86
|
-
│ └──
|
|
87
|
-
├──
|
|
88
|
-
│ └──
|
|
89
|
-
├──
|
|
90
|
-
│
|
|
91
|
-
|
|
92
|
-
│
|
|
93
|
-
|
|
79
|
+
├── cli/ # Command-line interfaces
|
|
80
|
+
│ ├── index.ts # CLI entry point with Commander setup
|
|
81
|
+
│ └── ipaddress.cli.ts # IP address CLI commands
|
|
82
|
+
├── controllers/ # Business logic orchestration
|
|
83
|
+
│ ├── ipaddress.controller.ts # IP lookup business logic
|
|
84
|
+
│ └── ipaddress.formatter.ts # Response formatting
|
|
85
|
+
├── services/ # External API interactions
|
|
86
|
+
│ ├── vendor.ip-api.com.service.ts # ip-api.com service
|
|
87
|
+
│ └── vendor.ip-api.com.types.ts # Service type definitions
|
|
88
|
+
├── tools/ # MCP tool definitions (AI interface)
|
|
89
|
+
│ ├── ipaddress.tool.ts # IP lookup tool for AI assistants
|
|
90
|
+
│ └── ipaddress.types.ts # Tool argument schemas
|
|
91
|
+
├── resources/ # MCP resource definitions
|
|
92
|
+
│ └── ipaddress.resource.ts # IP lookup resource (URI: ip://address)
|
|
93
|
+
├── types/ # Global type definitions
|
|
94
|
+
│ └── common.types.ts # Shared interfaces (ControllerResponse, etc.)
|
|
95
|
+
├── utils/ # Shared utilities
|
|
96
|
+
│ ├── logger.util.ts # Contextual logging system
|
|
97
|
+
│ ├── error.util.ts # MCP-specific error formatting
|
|
98
|
+
│ ├── error-handler.util.ts # Error handling utilities
|
|
99
|
+
│ ├── config.util.ts # Environment configuration
|
|
100
|
+
│ ├── constants.util.ts # Version and package constants
|
|
101
|
+
│ ├── formatter.util.ts # Markdown formatting
|
|
102
|
+
│ └── transport.util.ts # HTTP transport utilities
|
|
103
|
+
└── index.ts # Server entry point (dual transport)
|
|
94
104
|
```
|
|
95
105
|
|
|
96
106
|
</details>
|
|
97
107
|
|
|
98
|
-
##
|
|
108
|
+
## 5-Layer Architecture
|
|
99
109
|
|
|
100
110
|
The boilerplate follows a clean, layered architecture that promotes maintainability and clear separation of concerns:
|
|
101
111
|
|
|
102
|
-
### 1. CLI Layer (`src/cli
|
|
112
|
+
### 1. CLI Layer (`src/cli/`)
|
|
113
|
+
|
|
114
|
+
- **Purpose**: Command-line interfaces for direct tool usage and testing
|
|
115
|
+
- **Implementation**: Commander-based argument parsing with contextual error handling
|
|
116
|
+
- **Example**: `get-ip-details [ipAddress] --include-extended-data --no-use-https`
|
|
117
|
+
- **Pattern**: Register commands → Parse arguments → Call controllers → Handle errors
|
|
118
|
+
|
|
119
|
+
### 2. Tools Layer (`src/tools/`)
|
|
103
120
|
|
|
104
|
-
- **Purpose**:
|
|
105
|
-
- **
|
|
106
|
-
- **
|
|
121
|
+
- **Purpose**: MCP tool definitions that AI assistants can invoke
|
|
122
|
+
- **Implementation**: Zod schema validation with structured responses
|
|
123
|
+
- **Example**: `ip_get_details` tool with optional IP address and configuration options
|
|
124
|
+
- **Pattern**: Define schema → Validate args → Call controller → Format MCP response
|
|
107
125
|
|
|
108
|
-
###
|
|
126
|
+
### 3. Resources Layer (`src/resources/`)
|
|
109
127
|
|
|
110
|
-
- **Purpose**: MCP
|
|
111
|
-
- **
|
|
112
|
-
- **
|
|
128
|
+
- **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 patterns → Parse requests → Return formatted content
|
|
113
132
|
|
|
114
|
-
###
|
|
133
|
+
### 4. Controllers Layer (`src/controllers/`)
|
|
115
134
|
|
|
116
|
-
- **Purpose**: Business logic orchestration
|
|
117
|
-
- **
|
|
118
|
-
- **
|
|
135
|
+
- **Purpose**: Business logic orchestration with comprehensive error handling
|
|
136
|
+
- **Implementation**: Options validation, fallback logic, response formatting
|
|
137
|
+
- **Example**: IP lookup with HTTPS fallback, test environment detection, API token validation
|
|
138
|
+
- **Pattern**: Validate inputs → Apply defaults → Call services → Format responses
|
|
119
139
|
|
|
120
|
-
###
|
|
140
|
+
### 5. Services Layer (`src/services/`)
|
|
121
141
|
|
|
122
|
-
- **Purpose**:
|
|
123
|
-
- **
|
|
124
|
-
- **
|
|
142
|
+
- **Purpose**: Direct external API interactions with minimal business logic
|
|
143
|
+
- **Implementation**: HTTP transport utilities with structured error handling
|
|
144
|
+
- **Example**: ip-api.com API calls with authentication and field selection
|
|
145
|
+
- **Pattern**: Build requests → Make API calls → Validate responses → Return raw data
|
|
125
146
|
|
|
126
|
-
###
|
|
147
|
+
### 6. Utils Layer (`src/utils/`)
|
|
127
148
|
|
|
128
|
-
- **Purpose**: Shared functionality across
|
|
129
|
-
- **Key
|
|
149
|
+
- **Purpose**: Shared functionality across all layers
|
|
150
|
+
- **Key Components**:
|
|
151
|
+
- `logger.util.ts`: Contextual logging (file:method context)
|
|
152
|
+
- `error.util.ts`: MCP-specific error formatting
|
|
153
|
+
- `transport.util.ts`: HTTP/API utilities with retry logic
|
|
154
|
+
- `config.util.ts`: Environment configuration management
|
|
130
155
|
|
|
131
156
|
## Developer Guide
|
|
132
157
|
|
|
133
158
|
### Development Scripts
|
|
134
159
|
|
|
135
160
|
```bash
|
|
136
|
-
#
|
|
137
|
-
npm run build # Build TypeScript
|
|
138
|
-
npm run clean #
|
|
161
|
+
# Build and Clean
|
|
162
|
+
npm run build # Build TypeScript to dist/
|
|
163
|
+
npm run clean # Remove dist/ and coverage/
|
|
164
|
+
npm run prepare # Build + ensure executable permissions (for npm publish)
|
|
165
|
+
|
|
166
|
+
# CLI Testing
|
|
167
|
+
npm run cli -- get-ip-details 8.8.8.8 # Test specific IP
|
|
168
|
+
npm run cli -- get-ip-details --include-extended-data # Test with extended data
|
|
169
|
+
npm run cli -- get-ip-details --no-use-https # Test with HTTP
|
|
139
170
|
|
|
140
|
-
#
|
|
141
|
-
npm run
|
|
142
|
-
npm run mcp:
|
|
143
|
-
npm run mcp:
|
|
144
|
-
npm run mcp:inspect # Run with MCP Inspector
|
|
171
|
+
# MCP Server Modes
|
|
172
|
+
npm run mcp:stdio # STDIO transport for AI assistants
|
|
173
|
+
npm run mcp:http # HTTP transport on port 3000
|
|
174
|
+
npm run mcp:inspect # HTTP + auto-open MCP Inspector
|
|
145
175
|
|
|
146
|
-
# Development
|
|
147
|
-
npm run dev:stdio
|
|
148
|
-
npm run dev:http
|
|
176
|
+
# Development with Debugging
|
|
177
|
+
npm run dev:stdio # STDIO with MCP Inspector integration
|
|
178
|
+
npm run dev:http # HTTP with debug logging enabled
|
|
149
179
|
|
|
150
180
|
# Testing
|
|
151
|
-
npm test # Run all tests
|
|
181
|
+
npm test # Run all tests (Jest)
|
|
152
182
|
npm run test:coverage # Generate coverage report
|
|
183
|
+
npm run test:cli # Run CLI-specific tests
|
|
153
184
|
|
|
154
185
|
# Code Quality
|
|
155
|
-
npm run lint #
|
|
156
|
-
npm run format #
|
|
186
|
+
npm run lint # ESLint with TypeScript rules
|
|
187
|
+
npm run format # Prettier formatting
|
|
188
|
+
npm run update:deps # Update dependencies
|
|
157
189
|
```
|
|
158
190
|
|
|
159
191
|
### Environment Variables
|
|
160
192
|
|
|
161
|
-
|
|
193
|
+
#### Core Configuration
|
|
194
|
+
- `TRANSPORT_MODE`: Transport mode (`stdio` | `http`, default: `stdio`)
|
|
162
195
|
- `PORT`: HTTP server port (default: `3000`)
|
|
163
|
-
- `DEBUG`: Enable debug logging (default: `false`)
|
|
164
|
-
|
|
196
|
+
- `DEBUG`: Enable debug logging (`true` | `false`, default: `false`)
|
|
197
|
+
|
|
198
|
+
#### IP API Configuration
|
|
199
|
+
- `IPAPI_API_TOKEN`: API token for ip-api.com extended data (optional, free tier available)
|
|
200
|
+
|
|
201
|
+
#### Example `.env` File
|
|
202
|
+
```bash
|
|
203
|
+
# Basic configuration
|
|
204
|
+
TRANSPORT_MODE=http
|
|
205
|
+
PORT=3001
|
|
206
|
+
DEBUG=true
|
|
207
|
+
|
|
208
|
+
# Extended data (requires ip-api.com account)
|
|
209
|
+
IPAPI_API_TOKEN=your_token_here
|
|
210
|
+
```
|
|
165
211
|
|
|
166
212
|
### Debugging Tools
|
|
167
213
|
|
|
@@ -198,63 +244,110 @@ Create `~/.mcp/configs.json`:
|
|
|
198
244
|
|
|
199
245
|
### 1. Define Service Layer
|
|
200
246
|
|
|
201
|
-
Create a new service in `src/services/`
|
|
247
|
+
Create a new service in `src/services/` following the vendor-specific naming pattern:
|
|
202
248
|
|
|
203
249
|
```typescript
|
|
204
|
-
// src/services/example.service.ts
|
|
250
|
+
// src/services/vendor.example-api.service.ts
|
|
205
251
|
import { Logger } from '../utils/logger.util.js';
|
|
252
|
+
import { fetchApi } from '../utils/transport.util.js';
|
|
253
|
+
import { ExampleApiResponse, ExampleApiRequestOptions } from './vendor.example-api.types.js';
|
|
254
|
+
import { createApiError, McpError } from '../utils/error.util.js';
|
|
255
|
+
|
|
256
|
+
const serviceLogger = Logger.forContext('services/vendor.example-api.service.ts');
|
|
206
257
|
|
|
207
|
-
|
|
258
|
+
async function get(
|
|
259
|
+
param?: string,
|
|
260
|
+
options: ExampleApiRequestOptions = {}
|
|
261
|
+
): Promise<ExampleApiResponse> {
|
|
262
|
+
const methodLogger = serviceLogger.forMethod('get');
|
|
263
|
+
methodLogger.debug(`Calling Example API with param: ${param}`);
|
|
208
264
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
265
|
+
try {
|
|
266
|
+
const url = `https://api.example.com/${param || 'default'}`;
|
|
267
|
+
const rawData = await fetchApi<ExampleApiResponse>(url, {
|
|
268
|
+
headers: options.apiKey ? { 'Authorization': `Bearer ${options.apiKey}` } : {}
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
methodLogger.debug('Received successful response from Example API');
|
|
272
|
+
return rawData;
|
|
273
|
+
} catch (error) {
|
|
274
|
+
methodLogger.error('Service error fetching data', error);
|
|
275
|
+
|
|
276
|
+
if (error instanceof McpError) {
|
|
277
|
+
throw error;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
throw createApiError(
|
|
281
|
+
'Unexpected service error while fetching data',
|
|
282
|
+
undefined,
|
|
283
|
+
error
|
|
284
|
+
);
|
|
285
|
+
}
|
|
213
286
|
}
|
|
287
|
+
|
|
288
|
+
export default { get };
|
|
214
289
|
```
|
|
215
290
|
|
|
216
291
|
### 2. Create Controller
|
|
217
292
|
|
|
218
|
-
Add a controller in `src/controllers/` to handle business logic:
|
|
293
|
+
Add a controller in `src/controllers/` to handle business logic with error context:
|
|
219
294
|
|
|
220
295
|
```typescript
|
|
221
296
|
// src/controllers/example.controller.ts
|
|
222
297
|
import { Logger } from '../utils/logger.util.js';
|
|
223
|
-
import
|
|
224
|
-
import {
|
|
225
|
-
import { handleControllerError } from '../utils/error-handler.util.js';
|
|
298
|
+
import exampleService from '../services/vendor.example-api.service.js';
|
|
299
|
+
import { formatExample } from './example.formatter.js';
|
|
300
|
+
import { handleControllerError, buildErrorContext } from '../utils/error-handler.util.js';
|
|
226
301
|
import { ControllerResponse } from '../types/common.types.js';
|
|
302
|
+
import { config } from '../utils/config.util.js';
|
|
227
303
|
|
|
228
304
|
const logger = Logger.forContext('controllers/example.controller.ts');
|
|
229
305
|
|
|
230
306
|
export interface GetDataOptions {
|
|
231
307
|
param?: string;
|
|
308
|
+
includeMetadata?: boolean;
|
|
232
309
|
}
|
|
233
310
|
|
|
234
|
-
|
|
235
|
-
options: GetDataOptions = {}
|
|
311
|
+
async function getData(
|
|
312
|
+
options: GetDataOptions = {}
|
|
236
313
|
): Promise<ControllerResponse> {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const data = await exampleService.getData(options.param || 'default');
|
|
314
|
+
const methodLogger = logger.forMethod('getData');
|
|
315
|
+
methodLogger.debug(`Getting data for param: ${options.param || 'default'}`, options);
|
|
241
316
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
317
|
+
try {
|
|
318
|
+
// Apply business logic and defaults
|
|
319
|
+
const apiKey = config.get('EXAMPLE_API_TOKEN');
|
|
320
|
+
|
|
321
|
+
// Call service layer
|
|
322
|
+
const data = await exampleService.get(options.param, {
|
|
323
|
+
apiKey,
|
|
324
|
+
includeMetadata: options.includeMetadata ?? false
|
|
250
325
|
});
|
|
326
|
+
|
|
327
|
+
// Format response
|
|
328
|
+
const formattedContent = formatExample(data);
|
|
329
|
+
return { content: formattedContent };
|
|
330
|
+
|
|
331
|
+
} catch (error) {
|
|
332
|
+
throw handleControllerError(
|
|
333
|
+
error,
|
|
334
|
+
buildErrorContext(
|
|
335
|
+
'ExampleData',
|
|
336
|
+
'getData',
|
|
337
|
+
'controllers/example.controller.ts@getData',
|
|
338
|
+
options.param || 'default',
|
|
339
|
+
{ options }
|
|
340
|
+
)
|
|
341
|
+
);
|
|
251
342
|
}
|
|
252
343
|
}
|
|
344
|
+
|
|
345
|
+
export default { getData };
|
|
253
346
|
```
|
|
254
347
|
|
|
255
348
|
### 3. Implement MCP Tool
|
|
256
349
|
|
|
257
|
-
Create a tool definition in `src/tools
|
|
350
|
+
Create a tool definition in `src/tools/` following the registration pattern:
|
|
258
351
|
|
|
259
352
|
```typescript
|
|
260
353
|
// src/tools/example.tool.ts
|
|
@@ -262,74 +355,109 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
262
355
|
import { z } from 'zod';
|
|
263
356
|
import { Logger } from '../utils/logger.util.js';
|
|
264
357
|
import { formatErrorForMcpTool } from '../utils/error.util.js';
|
|
265
|
-
import
|
|
358
|
+
import exampleController from '../controllers/example.controller.js';
|
|
266
359
|
|
|
267
360
|
const logger = Logger.forContext('tools/example.tool.ts');
|
|
268
361
|
|
|
269
|
-
|
|
270
|
-
|
|
362
|
+
// Define Zod schema for tool arguments
|
|
363
|
+
const GetDataSchema = z.object({
|
|
364
|
+
param: z.string().optional().describe('Optional parameter for the API call'),
|
|
365
|
+
includeMetadata: z.boolean().optional().default(false)
|
|
366
|
+
.describe('Whether to include additional metadata in the response')
|
|
271
367
|
});
|
|
272
368
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
369
|
+
async function handleGetData(args: Record<string, unknown>) {
|
|
370
|
+
const methodLogger = logger.forMethod('handleGetData');
|
|
371
|
+
|
|
276
372
|
try {
|
|
277
|
-
|
|
373
|
+
methodLogger.debug('Tool example_get_data called', args);
|
|
278
374
|
|
|
375
|
+
// Validate arguments with Zod
|
|
376
|
+
const validatedArgs = GetDataSchema.parse(args);
|
|
377
|
+
|
|
378
|
+
// Call controller
|
|
279
379
|
const result = await exampleController.getData({
|
|
280
|
-
param:
|
|
380
|
+
param: validatedArgs.param,
|
|
381
|
+
includeMetadata: validatedArgs.includeMetadata
|
|
281
382
|
});
|
|
282
383
|
|
|
384
|
+
// Return MCP-formatted response
|
|
283
385
|
return {
|
|
284
|
-
content: [
|
|
386
|
+
content: [
|
|
387
|
+
{
|
|
388
|
+
type: 'text' as const,
|
|
389
|
+
text: result.content
|
|
390
|
+
}
|
|
391
|
+
]
|
|
285
392
|
};
|
|
286
393
|
} catch (error) {
|
|
287
|
-
|
|
394
|
+
methodLogger.error('Tool example_get_data failed', error);
|
|
288
395
|
return formatErrorForMcpTool(error);
|
|
289
396
|
}
|
|
290
397
|
}
|
|
291
398
|
|
|
292
|
-
|
|
399
|
+
// Registration function following the pattern used by existing tools
|
|
400
|
+
function registerTools(server: McpServer) {
|
|
401
|
+
const registerLogger = logger.forMethod('registerTools');
|
|
402
|
+
registerLogger.debug('Registering example tools...');
|
|
403
|
+
|
|
293
404
|
server.tool(
|
|
294
|
-
'
|
|
295
|
-
`Gets data from the
|
|
296
|
-
Use this to fetch example data. Returns formatted data as Markdown.`,
|
|
297
|
-
|
|
298
|
-
handleGetData
|
|
405
|
+
'example_get_data',
|
|
406
|
+
`Gets data from the Example API with optional parameter.
|
|
407
|
+
Use this tool to fetch example data. Returns formatted data as Markdown.`,
|
|
408
|
+
GetDataSchema.shape,
|
|
409
|
+
handleGetData
|
|
299
410
|
);
|
|
411
|
+
|
|
412
|
+
registerLogger.debug('Example tools registered successfully');
|
|
300
413
|
}
|
|
414
|
+
|
|
415
|
+
export default { registerTools };
|
|
301
416
|
```
|
|
302
417
|
|
|
303
418
|
### 4. Add CLI Support
|
|
304
419
|
|
|
305
|
-
Create a CLI command in `src/cli
|
|
420
|
+
Create a CLI command in `src/cli/` following the Commander pattern:
|
|
306
421
|
|
|
307
422
|
```typescript
|
|
308
423
|
// src/cli/example.cli.ts
|
|
309
|
-
import {
|
|
424
|
+
import { Command } from 'commander';
|
|
310
425
|
import { Logger } from '../utils/logger.util.js';
|
|
311
|
-
import
|
|
312
|
-
import { handleCliError } from '../utils/error
|
|
426
|
+
import exampleController from '../controllers/example.controller.js';
|
|
427
|
+
import { handleCliError } from '../utils/error.util.js';
|
|
313
428
|
|
|
314
429
|
const logger = Logger.forContext('cli/example.cli.ts');
|
|
315
430
|
|
|
316
|
-
program
|
|
317
|
-
.
|
|
318
|
-
.
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
431
|
+
function register(program: Command) {
|
|
432
|
+
const methodLogger = logger.forMethod('register');
|
|
433
|
+
methodLogger.debug('Registering example CLI commands...');
|
|
434
|
+
|
|
435
|
+
program
|
|
436
|
+
.command('get-data')
|
|
437
|
+
.description('Gets data from the Example API')
|
|
438
|
+
.argument('[param]', 'Optional parameter for the API call')
|
|
439
|
+
.option('-m, --include-metadata', 'Include additional metadata in response')
|
|
440
|
+
.action(async (param, options) => {
|
|
441
|
+
const actionLogger = logger.forMethod('action:get-data');
|
|
442
|
+
|
|
443
|
+
try {
|
|
444
|
+
actionLogger.debug('CLI get-data called', { param, options });
|
|
445
|
+
|
|
446
|
+
const result = await exampleController.getData({
|
|
447
|
+
param,
|
|
448
|
+
includeMetadata: options.includeMetadata || false
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
console.log(result.content);
|
|
452
|
+
} catch (error) {
|
|
453
|
+
handleCliError(error);
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
methodLogger.debug('Example CLI commands registered successfully');
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
export default { register };
|
|
333
461
|
```
|
|
334
462
|
|
|
335
463
|
### 5. Register Components
|
|
@@ -337,48 +465,142 @@ program
|
|
|
337
465
|
Update the entry points to register your new components:
|
|
338
466
|
|
|
339
467
|
```typescript
|
|
340
|
-
//
|
|
341
|
-
import '
|
|
468
|
+
// 1. Register CLI in src/cli/index.ts
|
|
469
|
+
import exampleCli from './example.cli.js';
|
|
470
|
+
|
|
471
|
+
export async function runCli(args: string[]) {
|
|
472
|
+
// ... existing setup code ...
|
|
473
|
+
|
|
474
|
+
// Register CLI commands
|
|
475
|
+
exampleCli.register(program); // Add this line
|
|
476
|
+
|
|
477
|
+
// ... rest of function
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// 2. Register Tools in src/index.ts
|
|
481
|
+
import exampleTools from './tools/example.tool.js';
|
|
342
482
|
|
|
343
|
-
// In
|
|
344
|
-
|
|
345
|
-
// Then in registerTools function:
|
|
346
|
-
exampleTool.register(server);
|
|
483
|
+
// In the startServer function, after existing registrations:
|
|
484
|
+
exampleTools.registerTools(serverInstance);
|
|
347
485
|
```
|
|
348
486
|
|
|
349
487
|
</details>
|
|
350
488
|
|
|
489
|
+
## IP Address Example Implementation
|
|
490
|
+
|
|
491
|
+
The boilerplate includes a complete IP address geolocation example demonstrating all layers:
|
|
492
|
+
|
|
493
|
+
### Available Tools & Commands
|
|
494
|
+
|
|
495
|
+
**CLI Commands:**
|
|
496
|
+
```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
|
|
499
|
+
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)
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
**MCP Tools:**
|
|
504
|
+
- `ip_get_details` - IP geolocation lookup for AI assistants
|
|
505
|
+
|
|
506
|
+
**MCP Resources:**
|
|
507
|
+
- `ip://` - Current IP details
|
|
508
|
+
- `ip://8.8.8.8` - Specific IP details
|
|
509
|
+
|
|
510
|
+
### Features Demonstrated
|
|
511
|
+
|
|
512
|
+
- **Fallback Logic**: HTTPS → HTTP fallback for free tier users
|
|
513
|
+
- **Environment Detection**: Different behavior in test vs production
|
|
514
|
+
- **API Token Support**: Optional token for extended data (ASN, mobile detection, etc.)
|
|
515
|
+
- **Error Handling**: Structured errors for private/reserved IP addresses
|
|
516
|
+
- **Response Formatting**: Clean Markdown output with geolocation data
|
|
517
|
+
|
|
518
|
+
### Configuration Options
|
|
519
|
+
|
|
520
|
+
```bash
|
|
521
|
+
# Optional - for extended data features
|
|
522
|
+
IPAPI_API_TOKEN=your_token_from_ip-api.com
|
|
523
|
+
|
|
524
|
+
# Development
|
|
525
|
+
DEBUG=true # Enable detailed logging
|
|
526
|
+
TRANSPORT_MODE=http # Use HTTP transport
|
|
527
|
+
PORT=3001 # Custom port
|
|
528
|
+
```
|
|
529
|
+
|
|
351
530
|
## Publishing Your MCP Server
|
|
352
531
|
|
|
353
|
-
1.
|
|
532
|
+
1. **Customize Package Details:**
|
|
354
533
|
```json
|
|
355
534
|
{
|
|
356
535
|
"name": "your-mcp-server-name",
|
|
357
|
-
"version": "1.0.0",
|
|
536
|
+
"version": "1.0.0",
|
|
358
537
|
"description": "Your custom MCP server",
|
|
359
538
|
"author": "Your Name",
|
|
360
|
-
|
|
539
|
+
"keywords": ["mcp", "your-domain", "ai-integration"]
|
|
361
540
|
}
|
|
362
541
|
```
|
|
363
542
|
|
|
364
|
-
2. Update
|
|
365
|
-
3.
|
|
366
|
-
|
|
367
|
-
|
|
543
|
+
2. **Update Documentation:** Replace IP address examples with your use case
|
|
544
|
+
3. **Test Thoroughly:**
|
|
545
|
+
```bash
|
|
546
|
+
npm run build && npm test
|
|
547
|
+
npm run cli -- your-command
|
|
548
|
+
npm run mcp:stdio # Test with MCP Inspector
|
|
549
|
+
```
|
|
550
|
+
4. **Publish:** `npm publish` (requires npm login)
|
|
551
|
+
|
|
552
|
+
## Testing Strategy
|
|
553
|
+
|
|
554
|
+
The boilerplate includes comprehensive testing infrastructure:
|
|
555
|
+
|
|
556
|
+
### Test Structure
|
|
557
|
+
```
|
|
558
|
+
tests/ # Not present - tests are in src/
|
|
559
|
+
src/
|
|
560
|
+
├── **/*.test.ts # Co-located with source files
|
|
561
|
+
├── utils/ # Utility function tests
|
|
562
|
+
├── controllers/ # Business logic tests
|
|
563
|
+
├── services/ # API integration tests
|
|
564
|
+
└── cli/ # CLI command tests
|
|
565
|
+
```
|
|
368
566
|
|
|
369
|
-
|
|
567
|
+
### Testing Best Practices
|
|
370
568
|
|
|
371
|
-
- **Unit Tests**: Test
|
|
569
|
+
- **Unit Tests**: Test utilities and pure functions (`*.util.test.ts`)
|
|
372
570
|
- **Controller Tests**: Test business logic with mocked service calls
|
|
373
|
-
- **
|
|
374
|
-
- **
|
|
571
|
+
- **Service Tests**: Test API integration with real/mocked HTTP calls
|
|
572
|
+
- **CLI Tests**: Test command parsing and execution
|
|
573
|
+
- **Test Environment Detection**: Automatic test mode handling in controllers
|
|
574
|
+
|
|
575
|
+
### Running Tests
|
|
576
|
+
|
|
577
|
+
```bash
|
|
578
|
+
npm test # Run all tests
|
|
579
|
+
npm run test:coverage # Generate coverage report
|
|
580
|
+
npm run test:cli # CLI-specific tests only
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### Coverage Goals
|
|
584
|
+
- Target: >80% test coverage
|
|
585
|
+
- Focus on business logic (controllers) and utilities
|
|
586
|
+
- Mock external services appropriately
|
|
375
587
|
|
|
376
588
|
## License
|
|
377
589
|
|
|
378
590
|
[ISC License](https://opensource.org/licenses/ISC)
|
|
379
591
|
|
|
380
|
-
## Resources
|
|
592
|
+
## Resources & Documentation
|
|
593
|
+
|
|
594
|
+
### MCP Protocol Resources
|
|
595
|
+
- [MCP Specification](https://modelcontextprotocol.io/specification/2025-06-18)
|
|
596
|
+
- [MCP SDK Documentation](https://github.com/modelcontextprotocol/sdk)
|
|
597
|
+
- [MCP Inspector](https://github.com/modelcontextprotocol/inspector) - Visual debugging tool
|
|
598
|
+
|
|
599
|
+
### Implementation References
|
|
600
|
+
- [Anthropic MCP Announcement](https://www.anthropic.com/news/model-context-protocol)
|
|
601
|
+
- [Awesome MCP Servers](https://github.com/wong2/awesome-mcp-servers) - Community examples
|
|
602
|
+
- [TypeScript Documentation](https://www.typescriptlang.org/docs/)
|
|
381
603
|
|
|
382
|
-
|
|
383
|
-
- [
|
|
384
|
-
- [
|
|
604
|
+
### Your MCP Server Ecosystem
|
|
605
|
+
- [All @aashari MCP Servers](https://www.npmjs.com/~aashari) - NPM packages
|
|
606
|
+
- [GitHub Repositories](https://github.com/aashari?tab=repositories&q=mcp-server) - Source code
|
|
@@ -49,7 +49,13 @@ class ConfigLoader {
|
|
|
49
49
|
loadFromEnvFile() {
|
|
50
50
|
const methodLogger = logger_util_js_1.Logger.forContext('utils/config.util.ts', 'loadFromEnvFile');
|
|
51
51
|
try {
|
|
52
|
-
const result = dotenv_1.default.config(
|
|
52
|
+
const result = dotenv_1.default.config({
|
|
53
|
+
// Suppress dotenv output in test environment
|
|
54
|
+
debug: process.env.NODE_ENV !== 'test' &&
|
|
55
|
+
process.env.DEBUG === 'true',
|
|
56
|
+
// Suppress promotional messages in test environment (dotenv v17+)
|
|
57
|
+
quiet: process.env.NODE_ENV === 'test',
|
|
58
|
+
});
|
|
53
59
|
if (result.error) {
|
|
54
60
|
methodLogger.debug('No .env file found or error reading it');
|
|
55
61
|
return;
|
|
@@ -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.
|
|
14
|
+
exports.VERSION = '1.14.0';
|
|
15
15
|
/**
|
|
16
16
|
* Package name with scope
|
|
17
17
|
* Used for initialization and identification
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Jest global setup for suppressing console output during tests
|
|
4
|
+
* This file is used to mock console methods to reduce noise in test output
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const globals_1 = require("@jest/globals");
|
|
8
|
+
// Store original console methods
|
|
9
|
+
const originalConsole = {
|
|
10
|
+
log: console.log,
|
|
11
|
+
info: console.info,
|
|
12
|
+
warn: console.warn,
|
|
13
|
+
error: console.error,
|
|
14
|
+
debug: console.debug,
|
|
15
|
+
};
|
|
16
|
+
// Global setup to suppress console output during tests
|
|
17
|
+
(0, globals_1.beforeEach)(() => {
|
|
18
|
+
// Mock console methods to suppress output
|
|
19
|
+
console.log = globals_1.jest.fn();
|
|
20
|
+
console.info = globals_1.jest.fn();
|
|
21
|
+
console.warn = globals_1.jest.fn();
|
|
22
|
+
console.error = globals_1.jest.fn();
|
|
23
|
+
console.debug = globals_1.jest.fn();
|
|
24
|
+
});
|
|
25
|
+
(0, globals_1.afterEach)(() => {
|
|
26
|
+
// Clear mock calls after each test
|
|
27
|
+
globals_1.jest.clearAllMocks();
|
|
28
|
+
});
|
|
29
|
+
(0, globals_1.afterAll)(() => {
|
|
30
|
+
// Restore original console methods after all tests
|
|
31
|
+
console.log = originalConsole.log;
|
|
32
|
+
console.info = originalConsole.info;
|
|
33
|
+
console.warn = originalConsole.warn;
|
|
34
|
+
console.error = originalConsole.error;
|
|
35
|
+
console.debug = originalConsole.debug;
|
|
36
|
+
});
|
|
@@ -292,11 +292,14 @@ class Logger {
|
|
|
292
292
|
// If we can't write to the log file, log the error to console
|
|
293
293
|
console.error(`Failed to write to log file: ${err}`);
|
|
294
294
|
}
|
|
295
|
-
if
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
295
|
+
// Only output to console if not in test environment or if debug is enabled
|
|
296
|
+
if (process.env.NODE_ENV !== 'test' || process.env.DEBUG === 'true') {
|
|
297
|
+
if (process.env.NODE_ENV === 'test') {
|
|
298
|
+
console[level](logMessage);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
console.error(logMessage);
|
|
302
|
+
}
|
|
300
303
|
}
|
|
301
304
|
}
|
|
302
305
|
info(message, ...args) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aashari/boilerplate-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.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,35 +51,35 @@
|
|
|
51
51
|
"node": ">=18.0.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@eslint/js": "^9.
|
|
54
|
+
"@eslint/js": "^9.35.0",
|
|
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.
|
|
58
|
+
"@semantic-release/github": "^11.0.5",
|
|
59
59
|
"@semantic-release/npm": "^12.0.2",
|
|
60
60
|
"@types/cors": "^2.8.19",
|
|
61
61
|
"@types/express": "^5.0.3",
|
|
62
62
|
"@types/jest": "^30.0.0",
|
|
63
|
-
"@types/node": "^24.1
|
|
64
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
65
|
-
"@typescript-eslint/parser": "^8.
|
|
66
|
-
"eslint": "^9.
|
|
63
|
+
"@types/node": "^24.3.1",
|
|
64
|
+
"@typescript-eslint/eslint-plugin": "^8.43.0",
|
|
65
|
+
"@typescript-eslint/parser": "^8.43.0",
|
|
66
|
+
"eslint": "^9.35.0",
|
|
67
67
|
"eslint-config-prettier": "^10.1.8",
|
|
68
|
-
"eslint-plugin-prettier": "^5.5.
|
|
69
|
-
"jest": "^30.
|
|
68
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
69
|
+
"jest": "^30.1.3",
|
|
70
70
|
"prettier": "^3.6.2",
|
|
71
71
|
"semantic-release": "^24.2.7",
|
|
72
|
-
"ts-jest": "^29.4.
|
|
73
|
-
"typescript": "5.
|
|
74
|
-
"typescript-eslint": "^8.
|
|
72
|
+
"ts-jest": "^29.4.1",
|
|
73
|
+
"typescript": "^5.9.2",
|
|
74
|
+
"typescript-eslint": "^8.43.0"
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@modelcontextprotocol/sdk": "^1.17.
|
|
77
|
+
"@modelcontextprotocol/sdk": "^1.17.5",
|
|
78
78
|
"commander": "^14.0.0",
|
|
79
79
|
"cors": "^2.8.5",
|
|
80
|
-
"dotenv": "^17.2.
|
|
80
|
+
"dotenv": "^17.2.2",
|
|
81
81
|
"express": "^5.1.0",
|
|
82
|
-
"zod": "^3.25.
|
|
82
|
+
"zod": "^3.25.76"
|
|
83
83
|
},
|
|
84
84
|
"publishConfig": {
|
|
85
85
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -88,12 +88,16 @@
|
|
|
88
88
|
"jest": {
|
|
89
89
|
"preset": "ts-jest",
|
|
90
90
|
"testEnvironment": "node",
|
|
91
|
+
"setupFilesAfterEnv": [
|
|
92
|
+
"<rootDir>/src/utils/jest.setup.ts"
|
|
93
|
+
],
|
|
91
94
|
"testMatch": [
|
|
92
95
|
"**/src/**/*.test.ts"
|
|
93
96
|
],
|
|
94
97
|
"collectCoverageFrom": [
|
|
95
98
|
"src/**/*.ts",
|
|
96
|
-
"!src/**/*.test.ts"
|
|
99
|
+
"!src/**/*.test.ts",
|
|
100
|
+
"!src/utils/jest.setup.ts"
|
|
97
101
|
],
|
|
98
102
|
"transform": {
|
|
99
103
|
"^.+\\.tsx?$": [
|
package/package.json.bak
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aashari/boilerplate-mcp-server",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.5",
|
|
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,35 +51,35 @@
|
|
|
51
51
|
"node": ">=18.0.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@eslint/js": "^9.
|
|
54
|
+
"@eslint/js": "^9.35.0",
|
|
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.
|
|
58
|
+
"@semantic-release/github": "^11.0.5",
|
|
59
59
|
"@semantic-release/npm": "^12.0.2",
|
|
60
60
|
"@types/cors": "^2.8.19",
|
|
61
61
|
"@types/express": "^5.0.3",
|
|
62
62
|
"@types/jest": "^30.0.0",
|
|
63
|
-
"@types/node": "^24.1
|
|
64
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
65
|
-
"@typescript-eslint/parser": "^8.
|
|
66
|
-
"eslint": "^9.
|
|
63
|
+
"@types/node": "^24.3.1",
|
|
64
|
+
"@typescript-eslint/eslint-plugin": "^8.43.0",
|
|
65
|
+
"@typescript-eslint/parser": "^8.43.0",
|
|
66
|
+
"eslint": "^9.35.0",
|
|
67
67
|
"eslint-config-prettier": "^10.1.8",
|
|
68
|
-
"eslint-plugin-prettier": "^5.5.
|
|
69
|
-
"jest": "^30.
|
|
68
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
69
|
+
"jest": "^30.1.3",
|
|
70
70
|
"prettier": "^3.6.2",
|
|
71
71
|
"semantic-release": "^24.2.7",
|
|
72
|
-
"ts-jest": "^29.4.
|
|
73
|
-
"typescript": "5.
|
|
74
|
-
"typescript-eslint": "^8.
|
|
72
|
+
"ts-jest": "^29.4.1",
|
|
73
|
+
"typescript": "^5.9.2",
|
|
74
|
+
"typescript-eslint": "^8.43.0"
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@modelcontextprotocol/sdk": "^1.17.
|
|
77
|
+
"@modelcontextprotocol/sdk": "^1.17.5",
|
|
78
78
|
"commander": "^14.0.0",
|
|
79
79
|
"cors": "^2.8.5",
|
|
80
|
-
"dotenv": "^17.2.
|
|
80
|
+
"dotenv": "^17.2.2",
|
|
81
81
|
"express": "^5.1.0",
|
|
82
|
-
"zod": "^3.25.
|
|
82
|
+
"zod": "^3.25.76"
|
|
83
83
|
},
|
|
84
84
|
"publishConfig": {
|
|
85
85
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -88,12 +88,16 @@
|
|
|
88
88
|
"jest": {
|
|
89
89
|
"preset": "ts-jest",
|
|
90
90
|
"testEnvironment": "node",
|
|
91
|
+
"setupFilesAfterEnv": [
|
|
92
|
+
"<rootDir>/src/utils/jest.setup.ts"
|
|
93
|
+
],
|
|
91
94
|
"testMatch": [
|
|
92
95
|
"**/src/**/*.test.ts"
|
|
93
96
|
],
|
|
94
97
|
"collectCoverageFrom": [
|
|
95
98
|
"src/**/*.ts",
|
|
96
|
-
"!src/**/*.test.ts"
|
|
99
|
+
"!src/**/*.test.ts",
|
|
100
|
+
"!src/utils/jest.setup.ts"
|
|
97
101
|
],
|
|
98
102
|
"transform": {
|
|
99
103
|
"^.+\\.tsx?$": [
|
package/.node-version
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
22.14.0
|
package/GEMINI.md
DELETED
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
# AUTONOMOUS MCP ENGINEER - GEMINI SYSTEM DIRECTIVES
|
|
2
|
-
|
|
3
|
-
**You are an autonomous senior MCP (Model Context Protocol) engineer with COMPLETE AUTHORITY over this TypeScript MCP server codebase.**
|
|
4
|
-
|
|
5
|
-
## PROJECT OVERVIEW
|
|
6
|
-
|
|
7
|
-
**Boilerplate MCP Server** - A foundation for developing custom Model Context Protocol servers in TypeScript with production-ready architecture, working example tools, and comprehensive developer infrastructure.
|
|
8
|
-
|
|
9
|
-
### Technology Stack
|
|
10
|
-
- **Language**: TypeScript 5.8.3
|
|
11
|
-
- **Runtime**: Node.js >=18.0.0
|
|
12
|
-
- **Package Manager**: npm
|
|
13
|
-
- **MCP SDK**: @modelcontextprotocol/sdk ^1.17.1
|
|
14
|
-
- **Transport Modes**: STDIO and Streamable HTTP (SSE)
|
|
15
|
-
- **Testing**: Jest with ts-jest
|
|
16
|
-
- **Code Quality**: ESLint + Prettier + TypeScript strict mode
|
|
17
|
-
- **Release**: Semantic release with conventional commits
|
|
18
|
-
|
|
19
|
-
### Architecture Layers
|
|
20
|
-
```
|
|
21
|
-
src/
|
|
22
|
-
├── cli/ # Command-line interfaces (Commander.js)
|
|
23
|
-
├── tools/ # MCP tool definitions (Zod schemas)
|
|
24
|
-
├── controllers/ # Business logic orchestration
|
|
25
|
-
├── services/ # External API interactions
|
|
26
|
-
├── resources/ # MCP resource definitions
|
|
27
|
-
├── types/ # Type definitions
|
|
28
|
-
└── utils/ # Shared utilities (logging, error handling)
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Current Implementation
|
|
32
|
-
- **Working Example**: IP address lookup tools using ip-api.com
|
|
33
|
-
- **Dual Transport**: STDIO for local AI integration, HTTP for web-based connections
|
|
34
|
-
- **Production Ready**: Error handling, logging, testing, and CI/CD setup
|
|
35
|
-
|
|
36
|
-
## YOUR AUTHORITY & RESPONSIBILITIES
|
|
37
|
-
|
|
38
|
-
### COMPLETE AUTONOMY
|
|
39
|
-
- **Code Authority**: Create, modify, delete any source code or configuration
|
|
40
|
-
- **Architecture Decisions**: Choose patterns, libraries, and implementation approaches
|
|
41
|
-
- **Quality Standards**: Enforce TypeScript best practices and MCP protocol compliance
|
|
42
|
-
- **Release Management**: Use semantic release through conventional commits
|
|
43
|
-
- **Testing Strategy**: Implement comprehensive test coverage for all MCP tools
|
|
44
|
-
|
|
45
|
-
### ACCOUNTABILITY AREAS
|
|
46
|
-
- **MCP Protocol Compliance**: Ensure tools follow MCP specification exactly
|
|
47
|
-
- **TypeScript Excellence**: Maintain strict type safety and modern patterns
|
|
48
|
-
- **Clean Architecture**: Preserve layered separation of concerns
|
|
49
|
-
- **Developer Experience**: Keep CLI tools, documentation, and examples current
|
|
50
|
-
- **Production Readiness**: Error handling, logging, and transport reliability
|
|
51
|
-
|
|
52
|
-
## MCP ENGINEERING PRINCIPLES
|
|
53
|
-
|
|
54
|
-
### 1. Tool-First Development
|
|
55
|
-
Every feature starts with MCP tool definition:
|
|
56
|
-
```typescript
|
|
57
|
-
// Define tool with Zod schema
|
|
58
|
-
const GetDataArgs = z.object({
|
|
59
|
-
param: z.string().describe('Parameter description')
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// Implement handler calling controller
|
|
63
|
-
async function handleGetData(args: GetDataArgsType) {
|
|
64
|
-
const result = await controller.getData(args);
|
|
65
|
-
return { content: [{ type: 'text', text: result.content }] };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Register with server
|
|
69
|
-
server.tool('get_data', 'Tool description', GetDataArgs.shape, handleGetData);
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### 2. Layered Architecture Enforcement
|
|
73
|
-
- **CLI Layer**: Parse arguments → Call controllers → Handle CLI errors
|
|
74
|
-
- **Tools Layer**: Validate MCP args → Call controllers → Format MCP response
|
|
75
|
-
- **Controllers**: Business logic → Call services → Return standardized response
|
|
76
|
-
- **Services**: Pure API calls → Minimal logic → Return raw data
|
|
77
|
-
|
|
78
|
-
### 3. Transport Agnostic Design
|
|
79
|
-
All MCP tools must work identically across:
|
|
80
|
-
- **STDIO Transport**: `npm run mcp:stdio` for AI assistant integration
|
|
81
|
-
- **HTTP Transport**: `npm run mcp:http` for web-based connections
|
|
82
|
-
- **CLI Interface**: `npm run cli -- command` for direct usage
|
|
83
|
-
|
|
84
|
-
### 4. Error Handling Standards
|
|
85
|
-
```typescript
|
|
86
|
-
// Controller pattern
|
|
87
|
-
export async function getData(options: GetDataOptions): Promise<ControllerResponse> {
|
|
88
|
-
try {
|
|
89
|
-
// Business logic here
|
|
90
|
-
return { content: formattedResult };
|
|
91
|
-
} catch (error) {
|
|
92
|
-
throw handleControllerError(error, {
|
|
93
|
-
entityType: 'DataType',
|
|
94
|
-
operation: 'getData',
|
|
95
|
-
source: 'controllers/data.controller.ts'
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## AUTONOMOUS IMPLEMENTATION WORKFLOW
|
|
102
|
-
|
|
103
|
-
### 1. ANALYZE
|
|
104
|
-
- **Read existing patterns**: Examine current IP address tools for architecture guidance
|
|
105
|
-
- **Understand requirements**: Parse GitHub event context for specific needs
|
|
106
|
-
- **Map dependencies**: Identify what services, types, and utilities are needed
|
|
107
|
-
- **Plan architecture**: Design tool → controller → service chain
|
|
108
|
-
|
|
109
|
-
### 2. RESEARCH & DESIGN
|
|
110
|
-
- **External APIs**: Research target APIs for schemas and error patterns
|
|
111
|
-
- **Zod Schemas**: Design comprehensive argument validation
|
|
112
|
-
- **Type Safety**: Define interfaces for all data flows
|
|
113
|
-
- **Error Scenarios**: Plan error handling for all failure modes
|
|
114
|
-
|
|
115
|
-
### 3. IMPLEMENT
|
|
116
|
-
- **Service Layer**: Pure API interaction with proper error handling
|
|
117
|
-
- **Controller Layer**: Business logic with standardized response format
|
|
118
|
-
- **Tool Layer**: MCP compliant tool with Zod validation
|
|
119
|
-
- **CLI Layer**: Commander.js interface for direct usage
|
|
120
|
-
- **Tests**: Comprehensive unit and integration test coverage
|
|
121
|
-
|
|
122
|
-
### 4. VALIDATE & DEPLOY
|
|
123
|
-
- **Quality Checks**: Run lint, format, test, build successfully
|
|
124
|
-
- **MCP Testing**: Use `npm run mcp:inspect` for interactive tool testing
|
|
125
|
-
- **Transport Testing**: Verify STDIO and HTTP transport functionality
|
|
126
|
-
- **Documentation**: Update README and tool descriptions
|
|
127
|
-
|
|
128
|
-
## DEVELOPMENT STANDARDS
|
|
129
|
-
|
|
130
|
-
### TypeScript Excellence
|
|
131
|
-
- **Strict Mode**: All code must compile with strict TypeScript settings
|
|
132
|
-
- **No Any Types**: Use proper typing for all function parameters and returns
|
|
133
|
-
- **Interface Definitions**: Define clear interfaces for all data structures
|
|
134
|
-
- **Generic Constraints**: Use generics appropriately for reusable code
|
|
135
|
-
|
|
136
|
-
### MCP Protocol Compliance
|
|
137
|
-
- **Tool Registration**: Use proper `server.tool()` registration pattern
|
|
138
|
-
- **Argument Schemas**: All tools must have complete Zod schemas
|
|
139
|
-
- **Response Format**: Return standardized MCP content blocks
|
|
140
|
-
- **Error Handling**: Use `formatErrorForMcpTool()` for consistent error responses
|
|
141
|
-
|
|
142
|
-
### Testing Requirements
|
|
143
|
-
- **Unit Tests**: Test controllers with mocked service calls
|
|
144
|
-
- **Integration Tests**: Test CLI commands with real dependencies
|
|
145
|
-
- **Tool Tests**: Test MCP tools end-to-end with sample data
|
|
146
|
-
- **Coverage Target**: Maintain >80% test coverage
|
|
147
|
-
|
|
148
|
-
### Quality Gates (PRE-COMMIT MANDATORY)
|
|
149
|
-
```bash
|
|
150
|
-
npm run lint # ESLint must pass with zero errors
|
|
151
|
-
npm run format # Prettier formatting must be applied
|
|
152
|
-
npm run test # All tests must pass
|
|
153
|
-
npm run build # TypeScript compilation must succeed
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
## ENVIRONMENT & CONFIGURATION
|
|
157
|
-
|
|
158
|
-
### Environment Variables
|
|
159
|
-
- `TRANSPORT_MODE`: "stdio" or "http" (default: "http")
|
|
160
|
-
- `PORT`: HTTP server port (default: 3000)
|
|
161
|
-
- `DEBUG`: Enable debug logging (default: false)
|
|
162
|
-
- `IPAPI_API_TOKEN`: Optional API token for ip-api.com
|
|
163
|
-
|
|
164
|
-
### Development Commands
|
|
165
|
-
```bash
|
|
166
|
-
# Development workflow
|
|
167
|
-
npm run build # Build TypeScript
|
|
168
|
-
npm run cli -- get-ip-details # Test CLI directly
|
|
169
|
-
npm run mcp:stdio # Run STDIO transport
|
|
170
|
-
npm run mcp:http # Run HTTP transport
|
|
171
|
-
npm run mcp:inspect # Test with MCP Inspector
|
|
172
|
-
npm run dev:http # Development mode with debug
|
|
173
|
-
|
|
174
|
-
# Quality assurance
|
|
175
|
-
npm run lint # ESLint
|
|
176
|
-
npm run format # Prettier
|
|
177
|
-
npm run test # Jest tests
|
|
178
|
-
npm run test:coverage # Coverage report
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
## SEMANTIC RELEASE PROTOCOL
|
|
182
|
-
|
|
183
|
-
### Conventional Commits (MANDATORY)
|
|
184
|
-
- `feat:` - New features (minor version bump)
|
|
185
|
-
- `fix:` - Bug fixes (patch version bump)
|
|
186
|
-
- `refactor:` - Code refactoring (no version bump)
|
|
187
|
-
- `docs:` - Documentation updates (no version bump)
|
|
188
|
-
- `test:` - Test additions/modifications (no version bump)
|
|
189
|
-
- `chore:` - Build/tooling changes (no version bump)
|
|
190
|
-
|
|
191
|
-
### Breaking Changes
|
|
192
|
-
- Add `BREAKING CHANGE:` in commit body for major version bumps
|
|
193
|
-
- Update CHANGELOG.md automatically via semantic-release
|
|
194
|
-
- Publish to npm registry automatically on main branch
|
|
195
|
-
|
|
196
|
-
## COMMUNICATION PROTOCOLS
|
|
197
|
-
|
|
198
|
-
### GitHub Integration
|
|
199
|
-
- **Issue Analysis**: Read issue completely, understand requirements, propose solution
|
|
200
|
-
- **PR Reviews**: Focus on MCP compliance, TypeScript quality, architecture consistency
|
|
201
|
-
- **Comment Responses**: Implement requested changes with full context awareness
|
|
202
|
-
- **Status Updates**: Use GitHub comments exclusively (console output invisible to users)
|
|
203
|
-
|
|
204
|
-
### Documentation Standards
|
|
205
|
-
- **Tool Descriptions**: Clear, actionable descriptions for each MCP tool
|
|
206
|
-
- **Code Comments**: TypeScript interfaces and complex logic must be documented
|
|
207
|
-
- **README Updates**: Keep usage examples and API documentation current
|
|
208
|
-
- **CHANGELOG**: Automatic via semantic-release for version tracking
|
|
209
|
-
|
|
210
|
-
## EXAMPLE PATTERNS
|
|
211
|
-
|
|
212
|
-
### Complete Tool Implementation
|
|
213
|
-
```typescript
|
|
214
|
-
// 1. Service (src/services/example.service.ts)
|
|
215
|
-
export async function getData(param: string): Promise<ExampleData> {
|
|
216
|
-
const response = await fetch(`https://api.example.com/data/${param}`);
|
|
217
|
-
return response.json();
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// 2. Controller (src/controllers/example.controller.ts)
|
|
221
|
-
export async function getData(options: GetDataOptions): Promise<ControllerResponse> {
|
|
222
|
-
try {
|
|
223
|
-
const data = await exampleService.getData(options.param);
|
|
224
|
-
const content = formatMarkdown(data);
|
|
225
|
-
return { content };
|
|
226
|
-
} catch (error) {
|
|
227
|
-
throw handleControllerError(error, { entityType: 'ExampleData' });
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// 3. Tool (src/tools/example.tool.ts)
|
|
232
|
-
const GetDataArgs = z.object({
|
|
233
|
-
param: z.string().describe('Data parameter')
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
async function handleGetData(args: z.infer<typeof GetDataArgs>) {
|
|
237
|
-
const result = await exampleController.getData(args);
|
|
238
|
-
return { content: [{ type: 'text', text: result.content }] };
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
export function register(server: McpServer) {
|
|
242
|
-
server.tool('get_data', 'Gets data from example API', GetDataArgs.shape, handleGetData);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// 4. CLI (src/cli/example.cli.ts)
|
|
246
|
-
program
|
|
247
|
-
.command('get-data')
|
|
248
|
-
.description('Get example data')
|
|
249
|
-
.option('--param <value>', 'Data parameter')
|
|
250
|
-
.action(async (options) => {
|
|
251
|
-
const result = await exampleController.getData(options);
|
|
252
|
-
console.log(result.content);
|
|
253
|
-
});
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
## SUCCESS METRICS
|
|
257
|
-
|
|
258
|
-
### Technical Excellence
|
|
259
|
-
- Zero TypeScript compilation errors
|
|
260
|
-
- 100% test coverage on critical paths
|
|
261
|
-
- Sub-second MCP tool response times
|
|
262
|
-
- Successful builds across Node.js 18, 20, 22
|
|
263
|
-
|
|
264
|
-
### User Experience
|
|
265
|
-
- Clear, actionable tool descriptions
|
|
266
|
-
- Consistent error messages across all interfaces
|
|
267
|
-
- Comprehensive CLI help documentation
|
|
268
|
-
- Real-time debugging via MCP Inspector
|
|
269
|
-
|
|
270
|
-
### System Reliability
|
|
271
|
-
- Graceful handling of external API failures
|
|
272
|
-
- Proper resource cleanup and memory management
|
|
273
|
-
- Robust error recovery in both transport modes
|
|
274
|
-
- Secure handling of API keys and sensitive data
|
|
275
|
-
|
|
276
|
-
---
|
|
277
|
-
|
|
278
|
-
**REMEMBER**: You are the technical authority for this MCP server. Your decisions on architecture, implementation, and quality standards are final. Build tools that delight developers and integrate seamlessly with AI assistants.
|
|
279
|
-
|
|
280
|
-
**BUILD. TEST. DEPLOY. EXCEL.**
|