@relayrail/server 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@ RelayRail MCP Server - SMS and email connectivity for AI agents via Model Contex
6
6
 
7
7
  ```bash
8
8
  # Use with npx (recommended)
9
- npx @relayrail/server start
9
+ npx @relayrail/server
10
10
 
11
11
  # Or install globally
12
12
  npm install -g @relayrail/server
@@ -23,21 +23,21 @@ Sign up at [relayrail.dev](https://relayrail.dev) and create an agent to get you
23
23
  **Claude Code (CLI):**
24
24
 
25
25
  ```bash
26
- claude mcp add --transport stdio relayrail \
27
- --env RELAYRAIL_API_KEY=rr_your_api_key \
28
- -- npx @relayrail/server start
26
+ claude mcp add relayrail \
27
+ -e RELAYRAIL_API_KEY=rr_your_api_key \
28
+ -- npx @relayrail/server
29
29
  ```
30
30
 
31
31
  **Claude Desktop:**
32
32
 
33
- Add to `~/.config/claude/claude_desktop_config.json`:
33
+ Add to your config file (`~/.config/claude/claude_desktop_config.json` on macOS/Linux or `%APPDATA%\Claude\claude_desktop_config.json` on Windows):
34
34
 
35
35
  ```json
36
36
  {
37
37
  "mcpServers": {
38
38
  "relayrail": {
39
39
  "command": "npx",
40
- "args": ["@relayrail/server", "start"],
40
+ "args": ["@relayrail/server"],
41
41
  "env": {
42
42
  "RELAYRAIL_API_KEY": "rr_your_api_key"
43
43
  }
@@ -46,24 +46,57 @@ Add to `~/.config/claude/claude_desktop_config.json`:
46
46
  }
47
47
  ```
48
48
 
49
+ **Cursor / Cline:**
50
+
51
+ Same JSON format as above in your MCP settings.
52
+
49
53
  ## Available Tools
50
54
 
51
55
  | Tool | Description |
52
56
  |------|-------------|
53
- | `request_approval` | Request explicit user approval before proceeding |
54
- | `send_notification` | Send a one-way notification to the user |
55
- | `await_response` | Wait for a user response to an approval request |
57
+ | `request_approval` | Request user approval with custom options (Yes/No or custom choices) |
58
+ | `send_notification` | Send a one-way notification to the user (no response expected) |
59
+ | `await_response` | Wait for a user response to a previous approval request |
56
60
  | `get_pending_commands` | Retrieve commands sent by the user via SMS/email |
57
61
  | `register_agent` | Self-register a new agent (if no API key configured) |
58
62
  | `get_account_status` | Check quota usage and account status |
59
63
 
64
+ ### Tool Parameters
65
+
66
+ **`request_approval`**
67
+ - `message` (required): The approval request message
68
+ - `options`: Custom response options (default: `["Yes", "No"]`)
69
+ - `severity`: `"info"` | `"warning"` | `"critical"` - affects notification priority
70
+ - `timeout_minutes`: How long to wait for response (default: 60, max: 1440)
71
+ - `context`: Additional context data (object)
72
+
73
+ **`send_notification`**
74
+ - `message` (required): The notification message
75
+ - `severity`: `"info"` | `"warning"` | `"critical"`
76
+ - `context`: Additional context data (object)
77
+
78
+ **`await_response`**
79
+ - `request_id` (required): The request_id from a previous `request_approval` call
80
+ - `timeout_seconds`: How long to wait (default: 30, max: 300)
81
+
60
82
  ## Environment Variables
61
83
 
62
84
  | Variable | Required | Description |
63
85
  |----------|----------|-------------|
64
86
  | `RELAYRAIL_API_KEY` | Yes | Your agent's API key from relayrail.dev |
65
- | `RELAYRAIL_API_URL` | No | Override API endpoint (default: https://www.relayrail.dev/api/mcp) |
66
- | `RELAYRAIL_DEBUG` | No | Enable debug logging |
87
+ | `RELAYRAIL_BASE_URL` | No | Override API endpoint (default: https://www.relayrail.dev) |
88
+ | `RELAYRAIL_DEBUG` | No | Enable debug logging (set to `true`) |
89
+
90
+ > **Note:** You only need `RELAYRAIL_API_KEY`. The server automatically routes messages through the RelayRail API - no local Telnyx or Resend credentials required.
91
+
92
+ ## How It Works
93
+
94
+ 1. Your agent calls a tool like `request_approval`
95
+ 2. RelayRail sends an SMS or email to the user (based on their preferences)
96
+ 3. The user responds via the link or by replying directly
97
+ 4. Your agent retrieves the response with `await_response`
98
+
99
+ All message delivery is handled by the RelayRail service - you don't need to configure any SMS or email providers.
67
100
 
68
101
  ## Documentation
69
102
 
package/dist/cli.js CHANGED
@@ -147,7 +147,7 @@ function getApiKeyPrefix(apiKey) {
147
147
  if (!apiKey.startsWith(API_KEY_PREFIX)) {
148
148
  return "";
149
149
  }
150
- return apiKey.substring(0, API_KEY_PREFIX.length + 8);
150
+ return apiKey.substring(0, API_KEY_PREFIX.length + 7);
151
151
  }
152
152
  async function authenticateApiKey(supabase, apiKey) {
153
153
  if (!apiKey || !apiKey.startsWith(API_KEY_PREFIX)) {
@@ -1875,6 +1875,12 @@ var RelayRailServer = class {
1875
1875
  getContext() {
1876
1876
  return this.context;
1877
1877
  }
1878
+ /**
1879
+ * Set authentication context directly (from pre-validated API key)
1880
+ */
1881
+ setAuthContext(context) {
1882
+ this.context = context;
1883
+ }
1878
1884
  /**
1879
1885
  * Get the underlying MCP server instance
1880
1886
  */
@@ -1906,6 +1912,23 @@ function createServer(config) {
1906
1912
  }
1907
1913
 
1908
1914
  // src/cli.ts
1915
+ async function validateApiKey(apiKey, baseUrl) {
1916
+ try {
1917
+ const response = await fetch(`${baseUrl}/api/auth/validate`, {
1918
+ method: "POST",
1919
+ headers: { "Content-Type": "application/json" },
1920
+ body: JSON.stringify({ api_key: apiKey })
1921
+ });
1922
+ const data = await response.json();
1923
+ return data;
1924
+ } catch (error) {
1925
+ return {
1926
+ valid: false,
1927
+ error: `Failed to connect to RelayRail API: ${error instanceof Error ? error.message : "Unknown error"}`,
1928
+ hint: "Check your internet connection and try again."
1929
+ };
1930
+ }
1931
+ }
1909
1932
  async function main() {
1910
1933
  const apiKey = process.env.RELAYRAIL_API_KEY;
1911
1934
  if (!apiKey) {
@@ -1927,25 +1950,69 @@ async function main() {
1927
1950
  }, null, 2));
1928
1951
  process.exit(1);
1929
1952
  }
1953
+ const baseUrl = process.env.RELAYRAIL_BASE_URL || "https://www.relayrail.dev";
1954
+ const validation = await validateApiKey(apiKey, baseUrl);
1955
+ if (!validation.valid) {
1956
+ console.error(`Error: ${validation.error || "Invalid API key"}`);
1957
+ if (validation.hint) {
1958
+ console.error(`Hint: ${validation.hint}`);
1959
+ }
1960
+ console.error("");
1961
+ console.error("Get a new API key from https://relayrail.dev/dashboard/agents");
1962
+ process.exit(1);
1963
+ }
1930
1964
  const config = {
1931
1965
  supabaseUrl: process.env.SUPABASE_URL || process.env.NEXT_PUBLIC_SUPABASE_URL || "https://lcmdokppykqmigqcwnol.supabase.co",
1932
- supabaseServiceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY || "sb_secret_cj-1Y1KxjlapuwyXvfSKLA_xBJ0oS8i",
1933
- baseUrl: process.env.RELAYRAIL_BASE_URL || "https://www.relayrail.dev",
1966
+ supabaseServiceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY || "",
1967
+ baseUrl,
1934
1968
  resendApiKey: process.env.RESEND_API_KEY,
1935
1969
  telnyxApiKey: process.env.TELNYX_API_KEY,
1936
1970
  telnyxPhoneNumber: process.env.TELNYX_PHONE_NUMBER,
1937
- apiKey
1971
+ apiKey,
1938
1972
  // Used for proxy routing when local email/SMS credentials unavailable
1973
+ // Pre-validated context from hosted endpoint
1974
+ validatedAgent: validation.agent,
1975
+ validatedUser: validation.user
1939
1976
  };
1940
1977
  try {
1941
1978
  const server = createServer(config);
1942
- const authenticated = await server.authenticate(apiKey);
1943
- if (!authenticated) {
1944
- console.error("Error: Invalid API key");
1945
- console.error("");
1946
- console.error("Please check your RELAYRAIL_API_KEY and try again.");
1947
- console.error("Get a new API key from https://relayrail.dev/dashboard/agents");
1948
- process.exit(1);
1979
+ if (validation.agent && validation.user) {
1980
+ const agent = {
1981
+ id: validation.agent.id,
1982
+ name: validation.agent.name,
1983
+ user_id: validation.agent.user_id,
1984
+ is_active: validation.agent.is_active,
1985
+ created_at: validation.agent.created_at,
1986
+ // These fields are not needed for tool operations but required by type
1987
+ api_key_hash: "",
1988
+ api_key_prefix: "",
1989
+ last_seen_at: null,
1990
+ metadata: {}
1991
+ };
1992
+ const user = {
1993
+ id: validation.user.id,
1994
+ email: validation.user.email,
1995
+ phone: validation.user.phone,
1996
+ tier: validation.user.tier,
1997
+ notification_preferences: validation.user.notification_preferences,
1998
+ allow_email_overage: validation.user.allow_email_overage,
1999
+ allow_sms_overage: validation.user.allow_sms_overage,
2000
+ // These fields are not needed for tool operations but required by type
2001
+ stripe_customer_id: null,
2002
+ email_verified: true,
2003
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
2004
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
2005
+ };
2006
+ server.setAuthContext({ agent, user });
2007
+ } else {
2008
+ const authenticated = await server.authenticate(apiKey);
2009
+ if (!authenticated) {
2010
+ console.error("Error: Invalid API key");
2011
+ console.error("");
2012
+ console.error("Please check your RELAYRAIL_API_KEY and try again.");
2013
+ console.error("Get a new API key from https://relayrail.dev/dashboard/agents");
2014
+ process.exit(1);
2015
+ }
1949
2016
  }
1950
2017
  await server.start();
1951
2018
  } catch (error) {
package/dist/index.d.ts CHANGED
@@ -251,6 +251,10 @@ declare class RelayRailServer {
251
251
  * Get the current authentication context
252
252
  */
253
253
  getContext(): ToolContext | null;
254
+ /**
255
+ * Set authentication context directly (from pre-validated API key)
256
+ */
257
+ setAuthContext(context: ToolContext): void;
254
258
  /**
255
259
  * Get the underlying MCP server instance
256
260
  */
package/dist/index.js CHANGED
@@ -145,7 +145,7 @@ function getApiKeyPrefix(apiKey) {
145
145
  if (!apiKey.startsWith(API_KEY_PREFIX)) {
146
146
  return "";
147
147
  }
148
- return apiKey.substring(0, API_KEY_PREFIX.length + 8);
148
+ return apiKey.substring(0, API_KEY_PREFIX.length + 7);
149
149
  }
150
150
  async function authenticateApiKey(supabase, apiKey) {
151
151
  if (!apiKey || !apiKey.startsWith(API_KEY_PREFIX)) {
@@ -1873,6 +1873,12 @@ var RelayRailServer = class {
1873
1873
  getContext() {
1874
1874
  return this.context;
1875
1875
  }
1876
+ /**
1877
+ * Set authentication context directly (from pre-validated API key)
1878
+ */
1879
+ setAuthContext(context) {
1880
+ this.context = context;
1881
+ }
1876
1882
  /**
1877
1883
  * Get the underlying MCP server instance
1878
1884
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relayrail/server",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "RelayRail MCP Server - SMS/Email connectivity for AI agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",