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

@zvndev/circular-mcp

v0.2.1

Published

Dependency-free stdio MCP server for the Circular Agent API — plan work into Circular as tracked tasks and subtasks.

Downloads

754

Readme

circular-mcp — Circular over MCP

A dependency-free stdio MCP server that exposes the Circular Agent API as tools any MCP client can call. Point Claude Code, the Codex CLI/app, Cursor, or any stdio MCP client at it and your agent can list issues, create tasks and subtasks, pull run context, and — the headline — turn a plan into a tracked task tree in one call.

Same philosophy as the circular CLI: plain Node ≥ 20, no npm dependencies. It shares the CLI's HTTP client, so the two surfaces never drift.

Tools

All tools are prefixed circular_:

| Tool | What it does | |---|---| | circular_get_next_work | Pull work. Up to limit candidate issues (highest priority first), each with its process: the team's playbook, the step ladder with completion state, and the definition of done. Excludes done, cancelled, and blocked issues. Does not claim. | | circular_complete_step | Tick one ACTION step complete with proof. REVIEW steps are refused with 403 by design. | | circular_list_issues | List issues; filter by status, assigneeId, or parentId ("none" = roots only). | | circular_get_issue | Full detail for one issue (description, comments, activity, parent, subtasks). | | circular_create_issue | Create one issue; parentId makes it a subtask; ownerParticipantId can assign an agent owner. | | circular_update_issue | Update status / priority / title / assignee / agent owner. | | circular_comment_issue | Post a comment (proof of work, handoff notes). | | circular_get_context | Pull the exact context a run would receive for a project/issue, now including the issue's process (playbook + steps). | | circular_save_plan | Save a free-text plan doc that feeds future context. | | circular_plan_tasks | Batch plan → tasks: one atomic call creates a plan doc + parent issues + subtasks, returns every id + identifier (ENG-N). Caps: ≤50 tasks, ≤20 subtasks each. | | circular_list_projects | Discover the projects this team works in (for the projectId the tools above need). | | circular_focus | The person's own Focus queue: every track, its name, and its items in order. | | circular_focus_next | The head of every track: one candidate each, skipping finished work. | | circular_focus_task | One task by id, <identifier> in any case, or bare number, with its queue position and what is behind it in its track. |

Your own Focus

Focus is the queue a person arranges for themselves: parallel tracks, each holding tasks in order. The three tools above read it with the login this server is running under, so a session can start on what that person actually queued instead of asking them to name a task.

A Focus belongs to a person, so the credential rule is strict. A browser sign-in or a personal login of your own (circular login) may read that person's own queue. A team API key is refused with 403, because a team key is not a person and "me" would silently resolve to whoever minted it. Reading is all that is on offer: arranging, reordering and marking stay in the app with a real sign-in.

A bare number that more than one team uses comes back as a list of candidates rather than a guess. Ask which one.

next on a task is the first unfinished task behind it in the same track, and never that track's head. A task with nothing behind it has next: null, which means the track is clear, not that it starts again from the top.

circular_focus_task answers a reference whether or not it is queued: a task outside the queue is found by one bounded read of the team the reference names, and comes back with focus: null because it has no queue position. Either way the task itself is fetched, so the description is whole and the process steps are there to record proof on.

Local Desktop mode

Use circular-mcp --local when an agent is running beside Circular Desktop and only needs read-only context from that running app. Local mode exposes a separate tool set (circular_local_context, circular_local_sessions, circular_local_focus, circular_local_next, circular_local_task and circular_local_focus_on) and does not load managed browser logins, CIRCULAR_API_KEY, workspace/team ids, or cloud HTTP configuration.

circular_local_task and circular_local_focus_on take an internal id, an <identifier> in any case, or a bare number. circular_local_focus_on answers with the task, its place in the queue, and the task to offer once it is finished, so a skill has one call rather than three. Desktop is worth preferring when it is running: it is the only source that knows which tasks other live sessions are already holding.

Desktop advertises the socket through CIRCULAR_LOCAL_ENDPOINT plus CIRCULAR_LOCAL_TOKEN, which must be set together, or through <desktop-data-dir>/local-context.json with { "version": 1, "endpoint": "...", "token": "...", "pid": 123 }. CIRCULAR_LOCAL_THREAD_ID is passed through when present.

