macro-agent 0.0.13 → 0.0.15

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 (143) hide show
  1. package/.claude/settings.local.json +59 -0
  2. package/dist/agent/agent-manager.d.ts.map +1 -1
  3. package/dist/agent/agent-manager.js +10 -4
  4. package/dist/agent/agent-manager.js.map +1 -1
  5. package/dist/cli/acp.d.ts +6 -0
  6. package/dist/cli/acp.d.ts.map +1 -1
  7. package/dist/cli/acp.js +16 -2
  8. package/dist/cli/acp.js.map +1 -1
  9. package/dist/map/adapter/index.d.ts +1 -1
  10. package/dist/map/adapter/index.d.ts.map +1 -1
  11. package/dist/map/adapter/index.js +1 -1
  12. package/dist/map/adapter/index.js.map +1 -1
  13. package/dist/map/utils/address-translation.d.ts +99 -0
  14. package/dist/map/utils/address-translation.d.ts.map +1 -0
  15. package/dist/map/utils/address-translation.js +285 -0
  16. package/dist/map/utils/address-translation.js.map +1 -0
  17. package/dist/map/utils/index.d.ts +7 -0
  18. package/dist/map/utils/index.d.ts.map +1 -0
  19. package/dist/map/utils/index.js +7 -0
  20. package/dist/map/utils/index.js.map +1 -0
  21. package/dist/server/combined-server.d.ts.map +1 -1
  22. package/dist/server/combined-server.js +8 -1
  23. package/dist/server/combined-server.js.map +1 -1
  24. package/dist/store/event-store.js +9 -2
  25. package/dist/store/event-store.js.map +1 -1
  26. package/dist/store/types/agents.d.ts +2 -0
  27. package/dist/store/types/agents.d.ts.map +1 -1
  28. package/package.json +4 -4
  29. package/references/acp-factory-ref/CHANGELOG.md +33 -0
  30. package/references/acp-factory-ref/LICENSE +21 -0
  31. package/references/acp-factory-ref/README.md +341 -0
  32. package/references/acp-factory-ref/package-lock.json +3102 -0
  33. package/references/acp-factory-ref/package.json +96 -0
  34. package/references/acp-factory-ref/python/CHANGELOG.md +33 -0
  35. package/references/acp-factory-ref/python/LICENSE +21 -0
  36. package/references/acp-factory-ref/python/Makefile +57 -0
  37. package/references/acp-factory-ref/python/README.md +253 -0
  38. package/references/acp-factory-ref/python/pyproject.toml +73 -0
  39. package/references/acp-factory-ref/python/tests/__init__.py +0 -0
  40. package/references/acp-factory-ref/python/tests/e2e/__init__.py +1 -0
  41. package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +349 -0
  42. package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +165 -0
  43. package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +296 -0
  44. package/references/acp-factory-ref/python/tests/test_client_handler.py +543 -0
  45. package/references/acp-factory-ref/python/tests/test_pushable.py +199 -0
  46. package/references/claude-code-acp/.github/workflows/ci.yml +45 -0
  47. package/references/claude-code-acp/.github/workflows/publish.yml +34 -0
  48. package/references/claude-code-acp/.prettierrc.json +4 -0
  49. package/references/claude-code-acp/CHANGELOG.md +249 -0
  50. package/references/claude-code-acp/LICENSE +222 -0
  51. package/references/claude-code-acp/README.md +53 -0
  52. package/references/claude-code-acp/docs/RELEASES.md +24 -0
  53. package/references/claude-code-acp/eslint.config.js +48 -0
  54. package/references/claude-code-acp/package-lock.json +4570 -0
  55. package/references/claude-code-acp/package.json +88 -0
  56. package/references/claude-code-acp/scripts/release.sh +119 -0
  57. package/references/claude-code-acp/src/acp-agent.ts +2079 -0
  58. package/references/claude-code-acp/src/index.ts +26 -0
  59. package/references/claude-code-acp/src/lib.ts +38 -0
  60. package/references/claude-code-acp/src/mcp-server.ts +911 -0
  61. package/references/claude-code-acp/src/settings.ts +522 -0
  62. package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +5 -0
  63. package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +6 -0
  64. package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +479 -0
  65. package/references/claude-code-acp/src/tests/acp-agent.test.ts +1502 -0
  66. package/references/claude-code-acp/src/tests/extract-lines.test.ts +103 -0
  67. package/references/claude-code-acp/src/tests/fork-session.test.ts +335 -0
  68. package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +334 -0
  69. package/references/claude-code-acp/src/tests/settings.test.ts +617 -0
  70. package/references/claude-code-acp/src/tests/skills-options.test.ts +187 -0
  71. package/references/claude-code-acp/src/tests/tools.test.ts +318 -0
  72. package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +558 -0
  73. package/references/claude-code-acp/src/tools.ts +819 -0
  74. package/references/claude-code-acp/src/utils.ts +171 -0
  75. package/references/claude-code-acp/tsconfig.json +18 -0
  76. package/references/claude-code-acp/vitest.config.ts +19 -0
  77. package/references/multi-agent-protocol/.sudocode/issues.jsonl +111 -0
  78. package/references/multi-agent-protocol/.sudocode/specs.jsonl +13 -0
  79. package/references/multi-agent-protocol/LICENSE +21 -0
  80. package/references/multi-agent-protocol/README.md +113 -0
  81. package/references/multi-agent-protocol/docs/00-design-specification.md +496 -0
  82. package/references/multi-agent-protocol/docs/01-open-questions.md +1050 -0
  83. package/references/multi-agent-protocol/docs/02-wire-protocol.md +296 -0
  84. package/references/multi-agent-protocol/docs/03-streaming-semantics.md +252 -0
  85. package/references/multi-agent-protocol/docs/04-error-handling.md +231 -0
  86. package/references/multi-agent-protocol/docs/05-connection-model.md +244 -0
  87. package/references/multi-agent-protocol/docs/06-visibility-permissions.md +243 -0
  88. package/references/multi-agent-protocol/docs/07-federation.md +259 -0
  89. package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +253 -0
  90. package/references/multi-agent-protocol/docs/09-authentication.md +680 -0
  91. package/references/multi-agent-protocol/docs/10-mail-protocol.md +553 -0
  92. package/references/multi-agent-protocol/docs/agent-iam-integration.md +877 -0
  93. package/references/multi-agent-protocol/docs/agentic-mesh-integration-draft.md +459 -0
  94. package/references/multi-agent-protocol/docs/git-transport-draft.md +251 -0
  95. package/references/multi-agent-protocol/docs-site/Gemfile +22 -0
  96. package/references/multi-agent-protocol/docs-site/README.md +82 -0
  97. package/references/multi-agent-protocol/docs-site/_config.yml +91 -0
  98. package/references/multi-agent-protocol/docs-site/_includes/head_custom.html +20 -0
  99. package/references/multi-agent-protocol/docs-site/_sass/color_schemes/map.scss +42 -0
  100. package/references/multi-agent-protocol/docs-site/_sass/custom/custom.scss +34 -0
  101. package/references/multi-agent-protocol/docs-site/examples/full-integration.md +510 -0
  102. package/references/multi-agent-protocol/docs-site/examples/index.md +138 -0
  103. package/references/multi-agent-protocol/docs-site/examples/simple-chat.md +282 -0
  104. package/references/multi-agent-protocol/docs-site/examples/task-queue.md +399 -0
  105. package/references/multi-agent-protocol/docs-site/getting-started/index.md +98 -0
  106. package/references/multi-agent-protocol/docs-site/getting-started/installation.md +219 -0
  107. package/references/multi-agent-protocol/docs-site/getting-started/overview.md +172 -0
  108. package/references/multi-agent-protocol/docs-site/getting-started/quickstart.md +237 -0
  109. package/references/multi-agent-protocol/docs-site/index.md +136 -0
  110. package/references/multi-agent-protocol/docs-site/protocol/authentication.md +391 -0
  111. package/references/multi-agent-protocol/docs-site/protocol/connection-model.md +376 -0
  112. package/references/multi-agent-protocol/docs-site/protocol/design.md +284 -0
  113. package/references/multi-agent-protocol/docs-site/protocol/error-handling.md +312 -0
  114. package/references/multi-agent-protocol/docs-site/protocol/federation.md +449 -0
  115. package/references/multi-agent-protocol/docs-site/protocol/index.md +129 -0
  116. package/references/multi-agent-protocol/docs-site/protocol/permissions.md +398 -0
  117. package/references/multi-agent-protocol/docs-site/protocol/streaming.md +353 -0
  118. package/references/multi-agent-protocol/docs-site/protocol/wire-protocol.md +369 -0
  119. package/references/multi-agent-protocol/docs-site/sdk/api/agent.md +357 -0
  120. package/references/multi-agent-protocol/docs-site/sdk/api/client.md +380 -0
  121. package/references/multi-agent-protocol/docs-site/sdk/api/index.md +62 -0
  122. package/references/multi-agent-protocol/docs-site/sdk/api/server.md +453 -0
  123. package/references/multi-agent-protocol/docs-site/sdk/api/types.md +468 -0
  124. package/references/multi-agent-protocol/docs-site/sdk/guides/agent.md +375 -0
  125. package/references/multi-agent-protocol/docs-site/sdk/guides/authentication.md +405 -0
  126. package/references/multi-agent-protocol/docs-site/sdk/guides/client.md +352 -0
  127. package/references/multi-agent-protocol/docs-site/sdk/guides/index.md +89 -0
  128. package/references/multi-agent-protocol/docs-site/sdk/guides/server.md +360 -0
  129. package/references/multi-agent-protocol/docs-site/sdk/guides/testing.md +446 -0
  130. package/references/multi-agent-protocol/docs-site/sdk/guides/transports.md +363 -0
  131. package/references/multi-agent-protocol/docs-site/sdk/index.md +206 -0
  132. package/references/multi-agent-protocol/package-lock.json +3886 -0
  133. package/references/multi-agent-protocol/package.json +56 -0
  134. package/references/multi-agent-protocol/schema/meta.json +467 -0
  135. package/references/multi-agent-protocol/schema/schema.json +2558 -0
  136. package/src/agent/__tests__/agent-manager.test.ts +67 -1
  137. package/src/agent/agent-manager.ts +10 -4
  138. package/src/cli/__tests__/stable-instance-id.test.ts +57 -0
  139. package/src/cli/acp.ts +17 -2
  140. package/src/map/adapter/index.ts +3 -0
  141. package/src/server/combined-server.ts +10 -0
  142. package/src/store/event-store.ts +10 -3
  143. package/src/store/types/agents.ts +2 -0
