MCP server
Railhook serves a Model Context Protocol server at /mcp, so an AI agent can work with your project directly: find out why a delivery failed, replay it, register an endpoint, send a test event. It acts on one project, with read-only or read & write access, and can do nothing more.
| Where | MCP server URL |
|---|---|
| Railhook Cloud | https://railhook.io/mcp |
| Self-hosted | <your origin>/mcp, e.g. https://hooks.example.com/mcp |
There are two ways in:
- Sign in. Apps that connect to remote servers themselves — claude.ai, Claude Desktop’s connectors, ChatGPT — send you to Railhook to approve them for a project. Nothing to copy or paste.
- A project API key. Clients configured from a file or a command line — Claude Code, Cursor, the
@railhook/mcpstdio bridge — send the key as a header.
Both reach the same tools with the same limits. The server speaks Streamable HTTP.
Connect by signing in
Section titled “Connect by signing in”- Open Settings → Connectors (in newer versions, Customize → Connectors) and add a custom connector.
- Name it
Railhookand enter the URLhttps://railhook.io/mcp. Leave the OAuth client ID and secret empty: Claude registers itself. - Click Connect. Railhook opens; sign in if you are not already.
- Pick the organization and project, choose Read Only or Read & Write, and click Connect. You are sent back to Claude.
A connector added on claude.ai is also available in Claude Desktop and the mobile apps signed in to the same account.
- Turn on developer mode: Settings → Apps → Advanced settings → Developer mode. On a Business or Enterprise workspace an admin may have to allow custom connectors first.
- Create a connector with the URL
https://railhook.io/mcpand OAuth as its authentication. - ChatGPT opens Railhook. Sign in, pick the organization and project, choose the access, and click Connect.
What you approve is exactly what an API key carries — one project and one scope — so an app you connect read-only cannot send an event or replay a delivery. The menus above change between versions of each app; what stays the same is the URL, and that the app handles the sign-in.
Who can connect what
Section titled “Who can connect what”Any member of the organization can connect an app read-only. Read & write takes the Owner or Developer role, the same roles that may create an API key. A connected app keeps working only while the person who approved it could approve it today: removing or suspending them, or taking a Developer down to Viewer, stops the apps they connected.
The app gets an access token for an hour at a time and renews it on its own, so it keeps working until someone disconnects it.
See and disconnect apps
Section titled “See and disconnect apps”A project’s connected apps are listed under API Keys, below the keys, with the access each has, the host it signed in from, who approved it and when it was last used. Disconnect stops it at once; to use it again, connect it again from the app. Connecting and disconnecting are recorded in the organization’s audit log, under the person who did it.
Connect with an API key
Section titled “Connect with an API key”claude mcp add --transport http railhook https://railhook.io/mcp \ --header "Authorization: Bearer $RAILHOOK_API_KEY"Add --scope user to have it in every project. claude mcp list shows whether it connected.
{ "mcpServers": { "railhook": { "url": "https://railhook.io/mcp", "headers": { "Authorization": "Bearer ${env:RAILHOOK_API_KEY}" } } }}~/.cursor/mcp.json makes it available in every project. ${env:RAILHOOK_API_KEY} is read from Cursor’s environment, so the key stays out of the file.
Servers in Claude Desktop’s config file are local processes, so they use the bridge. It needs Node.js 18 or later. To connect by signing in instead, add a connector as above.
{ "mcpServers": { "railhook": { "command": "npx", "args": ["-y", "@railhook/mcp"], "env": { "RAILHOOK_API_KEY": "your-project-api-key" } } }}Open the file from Settings → Developer → Edit Config, then restart Claude Desktop.
A client that supports remote servers needs the URL and one header, either of:
Authorization: Bearer <project API key>X-API-Key: <project API key>A client that only starts local processes runs the bridge instead:
RAILHOOK_API_KEY=<project API key> npx -y @railhook/mcpSelf-hosted
Section titled “Self-hosted”Replace https://railhook.io with your own origin in the URL. For the bridge, set RAILHOOK_BASE_URL next to the key:
"env": { "RAILHOOK_API_KEY": "your-project-api-key", "RAILHOOK_BASE_URL": "https://hooks.example.com"}Signing in needs two things from the instance. APP_BASE_URL must be its public HTTPS origin: it is the address the app is sent to and back from, and the issuer the app checks. And claude.ai and ChatGPT connect from their own servers, so the instance has to be reachable from the internet; one on a private network takes API keys only.
Both switches are on by default. MCP_ENABLED=false in .env turns /mcp off; MCP_OAUTH_ENABLED=false keeps it on for API keys and turns signing in off. See Configuration.
Every tool acts on the project the API key or the connected app belongs to. None takes a project id, so an agent cannot reach another project, even in the same organization.
| Tool | What it does | Access |
|---|---|---|
list_endpoints |
The project’s endpoints, with whether each is enabled and verified | Any |
list_subscriptions |
Which endpoint receives which event type, optionally for one endpoint | Any |
list_deliveries |
Deliveries, newest first, filtered by status, endpoint, event, event type or time | Any |
get_delivery |
One delivery and every attempt at it: status code, error, duration, request and response bodies | Any |
send_event |
Sends an event; one delivery is created per enabled subscription to its type | READ_WRITE |
create_endpoint |
Registers an endpoint and returns its signing secret, once | READ_WRITE |
create_subscription |
Subscribes an endpoint to an event type | READ_WRITE |
replay_delivery |
Puts a FAILED or DLQ delivery back on its retry ladder; dryRun shows what would be sent |
READ_WRITE |
The read tools carry the read-only hint, which a client can use to run them without asking you first. Endpoints, subscriptions, deliveries and attempts come back in the shapes the API reference documents, with attempt bodies cut to 2,000 characters; a list comes as content plus page, size, totalElements and totalPages.
The same limits apply as over the API: send_event counts against the project’s rate limit and event quota, and create_endpoint against the endpoint limit.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Fix |
|---|---|
401 when the client connects with a key |
The key is wrong, revoked or expired, or it belongs to another instance than the URL. Create a new key |
| The app asks you to sign in again | The app was disconnected, or the person who approved it was removed, suspended or lost the role it needs. Connect it again |
| “This request has expired” on the consent screen | The screen was open for more than ten minutes, or already answered. Start connecting again from the app |
| “This app can’t be connected” | The app asked to return somewhere it did not register. Remove the connector in the app and add it again |
| A tool answers that the key or app is read-only | Expected for write tools. Use a READ_WRITE key, or reconnect the app with Read & Write |
404 at /mcp or /.well-known/oauth-authorization-server on a self-hosted instance |
MCP_ENABLED or MCP_OAUTH_ENABLED is false, or the instance predates it. Upgrade it |
The bridge exits with RAILHOOK_API_KEY is not set |
Put the key in the env block of the client’s config, not in args |