Connect Claude Desktop
RESTHeart CloudConnect 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 |
Claude cannot find the authorization server |
|
The sign-in page loads but the redirect fails |
|
It worked yesterday and not today |
ngrok issued a new URL. Update both |
Claude asks to reconnect every 15 minutes |
|
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. |
|
|