Accessing MCP with a Machine Token
AI in Formwork Published on September 08, 2026

Accessing MCP with a Machine Token

API tokens for CI pipelines, scripts and command-line tools that cannot sign in through a browser.

AI assistants like Claude or ChatGPT connect to Formwork by signing in through your browser. A CI pipeline, a script or a command-line tool cannot do that. For those, Formwork has API tokens: a secret string you create once in Formwork and give to the machine, which then talks to the same MCP server on your behalf.

Typical uses:

  • A release pipeline that files its test results and screenshots into a Formwork test run after every build.
  • A script that bulk-creates or updates items from a spreadsheet.
  • Claude Code or Codex on a machine where a browser sign-in is impractical.

Creating a token

  1. In Formwork, switch to the company the token should work in. A token belongs to exactly one company and cannot be moved.
  2. Go to Settings → API access and click New token. You'll be asked to re-enter your password first.
  3. Give the token a name that says what uses it, e.g. GitHub Actions release pipeline.
  4. Pick the access level:
    • Read: query, read, search and trace.
    • Read and write: additionally create, update, upload files and send items for review. If your role in the company is viewer, only read is offered.
  5. Pick how long the token should live: 30 days, 90 days or 1 year.
  6. Click Create token. Formwork shows the token once. Copy it now and store it where your pipeline or script keeps its secrets. If you lose it, revoke it and create a new one.

Tokens look like this:

fw_G80tbc3vgC4uCsPFNK_wC72MZoWeYEjb9tVlk0ivYhE

What a token can do

A token acts as you in the company it belongs to. It can never do more than your own account can: a read-and-write token used by a viewer still cannot change anything, and a token never approves, releases, rejects, archives or deletes anything. If your role in the company changes later, the token follows it. If you leave the company, the token stops working.

Using a token

Send it as a bearer token to https://app.openregulatory.com/mcp. Every request is a JSON-RPC message; no session or handshake is needed.

From the command line

curl -X POST https://app.openregulatory.com/mcp \
  -H "Authorization: Bearer fw_..." \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

That lists the tools the token can use: five for a read token, nine for a read-and-write token. Calling a tool looks like this:

curl -X POST https://app.openregulatory.com/mcp \
  -H "Authorization: Bearer fw_..." \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "query_formwork_resources",
      "arguments": { "resource_type": "capa", "filters": { "status": "open" } }
    }
  }'

The result comes back as JSON under result.structuredContent. For the full list of tools, resource types, filters and fields, see MCP tools reference. The Accept header must list both application/json and text/event-stream, even though the answer is plain JSON.

From Claude Code

claude mcp add --transport http formwork https://app.openregulatory.com/mcp \
  --header "Authorization: Bearer fw_..."

No sign-in step: Claude Code sends the token with every request.

From Codex CLI

Codex reads the token from an environment variable rather than storing it in its config:

export FORMWORK_TOKEN=fw_...
codex mcp add formwork --url https://app.openregulatory.com/mcp --bearer-token-env-var FORMWORK_TOKEN

From a GitHub Actions workflow

Store the token as a repository secret (e.g. FORMWORK_TOKEN) and use it from a step:

- name: File test results in Formwork
  env:
    FORMWORK_TOKEN: ${{ secrets.FORMWORK_TOKEN }}
  run: |
    curl -sS -X POST https://app.openregulatory.com/mcp \
      -H "Authorization: Bearer $FORMWORK_TOKEN" \
      -H "Content-Type: application/json" \
      -H "Accept: application/json, text/event-stream" \
      -d @update-test-run.json

where update-test-run.json holds the tools/call message for the update you want to make.

Uploading files

Screenshots, PDFs and other evidence are uploaded in two steps: ask the upload_formwork_file tool for an upload URL by passing the file's size, then POST the file to that URL. The URL is valid for 10 minutes, works once, and needs no token:

# 1. ask for an upload URL
curl -sS -X POST https://app.openregulatory.com/mcp \
  -H "Authorization: Bearer $FORMWORK_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"upload_formwork_file","arguments":{"filename":"report.pdf","byte_size":184223}}}'

# 2. upload the file to the upload_url from the answer
curl -sS -X POST "<upload_url>" -F "[email protected]"

The second call answers with an attachment_signed_id. Pass it in attachment_signed_ids when updating a system test run, user test run, document or record to attach the file. The id is valid for 24 hours; upload and attach in the same run.

Managing tokens

Settings → API access lists your tokens with their company, access level, creation and expiry dates, when each was last used, and its status. From there you can:

  • Extend an active token by 30 days, 90 days or a year. A token never runs more than a year from today. Extend before it expires: an expired token stays expired, create a new one instead.
  • Revoke a token. Anything using it stops working immediately.

Company admins see every token bound to their company, with its owner, under Settings → API access in the company section, and can revoke any of them.

Keeping tokens safe

  • Treat a token like a password: store it in your CI's secret store or a password manager, never in a repository or a chat message.
  • All tokens start with fw_, which makes them easy to catch with a secret-scanning rule.
  • Give each machine its own token with a name that says what it is for. When one pipeline goes away, revoke just that token.
  • Pick the shortest lifetime that works. Read access is enough for anything that only reports.
  • If a token has leaked, revoke it in Formwork and create a new one. Revocation takes effect instantly.

Troubleshooting

  • 401 Unauthorized: the token was revoked, has expired, you are no longer a member of its company, or the Authorization header is missing or malformed. Create or extend a token in Formwork and check the header reads Bearer fw_....
  • "Tool not found" for create_formwork_resource or another writing tool: the token is read-only. Create a read-and-write token.
  • "you do not have edit access for this company" or a forbidden answer: the token works, but your own account cannot make that change. Ask a company admin about your role.
  • The response is not JSON: make sure the Accept header lists both application/json and text/event-stream.
  • The upload URL is rejected: it expired (10 minutes), was already used, or the file is larger than the byte_size you declared. Ask for a fresh URL.

As always, reach out in the customer support chat in the bottom right corner if you run into any trouble.