dtctl

dtctl

Provides an MCP server to interact with Dynatrace platform tools, including DQL queries, documents, workflows, SLOs, settings, and entities, enabling management through natural language.

Category
访问服务器

README

dtctl for VS Code

Zero-install Dynatrace Platform tooling. Everything dtctl does — DQL, documents, workflows, SLOs, settings, entities — reimplemented in pure TypeScript and shipped inside the extension. No CLI to download, no binary to unquarantine, no admin rights, no OS permission prompts.

  • 16 tools exposed to GitHub Copilot Chat (VS Code Language Model Tools API)
  • The same 16 tools exposed to Claude / any MCP client via a bundled stdio MCP server that VS Code auto-discovers — zero config
  • DQL query runner webview (table + JSON + CSV export), tenant explorer tree, status-bar tenant indicator, and command-palette verbs
  • Credentials never touch settings.json and never appear in logs. Browser-login tokens are stored as 0600 files in the extension's own storage directory (not the OS keychain, so nothing prompts for a keychain password); API tokens and OAuth client secrets continue to use VS Code SecretStorage

Install (locked-down managed machine)

You need VS Code and nothing else. No admin rights are required at any step.

Option A — sideload the VSIX (recommended for restricted environments)

  1. Copy dtctl-vscode-0.2.0.vsix to the machine (email, share drive, USB — it is a single file, ~2 MB, no installer).
  2. In VS Code: Extensions view → overflow menu → Install from VSIX… → pick the file. Or from a terminal: code --install-extension dtctl-vscode-0.2.0.vsix
  3. Reload the window when prompted. Done.

There is no post-install step. Nothing is written outside VS Code's own extension folder in your user profile, no service is registered, and nothing asks for elevation, Gatekeeper approval, or SmartScreen approval — because no native binary ships in the package.

Option B — Marketplace

Search the Extensions view for dtctl — Dynatrace Platform Tools and click Install.

Where it runs

Environment Extension UI Copilot Chat tools MCP server
VS Code desktop (Win/macOS/Linux) yes yes yes
GitHub Codespaces / dev containers yes yes yes
Remote-SSH / WSL yes yes yes
vscode.dev / github.dev (browser) yes yes no (browser hosts cannot spawn a child process)

The browser build is the same TypeScript, compiled to a web worker bundle. Only the stdio MCP server — which by definition needs a process — is unavailable there.


Login

Browser login (recommended)

