Skip to main content

Overview

@raijinlabs/lucid-skills-embedded bundles all 18 Lucid Skills as MCP server factories. Using the included EmbeddedRegistry, you can run them in-process via InMemoryTransport — tool calls execute in ~1-5ms with no HTTP round-trips.

Installation

npm install @raijinlabs/lucid-skills-embedded @modelcontextprotocol/sdk
@modelcontextprotocol/sdk is a peer dependency. It provides the InMemoryTransport and Client classes used internally.

Quick Start

import {
  EmbeddedRegistry,
  createTradeServer,
  createPredictServer,
} from '@raijinlabs/lucid-skills-embedded'

// Create a registry and register the skills you need
const registry = new EmbeddedRegistry()
registry.register(createTradeServer(), 'trade')
registry.register(createPredictServer(), 'predict')

// Call tools — the MCP client connects lazily on first use
const result = await registry.callTool('trade', 'analyze_market', {
  symbol: 'BTC',
})

console.log(result.content)
// [{ type: 'text', text: '## Market Analysis for BTC\n...' }]
console.log(result.isError) // false

// Clean up when your process shuts down
await registry.closeAll()

Available Skills

FactorySlugDomain
createAuditServer()auditSmart contract security
createBridgeServer()bridgeStartup ops (Notion/Linear/Slack)
createCompeteServer()competeCompetitive intelligence
createFeedbackServer()feedbackCustomer feedback / NPS
createHypeServer()hypeGrowth hacking
createInvoiceServer()invoiceBilling / revenue
createMeetServer()meetMeeting intelligence
createMetricsServer()metricsProduct analytics
createObservabilityServer()observabilityProduction monitoring
createPredictServer()predictPrediction markets
createProposeServer()proposeRFP / proposal engine
createProspectServer()prospectSales prospecting
createQuantumServer()quantumBitcoin quantum search
createRecruitServer()recruitATS / hiring pipeline
createSeoServer()seoSEO intelligence
createTaxServer()taxCrypto tax compliance
createTradeServer()tradeCrypto trading
createVeilleServer()veilleContent monitoring
createVideoServer()videoVideo generation

Registry API

register(server, name)

Register an MCP server factory output. Does not connect immediately — the client is created lazily on the first callTool.

callTool(serverName, toolName, args?)

Execute a tool on a registered server. Returns { content: unknown[], isError: boolean }.
const { content, isError } = await registry.callTool(
  'audit',
  'analyze_contract',
  { address: '0x...' }
)

has(name) / size

Check if a server is registered, or get the total count.

list()

Returns server status for health checks:
registry.list()
// [
//   { name: 'trade', connected: true, connectedAt: 1709500000000 },
//   { name: 'predict', connected: false },
// ]

closeAll()

Close all MCP clients and clear the registry. Call this during graceful shutdown.

How It Works

Your App
  └── EmbeddedRegistry
        └── register(createTradeServer(), 'trade')

              ├── First callTool('trade', ...)
              │     └── InMemoryTransport.createLinkedPair()
              │           ├── serverTransport → McpServer.connect()
              │           └── clientTransport → Client.connect()
              │                 └── client.callTool() → result (~1-5ms)

              └── Subsequent callTool('trade', ...)
                    └── Reuses existing client → result (~1-5ms)
Each createXxxServer() returns a bare McpServer from @modelcontextprotocol/sdk. The registry connects to it via InMemoryTransport — a zero-copy in-process pipe. No HTTP, no serialization, no network.

Integration with AI Frameworks

Vercel AI SDK

import { generateText } from 'ai'
import { EmbeddedRegistry, createTradeServer } from '@raijinlabs/lucid-skills-embedded'

const registry = new EmbeddedRegistry()
registry.register(createTradeServer(), 'trade')

// Use as a tool in your AI pipeline
const result = await generateText({
  model: yourModel,
  tools: {
    analyze_market: {
      description: 'Analyze crypto market data',
      parameters: z.object({ symbol: z.string() }),
      execute: async ({ symbol }) => {
        const { content } = await registry.callTool('trade', 'analyze_market', { symbol })
        return content.map((c: any) => c.text).join('\n')
      },
    },
  },
  prompt: 'Analyze the current BTC market',
})

Error Handling

Tool errors are returned in the response rather than thrown:
const { content, isError } = await registry.callTool('trade', 'bad_tool', {})

if (isError) {
  console.error('Tool failed:', content)
}
Connection errors (e.g., server not registered) throw immediately:
try {
  await registry.callTool('nonexistent', 'tool', {})
} catch (err) {
  // Error: Embedded server not found: nonexistent
}