Skip to main content

mycouncil — MCP server

Run multi-LLM myCouncil debates from Claude Code, Claude Desktop, Cursor, and any other MCP-aware client.

Thin wrapper over the public myCouncil API. Rounds, billing, and auto-config mode live on your account — the MCP server just relays calls.

What's new

0.6.1debate settings reach the server. max_rounds / initial_budget at the top level of config are moved into config["adf_settings"] before the request — the server only reads them there and silently ignored the top-level copy (a type-2 debate asked for 3 rounds ran, and reserved, 5). New optional max_rounds and initial_budget parameters on mycouncil_debate(_start); a setting that doesn't fit the config's session type returns {"error": "invalid_params"} instead of being dropped. Quota docs now cover competitive debates (session_type 3), which are priced by per-debater budget. See Quotas and debate settings.

0.6.0in-debate RAG (--rag-mode debate). The wrapper stops searching on its own and instead forwards per-call RAG parameters (pooled rag_access_token or per-expert rag_access_tokens, plus rag_max_requests / rag_expires_in) to the debate API as a retrieval object — the council's agents then query the corpus themselves, mid-debate. --rag-prelude becomes a deprecated alias for --rag-mode prelude; defaults are unchanged. See RAG modes.

0.5.0 — optional RAG prelude (--rag-prelude). The debate tools gain two optional per-call parameters — rag_access_token + rag_base_url. When a call carries both, the wrapper runs one hybrid search over an external stakeholder-call RAG corpus and prepends the found excerpts to the debate content, so the council grounds its takes in what stakeholders actually said. Off by default; without the flag the tool schemas are unchanged. See RAG modes.

0.4.0 — optional per-request auth for streamable-http (--auth per-request). Each HTTP call carries its own myCouncil API key in the X-MyCouncil-Key (or Authorization: Bearer) header, so one hosted wrapper can serve many myCouncil accounts — each caller spends their own rounds. Default is unchanged (--auth shared, single env key); stdio is unchanged. See Per-request auth.

0.3.0 — optional streamable-http transport (--transport streamable-http). Run the server as one long-lived HTTP service instead of a per-client stdio process — the async server handles concurrent debates natively (no stdio→HTTP bridge in front). Identity is unchanged: a single MYCOUNCIL_API_KEY from the environment. stdio stays the default. See Running over streamable HTTP.

0.2.0 — added mycouncil_info (orientation guide agents can call once per session) and mycouncil_list_roles (browse the curated expert-role catalogue when composing a custom council). 8 tools total now.

0.1.0 — initial release: 6 tools, tier abstraction (fast / balanced / deep), model IDs hidden from the agent.

Setup

  1. Sign up at https://app.mycouncil.xyz (10 free rounds).
  2. Pick your auto-config mode under Account → Auto-config Settings (standard is free; advanced costs 1 round per call).
  3. Create an API key under Account → API. The key is shown once — save it.
  4. Register the MCP server in your client (see below).

