Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/mcp.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// supports them, from one canonical definition. MoshCode drives each engine's
// own `mcp add` so the engine owns its config format. See prd/0003.
import { ENGINES, isInstalled, ranOk, runCmd } from "./engines.mjs";
import { isIP } from "node:net";

// Coding engines that can register MCP servers. Aider has no MCP support.
export const MCP_ENGINES = ["claude", "gemini", "codex", "opencode"];
Expand All @@ -19,7 +20,13 @@ const SUFFIX_LABELS = ["co", "com", "net", "org", "gov", "edu", "ac"];
export function deriveName(target) {
const sanitize = (s) => String(s).toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^-+|-+$/g, "");
try {
const labels = new URL(target).hostname.split(".").filter(Boolean);
const hostname = new URL(target).hostname;
const ipHost = hostname.replace(/^\[|\]$/g, "");
if (isIP(ipHost)) {
const ipName = ipHost.replace(/[.:]+/g, "-").replace(/^-+|-+$/g, "");
return sanitize(`ip-${ipName}`);
}
const labels = hostname.split(".").filter(Boolean);
let withoutTld = labels.slice(0, -1); // drop the TLD
// ...and the generic label of a multi-part suffix, as long as a real name
// still precedes it (a bare "co.uk" host has nothing better to offer).
Expand Down
5 changes: 5 additions & 0 deletions test/mcp.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ test("deriveName pulls a sane name from a remote host", () => {
assert.equal(deriveName("not a url"), "server");
});

test("deriveName keeps IP literal hosts recognizable", () => {
assert.equal(deriveName("http://127.0.0.1:3000/sse"), "ip-127-0-0-1");
assert.equal(deriveName("http://[::1]:3000/sse"), "ip-1");
});

test("deriveName skips the generic label of a multi-part suffix", () => {
assert.equal(deriveName("https://mcp.acme.co.uk/sse"), "acme");
assert.equal(deriveName("https://api.example.com.au/mcp"), "example");
Expand Down
Loading