@relaycast/mcp 0.5.1 → 0.5.3

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.
Files changed (58) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/piggyback.d.ts +12 -1
  6. package/dist/piggyback.d.ts.map +1 -1
  7. package/dist/piggyback.js +39 -16
  8. package/dist/piggyback.js.map +1 -1
  9. package/dist/prompts.d.ts +1 -1
  10. package/dist/prompts.d.ts.map +1 -1
  11. package/dist/prompts.js +9 -9
  12. package/dist/resources/definitions.d.ts +6 -1
  13. package/dist/resources/definitions.d.ts.map +1 -1
  14. package/dist/resources/definitions.js +38 -12
  15. package/dist/resources/definitions.js.map +1 -1
  16. package/dist/server.d.ts +5 -0
  17. package/dist/server.d.ts.map +1 -1
  18. package/dist/server.js +177 -38
  19. package/dist/server.js.map +1 -1
  20. package/dist/stdio.js +12 -7
  21. package/dist/stdio.js.map +1 -1
  22. package/dist/tool-aliases.d.ts +67 -0
  23. package/dist/tool-aliases.d.ts.map +1 -0
  24. package/dist/tool-aliases.js +71 -0
  25. package/dist/tool-aliases.js.map +1 -0
  26. package/dist/tools/channels.d.ts +5 -2
  27. package/dist/tools/channels.d.ts.map +1 -1
  28. package/dist/tools/channels.js +32 -21
  29. package/dist/tools/channels.js.map +1 -1
  30. package/dist/tools/features.d.ts +4 -1
  31. package/dist/tools/features.d.ts.map +1 -1
  32. package/dist/tools/features.js +28 -20
  33. package/dist/tools/features.js.map +1 -1
  34. package/dist/tools/messaging.d.ts +7 -1
  35. package/dist/tools/messaging.d.ts.map +1 -1
  36. package/dist/tools/messaging.js +34 -21
  37. package/dist/tools/messaging.js.map +1 -1
  38. package/dist/tools/programmability.d.ts +7 -1
  39. package/dist/tools/programmability.d.ts.map +1 -1
  40. package/dist/tools/programmability.js +22 -18
  41. package/dist/tools/programmability.js.map +1 -1
  42. package/dist/tools/registration.d.ts +4 -1
  43. package/dist/tools/registration.d.ts.map +1 -1
  44. package/dist/tools/registration.js +317 -21
  45. package/dist/tools/registration.js.map +1 -1
  46. package/dist/transports.d.ts +1 -1
  47. package/dist/transports.d.ts.map +1 -1
  48. package/dist/transports.js +128 -48
  49. package/dist/transports.js.map +1 -1
  50. package/dist/types.d.ts +23 -0
  51. package/dist/types.d.ts.map +1 -1
  52. package/dist/types.js +4 -0
  53. package/dist/types.js.map +1 -1
  54. package/dist/workspaces.d.ts +69 -0
  55. package/dist/workspaces.d.ts.map +1 -0
  56. package/dist/workspaces.js +134 -0
  57. package/dist/workspaces.js.map +1 -0
  58. package/package.json +3 -3
