Connect your AI
MarkdownConnect your AI assistant to Apigami and ask it to work with the pages you already have open. You choose which sites it can access.
Add Apigami
Section titled “Add Apigami”Add this server URL to your assistant. Claude and ChatGPT call it a connector, the others an MCP server:
https://api.eu.apigami.com/mcpYour assistant signs in through your browser, with OAuth, the first time it uses the server. In Claude and ChatGPT that sign-in opens in the browser you use them from. A coding assistant needs a browser on the machine where it runs; without one, in a terminal on a server or in CI, use the agent sign-in instead.
Claude, on claude.ai, in the desktop app or in Cowork. A connector added once shows up in all three, and in Claude Code signed in with the same account.
- Open Customize > Connectors (claude.ai/customize/connectors; in the desktop app, Customize in the sidebar).
- Choose Add custom connector and paste the server URL in MCP server URL. Leave the OAuth settings as they are.
- Choose Add, then sign in on the Apigami page that opens. The connector shows as Connected.
- In a conversation, choose +, then Connectors, and turn Apigami on. The first time a tool runs, choose Always allow or Allow once.
Cowork loads connectors when a task starts: start a new task once the connector is added. The Free plan allows one custom connector. On a Team or Enterprise plan, an Owner adds it first, in Organization settings > Connectors: Add, Custom, then Web if asked. Each member then finds it under Customize > Connectors, with the Custom label, and chooses Connect.
The connector runs from Claude’s side, not in the sandbox where Claude runs code: it works even when that sandbox’s network does not reach Apigami.
ChatGPT, on the web, with a paid plan. On a Business, Enterprise or Edu workspace, an admin may have to allow custom MCP servers first.
- In Settings > Security and login, turn on Developer mode.
- Open chatgpt.com/plugins, choose +, then Add custom MCP server.
- Name it Apigami, paste the server URL in Server URL under Connection, and set Authentication to OAuth.
- Choose I understand and want to continue, then Create as a plugin.
- In your personal plugins, open Apigami and choose + to install it. Sign in on the Apigami page when it opens.
- Start a new chat in the Work tab, type
@and choose Apigami.
Claude Code:
claude mcp add --transport http --scope user apigami https://api.eu.apigami.com/mcpThen open /mcp, choose apigami and Authenticate, or run claude mcp login apigami from the
shell. Signed in with a Claude account, Claude Code also lists the connectors added on claude.ai.
Cursor: add the server to ~/.cursor/mcp.json, then choose Connect next to it on the
Customize page.
{ "mcpServers": { "apigami": { "url": "https://api.eu.apigami.com/mcp" } }}Codex CLI:
codex mcp add apigami --url https://api.eu.apigami.com/mcpcodex mcp login apigamiVS Code: run MCP: Add Server from the Command Palette, choose HTTP, paste the server URL,
name it apigami, and add it for your user rather than the workspace.
Other MCP clients that support HTTP and OAuth use the same server URL.
Connect your browser
Section titled “Connect your browser”- Sign in on the page that opens with your email. No account yet? One is created on the spot; there’s no password, you sign in with a code sent to that address.
- Authorize your AI client. If Apigami is installed in the browser you’re signing in from and that browser isn’t attached to your account yet, an Apigami window opens in it, showing your account’s email: choose Allow to attach the browser. Closing the window attaches nothing. An older version of Apigami, before 0.15.0, is attached without a window.
- Return to the conversation.
The MCP server works once your email address is confirmed. Until then, your assistant tells you a confirmation email has just been sent: open its link, then ask again. An account created from a team invitation is already confirmed.
To use another browser, ask your assistant: apigami_status gives a link to open in that Chrome.
Sign in if the page asks, then choose Continue. From Apigami 0.15.0, an Apigami window opens in
that browser, showing your account’s email: choose Allow to attach it. Closing the window
attaches nothing. The page then confirms the browser is attached to your account.
Agent sign-in
Section titled “Agent sign-in”Connect an assistant that has no browser of its own, from a network that reaches
api.eu.apigami.com: a terminal on a server, or CI. The assistant asks Apigami for a link and gives
it to you; you open it on any device, your phone included, sign in, and approve. The assistant then
receives a token for your account and adds the server to its MCP settings. When a browser runs on the
same machine as the assistant, the OAuth sign-in above is shorter. In Claude, in ChatGPT, or in a
sandbox whose network blocks Apigami, add the connector instead.
- The assistant asks for a link, and names itself
<client> on <machine or project>, such asClaude Code on ada-laptop, so that you recognise it in your account later. - You open the link, check that the page shows the code the assistant gave you, accept the terms the first time, and choose Authorize. Only authorize a link you just asked your own assistant for: whoever sent it would act on your account.
- The assistant collects its token, adds Apigami to its MCP settings for your user, never for a
project, and asks you to restart it so that it loads the server. Until then, it can already call
the
/v1/appsroutes with the same token.
The token opens what the OAuth sign-in opens: the MCP tools, and the routes that create, write,
deploy and publish your team’s applications. It never manages your team, its API keys or its
webhooks, never deletes an application and never creates another access. It lasts 90 days, and
apigami_status warns two weeks before. It appears in your
account under Your agents’ access, where Remove access ends
it at once; the applications it created stay.
Ask for a link
Section titled “Ask for a link”The assistant runs this, with its own name. It keeps the request in
~/.config/apigami/agent-sign-in.json and prints only the link and the code to give you:
python3 - "Claude Code on ada-laptop" <<'PY'import json, os, sys, urllib.error, urllib.requestrequest = urllib.request.Request( 'https://api.eu.apigami.com/v1/device/code', data=json.dumps({'agent_name': sys.argv[1]}).encode(), headers={'Content-Type': 'application/json'},)try: answer = json.load(urllib.request.urlopen(request, timeout=30))except urllib.error.HTTPError as error: sys.exit(json.load(error).get('error_description'))path = os.path.expanduser('~/.config/apigami/agent-sign-in.json')os.makedirs(os.path.dirname(path), mode=0o700, exist_ok=True)with open(os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600), 'w') as file: json.dump({'device_code': answer['device_code'], 'interval': answer['interval']}, file)print(f"Open {answer['verification_uri_complete']} and check that the page shows {answer['user_code']}.")PYThe name takes letters, digits, spaces and . _ ( ) -, 60 characters at most, and names neither a
domain nor Apigami. The link expires after 15 minutes.
Wait for the answer
Section titled “Wait for the answer”This loop asks whether you decided, slows down when Apigami asks it to, waits and asks again when
Apigami or the network does not answer, and stops on a refusal or an expired link. It writes the
token to ~/.config/apigami/agent-token, readable by your user only, and never prints it. It gives
up after seven and a half minutes, within the time an assistant’s command may run: run it again as
it is while the link is still valid.
python3 - <<'PY'import json, os, sys, time, urllib.error, urllib.requeststate_path = os.path.expanduser('~/.config/apigami/agent-sign-in.json')token_path = os.path.expanduser('~/.config/apigami/agent-token')state = json.load(open(state_path))interval, deadline = state['interval'], time.monotonic() + 450while time.monotonic() < deadline: request = urllib.request.Request( 'https://api.eu.apigami.com/v1/device/token', data=json.dumps({'device_code': state['device_code']}).encode(), headers={'Content-Type': 'application/json'}, ) try: answer = json.load(urllib.request.urlopen(request, timeout=60)) except urllib.error.HTTPError as error: try: answer = json.load(error) if error.code < 500 else {} except ValueError: answer = {} except (urllib.error.URLError, TimeoutError, ValueError): answer = {} if 'access_token' in answer: with open(os.open(token_path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600), 'w') as file: file.write(answer['access_token']) os.remove(state_path) print(f"Approved for {answer['email']}. The token is in {token_path}, not shown.") sys.exit() if not answer or answer.get('error') in ('authorization_pending', 'slow_down'): interval = answer.get('interval', interval) time.sleep(interval) continue sys.exit(f"{answer.get('error')}: {answer.get('error_description')}")sys.exit('No answer yet. Run this again while the link is valid.')PYIt ends on what to do next: after access_denied, you refused, so the assistant does not start again
unless you ask it to; after expired_token, it asks for a new link; after invalid_grant, the token
was already collected.
Add the server to your client
Section titled “Add the server to your client”Each snippet reads the token from its file, so it never appears in the conversation. Always add the
server for your user: a project file such as .mcp.json or .vscode/mcp.json ends up committed,
token included.
Claude Code. Remove any earlier apigami server first, or the new one is refused, or the old
OAuth one keeps answering:
claude mcp remove apigami --scope local 2>/dev/nullclaude mcp remove apigami --scope user 2>/dev/nullclaude mcp add --transport http --scope user apigami https://api.eu.apigami.com/mcp \ --header "Authorization: Bearer $(cat ~/.config/apigami/agent-token)"Cursor, in ~/.cursor/mcp.json:
python3 - <<'PY'import json, ostoken = open(os.path.expanduser('~/.config/apigami/agent-token')).read().strip()path = os.path.expanduser('~/.cursor/mcp.json')config = json.load(open(path)) if os.path.exists(path) else {}config.setdefault('mcpServers', {})['apigami'] = { 'url': 'https://api.eu.apigami.com/mcp', 'headers': {'Authorization': f'Bearer {token}'},}os.makedirs(os.path.dirname(path), exist_ok=True)with open(os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600), 'w') as file: json.dump(config, file, indent=2)os.chmod(path, 0o600)PYCodex CLI, in its config.toml:
codex mcp remove apigami >/dev/null 2>&1python3 - <<'PY'import ostoken = open(os.path.expanduser('~/.config/apigami/agent-token')).read().strip()path = os.path.join(os.path.expanduser(os.environ.get('CODEX_HOME', '~/.codex')), 'config.toml')os.makedirs(os.path.dirname(path), exist_ok=True)with open(os.open(path, os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0o600), 'a') as file: os.chmod(path, 0o600) file.write('\n[mcp_servers.apigami]\nurl = "https://api.eu.apigami.com/mcp"\n' f'http_headers = {{ Authorization = "Bearer {token}" }}\n')PYWhere the environment already holds its secrets, in CI for example, keep the token in a variable
instead: codex mcp add apigami --url https://api.eu.apigami.com/mcp --bearer-token-env-var APIGAMI_AGENT_TOKEN, or "Authorization": "Bearer ${env:APIGAMI_AGENT_TOKEN}" in Cursor’s
headers.
VS Code, in the mcp.json of your user profile (MCP: Open User Configuration), never in a
workspace’s .vscode/mcp.json:
{ "servers": { "apigami": { "type": "http", "url": "https://api.eu.apigami.com/mcp", "headers": { "Authorization": "Bearer <the token in ~/.config/apigami/agent-token>" } } }}Without an MCP client, the server answers JSON-RPC over HTTP, each request standing alone:
curl -s https://api.eu.apigami.com/mcp \ -H "Authorization: Bearer $(cat ~/.config/apigami/agent-token)" \ -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"apigami_status","arguments":{}}}'A client usually loads a server added during a session only at the next one: the assistant asks you
to restart it. Meanwhile the same token works as Authorization: Bearer on the routes of
Push a version.
When the token expires or is removed, Claude Code, Cursor and Codex show the apigami server as
failed or needing authentication, without saying why. A new agent sign-in repairs it: ask for a new
link, then run the snippet of your client again.
Try a first prompt
Section titled “Try a first prompt”Open example.com in the connected browser, then ask:
Show my connected browsers, then read the text of my example.com tab.The first use of the site opens an approval window. Allow access, then let the assistant continue. A refusal is remembered until you change it from Apigami’s menu in your browser.
What your assistant can do
Section titled “What your assistant can do”It can list tabs, read page content and send requests using your existing sign-in. It only reaches the browsers attached to your own account, never a teammate’s, and the sites you allow it are yours alone: an approval given to your assistant doesn’t carry over to an app you build, and the other way round.
Behind the scenes, Apigami gives your account its own private MCP app, shared by every AI client you connect: allowing a site once in Claude Code allows it in your other clients too. It doesn’t appear in the dashboard, and there’s no default app shared by your team.
Your cookies stay in the browser by default. Requests and cookie-based anti-CSRF headers are handled
there, and cookie_get returns a cookie’s name, scope, length and flags, not its value. Only
cookie_get with redact: false returns the raw value, which then reaches the conversation.
Available tools
| Tool | Does |
|---|---|
apigami_status |
Who your AI acts for, the browsers attached to your account, the sites you already allow. Call it first |
request_fetch |
Run a request from your browser, with your session for that site — the request.fetch operation of POST /call, with as_client_call to get the payload for your own code |
tabs_list |
The tabs open on a site |
page_read |
Read a tab you already have open: outline maps the page and hands back reusable selectors, markdown its readable content, text its innerText, html the cleaned fragment to write an extractor against |
page_storage |
The localStorage and sessionStorage keys of a tab, with the type and a preview of each value — a key whose name looks like a credential is measured, never returned |
apigami_docs |
This documentation, whole or by keyword, without leaving the conversation |
Network and console tools for developers
Apigami Dev Assistant is a separate install for exploring a site’s network requests and console. Capture starts on the first call and stops after 30 minutes without one.
| Tool | Does |
|---|---|
network_endpoints |
The requests of a tab, grouped by endpoint — /api/contacts/{id}, GraphQL operations by name — with counts, statuses and sizes. A page that made 1 400 requests becomes 30 lines |
network_requests, network_get |
One request at a time: headers, body, the shape of a JSON body, a JSONPath into it |
network_requests |
Where a string appears — url, headers, bodies — with the requests that carry it |
network_mark |
Name a moment (“clicked Load more”) and read only what came after |
console_list |
Console messages and exceptions of the tab |
Cookie, Set-Cookie and Authorization values are dropped in the browser before anything is
sent; the AI sees their length, never their value.
Turn a request into app code
Section titled “Turn a request into app code”Once you’ve explored a site, ask your assistant to use request_fetch with as_client_call.
It returns the request body and HTTP headers to use with POST /call and
your app’s API key, with your user_ref and install_ref for your team’s apps. That call goes
through once you’ve connected to your app and allowed the site there: what you
allowed your assistant is for the MCP server alone. The export requests gzip: params.responseType: "binary", outer
Accept: application/octet-stream and Accept-Encoding: gzip. Send all three, even for
text or JSON from the site, and enable gzip decoding in your HTTP client, such as curl --compressed.
Read the raw response body, X-Apigami-Status for the site’s status and X-Apigami-Headers
for its JSON-encoded headers. Apigami errors still return non-2xx JSON. See
gzip and binary responses for a complete example.
The MCP tool itself keeps returning text or base64; its headers input targets the site,
so putting these Apigami transport headers there does not enable gzip.
There is no store of ready-made applications yet: request_fetch runs any request with the user’s session, and network_endpoints shows what a site’s own pages call.
To get Apigami Dev Assistant while its listing is private, contact us.