Nothing to install — uvx fetches the package on first use. Requires uv (curl -LsSf https://astral.sh/uv/install.sh | sh).

Claude Code

claude mcp add mycouncil \
  --env MYCOUNCIL_API_KEY=mc_your_key_here \
  -- uvx mycouncil

Claude Desktop / Cursor

In claude_desktop_config.json or ~/.cursor/mcp.json:

{
  "mcpServers": {
    "mycouncil": {
      "command": "uvx",
      "args": ["mycouncil"],
      "env": { "MYCOUNCIL_API_KEY": "mc_your_key_here" }
    }
  }
}

Running over streamable HTTP

By default the server runs over stdio — one process per client, spawned by the MCP client. You can instead run it as a single long-lived streamable-http service:

MYCOUNCIL_API_KEY=mc_your_key_here \
  uvx mycouncil --transport streamable-http --host 127.0.0.1 --port 8000

The endpoint is then http://<host>:<port>/mcp. Point any streamable-http MCP client at it:

{
  "mcpServers": {
    "mycouncil": {
      "type": "streamable-http",
      "url": "http://127.0.0.1:8000/mcp"
    }
  }
}

Or, with the Claude Code CLI (no env var on the client — the key lives with the running service):

claude mcp add --transport http mycouncil http://127.0.0.1:8000/mcp

By default this is single-identity (--auth shared): every request uses the one MYCOUNCIL_API_KEY the process was started with — all callers share that account's rounds and balance. The transport runs in stateless mode (a fresh transport per request), so there is no session affinity to manage. For one wrapper serving many accounts, see Per-request auth.

Per-request auth (multi-account)

--auth per-request makes each HTTP call authenticate itself: the caller passes their own myCouncil key on every request, and the wrapper uses it for exactly that call. No key is read from the environment; different callers spend their own rounds.

uvx mycouncil --transport streamable-http --host 0.0.0.0 --port 8000 \
  --auth per-request

The key is taken from (first match wins):

  1. X-MyCouncil-Key: mc_... — dedicated header; use it when a proxy in front of the wrapper already occupies Authorization for its own auth.
  2. Authorization: Bearer mc_... — the standard form.

Client config example (any streamable-http MCP client that supports custom headers):

{
  "mcpServers": {
    "mycouncil": {
      "type": "streamable-http",
      "url": "https://your-host.example/mcp",
      "headers": { "Authorization": "Bearer mc_your_key_here" }
    }
  }
}

Or with the Claude Code CLI:

claude mcp add --transport http mycouncil https://your-host.example/mcp \
  --header "Authorization: Bearer mc_your_key_here"

Calls without a key are rejected with a structured {"error": "api_error", "status_code": 401, ...} payload — there is no silent fallback to an environment key, so a misconfigured client can never spend someone else's rounds. --auth per-request requires --transport streamable-http (stdio has no request headers; startup fails otherwise).

Always put TLS in front of this mode. API keys travel in request headers on every call; terminate HTTPS at your reverse proxy. Plain http:// is acceptable only on 127.0.0.1.

Notes:

  • Binding beyond localhost. The default bind is 127.0.0.1. If you set --host 0.0.0.0 (e.g. behind a reverse proxy), the localhost-only DNS-rebinding guard is relaxed automatically — put the service behind your own proxy / network controls, since anyone who can reach the port spends the configured key's quota.
  • Long-running debates. Blocking mycouncil_debate holds the HTTP response open while it polls (up to timeout_minutes, default 20) with no bytes flowing. Raise idle timeouts on any intermediary proxy, or prefer the async pair mycouncil_debate_start + mycouncil_debate_status over HTTP.

All flags have environment-variable equivalents (MYCOUNCIL_TRANSPORT, MYCOUNCIL_HTTP_HOST, MYCOUNCIL_HTTP_PORT, MYCOUNCIL_HTTP_PATH, MYCOUNCIL_HTTP_AUTH) — see Environment variables.

RAG modes

--rag-mode {prelude|debate} (env: MYCOUNCIL_RAG_MODE) connects debates to an external RAG corpus of stakeholder call transcripts. Off by default: without the flag the debate tool schemas contain no rag parameters at all, so agents can't pass them by accident. Both modes work on both transports (parameters travel in the tool call, not in HTTP headers, so stdio works too) and compose with --auth per-request. Tokens are never logged, stored, or echoed into results in either mode.

Prelude mode (--rag-mode prelude)

The wrapper searches once, before the debate. Adds two optional per-call parameters to mycouncil_debate and mycouncil_debate_start:

Parameter What it is
rag_access_token Short-lived (~30 min) bearer token for the RAG service, issued per debate.
rag_base_url Base URL of the RAG service, e.g. https://rag.example.com.

When a call carries both, the wrapper runs one hybrid search (POST {rag_base_url}/v1/search, collection stt-calls, top_k 5) and sends the debate content to the server as:

### Question
<original content>

### Useful info
1. <excerpt from a stakeholder call> (score 0.91; source: ...)
2. ...

Behaviour details:

  • Both parameters omitted (or only one given) → plain debate, exactly as without the flag. RAG is an enrichment, not a dependency.
  • The result carries rag_prelude: "applied" or rag_prelude: "skipped (...)" so integrators can verify the prelude ran.
  • Failure policy: 401 from RAG → no retry (token is dead), run the debate plain; network errors / 5xx → one retry with backoff, then run plain. A RAG outage never fails a debate.

--rag-prelude (env: MYCOUNCIL_RAG_PRELUDE=1) is a deprecated alias for this mode; combining it with --rag-mode debate fails at startup.

Debate mode (--rag-mode debate)

The wrapper performs no searching at all — it forwards RAG parameters to the debate API as a retrieval object, and the council's agents query the corpus themselves, mid-debate (requires a myCouncil server with in-debate retrieval support). Parameters added to the debate tools:

Parameter What it is
rag_access_token Pooled bearer token — every council agent gets the memory-search tool.
rag_access_tokens Map of expert index to token, e.g. {"0": "...", "2": "..."} — only those experts get the tool. Requires an explicit config.experts list.
rag_base_url Base URL of the RAG service. Required with any token.
rag_max_requests Optional search budget, set by whoever issued the token (server default: 5).
rag_expires_in Optional token TTL in seconds, informational.

Validation happens in the wrapper before any API call: rag_access_token and rag_access_tokens are mutually exclusive; per-agent tokens require explicit experts (auto-config doesn't know the lineup in advance) and string-number keys within the expert index range; a token without rag_base_url is an error. Violations return {"error": "invalid_rag_params", "detail": ...}.

The result carries rag: the server's no-secrets retrieval summary (e.g. {"agents": ["agent_0"], "max_requests": 25, "used": 7}), or rag: "skipped (API does not support in-debate retrieval)" when the server predates the feature — there is no silent fallback to prelude.

Tools

Tool What it does
mycouncil_info One-call agent orientation: flows, tier semantics, quota notes. Call once at the start of a session.
mycouncil_balance Remaining rounds + current auto-config mode.
mycouncil_list_roles List curated system + own + team expert roles. Use their id as role_preset when composing a custom council.
mycouncil_auto_config Generate a session config from a query. Returns roles + temperatures + tier. Concrete model IDs are not exposed — the planner and the server pick them based on the tier.
mycouncil_debate_start Start a debate, return job_id. Accepts a config returned by mycouncil_auto_config (with or without edits). Optional max_rounds / initial_budget — see Quotas and debate settings.
mycouncil_debate_status Poll a debate by job_id.
mycouncil_debate Blocking: start, poll, return the finished result. return_as: pdf (default) / transcript / link. Same optional max_rounds / initial_budget.
mycouncil_share Share or export an existing conversation: format=link (public URL) or format=pdf (file on disk).

How tiers work

The planner LLM picks one of three operating tiers based on the question:

  • fast — quick + cheap models, for simple / casual questions.
  • balanced — sweet spot. Default for typical analytical questions.
  • deep — slow + reasoning-heavy models, for high-stakes / complex / irreversible decisions. Only available in advanced auto-config mode.

Tiers are an operating mode, not a quality rank — deep does not always beat balanced in absolute terms, it just takes more time and money. The planner is instructed to lean toward balanced and not escalate by default.

After mycouncil_auto_config, you may edit config["tier"] and roles before passing it to mycouncil_debate(_start). MCP fills concrete models from the tier locally; the agent never sees specific provider names.

Quotas and debate settings

What a debate reserves at start (the unused part is refunded when it finishes):

session_type Kind Reserve Setting
1 three-stage council 1 round
2 moderated debate max_rounds (default 5), charged per iteration run adf_settings.max_rounds
3 competitive debate initial_budget × experts (default budget 5), charged by the points the debaters burn adf_settings.initial_budget (1-10)

For type 3 max_rounds is only a hidden iteration ceiling, not a price — don't set it. A 403 "Not enough rounds. Need 20, have 5" on type 3 means e.g. 4 debaters × budget 5: lower the budget or the expert count.

Both settings live in config["adf_settings"]:

{"session_type": 2, "tier": "balanced", "experts": [...], "chairman": {...},
 "adf_settings": {"max_rounds": 3}}

The server reads them only there; max_rounds / initial_budget at the top level of config are ignored (and echoed back in config_used, so the mistake is invisible). Since 0.6.1 the wrapper normalizes before sending:

  • top-level max_rounds / initial_budget are moved into adf_settings (an explicit adf_settings value wins) and removed from the top level;
  • the tools' max_rounds / initial_budget parameters override both;
  • a setting that doesn't fit the session type — max_rounds on type 1, initial_budget on anything but type 3, either without a config — returns {"error": "invalid_params", "detail": ...} before any API call;
  • values are forwarded as-is (no client-side bounds); the server clamps initial_budget to 1-10.

Other quota notes:

  • mycouncil_auto_config is free in standard mode, 1 round in advanced mode (refunded if the planner LLM fails).
  • mycouncil_debate auto-configures internally if you don't pass a config — calling mycouncil_auto_config first only makes sense to preview / tweak the config. In advanced mode that bills you twice.

Environment variables

Variable Required Default Notes
MYCOUNCIL_API_KEY yes* Your mc_* key from Account → API. *Not read in per-request auth mode — keys arrive in request headers instead.
MYCOUNCIL_BASE_URL no https://app.mycouncil.xyz Override for staging / self-hosted.
MYCOUNCIL_TRANSPORT no stdio stdio or streamable-http. Overridden by --transport.
MYCOUNCIL_HTTP_HOST no 127.0.0.1 Bind host for streamable-http. Overridden by --host.
MYCOUNCIL_HTTP_PORT no 8000 Bind port for streamable-http. Overridden by --port.
MYCOUNCIL_HTTP_PATH no /mcp Endpoint path for streamable-http. Overridden by --path.
MYCOUNCIL_HTTP_AUTH no shared shared or per-request (streamable-http only). Overridden by --auth.
MYCOUNCIL_RAG_MODE no off prelude or debate — see RAG modes. Overridden by --rag-mode.
MYCOUNCIL_RAG_PRELUDE no off Deprecated alias: 1/true equals MYCOUNCIL_RAG_MODE=prelude.

Examples

Simplest path — let myCouncil pick everything:

Run mycouncil_debate on "Should we migrate our backend from FastAPI to Go?" and return the result as a PDF in ./review.pdf.

Preview and escalate the tier before running (advanced mode):

Use mycouncil_auto_config for "Replace our entire ML infra with a custom RAG system, $3M budget". If the planner returns tier: balanced, change it to deep and run mycouncil_debate with the edited config.

Async polling:

Start the debate with mycouncil_debate_start, then poll mycouncil_debate_status every minute until status is complete or failed.

License

Apache 2.0.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mycouncil-0.6.1.tar.gz (38.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mycouncil-0.6.1-py3-none-any.whl (35.1 kB view details)

Uploaded Python 3

File details

Details for the file mycouncil-0.6.1.tar.gz.

File metadata

  • Download URL: mycouncil-0.6.1.tar.gz
  • Upload date:
  • Size: 38.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.26

File hashes

Hashes for mycouncil-0.6.1.tar.gz
Algorithm Hash digest
SHA256 8d49ddda2e145bbe443565bd27f9deca09405c273b3d830589a52b7cf815af40
MD5 72259167b55830388cef39b986415dce
BLAKE2b-256 062d3574de91d4c5129faf6bf4a844e66c4265ce85d58779d0b06f9cfd375f23

See more details on using hashes here.

File details

Details for the file mycouncil-0.6.1-py3-none-any.whl.

File metadata

  • Download URL: mycouncil-0.6.1-py3-none-any.whl
  • Upload date:
  • Size: 35.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.26

File hashes

Hashes for mycouncil-0.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 77ade005d6bf46a5e79b008024cce1ec53c06fcbbf1692dfba8aadc7dc05aa6b
MD5 b51bf03e95ee40a1d87f783d6c3c6cd5
BLAKE2b-256 fb593dcadcd152a3c958533ff20227a2a3b34c03375d083df3e9e1a5200b021d

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.6.1 This release

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page