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.
Files changed (2) hide show
  1. package/dist/index.js +66 -0
  2. 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) }] };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marble-headed-mcp",
3
- "version": "0.1.38",
3
+ "version": "0.1.39",
4
4
  "description": "MCP server for Marble headed automation endpoints",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",