Skip to main content

Wrap an HTTP API as MCP Tools

Use this guide when the service you want to reach has an HTTP API but no MCP server. The MCP from API connector puts Willow in front of that API and lets you define each operation you want to expose as a tool.

This is a different errand from Add an MCP Server, which points Willow at something that already speaks MCP. Here you are building the MCP surface yourself.

Prerequisites

You need:

  • admin access to Willow
  • the API's base URL, and credentials for it if it requires any
  • the endpoints you intend to expose, and their request and response shapes

Step 1: Add the connector

  1. Open Build > MCP Servers > Add MCP Server.
  2. Search for MCP from API and hover the card.
  3. Select Use, then Create.

The server is created immediately with Needs Setup on its Overview tab and no tools. It reports Built-In transport, so Willow owns its configuration: unlike a custom MCP server, its Settings tab has no MCP Configuration or Proxy Configuration sections. You configure it through the Setup and Request Settings sections instead.

Step 2: Choose how it authenticates

Open the Setup tab and pick the mode that matches the API:

ModeUse when
API KeyOne key serves every caller and you manage it centrally. Takes the key and an optional expiration date, which raises an alert as it approaches.
Client CredentialsThe API issues server-to-server tokens from a client ID and secret.
API Key Per UserEach user supplies their own key, so calls are attributable to individuals.
NoneThe API needs no authentication.

Select Save Changes. This connector does not offer the OAuth or passthrough modes you may have seen elsewhere; see Configure authentication for why the sets differ.

Check client credentials before saving

Client Credentials has a Test credentials button below the form. It requests a token from the Token URL using the values currently on screen and reports what happened, so you can confirm the configuration without saving it or running a tool.

The result distinguishes the cases that otherwise look identical:

  • Success — the token endpoint issued an access token. The credentials and the token URL are both good.
  • Rejected — the endpoint answered but refused the grant, quoting its own reason (such as invalid_client). This is a credentials or scope problem.
  • Unreachable — the endpoint could not be contacted at all, naming the cause (DNS, refused connection, timeout, or an untrusted TLS certificate). This is a network or certificate problem between Willow and your identity provider, not a wrong secret. On a self-hosted install it usually means egress policy or a missing internal CA, and it is worth resolving before you add tools.

If the endpoint rejects the request as malformed, the result also suggests toggling Send credentials as JSON body — some providers accept the client secret only as JSON, others only as form encoding.

Three limits are worth knowing. The test gives up after ten seconds, so an endpoint that never answers is reported as unreachable rather than leaving the button spinning. On the hosted service the Token URL must use https, since the test sends your client secret to it; self-hosted installs also accept http, where an internal identity provider without TLS is a normal thing to have. And the button is unavailable when the client secret is held in an external KMS, because the test needs the secret itself.

Step 3: Point it at the API

Open Settings > Request Settings.

  1. Turn on Override base URL and enter the API's Base URL. Every tool you define resolves its path against this.
  2. Add any Headers the API expects, as key and value pairs, using Add Header for more than one.
  3. Select Save Changes.

Header values support templating. Use {{headers.<name>}} to forward a header from the incoming request, for example {{headers.authorization}} to pass the caller's own credential straight through. For static secrets, reference the vault as {{vault.SECRET_NAME}} rather than pasting the value. See Vault.

Step 4: Define the tools

Open the Tools tab and select New Tool. Willow offers three starting points:

Start fromWhat it does
Generate with AIDescribe what the tool should do and Willow generates the definition. Requires Bring Your Own AI.
Start from ExistingCopies an existing tool on this server as a starting point, which is the fastest route once you have defined one and want a near-duplicate.
From JSONPastes a tool definition as JSON. Use this when you already hold the shape, for example generated from an API specification.

All three land in the same editor, with whatever they produced filled in.

The JSON shape

From JSON requires name, description, and action. A complete definition looks like this:

{
"name": "Get User Profile",
"description": "Fetches user profile information by ID",
"action": {
"method": "GET",
"path": "/users/{id}",
"mapping": {
"params": "{ \"id\": $.userId }"
}
},
"inputSchema": {
"type": "object",
"properties": {
"userId": {
"type": "string",
"description": "The user ID to fetch"
}
},
"required": ["userId"]
}
}

path is relative to the Base URL you set in Step 3. inputSchema is standard JSON Schema and describes what the model passes in. mapping.params is a JSONata expression connecting the two: here it takes userId from the input and supplies it as the {id} path parameter.

The editor

Above the two-step wizard you set the Name, Description, and Slug. The slug, not the name, is what the MCP client sees, and it is capped at 60 characters. Willow normalizes it on save, so get user profile becomes get-user-profile. Annotation is a collapsible block for extra metadata, and the method and path show as a preview chip.

Step 1, Schema defines the input. Toggle between Form and JSON, use Generate from JSON Example to derive a schema from a sample payload, or Add Property to build it by hand. Each property takes a name, a type, and a description, plus Required and Constant value toggles.

Step 2, Mapping wires the input to the request. Params Mapping covers path parameters and is on when your definition supplied one, Query Mapping covers the query string, and Response Mapping shapes what comes back. Each opens with Edit.

Select Create Tool to finish. The tool appears on the Tools tab grouped by risk category, enabled.

Repeat for each endpoint you want to expose. There is no sync here: an HTTP API has no tool list for Willow to read, so every tool is one you define.

Step 5: Publish

  1. Review the tools you defined and the risk assessment on the Overview tab.
  2. Assign the server to a group under Connected Groups. Without one, no user can call it.
  3. Select Publish.

Verify it worked

You are done when the server shows active, at least one tool appears on the Tools tab, a test of that tool returns what the API returns, and the call appears in Monitor > Logs.

When a tool call cannot reach the API

If a tool fails with a gateway status such as 504, or with no response at all, the error includes a diagnosis field explaining which layer failed. Read it before checking your firewall or cluster: it already distinguishes the cases you would otherwise go looking for.

  • A gateway status (502, 503, 504) means something between Willow and the API answered instead of the API's own handler — typically an egress proxy, firewall, or load balancer. A 504 specifically means that hop gave up waiting. The tool and its arguments are not implicated.
  • No response, with a network code (ETIMEDOUT, ECONNREFUSED, ENOTFOUND, EHOSTUNREACH) means the request never completed a round trip. Confirm the gateway's network permits outbound access to the API's host.
  • No response, with a certificate code (UNABLE_TO_VERIFY_LEAF_SIGNATURE, SELF_SIGNED_CERT_IN_CHAIN, CERT_HAS_EXPIRED) means the connection was made but the certificate was not trusted. On a self-hosted install this is usually an internal CA missing from the gateway's trust store.
  • A connection dropped mid-request (ECONNRESET, ECONNABORTED, EPIPE) is the one ambiguous case, and the diagnosis says so. It is usually the network, but an API can also drop a connection whose request it rejects outright, so if outbound access is known to be open, check the size of the arguments you are sending.

Ordinary application errors (a 4xx, or a 500 from the API's own code) carry no diagnosis, because the API's response body describes those better than Willow can. The code and status fields are always present when the upstream supplied them.