huly-mcp-selfhost
MCP server · open source · EPL-2.0

huly-mcp-selfhost

  • Huly for AI agents.
  • Self-hosted + Huly Cloud.
  • 2.9× fewer tokens per answer.
  • One server for the team — log in with Huly.
  • 227 tools · undo · no telemetry · 4 MB.
01 — Quick setup

Pick your client. Paste. Done.

Account credentials only. The server finds your workspaces itself. Claude Code: install the plugin instead — /plugin marketplace add JoKeks2023/huly-mcp, then /huly:setup in your repo.

terminal
claude mcp add huly \
  -e HULY_EMAIL=you@example.com \
  -e HULY_PASSWORD=your-password \
  -- npx -y huly-mcp-selfhost

Add --scope user (all projects) or --scope project (.mcp.json — don’t commit secrets) after “add huly”. Check with: claude mcp list

SSO account without a password? Use HULY_TOKEN instead — see Authentication. More clients (Windsurf, Cline, Continue) in the README. For a whole team: the team server.

02 — Why this one

Built for agents. Measured, not claimed.

Native Huly SDK over WebSocket — not screen scraping, not a REST shim. Every answer is shaped for a model: open items by default, empty fields left out, one call instead of four.

Characters per answer compared with another popular Huly MCP server: 2.9× less text per answer (median), 13× smaller tool definitions, one call instead of up to four. Components: ours is larger because it includes descriptions and paths.

Same self-hosted Huly, same questions, the best parameters on both sides, measured 2026-11-11. All numbers.

Agent workflows
my_day, standup, project_report, release_notes and get_issue_context in one call each; start_work → finish_work; plans, specs and meeting notes → epics and issues; claims for parallel agents; huly-mcp watch hands Huly issues to Claude.
Undo
undo_changes reverses your last changes through the server — for every write tool. Dry run first; skips what someone else changed since.
Claude Code plugin
/huly:setup asks once per repo how Huly is used there and writes the rules; a skill that picks the cheapest call, hooks, /huly:* commands. Guides and a setup prompt for every other MCP client.
Team server
One container, everyone logs in with their own Huly account in the browser (OAuth). Persistent sessions, ~0.2 s per call.
Command line
huly-mcp <tool> --param value for scripts and CI, generated from the same schemas; completion for bash and zsh.
Safe by default
Every change names its workspace; risky tools ask first; writes can be limited to projects; audit log; unknown parameters are rejected instead of ignored.
No telemetry
It talks to your Huly server and nothing else. One self-contained package, ~4 MB — no 180 dependencies on first start.
03 — Multi-workspace

One login. Every workspace.

The server discovers what your account can access and keeps a separate connection per workspace. It never guesses which one you mean.

  • One account login — email + password or token, once per process.
  • Discovery via getUserWorkspaces(); list_workspaces shows name, slug and id.
  • One cached connection per workspace, opened on first use via selectWorkspace() with its own workspace token.
  • No current, default or last-used workspace. Every call names its target.
  • Writes require workspace — enforced by the tool schema, even with a single workspace.
  • Reads may omit it only when exactly one workspace is available. IDs like PROJ-1 are only unique within their workspace.
Multi-Workspace in the docs →
agent ↔ huly-mcp-selfhost
› list_workspaces()
- **Acme Team** — slug: `acmeteam` — id: `3f2b9c1e-…`
- **Personal** — slug: `personal` — id: `8a41d7e0-…`

› list_projects(workspace="acmeteam")
## Projects (2) …

› list_projects()
Multiple workspaces available — pass 'workspace' explicitly.

› log_time(identifier="WEB-12", hours=2)
Input validation error: workspace — Required
04 — Tools

Every tool, by toolset.

Only the default toolsets are loaded unless you choose more (HULY_TOOLSETS) — or let the agent load them on demand.

227tools
30toolsets
99loaded by default
137change data — workspace required

Core default

list_workspacesundo_changescheck_setup
3

Agent workflow default

get_issue_contextstart_workfinish_workcreate_issue_treemy_dayissues_from_documentissues_from_meetingstanduprelease_notesproject_reportchanges_sinceclaim_issuefind_project_for_reporelease_issue
14

Tracker default

list_projectsget_projectlist_issuesget_issuecreate_issueupdate_issuedelete_issuebulk_update_issuesmove_issuelist_sub_issuesadd_commentlist_commentsdelete_commentupdate_commentlog_timelist_time_reportslist_labelscreate_labeladd_labelremove_labeladd_relationadd_blocked_byset_parentremove_relationremove_blocked_bylist_milestonescreate_milestoneget_milestoneupdate_milestonelist_componentscreate_componentupdate_componentsearch_issuesattach_filelist_attachmentsdelete_attachmentlist_issue_statuses
37

Tracker admin

create_projectupdate_projectupdate_labeldelete_labelrepair_parent_linksdelete_milestonedelete_componentcreate_issue_statuslist_label_categoriescreate_label_categoryset_label_categorylist_project_types
12

Documents default

list_teamspacescreate_teamspacelist_documentsget_documentcreate_documentdelete_documentupdate_documentlink_document
8

Chat default

list_channelscreate_channelstart_direct_messagesend_messagelist_messageslist_threadreply_to_messageupdate_messagedelete_messageadd_reactionremove_reactionpin_message
12

Contacts default

list_memberslist_organizationsget_organizationcreate_organizationupdate_organizationlist_personsget_personcreate_personupdate_personadd_contact_channelremove_contact_channel
11

Inbox default

list_notificationstriage_inboxmark_notifications_readmanage_notifications
4

Activity default

get_activity
1

Planner default

list_todoscreate_todoupdate_tododelete_todoschedule_todo
5

Calendar

list_eventscreate_eventupdate_eventdelete_event
4

GitHub

list_pull_requestsget_pull_request
2

Any Huly class default

searchlist_classesdescribe_classquery_documents
4

Any class — writes

generic_creategeneric_updategeneric_delete
3

Collaboration

list_document_commentsadd_document_commentlist_collaboratorsadd_collaboratorremove_collaboratorcreate_public_linklist_public_linksrevoke_public_link
8

Cards

list_card_typeslist_cardsget_cardcreate_cardupdate_carddelete_cardcreate_card_typedelete_card_type
8

Custom fields

list_custom_fieldscreate_custom_fieldset_custom_fields
3

Drive

list_drivescreate_drivelist_drive_filescreate_folderupload_filedownload_fileupdate_drive_itemdelete_drive_itemlist_file_versionsrestore_file_version
10

Templates

list_issue_templatesget_issue_templatecreate_issue_templateupdate_issue_templatedelete_issue_templatecreate_issue_from_templatelist_message_templatesget_message_templatecreate_message_templateupdate_message_templatedelete_message_template
11

Test management

list_test_projectscreate_test_projectlist_test_casescreate_test_suiteget_test_casecreate_test_caseupdate_test_casedelete_test_caselist_test_planscreate_test_plancreate_test_runlist_test_runsget_test_runset_test_resultcreate_test_casesupdate_test_suitedelete_test_suiteupdate_test_rundelete_test_rundelete_test_planimport_test_resultsget_test_reportcreate_issue_from_test_result
23

Products

list_productsget_product
2

Members & invites

get_workspace_settingscreate_invite_linksend_inviteset_member_role
4

Recruiting

list_vacanciescreate_vacancyupdate_vacancylist_candidatescreate_candidatelist_applicationscreate_applicationupdate_applicationdelete_application
9

CRM

list_leadslist_customerscreate_leadupdate_leaddelete_lead
5

HR

list_departmentscreate_departmentdelete_departmentset_departmentlist_time_offcreate_time_offdelete_time_off
7

Inventory

list_inventorycreate_inventory_categorycreate_inventory_productupdate_inventory_itemdelete_inventory_item
5

Meetings

list_meetingsget_meeting
2

Quality documents

list_controlled_documentsget_controlled_documentlist_trainingsget_training
4

Processes

list_processeslist_executionsstart_processcancel_execution
4

Surveys

list_surveysget_survey
2
changes data — workspace requiredreads: workspace optional when only one is available
Full tool reference →
05 — Architecture

A thin, stateful bridge.

No database, no cache service, no extra infrastructure. All state is in process memory: account sessions, the discovered workspaces, one connection per workspace in use and the undo history. OAuth tokens are sealed, so nothing needs storing.

MCP clientClaude · Codex · Cursor · Zed · CLI

Calls tools over stdio, or over HTTP to the team server — each session with its own Huly login (OAuth or headers).

