MCP servers for ZennoPoster and ZennoDroid: let AI agents edit automation projects, run tasks, drive browser instances and Android devices from Claude, Cursor, VS Code and other MCP clients

English | Русский

Connecting the ZennoPoster/ProjectMaker MCP servers to your own LLM client

The MCP servers are published as self-contained win-x64 binaries via GitHub Releases inthe shared repository https://github.com/ZennoLab/zennoposter-mcp/releases. Eachserver has its own release line (its own tag prefix):

  • ProjectMaker (editor) — tags mcp-projectmaker-v*, archive MCP.ProjectMaker-v*-win-x64.zip
  • Instance (browser control, dual-mount) — tags mcp-instance-v*, archive MCP.Instance-v*-win-x64.zip
  • ZennoPoster (task runner) — tags mcp-zennoposter-v*, archive MCP.ZennoPoster-v*-win-x64.zip
  • Android (ZennoDroid device) — tags mcp-android-v*, archive MCP.Android-v*-win-x64.zip

PublicApi documentation (the OpenAPI contract rendered with Redoc, the integrator guide,error codes, versioning policy) lives at https://zennolab.github.io/zennoposter-mcp/(the pages are published from the docs/ folder of this repository).

These servers talk to ZennoPoster 7.9.2 and newer and to ZennoDroid 2.6.1 and newer.MCP.Instance applies to ZennoPoster only and MCP.Android to ZennoDroid only; MCP.ProjectMakerand MCP.ZennoPoster apply to both.Which server version goes with which product and contract version:https://zennolab.github.io/zennoposter-mcp/compatibility.html.

Install buttons for Cursor and VS Code and the Claude Code commands for every server:https://zennolab.github.io/zennoposter-mcp/install.html.

The model: your own MCP instance with your own key

The product itself starts internal MCP servers for its built-in AI chat — they live onthe internal port band 6107–6113 (on ZennoDroid everything is shifted by +10), receive aleast-privilege service key from the host, and ignore the Authorization header ofincoming requests. This is internal infrastructure: connecting toit from outside is not supported (permissions there are defined by the service key, notyours), and its ports must not be occupied — a foreign process on a port from this bandprevents the built-in server from starting (the product logs an error, but its AI stack isleft without that server).

For your own LLM client you run a separate copy of the MCP server from the publicpackage: it listens on the public port band 6207–6211 and talks to the same productPublicApi (:5299 ProjectMaker / :5300 ZennoPoster), but with your ApiKey — with thescopes/tier you chose when issuing the key. Both copies run side by side withoutinterfering with each other.

On ZennoDroid the two servers that serve both products listen +10 higher — MCP.ProjectMakeron 6217, MCP.ZennoPoster on 6220 — the same shift the product applies to its internal band.That way a machine with both products installed can run both sets at once. MCP.Android exists onlyon ZennoDroid and keeps 6211: nothing on ZennoPoster occupies it.

Default ports (set in the appsettings.json next to the exe):

Server Port Talks to Key in config
MCP.ProjectMaker 6207 PM PublicApi :5299 ProjectMaker:ApiKey
MCP.Instance (Target=projectmaker) 6208 PM PublicApi :5299 Instance:ApiKey
MCP.Instance (Target=zennoposter) 6209 (convention, set explicitly) ZP PublicApi :5300 Instance:ApiKey
MCP.ZennoPoster 6210 ZP PublicApi :5300 ZennoPoster:ApiKey
MCP.Android (ZennoDroid, editor device) 6211 ZDroid PM PublicApi :5309 Android:ApiKey
MCP.Android (ZennoDroid, task devices) 6212 (convention, set explicitly) ZDroid ZP PublicApi :5310 Android:ApiKey

The product API those servers call listens on different ports in the two products:

Application ZennoPoster ZennoDroid
ProjectMaker 5299 5309
ZennoPoster 5300 5310

The defaults above and the examples below are for ZennoPoster. On ZennoDroid each server needs bothits listen port and its BaseUrl set explicitly:

Server Port Talks to Key in config
MCP.ProjectMaker 6217 (set explicitly) ZDroid PM PublicApi :5309 ProjectMaker:ApiKey
MCP.ZennoPoster 6220 (set explicitly) ZDroid ZP PublicApi :5310 ZennoPoster:ApiKey
MCP.Android (editor device) 6211 ZDroid PM PublicApi :5309 Android:ApiKey
MCP.Android (task devices) 6212 (set explicitly) ZDroid ZP PublicApi :5310 Android:ApiKey

Everything can be overridden through standard ASP.NET Core configuration: theappsettings.json next to the exe, environment variables (ASPNETCORE_URLS,ProjectMaker__ApiKey, …) or command-line arguments (--urls, --ProjectMaker:ApiKey=…, …) —arguments override environment variables, environment variables overrideappsettings.json.

1. Download the server you need

On the releases page find the latest release of the server you need (by tag prefix),download its *-win-x64.zip and unpack it into any folder.Each archive is a single self-contained .exe + appsettings.json; no additional .NETruntime is required.

2. Issue an ApiKey

In ProjectMaker: Settings → API KeysAdd — the "Add API key" dialog opens:

  1. Set a Label (an arbitrary key name, to tell keys apart in the list).
  2. Choose the Max tier (the minimum sufficient for your tasks — T0 for read-only, higherfor mutating operations).
  3. Tick the Scopes you need (only *:read are ticked by default; add others as needed).
  4. Confirm — the raw key is shown once; copy it to a safe place immediately.

More on scopes/tiers — security-model.md.

3. Run the server with your key

The key is set in the MCP server's own configuration (not in the MCP client's headers —the server accepts connections from loopback only and does not read the Authorizationheader of incoming requests). The simplest way is to put the key into ApiKey in theappsettings.json next to the exe and start with no arguments; or pass it via environmentvariables / arguments:

# ProjectMaker (editor): 6207 -> :5299
.\ZennoLab.AI.MCP.ProjectMaker.exe --ProjectMaker:ApiKey=zp_xxx

# Instance for the editor (PM browser): 6208 -> :5299
.\ZennoLab.AI.MCP.Instance.exe --Instance:ApiKey=zp_xxx

# Instance for the runner — a SECOND copy of the same exe: the port and the Target/BaseUrl pair are set explicitly
.\ZennoLab.AI.MCP.Instance.exe --urls http://localhost:6209 `
  --Instance:Target=zennoposter --Instance:BaseUrl=http://localhost:5300/api/v1 `
  --Instance:ApiKey=zp_xxx

# ZennoPoster (runner tasks/sessions): 6210 -> :5300
.\ZennoLab.AI.MCP.ZennoPoster.exe --ZennoPoster:ApiKey=zp_xxx

# Android (the device attached to ProjectMaker): 6211 -> :5309
.\ZennoLab.AI.MCP.Android.exe --Android:ApiKey=zp_xxx

# Android for the runner — a SECOND copy of the same exe, for the devices of running tasks
.\ZennoLab.AI.MCP.Android.exe --urls http://localhost:6212 `
  --Android:BaseUrl=http://localhost:5310/api/v1 --Android:ApiKey=zp_xxx

MCP.Android mounts twice for the same reason MCP.Instance does on ZennoPoster: the Androiddomain is served both by ProjectMaker's PublicApi (the device you see in the editor) and by therunner's (the devices its tasks are driving). Unlike MCP.Instance it has no Target, so the twocopies differ only by --urls and BaseUrl.

On ZennoDroid, the same two executables are started on the shifted ports and pointed at theZennoDroid API:

# ProjectMaker on ZennoDroid: 6217 -> :5309
.\ZennoLab.AI.MCP.ProjectMaker.exe --urls http://localhost:6217 `
  --ProjectMaker:BaseUrl=http://localhost:5309/api/v1 --ProjectMaker:ApiKey=zp_xxx

# ZennoPoster tasks on ZennoDroid: 6220 -> :5310
.\ZennoLab.AI.MCP.ZennoPoster.exe --urls http://localhost:6220 `
  --ZennoPoster:BaseUrl=http://localhost:5310/api/v1 --ZennoPoster:ApiKey=zp_xxx

