Claude is a wonderful way to use an MCP server and a terrible way to debug one.

That is not a criticism. Claude’s job is to interpret a request, decide whether a tool is useful, call it, and turn the result into a helpful answer. During debugging, those conveniences create ambiguity. Did OAuth fail? Did tool discovery fail? Did Claude decide not to call the tool? Did the tool return malformed content? Did the model simply misunderstand the result?

If you begin with the full AI experience, five different layers can produce the same disappointing sentence.

Postman gives you a more boring path. Boring is exactly what we want.

The goal is to prove the protocol in small pieces—metadata, authorization, tokens, initialization, tool discovery, and tool execution—before adding model behavior.

Visual placeholder: Opening split-screen. Left: Claude displays a generic connector error surrounded by question marks. Right: Postman shows a precise 401 response with an `invalid_token` detail. Caption: “Mystery vs. evidence.”

The debugging ladder

Treat a remote MCP connection as a ladder. Do not climb to the next rung until the current one holds.

  1. The server is reachable over HTTPS.
  2. Protected-resource and authorization metadata are discoverable.
  3. The OAuth authorization flow completes.
  4. The token endpoint issues the expected token.
  5. The MCP endpoint accepts that token.
  6. MCP initialization succeeds.
  7. The server lists its tools.
  8. A tool returns a valid result.
  9. Claude can connect and use it.

This order matters. Testing step nine while step four is broken creates a highly advanced random-number generator.

Visual placeholder: Vertical ladder graphic with the nine rungs. Animate each rung turning green as the article progresses.

Start with reachability, not OAuth

Before configuring Postman authorization, verify that the hostname resolves, the TLS certificate is valid, and a deliberately public health endpoint responds.

A health endpoint should be useful but uninteresting. Return a status and perhaps a version or build identifier. Do not expose environment variables, tenant IDs, configured secrets, or downstream connection details.

Then send an unauthenticated request to the MCP endpoint. A 401 response is often good news. It proves that DNS, TLS, ingress, routing, and at least one authentication boundary are functioning.

A timeout, 404, 502, and 401 are not interchangeable “it doesn’t work” outcomes. Preserve the distinction.

Discover the server’s metadata

OAuth-protected MCP servers use metadata to tell clients where authorization happens and how the protected resource is identified. Fetch those documents directly and inspect the values.

Confirm that:

  • Every advertised URL is publicly reachable.
  • HTTPS is used consistently.
  • The authorization server issuer is exact.
  • Authorization and token endpoints point to the intended environment.
  • The protected resource matches the MCP endpoint’s expected audience.
  • Supported PKCE methods include what your client will use.

Small URL differences cause large amounts of confusion. A missing path segment, stale deployment hostname, or production issuer paired with a development resource can allow the browser portion of OAuth to look successful while producing a token the API will never accept.

Visual placeholder: Postman screenshot of the metadata response. Add callouts around issuer, authorization endpoint, token endpoint, resource, and PKCE support.

Run Authorization Code with PKCE deliberately

For a public client, Authorization Code with Proof Key for Code Exchange prevents an intercepted authorization code from being redeemed without the original verifier.

Postman can generate the verifier and challenge for you, but you should still understand the sequence:

  1. The client creates a random code verifier.
  2. It hashes that verifier into a code challenge.
  3. The authorization request includes the challenge.
  4. The user signs in and approves access.
  5. The authorization server redirects back with a short-lived code.
  6. The client exchanges the code plus the original verifier for tokens.

Configure the callback URL exactly as registered with the authorization server. OAuth compares redirect URIs precisely for good reason; “almost the same URL” is not a category.

During the first pass, capture the authorization response and token response without copying tokens into notes, screenshots, tickets, or chat. Postman can hold the token as an environment variable and apply it to later requests.

Visual placeholder: Short animation of the PKCE exchange. Show the challenge traveling outward and the hidden verifier returning at token exchange. Do not show a real token.

