marble-headed-mcp 0.1.38 → 0.1.39
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/dist/index.js +66 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,6 +7,11 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
|
7
7
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
8
8
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
9
9
|
const DEFAULT_BASE_URL = 'http://localhost:4000';
|
|
10
|
+
const ENVIRONMENT_BASE_URLS = {
|
|
11
|
+
localhost: 'http://localhost:3000',
|
|
12
|
+
dev: 'https://dev.withmarble.ai',
|
|
13
|
+
production: 'https://withmarble.ai',
|
|
14
|
+
};
|
|
10
15
|
const WEBAPP_LOG_PATH = '/tmp/webapp';
|
|
11
16
|
const DEFAULT_DEV_CONTAINER_PATH = '/Users/akilanbabu/code/marble-container';
|
|
12
17
|
const VSCODE_REPO_PATH = '/Users/akilanbabu/code/vscode-source-marble/code-server-7/lib/vscode';
|
|
@@ -15,6 +20,7 @@ const DEFAULT_CODEX_LOGGER_PATH = path.join(process.env.HOME || '/Users/akilanba
|
|
|
15
20
|
const CODEX_LOGGER_PATH_ENV = 'CODEX_LOGGER_PATH';
|
|
16
21
|
const CODEX_LOG_PREFIX = 'codex-run-';
|
|
17
22
|
const execFileAsync = promisify(execFile);
|
|
23
|
+
let selectedEnvironment = null;
|
|
18
24
|
function parseCodexJsonOutput(output) {
|
|
19
25
|
const result = {};
|
|
20
26
|
if (!output)
|
|
@@ -50,6 +56,15 @@ function parseCodexJsonOutput(output) {
|
|
|
50
56
|
function normalizeBaseUrl(input) {
|
|
51
57
|
return input.replace(/\/+$/, '');
|
|
52
58
|
}
|
|
59
|
+
function parseEnvironment(input) {
|
|
60
|
+
if (typeof input !== 'string')
|
|
61
|
+
return null;
|
|
62
|
+
const normalized = input.trim().toLowerCase();
|
|
63
|
+
if (normalized === 'localhost' || normalized === 'dev' || normalized === 'production') {
|
|
64
|
+
return normalized;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
53
68
|
function shellQuote(value) {
|
|
54
69
|
return `'${value.replace(/'/g, `'\"'\"'`)}'`;
|
|
55
70
|
}
|
|
@@ -111,6 +126,9 @@ async function readCodexThreadIdFromLog(filePath) {
|
|
|
111
126
|
}
|
|
112
127
|
}
|
|
113
128
|
function resolveRawBaseUrl() {
|
|
129
|
+
if (selectedEnvironment) {
|
|
130
|
+
return normalizeBaseUrl(ENVIRONMENT_BASE_URLS[selectedEnvironment]);
|
|
131
|
+
}
|
|
114
132
|
const base = process.env.HEADED_SERVER_BASE_URL || DEFAULT_BASE_URL;
|
|
115
133
|
return normalizeBaseUrl(base);
|
|
116
134
|
}
|
|
@@ -398,6 +416,22 @@ async function saveImageFromUrl({ url, filename }) {
|
|
|
398
416
|
return { ok: true, path: targetPath, bytes: buffer.length };
|
|
399
417
|
}
|
|
400
418
|
const TOOLS = [
|
|
419
|
+
{
|
|
420
|
+
name: 'set_environment',
|
|
421
|
+
description: 'Set the base URL for HTTP-backed actions. localhost -> http://localhost:3000, dev -> https://dev.withmarble.ai, production -> https://withmarble.ai.',
|
|
422
|
+
inputSchema: {
|
|
423
|
+
type: 'object',
|
|
424
|
+
properties: {
|
|
425
|
+
environment: {
|
|
426
|
+
type: 'string',
|
|
427
|
+
enum: ['localhost', 'dev', 'production'],
|
|
428
|
+
description: 'Environment to target.',
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
required: ['environment'],
|
|
432
|
+
additionalProperties: false,
|
|
433
|
+
},
|
|
434
|
+
},
|
|
401
435
|
{
|
|
402
436
|
name: 'headed_start_session',
|
|
403
437
|
description: 'Start a headed browser session (if email or password are not provided, they default to akilan@withmarble.ai and marbledebug123, respectively). Remember to call `headed_end_session` when finished to avoid leaving sessions open.',
|
|
@@ -716,6 +750,38 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
716
750
|
const { name, arguments: args } = request.params;
|
|
717
751
|
try {
|
|
718
752
|
switch (name) {
|
|
753
|
+
case 'set_environment': {
|
|
754
|
+
const environment = parseEnvironment(args?.environment);
|
|
755
|
+
if (!environment) {
|
|
756
|
+
return {
|
|
757
|
+
content: [
|
|
758
|
+
{
|
|
759
|
+
type: 'text',
|
|
760
|
+
text: JSON.stringify({
|
|
761
|
+
ok: false,
|
|
762
|
+
error: 'environment must be one of: localhost, dev, production.',
|
|
763
|
+
}, null, 2),
|
|
764
|
+
},
|
|
765
|
+
],
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
selectedEnvironment = environment;
|
|
769
|
+
const appBaseUrl = resolveAppBaseUrl();
|
|
770
|
+
return {
|
|
771
|
+
content: [
|
|
772
|
+
{
|
|
773
|
+
type: 'text',
|
|
774
|
+
text: JSON.stringify({
|
|
775
|
+
ok: true,
|
|
776
|
+
environment,
|
|
777
|
+
appBaseUrl,
|
|
778
|
+
apiBaseUrl: `${appBaseUrl}/api`,
|
|
779
|
+
headedApiBaseUrl: `${appBaseUrl}/api/headed`,
|
|
780
|
+
}, null, 2),
|
|
781
|
+
},
|
|
782
|
+
],
|
|
783
|
+
};
|
|
784
|
+
}
|
|
719
785
|
case 'headed_start_session': {
|
|
720
786
|
const result = await postHeadedJson('/start_session', args);
|
|
721
787
|
return { content: [{ type: 'text', text: JSON.stringify(result.json || { status: result.status, body: result.text }, null, 2) }] };
|