MCP Setup & Configuration
This guide walks you through setting up MCP (Model Context Protocol) in Lokus, from basic initialization to advanced configuration options.
Quick Start
1. Initialize MCP Integration
The MCP integration is automatically initialized when Lokus starts, but you can manually configure it:
import { initializeMCP, getMCPIntegration } from '@lokus/mcp'
// Initialize with default options
const mcp = await initializeMCP(pluginManager, securityManager)
// Or get the existing integration
const mcp = getMCPIntegration()
2. Basic Server Configuration
Create a simple MCP server plugin:
// manifest.json
{
"id": "my-mcp-server",
"name": "My MCP Server",
"version": "1.0.0",
"main": "index.js",
"type": "mcp-server",
"permissions": [
"mcp:serve",
"mcp:resources:read",
"mcp:tools:execute"
],
"mcp": {
"type": "mcp-server",
"enableResourceSubscriptions": true,
"enableToolExecution": true,
"enablePromptTemplates": true
}
}
// index.js
export default class MyMCPServer {
async activate(context) {
const { mcp } = context
// Register a simple resource
mcp.registerResource({
uri: 'myplugin://hello',
name: 'Hello Resource',
type: 'memory',
mimeType: 'text/plain',
content: 'Hello from MCP!'
})
console.log('MCP server activated')
}
async deactivate() {
// Cleanup happens automatically
}
}
3. Test Your Server
Use the MCP client to test your server:
import { MCPClient } from '@lokus/mcp'
const client = new MCPClient('test-client')
// Connect to your server
await client.connect(transport, {
name: 'Test Client',
version: '1.0.0'
})
// List resources
const resources = await client.listResources()
console.log(resources) // Should include your 'hello' resource
// Read resource
const content = await client.readResource('myplugin://hello')
console.log(content.contents[0].text) // 'Hello from MCP!'
Server Configuration
Server Types
Lokus supports three types of MCP servers:
Internal Servers (Web Workers)
Best for most plugins. Runs in isolated Web Worker for security and performance.
{
"mcp": {
"type": "mcp-server",
"serverType": "internal" // Default
}
}
Pros:
- Secure sandboxing
- No subprocess overhead
- Good performance
- Easy debugging
Cons:
- Limited Node.js API access
- Memory limits apply
External Servers (Subprocess)
For plugins needing full Node.js capabilities or running external executables.
{
"mcp": {
"type": "mcp-server",
"serverType": "external",
"command": "node",
"args": ["./server.js"],
"env": {
"NODE_ENV": "production"
}
}
}
Pros:
- Full Node.js API access
- Can run external programs
- More memory available
Cons:
- Subprocess overhead
- Requires process management
- More resource intensive
Embedded Servers (Main Thread)
Only for simple, trusted plugins. Runs in main thread.
{
"mcp": {
"type": "mcp-server",
"serverType": "embedded"
}
}
Warning: Use with caution. Can block UI if not careful.
Resource Limits
Configure resource constraints for your server:
{
"mcp": {
"memoryLimit": 134217728, // 128MB in bytes
"cpuTimeLimit": 1000, // 1 second per request
"maxConcurrentRequests": 50, // Max parallel requests
"requestTimeout": 30000 // 30 second timeout
}
}
Capabilities Configuration
Declare what your server supports:
{
"mcp": {
"capabilities": {
"resources": {
"subscribe": true, // Support resource subscriptions
"listChanged": true // Notify on resource list changes
},
"tools": {
"listChanged": true // Notify on tool list changes
},
"prompts": {
"listChanged": true // Notify on prompt list changes
},
"logging": {
"enabled": true // Support logging
}
}
}
}
Client Configuration
Creating a Client
import { MCPClient } from '@lokus/mcp'
const client = new MCPClient('my-client', {
// Connection
autoReconnect: true,
reconnectDelay: 5000,
maxReconnectAttempts: 5,
requestTimeout: 30000,
// Caching
enableResourceCaching: true,
resourceCacheTTL: 60000, // 1 minute
enableToolCaching: false, // Tools usually don't need caching
// Performance
maxConcurrentRequests: 10,
requestRetries: 3
})
Transport Configuration
Stdio Transport (for subprocess servers)
import { StdioTransport } from '@lokus/mcp'
const transport = new StdioTransport({
command: 'node',
args: ['./mcp-server.js'],
env: process.env
})
await client.connect(transport)
WebSocket Transport (for remote servers)
import { WebSocketTransport } from '@lokus/mcp'
const transport = new WebSocketTransport({
url: 'ws://localhost:3000/mcp',
protocols: ['mcp-v1'],
reconnect: true
})
await client.connect(transport)
IPC Transport (for internal communication)
import { IPCTransport } from '@lokus/mcp'
const transport = new IPCTransport({
channel: 'mcp-server-1',
timeout: 30000
})
await client.connect(transport)
Environment Configuration
Development Setup
Create a .env.development
file:
# MCP Configuration
MCP_ENABLED=true
MCP_DEBUG=true
MCP_LOG_LEVEL=debug
# Server Configuration
MCP_SERVER_MEMORY_LIMIT=134217728
MCP_SERVER_CPU_LIMIT=1000
MCP_MAX_SERVERS=20
# Client Configuration
MCP_CLIENT_TIMEOUT=30000
MCP_CLIENT_RETRIES=3
MCP_AUTO_RECONNECT=true
Load in your application:
import { loadMCPConfig } from '@lokus/mcp/config'
const config = loadMCPConfig({
env: process.env.NODE_ENV || 'development'
})
const mcp = await initializeMCP(pluginManager, securityManager, config)
Production Setup
Create a .env.production
file:
# MCP Configuration
MCP_ENABLED=true
MCP_DEBUG=false
MCP_LOG_LEVEL=info
# Server Configuration
MCP_SERVER_MEMORY_LIMIT=104857600 # 100MB
MCP_SERVER_CPU_LIMIT=500 # 500ms
MCP_MAX_SERVERS=50
# Security
MCP_REQUIRE_SIGNATURE=true
MCP_SANDBOX_MODE=strict
# Monitoring
MCP_METRICS_ENABLED=true
MCP_HEALTH_CHECK_INTERVAL=5000
Advanced Configuration
Custom Protocol Configuration
import { MCPProtocol } from '@lokus/mcp'
const protocol = new MCPProtocol('custom-server', {
// Protocol options
enableResourceSubscriptions: true,
enableToolExecution: true,
enablePromptTemplates: true,
enableLogging: true,
// Performance
maxConcurrentRequests: 100,
requestTimeout: 60000,
// Caching
cacheResources: true,
cacheTTL: 300000, // 5 minutes
// Validation
validateSchemas: true,
strictMode: true
})
Server Host Configuration
import { MCPServerHost } from '@lokus/mcp'
const serverHost = new MCPServerHost(securityManager, {
// Server limits
maxServers: 50,
serverStartupTimeout: 30000,
serverShutdownTimeout: 10000,
// Health monitoring
healthCheckInterval: 5000,
restartOnCrash: true,
maxRestartAttempts: 3,
// Process isolation
enableProcessIsolation: true,
memoryLimit: 100 * 1024 * 1024, // 100MB
cpuLimit: 1000, // 1 second
// Monitoring
enableMetrics: true,
metricsInterval: 10000
})
await serverHost.initialize()
Plugin Manager Configuration
import { MCPPluginManager } from '@lokus/mcp'
const pluginManager = new MCPPluginManager(basePluginManager, securityManager, {
// Discovery
autoDiscoverMCPPlugins: true,
scanInterval: 30000,
// Activation
lazyActivation: true,
activationTimeout: 10000,
// Global registry
enableGlobalRegistry: true,
indexResources: true,
indexTools: true,
indexPrompts: true,
// Security
requireSignature: true,
allowUnsignedPlugins: false,
// Performance
maxPlugins: 100,
resourceLimit: 200 * 1024 * 1024 // 200MB total
})
await pluginManager.initialize()
Security Configuration
Permission Model
Define granular permissions in your manifest:
{
"permissions": [
// Basic MCP
"mcp:serve",
"mcp:client",
// Resource permissions
"mcp:resources:read",
"mcp:resources:write",
"mcp:resources:subscribe",
// Tool permissions
"mcp:tools:execute",
"mcp:tools:register",
// Prompt permissions
"mcp:prompts:read",
"mcp:prompts:register",
// Specific resource access
"mcp:resource:lokus://notes/*",
"mcp:resource:file://workspace/*",
// Specific tool access
"mcp:tool:filesystem.*",
"mcp:tool:editor.*"
]
}
Sandboxing Configuration
{
"mcp": {
"sandbox": {
"enabled": true,
"mode": "strict", // 'strict' | 'moderate' | 'permissive'
// Memory limits
"memoryLimit": 134217728,
"heapLimit": 100663296,
// CPU limits
"cpuTimeLimit": 1000,
"cpuThrottling": true,
// Network access
"allowNetwork": false,
"allowedDomains": [
"api.example.com"
],
// File system access
"allowFileSystem": false,
"allowedPaths": [
"/workspace/*"
],
// API access
"allowedAPIs": [
"editor",
"workspace"
]
}
}
}
Code Signing
Sign your plugin for production:
# Generate signing key
lokus-plugin sign-key generate --output signing-key.pem
# Sign plugin
lokus-plugin sign \
--plugin ./my-plugin \
--key signing-key.pem \
--output my-plugin.signed.vsix
Configure signature verification:
{
"mcp": {
"requireSignature": true,
"trustedPublishers": [
"lokus-official",
"my-organization"
],
"publicKeys": [
"-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"
]
}
}
Monitoring and Debugging
Enable Logging
import { MCPProtocol } from '@lokus/mcp'
const protocol = new MCPProtocol('my-server', {
enableLogging: true,
logLevel: 'debug' // 'debug' | 'info' | 'warn' | 'error'
})
// Listen to log events
protocol.on('log', (event) => {
console.log(`[${event.level}] ${event.message}`, event.data)
})
Metrics Collection
import { MCPServerHost } from '@lokus/mcp'
const serverHost = new MCPServerHost(securityManager, {
enableMetrics: true,
metricsInterval: 10000
})
// Listen to metrics events
serverHost.on('server-resource-usage', (event) => {
console.log(`Server ${event.serverId}:`)
console.log(` Memory: ${event.usage.memory / 1024 / 1024}MB`)
console.log(` CPU: ${event.usage.cpu}ms`)
console.log(` Requests: ${event.usage.requests}`)
})
Health Checks
import { MCPServerHost } from '@lokus/mcp'
const serverHost = new MCPServerHost(securityManager, {
healthCheckInterval: 5000
})
// Listen to health status
serverHost.on('server-status-changed', (event) => {
console.log(`Server ${event.serverId} status: ${event.status}`)
if (event.status === 'error') {
console.error('Server error detected, attempting restart...')
}
})
// Manual health check
const stats = serverHost.getStats()
console.log(`Healthy servers: ${stats.healthyServers}/${stats.totalServers}`)
Debug Mode
Enable comprehensive debugging:
// Set global debug mode
process.env.MCP_DEBUG = 'true'
// Or configure per component
const client = new MCPClient('debug-client', {
debug: true,
logLevel: 'debug',
traceRequests: true,
traceCommunication: true
})
// Log all communication
client.on('message-sent', (msg) => {
console.log('→', JSON.stringify(msg, null, 2))
})
client.on('message-received', (msg) => {
console.log('←', JSON.stringify(msg, null, 2))
})
client.on('protocol-error', (error) => {
console.error('Protocol error:', error)
console.error('Stack:', error.stack)
})
Testing Configuration
Unit Testing Setup
import { createMockMCPServer, createMockMCPClient } from '@lokus/mcp/testing'
describe('MCP Integration', () => {
let server, client
beforeEach(async () => {
// Create mock server
server = createMockMCPServer({
resources: [
{
uri: 'test://resource',
name: 'Test Resource',
content: 'test data'
}
],
tools: [
{
name: 'testTool',
description: 'Test tool',
inputSchema: { type: 'object' },
execute: async () => ({ success: true })
}
]
})
// Create mock client
client = createMockMCPClient()
await client.connect(server.getTransport())
})
afterEach(async () => {
await client.disconnect()
await server.stop()
})
test('should list resources', async () => {
const resources = await client.listResources()
expect(resources.resources).toHaveLength(1)
expect(resources.resources[0].uri).toBe('test://resource')
})
})
Integration Testing
import { MCPTestHarness } from '@lokus/mcp/testing'
describe('MCP Plugin Integration', () => {
let harness
beforeAll(async () => {
harness = new MCPTestHarness({
plugins: ['./test-plugins/mcp-server-plugin'],
timeout: 10000
})
await harness.start()
})
afterAll(async () => {
await harness.stop()
})
test('plugin should register resources', async () => {
const resources = await harness.listAllResources()
expect(resources).toContainEqual(
expect.objectContaining({
uri: 'myplugin://hello'
})
)
})
test('plugin should execute tools', async () => {
const result = await harness.callTool('myPlugin.testTool', {
arg: 'value'
})
expect(result.isError).toBe(false)
})
})
Common Configuration Patterns
High-Performance Setup
Optimize for maximum throughput:
const mcp = await initializeMCP(pluginManager, securityManager, {
server: {
maxConcurrentRequests: 200,
requestTimeout: 10000,
enableResourceCaching: true,
cacheTTL: 300000
},
client: {
enableResourceCaching: true,
enableToolCaching: true,
maxConcurrentRequests: 50,
requestRetries: 1
},
monitoring: {
enableMetrics: true,
metricsInterval: 30000
}
})
Low-Latency Setup
Optimize for minimal latency:
const mcp = await initializeMCP(pluginManager, securityManager, {
server: {
requestTimeout: 5000,
enableResourceCaching: false, // Always fresh data
enablePreloading: true
},
client: {
enableResourceCaching: false,
requestTimeout: 3000,
maxConcurrentRequests: 10
}
})
High-Security Setup
Maximum security for production:
const mcp = await initializeMCP(pluginManager, securityManager, {
security: {
requireSignature: true,
allowUnsignedPlugins: false,
sandboxMode: 'strict',
validateSchemas: true
},
server: {
enableProcessIsolation: true,
memoryLimit: 50 * 1024 * 1024, // 50MB
cpuLimit: 500, // 500ms
allowNetwork: false,
allowFileSystem: false
},
monitoring: {
enableMetrics: true,
enableHealthChecks: true,
healthCheckInterval: 3000
}
})
Troubleshooting
Server Not Starting
Check server logs:
const serverHost = getMCPIntegration().mcpServerHost
serverHost.on('server-error', (event) => {
console.error(`Server ${event.serverId} error:`, event.error)
})
// Check server status
const server = serverHost.getServer('my-server')
console.log('Status:', server.status)
console.log('Last error:', server.lastError)
Connection Issues
Debug client connection:
client.on('state-changed', (event) => {
console.log(`State: ${event.oldState} → ${event.newState}`)
})
client.on('protocol-error', (error) => {
console.error('Protocol error:', error)
})
// Check connection status
console.log('Client state:', client.state)
console.log('Connection attempts:', client.connectionAttempts)
console.log('Last error:', client.lastConnectionError)
Performance Issues
Profile performance:
const stats = getMCPIntegration().getStats()
console.log('MCP Statistics:')
console.log(' Plugins:', stats.pluginManager.mcpPlugins)
console.log(' Servers:', stats.serverHost.runningServers)
console.log(' Clients:', stats.clients)
// Check resource usage
serverHost.on('server-resource-usage', (event) => {
if (event.usage.memory > 100 * 1024 * 1024) {
console.warn(`High memory usage: ${event.usage.memory / 1024 / 1024}MB`)
}
if (event.usage.cpu > 1000) {
console.warn(`High CPU usage: ${event.usage.cpu}ms`)
}
})
Next Steps
Related Documentation: