From 2c05da7deca7e7c06ec01213d425fecc49e07486 Mon Sep 17 00:00:00 2001 From: Brian Fox Date: Fri, 7 Aug 2026 09:25:38 +0200 Subject: [PATCH 1/4] docs(workflows): say what to check when MCP tools don't load An empty tool list, a rejected credential and an unreachable server are the three ways a connector fails, and they need three different fixes. Forest Runtime now names which one it was in its logs, so point readers at that rather than leaving "check that all the expected tools are exposed" as the only guidance. Co-Authored-By: Claude Opus 5 (1M context) --- .../connect/integrations/mcp-servers.mdx | 10 ++++++++ product/process/workflows/forest-runtime.mdx | 25 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/get-started/connect/integrations/mcp-servers.mdx b/get-started/connect/integrations/mcp-servers.mdx index 1927350..04b5f81 100644 --- a/get-started/connect/integrations/mcp-servers.mdx +++ b/get-started/connect/integrations/mcp-servers.mdx @@ -99,3 +99,13 @@ If a tool isn't in the list above, connect any MCP server by URL: 5. Save your configuration. Learn more about building and hosting MCP servers in the [Claude MCP documentation](https://docs.claude.com/en/docs/agents-and-tools/remote-mcp-servers). + +## A connector's tools don't load + +The tool list comes back empty, or a workflow step using the connector fails. Check, in order: + +1. **The server exposes the tools you expect.** Reopen the connector in **Project Settings → Integrations** — an empty list means the server answered but published nothing, which is a server-side configuration problem, not a connection one. +2. **The credential is still valid.** A revoked or expired token fails the whole connector; reconnect it. +3. **Forest Runtime can reach the server.** A self-hosted runtime must have network access to the server's URL — a private address behind your VPN is reachable only from inside it. + +If you [self-host Forest Runtime](/product/process/workflows/forest-runtime), its logs name which of these it was, per server, at the default log level. diff --git a/product/process/workflows/forest-runtime.mdx b/product/process/workflows/forest-runtime.mdx index c13a69b..cc8a0d5 100644 --- a/product/process/workflows/forest-runtime.mdx +++ b/product/process/workflows/forest-runtime.mdx @@ -239,6 +239,29 @@ If your workflows include [MCP Tasks](/product/process/workflows/overview) backe The Docker image ships with [OpenTelemetry](https://opentelemetry.io/) APM built in, compatible with any OTLP backend (Datadog, Grafana Tempo, Jaeger, Honeycomb…). It is **off by default** and turns on as soon as you set `OTEL_EXPORTER_OTLP_ENDPOINT`. OpenTelemetry is bundled only in the Docker image, not the npm package. +### When an MCP step can't load its tools + +Forest Runtime logs the reason at `Error`, so it is in your logs without changing `LOG_LEVEL`: + +```json +{ + "level": "Error", + "message": "MCP servers failed to load tools", + "mcpServerName": "acme-crm", + "failures": [ + { "server": "acme-crm", "kind": "connection", "error": "connect ECONNREFUSED 10.0.4.12:8080" } + ] +} +``` + +`kind` tells you where to look: + +- `auth` — the server rejected the credential. Reconnect the connector, or renew its token. +- `connection` — unreachable, refused, or slower than the 15-second per-server load timeout. +- `unknown` — the server answered but the load failed anyway; `error` carries the reason. + +A server that answers but exposes no tools is not a failure: you get an empty tool list and no error. + ## Tuning Beyond the required variables, these optional knobs have sensible defaults and rarely need changing: @@ -247,7 +270,7 @@ Beyond the required variables, these optional knobs have sensible defaults and r | --- | --- | --- | | `HTTP_PORT` | `3400` | Port Forest Runtime's HTTP server listens on. | | `POLLING_INTERVAL_S` | `30` | How often it polls the orchestrator for pending steps. | -| `LOG_LEVEL` | `Info` | `Debug`, `Info`, `Warn`, or `Error`. | +| `LOG_LEVEL` | `Info` | `Debug`, `Info`, `Warn`, or `Error`. `Debug` adds one line per MCP server with its tool count and load time. | | `STEP_TIMEOUT_S` | `300` | Max duration of a single step. | | `AI_INVOKE_TIMEOUT_S` | `30` | Max duration of a single AI provider invocation. | | `STOP_TIMEOUT_S` | `30` | Grace period on shutdown to finish in-flight steps before exiting. | From d4a9ab256f079110ee5542759ab9f354e6b04a0e Mon Sep 17 00:00:00 2001 From: Brian Fox Date: Fri, 7 Aug 2026 18:57:16 +0200 Subject: [PATCH 2/4] docs(mcp-servers): fold the empty-tool-list meaning into setup A symptom-titled troubleshooting section restated the runtime page's failure taxonomy in product language, so the same knowledge lived on two pages and would drift. Only the empty-list meaning was new, and it belongs where the reader meets it. Co-Authored-By: Claude Opus 5 (1M context) --- get-started/connect/integrations/mcp-servers.mdx | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/get-started/connect/integrations/mcp-servers.mdx b/get-started/connect/integrations/mcp-servers.mdx index 04b5f81..2c8fc24 100644 --- a/get-started/connect/integrations/mcp-servers.mdx +++ b/get-started/connect/integrations/mcp-servers.mdx @@ -95,17 +95,7 @@ If a tool isn't in the list above, connect any MCP server by URL: "apiKey": "your-api-key" } ``` -4. Check that all the expected tools are exposed. +4. Check that all the expected tools are exposed. An empty list means the server answered but published nothing — a configuration problem on the server, not a connection failure. 5. Save your configuration. Learn more about building and hosting MCP servers in the [Claude MCP documentation](https://docs.claude.com/en/docs/agents-and-tools/remote-mcp-servers). - -## A connector's tools don't load - -The tool list comes back empty, or a workflow step using the connector fails. Check, in order: - -1. **The server exposes the tools you expect.** Reopen the connector in **Project Settings → Integrations** — an empty list means the server answered but published nothing, which is a server-side configuration problem, not a connection one. -2. **The credential is still valid.** A revoked or expired token fails the whole connector; reconnect it. -3. **Forest Runtime can reach the server.** A self-hosted runtime must have network access to the server's URL — a private address behind your VPN is reachable only from inside it. - -If you [self-host Forest Runtime](/product/process/workflows/forest-runtime), its logs name which of these it was, per server, at the default log level. From 9517a7f7d1bbe770857c21faf2c9f20b8ef5a59c Mon Sep 17 00:00:00 2001 From: Brian Fox Date: Mon, 10 Aug 2026 12:11:12 +0200 Subject: [PATCH 3/4] docs(forest-runtime): correct the auth kind and name the log's real shape The auth bullet sent OAuth readers to reconnect a connector the runtime already refreshes on its own, 403 lands in unknown rather than auth, and the example omitted fields the logger actually emits. Co-Authored-By: Claude Opus 5 (1M context) --- product/process/workflows/forest-runtime.mdx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/product/process/workflows/forest-runtime.mdx b/product/process/workflows/forest-runtime.mdx index cc8a0d5..871eb46 100644 --- a/product/process/workflows/forest-runtime.mdx +++ b/product/process/workflows/forest-runtime.mdx @@ -239,14 +239,16 @@ If your workflows include [MCP Tasks](/product/process/workflows/overview) backe The Docker image ships with [OpenTelemetry](https://opentelemetry.io/) APM built in, compatible with any OTLP backend (Datadog, Grafana Tempo, Jaeger, Honeycomb…). It is **off by default** and turns on as soon as you set `OTEL_EXPORTER_OTLP_ENDPOINT`. OpenTelemetry is bundled only in the Docker image, not the npm package. -### When an MCP step can't load its tools +### When an MCP Task can't load its tools -Forest Runtime logs the reason at `Error`, so it is in your logs without changing `LOG_LEVEL`: +Forest Runtime logs the reason at `Error`, so it is in your logs without changing `LOG_LEVEL`. This is the JSON the Docker image writes to stdout; running in a terminal you get the same fields in the pretty single-line format instead. ```json { "level": "Error", "message": "MCP servers failed to load tools", + "timestamp": "2026-08-10T09:14:22.031Z", + "requestedMcpServerId": "39", "mcpServerName": "acme-crm", "failures": [ { "server": "acme-crm", "kind": "connection", "error": "connect ECONNREFUSED 10.0.4.12:8080" } @@ -256,12 +258,16 @@ Forest Runtime logs the reason at `Error`, so it is in your logs without changin `kind` tells you where to look: -- `auth` — the server rejected the credential. Reconnect the connector, or renew its token. +- `auth` — the server rejected the credential (HTTP 401). For an OAuth connector the runtime refreshes the token and retries once on its own, so act only if the failure repeats without a follow-up `MCP tools loaded after refreshing the credential` line. For a static credential, renew it in the connector's configuration. - `connection` — unreachable, refused, or slower than the 15-second per-server load timeout. -- `unknown` — the server answered but the load failed anyway; `error` carries the reason. +- `unknown` — the server answered but the load failed anyway, including HTTP 403 permission or scope errors that no token refresh can fix; `error` carries the reason. A server that answers but exposes no tools is not a failure: you get an empty tool list and no error. + + If your logs show a `failedConfigNames` list instead of `failures`, your runtime predates this change: it names which server failed but not why, and reports a healthy server exposing no tools as a failure. Upgrade to get the cause. + + ## Tuning Beyond the required variables, these optional knobs have sensible defaults and rarely need changing: From 56ae34d360d96fdd7bd12afd3da1ce7e13a483b0 Mon Sep 17 00:00:00 2001 From: Brian Fox Date: Mon, 10 Aug 2026 12:13:32 +0200 Subject: [PATCH 4/4] docs(mcp-servers): drop the empty-tool-list claim the UI contradicts The connector page flags any empty result as a load error on every path except oauth2-on-orchestrator, so telling readers an empty list is normal disagrees with what they see. Restore it when the server path can report failures. Co-Authored-By: Claude Opus 5 (1M context) --- get-started/connect/integrations/mcp-servers.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/get-started/connect/integrations/mcp-servers.mdx b/get-started/connect/integrations/mcp-servers.mdx index 2c8fc24..1927350 100644 --- a/get-started/connect/integrations/mcp-servers.mdx +++ b/get-started/connect/integrations/mcp-servers.mdx @@ -95,7 +95,7 @@ If a tool isn't in the list above, connect any MCP server by URL: "apiKey": "your-api-key" } ``` -4. Check that all the expected tools are exposed. An empty list means the server answered but published nothing — a configuration problem on the server, not a connection failure. +4. Check that all the expected tools are exposed. 5. Save your configuration. Learn more about building and hosting MCP servers in the [Claude MCP documentation](https://docs.claude.com/en/docs/agents-and-tools/remote-mcp-servers).