# Reported issues for periscope-mcp

Pod holds 20 of 21 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.

Back to [periscope-mcp](/mcp/periscope-mcp).

## Most discussed

### check_color_contrast default sweep checks only 1 element on a dense page

### Tool name

check_color_contrast

### Tool arguments

```json
{"session_id": "<session on app.companyapp.si dashboard>"}
```

(no `selector` — default sweep)

### Actual response

```json
{"checked": 1}
```

Only **1 element** checked on a dense dashboard page. With an explicit `selector: "td, th, h1, h2, button"` the same page yielded `checked: 25` and real AA failures (2026-07-03 retest: `checked: 45`, 12 failures at 4.34:1).

### Expected behavior

The default "all text elements" heuristic

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/4) · 2026-07-02 · closed · 4 comments

### Minor batch: stale URL on SPA nav, duplicate failed steps, script text in assert preview, selector-dialect asymmetry, drag false success

### Tool name

multiple (batch of minor issues: click_element, interact_and_test, assert_condition, get_page_elements/get_page_html, wait_for_network)

### Tool arguments

```json
{"note": "batch report — each item below names the tool and repro"}
```

### Actual response

1. **click_element** — on SPA route changes, returns the **pre-navigation** URL (`url` and screenshot captured before the router settles). Workaround: `assert_condition url_contains` afterwards.
2. **interact_and_test** — a fa

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/9) · 2026-07-02 · closed · 3 comments

### Cookie bleed across the shared default browser context (project-less tools contaminate each other)

### Tool name

open_session / check_links (shared "default" browser context)

### Tool arguments

```json
{"url": "https://github.com"}
```

(no `project` → default context; earlier in the same server lifetime: `check_links(url="https://companyapp.si", check_external=true)`, also project-less)

### Actual response