Inspect the token’s claims safely

If the token is a JWT, decode its header and payload locally or with a trusted internal tool. Decoding is not validation; it is only a way to inspect the claims.

The claims that most often explain a rejection are:

  • iss: who issued the token
  • aud: which API the token is meant for
  • exp and nbf: when it is valid
  • scp: delegated scopes
  • roles: application roles
  • oid or sub: the calling identity
  • tid: the tenant

Your server must still verify the signature using the issuer’s published keys and enforce issuer, audience, time, and permission requirements. A token that looks beautifully formatted can still be invalid.

Create a small claim checklist for each environment. “Audience should be the MCP application ID” is more useful than repeatedly staring at a long GUID and waiting for enlightenment.

Call the MCP endpoint yourself

Now use the access token as a bearer token and initialize an MCP session. The exact request shape depends on the protocol version and transport supported by your server, so use the current MCP specification and SDK behavior as your source of truth.

At this stage, save the raw requests and responses. Check:

  • HTTP status and content type
  • Protocol-version negotiation
  • Session identifiers or related headers
  • JSON-RPC request IDs
  • Error objects, not just error messages

Once initialization succeeds, request the tool list. Tool discovery should be deterministic. You should see the name, description, and input schema for every tool you intended to publish—and no experimental or dangerous tools you forgot to hide.

Then call the smallest possible tool. A get_status or tightly capped list operation is better than a broad semantic search backed by three external services.

Visual placeholder: Three Postman tabs labeled Initialize, List Tools, and Call Tool. Animate a green check appearing on each.

Read failures by layer

Here is the practical map I use:

The browser never reaches sign-in

Suspect authorization metadata, an invalid authorization URL, client registration, or redirect configuration.

Sign-in succeeds but token exchange fails

Suspect the callback URI, PKCE verifier, client authentication expectations, authorization-code reuse, or token-endpoint configuration.

A token is issued but /mcp returns 401

Suspect signature validation, issuer, audience, expiry, or missing scopes and roles.

/mcp returns 403 and the application has no log entry

Suspect an upstream authorization layer such as Azure Container Apps Easy Auth, an ingress policy, or a web application firewall.

Initialization works but tools are missing

Suspect server registration, feature flags, protocol-version behavior, or tool schema construction.

The direct tool call works but Claude does not use it

Congratulations: you have finally earned the right to investigate Claude-side configuration, tool enablement, descriptions, and prompting.

That last sentence is not sarcasm. Reaching it means you have removed most of the system from suspicion.

Make Postman a permanent smoke test

Do not discard the collection after the first successful connection. Sanitize it and keep it with the project as an operational artifact.

A useful collection contains:

  • Health check
  • Protected-resource metadata
  • Authorization-server metadata
  • OAuth configuration using variables
  • Unauthenticated MCP request expecting 401
  • Authenticated initialization
  • Tool listing
  • One harmless tool call
  • One deliberately forbidden operation or identity test

Use environment variables for hostnames, client IDs, resource identifiers, and tokens. Exported collections should contain placeholders, never live credentials. Add a short README explaining which values are safe to share and which must remain local.

This collection becomes valuable during deployments. If a new container revision fails, you can determine in minutes whether the problem is ingress, OAuth, protocol negotiation, or the downstream tool. That is much faster than asking the model progressively angrier versions of the same question.

Then bring Claude back in

Once Postman proves the end-to-end protocol, add the remote connector in Claude and authenticate it. Enable only the tool you already tested. Use a prompt that clearly requires that tool and asks for fields you know the direct response contains.

If it works, expand gradually. If it fails, the remaining search space is small: connector configuration, Claude organization policy, individual tool enablement, or how clearly the tool description communicates its purpose.

AI integrations feel unpredictable when protocol failures and model decisions are mixed together. Separate them. Make the network and authentication path boring first; then let the model be the interesting part.

References