Skip to content

MCP Server

PentestPad exposes a Model Context Protocol server, so an AI coding tool can read your projects and write findings directly into the platform. Instead of copying output out of your terminal and into a form, you ask the assistant to file the finding and it lands in the project, with the same permissions, activity log entries, and Jira sync as if you had typed it into the web UI.

It works with any MCP client that speaks streamable HTTP — Claude Code, Cursor, Zed, Windsurf, and Claude Desktop among them.

  • An MCP client that supports streamable HTTP (this page uses Claude Code for the examples).
  • A staff account you can sign into in a browser. Client-role users cannot connect — see Who can connect.
  • Nothing to create or copy beforehand. The server authenticates over OAuth, not an API key.

The endpoint is /mcp on your own instance:

https://your-instance.pentestpad.com/mcp
Terminal window
claude mcp add --transport http pentestpad https://your-instance.pentestpad.com/mcp

No header, no key to paste. Then check it registered:

Terminal window
claude mcp list

To share the server with a repository rather than your whole machine, commit a .mcp.json. There is no secret in it, so it is safe to commit as-is — every teammate who opens the project authorizes it with their own account the first time they use it:

{
"mcpServers": {
"pentestpad": {
"type": "http",
"url": "https://your-instance.pentestpad.com/mcp"
}
}
}

Add the same block to ~/.cursor/mcp.json, or to .cursor/mcp.json inside a project.

Registering the server does not authenticate it. The first time your assistant actually calls PentestPad, your browser opens to your instance. Sign in if you are not already, and you land on a consent screen naming the client:

Authorize Claude Code Claude Code is requesting access to your PentestPad account. It will act as you and can do nothing your own permissions do not already allow.

Click Authorize. The client stores the resulting token itself — there is nothing to copy back into a config file.

Ask your assistant something that has to go through PentestPad:

List my active pentest projects.

The assistant calls search-projects and comes back with names and UUIDs. From there:

On the Acme External Pentest, file a finding from the SQL Injection template. It’s in the login form on staging.acme.test, impact High, probability Medium.

See the tool reference for everything it can do.

Staff accounts (Admin, Manager, Pentester, custom staff roles) Can connect
Client-role accounts Cannot connect — refused at the consent screen

A client-role user is stopped before they ever reach /mcp: signing in and reaching the authorization screen shows Authorization unavailable instead of a consent prompt, explaining that the Model Context Protocol endpoint is available to team members only. This is deliberate for the current release: MCP is a single endpoint, so read and write access cannot be split apart for clients the way they are in the web UI. Clients keep their full REST API access, unchanged.

Open Profile → API Access and find Connected applications. Every client you have authorized is listed there with when you approved it.

Click Disconnect to revoke it. This revokes both the token the client is currently using and the one behind it that renews it automatically, so the client cannot quietly obtain a new token to replace the one it lost — reconnecting means going through the browser approval again.

Nothing can be deleted through MCP. There are no tools for deleting findings, projects, clients, users, or reports. The worst outcome from a confused assistant is a finding you delete yourself in the web UI.

Every action re-checks your permissions. The tools run inside PentestPad and consult exactly the same policies as the web interface. An assistant acting on your behalf can only do what you can do — if you cannot edit findings on a project, neither can it.

Writes are attributed to you. Findings, comments, and status changes created over MCP appear in the activity feed under your name and trigger the same notifications and Jira sync as ones made in the browser.

120 requests per minute per user. An assistant exploring a project makes many small calls in a burst, so this is set generously; you are unlikely to reach it in normal use.

The MCP endpoint is enabled by default on PentestPad Cloud and opt-in for self-hosted deployments. To turn it on, set the following in your .env:

Terminal window
MCP_ENABLED=true

Then restart the application. If you cache configuration, clear it first:

Terminal window
php artisan config:clear

Until it is enabled, /mcp and the OAuth endpoints it depends on (authorization, token, and discovery) all return 404 rather than an authentication error — the instance behaves as if none of it were routed at all, so your client will report that it cannot find the server rather than that it was refused.

Each container generates its own OAuth signing keypair the first time it boots. On a single-container install that is fine and needs no configuration. Behind a load balancer with two or more replicas it is not: a token minted by one container is rejected by every other, so a client authorizes successfully and then fails with 401 on later calls, seemingly at random.

Generate one keypair:

Terminal window
php artisan passport:keys

Then give every container the same two values, each holding the full contents of the matching file:

Terminal window
PASSPORT_PRIVATE_KEY="<contents of storage/oauth-private.key>"
PASSPORT_PUBLIC_KEY="<contents of storage/oauth-public.key>"

When these are set, containers use them instead of generating their own, and a token issued by any one of them is accepted by all.

Not the same as “MCP Servers” in Settings

Section titled “Not the same as “MCP Servers” in Settings”

PentestPad’s admin panel has a Settings → MCP Servers screen. That is the opposite direction: it lets PentestPad’s own in-app AI agent call out to MCP servers you configure. It has nothing to do with connecting your terminal to PentestPad, and nothing on this page requires it.