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

@devflow-one/mcp

v0.1.17

Published

stdio MCP server exposing DevFlow gateway repo actions as tools for AI agents

Readme

@devflow-one/mcp — stdio MCP server

Exposes the DevFlow local gateway's repo actions (branch, PR/MR, pipeline, reviewers) as MCP tools so AI agents, skills, and workflows can drive them.

It is a thin stdio client of the local gateway the desktop app runs (desktop/src/gateway/server.js). It reads the same auto-generated token file, routes by Jira project key, and returns the gateway's result. No provider API logic lives here.

How it works

  • One MCP tool per gateway action (19 actions), each with a typed input schema: routing fields (issueId / projectKey / profile / repo) plus the action's own args. Tool names are snake_case (create_branch); the gateway's own action names stay camelCase and are unaffected by them.
  • All four routing fields are optional — omitted, they are inferred from the working directory (see Zero-config routing below).
  • A list_actions discovery tool returns the gateway's advertised actions and the connected profiles (with the project keys each owns). It reports the gateway's camelCase names, not the snake_case tool names — call the tools.
  • A resolve_context tool answers "where am I?" — the project, issue, repo (with its configured baseBranch) and owning profile inferred from the working directory. Read-only.
  • Every call is POST /actions/:gatewayAction on 127.0.0.1:8787 with the Bearer token (e.g. the create_branch tool posts to /actions/createBranch).
  • Gateway/routing failures (NO_PROFILE, AMBIGUOUS_PROFILE, NO_CONTEXT, TIMEOUT, or an unreachable daemon) come back as structured tool errors (isError: true).
  • Destructive tools (delete_branch, close_pull_request, merge_pull_request) take an allowDestructive input and are refused with DESTRUCTIVE_BLOCKED unless it is true — enforced both here and by the gateway, so it can't be bypassed. Confirmation is never inferred.

Zero-config routing

An agent working inside a configured repo checkout does not need to know the project key. When a routing field is omitted, it is inferred — highest precedence first:

  1. the explicit tool input
  2. DEVFLOW_PROJECT / DEVFLOW_ISSUE / DEVFLOW_REPO / DEVFLOW_PROFILE
  3. the checkout's origin remote, matched against your configured repos
  4. the checkout path, matched against each repo's configured local path
  5. the issue key in the current branch name (feature/ABC-123-thing → ABC-123)
  6. a Jira-key-shaped ancestor directory (~/work/ABC-123/repo)

So inside a configured checkout this is enough:

{ "name": "create_branch", "arguments": { "branchName": "feat/ABC-123" } }

Passing a field always overrides inference. Supplying projectKey (or issueId) also drops any repo/profile that was inferred for a different project, so an explicit key can never be paired with another project's repo.

When inference can't decide

Nothing is ever guessed — each case is a structured error naming the fix:

| Code | Meaning | What to do | | --- | --- | --- | | AMBIGUOUS_PROFILE | Several configured repos match this directory. The error carries a candidates list. | Retry with projectKey (or repo) naming one. | | NO_CONTEXT | No routing input, and the directory matches no configured repo. | Pass projectKey or issueId, or call resolve_context to see what is inferable. | | NO_PROFILE | The owning Chrome profile is known but not running. The message names it. | Open that Chrome profile with the extension enabled, then retry. |

The last one matters: actions execute in the browser extension, so the profile that owns a project must be running. The daemon remembers which profile owns which project even while it's closed, so the error can name it instead of just failing.

Prerequisites

  • The DevFlow desktop app must be running — it hosts the gateway and writes the token, so nothing here works without it. v1 also requires the browser extension connected for a profile to own project keys.
  • Node >= 20 (for npx).

No clone, no build: the server is published to npm as @devflow-one/mcp and runs straight from npx.

Install

Claude Code

claude mcp add devflow -- npx -y @devflow-one/mcp

Cursor, Claude Desktop, and other JSON-configured clients

The same entry works in .cursor/mcp.json, claude_desktop_config.json, and project-level .mcp.json:

{
  "mcpServers": {
    "devflow": {
      "command": "npx",
      "args": ["-y", "@devflow-one/mcp"]
    }
  }
}

Intent by Augment (~/.augment/settings.json)

Intent injects mcpServers from its global settings into every agent it spawns:

{
  "mcpServers": {
    "devflow": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@devflow-one/mcp"],
      "env": {}
    }
  }
}

Intent aborts an agent whose MCP servers take more than a few seconds to answer initialize, and a cold npx download can cross that. If the server shows up as Connection closed, install it once and point command at the built entry instead of npx:

mkdir -p ~/.augment/mcp-servers && cd ~/.augment/mcp-servers && npm i @devflow-one/mcp
{
  "devflow": {
    "type": "stdio",
    "command": "/absolute/path/to/node",
    "args": ["/Users/you/.augment/mcp-servers/node_modules/@devflow-one/mcp/dist/index.js"],
    "env": {}
  }
}

command must be the executable alone — flags such as -y belong in args. Intent reads the config on every agent spawn, so a running agent keeps its old (failed) connection until it is replaced with a new one.

Codex CLI (~/.codex/config.toml)

[mcp_servers.devflow]
command = "npx"
args = ["-y", "@devflow-one/mcp"]

Restart the client after editing its config, then check that the devflow tools (starting with list_actions) are listed.

Token & port (zero-config)

The token and port are discovered automatically from the file the desktop app writes. Override when needed:

| Env var | Purpose | | --------------------------- | ---------------------------------------------------- | | DEVFLOW_GATEWAY_TOKEN | Provide the token directly (skips the file lookup). | | DEVFLOW_GATEWAY_TOKEN_PATH| Override where the token file is read from. | | DEVFLOW_GATEWAY_PORT | Gateway port (default 8787). |

