diff --git a/README.md b/README.md index b3684a5..6efb77c 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,14 @@ node packages/local-mcp/dist/cli.js --url https://board.holon.run --headless Built-in fallback adapter mode: ```bash -webmcp-local-mcp --site x --headless +webmcp-local-mcp --site x --headless --user-data-dir ~/.uxc/webmcp-profile/x +``` + +For auth-sensitive sites such as `x` and `google`, the recommended first step is a headed +session with a managed profile so local-mcp can bootstrap a normal browser for manual sign-in: + +```bash +webmcp-local-mcp --site x --no-headless --user-data-dir ~/.uxc/webmcp-profile/x ``` Deterministic fixture mode: diff --git a/docs/adapters/x.md b/docs/adapters/x.md index 5618563..9d25b4e 100644 --- a/docs/adapters/x.md +++ b/docs/adapters/x.md @@ -2,6 +2,21 @@ `@webmcp-bridge/adapter-x` provides the real fallback adapter for X/Twitter flows when a page does not expose native `navigator.modelContext`. +## Local-mcp session model + +When X is used through `@webmcp-bridge/local-mcp`, it is treated as an auth-sensitive site. +The recommended startup path is: + +1. start `local-mcp` with `--site x --user-data-dir ` in headed mode +2. let `bridge.session.bootstrap` open a normal browser for manual sign-in when needed +3. let local-mcp reattach to the authenticated profile for page automation + +Example: + +```bash +webmcp-local-mcp --site x --no-headless --user-data-dir ~/.uxc/webmcp-profile/x +``` + ## Tools - `auth.get`: detect `authenticated`, `auth_required`, or `challenge_required`. diff --git a/docs/migration.md b/docs/migration.md index dfd7842..982da80 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -11,7 +11,7 @@ - Start local-mcp via CLI: ```bash -node packages/local-mcp/dist/cli.js --site x +node packages/local-mcp/dist/cli.js --site x --no-headless --user-data-dir ~/.uxc/webmcp-profile/x ``` - Use `createWebMcpPageGateway` directly when integrating Playwright manually. @@ -20,4 +20,5 @@ node packages/local-mcp/dist/cli.js --site x - Native WebMCP is preferred automatically. - If native is unavailable, shim + fallback adapter is used automatically. +- Auth-sensitive adapters such as `x` and `google` now use managed profile bootstrap/attach lifecycle instead of Playwright-driven login startup. - local-mcp stdio transport now reuses `@modelcontextprotocol/sdk` (`Server` + `StdioServerTransport`) instead of custom framing code. diff --git a/packages/adapter-x/src/index.ts b/packages/adapter-x/src/index.ts index 8d33124..159889e 100644 --- a/packages/adapter-x/src/index.ts +++ b/packages/adapter-x/src/index.ts @@ -9,13 +9,14 @@ import { createXAdapter } from "./adapter.js"; export const manifest: AdapterManifest = { id: "x.com", displayName: "X", - version: "0.4.0", + version: "0.5.0", bridgeApiVersion: "1.0.0", defaultUrl: "https://x.com/home", hostPatterns: ["x.com", "www.x.com", "*.x.com"], authPolicy: { - mode: "none", + mode: "bootstrap_then_attach", authProbeTool: "auth.get", + allowAnonymousTools: true, }, }; diff --git a/packages/local-mcp/test/cli.test.ts b/packages/local-mcp/test/cli.test.ts index 3836b39..0bc0bae 100644 --- a/packages/local-mcp/test/cli.test.ts +++ b/packages/local-mcp/test/cli.test.ts @@ -128,6 +128,11 @@ describe("resolveSiteDefinition", () => { const site = resolveSiteDefinition("x"); expect(site.manifest.defaultUrl).toContain("x.com"); expect(site.manifest.hostPatterns).toContain("x.com"); + expect(site.manifest.authPolicy).toEqual({ + mode: "bootstrap_then_attach", + authProbeTool: "auth.get", + allowAnonymousTools: true, + }); }); it("resolves fixture site preset", () => { diff --git a/packages/local-mcp/test/sites.test.ts b/packages/local-mcp/test/sites.test.ts index a8c8106..f44a06e 100644 --- a/packages/local-mcp/test/sites.test.ts +++ b/packages/local-mcp/test/sites.test.ts @@ -33,6 +33,11 @@ describe("resolveSiteSource", () => { const site = await resolveSiteSource({ site: "x" }); expect(site.source).toBe("builtin"); expect(site.id).toBe("x"); + expect(site.manifest.authPolicy).toEqual({ + mode: "bootstrap_then_attach", + authProbeTool: "auth.get", + allowAnonymousTools: true, + }); }); it("resolves external adapter module by relative path", async () => { diff --git a/skills/webmcp-bridge/references/link-patterns.md b/skills/webmcp-bridge/references/link-patterns.md index 0a5f7a7..82a770a 100644 --- a/skills/webmcp-bridge/references/link-patterns.md +++ b/skills/webmcp-bridge/references/link-patterns.md @@ -37,6 +37,9 @@ This is for one daemon-managed site session. Do not treat it as permission to la If a site reacts badly to headed/headless switching or browser fingerprint differences, split the profile into separate `cli` and `ui` profiles for that site. +For auth-sensitive sites such as `x` and `google`, the shared profile is also the anchor for +`bridge.session.bootstrap` and later attach-mode reuse. Do not omit `--user-data-dir` for those sites. + ## Link Creation Pattern ```bash diff --git a/skills/webmcp-bridge/references/usage-patterns.md b/skills/webmcp-bridge/references/usage-patterns.md index 041647e..9c06ba3 100644 --- a/skills/webmcp-bridge/references/usage-patterns.md +++ b/skills/webmcp-bridge/references/usage-patterns.md @@ -16,10 +16,15 @@ board-webmcp-cli nodes.list command -v x-webmcp-cli command -v x-webmcp-ui skills/webmcp-bridge/scripts/ensure-links.sh --name x --site x +x-webmcp-ui bridge.session.status +x-webmcp-ui bridge.session.bootstrap x-webmcp-cli -h x-webmcp-cli timeline.home.list -h ``` +For auth-sensitive built-in sites such as `x`, expect the first headed run to require manual +sign-in against the managed profile before page tools become available. + ## Third-party adapter module ```bash