Gate MCP endpoint behind MCP_ENABLED flag
This commit is contained in:
commit
2b7eb29a0e
5 files changed
+46
-2
No files matched your search
@@ -54,6 +54,9 @@ Optional: set `TWO_FACTOR_ENCRYPTION_KEY` to a 64-character hex string to enable
|
||||
authentication. Generate one with `openssl rand -hex 32`. Two-factor authentication is unavailable
|
||||
and cannot be required until this key is set.
|
||||
|
||||
MCP is disabled by default. Set `MCP_ENABLED=1` to enable the `/mcp` endpoint, then
|
||||
authenticate with an API key generated under Settings → API keys.
|
||||
|
||||
The connection URL format:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -38,6 +38,7 @@ x-umami-env: &umami-env
|
||||
DISABLE_BOT_CHECK: "1"
|
||||
DISABLE_TELEMETRY: "1"
|
||||
DISABLE_UPDATES: "1"
|
||||
MCP_ENABLED: "1"
|
||||
|
||||
services:
|
||||
db:
|
||||
|
||||
@@ -60,7 +60,7 @@ Authorization: Bearer umami_<your-api-key>
|
||||
Use a client that supports bearer tokens or custom authorization headers. The endpoint accepts
|
||||
self-hosted API keys; browser login tokens are not supported. Tools are read-only and respect
|
||||
the key owner's existing user/team permissions. Revoke the key in Settings to disconnect access.
|
||||
Set `MCP_DISABLED=1` to disable the endpoint.
|
||||
MCP is disabled by default. Set `MCP_ENABLED=1` to enable the endpoint.
|
||||
|
||||
## Local / stdio
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { afterEach, beforeEach, expect, test, vi } from 'vitest';
|
||||
import { authenticateMcpRequest } from '@/lib/mcp/auth';
|
||||
import { DELETE, GET, POST } from './route';
|
||||
|
||||
vi.mock('@umami/mcp', () => ({
|
||||
createUmamiMcpHttpHandler: () => ({ fetch: vi.fn() }),
|
||||
}));
|
||||
vi.mock('@/lib/mcp/auth', () => ({
|
||||
authenticateMcpRequest: vi.fn(),
|
||||
mcpAuthErrorResponse: () => new Response(null, { status: 401 }),
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
vi.mocked(authenticateMcpRequest).mockReset();
|
||||
vi.mocked(authenticateMcpRequest).mockResolvedValue({
|
||||
ok: false,
|
||||
status: 401,
|
||||
error: 'invalid_request',
|
||||
description: 'Missing bearer API key.',
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => vi.unstubAllEnvs());
|
||||
|
||||
test.each([undefined, '', '0', 'true'])('MCP stays disabled for MCP_ENABLED=%s', async value => {
|
||||
vi.stubEnv('MCP_ENABLED', value);
|
||||
for (const handler of [GET, POST, DELETE]) {
|
||||
const response = await handler(new Request('http://localhost/mcp'));
|
||||
expect(response.status).toBe(404);
|
||||
}
|
||||
expect(authenticateMcpRequest).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('MCP_ENABLED=1 enables API-key authentication', async () => {
|
||||
vi.stubEnv('MCP_ENABLED', '1');
|
||||
const request = new Request('http://localhost/mcp');
|
||||
const response = await POST(request);
|
||||
expect(response.status).toBe(401);
|
||||
expect(authenticateMcpRequest).toHaveBeenCalledWith(request);
|
||||
});
|
||||
@@ -38,7 +38,7 @@ const handler = createUmamiMcpHttpHandler({
|
||||
});
|
||||
|
||||
async function handle(request: Request) {
|
||||
if (process.env.MCP_DISABLED === '1') {
|
||||
if (process.env.MCP_ENABLED !== '1') {
|
||||
return new Response(null, { status: 404 });
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user