Platform-agnostic Model Context Protocol (MCP) integration for LAMA.
mcp.core provides bidirectional MCP integration:
- Inbound MCP: AI assistants in LAMA can use external MCP tools (filesystem, etc.)
- Outbound MCP: External AI assistants (Claude Desktop) can access LAMA functionality
┌─────────────────────────────────────────────────────┐
│ mcp.core │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ MCPManager (Inbound) │ │
│ │ • Connects to external MCP servers │ │
│ │ • Tool discovery and execution │ │
│ │ • Tool call auditability │ │
│ └────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ MCPLamaServer (Outbound) │ │
│ │ • Plan Registry pattern │ │
│ │ • Dynamic tool discovery │ │
│ │ • Meta-tools (discover_plans, call_plan) │ │
│ └────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ Core Tools │ │
│ │ • MemoryTools - LLM memory storage │ │
│ │ • AssemblyTools - Supply/Demand/Plans │ │
│ │ • PlanRegistry - Dynamic plan discovery │ │
│ └────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
mcp.core/
├── src/
│ ├── server/ # MCP server implementations
│ │ ├── MCPManager.ts # Inbound: external tool management
│ │ └── MCPLamaServer.ts # Outbound: LAMA tool exposure
│ ├── tools/ # Tool implementations
│ │ ├── MemoryTools.js # Memory storage and retrieval
│ │ ├── AssemblyTools.js # Supply/Demand/Assembly/Plan ops
│ │ ├── PlanRegistry.ts # Dynamic plan registration
│ │ └── PlanMetaTools.ts # Plan discovery meta-tools
│ ├── interface/ # Tool definitions & execution
│ │ ├── tool-definitions.ts # MCP tool schemas
│ │ ├── tool-executor.ts # Tool execution engine
│ │ └── mcp-tool-interface.ts # Platform abstraction
│ ├── recipes/ # ONE.core data models
│ │ └── mcp-recipes.ts # MCP storage schemas
│ └── types/ # TypeScript definitions
├── README.md # This file
└── MCP-SERVER.md # Standalone server docs (legacy)
Instead of hard-coding tool definitions, mcp.core uses a Plan Registry where:
- Platform implementations (lama.cube, lama.browser) register plan instances
- Plans are platform-agnostic business logic (ChatPlan, ContactsPlan, etc.)
- MCP tools discover and call plan methods dynamically
- No static tool list - everything is discovered at runtime
Example:
import { planRegistry } from '@mcp/core';
// Register a plan instance
planRegistry.registerPlan(
'chat', // Plan name
'messaging', // Category
chatPlanInstance, // Plan instance with methods
'Chat and messaging operations'
);
// MCP clients can now discover and call chat plan methodsInbound (External tools → LAMA AI):
import { mcpManager } from '@mcp/core';
// MCPManager connects to external MCP servers
await mcpManager.init();
// AI assistants can now use tools like:
// - filesystem:read_file
// - filesystem:write_file
// - memory:store
// - assembly:createSupplyOutbound (External AI → LAMA):
import { LamaMCPServer } from '@mcp/core';
// Expose LAMA functionality via MCP
const mcpServer = new LamaMCPServer(nodeOneCore);
await mcpServer.start();
// External clients (Claude Desktop) can now use:
// - discover_plans (see what LAMA can do)
// - call_plan (execute LAMA operations)
// - memory_* (access LAMA memories)External MCP clients discover functionality via meta-tools:
discover_plans- List all available plans and methodscall_plan- Execute a specific plan method- No hard-coded tool list required
Flow:
- Client calls
discover_plans→ sees "chat" plan with "sendMessage" method - Client calls
call_planwith{plan: "chat", method: "sendMessage", params: {...}} - Plan registry routes to ChatPlan.sendMessage()
Used in lama.cube to give AI assistants access to filesystem, memory, etc.
import { mcpManager } from '@mcp/core';
// Initialize in Node.js main process
mcpManager.setNodeOneCore(nodeOneCore);
await mcpManager.init();
// Get available tools
const tools = mcpManager.getAvailableTools();
// Returns: filesystem:read_file, memory:store, assembly:createSupply, etc.
// Execute a tool
const result = await mcpManager.executeTool(
'filesystem:read_file',
{ path: '/path/to/file.txt' }
);
// Store tool call for audit
await mcpManager.storeToolCall({
id: 'tool-call-123',
toolName: 'filesystem:read_file',
parameters: { path: '/path/to/file.txt' },
result,
timestamp: Date.now(),
topicId: 'conversation-id'
});Used in standalone MCP server to expose LAMA to Claude Desktop.
import { LamaMCPServer } from '@mcp/core';
import { planRegistry, registerLamaCorePlans } from '@mcp/core';
// Register plans with the registry
const deps = { nodeOneCore, aiAssistantModel };
registerLamaCorePlans(deps);
// Register platform-specific plans
const chatPlan = new ChatPlan(nodeOneCore);
planRegistry.registerPlan('chat', 'messaging', chatPlan);
// Start MCP server (listens on stdio)
const mcpServer = new LamaMCPServer(nodeOneCore);
await mcpServer.start();
// External clients can now:
// - discover_plans → see chat, contacts, ai, etc.
// - call_plan → execute LAMA operationsFor platform-agnostic tool definitions and execution:
import { MCPToolInterface } from '@mcp/core';
const toolInterface = new MCPToolInterface(mcpServer, nodeOneCore);
// Get tool definitions in MCP format
const tools = toolInterface.getToolDefinitions();
// Execute a tool
const result = await toolInterface.executeTool('memory:store', {
content: 'User prefers dark mode',
category: 'preferences'
});All MCP data stored as versioned ONE.core objects:
{
$type$: 'MCPServer',
name: string, // Server ID
command: string, // Executable
args: string[],
description: string,
enabled: boolean,
createdAt: number,
updatedAt: number
}{
$type$: 'MCPServerConfig',
userEmail: string, // User ID
servers: SHA256IdHash<MCPServer>[],
updatedAt: number
}{
$type$: 'MCPTopicConfig',
topicId: string, // Conversation ID
inboundEnabled: boolean, // AI can use tools
outboundEnabled: boolean, // External access
allowedTools?: string[],
createdAt: number,
updatedAt: number
}{
$type$: 'MCPToolCall',
id: string,
toolName: string,
parameters: string, // JSON
result?: string, // JSON
error?: string,
timestamp: number,
duration?: number,
topicId: string,
messageHash?: string
}Filesystem (28 tools from 2 servers):
filesystem:read_file,filesystem:write_file,filesystem:edit_filefilesystem:list_directory,filesystem:directory_treefilesystem:create_directory,filesystem:move_filefilesystem-home:*(same tools, different root)
Memory (3 tools):
memory:store- Store information for later retrievalmemory:recall- Retrieve stored memoriesmemory:search- Search memories by keyword
Assembly (9 tools):
assembly:createSupply- Create a Supply objectassembly:createDemand- Create a Demand objectassembly:createAssembly- Match Supply and Demandassembly:createPlan- Create execution Planassembly:createStory- Create user Storyassembly:queryAssemblies,assembly:queryPlansassembly:getAssembly,assembly:getPlan
Meta-Tools:
discover_plans- List all available plans and methodscall_plan- Execute a plan method
Memory Tools:
memory_store,memory_recall,memory_searchsubject_extract,subject_search,subject_list
Plans (discovered dynamically via discover_plans):
chat- Send/receive messages, list conversationscontacts- Get/search contactsai- AI model management and generationassembly- Supply/Demand/Assembly/Plan operations- And more...
// main/core/node-one-core.ts
import { mcpManager } from '@mcp/core';
// Initialize MCP manager after ONE.core is ready
mcpManager.setNodeOneCore(nodeOneCore);
await mcpManager.init();
// Register plans for outbound MCP
import { planRegistry } from '@mcp/core';
import { ChatPlan } from '@chat/core/plans/ChatPlan';
const chatPlan = new ChatPlan(nodeOneCore);
planRegistry.registerPlan('chat', 'messaging', chatPlan);// Browser can't run Node.js MCP servers
// But can use HTTP proxy to access LAMA MCP functionality
// (Future implementation)See MCP-SERVER.md for standalone server setup connecting to LAMA API.
- Per-conversation control (MCPTopicConfig)
- Tool calls audited (MCPToolCall storage)
- Tools only execute when explicitly enabled
Current state:
- External MCP clients have FULL ACCESS to all LAMA data
- No per-chat or per-assembly access grants
- No client authentication
- Only use with trusted clients on personal machines
Required for production:
- MCPClientAccess verification (per-chat, per-assembly grants)
- Client authentication with cryptographic verification
- MCPClientAudit logging for all operations
- UI for managing client access grants
- Access revocation support
See lama.cube MCP.md for access control data model and implementation plan.
@modelcontextprotocol/sdk- MCP protocol implementation@refinio/one.core- Storage and versioning
- MCPManager: Requires Node.js (uses child processes via stdio)
- MCPLamaServer: Requires Node.js (uses stdio transport)
- Tools & Interface: Platform-agnostic (can run anywhere)
- lama.cube MCP.md - Detailed MCP integration docs
- lama.cube MCP-QUICKSTART.md - Quick setup guide
- MCP-SERVER.md - Standalone server setup (legacy)
- Model Context Protocol Spec
npm run build# Test inbound MCP
node -e "import('@mcp/core').then(m => m.mcpManager.debugState())"
# Test plan registry
node -e "import('@mcp/core').then(m => console.log(m.planRegistry.getAllPlans()))"Previously, tools were hard-coded in tool definitions. Now:
-
Register plans instead of defining tools:
// Old: Define each tool manually // New: Register plan, tools auto-discovered planRegistry.registerPlan('chat', 'messaging', chatPlan);
-
Use meta-tools for discovery:
// Old: Client needs to know all tools upfront // New: Client calls discover_plans to see what's available
-
Tool execution routes through plan registry:
// Old: Direct tool execution // New: call_plan routes to plan method
Part of the LAMA project.