Edit Page

Connect Claude Desktop

RESTHeart Cloud

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. Leave it there and Claude asks you to reconnect โ€” with the full sign-in again โ€” every quarter of an hour, because RESTHeart does not issue refresh tokens: grant_types_supported is authorization_code, password and client_credentials, so an expired access token cannot be renewed, only replaced by running the whole flow again. 480 gives you a working day. 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

It matters when the agent executes the request how_to_call composed through a browser rather than an HTTP library โ€” it then 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

jwtTokenManager/ttl is at its default. There are no refresh tokens, so the token has to outlive your 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.