Skip to content

Releases: VoltAgent/voltagent

@voltagent/[email protected]

23 Dec 18:18
380a38e

Choose a tag to compare

Patch Changes

  • #883 9320326 Thanks @omeraplak! - feat: add authNext and deprecate legacy auth

    Add a new authNext policy that splits routes into public, console, and user access. All routes are protected by default; use publicRoutes to opt out.

    AuthNext example:

    import { jwtAuth } from "@voltagent/server-core";
    import { honoServer } from "@voltagent/server-hono";
    
    const server = honoServer({
      authNext: {
        provider: jwtAuth({ secret: process.env.JWT_SECRET! }),
        publicRoutes: ["GET /health"],
      },
    });

    Behavior summary:

    • When authNext is set, all routes are private by default.
    • Console endpoints (agents, workflows, tools, docs, observability, updates) require a Console Access Key.
    • Execution endpoints require a user token (JWT).

    Console access uses VOLTAGENT_CONSOLE_ACCESS_KEY:

    VOLTAGENT_CONSOLE_ACCESS_KEY=your-console-key
    curl http://localhost:3141/agents \
      -H "x-console-access-key: your-console-key"

    Legacy auth remains supported but is deprecated. Use authNext for new integrations.

  • Updated dependencies [9320326]:

@voltagent/[email protected]

23 Dec 18:18
380a38e

Choose a tag to compare

Patch Changes

  • #883 9320326 Thanks @omeraplak! - feat: add authNext and deprecate legacy auth

    Add a new authNext policy that splits routes into public, console, and user access. All routes are protected by default; use publicRoutes to opt out.

    AuthNext example:

    import { jwtAuth } from "@voltagent/server-core";
    import { honoServer } from "@voltagent/server-hono";
    
    const server = honoServer({
      authNext: {
        provider: jwtAuth({ secret: process.env.JWT_SECRET! }),
        publicRoutes: ["GET /health"],
      },
    });

    Behavior summary:

    • When authNext is set, all routes are private by default.
    • Console endpoints (agents, workflows, tools, docs, observability, updates) require a Console Access Key.
    • Execution endpoints require a user token (JWT).

    Console access uses VOLTAGENT_CONSOLE_ACCESS_KEY:

    VOLTAGENT_CONSOLE_ACCESS_KEY=your-console-key
    curl http://localhost:3141/agents \
      -H "x-console-access-key: your-console-key"

    Legacy auth remains supported but is deprecated. Use authNext for new integrations.

@voltagent/[email protected]

22 Dec 17:07
7c4a849

Choose a tag to compare

Patch Changes

@voltagent/[email protected]

22 Dec 17:07
7c4a849

Choose a tag to compare

Patch Changes

  • b663dce Thanks @omeraplak! - fix: dedupe MCP endpoints in server startup output and include MCP transport paths (streamable HTTP/SSE) so the actual server endpoint is visible.

  • Updated dependencies [b663dce]:

@voltagent/[email protected]

22 Dec 17:07
7c4a849

Choose a tag to compare

Patch Changes

  • b663dce Thanks @omeraplak! - fix: dedupe MCP endpoints in server startup output and include MCP transport paths (streamable HTTP/SSE) so the actual server endpoint is visible.

@voltagent/[email protected]

20 Dec 18:34

Choose a tag to compare

Minor Changes

  • #879 2f81e6d Thanks @omeraplak! - feat: add VoltAgentRagRetriever to @voltagent/core

    Added VoltAgentRagRetriever - a built-in retriever that connects to VoltAgent Knowledge Bases for fully managed RAG. No infrastructure setup required - just upload documents to the Console and start searching.

    Features

    • Automatic context injection: Searches before each response and injects relevant context
    • Tool-based retrieval: Use as a tool that the agent calls when needed
    • Tag filtering: Filter results by custom document tags
    • Source tracking: Access retrieved chunk references via rag.references context

    Usage

    import { Agent, VoltAgentRagRetriever } from "@voltagent/core";
    import { openai } from "@ai-sdk/openai";
    
    const retriever = new VoltAgentRagRetriever({
      knowledgeBaseName: "my-docs",
      topK: 8,
      includeSources: true,
    });
    
    // Option 1: Automatic context injection
    const agent = new Agent({
      name: "RAG Assistant",
      model: openai("gpt-4o-mini"),
      retriever,
    });
    
    // Option 2: Tool-based retrieval
    const agentWithTool = new Agent({
      name: "RAG Assistant",
      model: openai("gpt-4o-mini"),
      tools: [retriever.tool],
    });

    Configuration

    Option Default Description
    knowledgeBaseName required Name of your knowledge base
    topK 8 Number of chunks to retrieve
    tagFilters null Filter by document tags
    includeSources true Include document metadata
    includeSimilarity false Include similarity scores

    Environment Variables

    VOLTAGENT_PUBLIC_KEY=pk_...
    VOLTAGENT_SECRET_KEY=sk_...
    # Optional
    VOLTAGENT_API_BASE_URL=https://api.voltagent.dev

@voltagent/[email protected]

17 Dec 16:30
10c1079

Choose a tag to compare

Patch Changes

@voltagent/[email protected]

17 Dec 22:30
fd7dd72

Choose a tag to compare