Routing defaults, applied when a tool input is omitted (see Zero-config routing):

| Env var | Overrides | | ------------------ | ------------------- | | DEVFLOW_PROJECT | projectKey | | DEVFLOW_ISSUE | issueId | | DEVFLOW_REPO | repo | | DEVFLOW_PROFILE | profile |

Usage examples (tool calls)

// discover what's available
{ "name": "list_actions", "arguments": {} }

// what does the working directory imply? (project, issue, repo, profile + liveness)
{ "name": "resolve_context", "arguments": {} }

// the branch an issue's work belongs on, from the repo's branch template (incl.
// {parentIssueKey}: a sub-issue may resolve to its parent's branch) + whether it exists.
// Check it out before committing — commit_by_template commits the checked-out branch.
{ "name": "resolve_branch_name", "arguments": { "issueId": "ABC-124" } }

// create (or reuse, if it exists) the issue's configured branch. The template always
// wins; a passed branchName is only a fallback, and a replaced one is listed in `warnings`.
// → { "branchName": "ABC-123", "created": false, "parentIssueKey": "ABC-123", "warnings": [] }
{ "name": "create_branch", "arguments": { "issueId": "ABC-124" } }

// inside a configured checkout — no routing fields needed at all
{ "name": "create_branch", "arguments": { "branchName": "feat/ABC-123" } }

// list the configured PR types (id, label, isDefault) to pick a valid prType
{ "name": "list_pr_types", "arguments": { "projectKey": "ABC" } }

// open a PR/MR — always created as a draft. The PR type supplies the templates and
// labels; an omitted or unrecognized prType is auto-selected by matching type names
// against the title's conventional prefix, branch prefix, Jira issue type and title
// keywords, falling back to the first type. Pass a type's id or label when you know better.
{ "name": "create_draft_pull_request", "arguments": { "projectKey": "ABC", "title": "Fix login", "body": "…", "headBranch": "feat/x" } }
{ "name": "create_draft_pull_request", "arguments": { "projectKey": "ABC", "title": "Fix login", "body": "…", "headBranch": "feat/x", "prType": "Bugfix" } }

// the issue key is parsed from headBranch; an explicit issueId overrides it (issue-key
// label + {issueKey}/{issueTitle} tokens). {issueTitle} needs the Jira API token set in
// Settings, else it renders empty. The branch template always picks the source branch,
// so headBranch may be omitted; a different one is replaced and listed in `warnings`.
{ "name": "create_draft_pull_request", "arguments": { "issueId": "ABC-123", "title": "Fix login", "body": "…" } }

// …then take it out of draft when it's ready
{ "name": "mark_pr_ready_for_review", "arguments": { "projectKey": "ABC", "prId": 42 } }

// read a PR/MR's current title + description, then edit it. title/description replace;
// appendDescription adds text after a `---` rule, skipped if it's already at the end
{ "name": "get_pull_request", "arguments": { "projectKey": "ABC", "prId": 42 } }
{ "name": "update_pull_request", "arguments": { "projectKey": "ABC", "prId": 42, "appendDescription": "## Test plan\n…" } }
{ "name": "update_pull_request", "arguments": { "projectKey": "ABC", "prId": 42, "title": "Fix login redirect" } }

// routing by issue id (prefix → project key)
{ "name": "find_pr_by_issue_key", "arguments": { "issueId": "ABC-123", "issueKey": "ABC-123" } }

// pipeline status
{ "name": "get_pipeline_status", "arguments": { "issueId": "ABC-123", "ref": { "prId": 42, "headSha": "abc123" } } }

// commit a managed worktree with the project's commit-message template
{ "name": "commit_by_template", "arguments": { "projectKey": "ABC", "worktreePath": "/wt/ABC-123", "values": { "summary": "fix login" }, "push": false } }

// …or the repository's configured checkout (its localPath): only already-staged changes are committed
{ "name": "commit_by_template", "arguments": { "projectKey": "ABC", "worktreePath": "/code/app", "values": { "summary": "fix login" } } }

// assembled fix-review-comments prompt (read-only; runs no AI, makes no writes)
{ "name": "get_fix_comments_prompt", "arguments": { "issueId": "ABC-123", "prId": 42 } }

// notify the project's configured Slack channel(s)
{ "name": "notify_slack", "arguments": { "projectKey": "ABC", "message": "Review fixes ready on {pr}", "values": { "pr": "#42" } } }

// destructive — must confirm, else DESTRUCTIVE_BLOCKED
{ "name": "delete_branch", "arguments": { "projectKey": "ABC", "branchName": "old", "allowDestructive": true } }
{ "name": "merge_pull_request", "arguments": { "projectKey": "ABC", "prId": 42, "mergeMethod": "squash", "deleteSourceBranch": true, "allowDestructive": true } }

Local development (contributors only)

Users don't need this — it's for working on the server itself from a clone of the monorepo:

cd mcp
npm install
npm run build      # → dist/index.js (the stdio entry point)

Point a client at the local build instead of the published package:

claude mcp add devflow-local -- node /absolute/path/to/monorepo/mcp/dist/index.js

Verify

npm test      # unit: action catalog, arg construction, routing, context inference
npm run verify   # scripted stdio client against a mock gateway (lists tools, calls list_actions + resolve_context + a real action, and checks the inference/ambiguity/offline-profile refusals)

The context resolver (src/contextResolver.js, src/gitFacts.js) is a generated copy of shared/ — edit the shared source and run npm run sync:shared, never the copy.

Releasing

Publishing this package to npm is a manual, dry-run-first process — see RELEASING.md at the repo root.