Give your customers your MCP server.
Publish the services Rayrun hosts for you as one public MCP server. Your customers add its address to their own AI client and sign in with your identity provider. They never join your workspace.
Your provider proves who each customer is. Rayrun stays the authorization server: it issues the tokens, applies your policy to every call, and can end a customer’s access at once.
{
"mcpServers": {
"acme-issues": {
"url": "https://ray.run/p/acme-issues/mcp"
}
}
}From a hosted service to a public server.
Only services Rayrun hosts can be published. Remote MCP servers and OpenAPI connections cannot be published yet.
Create
Choose the hosted services to offer and the address they are reached at. A draft serves nobody.
Connect and test sign-in
Connect your OpenID Connect provider, then test a real sign-in before publishing. The test verifies your credentials and Rayrun redirect URI.
Publish
Publish and share the address. Unpublishing stops it at once, and publishing again restores every customer’s access.
Your server knows who is calling.
Every call carries a short-lived token Rayrun signs, naming the customer your provider signed in. Verify it in one call and scope data to that customer. Projects from rayrun init already read it.
If Rayrun cannot sign the token, your server is not called at all.
import { verifyIdentityAssertion } from '@rayrun/sdk';
const identity = await verifyIdentityAssertion({
assertion: request.headers.get('rayrun-identity'),
environment: process.env,
});
if (identity !== null) {
// externalId is the subject your provider signed in.
console.log(identity.externalId, identity.email);
}The customer who made the call approves it.
When your policy asks before a change, the decision belongs to the customer who made the call, not to your administrators. They sign in again with your provider first, so a forwarded link is not enough to approve anything.
Each approval link reaches your webhook as it is issued, so your product can put the decision where your customer already is.
{
"id": "whd_…",
"type": "publication.approval.requested",
"occurredAt": "2026-09-14T09:30:00Z",
"data": {
"approvalUid": "…",
"approvalUrl": "https://ray.run/p/acme-issues/approve/…",
"connectionId": "01993fe8-78d7-7c7d-a681-11aa03e6f7a2",
"endUserUid": "…",
"expiresAt": "2026-09-14T09:40:00.000Z",
"publicationUid": "…",
"toolName": "create_issue"
}
}Serve it from your own domain.
Add a subdomain such as mcp.example.com. Publish the TXT record Rayrun shows to prove you own it, and a CNAME that points it at Rayrun. Cloudflare issues its certificate.
- Rayrun asks nothing of Cloudflare until your TXT record is found.
- If the record goes missing, the domain keeps serving for 7 days, then stops.
- Your Rayrun address keeps working beside the domain.
Automate it.
Create, configure, publish, and version publications from CI with the CLI, the API, or the JavaScript SDK. The CLI reads your provider’s client secret from stdin, never from an argument.
rayrun publications create acme-issues --name 'Acme issues' \
--services <connection-id>
printf %s "$OIDC_CLIENT_SECRET" | \
rayrun publications sign-in set <publication-uid> \
--issuer https://login.example.com --client-id rayrun-acme-issues \
--client-secret-stdin
rayrun publications publish <publication-uid> --reason 'Launch'
rayrun publications domain set <publication-uid> mcp.example.com