Connect a remote agent
Give this page to your assistant. An agent that can make HTTP requests can discover Ray, guide you through sign-in, and use its tools—even when you talk through WhatsApp or another chat app.
Read the complete HTTP connection guide as Markdown · Get the operating skill
Start with MCP discovery
The endpoint is https://letsrays.com/mcp/. Ray uses Streamable HTTP. An unauthenticated 401 is expected: follow the exact resource_metadata URL in its WWW-Authenticate header. Discover the listed authorization server’s metadata and use its advertised endpoints, resource identifier and scopes.
Reuse a valid client registration for that issuer and exact callback, or register through an advertised method. Each new authorization attempt needs fresh state and PKCE. Do not open the authorization link yourself to test it; let the user open it in their browser.
Choose a return address that works
If your client has its own reachable HTTPS callback, use it. A localhost callback works only when the user’s browser can reach the client’s listener. A phone opening a WhatsApp link cannot reach a listener on your server.
For a client that can retain an OAuth attempt and accept a pasted response, register this exact redirect URI before starting sign-in:
https://letsrays.com/agents/callback/
This page lets the user copy the response back to the same private conversation. It does not automatically notify your client. Use the same redirect URI throughout registration, authorization and token exchange.
Complete the consent and sign-in flow within 15 minutes. If it expires, start a fresh attempt with new state and PKCE.
Save the attempt, then explain sign-in
- Create random state and a PKCE verifier with an S256 challenge. Save them durably and privately with the client registration, exact redirect URI, issuer, resource and scopes before sending the link. Your runtime must be able to retrieve the verifier after the user returns.
- Send a clickable authorization link with the OAuth parameters and the explanation below. Keep the attempt pending while the user signs in. Retire older attempts when creating a new one.
- Compare the returned JSON’s
code,state,issandredirect_uriwith the saved pending attempt. Reject mismatches. The page itself does not verify your attempt or prove that the account is connected. - POST a form-encoded authorization-code exchange to the discovered token endpoint using the original verifier, redirect URI, resource and registered client authentication. Save the tokens securely and remove the completed attempt’s code and verifier. An expired/used code or missing verifier requires a new attempt.
Include this with the link:
Open this link to connect me to Ray. You’ll see a consent page naming this assistant and may be asked to sign in through Keycloak. After approval, the return page has a “Copy sign-in response” button. Paste that response back into this same private conversation. I’ll wait here, finish the connection, and check which team I can access. Use this newest link if you have older sign-in tabs open.
Keep the connection usable
Access tokens currently expire after 5 minutes. Use the token response’s expires_in and acquisition time to calculate expiry; use refresh_expires_in when returned. Refresh shortly before access-token expiry. Serialize refreshes and save replacement access and refresh tokens together, retaining the previous refresh token if no replacement is returned. Agent sign-in sessions allow 24 hours idle and require a fresh sign-in after 30 days.
Use your client’s secure credential store. Keep verifiers and tokens out of chat, logs and the notes you save in Ray. Remove obsolete attempt secrets and superseded tokens. The manual page returns an authorization response, not access or refresh tokens.
Initialize and discover the tools
POST one JSON-RPC message per request to the MCP endpoint with these headers:
Authorization: Bearer <access token> Content-Type: application/json Accept: application/json, text/event-stream
Start with initialize using a protocol version your client supports:
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"my-assistant","version":"1.0"}}}
Read the negotiated version, server capabilities and instructions. Send notifications/initialized without an ID; an empty HTTP 202 response is normal. Preserve any returned MCP-Session-Id and send the negotiated MCP-Protocol-Version on later requests. Sessions expire after 24 hours without requests and are also lost on a service restart. Call tools/list after initialization and again after a session expires or reconnects; tool lists are scoped to a live session.
Use tools/list and finish pagination using nextCursor. Read current input schemas. Discover resources and prompts when their capabilities are advertised. Then call:
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_fundraising_context","arguments":{}}}
Check the returned person, company, permissions and capture rules before writing anything. Refresh context when they change.
Read the actual result
Handle both JSON and server-sent events according to Content-Type. For SSE, join complete data: events, ignore comments, parse JSON-RPC and match the request ID. Network chunks are not complete messages.
HTTP 200 alone does not mean success. Check JSON-RPC errors, tool isError, and application statuses. needs_resolution needs an answer before anything is written; proposals await review. Verify applied changes with a fresh read.
Recover at the step that failed
- Old sign-in tab or expired code: create a new attempt and link; keep the same registered callback throughout each attempt.
- Brief 502/503: retry safe discovery or reads with bounded backoff. If a write was interrupted, read current state before deciding whether to retry.
- 401: check expiry and the challenge; refresh when appropriate. If refresh is rejected, sign in again.
- 403: inspect the scope or permission refusal; refreshing does not grant permission.
- Session 404: discard the stale session ID and initialize again using valid OAuth credentials.
Report connection success only after initialization, discovery and a successful context read. If a step keeps failing, name it and share the error without credentials.
Load the operating skill
Read or download the operating skill for research, reconciliation, photos and complete retrieval. It is available before sign-in. After connection, resources/list exposes the same files; begin with rays://skills/rays-operating/SKILL.md using resources/read.
Read the entrypoint and relevant references, or install the complete bundle through your client. Connecting MCP does not automatically install it. Follow live schemas and capture rules, and refresh installed copies when workflows change.
Report a useful problem
Once connected, use submit_feedback for concrete bugs, inconsistent behavior or documentation gaps that could materially improve Ray. Include observed versus expected behavior and minimal redacted steps. Skip feedback for its own sake. Keep the receipt and use get_feedback to read it back; reuse the same idempotency key after a timeout.
Reports go to the developers. Receipt confirms storage; the developer review and response UI will follow separately. Read the feedback guide for scope, privacy and recovery.
MCP authorization specification · HTTP transport specification