@utaba/ucm-mcp-server 4.0.0 → 4.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/README.md +1 -1
- package/dist/clients/UcmApiClient.d.ts +2 -1
- package/dist/clients/UcmApiClient.js +7 -4
- package/dist/index.js +4 -3
- package/dist/server/McpConfig.d.ts +2 -0
- package/dist/server/McpConfig.js +5 -1
- package/dist/server/McpServer.js +6 -1
- package/dist/tools/core/EditArtifactMetadataTool.js +1 -1
- package/dist/utils/HttpsAgentFactory.d.ts +21 -0
- package/dist/utils/HttpsAgentFactory.js +50 -0
- package/package.json +1 -1
- package/package.json.backup +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Get your auth token from https://ucm.utaba.ai
|
|
|
6
6
|
|
|
7
7
|
## Configuration
|
|
8
8
|
|
|
9
|
-
- `--auth-token <token>` (required): Authentication token in format `{apikey}`
|
|
9
|
+
- `--auth-token <token>` (required): Authentication token in format `{authorid}:{apikey}`
|
|
10
10
|
|
|
11
11
|
## Available MCP Tools
|
|
12
12
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import https from 'https';
|
|
1
2
|
import { ArtifactData, AuthorData } from '../types/UcmApiTypes.js';
|
|
2
3
|
export declare class UcmLocalApiClient {
|
|
3
4
|
private baseUrl;
|
|
4
5
|
private authToken?;
|
|
5
6
|
private authorId?;
|
|
6
7
|
private client;
|
|
7
|
-
constructor(baseUrl: string, authToken?: string | undefined, timeout?: number, authorId?: string | undefined);
|
|
8
|
+
constructor(baseUrl: string, authToken?: string | undefined, timeout?: number, authorId?: string | undefined, httpsAgent?: https.Agent);
|
|
8
9
|
private setupInterceptors;
|
|
9
10
|
private ensureClient;
|
|
10
11
|
getAuthors(): Promise<AuthorData[]>;
|
|
@@ -4,7 +4,7 @@ export class UcmLocalApiClient {
|
|
|
4
4
|
authToken;
|
|
5
5
|
authorId;
|
|
6
6
|
client;
|
|
7
|
-
constructor(baseUrl, authToken, timeout = 600000, authorId) {
|
|
7
|
+
constructor(baseUrl, authToken, timeout = 600000, authorId, httpsAgent) {
|
|
8
8
|
this.baseUrl = baseUrl;
|
|
9
9
|
this.authToken = authToken;
|
|
10
10
|
this.authorId = authorId;
|
|
@@ -14,7 +14,8 @@ export class UcmLocalApiClient {
|
|
|
14
14
|
headers: {
|
|
15
15
|
'Content-Type': 'application/json',
|
|
16
16
|
...(authToken && { 'Authorization': `Bearer ${authToken}` })
|
|
17
|
-
}
|
|
17
|
+
},
|
|
18
|
+
...(httpsAgent && { httpsAgent })
|
|
18
19
|
});
|
|
19
20
|
this.setupInterceptors();
|
|
20
21
|
}
|
|
@@ -187,7 +188,8 @@ export class UcmLocalApiClient {
|
|
|
187
188
|
if (data.queryParams) {
|
|
188
189
|
// New API structure with query params
|
|
189
190
|
Object.entries(data.queryParams).forEach(([key, value]) => {
|
|
190
|
-
if
|
|
191
|
+
// Skip if value is undefined, null, empty string, or string "null"/"undefined"
|
|
192
|
+
if (value !== undefined && value !== null && value !== '' && value !== 'null' && value !== 'undefined') {
|
|
191
193
|
// Handle arrays (e.g., tags) by JSON stringifying them
|
|
192
194
|
if (Array.isArray(value)) {
|
|
193
195
|
params.append(key, JSON.stringify(value));
|
|
@@ -221,7 +223,8 @@ export class UcmLocalApiClient {
|
|
|
221
223
|
if (data.queryParams) {
|
|
222
224
|
// New API structure with query params
|
|
223
225
|
Object.entries(data.queryParams).forEach(([key, value]) => {
|
|
224
|
-
if
|
|
226
|
+
// Skip if value is undefined, null, empty string, or string "null"/"undefined"
|
|
227
|
+
if (value !== undefined && value !== null && value !== '' && value !== 'null' && value !== 'undefined') {
|
|
225
228
|
// Handle arrays (e.g., tags) by JSON stringifying them
|
|
226
229
|
if (Array.isArray(value)) {
|
|
227
230
|
params.append(key, JSON.stringify(value));
|
package/dist/index.js
CHANGED
|
@@ -12,12 +12,12 @@ async function main() {
|
|
|
12
12
|
program
|
|
13
13
|
.name('ucm-mcp-server')
|
|
14
14
|
.description('Universal Context Manager - Read the ucm_connect tool first to avoid mistakes')
|
|
15
|
-
.version('1.0
|
|
15
|
+
.version('4.1.0')
|
|
16
16
|
.option('-u, --ucm-url <url>', 'UCM API base URL (defaults to https://ucm.utaba.ai)')
|
|
17
17
|
.option('-p, --port <port>', 'Server port', '3001')
|
|
18
18
|
.option('--log-level <level>', 'Log level', 'ERROR')
|
|
19
19
|
.option('--auth-token <token>', 'Authentication token for UCM API format is {auhtorid}:{apikey}. Get one from https://ucm.utaba.ai')
|
|
20
|
-
.option('--
|
|
20
|
+
.option('--ca-cert <path>', 'Path to CA certificate file (PEM format) for self-signed certificates')
|
|
21
21
|
.parse();
|
|
22
22
|
const options = program.opts();
|
|
23
23
|
const config = new McpConfig({
|
|
@@ -25,7 +25,8 @@ async function main() {
|
|
|
25
25
|
port: parseInt(options.port),
|
|
26
26
|
logLevel: options.logLevel,
|
|
27
27
|
authToken: options.authToken,
|
|
28
|
-
trustedAuthors: options.trustedAuthors ? options.trustedAuthors.split(',').map((a) => a.trim()) : ["utaba"]
|
|
28
|
+
trustedAuthors: options.trustedAuthors ? options.trustedAuthors.split(',').map((a) => a.trim()) : ["utaba"],
|
|
29
|
+
caCertPath: options.caCert
|
|
29
30
|
});
|
|
30
31
|
// Set the log level in the factory before creating any loggers
|
|
31
32
|
LoggerFactory.setLogLevel(config.logLevel);
|
|
@@ -6,6 +6,7 @@ export interface McpServerConfig {
|
|
|
6
6
|
logLevel: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
|
|
7
7
|
requestTimeout: number;
|
|
8
8
|
trustedAuthors: string[];
|
|
9
|
+
caCertPath?: string;
|
|
9
10
|
}
|
|
10
11
|
export declare class McpConfig {
|
|
11
12
|
private config;
|
|
@@ -21,6 +22,7 @@ export declare class McpConfig {
|
|
|
21
22
|
get requestTimeout(): number;
|
|
22
23
|
get trustedAuthors(): string[];
|
|
23
24
|
get authorId(): string | undefined;
|
|
25
|
+
get caCertPath(): string | undefined;
|
|
24
26
|
getFullConfig(): McpServerConfig;
|
|
25
27
|
}
|
|
26
28
|
//# sourceMappingURL=McpConfig.d.ts.map
|
package/dist/server/McpConfig.js
CHANGED
|
@@ -12,7 +12,8 @@ export class McpConfig {
|
|
|
12
12
|
authorId: options.authorId || authorId,
|
|
13
13
|
logLevel: options.logLevel || this.getEnvVar('MCP_LOG_LEVEL', 'ERROR'),
|
|
14
14
|
requestTimeout: options.requestTimeout || parseInt(this.getEnvVar('MCP_REQUEST_TIMEOUT', '30000')),
|
|
15
|
-
trustedAuthors: options.trustedAuthors || this.parseTrustedAuthors(this.getEnvVar('MCP_TRUSTED_AUTHORS', ''))
|
|
15
|
+
trustedAuthors: options.trustedAuthors || this.parseTrustedAuthors(this.getEnvVar('MCP_TRUSTED_AUTHORS', '')),
|
|
16
|
+
caCertPath: options.caCertPath
|
|
16
17
|
};
|
|
17
18
|
this.validateConfig();
|
|
18
19
|
}
|
|
@@ -82,6 +83,9 @@ export class McpConfig {
|
|
|
82
83
|
get authorId() {
|
|
83
84
|
return this.config.authorId;
|
|
84
85
|
}
|
|
86
|
+
get caCertPath() {
|
|
87
|
+
return this.config.caCertPath;
|
|
88
|
+
}
|
|
85
89
|
// Get full configuration object (for testing and debugging)
|
|
86
90
|
getFullConfig() {
|
|
87
91
|
return { ...this.config };
|
package/dist/server/McpServer.js
CHANGED
|
@@ -4,6 +4,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextpro
|
|
|
4
4
|
import { McpHandler } from './McpHandler.js';
|
|
5
5
|
import { UcmLocalApiClient } from '../clients/UcmApiClient.js';
|
|
6
6
|
import { ToolRegistry } from './ToolRegistry.js';
|
|
7
|
+
import { HttpsAgentFactory } from '../utils/HttpsAgentFactory.js';
|
|
7
8
|
export class McpServer {
|
|
8
9
|
config;
|
|
9
10
|
logger;
|
|
@@ -14,7 +15,11 @@ export class McpServer {
|
|
|
14
15
|
constructor(config, logger) {
|
|
15
16
|
this.config = config;
|
|
16
17
|
this.logger = logger;
|
|
17
|
-
|
|
18
|
+
// Create HTTPS agent with custom CA certificate if provided
|
|
19
|
+
const httpsAgent = config.caCertPath
|
|
20
|
+
? HttpsAgentFactory.createAgent({ caCertPath: config.caCertPath }, logger)
|
|
21
|
+
: undefined;
|
|
22
|
+
this.ucmClient = new UcmLocalApiClient(config.ucmApiUrl, config.authToken, config.requestTimeout, config.authorId, httpsAgent);
|
|
18
23
|
this.toolRegistry = new ToolRegistry(this.ucmClient, this.logger, config.trustedAuthors, config.authorId, config.ucmApiUrl);
|
|
19
24
|
this.handler = new McpHandler(this.toolRegistry, this.logger, config.authorId);
|
|
20
25
|
this.server = new Server({
|
|
@@ -9,7 +9,7 @@ export class EditArtifactMetadataTool extends BaseToolController {
|
|
|
9
9
|
return 'ucm_edit_artifact_metadata';
|
|
10
10
|
}
|
|
11
11
|
get description() {
|
|
12
|
-
return 'Edit artifact metadata and
|
|
12
|
+
return 'Edit artifact metadata and move artifacts. Supports updating description, namespace, filename, MIME type, technology, and tags. Move operations affect all versions while metadata-only updates apply to latest version only.';
|
|
13
13
|
}
|
|
14
14
|
get inputSchema() {
|
|
15
15
|
return {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import { ILogger } from '../interfaces/ILogger.js';
|
|
3
|
+
export interface HttpsAgentOptions {
|
|
4
|
+
caCertPath?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Factory for creating HTTPS agents with custom CA certificate support
|
|
8
|
+
* Enables secure connections to self-signed certificate environments
|
|
9
|
+
*/
|
|
10
|
+
export declare class HttpsAgentFactory {
|
|
11
|
+
/**
|
|
12
|
+
* Create an HTTPS agent with optional custom CA certificate
|
|
13
|
+
*
|
|
14
|
+
* @param options - Configuration options for the HTTPS agent
|
|
15
|
+
* @param logger - Logger instance for diagnostic messages
|
|
16
|
+
* @returns https.Agent configured with custom CA if provided, otherwise undefined
|
|
17
|
+
* @throws Error if certificate file cannot be read or is invalid
|
|
18
|
+
*/
|
|
19
|
+
static createAgent(options: HttpsAgentOptions, logger?: ILogger): https.Agent | undefined;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=HttpsAgentFactory.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
/**
|
|
4
|
+
* Factory for creating HTTPS agents with custom CA certificate support
|
|
5
|
+
* Enables secure connections to self-signed certificate environments
|
|
6
|
+
*/
|
|
7
|
+
export class HttpsAgentFactory {
|
|
8
|
+
/**
|
|
9
|
+
* Create an HTTPS agent with optional custom CA certificate
|
|
10
|
+
*
|
|
11
|
+
* @param options - Configuration options for the HTTPS agent
|
|
12
|
+
* @param logger - Logger instance for diagnostic messages
|
|
13
|
+
* @returns https.Agent configured with custom CA if provided, otherwise undefined
|
|
14
|
+
* @throws Error if certificate file cannot be read or is invalid
|
|
15
|
+
*/
|
|
16
|
+
static createAgent(options, logger) {
|
|
17
|
+
// If no CA certificate path provided, return undefined to use default behavior
|
|
18
|
+
if (!options.caCertPath) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
// Load the CA certificate from file
|
|
23
|
+
const caCert = fs.readFileSync(options.caCertPath, 'utf-8');
|
|
24
|
+
// Create HTTPS agent with custom CA certificate
|
|
25
|
+
// rejectUnauthorized: true ensures full certificate validation is maintained
|
|
26
|
+
const agent = new https.Agent({
|
|
27
|
+
ca: caCert
|
|
28
|
+
});
|
|
29
|
+
if (logger) {
|
|
30
|
+
logger.info('HttpsAgentFactory', `✓ Loaded CA certificate from: ${options.caCertPath}`);
|
|
31
|
+
}
|
|
32
|
+
return agent;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
36
|
+
const detailedMessage = `Failed to load CA certificate from ${options.caCertPath}: ${errorMessage}`;
|
|
37
|
+
if (logger) {
|
|
38
|
+
logger.warn('HttpsAgentFactory', detailedMessage);
|
|
39
|
+
logger.warn('HttpsAgentFactory', 'Continuing without custom CA certificate - using default certificate validation');
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
console.warn(`⚠️ ${detailedMessage}`);
|
|
43
|
+
console.warn('⚠️ Continuing without custom CA certificate - using default certificate validation');
|
|
44
|
+
}
|
|
45
|
+
// Return undefined to fall back to default behavior instead of crashing
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=HttpsAgentFactory.js.map
|
package/package.json
CHANGED