@marsnme/mcp-gateway 0.1.5 → 0.1.7
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/README.md +12 -3
- package/package.json +13 -4
- package/server.mjs +39 -2
package/README.md
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
# @marsnme/mcp-gateway
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/Marsmanleo/MarsNMe/main/docs/assets/demo.gif" alt="MarsNMe demo" width="640" />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
2
7
|
MarsNMe MCP Gateway for memory tools over streamable HTTP transport.
|
|
3
8
|
|
|
4
9
|
This package runs an MCP server at `POST /mcp` and exposes health status at `GET /health`.
|
|
@@ -23,8 +28,8 @@ After startup:
|
|
|
23
28
|
|
|
24
29
|
## Required environment variables
|
|
25
30
|
- `MCP_PROFILE`
|
|
26
|
-
-
|
|
27
|
-
-
|
|
31
|
+
- Any lowercase profile ID matching `^[a-z][a-z0-9_-]*$` (for example: `coco`, `toto`, `my-agent`)
|
|
32
|
+
- Legacy built-in IDs: `coco` and `toto`
|
|
28
33
|
- `SUPABASE_BASE_URL`
|
|
29
34
|
- Your Supabase REST project URL
|
|
30
35
|
- `SUPABASE_SERVICE_ROLE_KEY` (recommended) or `SUPABASE_SERVICE_KEY`
|
|
@@ -34,7 +39,11 @@ After startup:
|
|
|
34
39
|
|
|
35
40
|
## Common optional environment variables
|
|
36
41
|
- `PORT`
|
|
37
|
-
- Overrides
|
|
42
|
+
- Overrides the HTTP port used by the gateway
|
|
43
|
+
- If omitted, the gateway resolves a profile-based default:
|
|
44
|
+
- `coco` → `18790`
|
|
45
|
+
- `toto` → `18791`
|
|
46
|
+
- other profile IDs → deterministic port in `20000-29999`
|
|
38
47
|
- `MCP_REQUIRE_BEARER`
|
|
39
48
|
- Set `true` to require `Authorization: Bearer <token>` on MCP calls
|
|
40
49
|
- `MCP_OAUTH_ENABLED`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marsnme/mcp-gateway",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"mcpName": "io.github.Marsmanleo/marsnme",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Agent-agnostic, LLM-agnostic memory backend for MCP-compatible tools",
|
|
@@ -14,10 +14,19 @@
|
|
|
14
14
|
"keywords": [
|
|
15
15
|
"mcp",
|
|
16
16
|
"memory",
|
|
17
|
-
"ai",
|
|
18
|
-
"
|
|
17
|
+
"ai-memory",
|
|
18
|
+
"persistent-memory",
|
|
19
|
+
"ai-agent",
|
|
20
|
+
"model-context-protocol",
|
|
21
|
+
"semantic-search",
|
|
22
|
+
"supabase",
|
|
23
|
+
"jina",
|
|
19
24
|
"embedding",
|
|
20
|
-
"
|
|
25
|
+
"typescript",
|
|
26
|
+
"session-memory",
|
|
27
|
+
"cross-session",
|
|
28
|
+
"llm",
|
|
29
|
+
"symbiosis"
|
|
21
30
|
],
|
|
22
31
|
"bin": {
|
|
23
32
|
"marsnme": "server.mjs"
|
package/server.mjs
CHANGED
|
@@ -45,6 +45,19 @@ const PROFILE_CONFIGS = {
|
|
|
45
45
|
memoryIngestFixedTags: ['toto', 'insight']
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
|
+
const PROFILE_DEFAULT_PORT_RANGE_START = 20000;
|
|
49
|
+
const PROFILE_DEFAULT_PORT_RANGE_SIZE = 10000;
|
|
50
|
+
const PROFILE_LEGACY_DEFAULT_PORTS = {
|
|
51
|
+
coco: 18790,
|
|
52
|
+
toto: 18791
|
|
53
|
+
};
|
|
54
|
+
function resolveProfileDefaultPort(profileId) {
|
|
55
|
+
const legacyPort = PROFILE_LEGACY_DEFAULT_PORTS[profileId];
|
|
56
|
+
if (Number.isInteger(legacyPort)) return legacyPort;
|
|
57
|
+
const hash = crypto.createHash('sha256').update(profileId).digest();
|
|
58
|
+
const slot = hash.readUInt16BE(0) % PROFILE_DEFAULT_PORT_RANGE_SIZE;
|
|
59
|
+
return PROFILE_DEFAULT_PORT_RANGE_START + slot;
|
|
60
|
+
}
|
|
48
61
|
const PROFILE_ID_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
49
62
|
function buildProfileConfig(profileId) {
|
|
50
63
|
const legacyProfile = PROFILE_CONFIGS[profileId];
|
|
@@ -53,7 +66,7 @@ function buildProfileConfig(profileId) {
|
|
|
53
66
|
...PROFILE_CONFIGS.coco,
|
|
54
67
|
schema: profileId,
|
|
55
68
|
displayName: profileId,
|
|
56
|
-
defaultPort:
|
|
69
|
+
defaultPort: resolveProfileDefaultPort(profileId),
|
|
57
70
|
gatewayDir: `${profileId}-mcp-gateway`,
|
|
58
71
|
publicHostSuffix: `${profileId}-mcp.marsgroup.asia`,
|
|
59
72
|
recallBodyEnum: [profileId, 'system'],
|
|
@@ -151,7 +164,12 @@ function setMemorySourceWhitelist(nextSources) {
|
|
|
151
164
|
}
|
|
152
165
|
setMemorySourceWhitelist(buildMemorySourceListForMode());
|
|
153
166
|
|
|
154
|
-
const
|
|
167
|
+
const PORT_RAW = String(process.env.PORT || '').trim();
|
|
168
|
+
const PORT_SOURCE = PORT_RAW ? 'env' : 'profile-default';
|
|
169
|
+
const PORT = Number.parseInt(PORT_RAW || String(PROFILE.defaultPort), 10);
|
|
170
|
+
if (!Number.isInteger(PORT) || PORT < 1 || PORT > 65535) {
|
|
171
|
+
throw new Error(`Invalid PORT: ${PORT_RAW || String(PORT)}. Must be an integer between 1 and 65535.`);
|
|
172
|
+
}
|
|
155
173
|
const SUPABASE_BASE_URL = process.env.SUPABASE_BASE_URL || 'http://127.0.0.1:8100';
|
|
156
174
|
const OAUTH_ENABLED = process.env.MCP_OAUTH_ENABLED !== 'false';
|
|
157
175
|
const REQUIRE_BEARER = process.env.MCP_REQUIRE_BEARER === 'true';
|
|
@@ -4336,8 +4354,27 @@ const server = http.createServer(async (req, res) => {
|
|
|
4336
4354
|
}
|
|
4337
4355
|
});
|
|
4338
4356
|
|
|
4357
|
+
server.on('error', (error) => {
|
|
4358
|
+
if (error?.code === 'EADDRINUSE') {
|
|
4359
|
+
const hint =
|
|
4360
|
+
PORT_SOURCE === 'env'
|
|
4361
|
+
? `Set PORT to an unused value (current PORT=${PORT}).`
|
|
4362
|
+
: `Set PORT to an unused value or use another MCP_PROFILE (profile=${MCP_PROFILE}, default_port=${PROFILE.defaultPort}).`;
|
|
4363
|
+
console.error(`[fatal] ${SERVER_NAME} cannot start: port ${PORT} is already in use. ${hint}`);
|
|
4364
|
+
process.exit(1);
|
|
4365
|
+
return;
|
|
4366
|
+
}
|
|
4367
|
+
console.error(
|
|
4368
|
+
`[fatal] ${SERVER_NAME} failed to start: ${String(error?.message || error)}`
|
|
4369
|
+
);
|
|
4370
|
+
process.exit(1);
|
|
4371
|
+
});
|
|
4372
|
+
|
|
4339
4373
|
server.listen(PORT, '0.0.0.0', () => {
|
|
4340
4374
|
console.log(`${SERVER_NAME} listening on 0.0.0.0:${PORT}`);
|
|
4375
|
+
console.log(
|
|
4376
|
+
`[config] profile=${MCP_PROFILE} resolved_port=${PORT} source=${PORT_SOURCE} profile_default_port=${PROFILE.defaultPort}`
|
|
4377
|
+
);
|
|
4341
4378
|
console.log(`[config] source_mode=${SOURCE_MODE}`);
|
|
4342
4379
|
if (SOURCE_MODE === 'registry') {
|
|
4343
4380
|
void reloadSourceRegistryCache()
|