public MCP: the bare host answers MCP (POST /) and names the connect URL (GET /)

This commit is contained in:
CRTkafa 2026-11-08 02:26:11 +07:00
parent 9081ac921d
commit b82becf7fb
4 changed files with 28 additions and 2 deletions

View file

@ -235,6 +235,24 @@ describe('http, public mode', () => {
} finally { s.close(); }
});
test('the bare host is the endpoint too: POST / answers MCP, GET / names the connect URL', async () => {
const s = await startHttp({ ...base, public: { rate: 100, trustProxy: false } });
try {
const r = await fetch(`http://127.0.0.1:${s.port}/`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/list' }) });
expect(r.status).toBe(200);
expect(((await r.json()) as { result: { tools: unknown[] } }).result.tools.length).toBe(6);
const g = await fetch(`http://127.0.0.1:${s.port}/`);
expect(g.status).toBe(200);
expect(await g.text()).toContain('claude mcp add --transport http storebound');
expect((await fetch(`http://127.0.0.1:${s.port}/other`)).status).toBe(404);
} finally { s.close(); }
});
test('a signed-in server keeps / closed', async () => {
const s = await startHttp({ ...base, auth: { kind: 'token', token: 't' } as const });
try { expect((await fetch(`http://127.0.0.1:${s.port}/`)).status).toBe(404); } finally { s.close(); }
});
test('429 with Retry-After over the limit; X-Forwarded-For counts only with trustProxy', async () => {
const s = await startHttp({ ...base, public: { rate: 2, trustProxy: false } });
try {