marble-headed-mcp 0.1.39 → 0.1.41
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 +50 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { promisify } from 'util';
|
|
|
6
6
|
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
|
-
const DEFAULT_BASE_URL = 'http://localhost:
|
|
9
|
+
const DEFAULT_BASE_URL = 'http://localhost:3000';
|
|
10
10
|
const ENVIRONMENT_BASE_URLS = {
|
|
11
11
|
localhost: 'http://localhost:3000',
|
|
12
12
|
dev: 'https://dev.withmarble.ai',
|
|
@@ -125,22 +125,28 @@ async function readCodexThreadIdFromLog(filePath) {
|
|
|
125
125
|
return null;
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
function
|
|
129
|
-
if (selectedEnvironment) {
|
|
130
|
-
return normalizeBaseUrl(ENVIRONMENT_BASE_URLS[selectedEnvironment]);
|
|
131
|
-
}
|
|
128
|
+
function resolveHeadedServerRawBaseUrl() {
|
|
132
129
|
const base = process.env.HEADED_SERVER_BASE_URL || DEFAULT_BASE_URL;
|
|
133
130
|
return normalizeBaseUrl(base);
|
|
134
131
|
}
|
|
135
|
-
function
|
|
136
|
-
const raw =
|
|
132
|
+
function resolveHeadedServerAppBaseUrl() {
|
|
133
|
+
const raw = resolveHeadedServerRawBaseUrl();
|
|
137
134
|
return raw.replace(/\/api\/headed\/?$/, '');
|
|
138
135
|
}
|
|
136
|
+
function resolveBrowserAppBaseUrl() {
|
|
137
|
+
if (selectedEnvironment) {
|
|
138
|
+
return normalizeBaseUrl(ENVIRONMENT_BASE_URLS[selectedEnvironment]);
|
|
139
|
+
}
|
|
140
|
+
return resolveHeadedServerAppBaseUrl();
|
|
141
|
+
}
|
|
139
142
|
function buildUrl(pathname) {
|
|
140
|
-
return `${
|
|
143
|
+
return `${resolveHeadedServerAppBaseUrl()}${pathname}`;
|
|
141
144
|
}
|
|
142
145
|
function buildHeadedUrl(pathname) {
|
|
143
|
-
return `${
|
|
146
|
+
return `${resolveHeadedServerAppBaseUrl()}/api/headed${pathname}`;
|
|
147
|
+
}
|
|
148
|
+
function buildBrowserHeadedUrl(pathname) {
|
|
149
|
+
return `${resolveBrowserAppBaseUrl()}/api/headed${pathname}`;
|
|
144
150
|
}
|
|
145
151
|
async function postJson(pathname, payload) {
|
|
146
152
|
const response = await fetch(buildUrl(pathname), {
|
|
@@ -179,8 +185,24 @@ async function postHeadedJson(pathname, payload) {
|
|
|
179
185
|
}
|
|
180
186
|
return { status: response.status, ok: response.ok, text, json };
|
|
181
187
|
}
|
|
182
|
-
async function
|
|
183
|
-
const response = await fetch(
|
|
188
|
+
async function postBrowserHeadedJson(pathname, payload) {
|
|
189
|
+
const response = await fetch(buildBrowserHeadedUrl(pathname), {
|
|
190
|
+
method: 'POST',
|
|
191
|
+
headers: { 'Content-Type': 'application/json' },
|
|
192
|
+
body: JSON.stringify(payload ?? {}),
|
|
193
|
+
});
|
|
194
|
+
const text = await response.text();
|
|
195
|
+
let json = null;
|
|
196
|
+
try {
|
|
197
|
+
json = JSON.parse(text);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
json = null;
|
|
201
|
+
}
|
|
202
|
+
return { status: response.status, ok: response.ok, text, json };
|
|
203
|
+
}
|
|
204
|
+
async function getBrowserHeadedText(pathname) {
|
|
205
|
+
const response = await fetch(buildBrowserHeadedUrl(pathname));
|
|
184
206
|
const text = await response.text();
|
|
185
207
|
return { status: response.status, ok: response.ok, text };
|
|
186
208
|
}
|
|
@@ -418,7 +440,7 @@ async function saveImageFromUrl({ url, filename }) {
|
|
|
418
440
|
const TOOLS = [
|
|
419
441
|
{
|
|
420
442
|
name: 'set_environment',
|
|
421
|
-
description: 'Set the base URL for
|
|
443
|
+
description: 'Set the base URL for browser-session actions. localhost -> http://localhost:3000, dev -> https://dev.withmarble.ai, production -> https://withmarble.ai. Non-browser server/workflow actions continue using HEADED_SERVER_BASE_URL (default localhost:3000).',
|
|
422
444
|
inputSchema: {
|
|
423
445
|
type: 'object',
|
|
424
446
|
properties: {
|
|
@@ -766,7 +788,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
766
788
|
};
|
|
767
789
|
}
|
|
768
790
|
selectedEnvironment = environment;
|
|
769
|
-
const
|
|
791
|
+
const browserAppBaseUrl = resolveBrowserAppBaseUrl();
|
|
792
|
+
const headedServerAppBaseUrl = resolveHeadedServerAppBaseUrl();
|
|
770
793
|
return {
|
|
771
794
|
content: [
|
|
772
795
|
{
|
|
@@ -774,24 +797,25 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
774
797
|
text: JSON.stringify({
|
|
775
798
|
ok: true,
|
|
776
799
|
environment,
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
800
|
+
browserAppBaseUrl,
|
|
801
|
+
browserHeadedApiBaseUrl: `${browserAppBaseUrl}/api/headed`,
|
|
802
|
+
headedServerAppBaseUrl,
|
|
803
|
+
headedServerHeadedApiBaseUrl: `${headedServerAppBaseUrl}/api/headed`,
|
|
780
804
|
}, null, 2),
|
|
781
805
|
},
|
|
782
806
|
],
|
|
783
807
|
};
|
|
784
808
|
}
|
|
785
809
|
case 'headed_start_session': {
|
|
786
|
-
const result = await
|
|
810
|
+
const result = await postBrowserHeadedJson('/start_session', args);
|
|
787
811
|
return { content: [{ type: 'text', text: JSON.stringify(result.json || { status: result.status, body: result.text }, null, 2) }] };
|
|
788
812
|
}
|
|
789
813
|
case 'headed_end_session': {
|
|
790
|
-
const result = await
|
|
814
|
+
const result = await postBrowserHeadedJson('/end_session', args);
|
|
791
815
|
return { content: [{ type: 'text', text: JSON.stringify(result.json || { status: result.status, body: result.text }, null, 2) }] };
|
|
792
816
|
}
|
|
793
817
|
case 'headed_navigate_to_project': {
|
|
794
|
-
const result = await
|
|
818
|
+
const result = await postBrowserHeadedJson('/navigate_to_project', args);
|
|
795
819
|
return { content: [{ type: 'text', text: JSON.stringify(result.json || { status: result.status, body: result.text }, null, 2) }] };
|
|
796
820
|
}
|
|
797
821
|
case 'navigate_to_url': {
|
|
@@ -804,15 +828,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
804
828
|
if (!browserSessionId || Number.isNaN(browserSessionId)) {
|
|
805
829
|
return { content: [{ type: 'text', text: JSON.stringify({ ok: false, error: 'browserSession is required.' }, null, 2) }] };
|
|
806
830
|
}
|
|
807
|
-
const result = await
|
|
831
|
+
const result = await postBrowserHeadedJson('/navigate_to_url', { browserSessionId, url });
|
|
808
832
|
return { content: [{ type: 'text', text: JSON.stringify(result.json || { status: result.status, body: result.text }, null, 2) }] };
|
|
809
833
|
}
|
|
810
834
|
case 'start_plan_project': {
|
|
811
|
-
const result = await
|
|
835
|
+
const result = await postBrowserHeadedJson('/start_plan_project', args);
|
|
812
836
|
return { content: [{ type: 'text', text: JSON.stringify(result.json || { status: result.status, body: result.text }, null, 2) }] };
|
|
813
837
|
}
|
|
814
838
|
case 'headed_send_msg': {
|
|
815
|
-
const result = await
|
|
839
|
+
const result = await postBrowserHeadedJson('/send_msg_headed', args);
|
|
816
840
|
const payload = (result.json && typeof result.json === 'object') ? result.json : null;
|
|
817
841
|
if (payload?.workflowRunId) {
|
|
818
842
|
const summaryResult = await fetchWorkflowEntries(String(payload.workflowRunId));
|
|
@@ -827,7 +851,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
827
851
|
return { content: [{ type: 'text', text: JSON.stringify(payload || { status: result.status, body: result.text }, null, 2) }] };
|
|
828
852
|
}
|
|
829
853
|
case 'take_screenshot': {
|
|
830
|
-
const result = await
|
|
854
|
+
const result = await postBrowserHeadedJson('/take_screenshot', args);
|
|
831
855
|
const payload = (result.json && typeof result.json === 'object') ? result.json : null;
|
|
832
856
|
if (payload?.workflowRunId) {
|
|
833
857
|
const summaryResult = await fetchWorkflowEntries(String(payload.workflowRunId));
|
|
@@ -842,19 +866,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
842
866
|
return { content: [{ type: 'text', text: JSON.stringify(payload || { status: result.status, body: result.text }, null, 2) }] };
|
|
843
867
|
}
|
|
844
868
|
case 'take_screenshot': {
|
|
845
|
-
const result = await
|
|
869
|
+
const result = await postBrowserHeadedJson('/take_screenshot', args);
|
|
846
870
|
return { content: [{ type: 'text', text: JSON.stringify(result.json || { status: result.status, body: result.text }, null, 2) }] };
|
|
847
871
|
}
|
|
848
872
|
case 'screenshots_preview': {
|
|
849
873
|
const payload = args?.screenshotUrls
|
|
850
874
|
? { screenshotUrls: args.screenshotUrls }
|
|
851
875
|
: args?.response || args;
|
|
852
|
-
const result = await
|
|
876
|
+
const result = await postBrowserHeadedJson('/preview_screenshots', payload);
|
|
853
877
|
return { content: [{ type: 'text', text: JSON.stringify({ status: result.status, ok: result.ok, html: result.text }, null, 2) }] };
|
|
854
878
|
}
|
|
855
879
|
case 'screenshots_get_preview': {
|
|
856
880
|
const previewId = args?.previewId;
|
|
857
|
-
const result = await
|
|
881
|
+
const result = await getBrowserHeadedText(`/preview_screenshots/${encodeURIComponent(previewId)}`);
|
|
858
882
|
return { content: [{ type: 'text', text: JSON.stringify({ status: result.status, ok: result.ok, html: result.text }, null, 2) }] };
|
|
859
883
|
}
|
|
860
884
|
case 'workflow_end_to_end_project_generation': {
|