nuxt-volcano
nuxt-volcano

A Nuxt module for Volcano Agent SDK - build AI agents with LLM reasoning and MCP tools

Volcano

nuxt-volcano

Nuxt module for the Volcano Agent SDK — build AI agents that combine LLM reasoning with real-world actions via MCP tools.

Features

  • 🔒 Server-side only: API keys stay safe in runtime config
  • 🔌 Auto-imports: useVolcanoAgent(), useVolcanoLLM(), agent(), and mcp() available in server routes
  • 💬 Client composable: useVolcanoChat() for building chat UIs with streaming support
  • 🌊 SSE streaming: defineVolcanoStreamHandler() streams tokens to the browser in real-time
  • 🤖 Multi-provider: OpenAI, Anthropic, Mistral, Llama, Bedrock, Vertex, Azure
  • Zero config: set an API key env var and go

Quick Setup

Install the module:

npx nuxi module add nuxt-volcano

Add to nuxt.config.ts:

export default defineNuxtConfig({
  modules: ['nuxt-volcano'],
  volcano: {
    defaultProvider: 'openai',
    defaultModel: 'gpt-4o-mini',
  },
})

Set your API key via environment variable:

NUXT_VOLCANO_OPENAI_API_KEY=sk-...

Usage

Server API Route

// server/api/agent.post.ts
export default defineEventHandler(async (event) => {
  const { prompt } = await readBody(event)

  const myAgent = useVolcanoAgent()

  const results = await myAgent
    .then({ prompt })
    .run()

  return { output: results[0]?.llmOutput }
})

With MCP Tools

// server/api/research.post.ts
export default defineEventHandler(async (event) => {
  const { prompt } = await readBody(event)

  const myAgent = useVolcanoAgent()
  const webTools = mcp('http://localhost:3211/mcp')

  const results = await myAgent
    .then({ prompt, mcps: [webTools] })
    .then({ prompt: 'Summarize the findings.' })
    .run()

  return { output: results.at(-1)?.llmOutput }
})

Using a Different Provider Per-Request

const agent = useVolcanoAgent({ provider: 'anthropic', model: 'claude-3-5-sonnet-20241022' })

Direct LLM Access

const llm = useVolcanoLLM({ provider: 'openai', model: 'gpt-4o' })
const response = await llm.gen('Hello!')

Client-Side

useVolcanoChat() Chat UI Composable

A Vue composable for building chat interfaces with optional SSE streaming:

<script setup>
const { messages, input, isLoading, error, send, stop, clear } = useVolcanoChat({
  api: '/api/chat',
  stream: true, // Enable real-time token streaming
  onToken: (token) => console.log(token),
  onFinish: (msg) => console.log('Done:', msg.content),
})
</script>

<template>
  <div v-for="msg in messages" :key="msg.content">
    <strong>{{ msg.role }}:</strong> {{ msg.content }}
  </div>
  <form @submit.prevent="send()">
    <input v-model="input" placeholder="Type a message..." />
    <button v-if="!isLoading" type="submit">Send</button>
    <button v-else type="button" @click="stop()">Stop</button>
  </form>
</template>

Options

OptionTypeDefaultDescription
apistring'/api/agent'Server endpoint URL
streambooleanfalseEnable SSE token streaming
initialMessagesChatMessage[][]Pre-populate chat history
bodyobject--Extra fields sent with every request
headersobject--Extra headers sent with every request
onToken(token: string) => void--Callback per streamed token
onFinish(msg: ChatMessage) => void--Callback when response completes
onError(err: Error) => void--Callback on error

Return Value

PropertyTypeDescription
messagesRef<ChatMessage[]>Reactive message history
inputRef<string>Bound to your text input
isLoadingRef<boolean>True while waiting for a response
errorRef<Error | null>Last error, if any
send(content?)(string?) => PromiseSend a message (uses input if no arg)
stop()() => voidAbort the current request
clear()() => voidReset messages to initial state
setMessages()(msgs) => voidReplace message history

defineVolcanoStreamHandler() SSE Server Endpoint

A server utility that creates an endpoint supporting both JSON and SSE streaming. Automatically detects the Accept: text/event-stream header:

// server/api/chat.post.ts
export default defineVolcanoStreamHandler({
  async handler(event, { prompt, onToken }) {
    const myAgent = useVolcanoAgent()
    const results = await myAgent
      .then({ prompt, onToken })
      .run()
    return results[0]?.llmOutput ?? ''
  },
})
  • With stream: true on the client → SSE response, tokens arrive in real-time
  • Without streaming (regular $fetch) → JSON response { output: "..." }

Configuration

Module Options (nuxt.config.ts)

OptionTypeDefaultDescription
defaultProviderstring'openai'Default LLM provider
defaultModelstring--Default model identifier
instructionsstring--Global system instructions
timeoutnumber60Default step timeout (seconds)
retryRetryConfig--Retry configuration
contextMaxCharsnumber20480Context size limit
contextMaxToolResultsnumber8Tool results in context
maxToolIterationsnumber4Max tool calls per step
disableParallelToolExecutionbooleanfalseForce sequential tool execution
hideProgressbooleanfalseSuppress progress output

Environment Variables

API keys are set via NUXT_VOLCANO_* environment variables:

VariableProvider
NUXT_VOLCANO_OPENAI_API_KEYOpenAI
NUXT_VOLCANO_ANTHROPIC_API_KEYAnthropic
NUXT_VOLCANO_MISTRAL_API_KEYMistral
NUXT_VOLCANO_VERTEX_API_KEYGoogle Vertex
NUXT_VOLCANO_AZURE_API_KEYAzure AI
NUXT_VOLCANO_AZURE_ENDPOINTAzure AI endpoint
NUXT_VOLCANO_BEDROCK_ACCESS_KEY_IDAWS Bedrock
NUXT_VOLCANO_BEDROCK_SECRET_ACCESS_KEYAWS Bedrock
NUXT_VOLCANO_BEDROCK_REGIONAWS Bedrock region

Development

# Install dependencies
pnpm install

# Develop with the playground
pnpm dev

# Run tests
pnpm test

# Build the module
pnpm prepack