Connect an agent
The MCP server gives an agent two tools, search and fetch. They use the same request and response shapes as the REST API, run the same routing and limit checks, and write the same traces. Use MCP when an agent does the work, and REST when your own code does.
You need a running Polyweb stack (Quick start) and a project API key with the search.execute and fetch.execute scopes (Project API keys).
Server address
Section titled “Server address”With Docker, the MCP server listens at http://localhost:8000/mcp (host port MCP_PORT, default 8000). For another machine, replace localhost with your server’s address. In a manual setup the port comes from POLYWEB_MCP_PORT, and the server binds to 127.0.0.1 unless you set POLYWEB_MCP_HOST or pass --host.
Every request to /mcp must carry your project API key:
Authorization: Bearer fs_live_REPLACE_MEOnly project API keys work. Sign-in tokens from the dashboard are rejected, and so are requests with no key.
Codex, Claude Code, and OpenCode
Section titled “Codex, Claude Code, and OpenCode”1. Save your API key. The key needs the search.execute and fetch.execute scopes. These commands save it for future terminal sessions and load it into the current session. Replace fs_live_REPLACE_ME with your key.
Save the variable for your Windows user, then load it into this terminal:
[Environment]::SetEnvironmentVariable("POLYWEB_API_KEY", "fs_live_REPLACE_ME", "User")$env:POLYWEB_API_KEY = [Environment]::GetEnvironmentVariable("POLYWEB_API_KEY", "User")Restart terminal and agent apps that were open before this change. See PowerShell environment variables.
Run once to add the key to your zsh startup file and load it now:
printf '\nexport POLYWEB_API_KEY="fs_live_REPLACE_ME"\n' >> "${ZDOTDIR:-$HOME}/.zshrc"source "${ZDOTDIR:-$HOME}/.zshrc"New interactive zsh terminals load this file. See zsh startup files.
Run once to add the key to your Bash startup file and load it now:
printf '\nexport POLYWEB_API_KEY="fs_live_REPLACE_ME"\n' >> ~/.bashrcsource ~/.bashrcNew interactive non-login Bash terminals load this file. For login shells, make sure your ~/.bash_profile or ~/.profile loads ~/.bashrc. See Bash startup files.
On macOS and Linux, start your agent from the terminal. Desktop launchers do not load these shell profiles. To change the saved key later, edit the key line in the startup file.
2. Add the MCP server. Pick your agent. The server address is http://localhost:8000/mcp.
The command reads the variable by name, so it is the same on every system.
codex mcp add polyweb --url http://localhost:8000/mcp --bearer-token-env-var POLYWEB_API_KEYcodex mcp listSee the Codex CLI reference.
Your shell expands the variable inside double quotes. Claude Code saves the expanded key in its user configuration.
In PowerShell:
claude mcp add --transport http --scope user polyweb http://localhost:8000/mcp --header "Authorization: Bearer $env:POLYWEB_API_KEY"In zsh or bash:
claude mcp add --transport http --scope user polyweb http://localhost:8000/mcp --header "Authorization: Bearer $POLYWEB_API_KEY"Run claude mcp list, or type /mcp in Claude Code, to check the connection. See the Claude Code MCP guide.
Add this to opencode.json in your project directory. OpenCode reads {env:POLYWEB_API_KEY} from your environment. The file is the same on every system and contains no API key. This format is for OpenCode v2, which uses mcp.servers.
{ "mcp": { "servers": { "polyweb": { "type": "remote", "url": "http://localhost:8000/mcp", "oauth": false, "headers": { "Authorization": "Bearer {env:POLYWEB_API_KEY}" } } } }}Run opencode mcp list to check the connection. See the OpenCode MCP servers docs.
For a remote server, replace localhost in the address with your server’s address.
Cursor and other HTTP clients
Section titled “Cursor and other HTTP clients”Clients that read an mcpServers JSON file (Cursor’s mcp.json, for example) accept a URL plus headers. Field names can differ between client versions, so check your client’s docs if the file is rejected.
{ "mcpServers": { "polyweb": { "url": "http://localhost:8000/mcp", "headers": { "Authorization": "Bearer fs_live_REPLACE_ME" } } }}Some clients, such as those that use .mcp.json, also want "type": "http" next to the URL.
Local stdio clients
Section titled “Local stdio clients”For Docker, use the HTTP setup above. The published port serves HTTP only. Stdio requires the agent to start a process and connect to its stdin and stdout.
The Docker example below starts a separate stdio process inside the container through docker compose exec -T. The agent needs the Docker CLI and access to the running mcp container. For agents on another machine, use HTTP.
Replace /path/to/polyweb-mcp with your checkout path and fs_live_REPLACE_ME with your key.
{ "mcpServers": { "polyweb": { "command": "docker", "args": [ "compose", "-f", "/path/to/polyweb-mcp/compose.yaml", "exec", "-T", "-e", "POLYWEB_MCP_BEARER_TOKEN=fs_live_REPLACE_ME", "mcp", "uv", "run", "--no-sync", "polyweb-mcp", "--transport", "stdio" ] } }}In a manual setup, run the server from your checkout instead:
{ "mcpServers": { "polyweb": { "command": "uv", "args": ["run", "polyweb-mcp", "--transport", "stdio"], "cwd": "/path/to/polyweb-mcp", "env": { "POLYWEB_MCP_BEARER_TOKEN": "fs_live_REPLACE_ME" } } }}Over stdio the key comes from the POLYWEB_MCP_BEARER_TOKEN environment variable of the server process. Polyweb reads it from the process environment only, never from .env. Without it, every tool call is rejected.
Check the connection
Section titled “Check the connection”Ask your agent to list its tools. It should see exactly two: search and fetch. Then ask it a question that needs the web, such as the prompt below.
You have two Polyweb tools:
searchandfetch. To answer “What is new in solar panels?”, callsearchwith that question andlimit5. Then callfetchon the best result URL. Quote the source URL in your answer.
To test the key without an agent, send the same search over REST. A 200 response means the key and your provider setup work.
curl -X POST http://localhost:8001/search \ -H "Authorization: Bearer fs_live_REPLACE_ME" \ -H "Content-Type: application/json" \ -d '{"query": "solar panel prices", "limit": 1}'Each call shows up on the project’s Activity page (Activity and traces).
Transport options
Section titled “Transport options”| Option | Environment variable | Meaning |
|---|---|---|
--transport streamable-http (default) or stdio |
POLYWEB_MCP_TRANSPORT |
Which transport to serve. The flag wins over the variable. |
--stateless |
POLYWEB_MCP_STATELESS (true) |
Stateless HTTP, for proxies or several replicas. In Docker, set the variable on the mcp service. |
--host, --port |
POLYWEB_MCP_HOST, POLYWEB_MCP_PORT |
Bind address and port. A manual setup has no default port and refuses to start without one. |
| none | POLYWEB_MCP_BEARER_TOKEN |
Project API key for stdio only. HTTP never reads it. |
How keys are checked
Section titled “How keys are checked”The server verifies the key on every tool call, not only when the session starts. A key that you revoke, rescope, or let expire stops working on its next call, and so does a key of an archived project. A rejected call fails before any provider is used, so it costs nothing.
| What you see | Cause | Fix |
|---|---|---|
HTTP 401 on /mcp |
No key, a malformed Authorization header, or an invalid key. |
Send one Authorization: Bearer fs_live_... header with a valid key. |
Tool error authentication is required |
The key is invalid, expired, or revoked (or, over stdio, POLYWEB_MCP_BEARER_TOKEN is unset). |
Create a fresh project API key. |
Tool error execution is not permitted |
The key lacks search.execute or fetch.execute for that tool. |
Create a key with both scopes. |
Tool error project is unavailable |
You passed a project_id that is not the key’s project. |
Omit project_id. |
Tool error project is archived |
The key’s project is archived. | Ask a project admin to unarchive it. |
Next steps
Section titled “Next steps”searchtool: parameters and response fields.fetchtool: read one page.- Authentication and keys: how project API keys differ from sign-in sessions.
