motionmcp 1.0.2 → 2.1.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/LICENSE +202 -0
- package/README.md +241 -450
- package/dist/handlers/CommentHandler.d.ts +9 -0
- package/dist/handlers/CommentHandler.d.ts.map +1 -0
- package/dist/handlers/CommentHandler.js +66 -0
- package/dist/handlers/CommentHandler.js.map +1 -0
- package/dist/handlers/CustomFieldHandler.d.ts +14 -0
- package/dist/handlers/CustomFieldHandler.d.ts.map +1 -0
- package/dist/handlers/CustomFieldHandler.js +95 -0
- package/dist/handlers/CustomFieldHandler.js.map +1 -0
- package/dist/handlers/HandlerFactory.d.ts +15 -0
- package/dist/handlers/HandlerFactory.d.ts.map +1 -0
- package/dist/handlers/HandlerFactory.js +58 -0
- package/dist/handlers/HandlerFactory.js.map +1 -0
- package/dist/handlers/ProjectHandler.d.ts +10 -0
- package/dist/handlers/ProjectHandler.d.ts.map +1 -0
- package/dist/handlers/ProjectHandler.js +63 -0
- package/dist/handlers/ProjectHandler.js.map +1 -0
- package/dist/handlers/RecurringTaskHandler.d.ts +10 -0
- package/dist/handlers/RecurringTaskHandler.d.ts.map +1 -0
- package/dist/handlers/RecurringTaskHandler.js +68 -0
- package/dist/handlers/RecurringTaskHandler.js.map +1 -0
- package/dist/handlers/ScheduleHandler.d.ts +8 -0
- package/dist/handlers/ScheduleHandler.d.ts.map +1 -0
- package/dist/handlers/ScheduleHandler.js +43 -0
- package/dist/handlers/ScheduleHandler.js.map +1 -0
- package/dist/handlers/SearchHandler.d.ts +10 -0
- package/dist/handlers/SearchHandler.d.ts.map +1 -0
- package/dist/handlers/SearchHandler.js +116 -0
- package/dist/handlers/SearchHandler.js.map +1 -0
- package/dist/handlers/StatusHandler.d.ts +8 -0
- package/dist/handlers/StatusHandler.d.ts.map +1 -0
- package/dist/handlers/StatusHandler.js +22 -0
- package/dist/handlers/StatusHandler.js.map +1 -0
- package/dist/handlers/TaskHandler.d.ts +22 -0
- package/dist/handlers/TaskHandler.d.ts.map +1 -0
- package/dist/handlers/TaskHandler.js +324 -0
- package/dist/handlers/TaskHandler.js.map +1 -0
- package/dist/handlers/UserHandler.d.ts +9 -0
- package/dist/handlers/UserHandler.d.ts.map +1 -0
- package/dist/handlers/UserHandler.js +36 -0
- package/dist/handlers/UserHandler.js.map +1 -0
- package/dist/handlers/WorkspaceHandler.d.ts +10 -0
- package/dist/handlers/WorkspaceHandler.d.ts.map +1 -0
- package/dist/handlers/WorkspaceHandler.js +49 -0
- package/dist/handlers/WorkspaceHandler.js.map +1 -0
- package/dist/handlers/base/BaseHandler.d.ts +16 -0
- package/dist/handlers/base/BaseHandler.d.ts.map +1 -0
- package/dist/handlers/base/BaseHandler.js +31 -0
- package/dist/handlers/base/BaseHandler.js.map +1 -0
- package/dist/handlers/base/HandlerInterface.d.ts +18 -0
- package/dist/handlers/base/HandlerInterface.d.ts.map +1 -0
- package/dist/handlers/base/HandlerInterface.js +3 -0
- package/dist/handlers/base/HandlerInterface.js.map +1 -0
- package/dist/handlers/index.d.ts +14 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +31 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/mcp-server.d.ts +15 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +145 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/schemas/motion.d.ts +4971 -0
- package/dist/schemas/motion.d.ts.map +1 -0
- package/dist/schemas/motion.js +328 -0
- package/dist/schemas/motion.js.map +1 -0
- package/dist/services/motionApi.d.ts +199 -0
- package/dist/services/motionApi.d.ts.map +1 -0
- package/dist/services/motionApi.js +1950 -0
- package/dist/services/motionApi.js.map +1 -0
- package/dist/tools/ToolConfigurator.d.ts +19 -0
- package/dist/tools/ToolConfigurator.d.ts.map +1 -0
- package/dist/tools/ToolConfigurator.js +89 -0
- package/dist/tools/ToolConfigurator.js.map +1 -0
- package/dist/tools/ToolDefinitions.d.ts +25 -0
- package/dist/tools/ToolDefinitions.d.ts.map +1 -0
- package/dist/tools/ToolDefinitions.js +508 -0
- package/dist/tools/ToolDefinitions.js.map +1 -0
- package/dist/tools/ToolRegistry.d.ts +16 -0
- package/dist/tools/ToolRegistry.d.ts.map +1 -0
- package/dist/tools/ToolRegistry.js +89 -0
- package/dist/tools/ToolRegistry.js.map +1 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +21 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types/mcp-tool-args.d.ts +123 -0
- package/dist/types/mcp-tool-args.d.ts.map +1 -0
- package/dist/types/mcp-tool-args.js +7 -0
- package/dist/types/mcp-tool-args.js.map +1 -0
- package/dist/types/mcp.d.ts +32 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +3 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/motion.d.ts +304 -0
- package/dist/types/motion.d.ts.map +1 -0
- package/dist/types/motion.js +3 -0
- package/dist/types/motion.js.map +1 -0
- package/dist/utils/cache.d.ts +25 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +135 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/constants.d.ts +88 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +188 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/errorHandling.d.ts +50 -0
- package/dist/utils/errorHandling.d.ts.map +1 -0
- package/dist/utils/errorHandling.js +86 -0
- package/dist/utils/errorHandling.js.map +1 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +38 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +47 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/pagination.d.ts +61 -0
- package/dist/utils/pagination.d.ts.map +1 -0
- package/dist/utils/pagination.js +168 -0
- package/dist/utils/pagination.js.map +1 -0
- package/dist/utils/paginationNew.d.ts +44 -0
- package/dist/utils/paginationNew.d.ts.map +1 -0
- package/dist/utils/paginationNew.js +149 -0
- package/dist/utils/paginationNew.js.map +1 -0
- package/dist/utils/parameterUtils.d.ts +79 -0
- package/dist/utils/parameterUtils.d.ts.map +1 -0
- package/dist/utils/parameterUtils.js +189 -0
- package/dist/utils/parameterUtils.js.map +1 -0
- package/dist/utils/responseFormatters.d.ts +95 -0
- package/dist/utils/responseFormatters.d.ts.map +1 -0
- package/dist/utils/responseFormatters.js +342 -0
- package/dist/utils/responseFormatters.js.map +1 -0
- package/dist/utils/responseWrapper.d.ts +38 -0
- package/dist/utils/responseWrapper.d.ts.map +1 -0
- package/dist/utils/responseWrapper.js +201 -0
- package/dist/utils/responseWrapper.js.map +1 -0
- package/dist/utils/sanitize.d.ts +51 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +138 -0
- package/dist/utils/sanitize.js.map +1 -0
- package/dist/utils/validator.d.ts +37 -0
- package/dist/utils/validator.d.ts.map +1 -0
- package/dist/utils/validator.js +74 -0
- package/dist/utils/validator.js.map +1 -0
- package/dist/utils/workspaceResolver.d.ts +40 -0
- package/dist/utils/workspaceResolver.d.ts.map +1 -0
- package/dist/utils/workspaceResolver.js +207 -0
- package/dist/utils/workspaceResolver.js.map +1 -0
- package/package.json +41 -17
- package/.claude/settings.local.json +0 -15
- package/.env.example +0 -3
- package/sample.png +0 -0
- package/src/index.js +0 -179
- package/src/mcp-server.js +0 -1137
- package/src/routes/motion.js +0 -152
- package/src/services/motionApi.js +0 -1177
- package/src/worker.js +0 -248
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Centralized MCP-compliant logger
|
|
4
|
+
* Outputs structured JSON logs to stderr as required by MCP protocol
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.mcpLog = void 0;
|
|
8
|
+
const SENSITIVE_FIELDS = ['apiKey', 'password', 'token', 'secret', 'authorization'];
|
|
9
|
+
/**
|
|
10
|
+
* Sanitizes sensitive information from log data
|
|
11
|
+
*/
|
|
12
|
+
function sanitizeLogData(data) {
|
|
13
|
+
const sanitized = {};
|
|
14
|
+
for (const [key, value] of Object.entries(data)) {
|
|
15
|
+
// Check if key contains sensitive field names
|
|
16
|
+
if (SENSITIVE_FIELDS.some(field => key.toLowerCase().includes(field))) {
|
|
17
|
+
sanitized[key] = '[REDACTED]';
|
|
18
|
+
}
|
|
19
|
+
else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
20
|
+
// Recursively sanitize nested objects
|
|
21
|
+
sanitized[key] = sanitizeLogData(value);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
sanitized[key] = value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return sanitized;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* MCP-compliant logger that outputs to stderr in JSON format
|
|
31
|
+
* @param level - Log level (ERROR, WARN, INFO, DEBUG)
|
|
32
|
+
* @param message - Log message
|
|
33
|
+
* @param extra - Additional context data
|
|
34
|
+
*/
|
|
35
|
+
const mcpLog = (level, message, extra = {}) => {
|
|
36
|
+
const sanitizedExtra = sanitizeLogData(extra);
|
|
37
|
+
const logEntry = {
|
|
38
|
+
level,
|
|
39
|
+
msg: message,
|
|
40
|
+
time: new Date().toISOString(),
|
|
41
|
+
...sanitizedExtra
|
|
42
|
+
};
|
|
43
|
+
// MCP servers should log to stderr in JSON format
|
|
44
|
+
console.error(JSON.stringify(logEntry));
|
|
45
|
+
};
|
|
46
|
+
exports.mcpLog = mcpLog;
|
|
47
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;AAEpF;;GAEG;AACH,SAAS,eAAe,CAAC,IAAyB;IAChD,MAAM,SAAS,GAAwB,EAAE,CAAC;IAE1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,8CAA8C;QAC9C,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACtE,SAAS,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;QAChC,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAChF,sCAAsC;YACtC,SAAS,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACI,MAAM,MAAM,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,QAA6B,EAAE,EAAQ,EAAE;IAChG,MAAM,cAAc,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAE9C,MAAM,QAAQ,GAAG;QACf,KAAK;QACL,GAAG,EAAE,OAAO;QACZ,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC9B,GAAG,cAAc;KAClB,CAAC;IAEF,kDAAkD;IAClD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC1C,CAAC,CAAC;AAZW,QAAA,MAAM,UAYjB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pagination Utilities - Shared pagination logic for Motion API calls
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities to handle cursor-based and offset-based pagination
|
|
5
|
+
* consistently across all API endpoints.
|
|
6
|
+
*/
|
|
7
|
+
import { AxiosResponse } from 'axios';
|
|
8
|
+
export interface PaginatedResponse<T> {
|
|
9
|
+
items: T[];
|
|
10
|
+
nextCursor?: string;
|
|
11
|
+
hasMore: boolean;
|
|
12
|
+
totalFetched: number;
|
|
13
|
+
}
|
|
14
|
+
export interface PaginationMeta {
|
|
15
|
+
nextCursor?: string;
|
|
16
|
+
hasMore?: boolean;
|
|
17
|
+
total?: number;
|
|
18
|
+
page?: number;
|
|
19
|
+
limit?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface CursorPaginationOptions {
|
|
22
|
+
maxPages?: number;
|
|
23
|
+
pageSize?: number;
|
|
24
|
+
logProgress?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface PaginatedApiResponse<T> {
|
|
27
|
+
meta?: PaginationMeta;
|
|
28
|
+
items?: T[];
|
|
29
|
+
tasks?: T[];
|
|
30
|
+
projects?: T[];
|
|
31
|
+
users?: T[];
|
|
32
|
+
comments?: T[];
|
|
33
|
+
customFields?: T[];
|
|
34
|
+
recurringTasks?: T[];
|
|
35
|
+
schedules?: T[];
|
|
36
|
+
statuses?: T[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Generic cursor-based pagination handler
|
|
40
|
+
* Automatically fetches all pages or up to maxPages limit
|
|
41
|
+
*/
|
|
42
|
+
export declare function fetchAllPages<T>(fetchPage: (cursor?: string) => Promise<AxiosResponse<PaginatedApiResponse<T>>>, options?: CursorPaginationOptions): Promise<PaginatedResponse<T>>;
|
|
43
|
+
/**
|
|
44
|
+
* Simple pagination for APIs that might not have explicit pagination
|
|
45
|
+
* but could benefit from batching large requests
|
|
46
|
+
*/
|
|
47
|
+
export interface BatchOptions {
|
|
48
|
+
batchSize?: number;
|
|
49
|
+
maxBatches?: number;
|
|
50
|
+
delayMs?: number;
|
|
51
|
+
}
|
|
52
|
+
export declare function fetchInBatches<T, TParams>(fetchBatch: (params: TParams, offset: number, limit: number) => Promise<T[]>, params: TParams, options?: BatchOptions): Promise<T[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Check if a response indicates more pages are available
|
|
55
|
+
*/
|
|
56
|
+
export declare function hasMorePages<T>(response: PaginatedApiResponse<T>): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Get pagination info from response
|
|
59
|
+
*/
|
|
60
|
+
export declare function getPaginationInfo<T>(response: PaginatedApiResponse<T>): PaginationMeta | null;
|
|
61
|
+
//# sourceMappingURL=pagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/utils/pagination.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAItC,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;IACZ,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;IACZ,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;IACZ,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC;IACnB,cAAc,CAAC,EAAE,CAAC,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,EAC/E,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAqF/B;AAyBD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,cAAc,CAAC,CAAC,EAAE,OAAO,EAC7C,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,EAC5E,MAAM,EAAE,OAAO,EACf,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,CAAC,EAAE,CAAC,CAuCd;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,OAAO,CAE1E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,QAAQ,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,cAAc,GAAG,IAAI,CAE7F"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pagination Utilities - Shared pagination logic for Motion API calls
|
|
4
|
+
*
|
|
5
|
+
* Provides utilities to handle cursor-based and offset-based pagination
|
|
6
|
+
* consistently across all API endpoints.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.fetchAllPages = fetchAllPages;
|
|
10
|
+
exports.fetchInBatches = fetchInBatches;
|
|
11
|
+
exports.hasMorePages = hasMorePages;
|
|
12
|
+
exports.getPaginationInfo = getPaginationInfo;
|
|
13
|
+
const logger_1 = require("./logger");
|
|
14
|
+
const constants_1 = require("./constants");
|
|
15
|
+
/**
|
|
16
|
+
* Generic cursor-based pagination handler
|
|
17
|
+
* Automatically fetches all pages or up to maxPages limit
|
|
18
|
+
*/
|
|
19
|
+
async function fetchAllPages(fetchPage, options = {}) {
|
|
20
|
+
const { maxPages = 10, logProgress = true } = options;
|
|
21
|
+
let allItems = [];
|
|
22
|
+
let cursor;
|
|
23
|
+
let pageCount = 0;
|
|
24
|
+
let hasMore = true;
|
|
25
|
+
// Infinite loop protection - ensure we never fetch more than absolute max pages
|
|
26
|
+
const absoluteMaxPages = Math.min(maxPages, 50); // Hard limit to prevent infinite loops
|
|
27
|
+
while (hasMore && pageCount < absoluteMaxPages) {
|
|
28
|
+
try {
|
|
29
|
+
if (logProgress && pageCount > 0) {
|
|
30
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.DEBUG, `Fetching page ${pageCount + 1}`, { cursor });
|
|
31
|
+
}
|
|
32
|
+
const response = await fetchPage(cursor);
|
|
33
|
+
const data = response.data;
|
|
34
|
+
// Extract items from various possible response structures
|
|
35
|
+
const pageItems = extractItemsFromResponse(data);
|
|
36
|
+
// Enforce page size limit to prevent memory exhaustion
|
|
37
|
+
if (pageItems.length > constants_1.LIMITS.MAX_PAGE_SIZE) {
|
|
38
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, `Page size ${pageItems.length} exceeds maximum allowed ${constants_1.LIMITS.MAX_PAGE_SIZE}, truncating`, {
|
|
39
|
+
pageNumber: pageCount + 1,
|
|
40
|
+
originalSize: pageItems.length,
|
|
41
|
+
truncatedSize: constants_1.LIMITS.MAX_PAGE_SIZE
|
|
42
|
+
});
|
|
43
|
+
pageItems.splice(constants_1.LIMITS.MAX_PAGE_SIZE); // Truncate to limit
|
|
44
|
+
}
|
|
45
|
+
allItems = allItems.concat(pageItems);
|
|
46
|
+
// Update pagination state
|
|
47
|
+
const newCursor = data.meta?.nextCursor;
|
|
48
|
+
// Infinite loop protection: If cursor doesn't change, break
|
|
49
|
+
if (cursor && newCursor === cursor) {
|
|
50
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, 'Pagination cursor not advancing - breaking to prevent infinite loop', {
|
|
51
|
+
cursor,
|
|
52
|
+
pageCount,
|
|
53
|
+
itemsCount: pageItems.length
|
|
54
|
+
});
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
cursor = newCursor;
|
|
58
|
+
hasMore = !!cursor && pageItems.length > 0;
|
|
59
|
+
pageCount++;
|
|
60
|
+
if (logProgress) {
|
|
61
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.DEBUG, `Page ${pageCount} fetched`, {
|
|
62
|
+
pageItems: pageItems.length,
|
|
63
|
+
totalItems: allItems.length,
|
|
64
|
+
hasMore,
|
|
65
|
+
nextCursor: cursor
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.ERROR, `Pagination failed on page ${pageCount + 1}`, {
|
|
71
|
+
error: error instanceof Error ? error.message : String(error),
|
|
72
|
+
cursor
|
|
73
|
+
});
|
|
74
|
+
// Return what we have so far
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (pageCount >= absoluteMaxPages && hasMore) {
|
|
79
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, `Reached maximum page limit (${absoluteMaxPages})`, {
|
|
80
|
+
totalFetched: allItems.length,
|
|
81
|
+
finalCursor: cursor
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
items: allItems,
|
|
86
|
+
nextCursor: cursor,
|
|
87
|
+
hasMore,
|
|
88
|
+
totalFetched: allItems.length
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Extract items from various API response structures
|
|
93
|
+
* Handles the different ways Motion API can structure responses
|
|
94
|
+
*/
|
|
95
|
+
function extractItemsFromResponse(data) {
|
|
96
|
+
// Try different possible array locations
|
|
97
|
+
if (data.tasks && Array.isArray(data.tasks))
|
|
98
|
+
return data.tasks;
|
|
99
|
+
if (data.projects && Array.isArray(data.projects))
|
|
100
|
+
return data.projects;
|
|
101
|
+
if (data.users && Array.isArray(data.users))
|
|
102
|
+
return data.users;
|
|
103
|
+
if (data.comments && Array.isArray(data.comments))
|
|
104
|
+
return data.comments;
|
|
105
|
+
if (data.customFields && Array.isArray(data.customFields))
|
|
106
|
+
return data.customFields;
|
|
107
|
+
if (data.recurringTasks && Array.isArray(data.recurringTasks))
|
|
108
|
+
return data.recurringTasks;
|
|
109
|
+
if (data.schedules && Array.isArray(data.schedules))
|
|
110
|
+
return data.schedules;
|
|
111
|
+
if (data.statuses && Array.isArray(data.statuses))
|
|
112
|
+
return data.statuses;
|
|
113
|
+
if (data.items && Array.isArray(data.items))
|
|
114
|
+
return data.items;
|
|
115
|
+
// Fallback: if data itself is an array
|
|
116
|
+
if (Array.isArray(data))
|
|
117
|
+
return data;
|
|
118
|
+
// No items found
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
async function fetchInBatches(fetchBatch, params, options = {}) {
|
|
122
|
+
const { batchSize = 100, maxBatches = 10, delayMs = 100 } = options;
|
|
123
|
+
let allItems = [];
|
|
124
|
+
let offset = 0;
|
|
125
|
+
let batchCount = 0;
|
|
126
|
+
let hasMore = true;
|
|
127
|
+
while (hasMore && batchCount < maxBatches) {
|
|
128
|
+
try {
|
|
129
|
+
const batchItems = await fetchBatch(params, offset, batchSize);
|
|
130
|
+
if (batchItems.length === 0) {
|
|
131
|
+
hasMore = false;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
allItems = allItems.concat(batchItems);
|
|
135
|
+
offset += batchSize;
|
|
136
|
+
batchCount++;
|
|
137
|
+
// Small delay to be API-friendly
|
|
138
|
+
if (delayMs > 0 && hasMore) {
|
|
139
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
140
|
+
}
|
|
141
|
+
// If we got fewer items than batch size, we've reached the end
|
|
142
|
+
if (batchItems.length < batchSize) {
|
|
143
|
+
hasMore = false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.ERROR, `Batch fetch failed at offset ${offset}`, {
|
|
149
|
+
error: error instanceof Error ? error.message : String(error)
|
|
150
|
+
});
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return allItems;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Check if a response indicates more pages are available
|
|
158
|
+
*/
|
|
159
|
+
function hasMorePages(response) {
|
|
160
|
+
return !!(response.meta?.nextCursor || response.meta?.hasMore);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get pagination info from response
|
|
164
|
+
*/
|
|
165
|
+
function getPaginationInfo(response) {
|
|
166
|
+
return response.meta || null;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=pagination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/utils/pagination.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Pagination Utilities with Proper Response Wrapper Support
|
|
3
|
+
*
|
|
4
|
+
* This replaces the old pagination utility with proper handling of Motion API's
|
|
5
|
+
* inconsistent response patterns using the ResponseWrapper utility.
|
|
6
|
+
*/
|
|
7
|
+
import { AxiosResponse } from 'axios';
|
|
8
|
+
import { UnwrappedResponse } from './responseWrapper';
|
|
9
|
+
export interface PaginatedResponse<T> {
|
|
10
|
+
items: T[];
|
|
11
|
+
nextCursor?: string;
|
|
12
|
+
hasMore: boolean;
|
|
13
|
+
totalFetched: number;
|
|
14
|
+
}
|
|
15
|
+
export interface CursorPaginationOptions {
|
|
16
|
+
maxPages?: number;
|
|
17
|
+
pageSize?: number;
|
|
18
|
+
logProgress?: boolean;
|
|
19
|
+
maxItems?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Enhanced pagination handler that properly uses response wrapper
|
|
23
|
+
*
|
|
24
|
+
* @param fetchPage - Function that fetches a single page of data
|
|
25
|
+
* @param apiEndpoint - The API endpoint name for proper response unwrapping
|
|
26
|
+
* @param options - Pagination options
|
|
27
|
+
* @returns All items from all pages with pagination metadata
|
|
28
|
+
*/
|
|
29
|
+
export declare function fetchAllPages<T>(fetchPage: (cursor?: string) => Promise<AxiosResponse<any>>, apiEndpoint: string, options?: CursorPaginationOptions): Promise<PaginatedResponse<T>>;
|
|
30
|
+
/**
|
|
31
|
+
* Fetches a single page with proper response unwrapping
|
|
32
|
+
*
|
|
33
|
+
* @param fetchPage - Function that fetches a single page
|
|
34
|
+
* @param apiEndpoint - The API endpoint name for proper response unwrapping
|
|
35
|
+
* @param cursor - Optional cursor for the specific page
|
|
36
|
+
* @returns Single page of data with pagination metadata
|
|
37
|
+
*/
|
|
38
|
+
export declare function fetchSinglePage<T>(fetchPage: (cursor?: string) => Promise<AxiosResponse<any>>, apiEndpoint: string, cursor?: string): Promise<UnwrappedResponse<T>>;
|
|
39
|
+
/**
|
|
40
|
+
* Check if an endpoint supports pagination
|
|
41
|
+
*/
|
|
42
|
+
export declare function endpointSupportsPagination(apiEndpoint: string): boolean;
|
|
43
|
+
export { UnwrappedResponse } from './responseWrapper';
|
|
44
|
+
//# sourceMappingURL=paginationNew.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginationNew.d.ts","sourceRoot":"","sources":["../../src/utils/paginationNew.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAyC,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAG7F,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,EAC3D,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAuH/B;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,EAC3D,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAG/B;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAEvE;AAGD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Enhanced Pagination Utilities with Proper Response Wrapper Support
|
|
4
|
+
*
|
|
5
|
+
* This replaces the old pagination utility with proper handling of Motion API's
|
|
6
|
+
* inconsistent response patterns using the ResponseWrapper utility.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.fetchAllPages = fetchAllPages;
|
|
10
|
+
exports.fetchSinglePage = fetchSinglePage;
|
|
11
|
+
exports.endpointSupportsPagination = endpointSupportsPagination;
|
|
12
|
+
const logger_1 = require("./logger");
|
|
13
|
+
const constants_1 = require("./constants");
|
|
14
|
+
const responseWrapper_1 = require("./responseWrapper");
|
|
15
|
+
/**
|
|
16
|
+
* Enhanced pagination handler that properly uses response wrapper
|
|
17
|
+
*
|
|
18
|
+
* @param fetchPage - Function that fetches a single page of data
|
|
19
|
+
* @param apiEndpoint - The API endpoint name for proper response unwrapping
|
|
20
|
+
* @param options - Pagination options
|
|
21
|
+
* @returns All items from all pages with pagination metadata
|
|
22
|
+
*/
|
|
23
|
+
async function fetchAllPages(fetchPage, apiEndpoint, options = {}) {
|
|
24
|
+
const { maxPages = constants_1.LIMITS.MAX_PAGES, logProgress = true, maxItems = constants_1.LIMITS.MAX_PAGE_SIZE * 10 } = options;
|
|
25
|
+
let allItems = [];
|
|
26
|
+
let cursor;
|
|
27
|
+
let pageCount = 0;
|
|
28
|
+
let hasMore = true;
|
|
29
|
+
// Infinite loop protection - ensure we never fetch more than absolute max pages
|
|
30
|
+
const absoluteMaxPages = Math.min(maxPages, constants_1.LIMITS.ABSOLUTE_MAX_PAGES); // Hard limit to prevent infinite loops
|
|
31
|
+
while (hasMore && pageCount < absoluteMaxPages) {
|
|
32
|
+
try {
|
|
33
|
+
if (logProgress && pageCount > 0) {
|
|
34
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.DEBUG, `Fetching page ${pageCount + 1} for ${apiEndpoint}`, {
|
|
35
|
+
cursor,
|
|
36
|
+
pageCount,
|
|
37
|
+
itemsSoFar: allItems.length
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const response = await fetchPage(cursor);
|
|
41
|
+
const unwrapped = (0, responseWrapper_1.unwrapApiResponse)(response.data, apiEndpoint);
|
|
42
|
+
// Enforce page size limit to prevent memory exhaustion
|
|
43
|
+
if (unwrapped.data.length > constants_1.LIMITS.MAX_PAGE_SIZE) {
|
|
44
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, `Page size ${unwrapped.data.length} exceeds maximum allowed ${constants_1.LIMITS.MAX_PAGE_SIZE}, truncating`, {
|
|
45
|
+
pageNumber: pageCount + 1,
|
|
46
|
+
endpoint: apiEndpoint,
|
|
47
|
+
originalSize: unwrapped.data.length,
|
|
48
|
+
truncatedSize: constants_1.LIMITS.MAX_PAGE_SIZE
|
|
49
|
+
});
|
|
50
|
+
unwrapped.data = unwrapped.data.slice(0, constants_1.LIMITS.MAX_PAGE_SIZE);
|
|
51
|
+
}
|
|
52
|
+
// Add items to our collection, but check memory limits first
|
|
53
|
+
const itemsToAdd = unwrapped.data;
|
|
54
|
+
if (allItems.length + itemsToAdd.length > maxItems) {
|
|
55
|
+
// Limit reached - add only what fits
|
|
56
|
+
const remainingSlots = maxItems - allItems.length;
|
|
57
|
+
if (remainingSlots > 0) {
|
|
58
|
+
allItems.push(...itemsToAdd.slice(0, remainingSlots));
|
|
59
|
+
}
|
|
60
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, `Memory limit reached for ${apiEndpoint}, stopping pagination`, {
|
|
61
|
+
totalItems: allItems.length,
|
|
62
|
+
maxItems,
|
|
63
|
+
pageCount: pageCount + 1,
|
|
64
|
+
endpoint: apiEndpoint
|
|
65
|
+
});
|
|
66
|
+
hasMore = false;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
allItems.push(...itemsToAdd);
|
|
70
|
+
}
|
|
71
|
+
pageCount++;
|
|
72
|
+
// Determine if there are more pages
|
|
73
|
+
if (unwrapped.meta?.nextCursor) {
|
|
74
|
+
const newCursor = unwrapped.meta.nextCursor;
|
|
75
|
+
// Additional safety: detect cursor not advancing (API bug protection)
|
|
76
|
+
if (pageCount > 1 && cursor === newCursor) {
|
|
77
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, `Cursor not advancing for ${apiEndpoint}, stopping pagination`, {
|
|
78
|
+
oldCursor: cursor,
|
|
79
|
+
newCursor,
|
|
80
|
+
pageCount,
|
|
81
|
+
endpoint: apiEndpoint
|
|
82
|
+
});
|
|
83
|
+
hasMore = false;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
cursor = newCursor;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
hasMore = false;
|
|
91
|
+
}
|
|
92
|
+
// If we got no items on this page, stop
|
|
93
|
+
if (unwrapped.data.length === 0) {
|
|
94
|
+
hasMore = false;
|
|
95
|
+
}
|
|
96
|
+
if (logProgress) {
|
|
97
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.DEBUG, `Page ${pageCount} fetched for ${apiEndpoint}`, {
|
|
98
|
+
pageItems: unwrapped.data.length,
|
|
99
|
+
totalItems: allItems.length,
|
|
100
|
+
hasMore,
|
|
101
|
+
nextCursor: cursor,
|
|
102
|
+
endpoint: apiEndpoint
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.ERROR, `Failed to fetch page ${pageCount + 1} for ${apiEndpoint}`, {
|
|
108
|
+
error: error instanceof Error ? error.message : String(error),
|
|
109
|
+
pageCount,
|
|
110
|
+
cursor,
|
|
111
|
+
endpoint: apiEndpoint
|
|
112
|
+
});
|
|
113
|
+
// Don't completely fail - return what we have so far
|
|
114
|
+
hasMore = false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (pageCount >= absoluteMaxPages && hasMore) {
|
|
118
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, `Reached maximum page limit for ${apiEndpoint}`, {
|
|
119
|
+
maxPages: absoluteMaxPages,
|
|
120
|
+
totalItems: allItems.length,
|
|
121
|
+
endpoint: apiEndpoint
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
items: allItems,
|
|
126
|
+
nextCursor: cursor,
|
|
127
|
+
hasMore: hasMore && pageCount < absoluteMaxPages,
|
|
128
|
+
totalFetched: allItems.length
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Fetches a single page with proper response unwrapping
|
|
133
|
+
*
|
|
134
|
+
* @param fetchPage - Function that fetches a single page
|
|
135
|
+
* @param apiEndpoint - The API endpoint name for proper response unwrapping
|
|
136
|
+
* @param cursor - Optional cursor for the specific page
|
|
137
|
+
* @returns Single page of data with pagination metadata
|
|
138
|
+
*/
|
|
139
|
+
async function fetchSinglePage(fetchPage, apiEndpoint, cursor) {
|
|
140
|
+
const response = await fetchPage(cursor);
|
|
141
|
+
return (0, responseWrapper_1.unwrapApiResponse)(response.data, apiEndpoint);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Check if an endpoint supports pagination
|
|
145
|
+
*/
|
|
146
|
+
function endpointSupportsPagination(apiEndpoint) {
|
|
147
|
+
return (0, responseWrapper_1.supportsPagination)(apiEndpoint);
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=paginationNew.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginationNew.js","sourceRoot":"","sources":["../../src/utils/paginationNew.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter Utilities - Parameter parsing and validation helpers
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for parsing, validating, and setting
|
|
5
|
+
* default values for MCP handler parameters, reducing duplication and
|
|
6
|
+
* ensuring consistent parameter handling.
|
|
7
|
+
*/
|
|
8
|
+
interface WorkspaceArgs {
|
|
9
|
+
workspaceId?: string;
|
|
10
|
+
workspaceName?: string;
|
|
11
|
+
}
|
|
12
|
+
interface SearchArgs extends WorkspaceArgs {
|
|
13
|
+
query?: string;
|
|
14
|
+
searchScope?: 'both' | 'tasks' | 'projects';
|
|
15
|
+
limit?: number;
|
|
16
|
+
}
|
|
17
|
+
interface TaskArgs extends WorkspaceArgs {
|
|
18
|
+
name?: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
projectId?: string;
|
|
21
|
+
projectName?: string;
|
|
22
|
+
status?: string;
|
|
23
|
+
priority?: 'ASAP' | 'HIGH' | 'MEDIUM' | 'LOW';
|
|
24
|
+
dueDate?: string;
|
|
25
|
+
duration?: string | number;
|
|
26
|
+
labels?: string[];
|
|
27
|
+
assigneeId?: string;
|
|
28
|
+
autoScheduled?: Record<string, unknown> | null;
|
|
29
|
+
}
|
|
30
|
+
interface ProjectArgs extends WorkspaceArgs {
|
|
31
|
+
name?: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
color?: string;
|
|
34
|
+
status?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse workspace-related arguments from MCP request
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseWorkspaceArgs(args?: Record<string, unknown>): WorkspaceArgs;
|
|
40
|
+
/**
|
|
41
|
+
* Parse search-related arguments from MCP request
|
|
42
|
+
*/
|
|
43
|
+
export declare function parseSearchArgs(args?: Record<string, unknown>): SearchArgs;
|
|
44
|
+
/**
|
|
45
|
+
* Parse task creation/update arguments from MCP request
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseTaskArgs(args?: Record<string, unknown>): TaskArgs;
|
|
48
|
+
/**
|
|
49
|
+
* Parse project creation/update arguments from MCP request
|
|
50
|
+
*/
|
|
51
|
+
export declare function parseProjectArgs(args?: Record<string, unknown>): ProjectArgs;
|
|
52
|
+
/**
|
|
53
|
+
* Set default values for parameters
|
|
54
|
+
*/
|
|
55
|
+
export declare function setDefaults<T extends object, D extends Partial<T>>(args?: T, defaults?: D): T & D;
|
|
56
|
+
/**
|
|
57
|
+
* Validate that required parameters are present
|
|
58
|
+
* @throws {ValidationError} If required parameters are missing
|
|
59
|
+
*/
|
|
60
|
+
export declare function validateRequiredParams(args?: Record<string, unknown>, required?: string[]): void;
|
|
61
|
+
/**
|
|
62
|
+
* Validate parameter types
|
|
63
|
+
* @throws {ValidationError} If parameters have wrong types
|
|
64
|
+
*/
|
|
65
|
+
export declare function validateParameterTypes(args?: Record<string, unknown>, types?: Record<string, string>): void;
|
|
66
|
+
/**
|
|
67
|
+
* Sanitize string parameters (trim whitespace, handle empty strings)
|
|
68
|
+
* Following NULL_UNDEFINED_POLICY: empty strings become undefined (deleted)
|
|
69
|
+
*/
|
|
70
|
+
export declare function sanitizeStringParams<T extends Record<string, any>>(args?: T, stringParams?: (keyof T)[]): T;
|
|
71
|
+
interface ValidationOptions {
|
|
72
|
+
requireWorkspace?: boolean;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Parse and validate workspace parameters with common validation
|
|
76
|
+
*/
|
|
77
|
+
export declare function parseAndValidateWorkspace(args?: Record<string, unknown>, options?: ValidationOptions): WorkspaceArgs;
|
|
78
|
+
export {};
|
|
79
|
+
//# sourceMappingURL=parameterUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parameterUtils.d.ts","sourceRoot":"","sources":["../../src/utils/parameterUtils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,UAAU,aAAa;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,UAAW,SAAQ,aAAa;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,QAAS,SAAQ,aAAa;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAChD;AAED,UAAU,WAAY,SAAQ,aAAa;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,aAAa,CAKpF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,UAAU,CAO9E;AAoDD;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,QAAQ,CAe1E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,WAAW,CAQhF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EAChE,IAAI,GAAE,CAAW,EACjB,QAAQ,GAAE,CAAW,GACpB,CAAC,GAAG,CAAC,CAEP;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAClC,QAAQ,GAAE,MAAM,EAAO,GACtB,IAAI,CAgBN;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAClC,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACjC,IAAI,CAmBN;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAChE,IAAI,GAAE,CAAW,EACjB,YAAY,GAAE,CAAC,MAAM,CAAC,CAAC,EAAO,GAC7B,CAAC,CAoBH;AAED,UAAU,iBAAiB;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAClC,OAAO,GAAE,iBAAsB,GAC9B,aAAa,CAcf"}
|