@uluops/ops-mcp 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +383 -0
- package/LICENSE +21 -0
- package/README.md +272 -0
- package/dist/client/sdk-error-mapper.d.ts +24 -0
- package/dist/client/sdk-error-mapper.d.ts.map +1 -0
- package/dist/client/sdk-error-mapper.js +205 -0
- package/dist/client/sdk-error-mapper.js.map +1 -0
- package/dist/config/index.d.ts +26 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +121 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/tool-registry.d.ts +25 -0
- package/dist/config/tool-registry.d.ts.map +1 -0
- package/dist/config/tool-registry.js +439 -0
- package/dist/config/tool-registry.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +245 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/index.d.ts +12 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +16 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/projects.d.ts +12 -0
- package/dist/resources/projects.d.ts.map +1 -0
- package/dist/resources/projects.js +45 -0
- package/dist/resources/projects.js.map +1 -0
- package/dist/resources/response-helpers.d.ts +15 -0
- package/dist/resources/response-helpers.d.ts.map +1 -0
- package/dist/resources/response-helpers.js +34 -0
- package/dist/resources/response-helpers.js.map +1 -0
- package/dist/resources/taxonomy.d.ts +19 -0
- package/dist/resources/taxonomy.d.ts.map +1 -0
- package/dist/resources/taxonomy.js +45 -0
- package/dist/resources/taxonomy.js.map +1 -0
- package/dist/tools/add-issue-note.d.ts +25 -0
- package/dist/tools/add-issue-note.d.ts.map +1 -0
- package/dist/tools/add-issue-note.js +19 -0
- package/dist/tools/add-issue-note.js.map +1 -0
- package/dist/tools/archive-runs.d.ts +33 -0
- package/dist/tools/archive-runs.d.ts.map +1 -0
- package/dist/tools/archive-runs.js +21 -0
- package/dist/tools/archive-runs.js.map +1 -0
- package/dist/tools/bulk-update-status.d.ts +54 -0
- package/dist/tools/bulk-update-status.d.ts.map +1 -0
- package/dist/tools/bulk-update-status.js +22 -0
- package/dist/tools/bulk-update-status.js.map +1 -0
- package/dist/tools/create-issue.d.ts +52 -0
- package/dist/tools/create-issue.d.ts.map +1 -0
- package/dist/tools/create-issue.js +25 -0
- package/dist/tools/create-issue.js.map +1 -0
- package/dist/tools/create-project.d.ts +21 -0
- package/dist/tools/create-project.d.ts.map +1 -0
- package/dist/tools/create-project.js +17 -0
- package/dist/tools/create-project.js.map +1 -0
- package/dist/tools/delete-project.d.ts +28 -0
- package/dist/tools/delete-project.d.ts.map +1 -0
- package/dist/tools/delete-project.js +34 -0
- package/dist/tools/delete-project.js.map +1 -0
- package/dist/tools/delete-run.d.ts +24 -0
- package/dist/tools/delete-run.d.ts.map +1 -0
- package/dist/tools/delete-run.js +18 -0
- package/dist/tools/delete-run.js.map +1 -0
- package/dist/tools/diff-runs.d.ts +30 -0
- package/dist/tools/diff-runs.d.ts.map +1 -0
- package/dist/tools/diff-runs.js +20 -0
- package/dist/tools/diff-runs.js.map +1 -0
- package/dist/tools/edit-issue.d.ts +34 -0
- package/dist/tools/edit-issue.d.ts.map +1 -0
- package/dist/tools/edit-issue.js +25 -0
- package/dist/tools/edit-issue.js.map +1 -0
- package/dist/tools/get-agent-lifecycle.d.ts +10 -0
- package/dist/tools/get-agent-lifecycle.d.ts.map +1 -0
- package/dist/tools/get-agent-lifecycle.js +20 -0
- package/dist/tools/get-agent-lifecycle.js.map +1 -0
- package/dist/tools/get-agent-matrix.d.ts +24 -0
- package/dist/tools/get-agent-matrix.d.ts.map +1 -0
- package/dist/tools/get-agent-matrix.js +29 -0
- package/dist/tools/get-agent-matrix.js.map +1 -0
- package/dist/tools/get-agent-reliability.d.ts +22 -0
- package/dist/tools/get-agent-reliability.d.ts.map +1 -0
- package/dist/tools/get-agent-reliability.js +14 -0
- package/dist/tools/get-agent-reliability.js.map +1 -0
- package/dist/tools/get-agent-runs-analysis.d.ts +33 -0
- package/dist/tools/get-agent-runs-analysis.d.ts.map +1 -0
- package/dist/tools/get-agent-runs-analysis.js +26 -0
- package/dist/tools/get-agent-runs-analysis.js.map +1 -0
- package/dist/tools/get-analytics.d.ts +30 -0
- package/dist/tools/get-analytics.d.ts.map +1 -0
- package/dist/tools/get-analytics.js +29 -0
- package/dist/tools/get-analytics.js.map +1 -0
- package/dist/tools/get-burndown.d.ts +24 -0
- package/dist/tools/get-burndown.d.ts.map +1 -0
- package/dist/tools/get-burndown.js +26 -0
- package/dist/tools/get-burndown.js.map +1 -0
- package/dist/tools/get-discovery.d.ts +24 -0
- package/dist/tools/get-discovery.d.ts.map +1 -0
- package/dist/tools/get-discovery.js +26 -0
- package/dist/tools/get-discovery.js.map +1 -0
- package/dist/tools/get-full-taxonomy-analytics.d.ts +27 -0
- package/dist/tools/get-full-taxonomy-analytics.d.ts.map +1 -0
- package/dist/tools/get-full-taxonomy-analytics.js +19 -0
- package/dist/tools/get-full-taxonomy-analytics.js.map +1 -0
- package/dist/tools/get-issue-by-fingerprint.d.ts +24 -0
- package/dist/tools/get-issue-by-fingerprint.d.ts.map +1 -0
- package/dist/tools/get-issue-by-fingerprint.js +18 -0
- package/dist/tools/get-issue-by-fingerprint.js.map +1 -0
- package/dist/tools/get-issue-details.d.ts +27 -0
- package/dist/tools/get-issue-details.d.ts.map +1 -0
- package/dist/tools/get-issue-details.js +19 -0
- package/dist/tools/get-issue-details.js.map +1 -0
- package/dist/tools/get-issue-history.d.ts +19 -0
- package/dist/tools/get-issue-history.d.ts.map +1 -0
- package/dist/tools/get-issue-history.js +13 -0
- package/dist/tools/get-issue-history.js.map +1 -0
- package/dist/tools/get-latest-run.d.ts +24 -0
- package/dist/tools/get-latest-run.d.ts.map +1 -0
- package/dist/tools/get-latest-run.js +18 -0
- package/dist/tools/get-latest-run.js.map +1 -0
- package/dist/tools/get-project-analysis.d.ts +36 -0
- package/dist/tools/get-project-analysis.d.ts.map +1 -0
- package/dist/tools/get-project-analysis.js +28 -0
- package/dist/tools/get-project-analysis.js.map +1 -0
- package/dist/tools/get-project-summary.d.ts +21 -0
- package/dist/tools/get-project-summary.d.ts.map +1 -0
- package/dist/tools/get-project-summary.js +17 -0
- package/dist/tools/get-project-summary.js.map +1 -0
- package/dist/tools/get-project-trends.d.ts +24 -0
- package/dist/tools/get-project-trends.d.ts.map +1 -0
- package/dist/tools/get-project-trends.js +27 -0
- package/dist/tools/get-project-trends.js.map +1 -0
- package/dist/tools/get-project.d.ts +21 -0
- package/dist/tools/get-project.d.ts.map +1 -0
- package/dist/tools/get-project.js +17 -0
- package/dist/tools/get-project.js.map +1 -0
- package/dist/tools/get-run-analysis.d.ts +21 -0
- package/dist/tools/get-run-analysis.d.ts.map +1 -0
- package/dist/tools/get-run-analysis.js +17 -0
- package/dist/tools/get-run-analysis.js.map +1 -0
- package/dist/tools/get-run-details.d.ts +27 -0
- package/dist/tools/get-run-details.d.ts.map +1 -0
- package/dist/tools/get-run-details.js +19 -0
- package/dist/tools/get-run-details.js.map +1 -0
- package/dist/tools/get-run.d.ts +21 -0
- package/dist/tools/get-run.d.ts.map +1 -0
- package/dist/tools/get-run.js +17 -0
- package/dist/tools/get-run.js.map +1 -0
- package/dist/tools/get-taxonomy.d.ts +15 -0
- package/dist/tools/get-taxonomy.d.ts.map +1 -0
- package/dist/tools/get-taxonomy.js +15 -0
- package/dist/tools/get-taxonomy.js.map +1 -0
- package/dist/tools/get-velocity.d.ts +24 -0
- package/dist/tools/get-velocity.d.ts.map +1 -0
- package/dist/tools/get-velocity.js +28 -0
- package/dist/tools/get-velocity.js.map +1 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +119 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list-agents.d.ts +15 -0
- package/dist/tools/list-agents.d.ts.map +1 -0
- package/dist/tools/list-agents.js +29 -0
- package/dist/tools/list-agents.js.map +1 -0
- package/dist/tools/list-projects.d.ts +15 -0
- package/dist/tools/list-projects.d.ts.map +1 -0
- package/dist/tools/list-projects.js +15 -0
- package/dist/tools/list-projects.js.map +1 -0
- package/dist/tools/list-runs.d.ts +30 -0
- package/dist/tools/list-runs.d.ts.map +1 -0
- package/dist/tools/list-runs.js +23 -0
- package/dist/tools/list-runs.js.map +1 -0
- package/dist/tools/merge-issues.d.ts +25 -0
- package/dist/tools/merge-issues.d.ts.map +1 -0
- package/dist/tools/merge-issues.js +19 -0
- package/dist/tools/merge-issues.js.map +1 -0
- package/dist/tools/query-analysis-records.d.ts +39 -0
- package/dist/tools/query-analysis-records.d.ts.map +1 -0
- package/dist/tools/query-analysis-records.js +31 -0
- package/dist/tools/query-analysis-records.js.map +1 -0
- package/dist/tools/query-issues.d.ts +54 -0
- package/dist/tools/query-issues.d.ts.map +1 -0
- package/dist/tools/query-issues.js +41 -0
- package/dist/tools/query-issues.js.map +1 -0
- package/dist/tools/restore-issue.d.ts +21 -0
- package/dist/tools/restore-issue.d.ts.map +1 -0
- package/dist/tools/restore-issue.js +17 -0
- package/dist/tools/restore-issue.js.map +1 -0
- package/dist/tools/restore-project.d.ts +21 -0
- package/dist/tools/restore-project.d.ts.map +1 -0
- package/dist/tools/restore-project.js +17 -0
- package/dist/tools/restore-project.js.map +1 -0
- package/dist/tools/save-run.d.ts +1570 -0
- package/dist/tools/save-run.d.ts.map +1 -0
- package/dist/tools/save-run.js +50 -0
- package/dist/tools/save-run.js.map +1 -0
- package/dist/tools/search-issues.d.ts +42 -0
- package/dist/tools/search-issues.d.ts.map +1 -0
- package/dist/tools/search-issues.js +25 -0
- package/dist/tools/search-issues.js.map +1 -0
- package/dist/tools/soft-delete-issue.d.ts +21 -0
- package/dist/tools/soft-delete-issue.d.ts.map +1 -0
- package/dist/tools/soft-delete-issue.js +17 -0
- package/dist/tools/soft-delete-issue.js.map +1 -0
- package/dist/tools/soft-delete-project.d.ts +27 -0
- package/dist/tools/soft-delete-project.d.ts.map +1 -0
- package/dist/tools/soft-delete-project.js +22 -0
- package/dist/tools/soft-delete-project.js.map +1 -0
- package/dist/tools/undo-issue-status.d.ts +21 -0
- package/dist/tools/undo-issue-status.d.ts.map +1 -0
- package/dist/tools/undo-issue-status.js +17 -0
- package/dist/tools/undo-issue-status.js.map +1 -0
- package/dist/tools/update-issue-by-fingerprint.d.ts +30 -0
- package/dist/tools/update-issue-by-fingerprint.d.ts.map +1 -0
- package/dist/tools/update-issue-by-fingerprint.js +24 -0
- package/dist/tools/update-issue-by-fingerprint.js.map +1 -0
- package/dist/tools/update-project.d.ts +24 -0
- package/dist/tools/update-project.d.ts.map +1 -0
- package/dist/tools/update-project.js +21 -0
- package/dist/tools/update-project.js.map +1 -0
- package/dist/tools/update-run.d.ts +1495 -0
- package/dist/tools/update-run.d.ts.map +1 -0
- package/dist/tools/update-run.js +60 -0
- package/dist/tools/update-run.js.map +1 -0
- package/dist/tools/update-status.d.ts +64 -0
- package/dist/tools/update-status.d.ts.map +1 -0
- package/dist/tools/update-status.js +28 -0
- package/dist/tools/update-status.js.map +1 -0
- package/dist/tools/validate-run.d.ts +228 -0
- package/dist/tools/validate-run.d.ts.map +1 -0
- package/dist/tools/validate-run.js +25 -0
- package/dist/tools/validate-run.js.map +1 -0
- package/dist/types/config.d.ts +33 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +5 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mcp.d.ts +21 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +30 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/run-schemas.d.ts +996 -0
- package/dist/types/run-schemas.d.ts.map +1 -0
- package/dist/types/run-schemas.js +91 -0
- package/dist/types/run-schemas.js.map +1 -0
- package/dist/types/schemas.d.ts +288 -0
- package/dist/types/schemas.d.ts.map +1 -0
- package/dist/types/schemas.js +218 -0
- package/dist/types/schemas.js.map +1 -0
- package/dist/types/server.d.ts +59 -0
- package/dist/types/server.d.ts.map +1 -0
- package/dist/types/server.js +7 -0
- package/dist/types/server.js.map +1 -0
- package/dist/utils/logger.d.ts +24 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +90 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/normalize-keys.d.ts +20 -0
- package/dist/utils/normalize-keys.d.ts.map +1 -0
- package/dist/utils/normalize-keys.js +38 -0
- package/dist/utils/normalize-keys.js.map +1 -0
- package/dist/utils/tool-handler.d.ts +64 -0
- package/dist/utils/tool-handler.d.ts.map +1 -0
- package/dist/utils/tool-handler.js +138 -0
- package/dist/utils/tool-handler.js.map +1 -0
- package/package.json +83 -0
- package/tool-policies.json +96 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server interface types
|
|
3
|
+
*
|
|
4
|
+
* Defines the interface for SecureMcpServer to avoid using generic Function type.
|
|
5
|
+
*/
|
|
6
|
+
import type { ZodRawShape } from 'zod';
|
|
7
|
+
import type { McpToolResponse } from './mcp.js';
|
|
8
|
+
/**
|
|
9
|
+
* Tool handler function signature
|
|
10
|
+
*/
|
|
11
|
+
export type ToolHandler = (args: unknown) => Promise<McpToolResponse>;
|
|
12
|
+
/**
|
|
13
|
+
* Resource content item in MCP resource response
|
|
14
|
+
*/
|
|
15
|
+
export interface ResourceContent {
|
|
16
|
+
uri: string;
|
|
17
|
+
mimeType?: string;
|
|
18
|
+
text?: string;
|
|
19
|
+
blob?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resource response format returned by resource handlers
|
|
23
|
+
*/
|
|
24
|
+
export interface ResourceResponse {
|
|
25
|
+
contents: ResourceContent[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resource handler function signature
|
|
29
|
+
*/
|
|
30
|
+
export type ResourceHandler = () => Promise<ResourceResponse>;
|
|
31
|
+
/**
|
|
32
|
+
* Resource metadata for registration
|
|
33
|
+
*/
|
|
34
|
+
export interface ResourceMetadata {
|
|
35
|
+
description?: string;
|
|
36
|
+
mimeType?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Interface for MCP server tool registration
|
|
40
|
+
*/
|
|
41
|
+
export interface McpServerToolRegistration {
|
|
42
|
+
tool: (name: string, description: string, schema: ZodRawShape, handler: ToolHandler) => void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Interface for MCP server resource registration
|
|
46
|
+
*
|
|
47
|
+
* Supports two overloads:
|
|
48
|
+
* - resource(name, uri, handler)
|
|
49
|
+
* - resource(name, uri, metadata, handler)
|
|
50
|
+
*/
|
|
51
|
+
export interface McpServerResourceRegistration {
|
|
52
|
+
resource: (name: string, uri: string, metadataOrHandler: ResourceMetadata | ResourceHandler, handler?: ResourceHandler) => void;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Combined interface for MCP server with both tools and resources
|
|
56
|
+
*/
|
|
57
|
+
export interface McpServer extends McpServerToolRegistration, McpServerResourceRegistration {
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/types/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;CAC9F;AAED;;;;;;GAMG;AACH,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,iBAAiB,EAAE,gBAAgB,GAAG,eAAe,EACrD,OAAO,CAAC,EAAE,eAAe,KACtB,IAAI,CAAC;CACX;AAED;;GAEG;AACH,MAAM,WAAW,SAAU,SAAQ,yBAAyB,EAAE,6BAA6B;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/types/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logger with optional file output
|
|
3
|
+
*
|
|
4
|
+
* Logs to stderr (for MCP compatibility) and optionally to files.
|
|
5
|
+
*/
|
|
6
|
+
import type { LogLevel } from '../types/index.js';
|
|
7
|
+
export interface LoggerConfig {
|
|
8
|
+
level: LogLevel;
|
|
9
|
+
enableFileLogging?: boolean;
|
|
10
|
+
logDir?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface Logger {
|
|
13
|
+
debug: (message: string, context?: Record<string, unknown>) => void;
|
|
14
|
+
info: (message: string, context?: Record<string, unknown>) => void;
|
|
15
|
+
warn: (message: string, context?: Record<string, unknown>) => void;
|
|
16
|
+
error: (message: string, context?: Record<string, unknown>) => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a structured logger
|
|
20
|
+
*
|
|
21
|
+
* @param config - Logger configuration (or simple log level string for backwards compatibility)
|
|
22
|
+
*/
|
|
23
|
+
export declare function createLogger(config: LoggerConfig | LogLevel): Logger;
|
|
24
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,QAAQ,CAAC;IAChB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACpE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACnE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACnE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACrE;AA2CD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,GAAG,MAAM,CAkDpE"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logger with optional file output
|
|
3
|
+
*
|
|
4
|
+
* Logs to stderr (for MCP compatibility) and optionally to files.
|
|
5
|
+
*/
|
|
6
|
+
import { appendFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
const LOG_LEVELS = {
|
|
9
|
+
debug: 0,
|
|
10
|
+
info: 1,
|
|
11
|
+
warn: 2,
|
|
12
|
+
error: 3,
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Format a log entry as JSON
|
|
16
|
+
*/
|
|
17
|
+
function formatLogEntry(level, message, context) {
|
|
18
|
+
const entry = {
|
|
19
|
+
timestamp: new Date().toISOString(),
|
|
20
|
+
level: level.toUpperCase(),
|
|
21
|
+
message,
|
|
22
|
+
...(context && Object.keys(context).length > 0 ? { context } : {}),
|
|
23
|
+
};
|
|
24
|
+
return JSON.stringify(entry);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get the log file path for today
|
|
28
|
+
*/
|
|
29
|
+
function getLogFilePath(logDir) {
|
|
30
|
+
const date = new Date().toISOString().split('T')[0] ?? 'unknown'; // YYYY-MM-DD
|
|
31
|
+
return join(logDir, `mcp-client-${date}.log`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Ensure the log directory exists
|
|
35
|
+
*/
|
|
36
|
+
function ensureLogDir(logDir) {
|
|
37
|
+
if (!existsSync(logDir)) {
|
|
38
|
+
mkdirSync(logDir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create a structured logger
|
|
43
|
+
*
|
|
44
|
+
* @param config - Logger configuration (or simple log level string for backwards compatibility)
|
|
45
|
+
*/
|
|
46
|
+
export function createLogger(config) {
|
|
47
|
+
// Support simple string level for backwards compatibility
|
|
48
|
+
const resolvedConfig = typeof config === 'string' ? { level: config } : config;
|
|
49
|
+
const { level, enableFileLogging = false, logDir } = resolvedConfig;
|
|
50
|
+
const minLevel = LOG_LEVELS[level];
|
|
51
|
+
// Resolve log directory - use project-local logs/ folder like mcp-secure-server
|
|
52
|
+
const resolvedLogDir = logDir ?? join(process.cwd(), 'logs');
|
|
53
|
+
// Ensure log directory exists if file logging is enabled
|
|
54
|
+
if (enableFileLogging) {
|
|
55
|
+
ensureLogDir(resolvedLogDir);
|
|
56
|
+
}
|
|
57
|
+
const log = (logLevel, message, context) => {
|
|
58
|
+
if (LOG_LEVELS[logLevel] < minLevel) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const formatted = formatLogEntry(logLevel, message, context);
|
|
62
|
+
// Always log to stderr (MCP uses stdout for protocol)
|
|
63
|
+
console.error(formatted);
|
|
64
|
+
// Optionally log to file
|
|
65
|
+
if (enableFileLogging) {
|
|
66
|
+
try {
|
|
67
|
+
const filePath = getLogFilePath(resolvedLogDir);
|
|
68
|
+
appendFileSync(filePath, formatted + '\n', 'utf-8');
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Silently ignore file logging errors to avoid disrupting MCP
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
debug: (message, context) => {
|
|
77
|
+
log('debug', message, context);
|
|
78
|
+
},
|
|
79
|
+
info: (message, context) => {
|
|
80
|
+
log('info', message, context);
|
|
81
|
+
},
|
|
82
|
+
warn: (message, context) => {
|
|
83
|
+
log('warn', message, context);
|
|
84
|
+
},
|
|
85
|
+
error: (message, context) => {
|
|
86
|
+
log('error', message, context);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key normalization utilities for snake_case → camelCase conversion
|
|
3
|
+
*
|
|
4
|
+
* MCP tool inputs use snake_case (matching the MCP protocol convention).
|
|
5
|
+
* The SDK expects camelCase. This module provides recursive conversion.
|
|
6
|
+
*
|
|
7
|
+
* Same pattern used by the CLI (utils.ts) and API (case-transform.ts).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Recursively convert all object keys from snake_case to camelCase.
|
|
11
|
+
*
|
|
12
|
+
* - Arrays are recursed into (each element is normalized)
|
|
13
|
+
* - Primitives and null pass through unchanged
|
|
14
|
+
* - Nested objects are recursed
|
|
15
|
+
*
|
|
16
|
+
* @param input - The value to normalize
|
|
17
|
+
* @returns The value with all object keys converted to camelCase
|
|
18
|
+
*/
|
|
19
|
+
export declare function normalizeKeys(input: unknown): unknown;
|
|
20
|
+
//# sourceMappingURL=normalize-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-keys.d.ts","sourceRoot":"","sources":["../../src/utils/normalize-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAYrD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key normalization utilities for snake_case → camelCase conversion
|
|
3
|
+
*
|
|
4
|
+
* MCP tool inputs use snake_case (matching the MCP protocol convention).
|
|
5
|
+
* The SDK expects camelCase. This module provides recursive conversion.
|
|
6
|
+
*
|
|
7
|
+
* Same pattern used by the CLI (utils.ts) and API (case-transform.ts).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Convert a single snake_case string to camelCase
|
|
11
|
+
*/
|
|
12
|
+
function toCamelCase(str) {
|
|
13
|
+
return str.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Recursively convert all object keys from snake_case to camelCase.
|
|
17
|
+
*
|
|
18
|
+
* - Arrays are recursed into (each element is normalized)
|
|
19
|
+
* - Primitives and null pass through unchanged
|
|
20
|
+
* - Nested objects are recursed
|
|
21
|
+
*
|
|
22
|
+
* @param input - The value to normalize
|
|
23
|
+
* @returns The value with all object keys converted to camelCase
|
|
24
|
+
*/
|
|
25
|
+
export function normalizeKeys(input) {
|
|
26
|
+
if (Array.isArray(input)) {
|
|
27
|
+
return input.map(normalizeKeys);
|
|
28
|
+
}
|
|
29
|
+
if (input !== null && typeof input === 'object') {
|
|
30
|
+
const result = {};
|
|
31
|
+
for (const [key, value] of Object.entries(input)) {
|
|
32
|
+
result[toCamelCase(key)] = normalizeKeys(value);
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
return input;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=normalize-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-keys.js","sourceRoot":"","sources":["../../src/utils/normalize-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YAC5E,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool handler factory
|
|
3
|
+
*
|
|
4
|
+
* Creates standardized MCP tool handlers with consistent error handling.
|
|
5
|
+
* Eliminates boilerplate across tool implementations.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { type McpToolResponse } from '../types/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Sentinel used by preProcess hooks to short-circuit the handler with a
|
|
11
|
+
* tool response (typically an error). Discriminating on a dedicated symbol
|
|
12
|
+
* avoids accidental collision with tool input schemas that may legitimately
|
|
13
|
+
* contain a top-level `content` field.
|
|
14
|
+
*/
|
|
15
|
+
declare const SHORT_CIRCUIT: unique symbol;
|
|
16
|
+
type ShortCircuit = McpToolResponse & {
|
|
17
|
+
readonly [SHORT_CIRCUIT]: true;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Construct a short-circuit response from a preProcess hook. The returned
|
|
21
|
+
* value is a normal MCP tool response plus a non-enumerable marker symbol
|
|
22
|
+
* that createToolHandler recognises.
|
|
23
|
+
*/
|
|
24
|
+
export declare function shortCircuit(response: McpToolResponse): ShortCircuit;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a standardized tool handler with Zod validation, key normalization,
|
|
27
|
+
* and SDK error mapping.
|
|
28
|
+
*
|
|
29
|
+
* All handlers follow the same flow:
|
|
30
|
+
* 1. Parse input with Zod schema (validates snake_case MCP input)
|
|
31
|
+
* 2. Normalize keys from snake_case → camelCase for SDK
|
|
32
|
+
* 3. Call SDK method with normalized input
|
|
33
|
+
* 4. Return success response or mapped error
|
|
34
|
+
*
|
|
35
|
+
* @param schema - Zod schema for input validation (snake_case fields)
|
|
36
|
+
* @param sdkCall - Function that receives the normalized (camelCase) input as
|
|
37
|
+
* `Record<string, unknown>` and calls the SDK. The runtime contract is upheld
|
|
38
|
+
* by Zod validation immediately upstream.
|
|
39
|
+
* @returns MCP-compatible handler function
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* server.tool(
|
|
44
|
+
* 'query_issues',
|
|
45
|
+
* 'Query issues...',
|
|
46
|
+
* QueryIssuesInputSchema.shape,
|
|
47
|
+
* createToolHandler(QueryIssuesInputSchema, (n) =>
|
|
48
|
+
* opsClient.projects.listIssues(n['project'] as string, n)
|
|
49
|
+
* )
|
|
50
|
+
* );
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function createToolHandler<TInput>(schema: z.ZodSchema<TInput>, sdkCall: (normalized: any) => Promise<unknown>, options?: {
|
|
54
|
+
/** Tool name for error context. Included in error responses to help MCP clients diagnose failures. */
|
|
55
|
+
toolName?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Transform parsed input before normalization. Return the value produced
|
|
58
|
+
* by `shortCircuit(response)` to bypass the SDK call and return `response`
|
|
59
|
+
* directly to the caller.
|
|
60
|
+
*/
|
|
61
|
+
preProcess?: (input: TInput) => TInput | ShortCircuit;
|
|
62
|
+
}): (args: unknown) => Promise<McpToolResponse>;
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=tool-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-handler.d.ts","sourceRoot":"","sources":["../../src/utils/tool-handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAwChF;;;;;GAKG;AACH,QAAA,MAAM,aAAa,eAAmC,CAAC;AAEvD,KAAK,YAAY,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAEzE;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,GAAG,YAAY,CAOpE;AAUD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EACtC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAQ3B,OAAO,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,EAC9C,OAAO,CAAC,EAAE;IACR,sGAAsG;IACtG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,YAAY,CAAC;CACvD,GACA,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,eAAe,CAAC,CAiC7C"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool handler factory
|
|
3
|
+
*
|
|
4
|
+
* Creates standardized MCP tool handlers with consistent error handling.
|
|
5
|
+
* Eliminates boilerplate across tool implementations.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { mapSdkErrorToMcp, mapZodErrorToMcp } from '../client/sdk-error-mapper.js';
|
|
9
|
+
import { normalizeKeys } from './normalize-keys.js';
|
|
10
|
+
import { createSuccessResponse } from '../types/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* Coerce string values to numbers for fields that the Zod schema expects as numeric.
|
|
13
|
+
* MCP JSON-RPC sometimes serializes numeric parameters as strings (e.g., "50" instead of 50).
|
|
14
|
+
* This runs before Zod validation to prevent spurious type errors at the boundary.
|
|
15
|
+
*/
|
|
16
|
+
function coerceNumericFields(args, schema) {
|
|
17
|
+
if (typeof args !== 'object' || args === null)
|
|
18
|
+
return args;
|
|
19
|
+
if (!(schema instanceof z.ZodObject))
|
|
20
|
+
return args;
|
|
21
|
+
const shape = schema.shape;
|
|
22
|
+
const obj = { ...args };
|
|
23
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
24
|
+
if (key in obj && typeof obj[key] === 'string') {
|
|
25
|
+
if (isNumericSchema(fieldSchema)) {
|
|
26
|
+
const num = Number(obj[key]);
|
|
27
|
+
// Number.isFinite rejects NaN, Infinity, and -Infinity
|
|
28
|
+
if (Number.isFinite(num)) {
|
|
29
|
+
obj[key] = num;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return obj;
|
|
35
|
+
}
|
|
36
|
+
/** Check if a Zod schema (possibly wrapped in optional/nullable/default) expects a number. */
|
|
37
|
+
function isNumericSchema(schema) {
|
|
38
|
+
if (schema instanceof z.ZodNumber)
|
|
39
|
+
return true;
|
|
40
|
+
if (schema instanceof z.ZodOptional || schema instanceof z.ZodNullable) {
|
|
41
|
+
return isNumericSchema(schema.unwrap());
|
|
42
|
+
}
|
|
43
|
+
if (schema instanceof z.ZodDefault) {
|
|
44
|
+
return isNumericSchema(schema.removeDefault());
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Sentinel used by preProcess hooks to short-circuit the handler with a
|
|
50
|
+
* tool response (typically an error). Discriminating on a dedicated symbol
|
|
51
|
+
* avoids accidental collision with tool input schemas that may legitimately
|
|
52
|
+
* contain a top-level `content` field.
|
|
53
|
+
*/
|
|
54
|
+
const SHORT_CIRCUIT = Symbol('mcp.tool.short-circuit');
|
|
55
|
+
/**
|
|
56
|
+
* Construct a short-circuit response from a preProcess hook. The returned
|
|
57
|
+
* value is a normal MCP tool response plus a non-enumerable marker symbol
|
|
58
|
+
* that createToolHandler recognises.
|
|
59
|
+
*/
|
|
60
|
+
export function shortCircuit(response) {
|
|
61
|
+
return Object.defineProperty({ ...response }, SHORT_CIRCUIT, {
|
|
62
|
+
value: true,
|
|
63
|
+
enumerable: false,
|
|
64
|
+
writable: false,
|
|
65
|
+
configurable: false,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function isShortCircuit(value) {
|
|
69
|
+
return (typeof value === 'object' &&
|
|
70
|
+
value !== null &&
|
|
71
|
+
value[SHORT_CIRCUIT] === true);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Creates a standardized tool handler with Zod validation, key normalization,
|
|
75
|
+
* and SDK error mapping.
|
|
76
|
+
*
|
|
77
|
+
* All handlers follow the same flow:
|
|
78
|
+
* 1. Parse input with Zod schema (validates snake_case MCP input)
|
|
79
|
+
* 2. Normalize keys from snake_case → camelCase for SDK
|
|
80
|
+
* 3. Call SDK method with normalized input
|
|
81
|
+
* 4. Return success response or mapped error
|
|
82
|
+
*
|
|
83
|
+
* @param schema - Zod schema for input validation (snake_case fields)
|
|
84
|
+
* @param sdkCall - Function that receives the normalized (camelCase) input as
|
|
85
|
+
* `Record<string, unknown>` and calls the SDK. The runtime contract is upheld
|
|
86
|
+
* by Zod validation immediately upstream.
|
|
87
|
+
* @returns MCP-compatible handler function
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* server.tool(
|
|
92
|
+
* 'query_issues',
|
|
93
|
+
* 'Query issues...',
|
|
94
|
+
* QueryIssuesInputSchema.shape,
|
|
95
|
+
* createToolHandler(QueryIssuesInputSchema, (n) =>
|
|
96
|
+
* opsClient.projects.listIssues(n['project'] as string, n)
|
|
97
|
+
* )
|
|
98
|
+
* );
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export function createToolHandler(schema,
|
|
102
|
+
// SAFETY: `normalized` is `any` because normalizeKeys performs a runtime
|
|
103
|
+
// snake_case → camelCase key transformation that TypeScript cannot track
|
|
104
|
+
// statically. Zod validation immediately upstream enforces the shape; the
|
|
105
|
+
// SDK call signatures further constrain field types. createToolHandler is
|
|
106
|
+
// an internal utility (not re-exported from src/index.ts), so this `any`
|
|
107
|
+
// does not leak to the public npm surface.
|
|
108
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
109
|
+
sdkCall, options) {
|
|
110
|
+
const toolName = options?.toolName;
|
|
111
|
+
return async (args) => {
|
|
112
|
+
try {
|
|
113
|
+
let input = schema.parse(coerceNumericFields(args, schema));
|
|
114
|
+
if (options?.preProcess) {
|
|
115
|
+
const preResult = options.preProcess(input);
|
|
116
|
+
if (isShortCircuit(preResult)) {
|
|
117
|
+
return preResult;
|
|
118
|
+
}
|
|
119
|
+
input = preResult;
|
|
120
|
+
}
|
|
121
|
+
const normalized = normalizeKeys(input);
|
|
122
|
+
const result = await sdkCall(normalized);
|
|
123
|
+
return createSuccessResponse(result);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
// Log errors to stderr for debugging (MCP transport uses stdout)
|
|
127
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
128
|
+
const errorType = error instanceof z.ZodError ? 'validation' :
|
|
129
|
+
error instanceof Error ? error.constructor.name : 'unknown';
|
|
130
|
+
process.stderr.write(`[mcp-tool-error] tool=${toolName ?? 'unknown'} type=${errorType} message=${errorMsg.slice(0, 200)}\n`);
|
|
131
|
+
if (error instanceof z.ZodError) {
|
|
132
|
+
return mapZodErrorToMcp(error, toolName);
|
|
133
|
+
}
|
|
134
|
+
return mapSdkErrorToMcp(error, toolName);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=tool-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-handler.js","sourceRoot":"","sources":["../../src/utils/tool-handler.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@uluops/ops-mcp",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "MCP server for the UluOps Platform API — validation tracking, analytics, and issue management",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"uluops-ops-mcp": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"tool-policies.json",
|
|
20
|
+
"README.md",
|
|
21
|
+
"CHANGELOG.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"dev": "tsx watch src/index.ts",
|
|
27
|
+
"start": "node dist/index.js",
|
|
28
|
+
"clean": "rm -rf dist",
|
|
29
|
+
"prebuild": "npm run clean",
|
|
30
|
+
"postbuild": "chmod +x dist/index.js",
|
|
31
|
+
"lint": "eslint src/",
|
|
32
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
33
|
+
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"test:unit": "vitest run test/unit",
|
|
37
|
+
"test:integration": "vitest run test/integration",
|
|
38
|
+
"test:watch": "vitest",
|
|
39
|
+
"test:coverage": "vitest run --coverage"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"mcp",
|
|
43
|
+
"mcp-server",
|
|
44
|
+
"uluops",
|
|
45
|
+
"validation",
|
|
46
|
+
"analytics",
|
|
47
|
+
"claude",
|
|
48
|
+
"claude-code",
|
|
49
|
+
"model-context-protocol"
|
|
50
|
+
],
|
|
51
|
+
"author": "aself101",
|
|
52
|
+
"license": "MIT",
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/Uluops/ops-uluops-mcp.git"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/Uluops/ops-uluops-mcp#readme",
|
|
58
|
+
"bugs": {
|
|
59
|
+
"url": "https://github.com/Uluops/ops-uluops-mcp/issues"
|
|
60
|
+
},
|
|
61
|
+
"engines": {
|
|
62
|
+
"node": ">=18.0.0"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
66
|
+
"@uluops/ops-sdk": "3.1.0",
|
|
67
|
+
"mcp-secure-server": "0.0.14-security",
|
|
68
|
+
"zod": "3.25.76"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@eslint/js": "9.39.4",
|
|
72
|
+
"@types/node": "22.19.19",
|
|
73
|
+
"@typescript-eslint/eslint-plugin": "8.59.4",
|
|
74
|
+
"@typescript-eslint/parser": "8.59.4",
|
|
75
|
+
"@vitest/coverage-v8": "2.1.9",
|
|
76
|
+
"eslint": "9.39.4",
|
|
77
|
+
"prettier": "3.8.3",
|
|
78
|
+
"tsx": "4.22.3",
|
|
79
|
+
"typescript": "5.9.3",
|
|
80
|
+
"typescript-eslint": "8.59.4",
|
|
81
|
+
"vitest": "2.1.9"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2.0",
|
|
3
|
+
"tools": {
|
|
4
|
+
"save_run": {
|
|
5
|
+
"level": "STORAGE",
|
|
6
|
+
"relaxedFields": ["description", "title", "recommendations", "file_path", "raw_markdown"],
|
|
7
|
+
"description": "Stores validation results - may contain code snippets in markdown"
|
|
8
|
+
},
|
|
9
|
+
"validate_run": {
|
|
10
|
+
"level": "STORAGE",
|
|
11
|
+
"relaxedFields": ["description", "title", "recommendations", "file_path", "raw_markdown"],
|
|
12
|
+
"description": "Previews validation results - may contain code snippets in markdown"
|
|
13
|
+
},
|
|
14
|
+
"create_issue": {
|
|
15
|
+
"level": "STORAGE",
|
|
16
|
+
"relaxedFields": ["description", "title", "file_path"],
|
|
17
|
+
"description": "Creates issues - file paths may reference sensitive files being reported on"
|
|
18
|
+
},
|
|
19
|
+
"add_issue_note": {
|
|
20
|
+
"level": "STORAGE",
|
|
21
|
+
"relaxedFields": ["content", "issue_id"],
|
|
22
|
+
"description": "Issue notes may contain code snippets. issue_id is UUID (can trigger CC false positive)"
|
|
23
|
+
},
|
|
24
|
+
"update_status": {
|
|
25
|
+
"level": "STORAGE",
|
|
26
|
+
"relaxedFields": ["updates", "id", "issue_id", "fingerprint", "reason"],
|
|
27
|
+
"description": "Status updates contain UUIDs that can trigger credit card pattern false positives"
|
|
28
|
+
},
|
|
29
|
+
"bulk_update_status": {
|
|
30
|
+
"level": "STORAGE",
|
|
31
|
+
"relaxedFields": ["updates", "id", "issue_id", "reason"],
|
|
32
|
+
"description": "Bulk status updates contain UUIDs that can trigger credit card pattern false positives"
|
|
33
|
+
},
|
|
34
|
+
"get_issue_details": {
|
|
35
|
+
"level": "QUERY",
|
|
36
|
+
"relaxedFields": ["id"],
|
|
37
|
+
"description": "Issue ID is UUID that can trigger credit card pattern false positives"
|
|
38
|
+
},
|
|
39
|
+
"get_issue_history": {
|
|
40
|
+
"level": "QUERY",
|
|
41
|
+
"relaxedFields": ["issue_id"],
|
|
42
|
+
"description": "Issue ID is UUID that can trigger credit card pattern false positives"
|
|
43
|
+
},
|
|
44
|
+
"edit_issue": {
|
|
45
|
+
"level": "STORAGE",
|
|
46
|
+
"relaxedFields": ["issue_id", "title", "file_path", "category"],
|
|
47
|
+
"description": "Edit issue metadata - issue_id is UUID"
|
|
48
|
+
},
|
|
49
|
+
"merge_issues": {
|
|
50
|
+
"level": "STORAGE",
|
|
51
|
+
"relaxedFields": ["target_issue_id", "source_issue_ids"],
|
|
52
|
+
"description": "Merge issues - IDs are UUIDs that can trigger credit card pattern false positives"
|
|
53
|
+
},
|
|
54
|
+
"update_run": {
|
|
55
|
+
"level": "STORAGE",
|
|
56
|
+
"relaxedFields": ["raw_markdown", "validators"],
|
|
57
|
+
"description": "Update run metadata - raw_markdown may contain code snippets"
|
|
58
|
+
},
|
|
59
|
+
"soft_delete_project": {
|
|
60
|
+
"level": "STORAGE",
|
|
61
|
+
"relaxedFields": ["confirmation_phrase"],
|
|
62
|
+
"description": "Soft delete project - confirmation_phrase is user-provided text"
|
|
63
|
+
},
|
|
64
|
+
"delete_run": {
|
|
65
|
+
"level": "STORAGE",
|
|
66
|
+
"relaxedFields": ["run_id"],
|
|
67
|
+
"description": "Delete run - run_id is UUID that can trigger false positives"
|
|
68
|
+
},
|
|
69
|
+
"get_run": {
|
|
70
|
+
"level": "QUERY",
|
|
71
|
+
"relaxedFields": ["run_id"],
|
|
72
|
+
"description": "Get run by UUID - run_id can trigger credit card pattern false positives"
|
|
73
|
+
},
|
|
74
|
+
"update_issue_by_fingerprint": {
|
|
75
|
+
"level": "STORAGE",
|
|
76
|
+
"relaxedFields": ["fingerprint", "reason"],
|
|
77
|
+
"description": "Update issue by fingerprint - fingerprint is SHA-256 hash"
|
|
78
|
+
},
|
|
79
|
+
"get_issue_by_fingerprint": {
|
|
80
|
+
"level": "QUERY",
|
|
81
|
+
"relaxedFields": ["fingerprint"],
|
|
82
|
+
"description": "Get issue by fingerprint - fingerprint is SHA-256 hash"
|
|
83
|
+
},
|
|
84
|
+
"restore_issue": {
|
|
85
|
+
"level": "STORAGE",
|
|
86
|
+
"relaxedFields": ["issue_id"],
|
|
87
|
+
"description": "Restore issue - issue_id is UUID"
|
|
88
|
+
},
|
|
89
|
+
"undo_issue_status": {
|
|
90
|
+
"level": "STORAGE",
|
|
91
|
+
"relaxedFields": ["issue_id"],
|
|
92
|
+
"description": "Undo issue status - issue_id is UUID"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
"defaultLevel": "QUERY"
|
|
96
|
+
}
|