Skip to main content
The MCP server offers five tools and three prompts. Every tool only reads: nothing your assistant does through it changes anything in Periphery. Results are JSON, sent both as text and as structured content, so any client can use them.

Things to ask

You don’t call the tools yourself; your assistant picks them. A few requests that work well:
  • “What has Periphery indexed for acme.com? Group the apps by whether they look like ours, a partner’s, impersonation, or unrelated.”
  • “Which apps tied to acme.com expose a verified credential? Rank them by severity and tell me what to rotate first.”
  • “Find copies of acme-login.vercel.app by its favicon, and tell me which ones look like phishing.”
  • “What appeared for acme.com this week?”
  • “How many searches do I have left this month?“

search_apps

Runs a query and returns one page of up to 50 hits. Each call uses one search from your monthly allowance.
  • interpretedAs is the query as Periphery read it, when that differs from what was sent: a bare domain runs as domain:.
  • total counts every match across pages and stops at 1,000,000, where totalCapped is true.
  • A hit lists up to 10 email addresses; emailCount gives the total when there are more, and get_app has them all.
  • When the query matched the page’s text (free text, or a domain the page mentions), each hit carries a snippet of that text, with the matched words in **bold** and secrets masked as in get_app. A matched word with something masked in it isn’t bold.
  • If Periphery can’t read an app’s credentials at that moment, a hit with findings comes without its title and snippet rather than with them unmasked.
  • searchesLeft is omitted when your plan has no monthly limit.
A query that is empty or too long, or a page past 20,000, is refused before it runs and uses no search. So is a call your client gives up on while it waits for the account’s turn: nothing is counted for it. A page past the end of the results is not refused: it returns no hits and uses a search, so your assistant stops when hasMore is false.

get_app

Returns the full record of one app. It uses no search. The record has the same fields as GET /v1/apps/{hostname}, plus the console link, without the favicon URL and without the page-source link:
text is the visible text of the last snapshot, up to 2 KB. credentials lists every finding, verified or not, masked as on the app page. The screenshot link is signed and valid for one hour. Over MCP, what your assistant reads goes to its AI provider, so the text of a page, its title and search snippets included, is masked before it leaves:
  • every credential Periphery found on the page, wherever it shows: printed across lines, cut off where the stored text or a snippet ends, or with invisible characters such as zero-width spaces inside it;
  • a value of 8 or more characters labelled as a secret, such as API_KEY=…, API Key: …, "password": "…", Bearer … or Authorization: Basic …; a quoted value counts up to its closing quote, spaces included, or to the end of the text when the quote was cut off;
  • any other long string that looks random rather than like a word or a number, such as the secret half of an AWS key pair, whose finding holds only the key ID, even when it’s printed right against that ID.
A masked value keeps a few characters at each end, like sk_live_••••••••0000 in the record above, or none when only a piece of it was there or it holds spaces. Lower-case hostnames of three labels or more stay readable, deployment hashes in them included, such as dashboard-6f3b9a2c.vercel.app; a random-looking label in a hostname written in capitals, with fewer labels, or cut off can be masked. A title is cut to 512 characters. There is no link to the raw page source, which can hold keys in full, and no screenshot of a page that prints a credential Periphery found (see get_app_screenshot). Text the console shows you is not masked. A secret in a form no detector knows and that doesn’t look random, a short random key such as a 16-character authenticator seed, or a labelled one shorter than 8 characters can still be in the text.

get_app_screenshot

Returns the screenshot of an app’s last snapshot, 1280 × 800, as an image the assistant can look at: useful to judge what an app is, whose branding it carries, or whether it imitates a login page. It uses no search. The image comes with a one-line caption: the hostname, the snapshot time and the console link. The screenshot shows the page as any visitor sees it, and an image goes to your assistant’s AI provider like text does. So when the page’s text prints a credential Periphery found, the tool sends no image, and get_app no screenshotUrl: the call returns an error naming the record page, where you can see the screenshot yourself. A key Periphery didn’t find can still show in a screenshot.

get_account

Shows the connected account: its plan, whether the plan includes MCP, the searches used and left this month, when the allowance resets (resetsAt, the 1st of next month, UTC) and the rate limit. It works on every plan, so on Free your assistant can explain why the other tools refuse.

list_key_types

Lists the credential detectors with verified findings in the index, the most common first, each with the filter to use, such as creds:openai, so your assistant can filter by detector without spending a search on a misspelled name. It uses no search.

Prompts

Clients that support MCP prompts, such as Claude, list these as ready-made requests. Each fills in a short investigation plan, which your assistant then follows with the tools. They follow the response playbooks: a match is a lead, not proof, and a surfaced credential is never used or tested.

Errors

Errors come back as tool results your assistant can read and act on, rather than as failed calls: Some answers come at the HTTP level, before any tool runs: JSON-RPC batches are not supported: send one request per call.