Edit Page

Connect Claude Desktop

RESTHeart Cloud
Prefer not to run it yourself? RESTHeart Cloud is this, hosted, with sign-up, payments and an MCP server already on. Free to start. Get started →

Connect Claude Desktop to a RESTHeart running on your own machine, over a public HTTPS URL, with users signing in through OAuth.

Claude Desktop needs a reachable https:// endpoint, so a local instance has to be tunnelled โ€” this page uses ngrok. Everything else is RESTHeart configuration.

Note
The MCP server is available starting from RESTHeart v9.9.

1. Tunnel your instance

ngrok http 8080

Note the forwarding URL it prints โ€” https://ae5b-93-34-53-143.ngrok-free.app in the examples below. It changes every time you restart ngrok on the free plan, and both the RESTHeart configuration and the connector have to be updated when it does.

2. Start RESTHeart with OAuth enabled

All four OAuth services are disabled by default. Claude needs all of them: one to discover the authorization server, one to discover its endpoints, one to register itself, and one to run the flow.

RHO='/jwtTokenManager/ttl->480;
/mcpService/public-base-url->"https://ae5b-93-34-53-143.ngrok-free.app";
/oauthProtectedResourceMetadataService/enabled->true;
/oauthProtectedResourceMetadataService/base-url->"https://ae5b-93-34-53-143.ngrok-free.app";
/oauthAuthorizationServerMetadataService/enabled->true;
/oauthAuthorizationServerMetadataService/base-url->"https://ae5b-93-34-53-143.ngrok-free.app";
/oauthAuthorizationServerMetadataService/registration-endpoint-uri->"/register";
/oauthClientRegistrationService/enabled->true;
/oauthAuthorizationService/enabled->true;
/oauthAuthorizationService/allowed-redirect-uris->["https://claude.ai/api/mcp/auth_callback","http://localhost:*"]' \
java -jar restheart.jar
Warning
Substitute your own ngrok URL in all three places. The two base-url values are what the OAuth metadata advertises as the issuer, and a wrong one sends Claude to a host that does not exist.

mcpService/public-base-url is what the resources primitive builds resource URIs from. It defaults to http://localhost:8080, so leaving it out gives a remote client a catalogue of resources at localhost โ€” reading them through MCP still works, but an agent that takes those URIs and makes an HTTP call with them reaches nothing.

base-url is required rather than optional here: ngrok terminates TLS, so the Host header reaches RESTHeart as http:// while the public URL is https://, and issuer validation fails per RFC 8414 ยง3.3 unless you say what the public URL is.

You do not need to set login-url. It defaults to /oauth/login, the sign-in page RESTHeart serves itself, and it is deliberately relative: the browser resolves it against the origin it is already on, which is the https:// one.

jwtTokenManager/ttl is in minutes and defaults to 15. Since 9.9.0 Claude renews the token on its own โ€” grant_types_supported includes refresh_token โ€” so the default no longer means signing in every quarter of an hour. Raise it to 480 anyway if you want a session that survives a client which renews badly, or an instance restarted with a fresh signing key. Raise it only as far as you are willing to have a leaked token remain valid.

Check the metadata before going further:

curl https://ae5b-93-34-53-143.ngrok-free.app/.well-known/oauth-protected-resource
{ "resource": "https://ae5b-93-34-53-143.ngrok-free.app",
  "authorization_servers": ["https://ae5b-93-34-53-143.ngrok-free.app"] }

If those URLs are not your ngrok host, fix base-url and restart โ€” nothing after this step will work.

3. Add the connector in Claude Desktop

Settings โ†’ Connectors โ†’ Add custom connector, with the URL of the MCP endpoint:

https://ae5b-93-34-53-143.ngrok-free.app/mcp
Important
Include /mcp. Without it the requests go to RESTHeart’s root, the connector still appears to connect, and it reports having no tools available.

Leave the Authorization header empty: OAuth provides the credential.

4. Sign in

Click Connect. Claude registers itself, then opens the sign-in page RESTHeart serves. Enter the username and password of a RESTHeart user โ€” the page says which application is asking, by the host it will return you to.

Once signed in, the connector is live. Ask Claude what it can reach:

> what APIs do you have access to on restheart?

What the agent may see and do

The account you sign in with is the account the agent acts as. Its roles decide everything: which resources appear in the catalog, which reads succeed, which writes are refused. See Securing it โ€” you almost certainly do not want to sign in as admin.

Grant the agent’s role POST, GET and DELETE on /mcp, not POST alone: GET opens the stream notifications are delivered on, and DELETE ends the session.

The ngrok interstitial

On the free plan ngrok serves a warning page before your site โ€” but only to requests that look like they come from a browser, meaning a browser User-Agent together with Accept: text/html. A normal HTTP client gets your JSON:

curl -u admin:secret https://ae5b-93-34-53-143.ngrok-free.app/ping     # application/json

The agent itself never hits it: call_api and resources/read run on RESTHeart, and the MCP transport is a normal HTTP client. It matters for code of your own that opens a how_to_call descriptor through a browser โ€” that gets the warning page instead of the response. Add the header ngrok looks for:

ngrok-skip-browser-warning: 1

Any value works; ngrok only checks that the header is present. A paid ngrok plan, or any other tunnel, removes the problem.

If something does not work

Symptom Cause

"This connector has no tools available"

The connector URL is missing /mcp.

Claude cannot find the authorization server

base-url is wrong, or the metadata services are not enabled. Check /.well-known/oauth-protected-resource returns your ngrok host.

The sign-in page loads but the redirect fails

https://claude.ai/api/mcp/auth_callback is not in allowed-redirect-uris.

It worked yesterday and not today

ngrok issued a new URL. Update both base-url values and the connector.

Claude asks to reconnect every 15 minutes

Renewal is not reaching the server. Check that POST /token is allowed for the signed-in user’s role, and that you are on 9.9.0 or later โ€” before it there was no refresh_token grant and ttl had to outlive the whole session.

The catalog is empty but tools are listed

The signed-in user’s ACL grants nothing. The catalog only shows what that user could read.

A call returns HTML instead of JSON

ngrok’s free-plan warning page โ€” the request was made from a browser. See above.

resources/list shows localhost URIs

mcpService/public-base-url is not set to your ngrok URL.