Skip to content

bgx4k3p/huly-mcp-server

Huly MCP Server

npm License: MIT Node.js MCP Huly SDK Docker

MCP server providing full coverage of the Huly SDK — issues, projects, workspaces, members, and account management. Two transports: stdio for local tools and Streamable HTTP for remote clients. Tested against self-hosted Huly. May also work with Huly Cloud (not yet tested).

Why This Exists

Huly has no public API. The only programmatic access is through their JavaScript SDK, which connects via WebSocket. This server wraps that SDK and exposes MCP tools over both stdio and Streamable HTTP transports — compatible with Claude Code, VS Code, n8n, and any MCP client.

Install

From npm

npm install @bgx4k3p/huly-mcp-server

Or run directly with npx:

npx @bgx4k3p/huly-mcp-server

From source

git clone https://github.com/bgx4k3p/huly-mcp-server.git
cd huly-mcp-server
npm install

Publishing

The Huly SDK has workspace: protocol references in transitive dependencies on the npm registry. The custom pack script bundles only the needed SDK packages and prunes UI bloat (32MB to 4MB):

npm run pack
npm publish bgx4k3p-huly-mcp-server-<version>.tgz --access public

Quick Start

Authentication

You can authenticate with either email/password or a token.

Email and Password

export HULY_URL=https://your-huly-instance.com
export [email protected]
export HULY_PASSWORD=your-password
export HULY_WORKSPACE=your-workspace

Token (recommended)

Get a token from your Huly credentials — no env vars needed beforehand:

node src/index.mjs --get-token -e [email protected] -p your-password -u https://your-huly-instance.com

Then use it:

export HULY_URL=https://your-huly-instance.com
export HULY_TOKEN=<paste-token-from-above>
export HULY_WORKSPACE=your-workspace

The token does not expire. You can store it in a secrets manager and stop exposing your password in environment variables.


Integrations

Claude Code (stdio)

After cloning and running npm install, register the server:

claude mcp add huly \
  -e HULY_URL=https://your-huly-instance.com \
  -e HULY_TOKEN=your-token \
  -e HULY_WORKSPACE=your-workspace \
  -- node /absolute/path/to/huly-mcp-server/src/index.mjs

Or add to your .mcp.json manually (token auth — recommended):

{
  "mcpServers": {
    "huly": {
      "command": "node",
      "args": ["/path/to/huly-mcp-server/src/index.mjs"],
      "env": {
        "HULY_URL": "https://your-huly-instance.com",
        "HULY_TOKEN": "${HULY_TOKEN}",
        "HULY_WORKSPACE": "${HULY_WORKSPACE}"
      }
    }
  }
}

Or with email/password:

{
  "mcpServers": {
    "huly": {
      "command": "node",
      "args": ["/path/to/huly-mcp-server/src/index.mjs"],
      "env": {
        "HULY_URL": "https://your-huly-instance.com",
        "HULY_EMAIL": "${HULY_EMAIL}",
        "HULY_PASSWORD": "${HULY_PASSWORD}",
        "HULY_WORKSPACE": "${HULY_WORKSPACE}"
      }
    }
  }
}

Then ask Claude things like:

  • "List my issues in the OPS project"
  • "Create a bug report for the login page crash"
  • "Summarize the PROJ project — what's overdue?"
  • "Break down this feature into subtasks using the feature template"

All tools have detailed descriptions optimized for AI agents. MCP Resources are also available at huly://projects/{id} and huly://issues/{id}.

Streamable HTTP (n8n, VS Code, remote clients)

Start the HTTP MCP server:

npm run start:server
# MCP endpoint: http://localhost:3001/mcp
# Health check: http://localhost:3001/health

Any MCP client that supports Streamable HTTP can connect to http://localhost:3001/mcp. This includes n8n (v1.88+), VS Code, and other MCP-compatible tools.

To secure the endpoint, set a bearer token:

MCP_AUTH_TOKEN=your-secret npm run start:server

Clients must then include Authorization: Bearer your-secret in requests.

Docker

docker build -t huly-mcp-server .

# Streamable HTTP server (recommended)
docker run -d \
  -p 3001:3001 \
  -e HULY_URL=https://your-huly-instance.com \
  -e HULY_TOKEN=your-token \
  -e HULY_WORKSPACE=my-workspace \
  huly-mcp-server

# MCP stdio mode
docker run -i \
  -e HULY_URL=https://your-huly-instance.com \
  -e HULY_TOKEN=your-token \
  -e HULY_WORKSPACE=my-workspace \
  huly-mcp-server node src/mcp.mjs

Server Configuration

Environment Variables

