Make Your First Gateway Call with a Machine User
This tutorial takes you from nothing to a working, authenticated tool call against the Willow gateway using a machine user and curl. Machine users are API accounts for bots, scripts, and automations, so this is the path to reach your MCP tools programmatically rather than through an interactive AI client.
By the end, you will have:
- created a machine user and revealed its credentials
- given it access to an MCP server through a group
- completed the MCP handshake against the gateway
- listed the tools the machine user can reach
- called one of those tools and seen the result
Prerequisites
You need:
- admin access to Willow
- a deployed Willow MCP gateway
- at least one published MCP server with tools enabled
curlor any HTTP client
If you have not published an MCP server yet, complete Add and Configure Your First MCP Server first. A machine user with no MCP servers in its groups has nothing to call.
Step 1: Create a machine user
In the admin dashboard, open Manage > Machine Users and select Add Machine User. Enter a name and select Save.

Each machine user has an Access Key and a Secret. On the machine user's row, select the eye icon in the Access Key and Secret columns to reveal each value, and copy both. You will send them together as the bearer token.
Step 2: Give the machine user access through a group
A machine user only reaches tools from the MCP servers assigned to the groups it belongs to. Open Manage > Groups, open the row menu for a group that has your MCP server assigned, and select Edit Users. Check your machine user and select Done.
If you skip this step, the handshake still succeeds but tools/list comes back empty.
Step 3: Complete the MCP handshake
Your gateway URL is the Your Basecamp link in the top bar of the admin app, with /mcp appended (for example https://your-org.mcp-s.com/mcp).
Authenticate by joining the access key and secret with a colon and sending them as a bearer token. Send an initialize request to open the MCP session:
curl -X POST https://your-org.mcp-s.com/mcp \
-H "Authorization: Bearer <ACCESS_KEY>:<SECRET>" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": { "name": "my-script", "version": "0.1" }
}
}'
A successful response confirms the session and identifies the gateway:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": { "tools": {}, "prompts": {}, "resources": {} },
"serverInfo": { "name": "mcp-s", "version": "1.0.0" }
}
}
Both halves of the credential are required. Sending the access key or the secret on its own returns 401 Unauthorized with {"error": "invalid_token"}.
Step 4: List the tools you can reach
Ask the gateway for the tools available to this machine user:
curl -X POST https://your-org.mcp-s.com/mcp \
-H "Authorization: Bearer <ACCESS_KEY>:<SECRET>" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}'
Tools come back namespaced by their MCP server, in the form {server-slug}__{tool}. For example, a search-messages tool on a server with the slug slack appears as slack__search-messages. If the list is empty, the machine user is not in a group that has an MCP server assigned (revisit Step 2).
Step 5: Call a tool
Use a tool name from the previous response in a tools/call request:
curl -X POST https://your-org.mcp-s.com/mcp \
-H "Authorization: Bearer <ACCESS_KEY>:<SECRET>" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": { "name": "slack__search-messages", "arguments": {} }
}'
The response contains the tool's output under result.content.
Verify it worked
You are done when all of these are true:
- the machine user appears in the Machine Users table
- the
initializecall returns aresultwithserverInfo.nameofmcp-s tools/listreturns at least one tool, namespaced{server}__{tool}- a
tools/callreturns aresult - the call appears in Monitor > Logs, attributed to the machine user
Next steps
- Set Up Client-Credentials Auth for a Machine User with Okta to reach internal MCP servers that use proxy passthrough
- Programmatic Gateway Access for the full endpoint and error reference
- Machine Users to rotate the secret and manage owners
- Groups to scope which tools the machine user can reach