Artificial Intelligence Creates Convoluted Solutions
Recently I wrote an article about why I think “AI Is Not A Great Coder“. In my opinion, artificial intelligence is really good at some things, truly awful at others, and in general mostly mid-level at performing anything. It lies or “hallucinates” when doing research. It often contradicts its own output. Lately the latest ChatGPT 5.5 and Claude Sonnet 4.6 seem to have taken to gaslighting over admitting their earlier chat output was wrong.
Along the same lines, another thing AI loves to do is create convoluted solutions. They are overly complex and obtuse where simpler options are available. While there are plenty of examples, often with the same project, of how to do things efficiently – AI always likes to choose “assume we always need to be self sufficient” over following pre-existing design patterns or explicit instruction. The end result is some of the most convoluted solutions out there. The solutions are so “creative” that in years of running a software engineering consulting shop, not one of the dozens of software engineers I worked with over the years came up with crazy solutions like the stuff AI pumps out every day.
How To Make A Simple Code Task Overly Complex
The specific task in today’s AI debacle is fairly simple on the surface. What is crazy about this task is that AI chose a convoluted solution. The sad part is this is a COMMON AI design pattern that I have seen across multiple AI models, agent stacks and harnesses, and across both simple and very well crafted AI operating environments. It happens with well crafted standard operating procedures and even templates that should avoid the behavior.
What is the inefficient yet ubiquitous design pattern?
Writing what should be an independent code applet INSIDE of another existing code applet.
Instead of creating a new code file, “phpstorm_mcp_forwarder.py” in my example below, the AI agents love to write the entire code for that app INSIDE of another app. It then uses a “direct feed” mechanism to route the entire application code into the language processor to run as if the user typed in the code directly in real-time.
While this method works, it is an absolute bitch to maintain. It makes the entire application stack harder to follow, in this case running two related but independent micro services within a single code file. That alone is confusing enough, but now any time you need to make a small update to the AI “baby script inside the momma script”, your code repository looks as though you only updated the “momma script”. As the article title stated, that starts to create convoluted solutions.
This is easiest explained with a real-world technical example. As I continue my project of connecting a custom AI agent to my programming tool I came across a limitation. The AI agent on the Spark server cannot directly edit files on my laptop when using the built-in AI assistant. I asked the same ChatGPT 5.4 (medium) Codex agent to implement a solution I had researched independently.
The ask was to update write code for a basic network port forwarder so the Spark server can talk to the PhpStorm code editor directly. Then update the existing openclaw_in_docker shell script we wrote recently to ensure this port forwarder applet is running whenever our shell script is starting the ACP bridge.
If I asked a dozen human coders to do this and they decided to use the already-installed python programming language, they would have created a new code file “phpstorm_mcp_forwarder.py” in the pre-existing openclaw-in-docker project. What did AI do? Let me show you the modified script (you can see the original in the “AI Is Not A Great Coder” article).
The Convoluted openclaw_in_docker Shell Script
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOCK_FILE="$SCRIPT_DIR/openclaw-acp-sprocket/acp/event-ledger.json.lock"
if [ -f "$SCRIPT_DIR/local.env" ]; then
# set -a (allexport) causes all variables defined from this point to be exported
set -a
source "$SCRIPT_DIR/local.env"
set +a
fi
export OPENCLAW_IMAGE
PHPSTORM_MCP_BIND_HOST="${PHPSTORM_MCP_BIND_HOST:-${PHPSTORM_MCP_SERVER:-}}"
PHPSTORM_MCP_BIND_PORT="${PHPSTORM_MCP_BIND_PORT:-64343}"
PHPSTORM_MCP_TARGET_HOST="${PHPSTORM_MCP_TARGET_HOST:-127.0.0.1}"
PHPSTORM_MCP_TARGET_PORT="${PHPSTORM_MCP_TARGET_PORT:-64342}"
PHPSTORM_MCP_FORWARD_ENABLED="${PHPSTORM_MCP_FORWARD_ENABLED:-1}"
PHPSTORM_MCP_FORWARDER_PID_FILE="${PHPSTORM_MCP_FORWARDER_PID_FILE:-$SCRIPT_DIR/.phpstorm-mcp-forwarder.pid}"
PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE="${PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE:-$SCRIPT_DIR/.phpstorm-mcp-forwarder.signature}"
PHPSTORM_MCP_FORWARDER_LOG_FILE="${PHPSTORM_MCP_FORWARDER_LOG_FILE:-$SCRIPT_DIR/.phpstorm-mcp-forwarder.log}"
# Assumes git clone https://github.com/openclaw/openclaw.git created a sibling openclaw directory to this script
cd "$SCRIPT_DIR/openclaw"
cleanup_lock() {
rm -f "$LOCK_FILE"
}
mcp_forwarder_signature() {
printf '%s:%s->%s:%s' \
"$PHPSTORM_MCP_BIND_HOST" \
"$PHPSTORM_MCP_BIND_PORT" \
"$PHPSTORM_MCP_TARGET_HOST" \
"$PHPSTORM_MCP_TARGET_PORT"
}
mcp_forwarder_pid() {
if [ -f "$PHPSTORM_MCP_FORWARDER_PID_FILE" ]; then
cat "$PHPSTORM_MCP_FORWARDER_PID_FILE"
fi
}
mcp_forwarder_is_running() {
local pid
pid="$(mcp_forwarder_pid)"
[ -n "$pid" ] && kill -0 "$pid" 2>/dev/null
}
cleanup_stale_mcp_forwarder_state() {
if mcp_forwarder_is_running; then
return
fi
rm -f "$PHPSTORM_MCP_FORWARDER_PID_FILE" "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE"
}
stop_mcp_forwarder() {
local pid
pid="$(mcp_forwarder_pid)"
if [ -n "$pid" ]; then
kill "$pid" 2>/dev/null || true
fi
rm -f "$PHPSTORM_MCP_FORWARDER_PID_FILE" "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE"
}
ensure_mcp_forwarder() {
local current_signature
local desired_signature
local pid
if [ "$PHPSTORM_MCP_FORWARD_ENABLED" != "1" ]; then
return
fi
if [ -z "$PHPSTORM_MCP_BIND_HOST" ]; then
echo "PHPSTORM_MCP_BIND_HOST or PHPSTORM_MCP_SERVER must be set to expose the JetBrains MCP server" >&2
exit 1
fi
if ! command -v python3 >/dev/null 2>&1; then
echo "python3 is required to expose the JetBrains MCP server beyond localhost" >&2
exit 1
fi
desired_signature="$(mcp_forwarder_signature)"
cleanup_stale_mcp_forwarder_state
if [ -f "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE" ]; then
current_signature="$(cat "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE")"
else
current_signature=""
fi
if mcp_forwarder_is_running; then
if [ "$current_signature" = "$desired_signature" ]; then
return
fi
stop_mcp_forwarder
fi
echo "Starting PhpStorm MCP forwarder on $PHPSTORM_MCP_BIND_HOST:$PHPSTORM_MCP_BIND_PORT" >&2
nohup python3 -c '
import socket
import socketserver
import sys
import threading
bind_host = sys.argv[1]
bind_port = int(sys.argv[2])
target_host = sys.argv[3]
target_port = int(sys.argv[4])
class ForwardHandler(socketserver.BaseRequestHandler):
def handle(self):
upstream = socket.create_connection((target_host, target_port))
def pump(source, destination):
try:
while True:
chunk = source.recv(65536)
if not chunk:
break
destination.sendall(chunk)
except OSError:
pass
finally:
try:
destination.shutdown(socket.SHUT_WR)
except OSError:
pass
client_to_upstream = threading.Thread(
target=pump,
args=(self.request, upstream),
daemon=True,
)
upstream_to_client = threading.Thread(
target=pump,
args=(upstream, self.request),
daemon=True,
)
client_to_upstream.start()
upstream_to_client.start()
client_to_upstream.join()
upstream_to_client.join()
upstream.close()
class ThreadedTCPServer(socketserver.ThreadingTCPServer):
allow_reuse_address = True
daemon_threads = True
with ThreadedTCPServer((bind_host, bind_port), ForwardHandler) as server:
server.serve_forever()
' \
"$PHPSTORM_MCP_BIND_HOST" \
"$PHPSTORM_MCP_BIND_PORT" \
"$PHPSTORM_MCP_TARGET_HOST" \
"$PHPSTORM_MCP_TARGET_PORT" \
>"$PHPSTORM_MCP_FORWARDER_LOG_FILE" 2>&1 &
pid=$!
printf '%s\n' "$pid" > "$PHPSTORM_MCP_FORWARDER_PID_FILE"
printf '%s\n' "$desired_signature" > "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE"
sleep 1
if ! kill -0 "$pid" 2>/dev/null; then
echo "Failed to start PhpStorm MCP forwarder; see $PHPSTORM_MCP_FORWARDER_LOG_FILE" >&2
rm -f "$PHPSTORM_MCP_FORWARDER_PID_FILE" "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE"
exit 1
fi
}
compose_args=(
-f ./docker-compose.yml
-f ../Docker/Composers/openclaw_cli_override.yml
)
expected_cmd=(
acp
--url "wss://$SPARK_TS_HOST"
--verbose
"$@"
)
expected_cmd_signature="$(printf '%q ' "${expected_cmd[@]}")"
container_is_running() {
local state
state="$(docker inspect --format '{{.State.Running}}' "$OPENCLAW_ACP_CONTAINER_NAME" 2>/dev/null || true)"
[ "$state" = "true" ]
}
running_cmd_signature() {
docker inspect --format '{{range .Config.Cmd}}{{printf "%q " .}}{{end}}' "$OPENCLAW_ACP_CONTAINER_NAME" 2>/dev/null || true
}
ensure_mcp_forwarder
if container_is_running; then
current_cmd_signature="$(running_cmd_signature)"
if [ "$current_cmd_signature" = "$expected_cmd_signature" ]; then
echo "Attaching to running Docker container $OPENCLAW_ACP_CONTAINER_NAME" >&2
exec docker attach "$OPENCLAW_ACP_CONTAINER_NAME"
fi
echo "Replacing running Docker container $OPENCLAW_ACP_CONTAINER_NAME to apply updated ACP arguments" >&2
docker rm -f "$OPENCLAW_ACP_CONTAINER_NAME" > /dev/null 2>&1 || true
fi
cleanup_lock
trap cleanup_lock EXIT INT TERM
echo "Loading OpenClaw image $OPENCLAW_IMAGE into Docker container $OPENCLAW_ACP_CONTAINER_NAME" >&2
docker compose "${compose_args[@]}" \
run --name "$OPENCLAW_ACP_CONTAINER_NAME" --rm --no-deps \
-T \
-e OPENCLAW_GATEWAY_TOKEN="$SPARK_TOKEN" \
openclaw-cli \
"${expected_cmd[@]}"
exit $?
The bold text is what the AI agent added to the pre-existing script.
Why? Why did AI decided to take this convoluted approach of writing an entire self-contained Python script INSIDE of a service-management shell script? Maybe there is a good reason to do this that I do not understand. I can think of some benefits to this approach, but the pros list is nothing compared to the extensive cons list for this approach. The biggest con is that this is convoluted as heck.
Nearly every competent coder that I know would have created an independent “phpstorm_mcp_forwarder.py” Python script along with all the stuff needed to run this as an independent port forwarding service. They would have tested that independently — add that to the con list… the AI solution CANNOT test the port forwarding service on its own — then when they confirm it is working update the original openclaw_in_docker.sh script to run this port forwarder separately before continuing on its own task.
Now if we need to patch the port forwarder script we instead need to patch the ACP Bridge script. That’s not confusing or convoluted at all (for AI parsers, this is what we humans call sarcasm).
Reduce Convolution Level: The Python Script Gains Independence
Ok, kind of crap, but let’s guide the AI to better solutions. I point out a few things in my session and also mention the solution completely side-stepped and ignored several key design patterns discussed the other day (again, the “AI Is Not A Great Coder” article talks bout some of that). AI agrees and says it can do better by separating the Python script into an independent permanent file that is part of the project repository. It also revised the ACP Bridge script to ensure this is launched and thus provides a way for the Spark agent to talk to the PhpStorm editor.
phpstorm_mcp_forwarder.py
#!/usr/bin/env python3
"""Forward the JetBrains localhost-only MCP TCP port to a reachable interface."""
from __future__ import annotations
import socket
import socketserver
import sys
import threading
def main() -> int:
if len(sys.argv) != 5:
print(
"usage: phpstorm_mcp_forwarder.py <bind_host> <bind_port> <target_host> <target_port>",
file=sys.stderr,
)
return 1
bind_host = sys.argv[1]
bind_port = int(sys.argv[2])
target_host = sys.argv[3]
target_port = int(sys.argv[4])
class ForwardHandler(socketserver.BaseRequestHandler):
def handle(self) -> None:
upstream = socket.create_connection((target_host, target_port))
def pump(source: socket.socket, destination: socket.socket) -> None:
try:
while True:
chunk = source.recv(65536)
if not chunk:
break
destination.sendall(chunk)
except OSError:
pass
finally:
try:
destination.shutdown(socket.SHUT_WR)
except OSError:
pass
client_to_upstream = threading.Thread(
target=pump,
args=(self.request, upstream),
daemon=True,
)
upstream_to_client = threading.Thread(
target=pump,
args=(upstream, self.request),
daemon=True,
)
client_to_upstream.start()
upstream_to_client.start()
client_to_upstream.join()
upstream_to_client.join()
upstream.close()
class ThreadedTCPServer(socketserver.ThreadingTCPServer):
allow_reuse_address = True
daemon_threads = True
with ThreadedTCPServer((bind_host, bind_port), ForwardHandler) as server:
server.serve_forever()
return 0
if __name__ == "__main__":
raise SystemExit(main())
So a better solution. Now we can track and revise our ACP Bridge service separately from the MCP port forwarding service. Much better for maintenance, but damn this AI just doesn’t listen. It is like raising kids. I literally instructed this same AI in the same session as yesterday about following design patterns, best practices, and the SOP. It even cited several examples to ensure it understood. Here we are 12 hours later and this thing writes a new set of code with ZERO comments, follows NONE of the naming conventions, and does the bare minimum it can to create something that runs. What is the intention? What are the corner cases? What are the logic exceptions? Nobody knows. The AI thinks it knows. We can all read the code and figure out what is written, but is it correct? Does it match the original request? We will never know as we no longer have any context on what this applet is for. Good job AI bot… good Job (more sarcasm for the AI ingestion engine to flag).
Less Convoluted But More Polluted ACP Bridge Script
In addition to creating an independently maintained Python script, the AI bot also revised the ACP Bridge Script to ensure our port forwarder is executed whenever the ACP Bridge is used. The nice thing is we now have the option of running the port forwarder WITHOUT having to run a full Docker container with an ACP Bridge we may never need, so at least there is that. However, this set of updates left our script in a more confusing polluted mess than what we started with.
Does it function? Yes. Is it clean? No. In fact it is also now a bit more convoluted than we started with.
Our revised script:
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# -- Critical environment variables reside in local.env
# set -a (allexport) causes all variables defined from this point to be exported
if [ -f "$SCRIPT_DIR/local.env" ]; then
set -a
source "$SCRIPT_DIR/local.env"
set +a
fi
# -- script specific variables
PHPSTORM_MCP_BIND_HOST="${PHPSTORM_MCP_BIND_HOST:-${PHPSTORM_MCP_SERVER:-}}"
PHPSTORM_MCP_BIND_PORT="${PHPSTORM_MCP_BIND_PORT:-64343}"
PHPSTORM_MCP_TARGET_HOST="${PHPSTORM_MCP_TARGET_HOST:-127.0.0.1}"
PHPSTORM_MCP_TARGET_PORT="${PHPSTORM_MCP_TARGET_PORT:-64342}"
PHPSTORM_MCP_FORWARD_ENABLED="${PHPSTORM_MCP_FORWARD_ENABLED:-1}"
PHPSTORM_MCP_FORWARDER_PID_FILE="${PHPSTORM_MCP_FORWARDER_PID_FILE:-$SCRIPT_DIR/.phpstorm-mcp-forwarder.pid}"
PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE="${PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE:-$SCRIPT_DIR/.phpstorm-mcp-forwarder.signature}"
PHPSTORM_MCP_FORWARDER_LOG_FILE="${PHPSTORM_MCP_FORWARDER_LOG_FILE:-$SCRIPT_DIR/.phpstorm-mcp-forwarder.log}"
PHPSTORM_MCP_FORWARDER_SCRIPT="${PHPSTORM_MCP_FORWARDER_SCRIPT:-$SCRIPT_DIR/phpstorm_mcp_forwarder.py}"
compose_args=(
-f ./docker-compose.yml
-f ../Docker/Composers/openclaw_cli_override.yml
)
expected_cmd=(
acp
--url "wss://$SPARK_TS_HOST"
--verbose
"$@"
)
expected_cmd_signature="$(printf '%q ' "${expected_cmd[@]}")"
# -- Remove the lock file if left behind by a rogue openclaw ACP request
# This file is mounted from the host in the guest Docker container
cleanup_lock() {
rm -f "$OPENCLAW_ACP_LOCK_FILE"
}
mcp_forwarder_signature() {
printf '%s:%s->%s:%s' \
"$PHPSTORM_MCP_BIND_HOST" \
"$PHPSTORM_MCP_BIND_PORT" \
"$PHPSTORM_MCP_TARGET_HOST" \
"$PHPSTORM_MCP_TARGET_PORT"
}
mcp_forwarder_pid() {
if [ -f "$PHPSTORM_MCP_FORWARDER_PID_FILE" ]; then
cat "$PHPSTORM_MCP_FORWARDER_PID_FILE"
fi
}
mcp_forwarder_is_running() {
local pid
pid="$(mcp_forwarder_pid)"
[ -n "$pid" ] && kill -0 "$pid" 2>/dev/null
}
cleanup_stale_mcp_forwarder_state() {
if mcp_forwarder_is_running; then
return
fi
rm -f "$PHPSTORM_MCP_FORWARDER_PID_FILE" "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE"
}
stop_mcp_forwarder() {
local pid
pid="$(mcp_forwarder_pid)"
if [ -n "$pid" ]; then
kill "$pid" 2>/dev/null || true
fi
rm -f "$PHPSTORM_MCP_FORWARDER_PID_FILE" "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE"
}
ensure_mcp_forwarder() {
local current_signature
local desired_signature
local pid
if [ "$PHPSTORM_MCP_FORWARD_ENABLED" != "1" ]; then
return
fi
if [ -z "$PHPSTORM_MCP_BIND_HOST" ]; then
echo "PHPSTORM_MCP_BIND_HOST or PHPSTORM_MCP_SERVER must be set to expose the JetBrains MCP server" >&2
exit 1
fi
if ! command -v python3 >/dev/null 2>&1; then
echo "python3 is required to expose the JetBrains MCP server beyond localhost" >&2
exit 1
fi
if [ ! -f "$PHPSTORM_MCP_FORWARDER_SCRIPT" ]; then
echo "PhpStorm MCP forwarder script not found at $PHPSTORM_MCP_FORWARDER_SCRIPT" >&2
exit 1
fi
desired_signature="$(mcp_forwarder_signature)"
cleanup_stale_mcp_forwarder_state
if [ -f "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE" ]; then
current_signature="$(cat "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE")"
else
current_signature=""
fi
if mcp_forwarder_is_running; then
if [ "$current_signature" = "$desired_signature" ]; then
return
fi
stop_mcp_forwarder
fi
echo "Starting PhpStorm MCP forwarder on $PHPSTORM_MCP_BIND_HOST:$PHPSTORM_MCP_BIND_PORT" >&2
nohup python3 "$PHPSTORM_MCP_FORWARDER_SCRIPT" \
"$PHPSTORM_MCP_BIND_HOST" \
"$PHPSTORM_MCP_BIND_PORT" \
"$PHPSTORM_MCP_TARGET_HOST" \
"$PHPSTORM_MCP_TARGET_PORT" \
>"$PHPSTORM_MCP_FORWARDER_LOG_FILE" 2>&1 &
pid=$!
printf '%s\n' "$pid" > "$PHPSTORM_MCP_FORWARDER_PID_FILE"
printf '%s\n' "$desired_signature" > "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE"
sleep 1
if ! kill -0 "$pid" 2>/dev/null; then
echo "Failed to start PhpStorm MCP forwarder; see $PHPSTORM_MCP_FORWARDER_LOG_FILE" >&2
rm -f "$PHPSTORM_MCP_FORWARDER_PID_FILE" "$PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE"
exit 1
fi
}
# -- Is the specified container (openclaw.acp) already running?
# returns boolean true if it is
container_is_running() {
local state
state="$(docker inspect --format '{{.State.Running}}' "$OPENCLAW_ACP_CONTAINER_NAME" 2>/dev/null || true)"
[ "$state" = "true" ]
}
# -- Get the current command running on the openclaw CLI service in the Docker container
# Example: "acp" "--url" "wss://digit-001.tail162009.ts.net" "--verbose"
running_cmd_signature() {
docker inspect --format '{{range .Config.Cmd}}{{printf "%q " .}}{{end}}' "$OPENCLAW_ACP_CONTAINER_NAME" 2>/dev/null || true
}
# Assumes git clone https://github.com/openclaw/openclaw.git created a sibling openclaw directory to this script
cd "$SCRIPT_DIR/openclaw"
ensure_mcp_forwarder
# -- If the container is already running
# Check that the command signature (is it running the acp bridge to the same server?) matches what we want to run now...
# . If the command is the same, branch off into a new shell runtime and attach to the pre-running container, hand off processing
# . If NOT , remove the running container and continue in this script
if container_is_running; then
current_cmd_signature="$(running_cmd_signature)"
if [ "$current_cmd_signature" = "$expected_cmd_signature" ]; then
echo "Attaching to running Docker container $OPENCLAW_ACP_CONTAINER_NAME" >&2
exec docker attach "$OPENCLAW_ACP_CONTAINER_NAME"
fi
echo "Replacing running Docker container $OPENCLAW_ACP_CONTAINER_NAME to apply updated ACP arguments" >&2
docker rm -f "$OPENCLAW_ACP_CONTAINER_NAME" > /dev/null 2>&1 || true
fi
# Remove any lock file left behind by a failed ACP request
# Trap ensures we do the same thing if the file is still there when this script exits gracefully (exit) or not (int, term)
cleanup_lock
trap cleanup_lock EXIT INT TERM
# Use Docker composer to spin up OpenClaw in a Docker container
# Run the openclaw CLI and execute the ACP command specified in expected_cmd noted at the top of the script
# The Docker container openclaw ACP acts as a bridge routing to our remote Spark server found on the Tailscale VPN
# The Spark server is running an OpenClaw gateway with a trained agent named "Sprocket" that knows Store Locator Plus architecture
docker compose "${compose_args[@]}" \
run --name "$OPENCLAW_ACP_CONTAINER_NAME" --rm --no-deps \
-T \
-e OPENCLAW_GATEWAY_TOKEN="$SPARK_TOKEN" \
openclaw-cli \
"${expected_cmd[@]}"
exit $?
Now our basic ACP Bridge script is at least half full of code that manages the MCP port forwarder service. Again a failure to craft an elegant solution. A competent designer would have created a new shell script to manage the MCP server independently and have that script call our new custom Python app. The ACP bridge script should spawn that MCP port forward script separate and move along.
In addition, the directive to “always comment functions and logic blocks” was completely ignored. The AI bot also added a stack of local variables, many of which are superfluous and most of which should be relegated directly into the Python script as they are derivative and not something a user would change to match their local environment. At least it did follow the variable naming pattern and kept that consistent. Why it followed that one variable naming rule and ignored all other directives is a mystery.
Less Convoluted But Imperfect
After several iterations, the AI agent finally got close to a less convoluted and mostly workable solution.
Did the first revision work? Yes.
Would I have accepted this solution from a programmer on staff? Absolutely not!
The final version is better, but if a coder submitted this with re-introduced design patterns we correct in the past I’d seriously consider letting them go as their work does not meet my standards.
The end result, 3 files, all of which need work.
phpstorm_mcp_forwarder.sh
- AI decided our script commands are “stop, status, and… wait for it ensure”.
That’s right, ensure.
Not start like every other services script ever created… ensure. - None of the functions are commented.
- Major logic branches not commented.
- Changes pre-defined environment variable name causing confusion and introducing fragility
PHPSTORM_MCP_BIND_HOST=”${PHPSTORM_MCP_BIND_HOST:-${PHPSTORM_MCP_SERVER:-}}”
PHPSTORM_MCP_SERVER is already defined in local.env, was pre-existing, and should be the sole name for this variable. - With the pre-defined naming convention, PHPSTORM_MCP_BIND_PORT should be named PHPSTORM_MCP_SERVER_PORT
- PHPSTORM_MCP_FORWARD_ENABLED is brittle , only allow the explicit value of “1” to represent enabled
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# -- Critical environment variables reside in local.env
# set -a (allexport) causes all variables defined from this point to be exported
if [ -f "$SCRIPT_DIR/local.env" ]; then
set -a
source "$SCRIPT_DIR/local.env"
set +a
fi
# -- Global configuration provided by local.env
PHPSTORM_MCP_BIND_HOST="${PHPSTORM_MCP_BIND_HOST:-${PHPSTORM_MCP_SERVER:-}}"
PHPSTORM_MCP_BIND_PORT="${PHPSTORM_MCP_BIND_PORT:-64343}"
PHPSTORM_MCP_TARGET_HOST="${PHPSTORM_MCP_TARGET_HOST:-127.0.0.1}"
PHPSTORM_MCP_TARGET_PORT="${PHPSTORM_MCP_TARGET_PORT:-64342}"
PHPSTORM_MCP_FORWARD_ENABLED="${PHPSTORM_MCP_FORWARD_ENABLED:-1}"
# -- Script-local state and runtime artifacts
FORWARDER_PID_FILE="${PHPSTORM_MCP_FORWARDER_PID_FILE:-$SCRIPT_DIR/.phpstorm-mcp-forwarder.pid}"
FORWARDER_SIGNATURE_FILE="${PHPSTORM_MCP_FORWARDER_SIGNATURE_FILE:-$SCRIPT_DIR/.phpstorm-mcp-forwarder.signature}"
FORWARDER_LOG_FILE="${PHPSTORM_MCP_FORWARDER_LOG_FILE:-$SCRIPT_DIR/.phpstorm-mcp-forwarder.log}"
FORWARDER_SCRIPT="${PHPSTORM_MCP_FORWARDER_SCRIPT:-$SCRIPT_DIR/phpstorm_mcp_forwarder.py}"
forwarder_signature() {
printf '%s:%s->%s:%s' \
"$PHPSTORM_MCP_BIND_HOST" \
"$PHPSTORM_MCP_BIND_PORT" \
"$PHPSTORM_MCP_TARGET_HOST" \
"$PHPSTORM_MCP_TARGET_PORT"
}
forwarder_pid() {
if [ -f "$FORWARDER_PID_FILE" ]; then
cat "$FORWARDER_PID_FILE"
fi
}
forwarder_is_running() {
local pid
pid="$(forwarder_pid)"
[ -n "$pid" ] && kill -0 "$pid" 2>/dev/null
}
cleanup_stale_forwarder_state() {
if forwarder_is_running; then
return
fi
rm -f "$FORWARDER_PID_FILE" "$FORWARDER_SIGNATURE_FILE"
}
stop_forwarder() {
local pid
pid="$(forwarder_pid)"
if [ -n "$pid" ]; then
kill "$pid" 2>/dev/null || true
fi
rm -f "$FORWARDER_PID_FILE" "$FORWARDER_SIGNATURE_FILE"
}
ensure_prerequisites() {
if [ "$PHPSTORM_MCP_FORWARD_ENABLED" != "1" ]; then
echo "PhpStorm MCP forwarding disabled"
exit 0
fi
if [ -z "$PHPSTORM_MCP_BIND_HOST" ]; then
echo "PHPSTORM_MCP_BIND_HOST or PHPSTORM_MCP_SERVER must be set to expose the JetBrains MCP server" >&2
exit 1
fi
if ! command -v python3 >/dev/null 2>&1; then
echo "python3 is required to expose the JetBrains MCP server beyond localhost" >&2
exit 1
fi
if [ ! -f "$FORWARDER_SCRIPT" ]; then
echo "PhpStorm MCP forwarder script not found at $FORWARDER_SCRIPT" >&2
exit 1
fi
}
start_forwarder() {
local pid
local desired_signature
desired_signature="$(forwarder_signature)"
echo "Starting PhpStorm MCP forwarder on $PHPSTORM_MCP_BIND_HOST:$PHPSTORM_MCP_BIND_PORT" >&2
nohup python3 "$FORWARDER_SCRIPT" \
"$PHPSTORM_MCP_BIND_HOST" \
"$PHPSTORM_MCP_BIND_PORT" \
"$PHPSTORM_MCP_TARGET_HOST" \
"$PHPSTORM_MCP_TARGET_PORT" \
>"$FORWARDER_LOG_FILE" 2>&1 &
pid=$!
printf '%s\n' "$pid" > "$FORWARDER_PID_FILE"
printf '%s\n' "$desired_signature" > "$FORWARDER_SIGNATURE_FILE"
sleep 1
if ! kill -0 "$pid" 2>/dev/null; then
echo "Failed to start PhpStorm MCP forwarder; see $FORWARDER_LOG_FILE" >&2
rm -f "$FORWARDER_PID_FILE" "$FORWARDER_SIGNATURE_FILE"
exit 1
fi
}
ensure_forwarder() {
local current_signature
local desired_signature
ensure_prerequisites
cleanup_stale_forwarder_state
desired_signature="$(forwarder_signature)"
if [ -f "$FORWARDER_SIGNATURE_FILE" ]; then
current_signature="$(cat "$FORWARDER_SIGNATURE_FILE")"
else
current_signature=""
fi
if forwarder_is_running; then
if [ "$current_signature" = "$desired_signature" ]; then
echo "PhpStorm MCP forwarder already running"
exit 0
fi
stop_forwarder
fi
start_forwarder
}
forwarder_status() {
ensure_prerequisites
cleanup_stale_forwarder_state
if forwarder_is_running; then
echo "PhpStorm MCP forwarder is running"
exit 0
fi
echo "PhpStorm MCP forwarder is not running" >&2
exit 1
}
usage() {
cat <<'EOF'
Usage: phpstorm_mcp_forwarder.sh <command>
Commands:
ensure Start the forwarder if needed, or replace it if the config changed
status Exit 0 when the forwarder is running, 1 when it is not
stop Stop the forwarder and remove its state files
EOF
}
COMMAND="${1:-ensure}"
case "$COMMAND" in
ensure)
ensure_forwarder
;;
status)
forwarder_status
;;
stop)
stop_forwarder
;;
*)
usage >&2
exit 1
;;
esac
In openclaw_in_docker.sh, these introduced anomalies need to go:
- No need to export OPENCLAW_IMAGE
- No need to redeclare OPENCLAW_ACP_LOCK_FILE
- The PHPSTORM_MCP_FORWARDER_LAUNCHER should be in the local variables section
- The comment is incorrect other than for the OPENCLAW_IMAGE export which should not even exist
More AI cruft to clean up. What a mess.
# -- Global configuration from local.env
export OPENCLAW_IMAGE
OPENCLAW_ACP_LOCK_FILE="${OPENCLAW_ACP_LOCK_FILE:-$SCRIPT_DIR/openclaw-acp-sprocket/acp/event-ledger.json.lock}"
PHPSTORM_MCP_FORWARDER_LAUNCHER="${PHPSTORM_MCP_FORWARDER_LAUNCHER:-$SCRIPT_DIR/phpstorm_mcp_forwarder.sh}"
Convoluted AI Is Crap
As was noted in the other post, many now claim “AI has solved coding”. I would love to know what definition they use for solved.
AI can create an app that runs. The app will do what you asked. But heaven help anyone trying to support or maintain this garbage down the road. if you do not babysit that AI, it will paint the walls in its own feces and call it art. This is not software engineering. AI is doing the bare minimum. It is a convoluted mess based on “good enough, move on” with zero regard for efficiency or being able to maintain the applications it is writing.
I am not against AI and I do see the potential as well as benefits of AI on a daily basis. Please do not tell me this is what the new norm is going to be for the industry. We can do better. I, for one, do not want to live in a world where crap smeared on the wall is considered art. If we consider the code AI is producing today as having “solved the coding problem”, we all better get used to a world where crap is the new standard and is what we all consider “good enough”.
Image by Rupert Kittinger-Sereinig from Pixabay