Variable Required Default Description
Huly Connection
HULY_URL No http://localhost:8087 Huly instance URL
HULY_TOKEN No - Auth token (alternative to email/password)
HULY_EMAIL No - Huly login email (required if no token)
HULY_PASSWORD No - Huly login password (required if no token)
HULY_WORKSPACE Yes* - Default workspace slug
HULY_TRANSPORT No ws SDK transport: ws (WebSocket) or rest (REST API)
HULY_POOL_TTL_MS No 1800000 Connection pool TTL in ms (30 min)
HTTP Server
PORT No 3001 HTTP server port (auto-assigns if taken)
MCP_AUTH_TOKEN No - Bearer token for HTTP auth (disabled if unset)
HULY_RATE_LIMIT No 200 Max requests per minute per IP
ALLOWED_ORIGINS No * CORS allowed origins (comma-separated)

*HULY_WORKSPACE is required for MCP stdio mode. For HTTP mode it can be omitted if every request specifies a workspace via the tool arguments.

HTTP Server Authentication

The HTTP server optionally requires a bearer token. This protects your server from unauthorized access — it's separate from Huly's own authentication.

# Generate a token
openssl rand -hex 32

# Start with auth enabled
MCP_AUTH_TOKEN=your-token-here npm run start:server

If MCP_AUTH_TOKEN is not set, auth is disabled (fine for local-only usage).

MCP stdio mode (Claude Code) does not use this token — stdio is inherently local.

Multi-Workspace

All tools accept an optional workspace parameter. The connection pool caches clients by workspace slug with configurable TTL:

{"tool": "list_projects", "arguments": {"workspace": "workspace-a"}}

If omitted, the HULY_WORKSPACE env var is used as the default.


Testing

Uses Node.js built-in node:test and node:assert — no test framework dependencies. Tests run twice: once with WebSocket transport, once with REST transport.

npm test              # Both transports (ws + rest)
npm run test:ws       # WebSocket only
npm run test:rest     # REST only

194 tests across 101 suites:

Suite Tests Description
Unit 28 Constants, ID parsing, rate limiting, auth logic
Integration 55 Full CRUD lifecycle against live Huly
Dispatch 45 Schema to dispatch to client param forwarding for all tools
Account-level 11 Workspaces, profile, social IDs
Mock 44 Destructive ops, token auth via mocks
Streamable HTTP 11 MCP protocol over HTTP: init, tools, resources, auth, rate limiting

100% dispatch coverage — every tool's params are traced end-to-end through the dispatch table to the client method.


Network Configurations

  • Local: HULY_URL=http://localhost:8087
  • Remote: HULY_URL=https://huly.example.com
  • Behind nginx proxy: Point to the proxy port

Cloudflare Access / Tunnel

If Huly is behind Cloudflare Access with MFA, create a bypass Application for /_* or these individual paths:

  • /_accounts
  • /_transactor
  • /_collaborator
  • /_rekoni
  • /config.json

Architecture

src/
  client.mjs    # HulyClient — all business logic and SDK calls
  helpers.mjs   # Shared constants, markup conversion, JSDOM polyfills
  dispatch.mjs  # Tool-to-method dispatch table
  pool.mjs      # Connection pool — caches clients by workspace with TTL
  mcpShared.mjs # Shared MCP server factory — tool definitions + resources
  mcp.mjs       # MCP stdio entry point (Claude Code)
  server.mjs    # MCP Streamable HTTP entry point (n8n, VS Code, remote)
  index.mjs     # CLI entry point — --get-token mode + MCP re-export
Claude Code  -> stdio           -> mcp.mjs    -> mcpShared.mjs -> pool -> client -> Huly SDK
n8n / remote -> Streamable HTTP -> server.mjs -> mcpShared.mjs -> pool -> client -> Huly SDK

Response Format

All read operations return known fields at the top level with resolved, human-readable values (e.g., status names instead of IDs, formatted dates). Any additional fields from the Huly SDK that aren't explicitly mapped appear in an extra object — this future-proofs the API so new SDK fields are visible without a code update.

{
  "id": "PROJ-42",
  "title": "Fix the bug",
  "status": "In Progress",
  "priority": "High",
  "type": "Task",
  "parent": "PROJ-10",
  "childCount": 3,
  "createdOn": 1719700000000,
  "completedAt": null,
  "extra": {
    "_id": "69bab168...",
    "_class": "tracker:class:Issue",
    "space": "69b819b7...",
    "kind": "tracker:taskTypes:Issue"
  }
}

Text fields (description, comment) support three input formats via descriptionFormat / format parameter:

  • markdown (default) — rendered as rich text in the Huly UI
  • html — raw HTML, converted to rich text
  • plain — stored as unformatted text

API Reference

Full list of all MCP tools available through this server.

Account and Workspace Management

Tool Description
list_workspaces List all accessible workspaces
get_workspace_info Get workspace details by slug
create_workspace Create a new workspace
update_workspace_name Rename a workspace
delete_workspace Permanently delete a workspace
get_workspace_members List workspace members and roles
update_workspace_role Change a member's role
get_account_info Get current user's account info
get_user_profile Get current user's profile
set_my_profile Update profile fields
change_password Change password
change_username Change username

Invites

Tool Description
send_invite Send workspace invite email
resend_invite Resend pending invite
create_invite_link Generate shareable invite link

Integrations, Mailboxes, Social IDs, Subscriptions

Tool Description
list_integrations / get_integration / create_integration / update_integration / delete_integration Full CRUD for integrations
list_mailboxes / create_mailbox / delete_mailbox Mailbox management
find_person_by_social_key / get_social_ids / add_email_social_id Person/social ID management
list_subscriptions List account subscriptions

Projects

Tool Description Text Format
list_projects List all projects (supports include_details) --
get_project Get project by identifier (supports include_details) --
create_project Create a new project descriptionFormat: md/html/plain
update_project Update project name, description, privacy, default assignee descriptionFormat: md/html/plain
archive_project Archive or unarchive a project --
delete_project Permanently delete a project --
summarize_project Aggregated project metrics and health --

Issues

Tool Description Text Format
list_issues List issues with filters (supports include_details) --
get_issue Get full issue details (supports include_details) --
create_issue Create a new issue descriptionFormat: md/html/plain
update_issue Update issue fields descriptionFormat: md/html/plain
delete_issue Permanently delete an issue --
search_issues Full-text search across projects --
get_my_issues Issues assigned to current user --
batch_create_issues Create multiple issues at once descriptionFormat per item
move_issue Move issue between projects --
create_issues_from_template Create from predefined templates --

Labels

Tool Description
list_labels List all labels in the workspace
get_label Find a label by name
create_label Create a new label with optional color
update_label Update label name, color, or description
delete_label Permanently delete a label
add_label Add a label to an issue
remove_label Remove a label from an issue

Relations

Tool Description
add_relation Add bidirectional "related to" link
add_blocked_by Add "blocked by" dependency
set_parent Set parent issue (epic/task hierarchy)

Components

Tool Description Text Format
list_components List components in a project --
get_component Find a component by name --
create_component Create a new component (optional lead) descriptionFormat: md/html/plain
update_component Update component name, description, or lead descriptionFormat: md/html/plain
delete_component Delete a component --

Milestones

Tool Description Text Format
list_milestones List milestones (supports include_details) --
get_milestone Get milestone details (supports include_details) --
create_milestone Create a new milestone descriptionFormat: md/html/plain
update_milestone Update milestone fields descriptionFormat: md/html/plain
delete_milestone Delete a milestone --
set_milestone Set or clear milestone on an issue --

Members

Tool Description
list_members List all active workspace members
get_member Find a member by name (fuzzy match)

Comments

Tool Description Text Format
list_comments List all comments on an issue --
get_comment Get a specific comment by ID --
add_comment Add a comment to an issue format: md/html/plain
update_comment Update comment text format: md/html/plain
delete_comment Delete a comment --

Time Tracking

Tool Description Text Format
log_time Log actual time spent descriptionFormat: md/html/plain
list_time_reports List time reports for an issue --
get_time_report Get a specific time report by ID --
delete_time_report Delete a time report --

Metadata

Tool Description
list_task_types List task types for a project
get_task_type Find a task type by name
list_statuses List issue statuses
get_status Find a status by name

Text format: All text fields default to markdown. Set descriptionFormat (or format for comments) to "markdown", "html", or "plain". Content is passed through unmodified -- the format tells Huly how to render it.

include_details Flag

Several read tools support an include_details boolean parameter that fetches related data in a single call:

Tool Extra data when include_details=true
get_issue Comments, time reports, relations, children
list_issues Descriptions, comments, time reports, relations, children (limit reduced to 50)
get_project Milestones, components, labels, members
list_projects Milestones, components, labels, members per project (limit 20)
get_milestone Full list of issues in the milestone
list_milestones Issues list per milestone

CRUD Coverage

Entity Create Read List Update Delete
Project create_project get_project list_projects update_project delete_project
Issue create_issue get_issue list_issues update_issue delete_issue
Label create_label get_label list_labels update_label delete_label
Component create_component get_component list_components update_component delete_component
Milestone create_milestone get_milestone list_milestones update_milestone delete_milestone
Comment add_comment get_comment list_comments update_comment delete_comment
Time Report log_time get_time_report list_time_reports -- delete_time_report
Member -- get_member list_members -- --
Status -- get_status list_statuses -- --
Task Type -- get_task_type list_task_types -- --

Issue Templates

Use create_issues_from_template:

Template Creates
feature Parent + design/implement/test/docs/review sub-issues
bug Parent + reproduce/root-cause/fix/regression-test sub-issues
sprint Planning/standup/review/retro ceremony issues
release Parent + freeze/QA/changelog/staging/prod/verify sub-issues

Templates use task types like Epic/Bug when available, falling back to the workspace default type otherwise.


Security

npm audit reports moderate vulnerabilities in Svelte (SSR XSS). These come from Huly SDK transitive dependencies — the SDK shares packages with Huly's web frontend. MCP server never renders HTML or uses Svelte. The vulnerabilities are not exploitable in this context.


License

MIT

About

Universal MCP server for Huly project management — issue tracking, projects, milestones, labels, time tracking, and workspace management. Supports stdio (Claude Code) and Streamable HTTP transports. Self-hosted Huly SDK wrapper with multi-workspace support.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors