@aashari/boilerplate-mcp-server 1.4.8 → 1.5.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/dist/utils/constants.util.d.ts +1 -1
- package/dist/utils/constants.util.js +1 -1
- package/dist/utils/formatter.util.d.ts +8 -0
- package/dist/utils/formatter.util.js +37 -0
- package/dist/utils/pagination.util.d.ts +31 -0
- package/dist/utils/pagination.util.js +124 -0
- package/package.json +4 -4
- package/package.json.bak +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [1.5.0](https://github.com/aashari/boilerplate-mcp-server/compare/v1.4.9...v1.5.0) (2025-05-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **boilerplate:** add standard pagination utils and formatPagination ([cb1e004](https://github.com/aashari/boilerplate-mcp-server/commit/cb1e004fcb33eef61605983b74cf8a373018830b))
|
|
7
|
+
|
|
8
|
+
## [1.4.9](https://github.com/aashari/boilerplate-mcp-server/compare/v1.4.8...v1.4.9) (2025-05-04)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Performance Improvements
|
|
12
|
+
|
|
13
|
+
* Update dependencies ([d5653b8](https://github.com/aashari/boilerplate-mcp-server/commit/d5653b8e31581e3bffe9d5b1d891afd58dee6f3b))
|
|
14
|
+
|
|
1
15
|
## [1.4.8](https://github.com/aashari/boilerplate-mcp-server/compare/v1.4.7...v1.4.8) (2025-05-04)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -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.5.0';
|
|
15
15
|
/**
|
|
16
16
|
* Package name with scope
|
|
17
17
|
* Used for initialization and identification
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Standardized formatting utilities for consistent output across all CLI and Tool interfaces.
|
|
3
3
|
* These functions should be used by all formatters to ensure consistent formatting.
|
|
4
4
|
*/
|
|
5
|
+
import type { ResponsePagination } from './pagination.util.js';
|
|
5
6
|
/**
|
|
6
7
|
* Format a date in a standardized way: YYYY-MM-DD HH:MM:SS UTC
|
|
7
8
|
* @param dateString - ISO date string or Date object
|
|
@@ -34,3 +35,10 @@ export declare function formatBulletList(items: Record<string, unknown>, keyForm
|
|
|
34
35
|
* @returns Separator line
|
|
35
36
|
*/
|
|
36
37
|
export declare function formatSeparator(): string;
|
|
38
|
+
/**
|
|
39
|
+
* Formats the pagination information into a standardized footer string for CLI output.
|
|
40
|
+
*
|
|
41
|
+
* @param {ResponsePagination | undefined} pagination - The standardized pagination object.
|
|
42
|
+
* @returns {string} A formatted string summarizing pagination and next steps, or an empty string if no pagination.
|
|
43
|
+
*/
|
|
44
|
+
export declare function formatPagination(pagination: ResponsePagination | undefined): string;
|
|
@@ -9,6 +9,7 @@ exports.formatUrl = formatUrl;
|
|
|
9
9
|
exports.formatHeading = formatHeading;
|
|
10
10
|
exports.formatBulletList = formatBulletList;
|
|
11
11
|
exports.formatSeparator = formatSeparator;
|
|
12
|
+
exports.formatPagination = formatPagination;
|
|
12
13
|
/**
|
|
13
14
|
* Format a date in a standardized way: YYYY-MM-DD HH:MM:SS UTC
|
|
14
15
|
* @param dateString - ISO date string or Date object
|
|
@@ -114,3 +115,39 @@ function formatValue(value) {
|
|
|
114
115
|
function formatSeparator() {
|
|
115
116
|
return '---';
|
|
116
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Formats the pagination information into a standardized footer string for CLI output.
|
|
120
|
+
*
|
|
121
|
+
* @param {ResponsePagination | undefined} pagination - The standardized pagination object.
|
|
122
|
+
* @returns {string} A formatted string summarizing pagination and next steps, or an empty string if no pagination.
|
|
123
|
+
*/
|
|
124
|
+
function formatPagination(pagination) {
|
|
125
|
+
if (!pagination) {
|
|
126
|
+
return '';
|
|
127
|
+
}
|
|
128
|
+
const { count, hasMore, total, nextCursor, startAt, limit, nextPage, entityType, } = pagination;
|
|
129
|
+
const entity = entityType ? ` ${entityType.toLowerCase()}` : ' items'; // Default to 'items'
|
|
130
|
+
const lines = [formatSeparator()];
|
|
131
|
+
if (total !== undefined && total !== null) {
|
|
132
|
+
lines.push(`*Showing ${count} of ${total}${entity}.*`);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
lines.push(`*Showing ${count}${entity}.*`);
|
|
136
|
+
}
|
|
137
|
+
if (hasMore) {
|
|
138
|
+
lines.push('More results are available.');
|
|
139
|
+
if (nextCursor) {
|
|
140
|
+
lines.push(`*Use --cursor "${nextCursor}" to view more.*`);
|
|
141
|
+
}
|
|
142
|
+
else if (nextPage !== undefined) {
|
|
143
|
+
lines.push(`*Use --page ${nextPage} to view more.*`);
|
|
144
|
+
}
|
|
145
|
+
else if (startAt !== undefined && limit !== undefined) {
|
|
146
|
+
const nextStartAt = startAt + limit;
|
|
147
|
+
lines.push(`*Use --start-at ${nextStartAt} to view more.*`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Add the standard timestamp footer at the very end
|
|
151
|
+
lines.push(`*Information retrieved at: ${formatDate(new Date())}*`);
|
|
152
|
+
return lines.join('\n');
|
|
153
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enum for different pagination types used by APIs.
|
|
3
|
+
*/
|
|
4
|
+
export declare enum PaginationType {
|
|
5
|
+
CURSOR = "CURSOR",// Cursor-based (e.g., Confluence v2)
|
|
6
|
+
OFFSET = "OFFSET",// Offset-based (e.g., Jira)
|
|
7
|
+
PAGE = "PAGE"
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Standardized pagination information returned by controllers.
|
|
11
|
+
*/
|
|
12
|
+
export interface ResponsePagination {
|
|
13
|
+
count: number;
|
|
14
|
+
hasMore: boolean;
|
|
15
|
+
limit?: number;
|
|
16
|
+
startAt?: number;
|
|
17
|
+
total?: number;
|
|
18
|
+
nextCursor?: string;
|
|
19
|
+
nextPage?: number;
|
|
20
|
+
entityType?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Extracts standardized pagination information from various API response formats.
|
|
24
|
+
*
|
|
25
|
+
* @param data - The raw API response data. Expected to contain pagination fields.
|
|
26
|
+
* @param type - The type of pagination the API uses (CURSOR, OFFSET, PAGE).
|
|
27
|
+
* @param entityType - Optional name of the entity being paginated (for messages).
|
|
28
|
+
* @returns A standardized ResponsePagination object, or undefined if no pagination info found.
|
|
29
|
+
*/
|
|
30
|
+
export declare function extractPaginationInfo(data: any, // Using 'any' here as API responses vary greatly
|
|
31
|
+
type: PaginationType, entityType?: string): ResponsePagination | undefined;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PaginationType = void 0;
|
|
4
|
+
exports.extractPaginationInfo = extractPaginationInfo;
|
|
5
|
+
const logger_util_js_1 = require("./logger.util.js");
|
|
6
|
+
const logger = logger_util_js_1.Logger.forContext('utils/pagination.util.ts');
|
|
7
|
+
logger.debug('Pagination utility initialized');
|
|
8
|
+
/**
|
|
9
|
+
* Enum for different pagination types used by APIs.
|
|
10
|
+
*/
|
|
11
|
+
var PaginationType;
|
|
12
|
+
(function (PaginationType) {
|
|
13
|
+
PaginationType["CURSOR"] = "CURSOR";
|
|
14
|
+
PaginationType["OFFSET"] = "OFFSET";
|
|
15
|
+
PaginationType["PAGE"] = "PAGE";
|
|
16
|
+
})(PaginationType || (exports.PaginationType = PaginationType = {}));
|
|
17
|
+
/**
|
|
18
|
+
* Extracts standardized pagination information from various API response formats.
|
|
19
|
+
*
|
|
20
|
+
* @param data - The raw API response data. Expected to contain pagination fields.
|
|
21
|
+
* @param type - The type of pagination the API uses (CURSOR, OFFSET, PAGE).
|
|
22
|
+
* @param entityType - Optional name of the entity being paginated (for messages).
|
|
23
|
+
* @returns A standardized ResponsePagination object, or undefined if no pagination info found.
|
|
24
|
+
*/
|
|
25
|
+
function extractPaginationInfo(
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
data, // Using 'any' here as API responses vary greatly
|
|
28
|
+
type, entityType) {
|
|
29
|
+
if (!data) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
let count = 0;
|
|
33
|
+
let hasMore = false;
|
|
34
|
+
let total = undefined;
|
|
35
|
+
let nextCursor = undefined;
|
|
36
|
+
let nextPage = undefined;
|
|
37
|
+
let startAt = undefined;
|
|
38
|
+
let limit = undefined;
|
|
39
|
+
// Common count extraction
|
|
40
|
+
if (Array.isArray(data.results)) {
|
|
41
|
+
count = data.results.length;
|
|
42
|
+
}
|
|
43
|
+
else if (Array.isArray(data.values)) {
|
|
44
|
+
count = data.values.length;
|
|
45
|
+
}
|
|
46
|
+
else if (Array.isArray(data.issues)) {
|
|
47
|
+
count = data.issues.length;
|
|
48
|
+
}
|
|
49
|
+
else if (Array.isArray(data)) {
|
|
50
|
+
// Handle cases where the response is just an array (e.g., global statuses)
|
|
51
|
+
count = data.length;
|
|
52
|
+
// Assume no more pages if the response is just an array without metadata
|
|
53
|
+
hasMore = false;
|
|
54
|
+
return { count, hasMore, entityType };
|
|
55
|
+
}
|
|
56
|
+
switch (type) {
|
|
57
|
+
case PaginationType.CURSOR:
|
|
58
|
+
// Confluence v2 style (_links.next)
|
|
59
|
+
if (data._links?.next) {
|
|
60
|
+
hasMore = true;
|
|
61
|
+
// Extract cursor from the 'next' link query parameters
|
|
62
|
+
try {
|
|
63
|
+
const nextUrl = new URL(data._links.next, 'http://dummy.base');
|
|
64
|
+
nextCursor =
|
|
65
|
+
nextUrl.searchParams.get('cursor') || undefined;
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
logger.warn('Failed to parse next link URL for cursor:', e);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Limit might be present in the main response or derivable
|
|
72
|
+
limit = data.limit || data.size || count; // Use count as fallback limit if not explicit
|
|
73
|
+
break;
|
|
74
|
+
case PaginationType.OFFSET:
|
|
75
|
+
// Jira style (startAt, maxResults, total, isLast)
|
|
76
|
+
startAt = data.startAt ?? 0;
|
|
77
|
+
limit = data.maxResults;
|
|
78
|
+
total = data.total;
|
|
79
|
+
hasMore = data.isLast === false;
|
|
80
|
+
// Calculate next startAt if possible
|
|
81
|
+
if (hasMore && limit !== undefined) {
|
|
82
|
+
// Keep startAt as is, formatter will calculate next step
|
|
83
|
+
}
|
|
84
|
+
break;
|
|
85
|
+
case PaginationType.PAGE:
|
|
86
|
+
// Bitbucket style (page, pagelen, size, next)
|
|
87
|
+
limit = data.pagelen;
|
|
88
|
+
total = data.size; // Bitbucket uses 'size' for total
|
|
89
|
+
hasMore = !!data.next;
|
|
90
|
+
if (hasMore) {
|
|
91
|
+
// Try to parse the page number from the next URL
|
|
92
|
+
try {
|
|
93
|
+
const nextUrl = new URL(data.next);
|
|
94
|
+
nextPage = parseInt(nextUrl.searchParams.get('page') || '', 10);
|
|
95
|
+
if (isNaN(nextPage)) {
|
|
96
|
+
nextPage = (data.page || 1) + 1; // Fallback calculation
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
logger.warn('Failed to parse next link URL for page:', e);
|
|
101
|
+
nextPage = (data.page || 1) + 1; // Fallback calculation
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
default:
|
|
106
|
+
logger.warn('Unknown pagination type provided:', type);
|
|
107
|
+
return undefined; // Unknown type
|
|
108
|
+
}
|
|
109
|
+
// If count is zero and there's no indication of more pages, return undefined
|
|
110
|
+
if (count === 0 && !hasMore && total === 0) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
// Return standardized pagination object
|
|
114
|
+
return {
|
|
115
|
+
count,
|
|
116
|
+
hasMore,
|
|
117
|
+
limit,
|
|
118
|
+
startAt,
|
|
119
|
+
total,
|
|
120
|
+
nextCursor,
|
|
121
|
+
nextPage,
|
|
122
|
+
entityType,
|
|
123
|
+
};
|
|
124
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aashari/boilerplate-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "TypeScript Model Context Protocol (MCP) server boilerplate providing IP lookup tools/resources. Includes CLI support and extensible structure for connecting AI systems (LLMs) to external data sources like ip-api.com. Ideal template for creating new MCP integrations via Node.js.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"author": "",
|
|
54
54
|
"license": "ISC",
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@eslint/js": "^9.
|
|
56
|
+
"@eslint/js": "^9.26.0",
|
|
57
57
|
"@semantic-release/changelog": "^6.0.3",
|
|
58
58
|
"@semantic-release/exec": "^7.0.3",
|
|
59
59
|
"@semantic-release/git": "^10.0.1",
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
"@types/node": "^22.15.3",
|
|
64
64
|
"@typescript-eslint/eslint-plugin": "^8.31.1",
|
|
65
65
|
"@typescript-eslint/parser": "^8.31.1",
|
|
66
|
-
"eslint": "^9.
|
|
66
|
+
"eslint": "^9.26.0",
|
|
67
67
|
"eslint-config-prettier": "^10.1.2",
|
|
68
|
-
"eslint-plugin-prettier": "^5.
|
|
68
|
+
"eslint-plugin-prettier": "^5.3.1",
|
|
69
69
|
"jest": "^29.7.0",
|
|
70
70
|
"nodemon": "^3.1.10",
|
|
71
71
|
"npm-check-updates": "^18.0.1",
|
package/package.json.bak
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aashari/boilerplate-mcp-server",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.9",
|
|
4
4
|
"description": "TypeScript Model Context Protocol (MCP) server boilerplate providing IP lookup tools/resources. Includes CLI support and extensible structure for connecting AI systems (LLMs) to external data sources like ip-api.com. Ideal template for creating new MCP integrations via Node.js.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"author": "",
|
|
54
54
|
"license": "ISC",
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@eslint/js": "^9.
|
|
56
|
+
"@eslint/js": "^9.26.0",
|
|
57
57
|
"@semantic-release/changelog": "^6.0.3",
|
|
58
58
|
"@semantic-release/exec": "^7.0.3",
|
|
59
59
|
"@semantic-release/git": "^10.0.1",
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
"@types/node": "^22.15.3",
|
|
64
64
|
"@typescript-eslint/eslint-plugin": "^8.31.1",
|
|
65
65
|
"@typescript-eslint/parser": "^8.31.1",
|
|
66
|
-
"eslint": "^9.
|
|
66
|
+
"eslint": "^9.26.0",
|
|
67
67
|
"eslint-config-prettier": "^10.1.2",
|
|
68
|
-
"eslint-plugin-prettier": "^5.
|
|
68
|
+
"eslint-plugin-prettier": "^5.3.1",
|
|
69
69
|
"jest": "^29.7.0",
|
|
70
70
|
"nodemon": "^3.1.10",
|
|
71
71
|
"npm-check-updates": "^18.0.1",
|