Ctrl/Cmd+Shift+Pdtctl: Login (browser)

  1. Enter your Dynatrace environment URL (https://<id>.apps.dynatrace.com) and a profile name.
  2. VS Code opens your browser at the Dynatrace sign-in page. Sign in as you normally would — SSO, MFA and all.
  3. The tab shows "You can close this tab" and the profile appears in the status bar. Done.

No admin-created OAuth client is needed. Browser login uses Dynatrace's own first-party public OAuth clients (the same ones the dtctl CLI uses), with Authorization Code + PKCE (S256). There is no client secret anywhere — not in the extension, not in your settings, not on disk. You do not have to ask a tenant admin to mint a client ID/secret pair before you can use the extension.

Audit-log note. Because browser login reuses the dtctl CLI's public OAuth client, OAuth grants and token activity for this extension appear in Dynatrace audit logs attributed to dt0s12.dtctl-prod (the dtctl CLI), not to this extension by name. The signed-in user is recorded correctly — everything runs with that user's own permissions — but the extension has no separate application identity, so it cannot be audited or revoked independently of the dtctl CLI. If your security team needs the extension to be distinguishable, it needs its own registered OAuth client; set dtctl.oauthClientId once you have one.

The environment you sign in to is detected from the URL you type (apps.dynatrace.com → prod, dev.apps.dynatracelabs.com → dev, sprint.apps.dynatracelabs.com → sprint/hardening), and the URL is sent as the OAuth resource parameter so the issued token is bound to that tenant.

The loopback callback port

Sign-in completes by redirecting to a local listener on http://localhost:<port>/auth/login, bound explicitly to 127.0.0.1.

The extension tries port 3232 first — the port dtctl uses — and falls back to 3233/3234/3235 and then any free port if 3232 is busy. The Dynatrace OAuth clients accept a loopback redirect on any port, so a port conflict is not a failure mode; the actually-bound port is what goes into redirect_uri. If your machine blocks local loopback sockets entirely (some endpoint-protection policies do), login fails with a message saying exactly that.

Login times out after 5 minutes, and the listener is always closed afterwards — a failed or cancelled login never leaves a port bound.

Scopes (read-only by default)

Browser login requests dtctl's read-only scope set by default. Write scopes are opt-in via dtctl.loginScopeLevel, which mirrors dtctl's safety levels:

dtctl.loginScopeLevel Requests
readonly (default) 40 read scopes
readwrite-mine read + write/delete of resources you own
readwrite-all read + write/delete of all resources
dangerously-unrestricted every scope dtctl knows about

openid and offline_access are always requested — offline_access is what returns a refresh token. Access tokens are short-lived (~10 minutes) and are refreshed transparently in the background; you are only asked to sign in again if the refresh itself fails. Changing the setting takes effect on the next login. Write tools remain independently gated by dtctl.allowWriteTools.

dtctl.oauthClientId overrides the built-in client ID if your organisation issues a dedicated public OAuth client for this extension.

Where browser-login tokens are stored

Interactive-login tokens are written to disk, not the OS keychain:

<VS Code user data>/User/globalStorage/dtctl-tools.dtctl-vscode/oauth-tokens/<profile>.json

VS Code owns that directory (context.globalStorageUri) and resolves it to the right per-user location on Windows, macOS and Linux. It is outside your repo and workspace, so token files can never be committed or packaged into the VSIX.

This is deliberate. VS Code's SecretStorage is backed by the OS credential vault (macOS Keychain / Windows Credential Manager / libsecret), which can prompt for a password and is frequently unavailable on managed machines. dtctl has the same escape hatch (DTCTL_TOKEN_STORAGE=file).

Security properties:

  • Token files are created and chmoded 0600 (owner read/write only). On POSIX that is real protection. On Windows the POSIX mode is largely a no-op — the practical protection there is that the file lives under your own user profile directory, which is ACL'd to you. We do not claim more than that.
  • Writes are atomic: a temp file in the same directory is renamed over the target, so a crash mid-write cannot corrupt or truncate an existing token file, and no partial token file is left behind.
  • dtctl: Logout (browser login) deletes the token file from disk — it does not merely clear an in-memory cache.
  • Tokens are never logged. All diagnostic output goes through redact().

Keeping OAuth constants in sync with dtctl

The SSO endpoints, client IDs and callback contract are not hand-maintained. They are generated into src/kernel/dtctl-oauth-constants.ts from dtctl's own sdk/session/oauth_flow.go:

npm run sync:dtctl             # fetch upstream and regenerate the constants
npm run sync:dtctl -- --check  # exit 1 if the checked-in constants are stale

test/contract/dtctl-drift.contract.test.ts runs as part of npm test and fails with a per-constant diff if Dynatrace changes any of these upstream:

dtctl OAuth constants have CHANGED UPSTREAM.

  prod.tokenUrl
    checked-in: https://token.dynatrace.com/sso/oauth2/token
    upstream:   https://token.dynatrace.example/sso/oauth2/token

Fix: run `npm run sync:dtctl` to regenerate …

It is network-optional: with no network access it skips with an explanatory message rather than failing, so offline development and egress-restricted CI are unaffected.

This is build-time only. The extension never fetches dtctl source, and never fetches OIDC discovery, at run time — the login path resolves its endpoints entirely offline from the compiled-in constants. There is no code path by which a change upstream could redirect a live OAuth flow without a human running the sync and reviewing the diff.

Token-based profiles (unchanged)

dtctl: Add Tenant Profile still supports OAuth client credentials and classic dt0c01.… API tokens. Those credentials continue to live in VS Code SecretStorage exactly as before.


First-run setup (about 60 seconds)

For most users dtctl: Login (browser) above is the faster path — it needs no admin-created OAuth client. Use the flow below when you already have a client ID/secret or a classic API token.

  1. Ctrl/Cmd+Shift+Pdtctl: Add Tenant Profile
  2. Enter a profile name (e.g. prod), your tenant URL (https://<id>.apps.dynatrace.com), and pick the auth type:
    • OAuth client credentials — enter client ID, optional scopes, then the client secret
    • Classic API token — paste the dt0c01.… token
  3. The credential is stored with vscode.SecretStorage (OS keychain / Keychain Access / libsecret / Credential Manager, managed entirely by VS Code). The extension never writes it to a settings file, workspace file, log, or the VSIX.

Add as many profiles as you have tenants; the status bar shows the active one and clicking it switches profiles. dtctl.defaultProfile sets the startup profile.

Required permissions on the tenant

Read-only usage needs the standard read scopes (storage:*:read, document:documents:read, automation:workflows:read, settings:objects:read, environment-api:entities:read). Write verbs additionally need document:documents:write and the relevant write scopes.


Using it

Command palette

Command What it does
dtctl: Login (browser) browser sign-in with PKCE — no OAuth client needed
dtctl: Logout (browser login) deletes the stored tokens from disk
dtctl: Add / Switch / Remove Tenant Profile multi-tenant profile management
dtctl: Open DQL Query Runner webview with table/JSON views and CSV export
dtctl: Run DQL Query runs the current editor selection as DQL
dtctl: Export Query Results as CSV opens the last result set as a CSV document
dtctl: Show Current User / List Profiles whoami / contexts
dtctl: Find Resource / Get Resource by ID resource browse and fetch
dtctl: Apply Resource from File upsert the open JSON document (write-gated)
dtctl: Refresh Explorer reload the tenant tree
dtctl: Copy MCP Server Config config snippet for an external MCP client

Tenant explorer

The Dynatrace Tenants view in the Explorer sidebar lists profiles → resource types → live resources. Clicking a resource fetches and opens it as JSON.

Write safety

All write and destructive verbs are disabled by default. Set dtctl.allowWriteTools: true to enable them. Even then, destructive tools require an explicit confirm: true argument, agents see a confirmation dialog before execution, and the MCP server does not advertise write tools at all while the setting is off.


Agent access

See docs/SE-ONE-PAGER.md for the customer-facing enablement page. In short:

  • GitHub Copilot Chat — tools register on activation. Type #dtctl_query (or any other tool name) in chat, or just ask a question and let the agent pick.
  • Claude / MCP clients in VS Code — the extension registers an MCP server definition provider, so the server appears automatically with your active profile's credentials injected at start time. Nothing to paste, nothing to configure.
  • Standalone MCP clients — run dtctl: Copy MCP Server Config and paste the snippet into your client's config, then substitute your own token.

Tool surface (16)

Read tier — always available: dtctl_query, dtctl_verify, dtctl_get, dtctl_describe, dtctl_history, dtctl_find, dtctl_logs, dtctl_whoami, dtctl_contexts, dtctl_commands.

Write tier — requires dtctl.allowWriteTools: dtctl_apply, dtctl_share, dtctl_unshare.

Destructive tier — requires dtctl.allowWriteTools and confirm: true: dtctl_delete, dtctl_exec, dtctl_restore.

The registry in src/kernel/tools/index.ts is the single source of truth: the package.json contributions, the MCP tools/list payload, and the runtime handlers are all generated from or driven by it, and npm run gen:contributions -- --check fails the build if they drift.


Architecture

src/kernel/          pure TypeScript, zero vscode imports, zero native code
  auth.ts            OAuth client-credentials + classic token, cache/refresh/retry
  transport.ts       Live / Replay / Record HTTP transports
  dql.ts             DQL execute + poll + paging + CSV
  api/               Platform (gen3) and Classic API clients
  tools/             the tool registry and handlers
src/adapters/
  shared.ts          one executor -> byte-identical envelopes on every surface
  ui/core.ts  ui.ts  tree view, DQL webview, status bar, commands
  lm/core.ts  lm.ts  vscode.lm.registerTool  (Copilot Chat)
  mcp/core.ts mcp.ts vscode.lm.registerMcpServerDefinitionProvider (Claude/MCP)
src/mcp/server.ts    bundled stdio MCP server -> dist/mcp-server.js

Why no binary. A per-platform Go binary would need chmod +x, survive macOS Gatekeeper quarantine and Windows SmartScreen, and would not run in vscode.dev or a browser Codespace at all. Reimplementing the surface over fetch removes every one of those failure modes; the tradeoff is that parity with the Go CLI is maintained by hand (the registry + contract tests are how that is enforced). No fallback binary ships in this VSIX.


Development

npm ci
npm run build          # gen contributions + strict tsc + esbuild (3 bundles)
npm run test           # unit + contract + end-to-end MCP smoke
npm run package        # produces dtctl-vscode-<version>.vsix

npm run test:smoke stands up a fake tenant, spawns the bundled dist/mcp-server.js as a real child process, and drives a real MCP JSON-RPC conversation (initialize → tools/list → tools/call) against it.

License

Apache-2.0.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选