@efectoapp/mcp-studio 0.1.0

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.
@@ -0,0 +1,273 @@
1
+ "use strict";
2
+ /**
3
+ * Studio Session Tools
4
+ *
5
+ * Manages the lifecycle of a Studio session. The MCP process holds
6
+ * the active session ID in memory so agents don't have to pass it around.
7
+ *
8
+ * - create_session: Create a new session, store internally, return URL
9
+ * - session_status: Check browser connection + pending calls
10
+ * - close_session: Close session, clear internal state
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.sessionTools = void 0;
14
+ exports.getActiveSessionId = getActiveSessionId;
15
+ exports.handleSessionTool = handleSessionTool;
16
+ // Base URL for Efecto API
17
+ const API_BASE = process.env.EFECTO_API_URL || 'https://efecto.app';
18
+ // ---------------------------------------------------------------------------
19
+ // Internal session state — held in-process
20
+ // ---------------------------------------------------------------------------
21
+ let currentSessionId = null;
22
+ /** Get the active session ID (used by studio tools) */
23
+ function getActiveSessionId() {
24
+ return currentSessionId;
25
+ }
26
+ // ---------------------------------------------------------------------------
27
+ // Tool Definitions
28
+ // ---------------------------------------------------------------------------
29
+ exports.sessionTools = [
30
+ {
31
+ name: 'create_session',
32
+ description: 'Create a new Studio session. Returns a URL the user should open in their browser. ' +
33
+ 'Once open, you can use any Studio design tool — they execute in real-time. ' +
34
+ 'Only one session is active at a time; creating a new session replaces the previous one.',
35
+ inputSchema: {
36
+ type: 'object',
37
+ properties: {
38
+ label: {
39
+ type: 'string',
40
+ description: 'Human-readable label for the session (e.g. "Landing page design")',
41
+ },
42
+ },
43
+ required: [],
44
+ },
45
+ },
46
+ {
47
+ name: 'session_status',
48
+ description: 'Check the status of the active Studio session — whether the browser is connected, ' +
49
+ 'pending calls, etc. If no session is active, returns an error.',
50
+ inputSchema: {
51
+ type: 'object',
52
+ properties: {
53
+ sessionId: {
54
+ type: 'string',
55
+ description: 'Optional session ID to check (defaults to active session)',
56
+ },
57
+ },
58
+ required: [],
59
+ },
60
+ },
61
+ {
62
+ name: 'close_session',
63
+ description: 'Close the active Studio session. Disconnects the browser and cleans up resources.',
64
+ inputSchema: {
65
+ type: 'object',
66
+ properties: {
67
+ sessionId: {
68
+ type: 'string',
69
+ description: 'Optional session ID to close (defaults to active session)',
70
+ },
71
+ },
72
+ required: [],
73
+ },
74
+ },
75
+ ];
76
+ // ---------------------------------------------------------------------------
77
+ // Handler
78
+ // ---------------------------------------------------------------------------
79
+ async function handleSessionTool(name, args) {
80
+ const params = args || {};
81
+ switch (name) {
82
+ // -----------------------------------------------------------------------
83
+ // create_session
84
+ // -----------------------------------------------------------------------
85
+ case 'create_session': {
86
+ const body = {};
87
+ if (typeof params.label === 'string') {
88
+ body.label = params.label;
89
+ }
90
+ try {
91
+ const response = await fetch(`${API_BASE}/api/v1/studio/sessions`, {
92
+ method: 'POST',
93
+ headers: { 'Content-Type': 'application/json' },
94
+ body: JSON.stringify(body),
95
+ });
96
+ if (!response.ok) {
97
+ const errorText = await response.text();
98
+ return {
99
+ content: [{
100
+ type: 'text',
101
+ text: JSON.stringify({
102
+ success: false,
103
+ error: `API error: ${response.status}`,
104
+ details: errorText,
105
+ }, null, 2),
106
+ }],
107
+ };
108
+ }
109
+ const data = await response.json();
110
+ // Store the session ID internally
111
+ currentSessionId = data.sessionId;
112
+ return {
113
+ content: [{
114
+ type: 'text',
115
+ text: JSON.stringify({
116
+ success: true,
117
+ sessionId: data.sessionId,
118
+ studioUrl: data.studioUrl,
119
+ expiresAt: data.expiresAt,
120
+ message: `Studio session created! Ask the user to open this URL in their browser:\n\n` +
121
+ ` ${data.studioUrl}\n\n` +
122
+ `Once the browser is connected, use any design tool directly — no session ID needed.`,
123
+ }, null, 2),
124
+ }],
125
+ };
126
+ }
127
+ catch (error) {
128
+ return {
129
+ content: [{
130
+ type: 'text',
131
+ text: JSON.stringify({
132
+ success: false,
133
+ error: 'Failed to create session',
134
+ details: error instanceof Error ? error.message : String(error),
135
+ }, null, 2),
136
+ }],
137
+ };
138
+ }
139
+ }
140
+ // -----------------------------------------------------------------------
141
+ // session_status
142
+ // -----------------------------------------------------------------------
143
+ case 'session_status': {
144
+ const sessionId = (typeof params.sessionId === 'string' && params.sessionId)
145
+ ? params.sessionId
146
+ : currentSessionId;
147
+ if (!sessionId) {
148
+ return {
149
+ content: [{
150
+ type: 'text',
151
+ text: JSON.stringify({
152
+ success: false,
153
+ error: 'No active session. Call create_session first.',
154
+ }, null, 2),
155
+ }],
156
+ };
157
+ }
158
+ try {
159
+ const response = await fetch(`${API_BASE}/api/v1/studio/sessions/${sessionId}`);
160
+ if (!response.ok) {
161
+ const errorText = await response.text();
162
+ return {
163
+ content: [{
164
+ type: 'text',
165
+ text: JSON.stringify({
166
+ success: false,
167
+ error: `API error: ${response.status}`,
168
+ details: errorText,
169
+ }, null, 2),
170
+ }],
171
+ };
172
+ }
173
+ const data = await response.json();
174
+ return {
175
+ content: [{
176
+ type: 'text',
177
+ text: JSON.stringify({
178
+ success: true,
179
+ sessionId: data.session.id,
180
+ browserConnected: data.session.browserConnected,
181
+ label: data.session.label,
182
+ pendingCalls: data.pendingCalls,
183
+ completedCalls: data.completedCalls,
184
+ expiresAt: new Date(data.session.expiresAt).toISOString(),
185
+ message: data.session.browserConnected
186
+ ? 'Browser is connected and ready. Use any design tool directly.'
187
+ : 'Browser is not connected. Ask the user to open the Studio URL.',
188
+ }, null, 2),
189
+ }],
190
+ };
191
+ }
192
+ catch (error) {
193
+ return {
194
+ content: [{
195
+ type: 'text',
196
+ text: JSON.stringify({
197
+ success: false,
198
+ error: 'Failed to get session status',
199
+ details: error instanceof Error ? error.message : String(error),
200
+ }, null, 2),
201
+ }],
202
+ };
203
+ }
204
+ }
205
+ // -----------------------------------------------------------------------
206
+ // close_session
207
+ // -----------------------------------------------------------------------
208
+ case 'close_session': {
209
+ const sessionId = (typeof params.sessionId === 'string' && params.sessionId)
210
+ ? params.sessionId
211
+ : currentSessionId;
212
+ if (!sessionId) {
213
+ return {
214
+ content: [{
215
+ type: 'text',
216
+ text: JSON.stringify({
217
+ success: false,
218
+ error: 'No active session. Nothing to close.',
219
+ }, null, 2),
220
+ }],
221
+ };
222
+ }
223
+ try {
224
+ const response = await fetch(`${API_BASE}/api/v1/studio/sessions/${sessionId}`, {
225
+ method: 'DELETE',
226
+ });
227
+ if (!response.ok) {
228
+ const errorText = await response.text();
229
+ return {
230
+ content: [{
231
+ type: 'text',
232
+ text: JSON.stringify({
233
+ success: false,
234
+ error: `API error: ${response.status}`,
235
+ details: errorText,
236
+ }, null, 2),
237
+ }],
238
+ };
239
+ }
240
+ // Clear internal state
241
+ if (currentSessionId === sessionId) {
242
+ currentSessionId = null;
243
+ }
244
+ return {
245
+ content: [{
246
+ type: 'text',
247
+ text: JSON.stringify({
248
+ success: true,
249
+ message: 'Studio session closed successfully.',
250
+ }, null, 2),
251
+ }],
252
+ };
253
+ }
254
+ catch (error) {
255
+ return {
256
+ content: [{
257
+ type: 'text',
258
+ text: JSON.stringify({
259
+ success: false,
260
+ error: 'Failed to close session',
261
+ details: error instanceof Error ? error.message : String(error),
262
+ }, null, 2),
263
+ }],
264
+ };
265
+ }
266
+ }
267
+ default:
268
+ return {
269
+ content: [{ type: 'text', text: `Unknown session tool: ${name}` }],
270
+ };
271
+ }
272
+ }
273
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/tools/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Studio Design Tools — First-Class MCP Tools
3
+ *
4
+ * Every Studio AI tool is exposed as its own MCP tool with a full schema.
5
+ * No more proxy pattern — agents call tools directly.
6
+ *
7
+ * The active session ID is auto-resolved from the session module.
8
+ * Each tool also accepts an optional `sessionId` override for multi-session use.
9
+ */
10
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
11
+ export declare const studioTools: Tool[];
12
+ export declare function handleStudioTool(name: string, args: Record<string, unknown> | undefined): Promise<{
13
+ content: Array<{
14
+ type: string;
15
+ text: string;
16
+ }>;
17
+ }>;
18
+ //# sourceMappingURL=studio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"studio.d.ts","sourceRoot":"","sources":["../../src/tools/studio.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAA;AAuH9D,eAAO,MAAM,WAAW,EAAE,IAAI,EAgf7B,CAAA;AAuDD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GACxC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAgB7D"}