periscope-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| create_projectA | Create a persistent testing project: a named website/web-app target with its base URL and crawl limits, saved to disk and reused by crawl_project, test_project, and authenticated sessions. Returns the stored project config. Create this first, then attach auth (set_form_login / set_basic_auth / set_cookies) and run tests. |
| list_projectsA | List all saved testing projects with their base URL, crawl limits, and configured auth type. Returns an array of project configs (empty if none exist). Use it to discover the project names the other project/auth/testing tools expect. |
| get_projectA | Get one project's saved configuration: base URL, max_pages/max_depth, screenshot directory, and which auth (form/basic/cookies) is set up. Returns {success, project}. Use it to confirm setup before crawling, testing, or logging in. |
| delete_projectA | Permanently delete a project and its saved configuration and auth. Returns {success}. Irreversible; afterwards the name is free to reuse. Does not remove screenshots/reports already written to disk. |
| set_form_loginA | Configure username/password form login for a project (stored, not executed yet). For standard HTML login forms; field/submit selectors are auto-detected but can be overridden. Returns {success}. Call login_project afterwards to actually log in. For 2FA/SSO/CAPTCHA use interactive_login instead. |
| set_basic_authA | Configure HTTP Basic Auth credentials for a project — the browser sends them on every request in that project's context. Stored, not executed: call login_project to apply, then pass |
| set_cookiesA | Seed a project with session cookies to skip an interactive login (e.g. cookies copied from a logged-in browser). Each cookie needs name+value+domain (path defaults to '/'). Stored, not executed: call login_project to inject them. Returns {success}. |
| login_projectA | Execute a project's configured login — submit the form, apply Basic Auth, or inject cookies — and persist the resulting authenticated session (storage_state) for reuse. Requires set_form_login / set_basic_auth / set_cookies first. Returns {success} with login details. Re-run it when auth expires mid-test. |
| interactive_loginA | Open a VISIBLE browser window for a human to log in by hand — the way to authenticate flows that can't be automated (2FA/MFA, SSO/OAuth redirects, CAPTCHA, magic links, device confirmation). After you finish logging in, call save_login to capture the session; future headless sessions on the project reuse it. Requires a display on the server (DISPLAY set). |
| save_loginA | Capture the authenticated session (cookies + localStorage) from an in-progress interactive_login, save it to the project, and close the visible window. The project then opens authenticated sessions headlessly. Re-run interactive_login when the session expires. |
| test_urlA | Screenshot and audit a single URL in one shot (opens then closes a throwaway page). Runs the selected checks — visual, accessibility, functionality, seo, performance, geo — and returns {status, title, screenshot path, issues[]} where each issue has type/severity/message; never-idle pages come back flagged (wait_downgraded), not as errors. Pass |
| crawl_projectA | Discover a project's pages by breadth-first crawling internal links from its base URL, bounded by max_pages/max_depth (overridable per call). Discovery is deterministic (links sorted before the cap) and sitemap-seeded when a sitemap.xml/robots.txt Sitemap is present, so the same site yields the same page subset every run. Returns the discovered URLs plus pages_not_crawled[] (≤100, else a count) so a hit cap is never silent. Runs in the project's authenticated context. Set meta=true to also get each page's title + meta description (captured during the crawl, so behind-login/JS pages work), and save_md=true to save every crawled page as readable Markdown to data/fetches// (returns pages[] with saved_path + saved_dir). Discovery (optionally + capture) — use test_project to crawl and run full audits. |
| test_projectA | Full-site audit: crawl every page (up to max_pages) and run the selected checks on each, saving a timestamped JSON report. The crawl is deterministic + sitemap-seeded, so consecutive runs cover the same pages and before/after comparisons are reliable (issue #22). Returns per-page issues, site-wide findings (e.g. duplicate titles/descriptions), an auth_check, pages_not_tested[] when the cap is hit, and a coverage delta (pages_added/pages_dropped) vs the previous report. Pages that bounce to the login page come back as auth_lost, never as fake success. Reload the saved report with get_report. |
| get_screenshotA | Get the saved screenshot file path for a URL previously tested in a project. Returns {success, url, screenshot_path}. Locates the PNG on disk after test_url/test_project — it does not capture a new image (use screenshot_session for that). |
| list_reportsA | List saved test reports (the JSON files test_project writes), for one project or all projects. Returns each report's path and timestamp, newest first. Pass a path to get_report to read one. |
| get_reportA | Load a saved test report by file path and return its full contents — per-page issues, site-wide findings, and run metadata. Returns {success, report}. Get valid paths from list_reports. |
| session_reportA | Generate a human-readable dossier of EVERYTHING done this server run — every tool call in chronological order with arguments (secrets redacted), pass/fail verdicts, timings, error messages, and embedded screenshot thumbnails — as a self-contained HTML file plus a PDF. Made for handing to your user to review the whole session; add your findings via 'notes' so the report opens with your summary. The journal records automatically from server start; clear=true resets it after reporting (e.g. between test rounds). |
| open_sessionA | Open a persistent browser session and return {session_id, url, title, screenshot}. The page stays alive across tool calls so you can explore, click, fill, debug, and accumulate console/network logs — the main workflow for anything multi-step. Pass |
| close_sessionA | Close a browser session and free its resources (page, context, captured logs). Returns {success}. Call it when finished; using a closed or expired id returns a 'session not found' error that explains why (idle-expired, evicted, or crashed). |
| list_sessionsA | List active browser sessions with their session_id, current URL, and idle time. Returns an array (empty if none open). Use it to recover a session id or spot sessions nearing the idle-timeout or the concurrency cap. |
| click_elementA | Click an element in a session page. Returns a screenshot and the new URL/title after click. If a full-screen portal overlay (Radix/shadcn dialogs & menus) intercepts the pointer, automatically falls back to an element-level JS click and flags click_method='js_dispatch' — no workaround needed. Use force=true to bypass actionability checks for other cases (hidden/animating elements). |
| fill_formB | Fill form fields in a session page and optionally submit. Use force=true to bypass actionability checks when overlays or dialogs block the inputs. |
| interact_and_testB | Execute a multi-step interaction workflow. Supports 25 actions: click, force_click, fill, force_fill, type, select, select_option, wait, wait_for, wait_for_text, screenshot, navigate, hover, press_key, check, uncheck, scroll_to, scroll_within, evaluate_js, drag, right_click, go_back, go_forward, upload_file, wait_for_network. Can work on an existing session or create an ephemeral page. |
| get_page_elementsA | List elements matching a CSS selector with their attributes (tag, text, id, class, href, value, visible, enabled, aria_label, role). Pass 'attributes' for extra HTML attributes (data-, aria-, style, ...) and 'full_text' for complete text content instead of the 80-char preview. Works on a session or a URL. Standard CSS selectors only — Playwright-specific pseudo-classes (:has-text, :visible) are not supported here. |
| test_form_validationA | Audit a page's form validation: locate forms, list their required fields, and collect messages from :invalid fields and custom error elements. Returns the per-form field/validation details. Use to verify client-side validation behaves as intended. Works on a session or a URL. |
| compare_screenshotsA | Pixel-diff two screenshot files. Returns the percentage of differing pixels and writes a diff image highlighting the changed regions (path in the result). Use for visual-regression checks — capture with test_url/screenshot_session, then compare. |
| visual_checkA | Named visual-regression baselines — no screenshot-path bookkeeping. action='set' captures the session page (or one element via selector) as the baseline for 'name'; action='check' captures again and returns a hard verdict: passed (diff_percentage vs max_diff_percent, default 0.5%), plus a diff image with changed pixels highlighted. Baselines are stored per project+name. If a check fails on an intended change, re-baseline with action='set'. Prefer selector-scoped baselines for components — full pages flake more (animations, dynamic content). |
| test_responsiveA | Load a URL at several viewport sizes (default mobile 375x812, tablet 768x1024, desktop 1920x1080) and screenshot each, optionally running checks per size. Returns each viewport's screenshot path and any issues. Catches layout breakage across breakpoints in one call. Pass custom viewports as [{name,width,height}]. |
| check_linksA | Crawl all links on a page and report each one's URL, status code, and OK/broken result — catching 404s and dead anchors. External links are skipped unless check_external=true. Returns the per-link results plus a broken-link summary. Works on a session or a URL. |
| measure_interactionA | Click an element and measure how long until the result settles. Returns elapsed_ms, a 'measures' note stating exactly what was timed, and the click's real interaction_to_next_paint_ms when measurable. Three modes: wait_for_network (URL substring) measures until that response completes — use this for buttons whose handler fires a request asynchronously, where plain network-idle settles early and under-measures; wait_for (selector) measures until it appears; default measures to the first network-idle window. |
| record_sessionA | Run a sequence of steps while recording a video of the browser (Playwright video capture). Returns the saved .webm file path. Steps use the same format as interact_and_test. Use it to produce a visual artifact or repro of a workflow; for assertions/checks use interact_and_test instead. |
| test_keyboard_navigationA | Tab through a page from the top and record the focus order, flagging any stop with no visible focus indicator. Returns total_tab_stops, the focus_order sequence, and issues[]. Accessibility audit for keyboard operability. Works on a session or a URL. |
| get_console_errorsA | Return browser console output (errors, warnings, logs) captured passively on a session since it opened or since the last read; clears the buffer by default. Returns the buffered entries. First stop when debugging a broken page — no steps required. |
| copy_authA | Copy auth configuration and, when possible, the live login session (cookies + localStorage via storage_state) from one project to another on the same domain. Returns {success, session_copied}; session_copied is false when only the config/cookies could transfer. Use to reuse a login across related projects. |
| set_viewportA | Resize a session's viewport to a device preset or custom width/height, then screenshot. Returns the new size and screenshot. Persists for later actions in the session — use this to test responsive layouts inside an ongoing session (unlike test_responsive, which opens throwaway pages). |
| screenshot_sessionA | Screenshot the session's current page as-is — no actions performed. Returns the image path (full-page by default; full_page=false captures just the viewport). Full-page captures are PREPARED for fidelity: sticky/fixed headers are neutralized (no mid-page duplication), animations disabled, reduced-motion emulated, and scroll-reveal sections forced visible — the applied steps are reported in capture_prep. Pass raw=true to capture the unprepared stitch. Use to grab state at a point in a workflow; interactive tools already return screenshots, so don't call this after every step. |
| select_pageA | Adopt a popup or new tab this session opened (window.open, target=_blank, OAuth/payment windows) as a NEW session id you can drive with every normal tool — clicks, assertions, logs. Console/network recording attaches the instant the driver sees the popup open, so early traffic is captured (requests firing in the popup's first milliseconds can precede any driver's visibility — a browser-automation limit, not a periscope one). Returns {session_id, url, title}; with several popups open, call without index to list them first. The parent session keeps working for the original tab. |
| navigate_sessionA | Browser history/reload on a session: back, forward, or reload. Returns the new URL/title and a screenshot. Reload tests state persistence and caching; back/forward exercise SPA history. |
| run_checks_on_sessionA | Run the audit checks (visual/accessibility/functionality/seo/performance/geo) against a session's CURRENT page — after your interactions, without opening a new page (unlike test_url). Returns the same {issues[], per-check results} structure as test_url. Use to audit a state you reached by clicking/filling. |
| handle_dialogA | Arm a one-shot handler for the NEXT JavaScript dialog (alert/confirm/prompt) on a session — accept or dismiss, with optional prompt text. Returns {success}. Must be called BEFORE the action that triggers the dialog, otherwise the dialog blocks the page and times out. |
| upload_fileA | Set file(s) on an element by path, without the OS file picker. Returns {success}. Provide absolute paths that exist on the server. For a picker opened by a button, target the underlying file input's selector. |
| flowA | Save and re-run named step sequences — define a workflow once (login, checkout, smoke path), replay it in any session. action='save' stores steps (interact_and_test's exact format, all 25 actions); action='run' executes a saved flow on a session via the same engine as interact_and_test; action='list' shows saved flows; action='delete' removes one. Deliberately minimal: verify outcomes by following a run with assert_all or visual_check. Flows persist in data/flows/ across sessions and server restarts. |
| wait_for_networkA | Block until a network request whose URL contains the given substring completes (optionally filtered by HTTP method), up to timeout. url_pattern is required and is a plain substring match against the full URL including query string — not a regex or glob. Returns the matched request's URL/status/method, or times out. To catch a request fired by a click, run the click and this as consecutive steps in one interact_and_test call; after the fact, read get_response_body/get_network_log instead. |
| intercept_networkA | Mock matching API responses on a session — return a custom status/body/content-type for requests whose URL contains a substring. Returns {success}. Use it to force error, empty, or loading states without a real backend; call BEFORE the triggering action, and clear_intercepts to remove. once=true intercepts only the first match. |
| clear_interceptsA | Remove network mocks created by intercept_network — all of them, or only those registered with a given URL pattern. Returns {success}. Use to restore real backend responses after testing mocked states. |
| get_local_storageA | Read a session page's localStorage (or sessionStorage) — all entries, or specific keys. Returns the key/value pairs as an object. Use to inspect client-side state (tokens, flags, cached data) when debugging. |
| set_local_storageA | Write key/value entries to a session page's localStorage (or sessionStorage), optionally clearing existing entries first. Returns {success}. Use to seed client state (feature flags, tokens, cached data) to reproduce a specific app state; reload if the app reads storage only at load time. |
| download_fileA | Click a trigger and capture the file it downloads — the honest way to verify exports (CSV, PDF, invoices). The download waiter is armed BEFORE the click so fast downloads aren't missed, and the click uses the same overlay-fallback as click_element (export buttons inside Radix menus work). Returns the saved path, size, sha256, source URL, and for small text files a text_head preview so content can be asserted without another call. Files land in data/downloads/. |
| select_iframeA | Switch into an iframe and return a NEW session id scoped to that frame's content — use it like a normal session for elements inside the iframe, and keep the parent id for page-level actions. Close the returned session when done. Needed because cross-frame content isn't reachable through the parent session's selectors. |
| get_computed_styleA | Read the actual rendered CSS values (after stylesheets and inheritance) for the requested properties on matching elements. Returns per-element property→value maps. Use to verify colors, fonts, spacing, display, or opacity programmatically instead of eyeballing a screenshot. |
| emulate_networkA | Throttle a session's network to a preset — slow_3g, fast_3g, offline, or reset. Returns {success}. Persists across navigations until reset. Use to test loading spinners, skeleton states, offline fallbacks, and timeout handling. |
| test_dark_modeA | Emulate prefers-color-scheme (dark or light) on a session and screenshot the result. Returns the screenshot. Use to verify a site's dark/light theming without touching OS settings; the emulation persists for later actions in the session. |
| assert_conditionA | Assert a condition on the current page and get a hard pass/fail plus the actual value — no screenshot to interpret. Supports text_contains, text_equals, element_exists, element_visible, element_count, url_contains, title_contains, attribute_equals. Returns {passed, actual, expected}. The verification primitive — prefer it over screenshot-squinting. |
| assert_allA | Batch assertions: evaluate MANY conditions in one call and get every verdict — no early abort, so the response is the complete pass/fail picture (overall passed, failed_count, per-assertion results with actual values). Each item takes the same fields as assert_condition. Prefer this over sequential assert_condition calls when verifying a state with 2+ expectations. |
| get_page_mapA | Semantic page map in ONE call: every interactive element (links, buttons, inputs, custom controls) plus landmarks and headings, in document order — each with its ARIA role, accessible name, live state (disabled/checked/expanded/value), and a ready-to-use CSS selector. The fastest way to answer 'what can I do on this page?' — use it to orient before clicking instead of multiple get_page_elements calls. Interactive elements with no accessible name are flagged unnamed (an accessibility finding in itself). Output is compact: only truthy state fields, capped at max_nodes with an explicit truncated flag. |
| find_elementA | Find elements by text content, tag, ARIA role, and/or proximity to another element, ranked by match quality. Returns {found, elements} with the best CSS selector for each. Use it to get a reliable selector from what you can see (e.g. a button's text) instead of guessing. |
| auto_fill_formA | Detect a form's fields, infer each type (email/phone/name/address/date…), fill realistic test data, and optionally submit — one call replacing 5-10. Returns which fields were filled and with what. Use overrides={selector: value} for specific values and submit=true to submit. |
| get_network_logA | Return the network requests captured on a session — each with URL, HTTP method, status, resource type, and size. Optionally filter by URL substring; clear=true empties the log after reading. Returns the request list. Use to see which API calls fired and their status when debugging. |
| get_cookiesA | Read all cookies from a session's browser context (optionally filtered by domain). Returns {cookies, total} with each cookie's name/value/domain/path/flags. Essential for debugging auth/session issues — confirm the expected session cookie is present and scoped correctly. |
| page_stateA | Named page-state checkpoints. action=snapshot saves URL + cookies + storage + DOM signature under a name; action=restore navigates back to it and restores cookies/storage; action=diff compares the current DOM against the snapshot (added/removed/changed elements + tag count changes). Enables testing multiple paths from the same starting point. |
| get_interaction_logA | Export the real INP (Interaction to Next Paint) time series for a session — one record per interaction Periscope drove (click/typing), each with its input-to-next-paint latency, event type, target, timestamp, and URL. Saves a JSON (for graphing) or CSV file and returns percentile stats (p50/p75/p90/p98/worst). Use after driving interactions (interact_and_test, click_element, fill_form…) — ideal for a long interactive test where you want to see all INP times, not just the worst. Unlike Lighthouse (which can't measure INP in lab mode and falls back to TBT), this is measured from actual Event Timing entries. |
| run_lighthouseA | Run a real Google Lighthouse audit against a URL. Returns 0-100 category scores, Core Web Vitals lab metrics (LCP, TBT, CLS, Speed Index), and the failed audits, and saves the full JSON report. Requires Node.js — finds it on PATH or auto-detects nvm installs (~/.nvm); if none exists, returns the exact nvm install commands. Launches its own headless Chrome: no session or project auth state applies. |
| check_color_contrastA | Check WCAG color contrast ratios for text elements on the page. Samples one element per unique text style (color/background/size), so repeated nav items don't exhaust the budget — 'checked' counts style groups, 'elements_represented' the elements they cover. Reports failures against AA or AAA thresholds. |
| scroll_into_viewA | Scroll an element into the viewport without clicking it. Returns {success}. Use to trigger lazy-loaded content/images or to bring a section into view before screenshotting. |
| wait_for_goneA | Block until an element disappears — removed from the DOM or hidden — up to timeout. Returns {success} once it's gone, or times out. Use to wait for a modal/dialog to close or a loading spinner to vanish before the next step. |
| get_page_htmlA | Return the raw outerHTML of matching elements, or the full page HTML if no selector, truncated to max_length. Returns the HTML string(s). Use to inspect component/markup structure — e.g. head meta tags for SEO, or a widget's DOM. Standard CSS selectors only. |
| get_table_dataA | Parse an HTML table into structured data, mapping header cells to each row's values. Returns {headers, rows, total_rows} where rows are header→value objects. Use instead of scraping table markup by hand when verifying tabular content. |
| get_toast_messagesA | Capture currently-visible toast/notification/alert text on a session — checks common patterns ([role=alert], [role=status], [aria-live], .toast, .notification, Toastify, Sonner, Radix) or your own selector. Returns the messages found. Set wait_ms to let a toast animate in first. Use to verify success/error notifications after an action. |
| select_optionA | Select an option from a native or a custom dropdown (Radix/shadcn combobox), auto-detecting which. Choose by value, label, or index. Returns {success} and the resulting selection. For custom dropdowns it opens the menu and clicks the matching option — use this rather than click+click. When a page has several attribute-less elements, pass element_index to target the Nth match of the selector (Playwright '>>' syntax is not supported). |
| get_response_bodyA | Return the captured response body text for a request whose URL contains a substring (optionally filtered by method). Matching is a plain substring test against the full URL incl. query string — not a regex or glob. On a miss it lists the captured candidate URLs so you can adjust the pattern in one round-trip. Bodies are captured automatically for fetch/xhr/document requests, making this the fastest way to diagnose a 400/500 — no setup before the request. |
| web_searchA | Search DuckDuckGo and return result titles, URLs, and snippets (up to max_results). Use to look up documentation, verify external facts, or research during a testing workflow. |
| web_fetchA | Fetch a URL and return clean, readable content — Markdown by default (structure preserved: headings, lists, links, code, tables), with page boilerplate (nav/footer/cookie bars) stripped via readability extraction. Far fewer tokens than a raw text dump. format='text' for plain text, 'html' for raw HTML (raw_html=true is an alias). Static HTTP fetch by default; render=true loads the page in headless Chromium so client-rendered/SPA content is captured (runs all JS, then extracts) — pass project to render a page behind that project's login (host fetch tools can't). contains=[words] only returns the content if the page contains the term(s) (contains_mode any|all), else omits it to save tokens. save=true (or save_path) writes the full content to disk and returns saved_path. TLS verified by default (verify_ssl=false for dev certs). |
| periscope_systemA | Install status, self-update, and the current agent guide — Periscope's self-maintenance tool. action='status' (read-only): running version vs on-disk version, git commit, install type, capabilities (Node/Lighthouse, display for headed, Chromium), active session count, and whether an update is available. action='agents_md' (read-only): returns the CURRENT AGENTS.md so you can refresh a stale pasted copy of your operating guide. action='update': dry-run by default (commits behind + incoming changes); apply=true runs the updater (git pull + deps, data/ untouched) — new code loads only after the MCP server restarts, and the response says so explicitly. Managed installs (Docker, no .git) refuse update with guidance. |
| describe_toolsA | Return a structured catalog of Periscope's tools grouped by category, with parameters, workflow examples, and tips — optionally filtered to one category. Returns the guide as structured JSON. Call this first if you're new to the server, to plan a testing workflow. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/segentic-lab/periscope-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server