Skip to content

Commit 327902e

Browse files
cameroncookecodex
andcommitted
fix(debugging): Clarify debug attach PID mode
Document the valid debug_attach_sim attach modes in the public schema and reject pid attach calls that set waitFor to true before invoking LLDB. Fixes #417 Co-Authored-By: OpenAI Codex <noreply@openai.com>
1 parent fe64572 commit 327902e

3 files changed

Lines changed: 64 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
### Fixed
2424

25+
- Clarified `debug_attach_sim` PID attach arguments so the schema documents that `pid` must be used without `bundleId` or `waitFor`, and invalid `pid` + `waitFor: true` calls now fail validation before LLDB is invoked ([#417](https://github.com/getsentry/XcodeBuildMCP/issues/417)).
2526
- Fixed Claude UI benchmark preflight so transient malformed or still-loading UI snapshots no longer crash the harness or finish before app UI is observable.
2627
- Fixed Claude UI benchmark preflight so configured first-run dismissals require a concrete simulator ID, suite-provided simulator IDs are recorded in command logs, and preflight-launched apps are terminated after post-launch failures.
2728
- Fixed Claude UI benchmark config handling so invalid `failurePatterns` regexes and runtime-incompatible `sessionDefaults` fail before a suite starts and partial `allowedVariance` overrides preserve defaults for omitted metrics.

src/mcp/tools/debugging/__tests__/debugging-tools.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ describe('debug_attach_sim', () => {
126126
it('should expose schema with expected shape', () => {
127127
expect(attachSchema).toBeDefined();
128128
});
129+
130+
it('documents PID attach argument constraints in the public schema', () => {
131+
expect(attachSchema.pid.description).toContain('without bundleId');
132+
expect(attachSchema.pid.description).toContain('without waitFor');
133+
expect(attachSchema.waitFor.description).toContain('Only valid when attaching by bundleId');
134+
});
129135
});
130136

131137
describe('Handler Requirements', () => {
@@ -171,6 +177,34 @@ describe('debug_attach_sim', () => {
171177
expect(text).toContain('bundleId');
172178
expect(text).toContain('pid');
173179
});
180+
181+
it('rejects waitFor true when attaching by pid', async () => {
182+
__setTestDebuggerToolContextOverride(createTestContext());
183+
sessionStore.setDefaults({ simulatorId: 'test-sim-uuid' });
184+
185+
const result = await callHandler(attachHandler, {
186+
pid: 1234,
187+
waitFor: true,
188+
});
189+
190+
expect(result.isError).toBe(true);
191+
const text = result.content[0].text;
192+
expect(text).toContain('waitFor is only valid when attaching by bundleId');
193+
expect(text).toContain('For PID attach, omit waitFor or set it to false');
194+
});
195+
196+
it('allows waitFor false when attaching by pid', async () => {
197+
__setTestDebuggerToolContextOverride(createTestContext());
198+
sessionStore.setDefaults({ simulatorId: 'test-sim-uuid' });
199+
200+
const result = await callHandler(attachHandler, {
201+
pid: 1234,
202+
waitFor: false,
203+
});
204+
205+
expect(result.isError).toBeFalsy();
206+
expect(result.content[0].text).toContain('Attached');
207+
});
174208
});
175209

176210
describe('Logic Behavior', () => {

src/mcp/tools/debugging/debug_attach_sim.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ import {
1919
type DebuggerToolContext,
2020
} from '../../../utils/debugger/index.ts';
2121

22+
const DEBUG_ATTACH_MODE_HELP =
23+
'Valid attach modes: provide bundleId without pid, or provide pid without bundleId and omit waitFor or set waitFor to false.';
24+
2225
const baseSchemaObject = z.object({
2326
simulatorId: z
2427
.string()
@@ -32,9 +35,26 @@ const baseSchemaObject = z.object({
3235
.describe(
3336
"Name of the simulator (e.g., 'iPhone 17'). Provide EITHER this OR simulatorId, not both",
3437
),
35-
bundleId: z.string().optional(),
36-
pid: z.number().int().positive().optional(),
37-
waitFor: z.boolean().optional().describe('Wait for the process to appear when attaching'),
38+
bundleId: z
39+
.string()
40+
.optional()
41+
.describe(
42+
'Attach by bundle identifier. Provide bundleId without pid; waitFor may be used with this mode.',
43+
),
44+
pid: z
45+
.number()
46+
.int()
47+
.positive()
48+
.optional()
49+
.describe(
50+
'Attach to an already-running process by PID. Provide pid without bundleId and without waitFor.',
51+
),
52+
waitFor: z
53+
.boolean()
54+
.optional()
55+
.describe(
56+
'Only valid when attaching by bundleId. For PID attach, omit waitFor or set it to false.',
57+
),
3858
continueOnAttach: z.boolean().optional().default(true).describe('default: true'),
3959
makeCurrent: z
4060
.boolean()
@@ -47,10 +67,14 @@ const debugAttachSchema = z.preprocess(
4767
nullifyEmptyStrings,
4868
withSimulatorIdOrName(baseSchemaObject)
4969
.refine((val) => val.bundleId !== undefined || val.pid !== undefined, {
50-
message: 'Provide either bundleId or pid to attach.',
70+
message: `Provide either bundleId or pid to attach. ${DEBUG_ATTACH_MODE_HELP}`,
5171
})
5272
.refine((val) => !(val.bundleId && val.pid), {
53-
message: 'bundleId and pid are mutually exclusive. Provide only one.',
73+
message: 'Provide either bundleId or pid, not both.',
74+
})
75+
.refine((val) => !(val.pid !== undefined && val.waitFor === true), {
76+
message:
77+
'waitFor is only valid when attaching by bundleId. For PID attach, omit waitFor or set it to false.',
5478
}),
5579
);
5680

0 commit comments

Comments
 (0)