Skip to content

Environment validation fails with 403 when token lacks DataExport scope (not listed in README required scopes) #68

@at10ti0n

Description

@at10ti0n

Description

The MCP server fails to register environments as valid when the API token only has the scopes listed in the README documentation. The server internally requires the V1 DataExport scope for the /api/v1/config/clusterversion endpoint, but this scope is not listed in the README's Authentication section.

Steps to Reproduce

  1. Create a Dynatrace Managed API token with only the scopes documented in the README:
    • auditLogs.read, entities.read, events.read, logs.read, metrics.read, networkZones.read, problems.read, securityProblems.read, slo.read
  2. Configure the MCP server with this token
  3. Start the MCP server
  4. Call get_environments_info

Expected Behavior

The environment is registered as valid and all MCP tools work correctly.

Actual Behavior

The environment shows Valid Environment: No with a 403 error. All tool calls fail with:

Environment alias(es) not valid. Options are: ALL_ENVIRONMENTS

Root Cause Analysis

The issue is in src/authentication/managed-auth-client.ts:

1. validateConnection() (line ~122) has a fallback — works fine:

async validateConnection(): Promise<boolean> {
  try {
    const response = await this.httpClient.get('/api/v1/config/clusterversion');
    return response.status === 200;
  } catch (error) {
    // Fallback: try a basic API endpoint
    try {
      const response = await this.httpClient.get('/api/v2/metrics', { params: { pageSize: 1 } });
      return response.status === 200;
    } catch (fallbackError) {
      return false;
    }
  }
}

When the token lacks DataExport, the V1 call gets 403, but the V2 fallback succeeds → validateConnection() returns true.

2. getClusterVersion() (line ~143) has NO fallback — fails:

async getClusterVersion(): Promise<ClusterVersion> {
  const response = await this.httpClient.get('/api/v1/config/clusterversion');
  return response.data;
}

3. isConfigured() (line ~192) calls both sequentially:

async isConfigured() {
  try {
    const isConnected = await this.validateConnection();  // ✅ passes (V2 fallback)
    if (!isConnected) { return false; }

    const clusterVersion = await this.getClusterVersion();  // ❌ 403 - no fallback!
    // ...never reaches here
  } catch (error) {
    this.validationError = `Failed to connect...`;
    return false;
  }
}

So validateConnection() passes via the V2 fallback, but then getClusterVersion() hits the same V1 endpoint again without a fallback, throwing a 403 that marks the environment as invalid.

Evidence

The Dynatrace API returns this error for the V1 endpoint:

{"error":{"code":403,"message":"Token is missing required scope. Use one of: DataExport (Access problem and event feed, metrics, and topology)"}}

Meanwhile, V2 endpoints work perfectly with the documented scopes:

# V1 endpoint - 403
curl -H "Authorization: Api-Token <token>" "https://<host>/e/<env>/api/v1/config/clusterversion"

# V2 endpoint - 200
curl -H "Authorization: Api-Token <token>" "https://<host>/e/<env>/api/v2/metrics?pageSize=1"

Documentation Discrepancy

The source code at managed-auth-client.ts line 4-13 defines a MANAGED_API_SCOPES constant that includes DataExport and ReadConfig:

const MANAGED_API_SCOPES = [
  'DataExport',
  'ReadConfig',
  'ReadSyntheticData',
  // ...
];

But the README's Authentication section only lists V2 scopes:

auditLogs.read, entities.read, events.read, logs.read, metrics.read, networkZones.read, problems.read, securityProblems.read, slo.read

Suggested Fix

Option A (code fix): Add a fallback in getClusterVersion() similar to validateConnection() — if the V1 endpoint fails with 403, either:

  • Skip the version check and return a default/unknown version
  • Use a V2 endpoint to infer version info

Option B (documentation fix): Add DataExport to the README's required scopes list.

Option C (recommended — both): Fix the code to gracefully handle missing V1 scopes AND update the README to accurately document all required scopes (both V1 and V2).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions