← Field Notes · August 13, 2026 · 7 min read · AIOProductOS Team

MCP Server Not Working? Diagnose It in Five Layers

Your MCP server will not connect. A five-step diagnostic order that isolates which layer failed - client, process, transport, auth, or tool surface.

You added a server, restarted the client, and the tool list is empty - or it connects and then does nothing useful. Most of page one for this problem is a pile of fixes in no particular order, so people try them at random and cannot tell which one worked. The fix order matters more than the fixes.

Why is my MCP server not working?

Usually because the server process never started, and the client did not tell you. Clients launch MCP servers in a stripped environment that does not load your shell profile, so a command that works in your terminal fails when the client runs it. The other common causes are invalid JSON in the config and stray output corrupting the stdio channel.

MCP server troubleshooting: a five-layer diagnostic order from client config to tool surface

Diagnose in order, not at random

Each step below ends in a verdict about one layer. Stop at the first one that fails; everything after it is untestable until that layer is fixed.

#The testA pass provesA fail means
1Point the same client at a known-good public serverYour client, its config file and its JSON are all fineThe fault is in the client or the config, not in the server you were installing
2Run the exact command and args from your config in a plain shellThe server starts and the package resolves - so if the client still cannot attach, the difference is the environment the client launches it inYou now have the real error the client swallowed: missing runtime, wrong package name, missing variable
3Watch what the process writes to stdout on startupThe channel carries JSON-RPC and nothing elseA stray log line is corrupting every message - the server has a stdout discipline bug
4Ask the client to list tools, then make one read callYou are connected and authorisedConnection is fine; this is auth or scope, not a connection problem
5Ask a question the server should obviously answerThe tool surface is legible to the modelConnection and auth are fine; the model is picking wrong or picking nothing

Step 1 - is it the client, or the server?

Before touching the failing server, prove the client works. Point it at a server you know is healthy and requires no credentials, using the same config file and the same restart.

npx -y @aioproductoscom/mcp@latest

Started without a PRODUCTOS_TOKEN, that runs in demo mode against a fully seeded showcase workspace called Brightline - a read-only subset of the tools, no account, no credentials, nothing to cancel. A working connection looks like two things, in this order: the client lists tools, and a first call returns typed records with ids rather than a sentence. Ask it something ordinary in your own words, like which features have the most customer requests behind them.

If that works, your client, your JSON and your restart procedure are all fine, and the fault is in the other server. If it also fails, stop debugging the other server entirely - you have a client-side problem, and the config mechanics are covered in running a local MCP server.

A second option, if you want a known-good server that makes no network calls at all: AIOProductOS Studio is a free, MIT-licensed, fully-local server, installed with npx -y @aioproductoscom/mcp-studio.

Step 2 - did the process ever start?

This is the step page one skips, and it resolves more cases than everything else combined. Take the command and the args from your config, exactly as written, and run them yourself in a plain shell. The error the client swallowed appears immediately: a runtime that is not installed, a package name that does not resolve, a required variable that is unset.

If it runs in your terminal but still fails in the client, you have learned the actual fault - the environments differ. Your shell loaded a profile that put a version manager or a package binary on the PATH. The client, launched from the dock, never read that profile, so node or npx or uvx may not exist as far as it is concerned. Give the config an absolute path to the runtime instead of a bare command, and pass anything the server needs explicitly rather than assuming your exported variables are visible.

Two things to check before you conclude anything here. Confirm the config file is valid JSON - a trailing comma means the client loads nothing and says nothing. And confirm you fully restarted the client, not just closed a window; most read the server list once, at startup.

Step 3 - is the transport clean?

On stdio, stdout is the protocol channel. A single console.log or print in the server body writes non-JSON into the middle of the message stream and corrupts every exchange after it. The symptom is a server that clearly launched and still never attaches, or one that attaches and drops. Logging belongs on stderr; stdout carries JSON-RPC only.

You are running someone else's server, so this is not yours to patch - but it is yours to identify, because it changes what you do next. Pin an earlier version and see if the noise disappears; if it does, you have a reportable regression rather than a local misconfiguration. If the server is remote rather than local, the equivalent check is plainer: confirm the endpoint URL is reachable and returns what you expect before assuming the client is at fault. (Authoring concerns - return shapes, naming, versioning - are covered in what we learned building two MCP servers.)

Step 4 - is it auth, not connection?

Connected, tools listed, and every call comes back empty or denied. That is not a connection failure and no amount of config editing will fix it. Either the OAuth flow was started and never completed, or the token in play is scoped to less than you are asking for, or you are authenticated as an account with no data in it.

The tell is that reads succeed and writes fail: that is scope, working as designed. Check what the server says it grants before assuming a bug - and if the server exposes an identity or whoami tool, call it, because "which account am I" is frequently the whole answer. Whether that grant is one you should accept is a separate question, and the decision procedure is here.

Step 5 - is it the tool surface?

Connection is fine, auth is fine, and the model still does nothing useful. Two variants. If it never calls a tool, the descriptions are not telling it when to; name the tool explicitly in your prompt once and see whether the call succeeds - if it does, the connection is healthy and the selection is the problem. If it calls the wrong tool, the surface has overlapping names and you are watching a retrieval failure, not an integration failure.

This is also where a large surface earns scrutiny. Our own hosted endpoint exposes 71 tools plus three interactive ui:// apps; that is a big surface, and it stays workable only because the names disambiguate on their own, with the surface documented tool by tool so you can check what you are pointing at before you connect.

When it works for you and not your colleague

If your install is fine and someone else's is not, nothing is broken - that is what a per-machine stdio install does at team scale, where five people means five installs and three different versions of the same server name. That ceiling is a different problem with a different answer, covered in where a local MCP server stops paying.

The honest counter-case

Sometimes the answer is that the server is broken and you should stop.

Steps 1 and 2 both pass and step 3 fails on the current release. You have found a bug in someone else's code. Pin the last version that worked, file the issue with the exact stdout you captured, and move on - debugging your own setup further is wasted time, because your setup is fine.

The server has no identifiable maintainer and no recent releases. MCP is a small enough standard that a server which fails to hand back a tool list is often just unfinished. Reading its source to find out is a legitimate choice; so is picking a different server and spending the afternoon on your actual work.

And local stdio may still be the right call. If the capability is genuinely local - your filesystem, your browser, a device on your desk - none of the team-scale objections apply, and the per-machine install is the correct architecture rather than a compromise. Fix the PATH and keep it.

Whatever you are installing, run the order rather than the list: client, process, transport, auth, surface. If you want to run it against a real product spine on your own data instead of a seeded workspace, the MCP surface and every connection method are documented here.

Frequently asked questions

Why is my MCP server not showing up in Claude?

The two usual causes are invalid JSON in the client config file and a server process that failed to start. A config file with a trailing comma or an unescaped backslash does not produce an error - the client loads nothing and the server list is simply short. If the JSON parses, the next candidate is the launch itself: the client starts servers in a stripped environment without your shell profile, so a command that resolves in your terminal may not resolve for the client. Restart the client fully after any config edit; most reload servers only on startup.

Why does my MCP server work in the terminal but not in Claude?

Because your terminal and your AI client do not run the same environment. Your shell loads a profile that puts version managers, package binaries and exported variables on the PATH. A desktop client launched from the dock inherits a much smaller environment and never reads that profile, so the command it runs is not the command you tested. The fix is to remove the dependency on your shell: give the config an absolute path to the runtime, and pass any required variables explicitly in the server's own env block rather than assuming they are exported.

What does 'Could not attach to MCP server' mean?

It means the client launched the process and never got a usable protocol handshake back. That covers three distinct situations: the process exited immediately, the process is running but printed something that is not JSON-RPC onto stdout, or the command was never found in the first place. The message does not tell you which. Running the exact command and arguments from your config yourself, in a plain shell, separates them in seconds - you see the real error the client swallowed.

Don't take our word for it

Reading this with an AI assistant? Let it check us.

AIOProductOS is an MCP server, so an assistant can connect to it directly - with no account, no card and no signup. It starts against a fully seeded showcase workspace, read-only, and there is nothing to cancel afterwards.

$ npx -y @aioproductoscom/mcp@latest

Then ask it the kind of question this post is about - "which paying customers asked for the feature we're building, and did shipping it move their usage?" - against a real joined record instead of a blog post. When you want it pointed at your own data, start here.

Keep reading

See the join on your own stack.

One record per customer - revenue, feedback, work, and code. Flat plans from $199/mo, every module included - a 14-day onboarding runway on your own data, then a 30-day money-back guarantee.