Minor Changes

  • #875 93c52cc Thanks @omeraplak! - feat: add MCP client elicitation support for user input handling

    Added support for handling elicitation requests from MCP servers. When an MCP server needs user input during tool execution (e.g., confirmation dialogs, credentials, or form data), you can now dynamically register handlers to process these requests.

    New API

    Access the elicitation bridge via mcpClient.elicitation:

    const clients = await mcpConfig.getClients();
    
    // Set a persistent handler
    clients.myServer.elicitation.setHandler(async (request) => {
      console.log("Server asks:", request.message);
      console.log("Expected schema:", request.requestedSchema);
    
      const userConfirmed = await promptUser(request.message);
    
      return {
        action: userConfirmed ? "accept" : "decline",
        content: userConfirmed ? { confirmed: true } : undefined,
      };
    });
    
    // One-time handler (auto-removes after first call)
    clients.myServer.elicitation.once(async (request) => {
      return { action: "accept", content: { approved: true } };
    });
    
    // Remove handler
    clients.myServer.elicitation.removeHandler();
    
    // Check if handler exists
    if (clients.myServer.elicitation.hasHandler) {
      console.log("Handler registered");
    }

    Agent-Level Elicitation

    Pass elicitation handler directly to generateText or streamText:

    const response = await agent.generateText("Do something with MCP", {
      userId: "user123",
      elicitation: async (request) => {
        // Handler receives elicitation request from any MCP tool
        const confirmed = await askUser(request.message);
        return {
          action: confirmed ? "accept" : "decline",
          content: confirmed ? { confirmed: true } : undefined,
        };
      },
    });

    This handler is automatically applied to all MCP tools during the request.

    Key Features

    • Dynamic handler management: Add, replace, or remove handlers at runtime
    • One-time handlers: Use .once() for handlers that auto-remove after first invocation
    • Method chaining: All methods return this for fluent API usage
    • Auto-cancellation: Requests without handlers are automatically cancelled
    • Agent-level integration: Pass handler via generateText/streamText options
    • Full MCP SDK compatibility: Uses ElicitRequest and ElicitResult types from @modelcontextprotocol/sdk

    Exports

    New exports from @voltagent/core:

    • MCPClient - MCP client with elicitation support
    • UserInputBridge - Bridge class for handler management
    • UserInputHandler - Handler function type

@voltagent/[email protected]

17 Dec 20:15
89e63e9

Choose a tag to compare

Minor Changes

  • #870 63cade8 Thanks @omeraplak! - feat: add authorization layer for MCP tools

    Add a can function to MCPConfiguration that lets you control which MCP tools users can discover and execute. Supports both tool discovery filtering and execution-time checks.

    Usage

    import { MCPConfiguration, type MCPCanParams } from "@voltagent/core";
    
    const mcp = new MCPConfiguration({
      servers: {
        expenses: { type: "http", url: "http://localhost:3142/mcp" },
      },
      authorization: {
        can: async ({ toolName, action, userId, context }: MCPCanParams) => {
          const roles = (context?.get("roles") as string[]) ?? [];
    
          // action is "discovery" (getTools) or "execution" (tool call)
          if (toolName === "delete_expense" && !roles.includes("admin")) {
            return { allowed: false, reason: "Admin only" };
          }
    
          return true;
        },
        filterOnDiscovery: true, // Hide unauthorized tools from tool list
        checkOnExecution: true, // Verify on each tool call
      },
    });
    
    // Get tools filtered by user's permissions
    const tools = await mcp.getTools({
      userId: "user-123",
      context: { roles: ["manager"] },
    });

    MCPCanParams

    interface MCPCanParams {
      toolName: string; // Tool name (without server prefix)
      serverName: string; // MCP server identifier
      action: "discovery" | "execution"; // When the check is happening
      arguments?: Record<string, unknown>; // Tool arguments (execution only)
      userId?: string;
      context?: Map<string | symbol, unknown>;
    }

    Cerbos Integration

    For production use with policy-based authorization:

    import { GRPC } from "@cerbos/grpc";
    
    const cerbos = new GRPC("localhost:3593", { tls: false });
    
    const mcp = new MCPConfiguration({
      servers: { expenses: { type: "http", url: "..." } },
      authorization: {
        can: async ({ toolName, serverName, userId, context }) => {
          const roles = (context?.get("roles") as string[]) ?? ["user"];
    
          const result = await cerbos.checkResource({
            principal: { id: userId ?? "anonymous", roles },
            resource: { kind: `mcp::${serverName}`, id: serverName },
            actions: [toolName],
          });
    
          return { allowed: result.isAllowed(toolName) ?? false };
        },
        filterOnDiscovery: true,
        checkOnExecution: true,
      },
    });

    See the full Cerbos example: examples/with-cerbos

@voltagent/[email protected]

15 Dec 18:47
56e5089

Choose a tag to compare

Patch Changes

  • #865 77833b8 Thanks @omeraplak! - fix: make GET /tools endpoint public when auth is enabled

    Previously, GET /tools was listed in PROTECTED_ROUTES, requiring authentication even though it only returns tool metadata (name, description, parameters). This was inconsistent with GET /agents and GET /workflows which are publicly accessible for discovery.

    Changes

    • Moved GET /tools from PROTECTED_ROUTES to DEFAULT_PUBLIC_ROUTES
    • Tool execution (POST /tools/:name/execute) remains protected and requires authentication

    This allows VoltOps Console and other clients to discover available tools without authentication, while still requiring auth to actually execute them.