@relaycast/mcp 0.5.1 → 0.5.2

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 +123 -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,131 @@
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
+ const timeout = new Promise((_, reject) => setTimeout(() => reject(new Error(`Bootstrap timed out after ${timeoutMs}ms`)), timeoutMs));
62
+ return await Promise.race([doBootstrap(), timeout]);
33
63
  }
34
- const registered = await relay.agents.registerOrRotate({
35
- name: options.agentName,
36
- type: options.agentType,
64
+ catch (err) {
65
+ console.error(`[bootstrap] Failed to bootstrap workspace ${ws.workspace_id}: ${err instanceof Error ? err.message : String(err)}`);
66
+ // Still return the workspace config even if bootstrap failed,
67
+ // so it can be retried later
68
+ return ws;
69
+ }
70
+ }
71
+ /**
72
+ * Bootstrap workspaces by verifying/refreshing tokens and joining each
73
+ * workspace into the MCP server's session via setSession + saveWorkspaceContext.
74
+ *
75
+ * All workspaces are bootstrapped concurrently with individual timeouts.
76
+ */
77
+ async function bootstrapWorkspaces(workspaces, baseUrl) {
78
+ const results = await Promise.allSettled(workspaces.map(ws => bootstrapOneWorkspace(ws, baseUrl)));
79
+ return results.map((result, i) => {
80
+ if (result.status === 'fulfilled')
81
+ return result.value;
82
+ console.error(`[bootstrap] Workspace ${workspaces[i].workspace_id} rejected: ${result.reason}`);
83
+ return workspaces[i];
37
84
  });
38
- return {
39
- ...options,
40
- agentToken: registered.token,
41
- agentName: registered.name ?? options.agentName,
42
- };
43
85
  }
44
86
  /**
45
87
  * Start MCP server with stdio transport (single agent).
46
88
  * Reads from stdin, writes to stdout.
47
89
  */
48
90
  export async function startStdio(options) {
49
- const bootstrappedOptions = await resolveStdioBootstrapOptions(options);
50
- const mcpServer = createRelayMcpServer({
51
- ...bootstrappedOptions,
52
- telemetryTransport: "stdio",
53
- });
91
+ let effectiveOptions = { ...options, telemetryTransport: 'stdio' };
92
+ const hasAgentToken = Boolean(options.agentToken);
93
+ const hasWorkspaces = Boolean(options.workspaces?.length);
94
+ if (hasWorkspaces) {
95
+ if (hasAgentToken) {
96
+ // When agentToken is pre-provided (broker-spawned), skip bootstrap entirely —
97
+ // the token is already valid. Use workspace configs as-is for routing context.
98
+ const withNames = options.workspaces.map(ws => ({
99
+ ...ws,
100
+ agent_name: ws.agent_name ?? ws.workspace_alias ?? ws.workspace_id,
101
+ }));
102
+ effectiveOptions = { ...effectiveOptions, workspaces: withNames };
103
+ // Promote default workspace credentials so routing resolves correctly
104
+ const defaultWsId = resolveDefaultWorkspaceId(withNames, options.defaultWorkspace);
105
+ const defaultWs = withNames.find(w => w.workspace_id === defaultWsId);
106
+ if (defaultWs) {
107
+ effectiveOptions.apiKey = effectiveOptions.apiKey ?? defaultWs.api_key;
108
+ effectiveOptions.agentName = effectiveOptions.agentName ?? defaultWs.agent_name;
109
+ }
110
+ }
111
+ else {
112
+ // CLI user with RELAY_WORKSPACES_JSON — bootstrap is needed but now
113
+ // runs all workspaces concurrently (with per-workspace timeouts).
114
+ const bootstrapped = await bootstrapWorkspaces(options.workspaces, options.baseUrl);
115
+ effectiveOptions = { ...effectiveOptions, workspaces: bootstrapped };
116
+ // Set the default workspace's api key/token/name as the primary session
117
+ const defaultWsId = resolveDefaultWorkspaceId(bootstrapped, options.defaultWorkspace);
118
+ const defaultWs = bootstrapped.find(w => w.workspace_id === defaultWsId && w.agent_token);
119
+ if (defaultWs) {
120
+ effectiveOptions.apiKey = effectiveOptions.apiKey ?? defaultWs.api_key;
121
+ effectiveOptions.agentToken = effectiveOptions.agentToken ?? defaultWs.agent_token;
122
+ effectiveOptions.agentName = effectiveOptions.agentName ?? defaultWs.agent_name;
123
+ }
124
+ }
125
+ }
126
+ // createRelayMcpServer populates session.workspaces from
127
+ // effectiveOptions.workspaces internally — no need to reach into internals.
128
+ const mcpServer = createRelayMcpServer(effectiveOptions);
54
129
  const transport = new StdioServerTransport();
55
130
  await mcpServer.connect(transport);
56
131
  }
@@ -69,7 +144,7 @@ export function createHttpHandler(baseOptions, lifecycle) {
69
144
  hasSession: (sessionId) => sessions.has(sessionId),
70
145
  handleRequest: async (req, res) => {
71
146
  // Check for existing session
72
- const sessionId = req.headers["mcp-session-id"];
147
+ const sessionId = req.headers['mcp-session-id'];
73
148
  if (sessionId && sessions.has(sessionId)) {
74
149
  const session = sessions.get(sessionId);
75
150
  await session.transport.handleRequest(req, res);
@@ -77,8 +152,8 @@ export function createHttpHandler(baseOptions, lifecycle) {
77
152
  }
78
153
  // New session — create fresh MCP server + transport + telemetry
79
154
  const telemetry = createMcpTelemetry(MCP_VERSION, {
80
- originSurface: "mcp",
81
- originClient: "@relaycast/mcp",
155
+ originSurface: 'mcp',
156
+ originClient: '@relaycast/mcp',
82
157
  originVersion: MCP_VERSION,
83
158
  });
84
159
  const transport = new StreamableHTTPServerTransport({
@@ -86,7 +161,7 @@ export function createHttpHandler(baseOptions, lifecycle) {
86
161
  });
87
162
  const mcpServer = createRelayMcpServer({
88
163
  ...baseOptions,
89
- telemetryTransport: "http",
164
+ telemetryTransport: 'http',
90
165
  telemetry,
91
166
  });
92
167
  transport.onclose = () => {
@@ -102,9 +177,9 @@ export function createHttpHandler(baseOptions, lifecycle) {
102
177
  if (transport.sessionId && !sessions.has(transport.sessionId)) {
103
178
  sessions.set(transport.sessionId, { transport });
104
179
  lifecycle?.onCreated?.(transport.sessionId);
105
- telemetry.capture("relaycast_mcp_http_session_started", {
106
- source_surface: "mcp",
107
- transport: "http",
180
+ telemetry.capture('relaycast_mcp_http_session_started', {
181
+ source_surface: 'mcp',
182
+ transport: 'http',
108
183
  mcp_transport_session_id: transport.sessionId,
109
184
  });
110
185
  }
@@ -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":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relaycast/mcp",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
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.2",
17
+ "@relaycast/types": "0.5.2",
18
18
  "@modelcontextprotocol/sdk": "^1.26.0",
19
19
  "express": "^5.2.1",
20
20
  "zod": "^4.3.6"