`get_cookies` on the fresh GitHub session returned **13 cookies, 7 of them LinkedIn cookies** (`JSESSIONID`, `bcookie`, `bscookie`, `li_gc`, `lidc`, `__cf_bm`, `lang` on `.linkedin.co

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/8) · 2026-07-02 · closed · 3 comments

### copy_auth reports session_copied: true but the copied session doesn't authenticate

### Tool name

copy_auth

### Tool arguments

```json
{"from_project": "companyapp", "to_project": "companyapp2"}
```

### Actual response

```json
{"success": true, "message": "Auth copied from 'companyapp' to 'companyapp2'", "method": "form", "session_copied": true}
```

But the copied session does not work:

- `open_session(https://app.companyapp.si/dashboard, project=companyapp2)` → redirected to `/login?callbackUrl=%2Fdashboard`
- Control check at the same moment: `open_session(..., project

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/7) · 2026-07-02 · closed · 3 comments

### set_cookies claims 'Set 1 cookies' but is inert until login_project; silently overwrites other auth config

### Tool name

set_cookies

### Tool arguments

```json
{"project": "authtest", "cookies": [{"name": "periscope_test", "value": "cookie_works_123", "domain": "httpbin.org"}]}
```

### Actual response

```json
{"success": true, "message": "Set 1 cookies"}
```

But a session opened immediately afterwards had **zero** cookies:

- `open_session(https://httpbin.org/cookies, project=authtest)` → page body `{"cookies": {}}`
- `get_cookies(session)` → `{"total": 0, "cookies": []}`

Only after calling `l

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/6) · 2026-07-02 · closed · 3 comments

### Skip-link accessibility check false positive on non-English skip links

### Tool name

run_checks_on_session / test_url (accessibility check: skip link)

### Tool arguments

```json
{"session_id": "<session on app.companyapp.si>", "checks": ["accessibility"]}
```

### Actual response

```json
{"issues": [{"type": "accessibility", "severity": "info", "message": "No skip navigation link found"}]}
```

Reported on app pages that **do** have a proper sr-only skip link: `Preskoči na vsebino`, `href="#main-content"` — confirmed present by `test_keyboard_navigation` (first

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/5) · 2026-07-02 · closed · 3 comments

### find_element returns invalid CSS selectors from Tailwind variant classes

### Tool name

find_element

### Tool arguments

```json
{"session_id": "<session on app.companyapp.si>", "text": "<visible element text>"}
```

### Actual response

Returned "best CSS selector" built from raw class lists containing Tailwind variant classes, e.g.:

```json
{"selector": "button.hover:bg-accent.text-sidebar-foreground/70.[&_svg]:size-4"}
```

`querySelector` cannot parse these (`:`, `/`, `[` in class names) — the selector is unusable in follow-up calls. The text/aria data returned

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/3) · 2026-07-02 · closed · 3 comments

### auto_fill_form: ambiguous 'input' fallback on id/name-less fields, 30s timeouts, still reports success: true

### Tool name

auto_fill_form

### Tool arguments

```json
{"session_id": "<session on app.companyapp.si 'Nov kontakt' form>"}
```

### Actual response

```json
{"success": true, "...": "8 of 10 fields resolved to the ambiguous selector 'input'; each fill timed out after 30s; call blocked ~4.5 minutes total"}
```

`success: true` despite 8/10 fields never being filled.

### Expected behavior

- Field detector should build selectors from `placeholder` / `aria-label` when inputs have no `id`/`name

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/2) · 2026-07-02 · closed · 3 comments

## Most recent

### Full-page screenshots misrender sticky/reveal elements (stitching) — misleading for UI review

### What couldn't be done

Trust a full-page screenshot as evidence of what a page looks like, on pages with `position: sticky`/`fixed` headers or scroll-triggered reveal animations (IntersectionObserver `.reveal` patterns, scroll-driven animations).

Two failure modes observed repeatedly (periscope 0.10.2 and earlier, sites: agrarservice demo, segentic.dev — both Astro sites with sticky nav + reveal-on-scroll sections):

1. **Sticky elements stitched mid-page**: the sticky nav is painted a seco

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/23) · 2026-07-07 · closed · 1 comment

### Deterministic / sitemap-seeded crawl order — consecutive test_project runs pick different pages, findings silently vanish

### What couldn't be done

Compare two consecutive `test_project` runs of the same site. With `max_pages: 20` on a site with 24+ internal URLs, the crawler selected a **different 20-page subset** on each run, so per-page findings appeared and disappeared between reports without any change to the site.

Concrete case (periscope 0.10.2, commit a78b933, project `segentic-dev`, base_url `https://segentic.dev`):

- Run 1 (2026-07-07 01:11): crawled `/kontakt`, `/prenova-spletne-strani`, `/reference`,

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/22) · 2026-07-07 · closed · 2 comments

### Uniform, opt-in `observe` param on action tools (learn from glovebox)

## Where this came from

Cross-server comparison with [glovebox-mcp](https://github.com/segentic-lab/glovebox-mcp) (the computer-use sibling). Glovebox otherwise treats periscope as the standard to match — but on **one** dimension the arrow points back at us. From glovebox's own project guide:

> **The `observe`/`settle_ms` pattern.** Every action tool optionally returns the resulting screen state in the SAME call, saving a round-trip. This is periscope's batching instinct at the primitive level

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/21) · 2026-07-06 · closed · 2 comments

### Headed sessions ignore project storage_state/cookies (headless works, headed gets 0 cookies)

## Summary

`open_session(..., headed=true, project=<p>)` does **not** apply the project's persisted `storage_state` / injected cookies. A headless session opened with the *same* project and *same* auth is correctly authenticated, but the headed session opens with **zero cookies** and bounces to the app login page. This makes it impossible to watch an authenticated flow in a visible window.

## Environment
- Periscope version_running / version_on_disk: **0.10.0**
- commit: **7f241b8**
- install_

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/20) · 2026-07-05 · closed · 1 comment

### `wait_for_network` fails with cryptic `'url_pattern'` error when the param is omitted

## Summary
Using `wait_for_network` as a step in `interact_and_test` without a `url_pattern` fails with a bare `Step N (wait_for_network) failed: 'url_pattern'` — a raw KeyError-style message that doesn't say what's wrong or how to fix it.

## Repro
`interact_and_test` steps:
```json
[{"action":"click","selector":"button:has-text('Save')"},
 {"action":"wait_for_network","timeout":5000}]
```
→ `Step 1 (wait_for_network) failed: 'url_pattern'`

## Expected / suggestion
- If `url_pattern` is requir

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/19) · 2026-07-04 · closed · 1 comment

### `get_response_body` url_pattern matching is inconsistent / undocumented (anchors & regex)