@@ -1,56 +1,136 @@
1
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
- import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3
- import { createInternalRelayCast } from "@relaycast/sdk/internal";
4
- import { createRelayMcpServer, MCP_VERSION, } from "./server.js";
5
- import { randomUUID } from "node:crypto";
6
- import { createMcpTelemetry } from "./telemetry.js";
7
- async function resolveStdioBootstrapOptions(options) {
8
- if (!options.apiKey || !options.agentName) {
9
- return options;
10
- }
11
- const relay = createInternalRelayCast({
12
- apiKey: options.apiKey,
13
- baseUrl: options.baseUrl,
14
- }, {
15
- surface: "mcp",
16
- client: "@relaycast/mcp",
17
- version: MCP_VERSION,
18
- });
19
- if (options.agentToken) {
1
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3
+ import { createRelayMcpServer, MCP_VERSION } from './server.js';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { createMcpTelemetry } from './telemetry.js';
6
+ import { createInternalRelayCast } from '@relaycast/sdk/internal';
7
+ import { resolveDefaultWorkspaceId } from './workspaces.js';
8
+ const mcpOrigin = {
9
+ surface: 'mcp',
10
+ client: '@relaycast/mcp',
11
+ version: MCP_VERSION,
12
+ };
13
+ /**
14
+ * Bootstrap a single workspace by verifying/refreshing its token.
15
+ * Wrapped with a per-workspace timeout enforced via Promise.race so
16
+ * one slow workspace doesn't block all others.
17
+ */
18
+ async function bootstrapOneWorkspace(ws, baseUrl, timeoutMs = 5_000) {
19
+ const doBootstrap = async () => {
20
+ const relay = createInternalRelayCast({
21
+ apiKey: ws.api_key,
22
+ baseUrl,
23
+ }, mcpOrigin);
24
+ let token = ws.agent_token;
25
+ const agentName = ws.agent_name ?? ws.workspace_alias ?? ws.workspace_id;
26
+ let workspaceName = ws.workspace_name;
20
27
  try {
21
- await relay.as(options.agentToken).inbox();
22
- return options;
28
+ const workspace = await relay.workspace.info();
29
+ workspaceName = workspace.name;
30
+ }
31
+ catch {
32
+ // Keep any pre-supplied name or leave undefined if workspace info is unavailable.
23
33
  }
24
- catch (err) {
25
- const relayErr = err;
26
- const unauthorized = relayErr?.code === "unauthorized" ||
27
- relayErr?.statusCode === 401 ||
28
- relayErr?.statusCode === 403;
29
- if (!unauthorized) {
30
- throw err;
34
+ // If we have a token, verify it's still valid via an inbox call
35
+ if (token) {
36
+ try {
37
+ const client = relay.as(token);
38
+ await client.inbox();
39
+ }
40
+ catch {
41
+ // Token is invalid, need to re-register
42
+ token = undefined;
31
43
  }
32
44
  }
45
+ // If no valid token, register or rotate
46
+ if (!token) {
47
+ const result = await relay.agents.registerOrRotate({
48
+ name: agentName,
49
+ type: 'agent',
50
+ });
51
+ token = result.token;
52
+ }
53
+ return {
54
+ ...ws,
55
+ agent_token: token,
56
+ agent_name: agentName,
57
+ workspace_name: workspaceName,
58
+ };
59
+ };
60
+ try {
61
+ let timer;
62
+ const timeout = new Promise((_, reject) => {
63
+ timer = setTimeout(() => reject(new Error(`Bootstrap timed out after ${timeoutMs}ms`)), timeoutMs);
64
+ });
65
+ const result = await Promise.race([doBootstrap(), timeout]);
66
+ clearTimeout(timer);
67
+ return result;
33
68
  }
34
- const registered = await relay.agents.registerOrRotate({
35
- name: options.agentName,
36
- type: options.agentType,
69
+ catch (err) {
70
+ console.error(`[bootstrap] Failed to bootstrap workspace ${ws.workspace_id}: ${err instanceof Error ? err.message : String(err)}`);
71
+ // Still return the workspace config even if bootstrap failed,
72
+ // so it can be retried later
73
+ return ws;
74
+ }
75
+ }
76
+ /**
77
+ * Bootstrap workspaces by verifying/refreshing tokens and joining each
78
+ * workspace into the MCP server's session via setSession + saveWorkspaceContext.
79
+ *
80
+ * All workspaces are bootstrapped concurrently with individual timeouts.
81
+ */
82
+ async function bootstrapWorkspaces(workspaces, baseUrl) {
83
+ const results = await Promise.allSettled(workspaces.map(ws => bootstrapOneWorkspace(ws, baseUrl)));
84
+ return results.map((result, i) => {
85
+ if (result.status === 'fulfilled')
86
+ return result.value;
87
+ console.error(`[bootstrap] Workspace ${workspaces[i].workspace_id} rejected: ${result.reason}`);
88
+ return workspaces[i];
37
89
  });
38
- return {
39
- ...options,
40
- agentToken: registered.token,
41
- agentName: registered.name ?? options.agentName,
42
- };
43
90
  }
44
91
  /**
45
92
  * Start MCP server with stdio transport (single agent).
46
93
  * Reads from stdin, writes to stdout.
47
94
  */
48
95
  export async function startStdio(options) {
49
- const bootstrappedOptions = await resolveStdioBootstrapOptions(options);
50
- const mcpServer = createRelayMcpServer({
51
- ...bootstrappedOptions,
52
- telemetryTransport: "stdio",
53
- });
96
+ let effectiveOptions = { ...options, telemetryTransport: 'stdio' };
97
+ const hasAgentToken = Boolean(options.agentToken);
98
+ const hasWorkspaces = Boolean(options.workspaces?.length);
99
+ if (hasWorkspaces) {
100
+ if (hasAgentToken) {
101
+ // When agentToken is pre-provided (broker-spawned), skip bootstrap entirely —
102
+ // the token is already valid. Use workspace configs as-is for routing context.
103
+ const withNames = options.workspaces.map(ws => ({
104
+ ...ws,
105
+ agent_name: ws.agent_name ?? ws.workspace_alias ?? ws.workspace_id,
106
+ }));
107
+ effectiveOptions = { ...effectiveOptions, workspaces: withNames };
108
+ // Promote default workspace credentials so routing resolves correctly
109
+ const defaultWsId = resolveDefaultWorkspaceId(withNames, options.defaultWorkspace);
110
+ const defaultWs = withNames.find(w => w.workspace_id === defaultWsId);
111
+ if (defaultWs) {
112
+ effectiveOptions.apiKey = effectiveOptions.apiKey ?? defaultWs.api_key;
113
+ effectiveOptions.agentName = effectiveOptions.agentName ?? defaultWs.agent_name;
114
+ }
115
+ }
116
+ else {
117
+ // CLI user with RELAY_WORKSPACES_JSON — bootstrap is needed but now
118
+ // runs all workspaces concurrently (with per-workspace timeouts).
119
+ const bootstrapped = await bootstrapWorkspaces(options.workspaces, options.baseUrl);
120
+ effectiveOptions = { ...effectiveOptions, workspaces: bootstrapped };
121
+ // Set the default workspace's api key/token/name as the primary session
122
+ const defaultWsId = resolveDefaultWorkspaceId(bootstrapped, options.defaultWorkspace);
123
+ const defaultWs = bootstrapped.find(w => w.workspace_id === defaultWsId && w.agent_token);
124
+ if (defaultWs) {
125
+ effectiveOptions.apiKey = effectiveOptions.apiKey ?? defaultWs.api_key;
126
+ effectiveOptions.agentToken = effectiveOptions.agentToken ?? defaultWs.agent_token;
127
+ effectiveOptions.agentName = effectiveOptions.agentName ?? defaultWs.agent_name;
128
+ }
129
+ }
130
+ }
131
+ // createRelayMcpServer populates session.workspaces from
132
+ // effectiveOptions.workspaces internally — no need to reach into internals.
133
+ const mcpServer = createRelayMcpServer(effectiveOptions);
54
134
  const transport = new StdioServerTransport();
55
135
  await mcpServer.connect(transport);
56
136
  }
@@ -69,7 +149,7 @@ export function createHttpHandler(baseOptions, lifecycle) {
69
149
  hasSession: (sessionId) => sessions.has(sessionId),
70
150
  handleRequest: async (req, res) => {
71
151
  // Check for existing session
72
- const sessionId = req.headers["mcp-session-id"];
152
+ const sessionId = req.headers['mcp-session-id'];
73
153
  if (sessionId && sessions.has(sessionId)) {
74
154
  const session = sessions.get(sessionId);
75
155
  await session.transport.handleRequest(req, res);
@@ -77,8 +157,8 @@ export function createHttpHandler(baseOptions, lifecycle) {
77
157
  }
78
158
  // New session — create fresh MCP server + transport + telemetry
79
159
  const telemetry = createMcpTelemetry(MCP_VERSION, {
80
- originSurface: "mcp",
81
- originClient: "@relaycast/mcp",
160
+ originSurface: 'mcp',
161
+ originClient: '@relaycast/mcp',
82
162
  originVersion: MCP_VERSION,
83
163
  });
84
164
  const transport = new StreamableHTTPServerTransport({
@@ -86,7 +166,7 @@ export function createHttpHandler(baseOptions, lifecycle) {
86
166
  });
87
167
  const mcpServer = createRelayMcpServer({
88
168
  ...baseOptions,
89
- telemetryTransport: "http",
169
+ telemetryTransport: 'http',
90
170
  telemetry,
91
171
  });
92
172
  transport.onclose = () => {
@@ -102,9 +182,9 @@ export function createHttpHandler(baseOptions, lifecycle) {
102
182
  if (transport.sessionId && !sessions.has(transport.sessionId)) {
103
183
  sessions.set(transport.sessionId, { transport });
104
184
  lifecycle?.onCreated?.(transport.sessionId);
105
- telemetry.capture("relaycast_mcp_http_session_started", {
106
- source_surface: "mcp",
107
- transport: "http",
185
+ telemetry.capture('relaycast_mcp_http_session_started', {
186
+ source_surface: 'mcp',
187
+ transport: 'http',
108
188
  mcp_transport_session_id: transport.sessionId,
109
189
  });
110
190
  }
@@ -1 +1 @@
1
- {"version":3,"file":"transports.js","sourceRoot":"","sources":["../src/transports.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transports.js","sourceRoot":"","sources":["../src/transports.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,12 +1,35 @@
1
1
  import type { WsBridge } from './resources/ws-bridge.js';
2
2
  import type { SubscriptionManager } from './resources/subscriptions.js';
3
+ export interface RegisteredAgent {
4
+ agentName: string;
5
+ agentToken: string;
6
+ }
7
+ /** Saved context for a single workspace membership. */
8
+ export interface WorkspaceContext {
9
+ workspaceKey: string;
10
+ agentToken: string;
11
+ agentName: string;
12
+ /** Registered agent tokens for this workspace, keyed by agent name. */
13
+ agents: Map<string, RegisteredAgent>;
14
+ /** Canonical workspace name from the Relaycast API. */
15
+ workspaceName?: string;
16
+ /** Optional user-saved label for switching. */
17
+ workspaceLabel?: string;
18
+ wsBridge: WsBridge | null;
19
+ subscriptions: SubscriptionManager | null;
20
+ wsInitAttempted: boolean;
21
+ }
3
22
  export interface SessionState {
4
23
  workspaceKey: string | null;
5
24
  agentToken: string | null;
6
25
  agentName: string | null;
26
+ /** Registered agent tokens for the active workspace, keyed by agent name. */
27
+ agents: Map<string, RegisteredAgent>;
7
28
  wsBridge: WsBridge | null;
8
29
  subscriptions: SubscriptionManager | null;
9
30
  wsInitAttempted: boolean;
31
+ /** Map of workspace key → saved context for joined workspaces. */
32
+ workspaces: Map<string, WorkspaceContext>;
10
33
  }
11
34
  export interface InitialSessionOptions {
12
35
  workspaceKey?: string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC1C,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,oBAAoB,CAClC,qBAAqB,GAAE,MAAM,GAAG,IAAI,GAAG,qBAA4B,GAClE,YAAY,CAcd"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,uDAAuD;AACvD,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACrC,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC1C,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,6EAA6E;IAC7E,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACrC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC1C,eAAe,EAAE,OAAO,CAAC;IACzB,kEAAkE;IAClE,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,oBAAoB,CAClC,qBAAqB,GAAE,MAAM,GAAG,IAAI,GAAG,qBAA4B,GAClE,YAAY,CAmBd"}
package/dist/types.js CHANGED
@@ -6,9 +6,13 @@ export function createInitialSession(workspaceKeyOrOptions = null) {
6
6
  workspaceKey: opts.workspaceKey ?? null,
7
7
  agentToken: opts.agentToken ?? null,
8
8
  agentName: opts.agentName ?? null,
9
+ agents: opts.agentName && opts.agentToken
10
+ ? new Map([[opts.agentName, { agentName: opts.agentName, agentToken: opts.agentToken }]])
11
+ : new Map(),
9
12
  wsBridge: null,
10
13
  subscriptions: null,
11
14
  wsInitAttempted: false,
15
+ workspaces: new Map(),
12
16
  };
13
17
  }
14
18
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAkBA,MAAM,UAAU,oBAAoB,CAClC,wBAA+D,IAAI;IAEnE,MAAM,IAAI,GACR,OAAO,qBAAqB,KAAK,QAAQ,IAAI,qBAAqB,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,qBAAqB,CAAC,IAAI,cAAc,IAAI,qBAAqB;QAC7J,CAAC,CAAC,qBAAqB;QACvB,CAAC,CAAC,EAAE,YAAY,EAAE,qBAAsC,EAAE,CAAC;IAE/D,OAAO;QACL,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI;QACvC,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI;QACnC,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI;QACjC,QAAQ,EAAE,IAAI;QACd,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,KAAK;KACvB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA2CA,MAAM,UAAU,oBAAoB,CAClC,wBAA+D,IAAI;IAEnE,MAAM,IAAI,GACR,OAAO,qBAAqB,KAAK,QAAQ,IAAI,qBAAqB,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,qBAAqB,CAAC,IAAI,cAAc,IAAI,qBAAqB;QAC7J,CAAC,CAAC,qBAAqB;QACvB,CAAC,CAAC,EAAE,YAAY,EAAE,qBAAsC,EAAE,CAAC;IAE/D,OAAO;QACL,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI;QACvC,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI;QACnC,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI;QACjC,MAAM,EACJ,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU;YAC/B,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YACzF,CAAC,CAAC,IAAI,GAAG,EAAE;QACf,QAAQ,EAAE,IAAI;QACd,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,KAAK;QACtB,UAAU,EAAE,IAAI,GAAG,EAAE;KACtB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { z } from 'zod';
2
+ import type { SessionState, WorkspaceContext } from './types.js';
3
+ export type WorkspaceRouting = {
4
+ workspace_id?: string;
5
+ workspace_alias?: string;
6
+ };
7
+ export type AgentRouting = WorkspaceRouting & {
8
+ as?: string;
9
+ };
10
+ /**
11
+ * Configuration for a single workspace provided via RELAY_WORKSPACES_JSON.
12
+ */
13
+ export interface McpWorkspaceConfig {
14
+ workspace_id: string;
15
+ workspace_alias?: string;
16
+ workspace_name?: string;
17
+ api_key: string;
18
+ agent_token?: string;
19
+ agent_name?: string;
20
+ }
21
+ /**
22
+ * Parse RELAY_WORKSPACES_JSON env var into an array of workspace configs.
23
+ * Returns an empty array if the env var is not set or empty.
24
+ */
25
+ export declare function parseWorkspaceEnv(raw?: string): McpWorkspaceConfig[];
26
+ /**
27
+ * Validate an array of workspace config objects.
28
+ * Ensures each entry has the required fields.
29
+ */
30
+ export declare function validateWorkspaceConfigs(configs: unknown[]): McpWorkspaceConfig[];
31
+ /**
32
+ * Resolve which workspace ID should be the default/active workspace.
33
+ * Falls back to the first workspace in the list.
34
+ */
35
+ export declare function resolveDefaultWorkspaceId(configs: McpWorkspaceConfig[], defaultWorkspace?: string): string | undefined;
36
+ /**
37
+ * Optional workspace routing params added to messaging tools.
38
+ * When provided, the tool targets a specific workspace instead of the active one.
39
+ */
40
+ export declare const workspaceRoutingInputShape: {
41
+ workspace_id: z.ZodOptional<z.ZodString>;
42
+ workspace_alias: z.ZodOptional<z.ZodString>;
43
+ };
44
+ /**
45
+ * Optional agent identity override for tools whose behavior depends on the
46
+ * authenticated agent.
47
+ */
48
+ export declare const identityOverrideInputShape: {
49
+ as: z.ZodOptional<z.ZodString>;
50
+ };
51
+ /**
52
+ * Extract optional workspace and identity routing from loose request params.
53
+ * Throws on invalid types so resource requests match tool-layer validation.
54
+ */
55
+ export declare function parseAgentRouting(raw: unknown): AgentRouting | undefined;
56
+ /**
57
+ * Extract workspace routing info from tool arguments.
58
+ * Returns the workspace_id or workspace_alias if provided, or undefined.
59
+ */
60
+ export declare function workspaceRefFromArgs(args: WorkspaceRouting): WorkspaceRouting | undefined;
61
+ /**
62
+ * Find a WorkspaceContext in the session by workspace_id or workspace_alias.
63
+ * Falls back to matching a saved workspace label or canonical workspace name.
64
+ */
65
+ export declare function findWorkspaceContext(session: SessionState, ref: {
66
+ workspace_id?: string;
67
+ workspace_alias?: string;
68
+ }, configs?: McpWorkspaceConfig[]): WorkspaceContext | undefined;
69
+ //# sourceMappingURL=workspaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../src/workspaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG;IAC5C,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAWD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAcpE;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,kBAAkB,EAAE,CAYjF;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,kBAAkB,EAAE,EAC7B,gBAAgB,CAAC,EAAE,MAAM,GACxB,MAAM,GAAG,SAAS,CASpB;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;CAOtC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;CAItC,CAAC;AAOF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CASxE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,gBAAgB,GACrB,gBAAgB,GAAG,SAAS,CAQ9B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,YAAY,EACrB,GAAG,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,EACxD,OAAO,CAAC,EAAE,kBAAkB,EAAE,GAC7B,gBAAgB,GAAG,SAAS,CA0B9B"}
@@ -0,0 +1,134 @@
1
+ import { z } from 'zod';
2
+ const mcpWorkspaceConfigSchema = z.object({
3
+ workspace_id: z.string({ error: 'is required and must be a string' }),
4
+ workspace_alias: z.string().optional(),
5
+ workspace_name: z.string().optional(),
6
+ api_key: z.string({ error: 'is required and must be a string' }),
7
+ agent_token: z.string().optional(),
8
+ agent_name: z.string().optional(),
9
+ });
10
+ /**
11
+ * Parse RELAY_WORKSPACES_JSON env var into an array of workspace configs.
12
+ * Returns an empty array if the env var is not set or empty.
13
+ */
14
+ export function parseWorkspaceEnv(raw) {
15
+ if (!raw || !raw.trim())
16
+ return [];
17
+ try {
18
+ const parsed = JSON.parse(raw);
19
+ if (!Array.isArray(parsed)) {
20
+ throw new Error('RELAY_WORKSPACES_JSON must be a JSON array');
21
+ }
22
+ return validateWorkspaceConfigs(parsed);
23
+ }
24
+ catch (err) {
25
+ if (err instanceof SyntaxError) {
26
+ throw new Error(`RELAY_WORKSPACES_JSON is not valid JSON: ${err.message}`);
27
+ }
28
+ throw err;
29
+ }
30
+ }
31
+ /**
32
+ * Validate an array of workspace config objects.
33
+ * Ensures each entry has the required fields.
34
+ */
35
+ export function validateWorkspaceConfigs(configs) {
36
+ return configs.map((cfg, i) => {
37
+ const result = mcpWorkspaceConfigSchema.safeParse(cfg);
38
+ if (!result.success) {
39
+ const issue = result.error.issues[0];
40
+ if (!issue.path.length) {
41
+ throw new Error(`RELAY_WORKSPACES_JSON[${i}] must be an object`);
42
+ }
43
+ throw new Error(`RELAY_WORKSPACES_JSON[${i}].${issue.path.join('.')} ${issue.message}`);
44
+ }
45
+ return result.data;
46
+ });
47
+ }
48
+ /**
49
+ * Resolve which workspace ID should be the default/active workspace.
50
+ * Falls back to the first workspace in the list.
51
+ */
52
+ export function resolveDefaultWorkspaceId(configs, defaultWorkspace) {
53
+ if (!configs.length)
54
+ return undefined;
55
+ if (defaultWorkspace) {
56
+ const match = configs.find(c => c.workspace_id === defaultWorkspace || c.workspace_alias === defaultWorkspace);
57
+ if (match)
58
+ return match.workspace_id;
59
+ }
60
+ return configs[0].workspace_id;
61
+ }
62
+ /**
63
+ * Optional workspace routing params added to messaging tools.
64
+ * When provided, the tool targets a specific workspace instead of the active one.
65
+ */
66
+ export const workspaceRoutingInputShape = {
67
+ workspace_id: z.string().optional().describe('Target a specific workspace by its workspace_id (from RELAY_WORKSPACES_JSON). If omitted, uses the active workspace.'),
68
+ workspace_alias: z.string().optional().describe('Target a specific workspace by its alias (from RELAY_WORKSPACES_JSON). If omitted, uses the active workspace.'),
69
+ };
70
+ /**
71
+ * Optional agent identity override for tools whose behavior depends on the
72
+ * authenticated agent.
73
+ */
74
+ export const identityOverrideInputShape = {
75
+ as: z.string().optional().describe('Act as a specific registered agent name in the target workspace. If omitted, uses the active agent identity.'),
76
+ };
77
+ const agentRoutingSchema = z.object({
78
+ ...workspaceRoutingInputShape,
79
+ ...identityOverrideInputShape,
80
+ }).passthrough();
81
+ /**
82
+ * Extract optional workspace and identity routing from loose request params.
83
+ * Throws on invalid types so resource requests match tool-layer validation.
84
+ */
85
+ export function parseAgentRouting(raw) {
86
+ const parsed = agentRoutingSchema.parse(raw ?? {});
87
+ const { workspace_id, workspace_alias, as } = parsed;
88
+ if (!workspace_id && !workspace_alias && !as) {
89
+ return undefined;
90
+ }
91
+ return { workspace_id, workspace_alias, as };
92
+ }
93
+ /**
94
+ * Extract workspace routing info from tool arguments.
95
+ * Returns the workspace_id or workspace_alias if provided, or undefined.
96
+ */
97
+ export function workspaceRefFromArgs(args) {
98
+ if (args.workspace_id || args.workspace_alias) {
99
+ return {
100
+ workspace_id: args.workspace_id,
101
+ workspace_alias: args.workspace_alias,
102
+ };
103
+ }
104
+ return undefined;
105
+ }
106
+ /**
107
+ * Find a WorkspaceContext in the session by workspace_id or workspace_alias.
108
+ * Falls back to matching a saved workspace label or canonical workspace name.
109
+ */
110
+ export function findWorkspaceContext(session, ref, configs) {
111
+ // Try to find the matching config first to get the api_key
112
+ const config = configs?.find(c => {
113
+ if (ref.workspace_id && c.workspace_id === ref.workspace_id)
114
+ return true;
115
+ if (ref.workspace_alias && c.workspace_alias === ref.workspace_alias)
116
+ return true;
117
+ return false;
118
+ });
119
+ if (config) {
120
+ return session.workspaces.get(config.api_key);
121
+ }
122
+ // Fall back to matching by workspace_alias against saved workspace metadata.
123
+ if (ref.workspace_alias) {
124
+ const target = ref.workspace_alias.toLowerCase();
125
+ for (const ctx of session.workspaces.values()) {
126
+ if (ctx.workspaceLabel?.toLowerCase() === target
127
+ || ctx.workspaceName?.toLowerCase() === target) {
128
+ return ctx;
129
+ }
130
+ }
131
+ }
132
+ return undefined;
133
+ }
134
+ //# sourceMappingURL=workspaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../src/workspaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAwBxB,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,kCAAkC,EAAE,CAAC;IACrE,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,kCAAkC,EAAE,CAAC;IAChE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,4CAA4C,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAkB;IACzD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QAC5B,MAAM,MAAM,GAAG,wBAAwB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACrC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,qBAAqB,CAAC,CAAC;YACnE,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAA6B,EAC7B,gBAAyB;IAEzB,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACtC,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CACxB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,gBAAgB,IAAI,CAAC,CAAC,eAAe,KAAK,gBAAgB,CACnF,CAAC;QACF,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC,YAAY,CAAC;IACvC,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAC1C,sHAAsH,CACvH;IACD,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAC7C,+GAA+G,CAChH;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAChC,8GAA8G,CAC/G;CACF,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,GAAG,0BAA0B;IAC7B,GAAG,0BAA0B;CAC9B,CAAC,CAAC,WAAW,EAAE,CAAC;AAEjB;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC;IAErD,IAAI,CAAC,YAAY,IAAI,CAAC,eAAe,IAAI,CAAC,EAAE,EAAE,CAAC;QAC7C,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAsB;IAEtB,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;QAC9C,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,eAAe,EAAE,IAAI,CAAC,eAAe;SACtC,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAqB,EACrB,GAAwD,EACxD,OAA8B;IAE9B,2DAA2D;IAC3D,MAAM,MAAM,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE;QAC/B,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,CAAC,YAAY,KAAK,GAAG,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC;QACzE,IAAI,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,eAAe,KAAK,GAAG,CAAC,eAAe;YAAE,OAAO,IAAI,CAAC;QAClF,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,6EAA6E;IAC7E,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,GAAG,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC;QACjD,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,IACE,GAAG,CAAC,cAAc,EAAE,WAAW,EAAE,KAAK,MAAM;mBACzC,GAAG,CAAC,aAAa,EAAE,WAAW,EAAE,KAAK,MAAM,EAC9C,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relaycast/mcp",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -13,8 +13,8 @@
13
13
  "lint": "eslint src/"
14
14
  },
15
15
  "dependencies": {
16
- "@relaycast/sdk": "0.5.1",
17
- "@relaycast/types": "0.5.1",
16
+ "@relaycast/sdk": "0.5.3",
17
+ "@relaycast/types": "0.5.3",
18
18
  "@modelcontextprotocol/sdk": "^1.26.0",
19
19
  "express": "^5.2.1",
20
20
  "zod": "^4.3.6"