AI Assistant Integration

Learn how to connect AI assistants to Lokus using the Model Context Protocol (MCP).

Supported AI Assistants

Lokus’s MCP implementation works with any AI assistant that supports the MCP protocol:

  • Desktop AI assistants
  • Web-based AI tools
  • Custom AI integrations
  • IDE extensions with AI capabilities

Connection Methods

Method 1: Stdio Transport

For local AI assistants that communicate via standard input/output:

import { StdioTransport, MCPClient } from '@lokus/mcp'
 
// Start Lokus MCP server
const transport = new StdioTransport({
  command: 'lokus',
  args: ['mcp', 'server'],
  env: process.env
})
 
// Connect client
const client = new MCPClient('ai-assistant')
await client.connect(transport, {
  name: 'My AI Assistant',
  version: '1.0.0'
})
 
// Use Lokus capabilities
const resources = await client.listResources()
const result = await client.callTool('note.create', {
  title: 'AI Generated Note',
  content: 'Content from AI'
})

Method 2: WebSocket Transport

For remote or web-based AI assistants:

import { WebSocketTransport, MCPClient } from '@lokus/mcp'
 
// Connect to Lokus WebSocket server
const transport = new WebSocketTransport({
  url: 'ws://localhost:3000/mcp',
  protocols: ['mcp-v1']
})
 
const client = new MCPClient('web-ai-assistant')
await client.connect(transport)

Method 3: HTTP/REST Transport

For REST API-based integrations:

import { HTTPTransport, MCPClient } from '@lokus/mcp'
 
const transport = new HTTPTransport({
  baseURL: 'http://localhost:3000/mcp',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
})
 
const client = new MCPClient('rest-ai')
await client.connect(transport)

Configuration Examples

Desktop AI Assistant

Configuration for a desktop AI application:

{
  "mcpServers": {
    "lokus": {
      "command": "lokus",
      "args": ["mcp", "server"],
      "transport": "stdio",
      "autoStart": true,
      "description": "Lokus note-taking application"
    }
  }
}

VS Code Extension

Integrate with VS Code-based AI extensions:

// extension.js
import * as vscode from 'vscode'
import { MCPClient } from '@lokus/mcp'
 
export async function activate(context) {
  // Create MCP client
  const client = new MCPClient('vscode-ai')
 
  // Connect to Lokus
  await client.connect(transport)
 
  // Register commands
  context.subscriptions.push(
    vscode.commands.registerCommand('ai.createNote', async () => {
      const title = await vscode.window.showInputBox({
        prompt: 'Note title'
      })
 
      const result = await client.callTool('note.create', {
        title,
        content: ''
      })
 
      vscode.window.showInformationMessage(`Created: ${result.noteId}`)
    })
  )
}

Web Application

Integrate MCP into a web-based AI assistant:

// ai-web-app.js
import { MCPClient } from '@lokus/mcp'
 
class AIWebApp {
  async connect() {
    this.mcpClient = new MCPClient('web-app')
 
    await this.mcpClient.connect(new WebSocketTransport({
      url: 'ws://localhost:3000/mcp'
    }))
 
    // Subscribe to resource updates
    this.mcpClient.on('resource-updated', (event) => {
      this.updateUI(event)
    })
  }
 
  async generateNote(prompt) {
    // Get context from Lokus
    const currentNote = await this.mcpClient.readResource('lokus://notes/current')
    const relatedNotes = await this.mcpClient.callTool('note.search', {
      query: prompt,
      limit: 5
    })
 
    // Generate content with AI
    const content = await this.aiModel.generate({
      prompt,
      context: {
        currentNote: currentNote.contents[0].text,
        relatedNotes: relatedNotes.results
      }
    })
 
    // Create note in Lokus
    return await this.mcpClient.callTool('note.create', {
      title: 'AI Generated',
      content
    })
  }
}

Common Integration Patterns

Pattern 1: Context-Aware Generation

Use Lokus resources as context for AI generation:

async function generateWithContext(aiClient, mcpClient, prompt) {
  // Gather context from Lokus
  const context = {
    currentNote: await mcpClient.readResource('lokus://notes/current'),
    recentNotes: await mcpClient.callTool('note.search', {
      query: '',
      limit: 10
    }),
    workspace: await mcpClient.readResource('lokus://workspace/info')
  }
 
  // Generate with AI
  const response = await aiClient.generate({
    prompt,
    context: JSON.stringify(context, null, 2)
  })
 
  // Save result to Lokus
  await mcpClient.callTool('note.create', {
    title: 'AI Generated',
    content: response.text
  })
 
  return response
}

Pattern 2: Tool-Augmented AI

Let AI execute Lokus tools:

async function toolAugmentedAI(aiClient, mcpClient, userQuery) {
  // Get available tools
  const tools = await mcpClient.listTools()
 
  // Let AI choose which tools to use
  const plan = await aiClient.planActions({
    query: userQuery,
    availableTools: tools.tools
  })
 
  // Execute planned tools
  const results = []
  for (const action of plan.actions) {
    const result = await mcpClient.callTool(action.tool, action.args)
    results.push(result)
  }
 
  // Generate final response
  return await aiClient.synthesize({
    query: userQuery,
    toolResults: results
  })
}

Pattern 3: Interactive Editing

AI-assisted editing with real-time updates:

class InteractiveEditor {
  constructor(mcpClient) {
    this.mcpClient = mcpClient
 
    // Subscribe to changes
    mcpClient.on('resource-updated', (event) => {
      if (event.uri === 'lokus://notes/current') {
        this.onNoteChange(event.content)
      }
    })
  }
 
  async suggestImprovements() {
    const note = await this.mcpClient.readResource('lokus://notes/current')
 
    const prompt = await this.mcpClient.getPrompt('note.improve', {
      title: note.metadata.title,
      content: note.contents[0].text
    })
 
    const suggestions = await this.ai.generate(prompt.messages)
 
    return suggestions
  }
 
  async applyImprovement(suggestion) {
    const note = await this.mcpClient.readResource('lokus://notes/current')
 
    const improved = await this.ai.applyEdit({
      original: note.contents[0].text,
      instruction: suggestion
    })
 
    await this.mcpClient.callTool('note.update', {
      noteId: note.metadata.noteId,
      content: improved
    })
  }
}

Security Considerations

Authentication

Secure your MCP server:

import { MCPServer } from '@lokus/mcp'
 
const server = new MCPServer({
  authentication: {
    type: 'token',
    validateToken: async (token) => {
      return await this.tokenStore.validate(token)
    }
  }
})
 
// Client includes token
const client = new MCPClient('ai-assistant', {
  authentication: {
    token: 'your-api-token'
  }
})

Permission Scoping

Limit what AI assistants can access:

const server = new MCPServer({
  authorization: {
    resources: {
      'lokus://notes/current': ['read'],
      'lokus://notes/all': ['read'],
      'lokus://admin/*': [] // Deny admin resources
    },
    tools: {
      'note.create': true,
      'note.search': true,
      'note.delete': false // Prevent deletion
    }
  }
})

Audit Logging

Track AI assistant actions:

mcpServer.on('tool-called', (event) => {
  console.log('Audit log:', {
    timestamp: new Date().toISOString(),
    client: event.clientId,
    tool: event.toolName,
    args: event.args,
    result: event.result
  })
})

Best Practices

1. Connection Management

  • Implement reconnection logic
  • Handle connection errors gracefully
  • Use keep-alive for long sessions
  • Clean up resources on disconnect

2. Resource Usage

  • Cache frequently accessed resources
  • Use subscriptions for live updates
  • Batch operations when possible
  • Implement rate limiting

3. Error Handling

  • Validate tool inputs
  • Provide helpful error messages
  • Implement retry logic
  • Log errors for debugging

4. User Experience

  • Show loading states
  • Provide progress updates
  • Allow cancellation
  • Display clear feedback

Example: Complete AI Assistant

import { MCPClient, StdioTransport } from '@lokus/mcp'
 
class LokusAIAssistant {
  constructor(aiModel) {
    this.aiModel = aiModel
    this.mcpClient = null
  }
 
  async connect() {
    const transport = new StdioTransport({
      command: 'lokus',
      args: ['mcp', 'server']
    })
 
    this.mcpClient = new MCPClient('ai-assistant', {
      autoReconnect: true,
      reconnectDelay: 5000
    })
 
    await this.mcpClient.connect(transport, {
      name: 'Lokus AI Assistant',
      version: '1.0.0'
    })
 
    console.log('Connected to Lokus')
  }
 
  async processQuery(userQuery) {
    // Get relevant context
    const resources = await this.gatherContext(userQuery)
 
    // Get available tools
    const tools = await this.mcpClient.listTools()
 
    // Let AI plan actions
    const plan = await this.aiModel.plan({
      query: userQuery,
      context: resources,
      tools: tools.tools
    })
 
    // Execute plan
    const results = await this.executePlan(plan)
 
    // Generate response
    return await this.aiModel.synthesize({
      query: userQuery,
      context: resources,
      results
    })
  }
 
  async gatherContext(query) {
    // Search relevant notes
    const searchResults = await this.mcpClient.callTool('note.search', {
      query,
      limit: 5
    })
 
    // Get current note
    const currentNote = await this.mcpClient.readResource('lokus://notes/current')
 
    return {
      searchResults: searchResults.results,
      currentNote: currentNote.contents[0].text
    }
  }
 
  async executePlan(plan) {
    const results = []
 
    for (const step of plan.steps) {
      try {
        const result = await this.mcpClient.callTool(step.tool, step.args)
        results.push({
          step: step.id,
          success: true,
          result
        })
      } catch (error) {
        results.push({
          step: step.id,
          success: false,
          error: error.message
        })
      }
    }
 
    return results
  }
 
  async disconnect() {
    if (this.mcpClient) {
      await this.mcpClient.disconnect()
    }
  }
}
 
// Usage
const assistant = new LokusAIAssistant(myAIModel)
await assistant.connect()
 
const response = await assistant.processQuery(
  'Create a summary of my recent project notes'
)
console.log(response)
 
await assistant.disconnect()

Next Steps

Related Documentation: