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
| Factory | Slug | Domain |
|---|
createAuditServer() | audit | Smart contract security |
createBridgeServer() | bridge | Startup ops (Notion/Linear/Slack) |
createCompeteServer() | compete | Competitive intelligence |
createFeedbackServer() | feedback | Customer feedback / NPS |
createHypeServer() | hype | Growth hacking |
createInvoiceServer() | invoice | Billing / revenue |
createMeetServer() | meet | Meeting intelligence |
createMetricsServer() | metrics | Product analytics |
createObservabilityServer() | observability | Production monitoring |
createPredictServer() | predict | Prediction markets |
createProposeServer() | propose | RFP / proposal engine |
createProspectServer() | prospect | Sales prospecting |
createQuantumServer() | quantum | Bitcoin quantum search |
createRecruitServer() | recruit | ATS / hiring pipeline |
createSeoServer() | seo | SEO intelligence |
createTaxServer() | tax | Crypto tax compliance |
createTradeServer() | trade | Crypto trading |
createVeilleServer() | veille | Content monitoring |
createVideoServer() | video | Video 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.
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
}