MCP toolssrc/tools/*.ts

227 handlers in toolsets. Each resolves its own connection from its workspace argument; inputs are validated against zod schemas first; writes are recorded for undo_changes.

Account clientHULY_ACCOUNTS_URL · account token

login / getLoginInfoByToken, then getUserWorkspaces() and selectWorkspace(). Never holds a workspace token.

Workspace connection managersrc/connection.ts

Caches the session, the workspace list and one connection per workspace id. Failed attempts are not cached; shutdown closes everything.

Workspace clientper workspace · workspace token

TxOperations for all reads and writes, plus a workspace-scoped account client for getWorkspaceMembers().

Huly WebSocketendpoint from selectWorkspace()

Opened with @hcengineering/server-client; loads the workspace model once, then stays open.

Storage / /filesHULY_FRONT_URL · workspace token

Markup blobs (document bodies, descriptions) and attachments — Bearer-authenticated, per workspace.

Architecture in the docs →
06 — Self-hosted

Built for huly-selfhost. Works on Huly Cloud.

Huly Cloud stores document content in its datalake service, which self-hosted instances don’t run. On a self-hosted instance the server reads and writes it through the front service’s own /files endpoint — and can connect to the transactor internally when it runs next to Huly.

HULY_ACCOUNTS_URL

Account service: login, workspace discovery, selectWorkspace(), members. Defaults to https://account.huly.app. Self-hosted: e.g. https://your-huly-instance.com/_accounts.

HULY_FRONT_URL

Front service: reads document and description content and — when set — handles uploads via /files. Not involved in login or discovery. Self-hosted: e.g. https://your-huly-instance.com.

Blob operationHULY_FRONT_URL setHULY_FRONT_URL unset (Cloud)
Read contentGET {front}/files?file=…&workspace=…not fetched — blob ref shown
UploadPOST {front}/filesPOST dl-eu.huly.app/upload/form-data/{workspace}
DeleteDELETE {front}/files?file=…DELETE dl-eu.huly.app/blob/{workspace}/{id}
AuthAuthorization: Bearer <workspace token> — of the workspace named in the call

Note: HULY_FRONT_URL doubles as the self-hosted switch for uploads. On a self-hosted instance, always set it.

Self-hosted Huly in the docs →
07 — Team server

One server. Everyone logs in with Huly.

Run the HTTP server once; people add its URL in Claude Code, Claude's custom connectors or another MCP client and log in in the browser with their own Huly account. Each session acts as that person.

  • Password or one-time code — Google/GitHub accounts get a code by e-mail.
  • Nothing to store — registrations, codes and tokens are sealed with AES-256-GCM under one secret; logins survive restarts.
  • The password is never kept — only the Huly token from the login, inside the sealed tokens. Access tokens last an hour, refresh tokens rotate.
  • Protocol from the MCP SDK — client registration, PKCE, token endpoint, metadata.
  • Without OAuth: per-user X-Huly-* headers, or one shared account only behind MCP_AUTH_TOKEN.
Team server in the README →
server
docker run -d -p 8000:8000 \
  -e MCP_TRANSPORT=http \
  -e MCP_OAUTH_SECRET="$(openssl rand -hex 32)" \
  -e MCP_PUBLIC_URL=https://huly-mcp.example.com \
  -e HULY_ACCOUNTS_URL=https://huly.example.com/_accounts \
  -e HULY_FRONT_URL=https://huly.example.com \
  jokeks2023/huly-mcp
each person
claude mcp add --transport http huly \
  https://huly-mcp.example.com/mcp
# → browser: "Log in with Huly"

Keep the secret fixed (env file) and put the server behind HTTPS at MCP_PUBLIC_URL. Changing the secret logs everyone out.

08 — Security & privacy

Your data stays between you and your Huly.

No telemetry
No analytics, no usage tracking, nothing to opt out of. The only other request — the npm version check — runs when you call check_setup.
Tokens in headers
Workspace tokens travel only as Authorization headers, never in URLs or tool results — covered by regression tests; tokens in logs are masked.
Guard rails
Writes always name their workspace; HULY_WRITE_PROJECTS limits where; risky tools ask first (HULY_CONFIRM); HULY_AUDIT_LOG records every change; undo_changes reverses them.
Supply chain
npm Trusted Publishing with provenance; Docker images with SBOM and build provenance; one bundled, readable file — no runtime dependencies to audit.
09 — Install

Five ways to run it.

npm

Launched by your MCP client over stdio. Node.js ≥ 20, ~4 MB.

terminal
npx -y huly-mcp-selfhost

Claude Desktop extension

One file, double-click, enter your Huly login. Claude Desktop brings Node.js; secrets go to the keychain.

Download .mcpb ↓

Claude Code plugin

Server, skill, hooks and /huly:* commands.

claude code
/plugin marketplace add JoKeks2023/huly-mcp
/plugin install huly@huly-mcp

Docker

The team server above, or classic mode via mcp-proxy (/mcp, /sse). amd64 + arm64.

terminal
docker run -d --name huly-mcp -p 127.0.0.1:8000:8000 \
  --env-file .env jokeks2023/huly-mcp:latest

Command line

Every tool from the terminal, for scripts and CI.

terminal
npm i -g huly-mcp-selfhost
huly-mcp help list_issues
Quick start in the README →