@stigmer/mcp-server 3.34.0 → 3.36.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.
Files changed (157) hide show
  1. package/cli/mcp-server-stigmer.d.ts.map +1 -1
  2. package/cli/mcp-server-stigmer.js +2 -2
  3. package/cli/mcp-server-stigmer.js.map +1 -1
  4. package/config.d.ts.map +1 -1
  5. package/config.js.map +1 -1
  6. package/domains/agentexecutions/approve.d.ts.map +1 -1
  7. package/domains/agentexecutions/approve.js.map +1 -1
  8. package/domains/agentexecutions/fetch.d.ts.map +1 -1
  9. package/domains/agentexecutions/fetch.js.map +1 -1
  10. package/domains/agentexecutions/run.d.ts.map +1 -1
  11. package/domains/agentexecutions/run.js.map +1 -1
  12. package/domains/agentexecutions/tools.d.ts.map +1 -1
  13. package/domains/agentexecutions/tools.js.map +1 -1
  14. package/domains/agents/apply.d.ts.map +1 -1
  15. package/domains/agents/apply.js.map +1 -1
  16. package/domains/agents/delete.d.ts.map +1 -1
  17. package/domains/agents/delete.js.map +1 -1
  18. package/domains/agents/fetch.d.ts.map +1 -1
  19. package/domains/agents/fetch.js.map +1 -1
  20. package/domains/agents/resources.d.ts.map +1 -1
  21. package/domains/agents/resources.js.map +1 -1
  22. package/domains/agents/tools.d.ts.map +1 -1
  23. package/domains/agents/tools.js.map +1 -1
  24. package/domains/apply-visibility.d.ts.map +1 -1
  25. package/domains/apply-visibility.js.map +1 -1
  26. package/domains/channels/calls.d.ts.map +1 -1
  27. package/domains/channels/calls.js.map +1 -1
  28. package/domains/channels/errors.d.ts.map +1 -1
  29. package/domains/channels/errors.js.map +1 -1
  30. package/domains/channels/tools.d.ts.map +1 -1
  31. package/domains/channels/tools.js.map +1 -1
  32. package/domains/client.d.ts.map +1 -1
  33. package/domains/client.js.map +1 -1
  34. package/domains/conversation/calls.d.ts.map +1 -1
  35. package/domains/conversation/calls.js.map +1 -1
  36. package/domains/conversation/errors.d.ts.map +1 -1
  37. package/domains/conversation/errors.js.map +1 -1
  38. package/domains/conversation/tools.d.ts.map +1 -1
  39. package/domains/conversation/tools.js.map +1 -1
  40. package/domains/environments/apply.d.ts.map +1 -1
  41. package/domains/environments/apply.js.map +1 -1
  42. package/domains/environments/delete.d.ts.map +1 -1
  43. package/domains/environments/delete.js.map +1 -1
  44. package/domains/environments/fetch.d.ts.map +1 -1
  45. package/domains/environments/fetch.js.map +1 -1
  46. package/domains/environments/resources.d.ts.map +1 -1
  47. package/domains/environments/resources.js.map +1 -1
  48. package/domains/environments/tools.d.ts.map +1 -1
  49. package/domains/environments/tools.js.map +1 -1
  50. package/domains/executions/cancel.d.ts.map +1 -1
  51. package/domains/executions/cancel.js.map +1 -1
  52. package/domains/executions/tools.d.ts.map +1 -1
  53. package/domains/executions/tools.js.map +1 -1
  54. package/domains/marshal.d.ts.map +1 -1
  55. package/domains/marshal.js.map +1 -1
  56. package/domains/mcpservers/apply.d.ts.map +1 -1
  57. package/domains/mcpservers/apply.js.map +1 -1
  58. package/domains/mcpservers/delete.d.ts.map +1 -1
  59. package/domains/mcpservers/delete.js.map +1 -1
  60. package/domains/mcpservers/fetch.d.ts.map +1 -1
  61. package/domains/mcpservers/fetch.js.map +1 -1
  62. package/domains/mcpservers/resources.d.ts.map +1 -1
  63. package/domains/mcpservers/resources.js.map +1 -1
  64. package/domains/mcpservers/tools.d.ts.map +1 -1
  65. package/domains/mcpservers/tools.js.map +1 -1
  66. package/domains/memory/calls.d.ts.map +1 -1
  67. package/domains/memory/calls.js.map +1 -1
  68. package/domains/memory/context.d.ts.map +1 -1
  69. package/domains/memory/context.js.map +1 -1
  70. package/domains/memory/errors.d.ts.map +1 -1
  71. package/domains/memory/errors.js.map +1 -1
  72. package/domains/memory/tools.d.ts.map +1 -1
  73. package/domains/memory/tools.js.map +1 -1
  74. package/domains/resourcehandler.d.ts.map +1 -1
  75. package/domains/resourcehandler.js.map +1 -1
  76. package/domains/resourceuri.d.ts.map +1 -1
  77. package/domains/resourceuri.js.map +1 -1
  78. package/domains/rpcerr.d.ts.map +1 -1
  79. package/domains/rpcerr.js.map +1 -1
  80. package/domains/search/tools.d.ts.map +1 -1
  81. package/domains/search/tools.js.map +1 -1
  82. package/domains/skills/delete.d.ts.map +1 -1
  83. package/domains/skills/delete.js.map +1 -1
  84. package/domains/skills/fetch.d.ts.map +1 -1
  85. package/domains/skills/fetch.js.map +1 -1
  86. package/domains/skills/resources.d.ts.map +1 -1
  87. package/domains/skills/resources.js.map +1 -1
  88. package/domains/skills/tools.d.ts.map +1 -1
  89. package/domains/skills/tools.js.map +1 -1
  90. package/domains/skills/versions.d.ts.map +1 -1
  91. package/domains/skills/versions.js.map +1 -1
  92. package/domains/toolresult.d.ts.map +1 -1
  93. package/domains/toolresult.js.map +1 -1
  94. package/domains/workflowexecutions/approvals.d.ts.map +1 -1
  95. package/domains/workflowexecutions/approvals.js.map +1 -1
  96. package/domains/workflowexecutions/run.d.ts.map +1 -1
  97. package/domains/workflowexecutions/run.js.map +1 -1
  98. package/domains/workflowexecutions/tools.d.ts.map +1 -1
  99. package/domains/workflowexecutions/tools.js.map +1 -1
  100. package/domains/workflows/apply.d.ts.map +1 -1
  101. package/domains/workflows/apply.js.map +1 -1
  102. package/domains/workflows/delete.d.ts.map +1 -1
  103. package/domains/workflows/delete.js.map +1 -1
  104. package/domains/workflows/fetch.d.ts.map +1 -1
  105. package/domains/workflows/fetch.js.map +1 -1
  106. package/domains/workflows/resources.d.ts.map +1 -1
  107. package/domains/workflows/resources.js.map +1 -1
  108. package/domains/workflows/taskkinds.d.ts.map +1 -1
  109. package/domains/workflows/taskkinds.js.map +1 -1
  110. package/domains/workflows/tools.d.ts.map +1 -1
  111. package/domains/workflows/tools.js.map +1 -1
  112. package/domains/workflows/validate.d.ts.map +1 -1
  113. package/domains/workflows/validate.js.map +1 -1
  114. package/domains/workflows/versions.d.ts.map +1 -1
  115. package/domains/workflows/versions.js.map +1 -1
  116. package/gen/agent.d.ts.map +1 -1
  117. package/gen/agent.js.map +1 -1
  118. package/gen/apply-runtime.d.ts.map +1 -1
  119. package/gen/apply-runtime.js.map +1 -1
  120. package/gen/environment.d.ts.map +1 -1
  121. package/gen/environment.js.map +1 -1
  122. package/gen/mcpserver.d.ts.map +1 -1
  123. package/gen/mcpserver.js.map +1 -1
  124. package/gen/workflow.d.ts.map +1 -1
  125. package/gen/workflow.js +2 -2
  126. package/gen/workflow.js.map +1 -1
  127. package/index.d.ts.map +1 -1
  128. package/index.js.map +1 -1
  129. package/logger.d.ts.map +1 -1
  130. package/logger.js.map +1 -1
  131. package/package.json +3 -3
  132. package/readiness.d.ts.map +1 -1
  133. package/readiness.js.map +1 -1
  134. package/server.d.ts.map +1 -1
  135. package/server.js.map +1 -1
  136. package/src/gen/workflow.ts +2 -2
  137. package/src/config.test.ts +0 -88
  138. package/src/domains/apply.integration.test.ts +0 -313
  139. package/src/domains/channels/channels.integration.test.ts +0 -272
  140. package/src/domains/channels/errors.test.ts +0 -52
  141. package/src/domains/conversation/conversation.integration.test.ts +0 -233
  142. package/src/domains/deletes.integration.test.ts +0 -147
  143. package/src/domains/executions.integration.test.ts +0 -376
  144. package/src/domains/memory/context.test.ts +0 -95
  145. package/src/domains/memory/errors.test.ts +0 -54
  146. package/src/domains/memory/memory.integration.test.ts +0 -253
  147. package/src/domains/reads.integration.test.ts +0 -163
  148. package/src/domains/resources.integration.test.ts +0 -157
  149. package/src/domains/resourceuri.test.ts +0 -104
  150. package/src/domains/rpcerr.test.ts +0 -62
  151. package/src/domains/search/search.integration.test.ts +0 -141
  152. package/src/domains/versions.integration.test.ts +0 -212
  153. package/src/domains/workflows/validate.integration.test.ts +0 -117
  154. package/src/domains/workflows/workflow-tools.integration.test.ts +0 -148
  155. package/src/http.integration.test.ts +0 -235
  156. package/src/readiness.test.ts +0 -90
  157. package/src/server.integration.test.ts +0 -82
@@ -1,233 +0,0 @@
1
- // In-process integration test for the conversation roster (the
2
- // channels.integration.test.ts pattern: real Connect backend with a
3
- // stubbed conversation service, real MCP client over an in-memory
4
- // transport).
5
- //
6
- // Verifies the DD-008 D-b / A14 / A15 contract surface:
7
- // - the conversation-only roster is exactly escalate_to_human with a
8
- // single `reason` argument (agent audience — identity is
9
- // server-derived, so nothing else exists to send);
10
- // - the success answer is the A15 fixed copy, never the RPC's
11
- // ChannelConversation row, and claims nothing the platform cannot
12
- // keep (no console claim until the T04+ surface renders attention);
13
- // - the conversation-own error mapper passes domain messages verbatim
14
- // as {error, code} JSON — including NOT_FOUND, this domain's
15
- // deliberate addition — while transport errors delegate to the
16
- // shared classifier;
17
- // - the zod bounds mirror the protovalidate constraints, refusing an
18
- // empty or over-budget reason before any RPC.
19
-
20
- import { create } from "@bufbuild/protobuf";
21
- import { Code, ConnectError, type ConnectRouter } from "@connectrpc/connect";
22
- import { connectNodeAdapter } from "@connectrpc/connect-node";
23
- import {
24
- createServer as createHttp2Server,
25
- type Http2Server,
26
- type ServerHttp2Session,
27
- } from "node:http2";
28
- import type { AddressInfo } from "node:net";
29
-
30
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
31
- import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
32
- import { ChannelConversationCommandController } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/conversation_command_pb";
33
- import {
34
- ChannelConversationSchema,
35
- type EscalateConversationInput,
36
- } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/conversation_io_pb";
37
- import { afterAll, beforeAll, describe, expect, it } from "vitest";
38
-
39
- import { configureLogger } from "../../logger";
40
- import { CONVERSATION_ROUTE, createConversationServer } from "../../server";
41
-
42
- configureLogger({ level: "error", format: "text" });
43
-
44
- let backend: Http2Server;
45
- let client: Client;
46
- const openSessions = new Set<ServerHttp2Session>();
47
-
48
- /** The next stubbed outcome; tests set this. */
49
- let escalateResponse: () => ReturnType<typeof create<typeof ChannelConversationSchema>>;
50
-
51
- /** Requests the stub captured (object property for closure narrowing). */
52
- const captured: { escalate?: EscalateConversationInput } = {};
53
-
54
- interface ToolResult {
55
- content: Array<{ type: string; text?: string }>;
56
- isError?: boolean;
57
- }
58
-
59
- async function escalate(args: Record<string, unknown>): Promise<ToolResult> {
60
- return (await client.callTool({
61
- name: "escalate_to_human",
62
- arguments: args,
63
- })) as ToolResult;
64
- }
65
-
66
- beforeAll(async () => {
67
- const routes = (router: ConnectRouter) => {
68
- router.service(ChannelConversationCommandController, {
69
- escalate: (req) => {
70
- captured.escalate = req;
71
- return escalateResponse();
72
- },
73
- });
74
- };
75
- backend = createHttp2Server(connectNodeAdapter({ routes }));
76
- backend.on("session", (session) => {
77
- openSessions.add(session);
78
- session.on("close", () => openSessions.delete(session));
79
- });
80
- await new Promise<void>((resolve) => backend.listen(0, "127.0.0.1", resolve));
81
- const port = (backend.address() as AddressInfo).port;
82
-
83
- const mcp = createConversationServer({ serverAddress: `127.0.0.1:${port}`, apiKey: "" });
84
- const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
85
- client = new Client({ name: "conversation-integration", version: "test" });
86
- await Promise.all([mcp.connect(serverTransport), client.connect(clientTransport)]);
87
- });
88
-
89
- afterAll(async () => {
90
- await client?.close();
91
- for (const session of openSessions) session.destroy();
92
- await new Promise<void>((resolve) => backend.close(() => resolve()));
93
- });
94
-
95
- describe("conversation roster (DD-008 D-c / A14)", () => {
96
- it("exposes exactly escalate_to_human with a single reason argument", async () => {
97
- const { tools } = await client.listTools();
98
- expect(tools.map((t) => t.name)).toEqual(["escalate_to_human"]);
99
-
100
- // The conversation identity is server-derived from the session
101
- // credential's channel labels (the DD-003 identity doctrine), so
102
- // reason is the ONLY argument — a channel or conversation id here
103
- // would be a caller-supplied identity the reach must never trust.
104
- const properties = (tools[0].inputSchema as { properties?: Record<string, unknown> })
105
- .properties;
106
- expect(Object.keys(properties ?? {})).toEqual(["reason"]);
107
- });
108
-
109
- it("pins the cross-repo route string (the TOOL_CALL_LIMIT precedent)", () => {
110
- // The runner's conversation-attachment.ts builds the URL
111
- // independently (shared/conversation-attachment.ts and its route
112
- // pin); a drift here strands every synthesized attachment on a 404.
113
- expect(CONVERSATION_ROUTE).toBe("/conversation");
114
- });
115
- });
116
-
117
- describe("the success answer is the A15 copy, not the row", () => {
118
- it("sends the reason verbatim and answers with fixed copy", async () => {
119
- escalateResponse = () =>
120
- create(ChannelConversationSchema, {
121
- agentChannelId: "agch_1",
122
- conversationKey: "919000000001",
123
- needsAttention: true,
124
- attentionReason: "customer wants a refund decision",
125
- });
126
- captured.escalate = undefined;
127
-
128
- const result = await escalate({ reason: "customer wants a refund decision" });
129
-
130
- expect(result.isError).toBeFalsy();
131
- const req = captured.escalate as EscalateConversationInput | undefined;
132
- expect(req?.reason).toBe("customer wants a refund decision");
133
-
134
- const text = result.content[0]?.text ?? "";
135
- expect(text).toContain("recorded on this conversation");
136
- // A15: the answer instructs against the promise at the moment of
137
- // temptation — the model's next message to the customer.
138
- expect(text).toContain("do not");
139
- // The row must never leak back: its control state and conversation
140
- // key are internal, and reflecting them invites the model to
141
- // narrate platform state to the customer.
142
- expect(text).not.toContain("919000000001");
143
- expect(text).not.toContain("needs_attention");
144
- // No console surface renders attention yet (T04+); the copy must
145
- // not claim one. Delete this pin when the Conversations surface
146
- // ships and the copy gains the claim.
147
- expect(text.toLowerCase()).not.toContain("console");
148
- });
149
- });
150
-
151
- describe("zod bounds mirror the protovalidate constraints", () => {
152
- it("refuses an empty and an over-budget reason before any RPC", async () => {
153
- captured.escalate = undefined;
154
-
155
- const empty = await escalate({ reason: "" });
156
- expect(empty.isError).toBe(true);
157
-
158
- const overBudget = await escalate({ reason: "x".repeat(1025) });
159
- expect(overBudget.isError).toBe(true);
160
-
161
- expect(captured.escalate).toBeUndefined();
162
- });
163
- });
164
-
165
- describe("conversation error mapper", () => {
166
- it("passes a reach denial through verbatim — never the shared rewrite", async () => {
167
- escalateResponse = () => {
168
- throw new ConnectError(
169
- "escalate is agent-audience only: it requires a session-scoped runner credential",
170
- Code.PermissionDenied,
171
- );
172
- };
173
-
174
- const result = await escalate({ reason: "needs a human" });
175
-
176
- expect(result.isError).toBe(true);
177
- expect(JSON.parse(result.content[0]?.text ?? "{}")).toEqual({
178
- error: "escalate is agent-audience only: it requires a session-scoped runner credential",
179
- code: "PERMISSION_DENIED",
180
- });
181
- });
182
-
183
- it("passes the OSS refusal through verbatim as FAILED_PRECONDITION", async () => {
184
- escalateResponse = () => {
185
- throw new ConnectError(
186
- "conversation participation requires Stigmer Cloud",
187
- Code.FailedPrecondition,
188
- );
189
- };
190
-
191
- const result = await escalate({ reason: "needs a human" });
192
-
193
- expect(result.isError).toBe(true);
194
- expect(JSON.parse(result.content[0]?.text ?? "{}")).toEqual({
195
- error: "conversation participation requires Stigmer Cloud",
196
- code: "FAILED_PRECONDITION",
197
- });
198
- });
199
-
200
- it("passes NOT_FOUND through verbatim — this domain's deliberate addition", async () => {
201
- // The shared classifier rewrites NotFound into "Verify the org and
202
- // slug are correct" — advice naming arguments escalate does not
203
- // take. The domain set includes NotFound so the handler's honest
204
- // answer reaches the model.
205
- escalateResponse = () => {
206
- throw new ConnectError(
207
- "no conversation with this key exists on channel agch_1",
208
- Code.NotFound,
209
- );
210
- };
211
-
212
- const result = await escalate({ reason: "needs a human" });
213
-
214
- expect(result.isError).toBe(true);
215
- expect(JSON.parse(result.content[0]?.text ?? "{}")).toEqual({
216
- error: "no conversation with this key exists on channel agch_1",
217
- code: "NOT_FOUND",
218
- });
219
- });
220
-
221
- it("delegates transport codes to the shared classifier", async () => {
222
- escalateResponse = () => {
223
- throw new ConnectError("upstream down", Code.Unavailable);
224
- };
225
-
226
- const result = await escalate({ reason: "needs a human" });
227
-
228
- expect(result.isError).toBe(true);
229
- expect(result.content[0]?.text).toBe(
230
- "Stigmer server is unavailable. Ensure it is running and reachable.",
231
- );
232
- });
233
- });
@@ -1,147 +0,0 @@
1
- // In-process integration test for the delete tools. Verifies the two-step
2
- // resolve→delete flow forwards the resolved id into the correct per-domain
3
- // delete-input shape: typed {value} for agent/skill/workflow, and
4
- // ApiResourceDeleteInput {resource_id} for mcp_server and environment.
5
-
6
- import { create, toJson } from "@bufbuild/protobuf";
7
- import type { ConnectRouter } from "@connectrpc/connect";
8
- import { connectNodeAdapter } from "@connectrpc/connect-node";
9
- import {
10
- createServer as createHttp2Server,
11
- type Http2Server,
12
- type ServerHttp2Session,
13
- } from "node:http2";
14
- import type { AddressInfo } from "node:net";
15
-
16
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
17
- import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
18
- import { AgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
19
- import { AgentCommandController } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/command_pb";
20
- import { AgentQueryController } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/query_pb";
21
- import { EnvironmentSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
22
- import { EnvironmentCommandController } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/command_pb";
23
- import { EnvironmentQueryController } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/query_pb";
24
- import { McpServerSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
25
- import { McpServerCommandController } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/command_pb";
26
- import { McpServerQueryController } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/query_pb";
27
- import { afterAll, beforeAll, describe, expect, it } from "vitest";
28
-
29
- import { configureLogger } from "../logger";
30
- import { createServer } from "../server";
31
-
32
- configureLogger({ level: "error", format: "text" });
33
-
34
- const resolvedAgent = create(AgentSchema, {
35
- apiVersion: "v1",
36
- kind: "agent",
37
- metadata: { name: "Code Reviewer", slug: "code-reviewer", org: "acme", id: "agt-123" },
38
- });
39
- const resolvedMcpServer = create(McpServerSchema, {
40
- apiVersion: "v1",
41
- kind: "mcp_server",
42
- metadata: { name: "GitHub", slug: "github", org: "acme", id: "mcp-456" },
43
- });
44
- const resolvedEnvironment = create(EnvironmentSchema, {
45
- apiVersion: "v1",
46
- kind: "environment",
47
- metadata: { name: "GitHub Creds", slug: "github-creds", org: "acme", id: "env-789" },
48
- });
49
-
50
- let backend: Http2Server;
51
- let client: Client;
52
- let deletedAgentId: string | undefined;
53
- let deletedMcpResourceId: string | undefined;
54
- let deletedEnvironmentResourceId: string | undefined;
55
- const openSessions = new Set<ServerHttp2Session>();
56
-
57
- interface ToolResult {
58
- content: Array<{ type: string; text?: string }>;
59
- isError?: boolean;
60
- }
61
-
62
- async function callTool(name: string, args: Record<string, unknown>): Promise<ToolResult> {
63
- return (await client.callTool({ name, arguments: args })) as ToolResult;
64
- }
65
-
66
- beforeAll(async () => {
67
- const routes = (router: ConnectRouter) => {
68
- router.service(AgentQueryController, { getByReference: () => resolvedAgent });
69
- router.service(AgentCommandController, {
70
- delete: (req) => {
71
- deletedAgentId = req.value;
72
- return resolvedAgent;
73
- },
74
- });
75
- router.service(McpServerQueryController, { getByReference: () => resolvedMcpServer });
76
- router.service(McpServerCommandController, {
77
- delete: (req) => {
78
- deletedMcpResourceId = req.resourceId;
79
- return resolvedMcpServer;
80
- },
81
- });
82
- router.service(EnvironmentQueryController, { getByReference: () => resolvedEnvironment });
83
- router.service(EnvironmentCommandController, {
84
- delete: (req) => {
85
- deletedEnvironmentResourceId = req.resourceId;
86
- return resolvedEnvironment;
87
- },
88
- });
89
- };
90
- backend = createHttp2Server(connectNodeAdapter({ routes }));
91
- backend.on("session", (session) => {
92
- openSessions.add(session);
93
- session.on("close", () => openSessions.delete(session));
94
- });
95
- await new Promise<void>((resolve) => backend.listen(0, "127.0.0.1", resolve));
96
- const port = (backend.address() as AddressInfo).port;
97
-
98
- const mcp = createServer({ serverAddress: `127.0.0.1:${port}`, apiKey: "" });
99
- const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
100
- client = new Client({ name: "deletes-integration", version: "test" });
101
- await Promise.all([mcp.connect(serverTransport), client.connect(clientTransport)]);
102
- });
103
-
104
- afterAll(async () => {
105
- await client?.close();
106
- for (const session of openSessions) session.destroy();
107
- await new Promise<void>((resolve) => backend.close(() => resolve()));
108
- });
109
-
110
- describe("delete tools integration", () => {
111
- it("advertises every delete tool", async () => {
112
- const { tools } = await client.listTools();
113
- expect(tools.map((t) => t.name)).toEqual(
114
- expect.arrayContaining([
115
- "delete_agent",
116
- "delete_skill",
117
- "delete_workflow",
118
- "delete_mcp_server",
119
- "delete_environment",
120
- ]),
121
- );
122
- });
123
-
124
- it("delete_agent resolves the id then deletes via the typed AgentId", async () => {
125
- const result = await callTool("delete_agent", { org: "acme", slug: "code-reviewer" });
126
- expect(result.isError).toBeFalsy();
127
- expect(deletedAgentId).toBe("agt-123");
128
- expect(JSON.parse(result.content[0]?.text ?? "{}")).toEqual(
129
- toJson(AgentSchema, resolvedAgent, { useProtoFieldName: true }),
130
- );
131
- });
132
-
133
- it("delete_mcp_server resolves the id then deletes via ApiResourceDeleteInput", async () => {
134
- const result = await callTool("delete_mcp_server", { org: "acme", slug: "github" });
135
- expect(result.isError).toBeFalsy();
136
- expect(deletedMcpResourceId).toBe("mcp-456");
137
- expect(JSON.parse(result.content[0]?.text ?? "{}")).toEqual(
138
- toJson(McpServerSchema, resolvedMcpServer, { useProtoFieldName: true }),
139
- );
140
- });
141
-
142
- it("delete_environment resolves the id then deletes via ApiResourceDeleteInput", async () => {
143
- const result = await callTool("delete_environment", { org: "acme", slug: "github-creds" });
144
- expect(result.isError).toBeFalsy();
145
- expect(deletedEnvironmentResourceId).toBe("env-789");
146
- });
147
- });