Skip to content

Connect your AI

Markdown

Connect 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 this server URL to your assistant. Claude and ChatGPT call it a connector, the others an MCP server:

https://api.eu.apigami.com/mcp

Your 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.

  1. Open Customize > Connectors (claude.ai/customize/connectors; in the desktop app, Customize in the sidebar).
  2. Choose Add custom connector and paste the server URL in MCP server URL. Leave the OAuth settings as they are.
  3. Choose Add, then sign in on the Apigami page that opens. The connector shows as Connected.
  4. 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.

  1. In Settings > Security and login, turn on Developer mode.
  2. Open chatgpt.com/plugins, choose +, then Add custom MCP server.
  3. Name it Apigami, paste the server URL in Server URL under Connection, and set Authentication to OAuth.
  4. Choose I understand and want to continue, then Create as a plugin.
  5. In your personal plugins, open Apigami and choose + to install it. Sign in on the Apigami page when it opens.
  6. Start a new chat in the Work tab, type @ and choose Apigami.

Claude Code:

Terminal window
claude mcp add --transport http --scope user apigami https://api.eu.apigami.com/mcp

Then 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.

~/.cursor/mcp.json
{
"mcpServers": {
"apigami": { "url": "https://api.eu.apigami.com/mcp" }
}
}

Codex CLI:

Terminal window
codex mcp add apigami --url https://api.eu.apigami.com/mcp
codex mcp login apigami

VS 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.

  1. 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.
  2. 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.
  3. 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.

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.

  1. The assistant asks for a link, and names itself <client> on <machine or project>, such as Claude Code on ada-laptop, so that you recognise it in your account later.
  2. 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.
  3. 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/apps routes 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.

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:

Terminal window
python3 - "Claude Code on ada-laptop" <<'PY'
import json, os, sys, urllib.error, urllib.request
request = 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']}.")
PY

The name takes letters, digits, spaces and . _ ( ) -, 60 characters at most, and names neither a domain nor Apigami. The link expires after 15 minutes.

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.

Terminal window
python3 - <<'PY'
import json, os, sys, time, urllib.error, urllib.request
state_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() + 450
while 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.')
PY

It 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.

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:

Terminal window
claude mcp remove apigami --scope local 2>/dev/null
claude mcp remove apigami --scope user 2>/dev/null
claude 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:

Terminal window
python3 - <<'PY'
import json, os
token = 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)
PY

Codex CLI, in its config.toml:

Terminal window
codex mcp remove apigami >/dev/null 2>&1
python3 - <<'PY'
import os
token = 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')
PY

Where 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:

Terminal window
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.

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.

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.

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.