Netraptor

How to let a coding agent call your authenticated API without sharing tokens (Claude Code, Cursor, Codex)

Updated · 9 min read

To let a coding agent call an authenticated API without giving it a token, run the request where the session already lives, which is your logged-in browser tab. Netraptor 0.7.0 adds call_endpoint, an opt-in MCP tool that lets Claude Code, Cursor or Codex re-run a request your app already made, inside that tab, and read the fresh response. The browser attaches your cookies and Netraptor replays the recorded headers there, so the agent gets the response and never sees the credentials.

Steps

  1. 1

    Update both sides to 0.7.0

    Update the Netraptor extension from the Chrome Web Store, and start the server with npx -y @branch42-labs/netraptor-mcp@latest. Stop the old bridge and restart your agent. Live calls need 0.7.0 on both sides.

  2. 2

    Record the endpoint once

    Open the toolbar popup on your app, turn on "Keep history for this site", reload, and use the page that makes the request. The agent can only call endpoints the app has already called.

  3. 3

    Turn on live calls

    In Netraptor open Settings, then Local MCP server, and turn on "Let agents call recorded endpoints". The switch is off by default and an agent cannot change it.

  4. 4

    Confirm the tab

    Ask the agent about your traffic. It calls list_sessions and asks you to confirm the Tab ID, Session #ID and origin shown in Netraptor before it reads or calls anything.

  5. 5

    Ask for a fresh response

    Try "call GET /api/orders/{id} again for order 1042 and tell me whether total is a number now". The agent picks a recorded request for that endpoint and calls call_endpoint.

  6. 6

    Check the call in the session

    Every live call goes through the page's own fetch, so it shows up in the Netraptor session next to the requests your app made.

Why can't my coding agent call my app's API?

Claude Code, Cursor and Codex run in a terminal or an editor. Your session lives in a browser tab. The agent can read the handler you just changed, and it still cannot ask the running app what that handler returns for your account, because it has nothing to authenticate with.

Copying the session over is harder than it looks.

  • Session cookies are usually HttpOnly, so page scripts cannot read them, and the browser adds them to requests on its own.
  • Bearer tokens are short-lived. A token pasted into a chat is often expired by the time the agent has finished the edit.
  • CSRF tokens, single sign-on and multi-factor prompts assume a person in a browser.
  • Anything you paste into the conversation goes to the model provider and stays in the transcript.

