Skip to content
Draft
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
19 changes: 18 additions & 1 deletion main/src/utils/mcp-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/
import type { CoreWorkload } from '@api/types.gen'
import log from '../logger'

/**
* Determines if the platform is probably using native containers.
* Native containers mean Docker runs directly on the host OS (Linux),
* as opposed to running in a VM (macOS/Windows with Docker Desktop).
* When native containers are used, host networking mode allows direct
* access to the host's network stack.
*/
function isProbablyUsingNativeContainers(): boolean {
return process.platform === 'linux'
}

export interface McpToolDefinition {
description?: string
inputSchema: Tool['inputSchema']
Expand Down Expand Up @@ -56,7 +67,13 @@ export function createTransport(workload: CoreWorkload): MCPClientConfig {
}),
}),
'streamable-http': () => {
const url = new URL(`http://localhost:${workload.port}/mcp`)
// On platforms with native containers (Linux), use fixed port for mcp-optimizer
// to work around thv port management bugs in host networking mode
const useFixedPort =
isProbablyUsingNativeContainers() &&
workload.name === 'internal---meta-mcp'
const port = useFixedPort ? 50051 : workload.port
const url = new URL(`http://localhost:${port}/mcp`)
return {
name: workload.name,
transport: new StreamableHTTPClientTransport(url),
Expand Down
299 changes: 299 additions & 0 deletions renderer/src/common/lib/__tests__/meta-optimizer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { initMetaOptimizer } from '../meta-optimizer'
import { server } from '@/common/mocks/node'
import { http, HttpResponse } from 'msw'
import { mswEndpoint } from '@/common/mocks/customHandlers'
import log from 'electron-log/renderer'
import { queryClient } from '../query-client'
import * as apiSdk from '@api/sdk.gen'
import {
ALLOWED_GROUPS_ENV_VAR,
MCP_OPTIMIZER_GROUP_NAME,
META_MCP_SERVER_NAME,
} from '../constants'

vi.mock('electron-log/renderer', () => ({
default: {
error: vi.fn(),
info: vi.fn(),
},
}))

const mockElectronAPI = {
featureFlags: {
get: vi.fn(),
},
getToolhivePort: vi.fn(),
isLinux: true, // Tests run on Linux by default (for host networking tests)
}

Object.defineProperty(window, 'electronAPI', {
value: mockElectronAPI,
writable: true,
})

describe('Meta Optimizer', () => {
beforeEach(() => {
vi.clearAllMocks()
queryClient.clear()
})

describe('initMetaOptimizer', () => {
it('not initialize when both flags are disabled', async () => {
mockElectronAPI.featureFlags.get.mockResolvedValue(false)

const getGroupsSpy = vi.spyOn(apiSdk, 'getApiV1BetaGroups')
const postGroupsSpy = vi.spyOn(apiSdk, 'postApiV1BetaGroups')
const postWorkloadsSpy = vi.spyOn(apiSdk, 'postApiV1BetaWorkloads')

await initMetaOptimizer()

expect(getGroupsSpy).not.toHaveBeenCalled()
expect(postGroupsSpy).not.toHaveBeenCalled()
expect(postWorkloadsSpy).not.toHaveBeenCalled()
expect(log.error).not.toHaveBeenCalled()
expect(log.info).not.toHaveBeenCalled()
})

it('initialize and create group when it does not exist', async () => {
mockElectronAPI.featureFlags.get.mockResolvedValue(true)
mockElectronAPI.getToolhivePort.mockResolvedValue(50055)

const postGroupsSpy = vi.spyOn(apiSdk, 'postApiV1BetaGroups')

server.use(
// Mock groups check - group doesn't exist
http.get(mswEndpoint('/api/v1beta/groups'), () =>
HttpResponse.json({ groups: [] })
),

// Mock workload already exists
http.get(mswEndpoint('/api/v1beta/workloads/:name'), () =>
HttpResponse.json({ name: META_MCP_SERVER_NAME })
)
)

await initMetaOptimizer()

expect(postGroupsSpy).toHaveBeenCalledWith({
body: { name: MCP_OPTIMIZER_GROUP_NAME },
})
})

it('initialize and create group and workload when they do not exist', async () => {
mockElectronAPI.featureFlags.get.mockResolvedValue(true)
mockElectronAPI.getToolhivePort.mockResolvedValue(50055)

const postWorkloadsSpy = vi.spyOn(apiSdk, 'postApiV1BetaWorkloads')

server.use(
// Mock groups check - group doesn't exist
http.get(mswEndpoint('/api/v1beta/groups'), () =>
HttpResponse.json({ groups: [] })
),
// Mock workload check - workload doesn't exist (404)
http.get(mswEndpoint('/api/v1beta/workloads/:name'), () =>
HttpResponse.json({ error: 'Workload not found' }, { status: 404 })
),
// Mock server from registry - mcp-optimizer not found, falls back to meta-mcp
http.get(
mswEndpoint('/api/v1beta/registry/:name/servers/:serverName'),
({ params }) => {
if (params.serverName === 'mcp-optimizer') {
return HttpResponse.json(
{ error: 'Server not found' },
{ status: 404 }
)
}
// Fallback to meta-mcp
return HttpResponse.json({
server: {
image: 'ghcr.io/stackloklabs/meta-mcp:latest',
transport: 'streamable-http',
},
})
}
)
)

await initMetaOptimizer()

expect(postWorkloadsSpy).toHaveBeenCalledWith({
body: expect.objectContaining({
name: META_MCP_SERVER_NAME,
group: MCP_OPTIMIZER_GROUP_NAME,
// Image is hardcoded to mcp-optimizer:latest
image: 'ghcr.io/stackloklabs/mcp-optimizer:latest',
transport: 'streamable-http',
target_port: 50051,
env_vars: {
[ALLOWED_GROUPS_ENV_VAR]: 'default',
TOOLHIVE_HOST: '127.0.0.1',
TOOLHIVE_PORT: '50055',
},
permission_profile: {
network: {
mode: 'host',
},
},
}),
})
})

it('skip workload creation if it already exists', async () => {
mockElectronAPI.featureFlags.get.mockResolvedValue(true)

const postWorkloadsSpy = vi.spyOn(apiSdk, 'postApiV1BetaWorkloads')

server.use(
// Mock group exists
http.get(mswEndpoint('/api/v1beta/groups'), () =>
HttpResponse.json({
groups: [{ name: MCP_OPTIMIZER_GROUP_NAME }],
})
),
// Mock workload already exists
http.get(mswEndpoint('/api/v1beta/workloads/:name'), () =>
HttpResponse.json({
name: META_MCP_SERVER_NAME,
group: MCP_OPTIMIZER_GROUP_NAME,
})
)
)

await initMetaOptimizer()

expect(postWorkloadsSpy).not.toHaveBeenCalled()
})

it('handle group fetch errors gracefully', async () => {
mockElectronAPI.featureFlags.get.mockResolvedValue(true)

server.use(
http.get(mswEndpoint('/api/v1beta/groups'), () =>
HttpResponse.json({ error: 'Server error' }, { status: 500 })
)
)

await initMetaOptimizer()

expect(log.error).toHaveBeenCalledWith(
'[ensureMetaOptimizerGroup] Error checking group:',
expect.any(Error)
)
})

it('not call workload creation when group creation fails', async () => {
mockElectronAPI.featureFlags.get.mockResolvedValue(true)

const postWorkloadsSpy = vi.spyOn(apiSdk, 'postApiV1BetaWorkloads')

server.use(
// Mock groups check - group doesn't exist
http.get(mswEndpoint('/api/v1beta/groups'), () =>
HttpResponse.json({ groups: [] })
),
// Mock group creation fails
http.post(mswEndpoint('/api/v1beta/groups'), () =>
HttpResponse.json(
{ error: 'Failed to create group' },
{ status: 500 }
)
),
// Mock workload check - workload doesn't exist (404)
http.get(mswEndpoint('/api/v1beta/workloads/:name'), () =>
HttpResponse.json({ error: 'Workload not found' }, { status: 404 })
)
)

await initMetaOptimizer()

expect(postWorkloadsSpy).not.toHaveBeenCalled()
expect(log.error).toHaveBeenCalledWith(
'[createMetaOptimizerGroup] Failed to create group:',
expect.objectContaining({ error: 'Failed to create group' })
)
})

it('handle workload creation failure', async () => {
mockElectronAPI.featureFlags.get.mockResolvedValue(true)
mockElectronAPI.getToolhivePort.mockResolvedValue(50055)

server.use(
// Mock groups check - group doesn't exist
http.get(mswEndpoint('/api/v1beta/groups'), () =>
HttpResponse.json({ groups: [] })
),
http.get(mswEndpoint('/api/v1beta/workloads/:name'), () =>
HttpResponse.json({ error: 'Workload not found' }, { status: 404 })
),
http.get(
mswEndpoint('/api/v1beta/registry/:name/servers/:serverName'),
({ params }) => {
if (params.serverName === 'mcp-optimizer') {
return HttpResponse.json(
{ error: 'Server not found' },
{ status: 404 }
)
}
// Fallback to meta-mcp
return HttpResponse.json({
server: {
image: 'ghcr.io/stackloklabs/meta-mcp:latest',
transport: 'streamable-http',
},
})
}
),
http.post(mswEndpoint('/api/v1beta/workloads'), () =>
HttpResponse.json(
{ error: 'Failed to create workload' },
{ status: 500 }
)
)
)

await initMetaOptimizer()

expect(log.error).toHaveBeenCalledWith(
'[createMetaOptimizerWorkload] Failed to create meta optimizer workload:',
expect.objectContaining({ error: 'Failed to create workload' })
)
})

it('handle missing server from registry', async () => {
mockElectronAPI.featureFlags.get.mockResolvedValue(true)
mockElectronAPI.getToolhivePort.mockResolvedValue(50055)

server.use(
// Mock groups check - group doesn't exist
http.get(mswEndpoint('/api/v1beta/groups'), () =>
HttpResponse.json({ groups: [] })
),
http.get(mswEndpoint('/api/v1beta/workloads/:name'), () =>
HttpResponse.json({ error: 'Workload not found' }, { status: 404 })
),
// Both mcp-optimizer and meta-mcp return null (not found)
http.get(
mswEndpoint('/api/v1beta/registry/:name/servers/:serverName'),
({ params }) => {
if (params.serverName === 'mcp-optimizer') {
return HttpResponse.json(
{ error: 'Server not found' },
{ status: 404 }
)
}
// meta-mcp also returns null
return HttpResponse.json({ server: null })
}
)
)

await initMetaOptimizer()

expect(log.info).toHaveBeenCalledWith(
'[createMetaOptimizerWorkload] Server not found in the registry'
)
})
})
})
11 changes: 11 additions & 0 deletions renderer/src/common/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,14 @@ export const MCP_OPTIMIZER_GROUP_NAME = '__mcp-optimizer__'
export const META_MCP_SERVER_NAME = 'internal---meta-mcp'
export const ALLOWED_GROUPS_ENV_VAR = 'ALLOWED_GROUPS'
export const MCP_OPTIMIZER_REGISTRY_SERVER_NAME = 'mcp-optimizer'

/**
* Determines if the platform is probably using native containers.
* Native containers mean Docker runs directly on the host OS (Linux),
* as opposed to running in a VM (macOS/Windows with Docker Desktop).
* When native containers are used, host networking mode allows direct
* access to the host's network stack.
*/
export function isProbablyUsingNativeContainers(): boolean {
return window.electronAPI.isLinux
}
Loading