Important note on the two MCP.Instance copies: for the Instance server, Target(which instructions it serves to the AI — about ProjectMaker or about ZennoPoster) andBaseUrl (where HTTP requests actually go) are configured only together, as a pair, andare not linked in code (Target=projectmakerBaseUrl at the PM PublicApi :5299,Target=zennoposterBaseUrl at the ZP PublicApi :5300). On startup the server makesa best-effort check via the target host's /capabilities and logs a warning on mismatch,but if the target host is unreachable at startup the check is silently skipped — amismatch is then not detected, and the AI gets instructions about one host while requestsgo to another.

4. Configure your LLM client

A ready-made configuration fragment (the format matches Claude Code's .mcp.json; use theequivalent for your MCP client if needed):

{
  "servers": {
    "projectmaker": {
      "type": "http",
      "url": "http://localhost:6207"
    },
    "instance-pm": {
      "type": "http",
      "url": "http://localhost:6208"
    },
    "instance-zp": {
      "type": "http",
      "url": "http://localhost:6209"
    },
    "zennoposter": {
      "type": "http",
      "url": "http://localhost:6210"
    }
  }
}

On ZennoDroid the entries are these — different names, so both products can be configured in oneclient, and no instance-* mount, which ZennoDroid does not have:

{
  "servers": {
    "projectmaker-droid": {
      "type": "http",
      "url": "http://localhost:6217"
    },
    "zennodroid": {
      "type": "http",
      "url": "http://localhost:6220"
    },
    "android-pm": {
      "type": "http",
      "url": "http://localhost:6211"
    },
    "android-zd": {
      "type": "http",
      "url": "http://localhost:6212"
    }
  }
}

No authorization is needed on this leg: the MCP servers listen on loopback only, and thepermissions are defined by the key the server itself was started with (step 3).

5. Verify the connection

With any MCP client (or plain HTTP) call a safe read-only method and make sure it responds200 OK with the expected data — e.g. get_product_version/ping on the server you need.If the key is invalid or lacks a scope/tier, the server returns a structured error(401 unauthorized / 403 forbidden with required/current fields), not a silentfailure.

Changing ports

Each server has two ports: the one it listens on for your LLM client, and the product API port itcalls.

Listen port. Any of the three, arguments winning over environment, environment over the file:

.\ZennoLab.AI.MCP.ProjectMaker.exe --urls http://localhost:7207

$env:ASPNETCORE_URLS = "http://localhost:7207"
.\ZennoLab.AI.MCP.ProjectMaker.exe

or "Urls": "http://localhost:7207" in the appsettings.json next to the exe. After moving alisten port, update the matching URL in the client configuration from step 4.

Stay off 6107–6113 (6117–6123 on ZennoDroid): those belong to the product's built-in servers,and a foreign process on one of them prevents the built-in server from starting.

Product API port. Set the BaseUrl of that server's own section — this is what you change onZennoDroid:

# ProjectMaker API on 5309 instead of 5299
.\ZennoLab.AI.MCP.ProjectMaker.exe --ProjectMaker:BaseUrl=http://localhost:5309/api/v1 --ProjectMaker:ApiKey=zp_xxx

# ZennoPoster API on 5310 instead of 5300
.\ZennoLab.AI.MCP.ZennoPoster.exe --ZennoPoster:BaseUrl=http://localhost:5310/api/v1 --ZennoPoster:ApiKey=zp_xxx

The section is named after the server: ProjectMaker, Instance, ZennoPoster, Android.Versions up to 0.3.0 of MCP.ProjectMaker and MCP.ZennoPoster used NeuroBot and ZennoPosterApi;those names still work in later versions and the server logs a warning at startup.

License

The files in this repository (documentation and the OpenAPI specification) are licensed under theMIT License. The MCP serverbinaries on the Releases page are proprietary; their terms are inTERMS.md.

MCP Server · Populars

MCP Server · New