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

@posara/horizon-mcp

v1.1.2

Published

POSARA Horizon MCP Server — connect any AI assistant to your business data

Readme

POSARA Horizon MCP Server

Connects any MCP-capable AI assistant (Claude Desktop, Claude Code, …) to a POSARA Horizon business: read reports, manage the catalog, control inventory, and raise purchase orders.

Quick Start

  1. In Horizon, open Apps → Horizon MCP → Tokens and generate a token, ticking only the privileges the assistant should have.
  2. Run the server with npx, pointing it at your instance:
HORIZON_API_URL=https://posara-horizon-t1.dcn01.ctdn.dev \
HORIZON_API_KEY=your-mcp-token \
npx @posara/horizon-mcp

This starts the HTTP transport on :3001/mcp by default. For Claude Desktop or other local stdio clients, set MCP_TRANSPORT=stdio instead:

{
  "mcpServers": {
    "posara-horizon": {
      "command": "npx",
      "args": ["-y", "@posara/horizon-mcp"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "HORIZON_API_URL": "https://posara-horizon-t1.dcn01.ctdn.dev",
        "HORIZON_API_KEY": "your-mcp-token"
      }
    }
  }
}

Pass --verbose (or set MCP_LOG_LEVEL=verbose) to log each request and tool call to stderr:

npx @posara/horizon-mcp --verbose

Already on Horizon? You may not need to run anything

Every Horizon deployment already exposes MCP over HTTP at /api/v1/mcp — remote clients (Claude custom connectors, any other remote MCP client) can talk to it directly instead of running this package at all:

POST https://posara-horizon-t1.dcn01.ctdn.dev/api/v1/mcp
Authorization: Bearer <mcp-token>

Run this package yourself only for local stdio access (Claude Desktop) or to front a self-hosted instance. One deployment serves many businesses — the token identifies both the business and the granted privileges.

Claude custom connector (OAuth)

Instead of pasting a token, register an OAuth client in Apps → Horizon MCP → Connectors, then in Claude: Settings → Connectors → Add custom connector, paste https://<your-host>/api/v1/mcp, and put the Client ID and Client Secret under Advanced settings. Claude opens the Horizon consent screen; each user approves individually, and access tokens refresh automatically.

Discovery is served by the app, not this package:

| Endpoint | Purpose | |---|---| | /.well-known/oauth-protected-resource[/api/v1/mcp] | RFC 9728 — points clients at the authorization server | | /.well-known/oauth-authorization-server[/api/v1/mcp] | RFC 8414 — authorize/token endpoints, scopes, PKCE methods | | /oauth/authorize | consent screen | | /api/v1/oauth/token | token exchange (client_secret_post or client_secret_basic) |

Unauthenticated or expired requests get 401 with a WWW-Authenticate: Bearer … resource_metadata="…" challenge, which is what triggers the client to (re-)run the flow. Set HORIZON_PUBLIC_URL when HORIZON_API_URL is an internal address, so that challenge points somewhere clients can actually reach.

There is deliberately no Dynamic Client Registrationregistration_endpoint is absent from the metadata, so clients fall back to asking for a Client ID and Secret. A business registers a connector once, on purpose.

Tools

| Area | Tools | |---|---| | Sales & reporting | get_dashboard_overview · get_sales_summary · get_top_products · get_invoices · get_invoice · get_customers · get_branches | | Catalog | search_products · get_product · create_product* · update_product* · get_product_activity · get_catalog_metadata | | Bundles | get_product_bundle · set_product_bundle* | | Inventory | get_inventory_status · get_inventory_movements · adjust_inventory* · import_stock* · get_inventory_summary · get_inventory_analytics · get_expiring_inventory · get_warehouses | | Purchasing | get_suppliers · get_reorder_suggestions · get_purchase_orders · get_purchase_order · create_purchase_order* · update_purchase_order* · receive_purchase_order* · get_purchase_order_receipts |

* Write tool — needs the matching *.write privilege on the token and is annotated readOnlyHint: false so clients can prompt before running it.

Restocking flow

get_reorder_suggestions scans stock against each product's reorder point and proposes quantities. Feed the result to create_purchase_order, then receive_purchase_order when the goods arrive — that last step is what actually raises stock levels and updates product cost. For stock that never had a PO (opening balances, a walk-in supplier drop-off), use import_stock instead — it optionally links a supplier and records a payment against it.

Both receive_purchase_order and import_stock (and adjust_inventory for inbound/outbound corrections) enforce the product's tracking settings: check get_product's identifierTrackingMode ("imei" / "serial") and expiryTracking first. If tracking is on, the matching identifiers / expiryDate fields are mandatory and the identifier count must equal the quantity converted to base units (via the line's unit conversion rate) — the call is rejected otherwise.

Audit trail

Every tool call is posted back to Horizon and stored with its arguments, outcome, and latency. Browse it in Apps → Horizon MCP → Call History. Logging is fire-and-forget: if the endpoint is unreachable, the tool still returns normally.

Privileges

Tokens carry Horizon API scopes. Typical sets:

  • Read-only analystreports.read, products.read, inventory.read, invoices.read, customers.read, branches.read
  • Inventory manager — the above plus inventory.write, products.write, warehouses.read
  • Purchasing — plus suppliers.read, purchase_orders.read, purchase_orders.write

A tool called without the required scope fails with a clear 403 naming the missing scope, rather than silently returning nothing.

Contributing

Building from source — not needed just to use the published package:

bun install
cp .env.example .env      # set HORIZON_API_URL
bun run dev               # HTTP transport on :3001/mcp
bun run smoke             # asserts all tools register (no network calls)

Local stdio config, running from source instead of the published package:

{
  "mcpServers": {
    "posara-horizon": {
      "command": "bun",
      "args": ["run", "/path/to/packages/horizon-mcp/src/index.ts"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "HORIZON_API_URL": "https://posara-horizon-t1.dcn01.ctdn.dev",
        "HORIZON_API_KEY": "your-mcp-token"
      }
    }
  }
}

Docker: docker-compose.yml at the repo root defines the horizon-mcp service, talking to the app over the compose network (HORIZON_API_URL=http://posara-horizon-app:3000).

docker compose up -d horizon-mcp