@@ -0,0 +1,446 @@
1
+ ---
2
+ title: Testing
3
+ parent: Guides
4
+ grand_parent: SDK
5
+ nav_order: 6
6
+ description: "Test your MAP integrations"
7
+ ---
8
+
9
+ # Testing
10
+ {: .no_toc }
11
+
12
+ Test your MAP integrations effectively.
13
+ {: .fs-6 .fw-300 }
14
+
15
+ ## Table of contents
16
+ {: .no_toc .text-delta }
17
+
18
+ 1. TOC
19
+ {:toc}
20
+
21
+ ---
22
+
23
+ ## Overview
24
+
25
+ The SDK provides utilities for testing MAP integrations without network overhead.
26
+
27
+ ---
28
+
29
+ ## In-Memory Testing
30
+
31
+ Use `createStreamPair()` to create connected streams for testing:
32
+
33
+ ```typescript
34
+ import { createStreamPair } from "@multi-agent-protocol/sdk/stream";
35
+ import { MAPServer } from "@multi-agent-protocol/sdk/server";
36
+ import { ClientConnection, AgentConnection } from "@multi-agent-protocol/sdk";
37
+
38
+ describe("MAP Integration", () => {
39
+ let server: MAPServer;
40
+
41
+ beforeEach(() => {
42
+ server = new MAPServer({ name: "TestServer" });
43
+ });
44
+
45
+ afterEach(async () => {
46
+ await server.close();
47
+ });
48
+
49
+ it("should connect a client", async () => {
50
+ const [clientStream, serverStream] = createStreamPair();
51
+ server.accept(serverStream).start();
52
+
53
+ const client = new ClientConnection(clientStream, { name: "TestClient" });
54
+ const result = await client.connect();
55
+
56
+ expect(result.sessionId).toBeDefined();
57
+ expect(result.systemInfo?.name).toBe("TestServer");
58
+
59
+ await client.disconnect();
60
+ });
61
+ });
62
+ ```
63
+
64
+ ---
65
+
66
+ ## Testing Agents
67
+
68
+ ```typescript
69
+ import { createStreamPair } from "@multi-agent-protocol/sdk/stream";
70
+ import { MAPServer } from "@multi-agent-protocol/sdk/server";
71
+ import { AgentConnection } from "@multi-agent-protocol/sdk";
72
+
73
+ describe("Agent", () => {
74
+ let server: MAPServer;
75
+
76
+ beforeEach(() => {
77
+ server = new MAPServer({ name: "TestServer" });
78
+ });
79
+
80
+ afterEach(async () => {
81
+ await server.close();
82
+ });
83
+
84
+ it("should register an agent", async () => {
85
+ const [agentStream, serverStream] = createStreamPair();
86
+ server.accept(serverStream).start();
87
+
88
+ const agent = new AgentConnection(agentStream, {
89
+ name: "TestAgent",
90
+ role: "worker",
91
+ });
92
+
93
+ const { agent: registered } = await agent.connect();
94
+
95
+ expect(registered.id).toBeDefined();
96
+ expect(registered.name).toBe("TestAgent");
97
+ expect(registered.role).toBe("worker");
98
+
99
+ // Verify agent is in registry
100
+ const agents = server.agents.list();
101
+ expect(agents).toHaveLength(1);
102
+ expect(agents[0].name).toBe("TestAgent");
103
+
104
+ await agent.disconnect();
105
+ });
106
+
107
+ it("should handle messages", async () => {
108
+ const [agentStream, serverStream] = createStreamPair();
109
+ server.accept(serverStream).start();
110
+
111
+ const agent = new AgentConnection(agentStream, {
112
+ name: "TestAgent",
113
+ role: "worker",
114
+ });
115
+
116
+ const receivedMessages: any[] = [];
117
+ agent.onMessage((message) => {
118
+ receivedMessages.push(message);
119
+ });
120
+
121
+ await agent.connect();
122
+
123
+ // Send message directly through server
124
+ server.messages.send({
125
+ to: { agentId: agent.id },
126
+ payload: { type: "test", data: "hello" },
127
+ });
128
+
129
+ // Wait for message delivery
130
+ await new Promise((r) => setTimeout(r, 50));
131
+
132
+ expect(receivedMessages).toHaveLength(1);
133
+ expect(receivedMessages[0].payload.type).toBe("test");
134
+
135
+ await agent.disconnect();
136
+ });
137
+ });
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Testing Client Subscriptions
143
+
144
+ ```typescript
145
+ describe("Client Subscriptions", () => {
146
+ let server: MAPServer;
147
+
148
+ beforeEach(() => {
149
+ server = new MAPServer({ name: "TestServer" });
150
+ });
151
+
152
+ afterEach(async () => {
153
+ await server.close();
154
+ });
155
+
156
+ it("should receive events", async () => {
157
+ const [clientStream, serverStream] = createStreamPair();
158
+ server.accept(serverStream).start();
159
+
160
+ const client = new ClientConnection(clientStream, { name: "TestClient" });
161
+ await client.connect();
162
+
163
+ // Subscribe to agent events
164
+ const subscription = await client.subscribe({
165
+ eventTypes: ["agent.registered"],
166
+ });
167
+
168
+ // Collect events
169
+ const events: any[] = [];
170
+ const eventPromise = (async () => {
171
+ for await (const event of subscription) {
172
+ events.push(event);
173
+ if (events.length >= 1) break;
174
+ }
175
+ })();
176
+
177
+ // Register an agent
178
+ const [agentStream, agentServerStream] = createStreamPair();
179
+ server.accept(agentServerStream).start();
180
+ const agent = new AgentConnection(agentStream, { name: "NewAgent" });
181
+ await agent.connect();
182
+
183
+ // Wait for event
184
+ await eventPromise;
185
+
186
+ expect(events).toHaveLength(1);
187
+ expect(events[0].type).toBe("agent.registered");
188
+ expect(events[0].data.agent.name).toBe("NewAgent");
189
+
190
+ await subscription.unsubscribe();
191
+ await agent.disconnect();
192
+ await client.disconnect();
193
+ });
194
+ });
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Testing Agent-to-Agent Messaging
200
+
201
+ ```typescript
202
+ describe("Agent Messaging", () => {
203
+ let server: MAPServer;
204
+
205
+ beforeEach(() => {
206
+ server = new MAPServer({ name: "TestServer" });
207
+ });
208
+
209
+ afterEach(async () => {
210
+ await server.close();
211
+ });
212
+
213
+ it("should send messages between agents", async () => {
214
+ // Create two agents
215
+ const [stream1, serverStream1] = createStreamPair();
216
+ const [stream2, serverStream2] = createStreamPair();
217
+ server.accept(serverStream1).start();
218
+ server.accept(serverStream2).start();
219
+
220
+ const agent1 = new AgentConnection(stream1, { name: "Agent1" });
221
+ const agent2 = new AgentConnection(stream2, { name: "Agent2" });
222
+
223
+ const agent2Messages: any[] = [];
224
+ agent2.onMessage((message) => {
225
+ agent2Messages.push(message);
226
+ });
227
+
228
+ const { agent: registered1 } = await agent1.connect();
229
+ const { agent: registered2 } = await agent2.connect();
230
+
231
+ // Agent1 sends to Agent2
232
+ await agent1.send({
233
+ to: { agentId: registered2.id },
234
+ payload: { type: "greeting", message: "Hello from Agent1" },
235
+ });
236
+
237
+ // Wait for delivery
238
+ await new Promise((r) => setTimeout(r, 50));
239
+
240
+ expect(agent2Messages).toHaveLength(1);
241
+ expect(agent2Messages[0].payload.message).toBe("Hello from Agent1");
242
+ expect(agent2Messages[0].from).toBe(registered1.id);
243
+
244
+ await agent1.disconnect();
245
+ await agent2.disconnect();
246
+ });
247
+ });
248
+ ```
249
+
250
+ ---
251
+
252
+ ## Testing Scopes
253
+
254
+ ```typescript
255
+ describe("Scopes", () => {
256
+ let server: MAPServer;
257
+
258
+ beforeEach(() => {
259
+ server = new MAPServer({ name: "TestServer" });
260
+ });
261
+
262
+ afterEach(async () => {
263
+ await server.close();
264
+ });
265
+
266
+ it("should broadcast to scope members", async () => {
267
+ // Create three agents
268
+ const connections = await Promise.all([
269
+ createAgent(server, "Agent1"),
270
+ createAgent(server, "Agent2"),
271
+ createAgent(server, "Agent3"),
272
+ ]);
273
+
274
+ const [agent1, agent2, agent3] = connections;
275
+
276
+ // Collect messages for agents 2 and 3
277
+ const messages2: any[] = [];
278
+ const messages3: any[] = [];
279
+ agent2.conn.onMessage((m) => messages2.push(m));
280
+ agent3.conn.onMessage((m) => messages3.push(m));
281
+
282
+ // Agent1 creates scope
283
+ const scope = await agent1.conn.createScope({ name: "team" });
284
+
285
+ // Agent2 joins, Agent3 doesn't
286
+ await agent2.conn.joinScope(scope.id);
287
+
288
+ // Agent1 broadcasts to scope
289
+ await agent1.conn.send({
290
+ to: { scopeId: scope.id },
291
+ payload: { type: "announcement", text: "Team meeting!" },
292
+ });
293
+
294
+ await new Promise((r) => setTimeout(r, 50));
295
+
296
+ // Only Agent2 (scope member) receives the message
297
+ expect(messages2).toHaveLength(1);
298
+ expect(messages3).toHaveLength(0);
299
+
300
+ // Cleanup
301
+ for (const { conn } of connections) {
302
+ await conn.disconnect();
303
+ }
304
+ });
305
+ });
306
+
307
+ async function createAgent(server: MAPServer, name: string) {
308
+ const [stream, serverStream] = createStreamPair();
309
+ server.accept(serverStream).start();
310
+ const conn = new AgentConnection(stream, { name });
311
+ const { agent } = await conn.connect();
312
+ return { conn, agent };
313
+ }
314
+ ```
315
+
316
+ ---
317
+
318
+ ## Test Utilities
319
+
320
+ ### Helper for Multiple Connections
321
+
322
+ ```typescript
323
+ class TestHarness {
324
+ server: MAPServer;
325
+ connections: Array<{
326
+ stream: Stream;
327
+ client?: ClientConnection;
328
+ agent?: AgentConnection;
329
+ }> = [];
330
+
331
+ constructor() {
332
+ this.server = new MAPServer({ name: "TestServer" });
333
+ }
334
+
335
+ async createClient(name: string): Promise<ClientConnection> {
336
+ const [clientStream, serverStream] = createStreamPair();
337
+ this.server.accept(serverStream).start();
338
+
339
+ const client = new ClientConnection(clientStream, { name });
340
+ await client.connect();
341
+
342
+ this.connections.push({ stream: clientStream, client });
343
+ return client;
344
+ }
345
+
346
+ async createAgent(name: string, role?: string): Promise<AgentConnection> {
347
+ const [agentStream, serverStream] = createStreamPair();
348
+ this.server.accept(serverStream).start();
349
+
350
+ const agent = new AgentConnection(agentStream, { name, role });
351
+ await agent.connect();
352
+
353
+ this.connections.push({ stream: agentStream, agent });
354
+ return agent;
355
+ }
356
+
357
+ async cleanup() {
358
+ for (const { client, agent } of this.connections) {
359
+ if (client) await client.disconnect().catch(() => {});
360
+ if (agent) await agent.disconnect().catch(() => {});
361
+ }
362
+ await this.server.close();
363
+ }
364
+ }
365
+
366
+ // Usage
367
+ describe("With TestHarness", () => {
368
+ let harness: TestHarness;
369
+
370
+ beforeEach(() => {
371
+ harness = new TestHarness();
372
+ });
373
+
374
+ afterEach(async () => {
375
+ await harness.cleanup();
376
+ });
377
+
378
+ it("should work", async () => {
379
+ const client = await harness.createClient("TestClient");
380
+ const agent = await harness.createAgent("TestAgent", "worker");
381
+
382
+ const { agents } = await client.listAgents();
383
+ expect(agents).toHaveLength(1);
384
+ });
385
+ });
386
+ ```
387
+
388
+ ---
389
+
390
+ ## Mocking
391
+
392
+ ### Mock Event Emission
393
+
394
+ ```typescript
395
+ it("should handle events", async () => {
396
+ const harness = new TestHarness();
397
+ const client = await harness.createClient("TestClient");
398
+
399
+ const subscription = await client.subscribe({
400
+ eventTypes: ["custom.event"],
401
+ });
402
+
403
+ const events: any[] = [];
404
+ const eventPromise = collectEvents(subscription, events, 1);
405
+
406
+ // Emit custom event directly
407
+ harness.server.emit({
408
+ type: "custom.event",
409
+ data: { foo: "bar" },
410
+ });
411
+
412
+ await eventPromise;
413
+ expect(events[0].data.foo).toBe("bar");
414
+
415
+ await harness.cleanup();
416
+ });
417
+
418
+ async function collectEvents(
419
+ subscription: Subscription,
420
+ events: any[],
421
+ count: number
422
+ ) {
423
+ for await (const event of subscription) {
424
+ events.push(event);
425
+ if (events.length >= count) break;
426
+ }
427
+ }
428
+ ```
429
+
430
+ ---
431
+
432
+ ## Best Practices
433
+
434
+ 1. **Use in-memory streams** - Avoid network in unit tests
435
+ 2. **Clean up connections** - Always disconnect and close server
436
+ 3. **Use timeouts wisely** - Allow time for async message delivery
437
+ 4. **Test error cases** - Verify error handling works correctly
438
+ 5. **Isolate tests** - Fresh server instance per test
439
+ 6. **Use helpers** - Create utilities for common patterns
440
+
441
+ ---
442
+
443
+ ## Next Steps
444
+
445
+ - [Server Setup](./server.html) - Configure test servers
446
+ - [Transports](./transports.html) - Understand transport options