mcp-zenskar 1.0.9 → 1.0.11

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/server.js +39 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-zenskar",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "Model Context Protocol (MCP) server for Zenskar API - customer management, invoicing, and billing operations",
5
5
  "main": "src/server.js",
6
6
  "bin": {
package/src/server.js CHANGED
@@ -378,6 +378,32 @@ async function executeAPICall(tool, args) {
378
378
  }
379
379
  });
380
380
 
381
+ // Nest flat address_* fields into an address object for the Zenskar API
382
+ if (tool.name === 'createCustomer') {
383
+ const addressFieldMap = {
384
+ address_line1: 'line1',
385
+ address_line2: 'line2',
386
+ address_city: 'city',
387
+ address_state: 'state',
388
+ address_zipCode: 'zipCode',
389
+ address_country: 'country',
390
+ address_country_code: 'country_code'
391
+ };
392
+ const addressObj = {};
393
+ let hasAddress = false;
394
+ Object.entries(addressFieldMap).forEach(([flatKey, nestedKey]) => {
395
+ if (bodyParams[flatKey] !== undefined) {
396
+ addressObj[nestedKey] = bodyParams[flatKey];
397
+ delete bodyParams[flatKey];
398
+ hasAddress = true;
399
+ }
400
+ });
401
+ if (hasAddress) {
402
+ bodyParams.address = addressObj;
403
+ logger.debug(`[${tool.name}] Transformed flat address fields into address object`);
404
+ }
405
+ }
406
+
381
407
  // Smart defaults for helper tools
382
408
  if (tool.name === 'extractContractFromRaw') {
383
409
  // Auto-populate organization_id from user context or env var if not provided
@@ -431,7 +457,11 @@ async function executeAPICall(tool, args) {
431
457
  const authToken = userContext?.authorization ||
432
458
  userContext?.headers?.['authorization'] ||
433
459
  userContext?.headers?.['Authorization'] ||
434
- (process.env.ZENSKAR_AUTH_TOKEN ? `Bearer ${process.env.ZENSKAR_AUTH_TOKEN}` : null);
460
+ process.env.ZENSKAR_AUTH_TOKEN;
461
+ const apiKey = userContext?.apiKey ||
462
+ userContext?.headers?.['x-api-key'] ||
463
+ process.env.ZENSKAR_API_KEY ||
464
+ process.env.ZENSKAR_AUTH_TOKEN; // Fallback: use AUTH_TOKEN as API key if it looks like one
435
465
 
436
466
  if (orgId) {
437
467
  headers['organisation'] = orgId;
@@ -440,18 +470,16 @@ async function executeAPICall(tool, args) {
440
470
  throw new Error('Organization ID is required for API access. Set ZENSKAR_ORGANIZATION env var or provide in user context.');
441
471
  }
442
472
 
443
- if (authToken) {
473
+ // Determine auth method: Bearer token for JWT, x-api-key for sandbox keys
474
+ if (authToken && authToken.startsWith('eyJ')) {
475
+ // JWT token - use Bearer auth
444
476
  headers['Authorization'] = authToken.startsWith('Bearer ') ? authToken : `Bearer ${authToken}`;
477
+ } else if (apiKey) {
478
+ // API key (sandbox_* or other) - use x-api-key header
479
+ headers['x-api-key'] = apiKey;
445
480
  } else {
446
- logger.error(`[${tool.name}] SECURITY ERROR: No authorization token provided`);
447
- throw new Error('Authorization token is required for API access. Set ZENSKAR_AUTH_TOKEN env var or provide in user context.');
448
- }
449
-
450
- // Also support legacy x-api-key if provided (optional)
451
- if (userContext?.apiKey) {
452
- headers['x-api-key'] = userContext.apiKey;
453
- } else if (userContext?.headers?.['x-api-key']) {
454
- headers['x-api-key'] = userContext.headers['x-api-key'];
481
+ logger.error(`[${tool.name}] SECURITY ERROR: No authorization provided`);
482
+ throw new Error('Authorization is required. Set ZENSKAR_AUTH_TOKEN (JWT) or ZENSKAR_API_KEY env var.');
455
483
  }
456
484
 
457
485
  // Add any other headers from user context