npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

hugin-agent

v0.1.18

Published

Hugin — AI personal assistant powered by MCP and any OpenAI-compatible LLM

Readme

Hugin banner

Hugin

Hugin is an AI personal assistant built on Spring Boot that connects to Model Context Protocol (MCP) servers and lets an OpenAI-schema LLM use their tools to answer prompts. The LLM backend is pluggable — point it at any hosted provider such as OpenRouter (see LLM provider).

Getting started

Clone the repo and install the Hugin CLI:

git clone https://github.com/jeremyunck/mcp-client.git && cd mcp-client
npm install && npm install -g .

Then run the interactive setup:

hugin onboard

Onboarding will:

  • Install Java 21 (Temurin), git, and Maven if missing
  • Prompt for your OpenRouter API key (required — used for LLM + web search)
  • Prompt for a Redis host for long-term memory (leave blank to skip)
  • Build the fat jars, create ~/.hugin/, and register a systemd service that starts on boot

From then on, one command opens the chat:

hugin        # starts the service if needed, waits for health, opens terminal

The agent server is always available on :8080 for direct API access too:

curl -X POST http://localhost:8080/api/agent/chat \
  -H "Content-Type: application/json" \
  -d '{"prompt": "What can you do?"}'

Commands

| Command | Description | |---|---| | hugin | Ensure server is running, then open terminal chat | | hugin onboard | Run the interactive setup wizard | | hugin server run | Run the server in the foreground (no systemd) | | hugin server start / stop / restart / status | Manage the background service | | hugin server logs | Stream service logs (journalctl -f) | | hugin terminal | Launch the terminal client directly |

Set AGENT_HOME to override the default install location (~/.hugin).

Prerequisites

  • Java 21 and Maven
  • An OpenAI-compatible LLM endpoint with a tool-calling model. OpenRouter is recommended — set OPEN_ROUTER_API_KEY.
  • Runtimes for the MCP servers you configure. The default mcp-servers.json uses:
    • uvx (uv) for the time server
    • python3 for the web search server (when search.provider=openrouter, the default)
  • (Optional) Redis — only needed if you enable long-term memory. Any Redis 6+ works; no modules required.

Configure MCP servers

Servers are declared in mcp-servers.json (repo root) using the standard Claude Desktop format. This file is gitignored so your local server list stays private — create it by copying the committed example:

cp mcp-servers.example.json mcp-servers.json

mcp-servers.example.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
      "env": {}
    },
    "time": {
      "command": "uvx",
      "args": ["mcp-server-time"],
      "env": {}
    }
  }
}

Stdio servers use command / args / env; SSE/HTTP servers use url / headers. Servers can also be managed at runtime through the /api/servers REST API.

Stdio servers do not inherit your shell environment — pass API keys and other config through each server's env block. mcp-servers.json is gitignored so secrets placed there stay local.

Build

mvn clean install

Run

Start the agent server:

mvn -pl mcp-integration spring-boot:run

The server starts on port 8080. agent-core and mcp-client are libraries.

Terminal front-end

agent-terminal is an interactive terminal client — think Claude Code. With the server running, start it in another shell:

mvn -pl agent-terminal spring-boot:run

Type a prompt and the answer streams back token-by-token in real time; tool calls the agent makes are shown inline. Built-in commands:

  • /help — show help
  • /model [name] — show or change the model used for new prompts
  • /exit (also /quit, exit, quit, or Ctrl-D) — quit

Configure it via the terminal block in agent-terminal/src/main/resources/application.yml (or environment variables):

| Key | Env var | Description | Default | | --- | --- | --- | --- | | terminal.server-url | AGENT_SERVER_URL | Base URL of the running server | http://localhost:8080 | | terminal.api-key | AGENT_API_KEY | Sent as X-API-Key; needed only if the server sets agent.api-key | (blank) | | terminal.model | AGENT_MODEL | Default model; blank lets the server pick llm.model | (blank) |

Usage

Send a prompt to the agent (non-streaming):

curl -X POST http://localhost:8080/api/agent/chat \
  -H "Content-Type: application/json" \
  -d '{"prompt": "What time is it in Tokyo?"}'

Or stream the response as Server-Sent Events (this is what the terminal uses):

curl -N -X POST http://localhost:8080/api/agent/stream \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"prompt": "What time is it in Tokyo?"}'

model is optional and falls back to llm.model from configuration.

Manage MCP servers at runtime:

curl http://localhost:8080/api/servers                 # list servers + connection status
curl http://localhost:8080/api/servers/time/tools      # list a server's tools
curl -X POST http://localhost:8080/api/servers/time/reconnect

LLM provider

The agent talks to any OpenAI-schema /chat/completions endpoint. Providers are declared under llm.providers in application.yml, and llm.provider selects the active one:

llm:
  provider: openrouter
  model: openai/gpt-oss-120b        # default model for the active provider
  providers:
    openrouter:
      base-url: https://openrouter.ai/api/v1
      api-key: ${OPEN_ROUTER_API_KEY:}       # sent as Authorization: Bearer <key>

OpenRouter authenticates with an Authorization: Bearer <api-key> header (OpenRouter auth docs). Provide the key via the OPEN_ROUTER_API_KEY environment variable.

To add another OpenAI-compatible provider, add an entry under llm.providers with its base-url and (optionally) api-key, then point llm.provider at it.

Web search

Web search is a built-in local tool (web_search) that calls perplexity/sonar via OpenRouter for real-time results. It activates automatically when OPEN_ROUTER_API_KEY is set and agent.tools.enabled is true (the default). No extra runtime dependencies are required.

Google Docs & Sheets

Hugin can create, read, and edit Google Docs and Sheets through seven built-in local tools backed by the official Google API Java client libraries: google_docs_create, google_docs_read, google_docs_edit, google_sheets_create, google_sheets_read, google_sheets_write, and google_sheets_append.

Authentication uses a Google service account (the recommended method for a headless server):

  1. In a Google Cloud project, enable the Google Docs, Sheets, and Drive APIs.
  2. Create a service account and download its JSON key.
  3. Set GOOGLE_APPLICATION_CREDENTIALS to the key's path (or google.credentials-file in application.yml).
  4. Share the docs/sheets you want Hugin to access with the service account's client_email. Files Hugin creates are owned by the service account, so pass a share_with email (or set GOOGLE_DEFAULT_SHARE_WITH) to make them visible to a person.

When no credentials are configured the tools report themselves as unavailable rather than failing startup. Workspace domains can use domain-wide delegation via GOOGLE_IMPERSONATE_USER. See docs/skills/google-docs-sheets for usage details and the Configuration table for the google.* settings.

Long-term memory

The agent can keep a Redis-backed long-term memory of past conversations using text embeddings. It is disabled by default. When enabled, every finished exchange (the prompt and the agent's final answer) is embedded and stored in Redis; on each new request the most similar past memories are recalled and injected into the prompt as extra context, so the agent can remember things across requests and restarts.

Similarity search runs in-process (cosine similarity over the stored vectors), so it works against plain Redis — no RediSearch or vector modules required.

To enable: start a Redis instance, set OPEN_ROUTER_API_KEY (used for embeddings), then start the server with MEMORY_ENABLED=true. See the Configuration table for all tunables (memory.*, embedding.*, spring.data.redis.*). Embedding and store failures are non-fatal — the agent logs a warning and continues without memory.

Configuration

Settings live in mcp-integration/src/main/resources/application.yml:

| Key | Description | Default | | --- | --- | --- | | llm.provider | Active provider; must match a key under llm.providers | openrouter | | llm.model | Default model when a request omits one (must support tool calling) | openai/gpt-oss-120b | | llm.providers.<name>.base-url | OpenAI-compatible API root (the part before /chat/completions) | (per provider) | | llm.providers.<name>.api-key | Optional; when set, sent as Authorization: Bearer <key> | (blank) | | mcp.config-file | Path to the MCP servers JSON (supports ~/) | ./mcp-servers.json | | agent.api-key | If set, /api/agent/** requires the X-API-Key header; if blank, those endpoints are open | (blank) | | agent.request-timeout | Per-request wall-clock budget for the agent loop | 5m | | google.credentials-file | Path to a Google service-account JSON key enabling the google_docs_*/google_sheets_* tools | ${GOOGLE_APPLICATION_CREDENTIALS:} | | google.application-name | Application name reported to the Google APIs | Hugin | | google.impersonate-user | Optional user email to impersonate via domain-wide delegation | ${GOOGLE_IMPERSONATE_USER:} | | google.default-share-with | Optional email that newly created docs/sheets are auto-shared with | ${GOOGLE_DEFAULT_SHARE_WITH:} | | memory.enabled | Enable Redis-backed long-term memory (see Long-term memory) | false | | memory.key-prefix | Redis key prefix for stored memory records | agent:memory | | memory.top-k | Number of most-similar past memories recalled into the prompt | 3 | | memory.min-score | Minimum cosine similarity (0..1) to recall a memory; 0 disables the threshold | 0.75 | | memory.max-entries | Cap on stored memories; oldest are evicted past this | 1000 | | embedding.base-url | OpenAI-schema embeddings API root (before /embeddings) | https://openrouter.ai/api/v1 | | embedding.api-key | Optional; when set, sent as Authorization: Bearer <key> | ${OPEN_ROUTER_API_KEY:} | | embedding.model | Model used specifically for embedding text | openai/text-embedding-3-small | | spring.data.redis.host / .port | Redis connection (only used when memory.enabled) | localhost / 6379 |