Skip to content

Commit 248f408

Browse files
style: fix import order and formatting
- Fix ESLint import/order for type imports in tools.ts - Apply Prettier formatting to webauthn files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 300e963 commit 248f408

4 files changed

Lines changed: 64 additions & 19 deletions

File tree

WEBAUTHN_IMPLEMENTATION.md

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Adding WebAuthn CDP domain support to chrome-devtools-mcp using strict outside-i
1010
## Goal (Definition of Done)
1111

1212
A user can:
13+
1314
1. Enable WebAuthn virtual authenticator environment via MCP tool
1415
2. Add a virtual authenticator (CTAP2/U2F, internal/USB/BLE/NFC)
1516
3. Use WebAuthn on a webpage (e.g., webauthn.io) with the virtual authenticator responding
@@ -69,68 +70,84 @@ describe('webauthn', () => {
6970
### Phase 1: Minimal Vertical Slice
7071

7172
#### Step 1.1: Observe Missing Functionality
73+
7274
- [x] Verify no `webauthn_*` tools exist in MCP
7375
- [x] Navigate to webauthn.io, confirm we can't do WebAuthn without virtual authenticator
7476

7577
#### Step 1.2: Failing Test - Tool Exists
78+
7679
Create `tests/tools/webauthn.test.ts`:
80+
7781
```typescript
78-
it('webauthn_enable tool can be called')
82+
it('webauthn_enable tool can be called');
7983
```
84+
8085
Run: `npm run test -- --test-name-pattern="webauthn"`
8186
Expected: FAIL (module not found)
8287

8388
#### Step 1.3: Implement - Minimal Tool Skeleton
89+
8490
- Create `src/tools/webauthn.ts` with `enableWebAuthn` tool (no-op handler)
8591
- Export from `src/tools/tools.ts`
8692
- Run test: Should PASS
8793
- Commit: `feat(webauthn): add webauthn_enable tool skeleton`
8894

8995
#### Step 1.4: Verify Tool Appears in MCP
96+
9097
- Rebuild: `npm run build`
9198
- Check if MCP picks up changes (may need restart)
9299
- Verify tool appears
93100

94101
#### Step 1.5: Failing Test - Enable Actually Works
102+
95103
```typescript
96104
it('enables WebAuthn so addVirtualAuthenticator succeeds', async () => {
97105
await withMcpContext(async (response, context) => {
98106
await enableWebAuthn.handler({params: {}}, response, context);
99107
const session = context.getSelectedPage()._client();
100108
// This should succeed only if WebAuthn.enable was called
101109
const result = await session.send('WebAuthn.addVirtualAuthenticator', {
102-
options: { protocol: 'ctap2', transport: 'internal' }
110+
options: {protocol: 'ctap2', transport: 'internal'},
103111
});
104112
assert.ok(result.authenticatorId);
105113
});
106114
});
107115
```
116+
108117
Run: FAIL (WebAuthn not enabled)
109118

110119
#### Step 1.6: Implement - CDP Call
120+
111121
Add to handler:
122+
112123
```typescript
113124
await context.getSelectedPage()._client().send('WebAuthn.enable');
114125
```
126+
115127
Run test: PASS
116128
Commit: `feat(webauthn): implement WebAuthn.enable CDP call`
117129

118130
#### Step 1.7: Verify via MCP
131+
119132
- Call `webauthn_enable` tool
120133
- Confirm no error
121134

122135
#### Step 1.8: Failing Test - Add Authenticator Tool
136+
123137
```typescript
124-
it('adds virtual authenticator and returns ID')
138+
it('adds virtual authenticator and returns ID');
125139
```
140+
126141
Run: FAIL (tool doesn't exist)
127142

128143
#### Step 1.9: Implement - Add Authenticator
144+
129145
- Add `addVirtualAuthenticator` tool with params: protocol, transport, hasResidentKey, hasUserVerification, isUserVerified
130146
- Run test: PASS
131147
- Commit: `feat(webauthn): add webauthn_add_authenticator tool`
132148

133149
#### Step 1.10: E2E Verification
150+
134151
1. Navigate to webauthn.io
135152
2. Call `webauthn_enable`
136153
3. Call `webauthn_add_authenticator` with ctap2/internal/userVerified
@@ -142,6 +159,7 @@ Commit: `test(webauthn): verify e2e with webauthn.io`
142159
### Phase 2: Expand Coverage
143160

144161
After vertical slice works:
162+
145163
- `webauthn_disable`
146164
- `webauthn_remove_authenticator`
147165
- `webauthn_get_credentials`
@@ -151,6 +169,7 @@ After vertical slice works:
151169
- `webauthn_set_user_verified`
152170

153171
### Phase 3: Polish
172+
154173
- Error handling tests
155174
- Run `npm run docs` to update documentation
156175
- Run `npm run check-format` and fix any issues
@@ -191,6 +210,7 @@ npm run check-format
191210
## Reference: Emulation Tool Pattern
192211

193212
From `src/tools/emulation.ts`:
213+
194214
```typescript
195215
export const emulate = defineTool({
196216
name: 'emulate',
@@ -238,13 +258,27 @@ describe('myTool', () => {
238258

239259
Track each step completion here:
240260

241-
- [ ] Step 1.1: Observe missing functionality
242-
- [ ] Step 1.2: Failing test - tool exists
243-
- [ ] Step 1.3: Implement tool skeleton
244-
- [ ] Step 1.4: Verify tool appears in MCP
245-
- [ ] Step 1.5: Failing test - enable works
246-
- [ ] Step 1.6: Implement CDP call
247-
- [ ] Step 1.7: Verify via MCP
248-
- [ ] Step 1.8: Failing test - add authenticator
249-
- [ ] Step 1.9: Implement add authenticator
250-
- [ ] Step 1.10: E2E verification
261+
- [x] Step 1.1: Observe missing functionality
262+
- [x] Step 1.2: Failing test - tool exists
263+
- [x] Step 1.3: Implement tool skeleton
264+
- [x] Step 1.4: Verify tool appears in MCP
265+
- [x] Step 1.5: Failing test - enable works
266+
- [x] Step 1.6: Implement CDP call
267+
- [x] Step 1.7: Verify via MCP
268+
- [x] Step 1.8: Failing test - add authenticator
269+
- [x] Step 1.9: Implement add authenticator
270+
- [x] Step 1.10: E2E verification
271+
272+
**Phase 1 COMPLETE** - Minimal vertical slice working!
273+
274+
### Commits:
275+
276+
- `5f35101` feat(webauthn): add webauthn_enable tool skeleton
277+
- `ce3a0ed` feat(webauthn): implement WebAuthn.enable CDP call
278+
- `300e963` feat(webauthn): add webauthn_add_authenticator tool
279+
280+
### E2E Verified:
281+
282+
- webauthn.io registration + authentication works automatically
283+
- No user interaction required (Touch ID bypassed)
284+
- Virtual authenticator responds to both registration and authentication

src/tools/tools.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import * as performanceTools from './performance.js';
1414
import * as screenshotTools from './screenshot.js';
1515
import * as scriptTools from './script.js';
1616
import * as snapshotTools from './snapshot.js';
17-
import * as webauthnTools from './webauthn.js';
1817
import type {ToolDefinition} from './ToolDefinition.js';
18+
import * as webauthnTools from './webauthn.js';
1919

2020
const tools = [
2121
...Object.values(consoleTools),

src/tools/webauthn.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import {defineTool} from './ToolDefinition.js';
1212

1313
export const enableWebAuthn = defineTool({
1414
name: 'webauthn_enable',
15-
description: 'Enable the WebAuthn virtual authenticator environment for the selected page.',
15+
description:
16+
'Enable the WebAuthn virtual authenticator environment for the selected page.',
1617
annotations: {
1718
category: ToolCategory.EMULATION,
1819
readOnlyHint: false,
@@ -23,7 +24,9 @@ export const enableWebAuthn = defineTool({
2324
// @ts-expect-error _client is internal Puppeteer API
2425
const session = page._client() as CDPSession;
2526
await session.send('WebAuthn.enable');
26-
response.appendResponseLine('WebAuthn virtual authenticator environment enabled.');
27+
response.appendResponseLine(
28+
'WebAuthn virtual authenticator environment enabled.',
29+
);
2730
},
2831
});
2932

@@ -59,8 +62,13 @@ export const addVirtualAuthenticator = defineTool({
5962
// @ts-expect-error _client is internal Puppeteer API
6063
const session = page._client() as CDPSession;
6164

62-
const {protocol, transport, hasResidentKey, hasUserVerification, isUserVerified} =
63-
request.params;
65+
const {
66+
protocol,
67+
transport,
68+
hasResidentKey,
69+
hasUserVerification,
70+
isUserVerified,
71+
} = request.params;
6472

6573
const result = await session.send('WebAuthn.addVirtualAuthenticator', {
6674
options: {

tests/tools/webauthn.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ describe('webauthn', () => {
6363
const hasAuthenticatorId = response.responseLines.some(line =>
6464
line.includes('authenticatorId'),
6565
);
66-
assert.ok(hasAuthenticatorId, 'Should include authenticator ID in response');
66+
assert.ok(
67+
hasAuthenticatorId,
68+
'Should include authenticator ID in response',
69+
);
6770
});
6871
});
6972
});

0 commit comments

Comments
 (0)