@symbo.ls/mcp-server 3.7.0 → 3.7.4
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/package.json +1 -1
- package/src/mcp-handler.js +200 -3
- package/src/worker-handler.js +3 -3
package/package.json
CHANGED
package/src/mcp-handler.js
CHANGED
|
@@ -212,6 +212,104 @@ const TOOLS = [
|
|
|
212
212
|
required: ['component_code'],
|
|
213
213
|
},
|
|
214
214
|
},
|
|
215
|
+
{
|
|
216
|
+
name: 'login',
|
|
217
|
+
description:
|
|
218
|
+
'Log in to the Symbols platform with email and password. Returns a JWT token for use with publish and push tools.',
|
|
219
|
+
inputSchema: {
|
|
220
|
+
type: 'object',
|
|
221
|
+
properties: {
|
|
222
|
+
email: {
|
|
223
|
+
type: 'string',
|
|
224
|
+
description: 'Symbols account email address',
|
|
225
|
+
},
|
|
226
|
+
password: {
|
|
227
|
+
type: 'string',
|
|
228
|
+
description: 'Symbols account password',
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
required: ['email', 'password'],
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: 'publish',
|
|
236
|
+
description:
|
|
237
|
+
'Publish a version of a Symbols project to the platform. Requires authentication via token or api_key.',
|
|
238
|
+
inputSchema: {
|
|
239
|
+
type: 'object',
|
|
240
|
+
properties: {
|
|
241
|
+
project: {
|
|
242
|
+
type: 'string',
|
|
243
|
+
description: 'Project ID (MongoDB ObjectId) or project key (pr_xxxx)',
|
|
244
|
+
},
|
|
245
|
+
token: {
|
|
246
|
+
type: 'string',
|
|
247
|
+
description: 'JWT access token from login or ~/.smblsrc',
|
|
248
|
+
},
|
|
249
|
+
api_key: {
|
|
250
|
+
type: 'string',
|
|
251
|
+
description:
|
|
252
|
+
'API key (sk_live_...) from project integration settings. Alternative to token.',
|
|
253
|
+
},
|
|
254
|
+
version: {
|
|
255
|
+
type: 'string',
|
|
256
|
+
description: 'Version string or version ID to publish. Leave empty for latest.',
|
|
257
|
+
default: '',
|
|
258
|
+
},
|
|
259
|
+
branch: {
|
|
260
|
+
type: 'string',
|
|
261
|
+
description: 'Branch to publish from',
|
|
262
|
+
default: 'main',
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
required: ['project'],
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
name: 'push',
|
|
270
|
+
description:
|
|
271
|
+
'Push/deploy a Symbols project to a specific environment. Requires authentication via token or api_key.',
|
|
272
|
+
inputSchema: {
|
|
273
|
+
type: 'object',
|
|
274
|
+
properties: {
|
|
275
|
+
project: {
|
|
276
|
+
type: 'string',
|
|
277
|
+
description: 'Project ID (MongoDB ObjectId) or project key (pr_xxxx)',
|
|
278
|
+
},
|
|
279
|
+
token: {
|
|
280
|
+
type: 'string',
|
|
281
|
+
description: 'JWT access token from login or ~/.smblsrc',
|
|
282
|
+
},
|
|
283
|
+
api_key: {
|
|
284
|
+
type: 'string',
|
|
285
|
+
description:
|
|
286
|
+
'API key (sk_live_...) from project integration settings. Alternative to token.',
|
|
287
|
+
},
|
|
288
|
+
environment: {
|
|
289
|
+
type: 'string',
|
|
290
|
+
description: 'Target environment key (e.g. "production", "staging", "dev")',
|
|
291
|
+
default: 'production',
|
|
292
|
+
},
|
|
293
|
+
mode: {
|
|
294
|
+
type: 'string',
|
|
295
|
+
description:
|
|
296
|
+
'Deploy mode — "latest" (newest from branch), "published" (current published version), "version" (specific version), or "branch" (track a branch)',
|
|
297
|
+
default: 'published',
|
|
298
|
+
},
|
|
299
|
+
version: {
|
|
300
|
+
type: 'string',
|
|
301
|
+
description: 'Required when mode is "version" — the version string or ID to deploy',
|
|
302
|
+
default: '',
|
|
303
|
+
},
|
|
304
|
+
branch: {
|
|
305
|
+
type: 'string',
|
|
306
|
+
description: 'Branch to deploy from when mode is "latest" or "branch"',
|
|
307
|
+
default: 'main',
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
required: ['project'],
|
|
311
|
+
},
|
|
312
|
+
},
|
|
215
313
|
{
|
|
216
314
|
name: 'detect_environment',
|
|
217
315
|
description:
|
|
@@ -259,7 +357,42 @@ const TOOLS = [
|
|
|
259
357
|
},
|
|
260
358
|
];
|
|
261
359
|
|
|
262
|
-
|
|
360
|
+
const API_BASE = 'https://api.symbols.app';
|
|
361
|
+
|
|
362
|
+
const AUTH_HELP = `To authenticate, provide one of:
|
|
363
|
+
- **token**: JWT from \`smbls login\` (stored in ~/.smblsrc) or env var SYMBOLS_TOKEN
|
|
364
|
+
- **api_key**: API key (sk_live_...) from your project's integration settings
|
|
365
|
+
|
|
366
|
+
To get a token:
|
|
367
|
+
1. Run \`smbls login\` in your terminal, or
|
|
368
|
+
2. Use the \`login\` tool with your email and password
|
|
369
|
+
|
|
370
|
+
Your project can be identified by either:
|
|
371
|
+
- **project**: MongoDB ObjectId (from project settings or symbols.json)
|
|
372
|
+
- **project**: Project key (pr_xxxx, found in symbols.json or project URL)`;
|
|
373
|
+
|
|
374
|
+
function authHeader(token, apiKey) {
|
|
375
|
+
if (apiKey) return { 'Authorization': `ApiKey ${apiKey}`, 'Content-Type': 'application/json' };
|
|
376
|
+
if (token) return { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' };
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async function apiRequest(method, path, { token, api_key, body } = {}) {
|
|
381
|
+
const headers = authHeader(token, api_key);
|
|
382
|
+
if (!headers) return { success: false, error: 'No credentials provided', message: AUTH_HELP };
|
|
383
|
+
const resp = await fetch(`${API_BASE}${path}`, {
|
|
384
|
+
method,
|
|
385
|
+
headers,
|
|
386
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
387
|
+
});
|
|
388
|
+
try {
|
|
389
|
+
return await resp.json();
|
|
390
|
+
} catch {
|
|
391
|
+
return { success: false, error: `HTTP ${resp.status}`, message: await resp.text() };
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
async function callTool(name, args = {}) {
|
|
263
396
|
if (name === 'get_project_rules') {
|
|
264
397
|
return readSkill('RULES.md');
|
|
265
398
|
}
|
|
@@ -376,6 +509,70 @@ function callTool(name, args = {}) {
|
|
|
376
509
|
return output;
|
|
377
510
|
}
|
|
378
511
|
|
|
512
|
+
if (name === 'login') {
|
|
513
|
+
const { email, password } = args;
|
|
514
|
+
if (!email || !password) return 'Error: email and password are required.';
|
|
515
|
+
const resp = await fetch(`${API_BASE}/core/auth/login`, {
|
|
516
|
+
method: 'POST',
|
|
517
|
+
headers: { 'Content-Type': 'application/json' },
|
|
518
|
+
body: JSON.stringify({ email, password }),
|
|
519
|
+
});
|
|
520
|
+
let result;
|
|
521
|
+
try {
|
|
522
|
+
result = await resp.json();
|
|
523
|
+
} catch {
|
|
524
|
+
return `Login failed: HTTP ${resp.status}`;
|
|
525
|
+
}
|
|
526
|
+
if (result.success) {
|
|
527
|
+
const data = result.data || {};
|
|
528
|
+
const tokens = data.tokens || {};
|
|
529
|
+
const user = data.user || {};
|
|
530
|
+
return `Logged in as ${user.name || user.email || 'unknown'}.\nToken: ${tokens.accessToken || ''}\nExpires: ${(tokens.accessTokenExp || {}).expiresAt || 'unknown'}\n\nUse this token with the \`publish\` and \`push\` tools.`;
|
|
531
|
+
}
|
|
532
|
+
return `Login failed: ${result.error || result.message || 'Unknown error'}`;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (name === 'publish') {
|
|
536
|
+
const { project, token, api_key, version, branch = 'main' } = args;
|
|
537
|
+
if (!project) return 'Error: project (ID or key) is required.';
|
|
538
|
+
if (!token && !api_key) return `Authentication required.\n\n${AUTH_HELP}`;
|
|
539
|
+
const body = { branch };
|
|
540
|
+
if (version) body.version = version;
|
|
541
|
+
const result = await apiRequest('POST', `/${project}/publish`, { token, api_key, body });
|
|
542
|
+
if (result.success) {
|
|
543
|
+
const data = result.data || {};
|
|
544
|
+
return `Published successfully.\nVersion: ${data.value || data.id || 'unknown'}`;
|
|
545
|
+
}
|
|
546
|
+
return `Publish failed: ${result.error || 'Unknown error'}\n${result.message || ''}`;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
if (name === 'push') {
|
|
550
|
+
const {
|
|
551
|
+
project,
|
|
552
|
+
token,
|
|
553
|
+
api_key,
|
|
554
|
+
environment = 'production',
|
|
555
|
+
mode = 'published',
|
|
556
|
+
version,
|
|
557
|
+
branch = 'main',
|
|
558
|
+
} = args;
|
|
559
|
+
if (!project) return 'Error: project (ID or key) is required.';
|
|
560
|
+
if (!token && !api_key) return `Authentication required.\n\n${AUTH_HELP}`;
|
|
561
|
+
const body = { mode, branch };
|
|
562
|
+
if (version) body.version = version;
|
|
563
|
+
const result = await apiRequest('POST', `/${project}/environments/${environment}/publish`, {
|
|
564
|
+
token,
|
|
565
|
+
api_key,
|
|
566
|
+
body,
|
|
567
|
+
});
|
|
568
|
+
if (result.success) {
|
|
569
|
+
const data = result.data || {};
|
|
570
|
+
const config = data.config || {};
|
|
571
|
+
return `Pushed to ${data.key || environment} successfully.\nMode: ${config.mode || mode}\nVersion: ${config.version || 'latest'}\nBranch: ${config.branch || branch}`;
|
|
572
|
+
}
|
|
573
|
+
return `Push failed: ${result.error || 'Unknown error'}\n${result.message || ''}`;
|
|
574
|
+
}
|
|
575
|
+
|
|
379
576
|
if (name === 'detect_environment') {
|
|
380
577
|
const {
|
|
381
578
|
has_symbols_json,
|
|
@@ -590,7 +787,7 @@ const PROMPTS = [
|
|
|
590
787
|
|
|
591
788
|
const SERVER_INFO = { name: 'Symbols MCP', version: '1.1.1' };
|
|
592
789
|
|
|
593
|
-
export function handleJsonRpc(req) {
|
|
790
|
+
export async function handleJsonRpc(req) {
|
|
594
791
|
const { method, params, id } = req;
|
|
595
792
|
|
|
596
793
|
if (method === 'initialize') {
|
|
@@ -615,7 +812,7 @@ export function handleJsonRpc(req) {
|
|
|
615
812
|
if (method === 'tools/call') {
|
|
616
813
|
const { name, arguments: args = {} } = params || {};
|
|
617
814
|
try {
|
|
618
|
-
const text = callTool(name, args);
|
|
815
|
+
const text = await callTool(name, args);
|
|
619
816
|
return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text }] } };
|
|
620
817
|
} catch (e) {
|
|
621
818
|
return {
|
package/src/worker-handler.js
CHANGED
|
@@ -66,14 +66,14 @@ function isNotificationOrResponse(msg) {
|
|
|
66
66
|
return false;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
function handleMcpPost(request, body) {
|
|
69
|
+
async function handleMcpPost(request, body) {
|
|
70
70
|
// Notifications and responses get 202 Accepted
|
|
71
71
|
if (isNotificationOrResponse(body)) {
|
|
72
72
|
return new Response(null, { status: 202, headers: CORS_HEADERS });
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
// Handle JSON-RPC request
|
|
76
|
-
const result = handleJsonRpc(body);
|
|
76
|
+
const result = await handleJsonRpc(body);
|
|
77
77
|
if (result === null) {
|
|
78
78
|
return new Response(null, { status: 202, headers: CORS_HEADERS });
|
|
79
79
|
}
|
|
@@ -166,7 +166,7 @@ export async function handleRequest(request) {
|
|
|
166
166
|
return json({ error: 'Invalid JSON body' }, 400);
|
|
167
167
|
}
|
|
168
168
|
try {
|
|
169
|
-
const result = callTool(toolName, args);
|
|
169
|
+
const result = await callTool(toolName, args);
|
|
170
170
|
return json({ content: [{ type: 'text', text: result }] });
|
|
171
171
|
} catch (e) {
|
|
172
172
|
return json({ error: e.message }, 404);
|