## Summary
`get_response_body(url_pattern=…)` matching behaves inconsistently — some intuitive patterns return "No response bodies found" while a looser substring matches. It's unclear whether the pattern is a substring, glob, or full regex, whether it's anchored, and whether the query string is included.

## Repro (all against the same captured traffic)
- `url_pattern="api/v1/appointments$"` → **No response bodies found** (the `$` anchor didn't match, presumably due to a query string / trailing

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/18) · 2026-07-04 · closed · 1 comment

### `measure_interaction` under-measures async interactions — misleading as an INP proxy

## Summary
`measure_interaction` clicks and waits for networkidle (or a selector), returning elapsed ms. For an interaction whose effect is an async mutation fired *after* the click handler returns (e.g. a form submit that triggers a `fetch` a tick later), it settles on the first network-idle window *before* the request registers, returning a misleadingly tiny number.

## Repro
An admin "Save" button that fires `PATCH /users/:id` (which round-trips to Keycloak + DB):
- `measure_interaction` retu

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/17) · 2026-07-04 · closed · 1 comment

### `select_option` cannot target attribute-less `<select>` (no nth / locator support)

## Summary
`select_option` takes a CSS selector passed to `document.querySelector`. When a page has multiple `<select>` elements with no `id`/`name`/distinguishing attributes (common with form libraries), there is no way to target the Nth one, and Playwright-style locators are rejected.

## Repro
A form with 3 attribute-less `<select>` (staff / client / service):
- `select_option(selector="select >> nth=0", label="…")` → `SyntaxError: Failed to execute 'querySelector' on 'Document': 'select >> n

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/16) · 2026-07-04 · closed · 1 comment

### Clicks intercepted by Radix/shadcn portal overlays (`fixed inset-0`) — need overlay-aware clicking

## Summary
`click_element` / `interact_and_test` clicks frequently fail on apps built with Radix UI / shadcn/ui (dropdown menus, dialogs) because the component's full-screen overlay (`<div class="fixed inset-0 z-40/z-50" data-aria-hidden="true">`) sits above the target and intercepts pointer events. Playwright reports the element as "visible, enabled, stable" and then times out with `…overlay intercepts pointer events`.

## Repro (observed against an authenticated Next.js + shadcn app)
- Open a 

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/15) · 2026-07-04 · closed · 1 comment

### Pages with Cloudflare Turnstile fail the crawl: networkidle never settles, page reported as hard error

### Tool name

test_project (also reproducible with test_url / any tool navigating with the default wait)

### Tool arguments

```json
{"project": "racunalnicar"}
```

(project base_url: https://racunalnicar.eu, max_pages: 15, no auth)

### Actual response

Page entry inside the otherwise successful report (14/15 pages passed):

```json
{
  "url": "https://racunalnicar.eu/ai/zacni",
  "status": "error",
  "error": "Page.goto: Timeout 30000ms exceeded.\nCall log:\n  - navigating to \"https://racu

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/14) · 2026-07-03 · closed · 1 comment

### test_project runs unauthenticated despite is_logged_in: true — logged-out pages reported as success

## Summary

On a project with working form login (`login_project` → redirected to the app dashboard, `is_logged_in: true`), `test_project` crawled and tested only the **public** pages (`/login`, `/register`, `/forgot-password`, `/`) — its screenshot of the site root is literally the login form — yet every page came back `"status": "success"` with no hint that auth was lost. A user reading the report would believe the authenticated app was audited.

Related to #7 (copy_auth session not authentica

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/11) · 2026-07-02 · closed · 2 comments

### find_element prefers hidden duplicate elements; role filter misses implicit ARIA roles

### Tool name

find_element

### Tool arguments

```json
{"session_id": "<session on app.companyapp.si/transport>", "text": "Nadzorna plošča"}
```

### Actual response

```json
{"found": 1, "elements": [{"selector": "#nav-group-work > a:nth-child(1) > span:nth-child(2)", "text": "Nadzorna plošča"}]}
```

The selector is valid CSS (good — issue #3 fix works), but it resolves to the **hidden** copy of the element: the page renders the sidebar twice (mobile drawer + desktop sidebar, with duplicate 

[Read the thread](https://github.com/segentic-lab/periscope-mcp/issues/10) · 2026-07-02 · closed · 2 comments

The remaining reports are on [the project's issue tracker](https://github.com/segentic-lab/periscope-mcp/issues).