Reading recorded traffic solves the first half of the problem. The agent can see which endpoints exist and what they returned (how a coding agent can see your app's API calls). Recorded traffic is a snapshot, though. After the agent edits a handler, the old response no longer tells it whether the change worked.

What are the ways to give an agent an authenticated request?

There are four common approaches. They differ in where the credential ends up.

  • Paste a token or a "Copy as cURL" command into the chat. It is quick and works with any agent. The credential is now in the conversation, and it expires.
  • Put an API key in the environment or in the MCP server's config. This fits public APIs that issue keys. Most logged-in web apps authenticate with a session cookie and have no key to issue.
  • Let the agent drive a browser. Claude in Chrome, Chrome DevTools MCP and Playwright MCP let an agent click and type in a browser, some of them in your signed-in profile. The agent gets the whole page, including whatever else that profile is logged in to.
  • Run the one request in your own tab and return only the response. This is what call_endpoint does. The agent names a recorded request, and the browser sends it with the session it already has.

The last approach is the narrowest. It cannot fill in a form or click a button, and it can only reach endpoints your app has already called. In exchange, no credential leaves the browser.

How does call_endpoint work?

The Netraptor MCP server runs on your machine and talks to the extension over a paired local connection (setup guide). When the agent calls call_endpoint, it passes the confirmed tab and the ID of a recorded request. The extension then does the following.

  1. Checks that you turned live calls on, that the request belongs to the recording in that tab, and that the tab is still recording.
  2. Rebuilds the request from the recorded one. The method, headers and body come from the recording. The agent may change path and query parameters of the same endpoint, or the variables of a GraphQL query.
  3. Runs it inside the page through the page's own fetch, after checking that the tab is still on the origin where the request was recorded.
  4. Lets the browser attach your cookies, as it does for any request the page makes.
  5. Redacts the response the same way as saved traffic, then returns the status, headers and body to the agent.

The agent's input is small.

{
  "tabId": 123,
  "browserInstanceId": "<from list_sessions>",
  "requestId": 42,
  "url": "https://app.example.com/api/orders/1042"
}

The result looks like this, trimmed.

{
  "sessionId": 12,
  "origin": "https://app.example.com",
  "requestId": 42,
  "method": "GET",
  "url": "https://app.example.com/api/orders/1042",
  "status": 200,
  "statusText": "OK",
  "responseHeaders": { "content-type": "application/json" },
  "responseBody": "{\"id\":1042,\"total\":129.5,\"status\":\"paid\"}",
  "bodyTruncated": false
}

Because the call goes through the page's fetch, Netraptor records it like any other request. You can see every call an agent made in the session, and the agent can follow them with watch_requests.

What can the agent call, and what is refused?

Live calls are limited to reads on endpoints your app already uses.

  • Allowed: GET, HEAD and GraphQL queries sent by POST.
  • Refused: POST, PUT, PATCH and DELETE, GraphQL mutations and subscriptions, batched GraphQL requests, and persisted queries with no query text to check.
  • Only recorded endpoints. A changed URL must keep the recorded origin and match the endpoint's path template, so /api/orders/{id} accepts another ID and nothing else.
  • The agent cannot set headers or a body. For a GraphQL query it can change variables only, and the URL stays as recorded.
  • Redirects are not followed. A call that answers with a redirect fails.
  • The tab must still be recording and still be on the site where the request was recorded. A call times out after 8 seconds.

The MCP tool is marked as not read-only and open-world, so a client such as Claude Code can ask you before each call. If live calls are off, the tool tells the agent to ask you and not to work around it.

How do I use it to check a change against the running app?

This is the loop the tool was built for. It is a small piece of agentic testing: the agent checks its own change against the real app before it tells you the work is done.

  1. You report a bug, for example that total comes back as a string on the order page.
  2. The agent uses search and get_endpoint to find GET /api/orders/{id} and a recorded example.
  3. The agent edits the handler, and your dev server reloads.
  4. The agent calls call_endpoint with that example's request ID.
  5. The agent reads the fresh response and reports what it saw, with the status code.

It works on localhost, staging or production, wherever your tab is logged in. Reads only, so it suits checks such as response shape, status codes, permissions for the current user, and pagination. A change to a write endpoint still needs you to click through the app, and the agent can read the result with watch_requests.

If the recorded request carried a short-lived bearer token that has since expired, the call returns 401. Use the app so a fresh request is recorded, then have the agent replay that one.

How is this different from Claude in Chrome, Chrome DevTools MCP and Playwright MCP?

Those tools give an agent a browser to operate. Claude Code's documentation describes Claude in Chrome as a way to test web apps, debug with console logs, automate form filling and extract data from pages. Chrome DevTools MCP and Playwright MCP drive a browser through DevTools and Playwright.

  • Browser tools work at the level of pages. The agent navigates, clicks, reads the DOM and can inspect network requests along the way.
  • call_endpoint works at the level of one HTTP request. The agent gets JSON back and spends no steps on navigation or screenshots.
  • A browser tool can do anything a user can do on the page, including writes. A live call is limited to recorded GET, HEAD and GraphQL query endpoints.

They fit together. Use a browser tool when the job is a user flow, a visual check or a console error. Use a live call when the question is "what does this endpoint return now?" and you want the answer in one tool call.

Is this the same as MCP authentication?

No. MCP authentication usually means how an MCP client proves itself to an MCP server. The specification defines an OAuth-based authorization flow for servers reached over HTTP, and says stdio servers should take credentials from the environment instead.

This guide is about a different hop, from the agent to your own app's API. The Netraptor server is a local stdio server, paired with the extension by a shared secret, and it holds no credential for your app. The session stays in the tab.

Is it safe to let an AI agent call my API?

A live call is a real request sent as you. These are the properties to weigh before you turn it on.

  • It is off by default, and the switch lives in the extension's settings. Nothing sent through MCP can turn it on.
  • Credentials are replayed inside the browser. Credential-like headers, URL parameters and JSON fields in the response are redacted by name before the agent sees them.
  • The rest of the response body goes to your MCP client, which may send it to its model provider. Redaction works on names, so a secret stored under an unusual field name is returned as is.
  • GET is meant to be safe, and not every API follows that. If your app has a GET route that changes data, such as /logout or /items/123/delete, and the app called it while recording, an agent could call it again.
  • Every call appears in the session, so you can review what an agent did.

Use a test account where you can, and leave the switch off on apps where a read is sensitive. Record only apps you build, test or are authorized to test.

Frequently asked questions

How do I give Claude Code access to an API that needs a login?
Record the app's traffic with Netraptor, add @branch42-labs/netraptor-mcp to Claude Code, and turn on "Let agents call recorded endpoints" in Netraptor's settings. Claude Code can then re-run recorded GET requests and GraphQL queries inside your logged-in tab and read the response, without a token in the chat.
Does the agent see my cookies or tokens?
No. The browser attaches cookies when the request is sent, and recorded headers are replayed inside the browser. Responses are redacted by name the same way as saved traffic.
Can the agent send POST, PUT or DELETE requests?
No. Live calls cover GET, HEAD and GraphQL queries. Other methods, GraphQL mutations and subscriptions are refused.
Can the agent call an endpoint my app has not called?
No. It can only re-run a recorded request, on the same origin and the same path template. Path and query parameters may change.
Does it work with Cursor and Codex?
Yes. Any MCP client that runs a stdio server can use it. Setup commands for Codex, Claude Code and Cursor are in the MCP server guide.
Does it work on localhost?
Yes. The call runs in whichever tab you confirmed, so it works on localhost, staging or production, as long as the tab is recording and still on the site where the request was recorded.
Why did a live call fail?
The common causes are that live calls are switched off, the tab stopped recording or moved to another site, the endpoint answered with a redirect, or the call took longer than 8 seconds. An extension older than 0.7.0 answers that it does not support live calls.
Is call_endpoint free?
It is part of the local MCP server, which is a Pro feature. Pro is a one-time $29.99 purchase. The Free plan includes recording, filters and Postman, HAR and curl exports.