{
  "mcpServers": {
    "circular-local": {
      "command": "npx",
      "args": ["--yes", "@zvndev/circular-mcp", "--local"]
    }
  }
}

The planning loop: circular_get_context → plan → circular_plan_tasks → hand each returned ENG-N to a sub-agent → circular_update_issue / circular_comment_issue to track progress and post proof.

The execution loop: circular_get_next_work → pick a candidate and reserve it with circular_claim_issue_work → move ordinary product status with circular_update_issue status=in_progress → work through the playbook → circular_complete_step with proof per step → release the reservation with circular_release_issue_work_claimcircular_update_issue status=done.

Read situation.disposition before acting

Every candidate comes back with a situation saying where you stand on it, so an agent never has to probe the API and read refusals to find out:

| disposition | What to do | |---|---| | ready_for_you | The open step is an ACTION step you may complete. Proceed | | waiting_on_human_review | Parked on a REVIEW step. No API key can tick it. Skip | | waiting_on_automation | An AUTOMATION step, ticked by its own signal. Skip | | assigned_to_someone_else | The open step names another person, team, or agent. Skip | | process_complete | Every step ticked; it only needs closing | | no_process | No ladder. Do the work, comment, set it to done | | ladder_unreadable | Steps cannot be parsed. Do the work only if it is otherwise clear, then comment |

situation.currentStep carries the open step's id, kind, assignment, assignedTo, canComplete, and a refusal reason when you may not complete it. The response's actor block tells you who Circular thinks you are, including canCompleteReviewSteps, which is always false for an API key.

Full reference, including every refusal and the stricter per-step sign-off route: docs/AGENT_INTEGRATION.md.

Agent ownership

Human assignment and agent ownership are separate fields. assigneeId names the human assignee; ownerParticipantId names the agent participant that owns the work. Creating or updating with ownerParticipantId uses the same API field as the web app, so existing workspace/team permission checks still apply. On circular_update_issue, omit ownerParticipantId to preserve the current agent owner, or send ownerParticipantId: null to deliberately clear it. Clearing the agent owner does not remove human collaborators.

Processes: how a team's business logic reaches your agent

A process is a reusable definition of how one kind of work gets done: an ordered set of steps plus a markdown playbook, mapped to issues by label (or a workspace default). circular_get_next_work and circular_get_context hand it to you with the issue, so you never have to guess a team's conventions.

Steps come in three kinds:

  • ACTION: you do it, then tick it with circular_complete_step and real evidence in proof (test output, a diff summary, a link).
  • REVIEW: a human gate. circular_complete_step answers 403 for these, always: an agent may never sign off its own review. Enrolled runner connections cannot mark done with open stored REVIEW or AUTOMATION steps, even when paused. Legacy callers retain the configured legacy process-gate policy (currently off); an unticked review is never an agent approval. Post proof/commentary.
  • AUTOMATION: ticked by its own CI/GitHub signal, not by hand.

circular_get_next_work deliberately does not reserve the issue it returns. Reservations live in circular_claim_issue_work, keyed by a stable request id for safe retry after a lost response. Several candidates come back so two agents pulling at the same moment can pick another candidate if a reservation loses.

MCP tools versus an always-on computer

Adding this stdio connector makes tools available to an agent. It does not start a provider, register a worker, or install a background service. Circular's cloud durably queues assignments, mentions and workflow events. An explicitly enrolled foreground local runner polls its addressed deliveries and launches the installed Codex or Claude CLI on that computer, one job at a time. Its connection and provider subscription stay private to that computer.

Use the public connection docs after browser login (or importing an admin-created workspace-agent connection), linking the project repository, and connecting the local checkout. Keep circular runner start --connection CONNECTION_ID running; an OS service is a separate explicit operator setup, never an automatic side effect of installing MCP or Desktop.

runner register --allow-circular-tools explicitly permits unattended use of the runner's generated Circular MCP tools. --allow-write separately permits local code edits within the grant/profile ceiling. Neither flag grants access to unrelated MCP servers or lets an agent approve human-only steps. A runner works its already leased delivery rather than pulling unrelated next-work candidates. Registration requires the explicit Circular tool opt-in to avoid provider approval prompts stranding headless work. Use an interactive agent if you do not want unattended tool calls.

Authentication

Identical to the CLI. The normal path is managed browser sign-in:

npx -y @zvndev/circular-cli login --runtime codex

That command opens Circular, asks the signed-in human to approve a named agent, then stores the managed connection locally in ~/.circular/connections.json. No API key has to be copied into an agent prompt or MCP config.

For long-running MCP processes, pin the connection id returned by login:

CIRCULAR_CONNECTION_ID=key_or_connection_id_from_login

Owners/admins can still provide an explicit team API key (circ_tk_…) for ongoing workspace agents or legacy automation. MCP clients inject these through the server's env block:

CIRCULAR_API_KEY=circ_tk_xxx
CIRCULAR_WORKSPACE_ID=ws_xxx
CIRCULAR_TEAM_ID=team_xxx
CIRCULAR_BASE_URL=https://gocircular.dev   # optional; default

~/.circular/config.json also works as a fallback for explicit keys. An explicit key always wins over managed login; a Desktop-bound agent identity does not borrow a managed or global fallback credential.

Minting a team API key

In Circular, go to Team → Access → API keys and create a key. Optionally bind it to an agent participant so every write (issues, comments, activity) is attributed to that agent. Copy the circ_tk_… value — it is shown once.

Registration

The published package exposes the circular-mcp binary through npx. For local source development, replace the npx -y @zvndev/circular-mcp command below with node /ABS/PATH/mcp/bin/circular-mcp.mjs.

Claude Code

claude mcp add circular \
  -e CIRCULAR_CONNECTION_ID=key_or_connection_id_from_login \
  -- npx -y @zvndev/circular-mcp

Then, in a session, the tools are available as mcp__circular__*, e.g.:

claude -p "use the circular MCP tools to list issues" --allowedTools "mcp__circular__*"

Codex CLI / app

Via the CLI:

codex mcp add circular \
  --env CIRCULAR_CONNECTION_ID=key_or_connection_id_from_login \
  -- npx -y @zvndev/circular-mcp

Or add the block directly to ~/.codex/config.toml:

[mcp_servers.circular]
command = "npx"
args = ["-y", "@zvndev/circular-mcp"]
env = { CIRCULAR_API_KEY = "circ_tk_xxx", CIRCULAR_WORKSPACE_ID = "ws_xxx", CIRCULAR_TEAM_ID = "team_xxx" }

For a managed connection, use:

env = { CIRCULAR_CONNECTION_ID = "key_or_connection_id_from_login" }

Verify with codex mcp list / codex mcp get circular.

Cursor

Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json (per-project):

{
  "mcpServers": {
    "circular": {
      "command": "npx",
      "args": ["-y", "@zvndev/circular-mcp"],
      "env": {
        "CIRCULAR_API_KEY": "circ_tk_xxx",
        "CIRCULAR_WORKSPACE_ID": "ws_xxx",
        "CIRCULAR_TEAM_ID": "team_xxx"
      }
    }
  }
}

Generic stdio MCP client

Any client that speaks the MCP stdio transport uses the same shape:

{
  "command": "npx",
  "args": ["-y", "@zvndev/circular-mcp"],
  "env": {
    "CIRCULAR_API_KEY": "circ_tk_xxx",
    "CIRCULAR_WORKSPACE_ID": "ws_xxx",
    "CIRCULAR_TEAM_ID": "team_xxx"
  }
}

Agent skill

Registering the server gives an agent the tools; the circular-planning skill (skills/circular-planning/) gives it the discipline — when to pull context, how to materialize a plan with circular_plan_tasks, and how to delegate one ENG-N per sub-agent with proof-of-work. Install it with npm run install-agent-skill (repo root). See skills/circular-planning/README.md.

Protocol notes

  • Transport: MCP stdio — newline-delimited JSON-RPC 2.0 (one message per line on stdin/stdout; logs go to stderr).
  • Implements initialize, notifications/initialized, tools/list, tools/call, and ping. Protocol version negotiated at initialize (defaults to 2025-06-18).
  • Tool execution errors (e.g. an API 4xx) are returned in-band as a tools/call result with isError: true, not as a JSON-RPC protocol error, so the agent can read and react to them.

Development

npm test        # node --test — exercises the JSON-RPC dispatcher + tool registry

# Drive a live session by hand:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | CIRCULAR_API_KEY=circ_tk_xxx \
  CIRCULAR_WORKSPACE_ID=ws_xxx CIRCULAR_TEAM_ID=team_xxx node bin/circular-mcp.mjs