Skip to content

Commit 8d5b8ea

Browse files
authored
Merge pull request #20 from datadog-labs/release/v0.7.21
Release v0.7.21
2 parents f9eb29b + 029f163 commit 8d5b8ea

5 files changed

Lines changed: 33 additions & 5 deletions

File tree

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ The agent has three tools:
5151
- `ddconfig` reports saved connection state; its `check` action probes the server without starting interactive sign-in, and its `switch` action moves the session to another saved connection, so the agent can compare orgs in one prompt.
5252
- `ddtoolsets` manages toolsets for the selected connection.
5353

54+
Prompts also carry the Datadog MCP Server's instructions for the selected organization, such as skill and access guidance. Pi connects at the start of a prompt to read them and leaves them out if the server can't be reached within a few seconds.
55+
5456
`/datadog setup` and `/datadog configure` without arguments open the same connection screen for compatibility. Their old site/scope arguments and the separate `ddsetup` tool have been removed. Sign-in and adding organizations are user-controlled through `/datadog`; the agent can only switch between connections you've already saved.
5557

5658
## Visualization panel (macOS preview)

‎datadog.ts‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ import { createDatadogProxy } from './tools/proxy.js';
1212
import { initVizRuntime } from './viz/index.js';
1313
import { makeConnectionBuilder } from '#shared/url';
1414

15-
const PLUGIN_VERSION = '0.7.20';
15+
const PLUGIN_VERSION = '0.7.21';
1616
const PLUGIN_ID = 'pi-plugin';
1717
const MCP_FILE = 'datadog.json';
1818
const MCP_ENABLED_TOOLSETS = 'core,visualizations';
1919
const SELECTION_ENTRY = 'datadog-selection';
2020
const ORGANIZATION_SECTION = 'datadog_organization';
21+
const SERVER_INSTRUCTIONS_SECTION = 'datadog_server_instructions';
22+
// Bounds how long a prompt waits on the first connection; a later prompt retries.
23+
const SERVER_INSTRUCTIONS_TIMEOUT_MS = 5_000;
2124

2225
const organizationNotice = async (connections: Connections): Promise<string | undefined> => {
2326
try {
@@ -29,6 +32,17 @@ const organizationNotice = async (connections: Connections): Promise<string | un
2932
}
3033
};
3134

35+
// The server returns caller-specific guidance (skills, access notes) only during the MCP handshake.
36+
const serverInstructions = async (connections: Connections): Promise<string | undefined> => {
37+
try {
38+
const { client } = await connections.connection(AbortSignal.timeout(SERVER_INSTRUCTIONS_TIMEOUT_MS));
39+
const instructions = await client.instructions();
40+
return instructions && `Instructions from the Datadog MCP Server, for the datadog tool:\n${instructions}`;
41+
} catch {
42+
return undefined;
43+
}
44+
};
45+
3246
export default function activate(pi: ExtensionAPI): void {
3347
const connections = new Connections({
3448
cwd: process.cwd(),
@@ -65,8 +79,12 @@ export default function activate(pi: ExtensionAPI): void {
6579
});
6680
// A prompt section, unlike a returned message, is only re-sent to the model when its text changes.
6781
pi.on('before_agent_start', async ({ systemPromptOptions: { sections } }) => {
68-
const notice = await organizationNotice(connections);
82+
const [notice, instructions] = await Promise.all([
83+
organizationNotice(connections),
84+
serverInstructions(connections),
85+
]);
6986
if (notice) sections[ORGANIZATION_SECTION] = notice;
87+
if (instructions) sections[SERVER_INSTRUCTIONS_SECTION] = instructions;
7088
});
7189
pi.registerTool(createDatadogProxy(deps, viz.subtools));
7290
pi.registerTool(createDdconfig(deps));

‎mcp-client.ts‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export type ConnectionClient = {
2020
readonly authMode: 'oauth' | 'apiKey';
2121
identity(signal?: AbortSignal): Promise<OrgIdentity>;
2222
listTools(signal?: AbortSignal): Promise<Tool[]>;
23+
// Caller-specific guidance the server returns during the MCP handshake.
24+
instructions(signal?: AbortSignal): Promise<string | undefined>;
2325
readResource(uri: string, signal?: AbortSignal): Promise<ReadResourceResult>;
2426
callTool(name: string, args: Record<string, unknown> | undefined, signal?: AbortSignal): Promise<CallToolResult>;
2527
close(): Promise<void>;
@@ -67,6 +69,9 @@ export const createConnectionClient = (
6769
assertOpen();
6870
const next = new Client({ name: 'datadog-pi-plugin', version });
6971
let wire = transport();
72+
// The SDK sends notifications/initialized without the caller's signal; closing the transport cancels it.
73+
const abort = () => void wire.close().catch(() => undefined);
74+
signal?.addEventListener('abort', abort, { once: true });
7075
try {
7176
try {
7277
await next.connect(wire, { signal });
@@ -92,6 +97,8 @@ export const createConnectionClient = (
9297
await next.close().catch(() => undefined);
9398
await wire.close().catch(() => undefined);
9499
throw error;
100+
} finally {
101+
signal?.removeEventListener('abort', abort);
95102
}
96103
};
97104
const ensure = async (signal?: AbortSignal): Promise<Client> => {
@@ -113,6 +120,7 @@ export const createConnectionClient = (
113120
authMode: auth.kind === 'oauth' ? 'oauth' : 'apiKey',
114121
identity: (signal) => run(async () => identity!, signal),
115122
listTools: (signal) => run(async (current) => (await current.listTools({}, { signal })).tools, signal),
123+
instructions: (signal) => run(async (current) => current.getInstructions(), signal),
116124
readResource: (uri, signal) => run((current) => current.readResource({ uri }, { signal }), signal),
117125
callTool: (name, args, signal) =>
118126
run(
@@ -132,4 +140,4 @@ export const createConnectionClient = (
132140

133141
export type AuthMode = 'oauth' | 'apiKey';
134142
export type McpCallToolArgs = Record<string, unknown> | undefined;
135-
export type McpClient = Omit<ConnectionClient, 'identity'>;
143+
export type McpClient = Omit<ConnectionClient, 'identity' | 'instructions'>;

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@datadog/pi-plugin",
3-
"version": "0.7.20",
3+
"version": "0.7.21",
44
"description": "Use Datadog directly in the Pi coding agent through a preconfigured Datadog MCP server. Query logs, metrics, traces, dashboards, and more through natural conversation.",
55
"main": "datadog.ts",
66
"type": "module",

‎viz/ddviz.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import WebKit
2727
struct Config {
2828

2929
static let appName = "ddviz"
30-
static let appVersion = "0.7.20"
30+
static let appVersion = "0.7.21"
3131
static let pluginId = "pi-plugin"
3232
static let defaultWindowWidth = 610.0
3333
static let defaultWindowHeight = 400.0

0 commit comments

Comments
 (0)