@el4cteo/rbx-studio-mcp 0.1.0 → 0.1.1

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.
@@ -10,7 +10,7 @@ import { defineTool } from "../lib/tool.js";
10
10
  * and its context is exactly what the caller needs.
11
11
  */
12
12
  async function findPlaytestSession(bridge) {
13
- const sessions = bridge.list();
13
+ const sessions = (await bridge.sessions()).list;
14
14
  const cached = sessions.find((session) => session.context?.includes("playtest"));
15
15
  if (cached)
16
16
  return cached.studioId;
@@ -18,7 +18,7 @@ async function findPlaytestSession(bridge) {
18
18
  const probed = await Promise.all(unknown.map(async (session) => {
19
19
  try {
20
20
  const status = await bridge.call("studio.status", {}, { studioId: session.studioId, timeoutMs: 3_000 });
21
- bridge.notePlaceName(session.studioId, status.placeName, status.context);
21
+ await bridge.notePlaceName(session.studioId, status.placeName, status.context);
22
22
  return status.context?.includes("playtest") ? session.studioId : null;
23
23
  }
24
24
  catch {
@@ -105,7 +105,7 @@ export function registerPlaytestTools(context) {
105
105
  timeoutMs: 10_000,
106
106
  })
107
107
  .catch(() => null);
108
- const survivor = bridge.list().find((session) => session.studioId !== playtest);
108
+ const survivor = (await bridge.sessions()).list.find((session) => session.studioId !== playtest);
109
109
  if (survivor) {
110
110
  //[[
111
111
  // Waited for, not sampled. The teardown is deliberately deferred so
@@ -1 +1 @@
1
- {"version":3,"file":"playtest.js","sourceRoot":"","sources":["../../src/tools/playtest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"playtest.js","sourceRoot":"","sources":["../../src/tools/playtest.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { zstdDecompressSync } from "node:zlib";
2
2
  import { z } from "zod";
3
+ import { ToolError } from "../lib/errors.js";
3
4
  import { image } from "../lib/format.js";
4
5
  import { encodePng } from "../lib/png.js";
5
6
  import { defineTool } from "../lib/tool.js";
@@ -19,6 +20,37 @@ function toPngBase64(response) {
19
20
  const rgb = zstdDecompressSync(Buffer.from(response.data, "base64"));
20
21
  return encodePng(rgb, response.width, response.height).toString("base64");
21
22
  }
23
+ const isPlaytest = (session) => (session.context ?? "").startsWith("playtest");
24
+ /** Which session this call will land on, when that can be told from here. */
25
+ function targetOf(sessions, activeId, wanted) {
26
+ if (wanted !== undefined)
27
+ return sessions.find((session) => session.studioId === wanted);
28
+ if (activeId !== null)
29
+ return sessions.find((session) => session.studioId === activeId);
30
+ return sessions.length === 1 ? sessions[0] : undefined;
31
+ }
32
+ /**
33
+ * A playtest screenshot, which takes two sessions.
34
+ *
35
+ * The client is the only thing that can take the picture, and it cannot read
36
+ * it back: `CaptureService` returns a temporary texture id and
37
+ * `CreateEditableImageAsync` refuses those at script identity. The id names a
38
+ * texture in the Studio *process*, though, so the editor session's plugin —
39
+ * same process, plugin identity — opens it without complaint. This is the only
40
+ * place that can see both sessions at once, so the pairing lives here.
41
+ */
42
+ async function playtestShot(bridge, playtest, sessions, width) {
43
+ const editor = sessions.find((session) => session.placeId === playtest.placeId && !isPlaytest(session));
44
+ if (editor === undefined) {
45
+ throw new ToolError("NO_EDITOR_SESSION", "The playtest is connected but its editor session is not, and reading the " +
46
+ "captured image needs the editor's plugin identity.", "The editor window must stay connected while the playtest runs. Check " +
47
+ "`list_studios` — there should be two entries for this place.");
48
+ }
49
+ const { contentId } = await bridge.call("capture.playtestId", {}, { studioId: playtest.studioId, timeoutMs: 40_000 });
50
+ // Straight on, with no await in between: the texture is temporary and there
51
+ // is no promise about how long Studio keeps one nobody has opened yet.
52
+ return bridge.call("capture.decode", { contentId, width, context: "playtest client" }, { studioId: editor.studioId, timeoutMs: 60_000 });
53
+ }
22
54
  export function registerScreenshotTools(context) {
23
55
  const { bridge } = context;
24
56
  defineTool(context, {
@@ -36,13 +68,12 @@ export function registerScreenshotTools(context) {
36
68
  "their camera angle, not a framing of your choosing. Frame the subject " +
37
69
  "with `viewport op=\"focus\"` first — that is what makes this tool " +
38
70
  "worth calling.\n\n" +
39
- "NOT AVAILABLE WHILE A PLAYTEST IS RUNNING. Studio only lets a client " +
40
- "session capture the screen, and it forbids client sessions from making " +
41
- "HTTP requests, so no session that can be reached is allowed to take the " +
42
- "picture: the playtest server refuses outright and the editor session " +
43
- "times out, because the window is no longer rendering its data model. " +
44
- "Stop the playtest and screenshot in edit mode, or read the running game " +
45
- "through `character`, `console` and `find` instead.",
71
+ "Works during a playtest too — address it at the playtest's studioId and " +
72
+ "you get the player's own view, which is the only way to check what a GUI " +
73
+ "actually looks like in front of the game. That one is taken on the client " +
74
+ "and read back through the editor session, so it is a little slower and " +
75
+ "needs the editor window still connected; the caption says `playtest " +
76
+ "client` when it came from there.",
46
77
  inputSchema: {
47
78
  width: z
48
79
  .number()
@@ -57,10 +88,14 @@ export function registerScreenshotTools(context) {
57
88
  },
58
89
  readOnly: true,
59
90
  }, async (args) => {
60
- const response = await bridge.call("capture.screenshot", { width: args.width },
61
- // Capturing, reading the pixels back and encoding a PNG in Luau all
62
- // happen before the reply, and none of them is instant on a big viewport.
63
- { studioId: args.studioId, timeoutMs: 60_000 });
91
+ const { list, activeId } = await bridge.sessions();
92
+ const target = targetOf(list, activeId, args.studioId);
93
+ const response = target !== undefined && isPlaytest(target)
94
+ ? await playtestShot(bridge, target, list, args.width)
95
+ : await bridge.call("capture.screenshot", { width: args.width },
96
+ // Capturing, reading the pixels back and compressing them all happen
97
+ // before the reply, and none is instant on a big viewport.
98
+ { studioId: args.studioId, timeoutMs: 60_000 });
64
99
  const png = toPngBase64(response);
65
100
  // The device is named in the caption rather than left to be inferred: an
66
101
  // emulated phone makes every screenshot tall and narrow until it is
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/tools/screenshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,KAAK,EAAmB,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAoB,MAAM,gBAAgB,CAAC;AAiB9D;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,QAA4B;IAC/C,IAAI,QAAQ,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QACrC,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IACD,MAAM,GAAG,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IACrE,OAAO,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAoB;IAC1D,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE3B,UAAU,CACR,OAAO,EACP;QACE,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,yBAAyB;QAChC,WAAW,EACT,wEAAwE;YACxE,2BAA2B;YAC3B,kEAAkE;YAClE,wEAAwE;YACxE,wEAAwE;YACxE,sEAAsE;YACtE,qEAAqE;YACrE,+BAA+B;YAC/B,sEAAsE;YACtE,wEAAwE;YACxE,oEAAoE;YACpE,oBAAoB;YACpB,uEAAuE;YACvE,yEAAyE;YACzE,0EAA0E;YAC1E,uEAAuE;YACvE,uEAAuE;YACvE,0EAA0E;YAC1E,oDAAoD;QACtD,WAAW,EAAE;YACX,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,GAAG,CAAC,GAAG,CAAC;iBACR,GAAG,CAAC,IAAI,CAAC;iBACT,OAAO,CAAC,GAAG,CAAC;iBACZ,QAAQ,CACP,kEAAkE;gBAChE,oEAAoE;gBACpE,2CAA2C,CAC9C;YACH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;SACpF;QACD,QAAQ,EAAE,IAAI;KACf,EACD,KAAK,EAAE,IAAI,EAAuB,EAAE;QAClC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAChC,oBAAoB,EACpB,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;QACrB,oEAAoE;QACpE,0EAA0E;QAC1E,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,CAC/C,CAAC;QAEF,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QAElC,yEAAyE;QACzE,oEAAoE;QACpE,wEAAwE;QACxE,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM;YAC/B,CAAC,CAAC,cAAc,QAAQ,CAAC,MAAM,uDAAuD;YACtF,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO,KAAK,CACV,GAAG,EACH,oBAAoB,QAAQ,CAAC,OAAO,MAAM,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE;YAC3E,gBAAgB,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,YAAY,IAAI,SAAS,EAAE,CAC/E,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/tools/screenshot.ts"],"names":[],"mappings":"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"}
@@ -33,12 +33,13 @@ export function registerSessionTools(context) {
33
33
  readOnly: true,
34
34
  }, async ({ studioId }) => {
35
35
  const status = await bridge.call("studio.status", {}, { studioId });
36
- const targetId = studioId ?? bridge.activeId;
36
+ const view = await bridge.sessions();
37
+ const targetId = studioId ?? view.activeId;
37
38
  if (targetId)
38
- bridge.notePlaceName(targetId, status.placeName, status.context);
39
+ await bridge.notePlaceName(targetId, status.placeName, status.context);
39
40
  // A stale plugin answers with older handlers and no other symptom, so the
40
41
  // warning rides along with the one call agents are told to make first.
41
- const session = bridge.list().find((entry) => entry.studioId === targetId);
42
+ const session = view.list.find((entry) => entry.studioId === targetId);
42
43
  const warning = pluginStalenessWarning(session?.buildId);
43
44
  return json(status, warning ? `WARNING: ${warning}` : undefined);
44
45
  });
@@ -67,7 +68,8 @@ export function registerSessionTools(context) {
67
68
  inputSchema: {},
68
69
  readOnly: true,
69
70
  }, async () => {
70
- const sessions = bridge.list();
71
+ const view = await bridge.sessions();
72
+ const sessions = view.list;
71
73
  if (sessions.length === 0) {
72
74
  return text("No Studio instances are connected.\n" +
73
75
  "Open Roblox Studio and enable the Studio MCP plugin (Plugins tab -> " +
@@ -76,7 +78,7 @@ export function registerSessionTools(context) {
76
78
  // A defaulted target is not reported as active: tools refuse to use it
77
79
  // while several are connected, so showing it as active would explain
78
80
  // neither the AMBIGUOUS_STUDIO that follows nor how to clear it.
79
- const active = bridge.activeIsChosen || sessions.length === 1 ? bridge.activeId : null;
81
+ const active = view.activeIsChosen || sessions.length === 1 ? view.activeId : null;
80
82
  // The identity captured at connect only knows the data model's name. Each
81
83
  // Studio is asked live for the name the user would actually recognise,
82
84
  // plus what it has open — which is usually how someone identifies a window
@@ -85,7 +87,7 @@ export function registerSessionTools(context) {
85
87
  const detail = await Promise.all(sessions.map(async (session) => {
86
88
  try {
87
89
  const status = await bridge.call("studio.status", {}, { studioId: session.studioId, timeoutMs: 3_000 });
88
- bridge.notePlaceName(session.studioId, status.placeName, status.context);
90
+ await bridge.notePlaceName(session.studioId, status.placeName, status.context);
89
91
  return {
90
92
  placeName: status.placeName,
91
93
  context: status.context,
@@ -133,8 +135,8 @@ export function registerSessionTools(context) {
133
135
  destructive: false,
134
136
  idempotent: true,
135
137
  }, async ({ studioId }) => {
136
- bridge.setActive(studioId);
137
- const session = bridge.list().find((s) => s.studioId === studioId);
138
+ await bridge.setActive(studioId);
139
+ const session = (await bridge.sessions()).list.find((s) => s.studioId === studioId);
138
140
  // Confirmed with the session's context because two entries can share a
139
141
  // place name, and picking the playtest one means work that disappears
140
142
  // when the user presses stop.
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/tools/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/tools/session.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,62 +1,62 @@
1
- {
2
- "name": "@el4cteo/rbx-studio-mcp",
3
- "version": "0.1.0",
4
- "description": "Free, open-source MCP server for Roblox Studio. Push-based SSE transport, editor-safe script edits, token-lean tools.",
5
- "type": "module",
6
- "license": "MIT",
7
- "bin": {
8
- "rbx-studio-mcp": "dist/index.js"
9
- },
10
- "files": [
11
- "dist",
12
- "plugin",
13
- "scripts",
14
- "README.md",
15
- "LICENSE"
16
- ],
17
- "engines": {
18
- "node": ">=22.15"
19
- },
20
- "scripts": {
21
- "build": "tsc",
22
- "watch": "tsc --watch",
23
- "typecheck": "tsc --noEmit",
24
- "start": "node dist/index.js",
25
- "build:plugin": "node scripts/check-plugin.mjs && node scripts/build-plugin.mjs",
26
- "sourcemap": "node scripts/sourcemap.mjs",
27
- "test": "node scripts/test-plugin.mjs",
28
- "build:all": "npm run build && npm run build:plugin",
29
- "install:plugin": "node scripts/install-plugin.mjs",
30
- "check:plugin": "node scripts/check-plugin.mjs",
31
- "prepack": "npm run build"
32
- },
33
- "keywords": [
34
- "mcp",
35
- "model-context-protocol",
36
- "roblox",
37
- "roblox-studio",
38
- "luau",
39
- "claude",
40
- "ai"
41
- ],
42
- "dependencies": {
43
- "@modelcontextprotocol/sdk": "^1.22.0",
44
- "zod": "^4.4.3"
45
- },
46
- "devDependencies": {
47
- "@types/node": "^26.2.0",
48
- "typescript": "^7.0.2"
49
- },
50
- "author": "EL4CTEO",
51
- "repository": {
52
- "type": "git",
53
- "url": "git+https://github.com/EL4CTEO/roblox-studio-mcp.git"
54
- },
55
- "homepage": "https://github.com/EL4CTEO/roblox-studio-mcp#readme",
56
- "bugs": {
57
- "url": "https://github.com/EL4CTEO/roblox-studio-mcp/issues"
58
- },
59
- "publishConfig": {
60
- "access": "public"
61
- }
62
- }
1
+ {
2
+ "name": "@el4cteo/rbx-studio-mcp",
3
+ "version": "0.1.1",
4
+ "description": "Free, open-source MCP server for Roblox Studio. Push-based SSE transport, editor-safe script edits, token-lean tools.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "bin": {
8
+ "rbx-studio-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "plugin",
13
+ "scripts",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "engines": {
18
+ "node": ">=22.15"
19
+ },
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "watch": "tsc --watch",
23
+ "typecheck": "tsc --noEmit",
24
+ "start": "node dist/index.js",
25
+ "build:plugin": "node scripts/check-plugin.mjs && node scripts/build-plugin.mjs",
26
+ "sourcemap": "node scripts/sourcemap.mjs",
27
+ "test": "node scripts/test-plugin.mjs",
28
+ "build:all": "npm run build && npm run build:plugin",
29
+ "install:plugin": "node scripts/install-plugin.mjs",
30
+ "check:plugin": "node scripts/check-plugin.mjs",
31
+ "prepack": "npm run build"
32
+ },
33
+ "keywords": [
34
+ "mcp",
35
+ "model-context-protocol",
36
+ "roblox",
37
+ "roblox-studio",
38
+ "luau",
39
+ "claude",
40
+ "ai"
41
+ ],
42
+ "dependencies": {
43
+ "@modelcontextprotocol/sdk": "^1.22.0",
44
+ "zod": "^4.4.3"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^26.2.0",
48
+ "typescript": "^7.0.2"
49
+ },
50
+ "author": "EL4CTEO",
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "git+https://github.com/EL4CTEO/rbx-studio-mcp.git"
54
+ },
55
+ "homepage": "https://github.com/EL4CTEO/rbx-studio-mcp#readme",
56
+ "bugs": {
57
+ "url": "https://github.com/EL4CTEO/rbx-studio-mcp/issues"
58
+ },
59
+ "publishConfig": {
60
+ "access": "public"
61
+ }
62
+ }
@@ -1,59 +1,59 @@
1
- --!strict
2
- --[[
3
- Connection settings for the Studio MCP plugin.
4
-
5
- The port must match the one the Node server was started with (`--port`, or
6
- the ROBLOX_STUDIO_MCP_PORT environment variable). It is stored as a plugin
7
- setting so a user running on a non-default port only has to set it once.
8
- ]]
9
-
10
- local Config = {}
11
-
12
- Config.PLUGIN_VERSION = "0.1.0"
13
-
14
- -- Fingerprint of plugin/src, stamped in by scripts/build-plugin.mjs. The server
15
- -- computes the same hash from its own copy of the sources and compares, so a
16
- -- plugin left running from an older build is reported rather than silently
17
- -- answering with stale handlers. Stays "dev" when the tree is loaded unbuilt.
18
- Config.BUILD_ID = "dev"
19
- Config.PROTOCOL_VERSION = 1
20
- Config.DEFAULT_PORT = 44755
21
-
22
- -- Header the bridge requires on every request. A web page cannot set it
23
- -- cross-origin without a preflight the bridge never answers, which is what
24
- -- keeps a malicious site from driving Studio through the loopback port.
25
- Config.CLIENT_HEADER = "x-roblox-studio-mcp"
26
-
27
- -- How long to wait before retrying after the stream drops. Studio closes SSE
28
- -- connections at the 30 minute mark, so reconnects are routine, not exceptional.
29
- Config.RECONNECT_DELAY = 1
30
- Config.MAX_RECONNECT_DELAY = 30
31
-
32
- -- How long a healthy long-poll session runs before standing aside so streaming
33
- -- can be tried again. Long enough that a Studio which genuinely cannot stream
34
- -- is not reconnecting constantly, short enough that a session downgraded by one
35
- -- unlucky attempt does not spend the rest of its life slower than it should be.
36
- Config.RESTREAM_INTERVAL = 60
37
-
38
- local port: number? = nil
39
-
40
- function Config.setPort(value: number)
41
- port = value
42
- end
43
-
44
- function Config.getPort(): number
45
- return port or Config.DEFAULT_PORT
46
- end
47
-
48
- function Config.baseUrl(): string
49
- return string.format("http://127.0.0.1:%d", Config.getPort())
50
- end
51
-
52
- function Config.headers(): { [string]: string }
53
- return {
54
- [Config.CLIENT_HEADER] = tostring(Config.PROTOCOL_VERSION),
55
- ["Content-Type"] = "application/json",
56
- }
57
- end
58
-
59
- return Config
1
+ --!strict
2
+ --[[
3
+ Connection settings for the Studio MCP plugin.
4
+
5
+ The port must match the one the Node server was started with (`--port`, or
6
+ the ROBLOX_STUDIO_MCP_PORT environment variable). It is stored as a plugin
7
+ setting so a user running on a non-default port only has to set it once.
8
+ ]]
9
+
10
+ local Config = {}
11
+
12
+ Config.PLUGIN_VERSION = "0.1.1"
13
+
14
+ -- Fingerprint of plugin/src, stamped in by scripts/build-plugin.mjs. The server
15
+ -- computes the same hash from its own copy of the sources and compares, so a
16
+ -- plugin left running from an older build is reported rather than silently
17
+ -- answering with stale handlers. Stays "dev" when the tree is loaded unbuilt.
18
+ Config.BUILD_ID = "dev"
19
+ Config.PROTOCOL_VERSION = 1
20
+ Config.DEFAULT_PORT = 44755
21
+
22
+ -- Header the bridge requires on every request. A web page cannot set it
23
+ -- cross-origin without a preflight the bridge never answers, which is what
24
+ -- keeps a malicious site from driving Studio through the loopback port.
25
+ Config.CLIENT_HEADER = "x-roblox-studio-mcp"
26
+
27
+ -- How long to wait before retrying after the stream drops. Studio closes SSE
28
+ -- connections at the 30 minute mark, so reconnects are routine, not exceptional.
29
+ Config.RECONNECT_DELAY = 1
30
+ Config.MAX_RECONNECT_DELAY = 30
31
+
32
+ -- How long a healthy long-poll session runs before standing aside so streaming
33
+ -- can be tried again. Long enough that a Studio which genuinely cannot stream
34
+ -- is not reconnecting constantly, short enough that a session downgraded by one
35
+ -- unlucky attempt does not spend the rest of its life slower than it should be.
36
+ Config.RESTREAM_INTERVAL = 60
37
+
38
+ local port: number? = nil
39
+
40
+ function Config.setPort(value: number)
41
+ port = value
42
+ end
43
+
44
+ function Config.getPort(): number
45
+ return port or Config.DEFAULT_PORT
46
+ end
47
+
48
+ function Config.baseUrl(): string
49
+ return string.format("http://127.0.0.1:%d", Config.getPort())
50
+ end
51
+
52
+ function Config.headers(): { [string]: string }
53
+ return {
54
+ [Config.CLIENT_HEADER] = tostring(Config.PROTOCOL_VERSION),
55
+ ["Content-Type"] = "application/json",
56
+ }
57
+ end
58
+
59
+ return Config