MCP-first control plane for ProAgentStore agents and private instances.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
Marketplace for server-powered AI agents. Creators build agent templates, clients subscribe and run them on their own data.
Store: https://proagentstore.online API: https://api.proagentstore.online MCP: https://mcp.proagentstore.online/mcp Console: https://proagentstore.online/console/ GitHub: https://github.com/ProAgentStore Free pair: https://freeagentstore.online
| Type | Template | What it does |
|---|---|---|
| Agent | worker | Full AI: conversation, memory, knowledge base, core tools, Workers AI |
| Worker | cron | Scheduled tasks: daily digests, monitoring, batch processing |
| Tool | api | Stateless endpoint: transform, generate, analyze |
MCP has two runtime modes:
chat_with_agent calls the public trial endpoint. Use it for discovery and smoke tests.subscribe_agent creates your private instance, then chat_with_instance runs that instance with your own state, knowledge, and caller-provided AI credentials.Typical user run:
The expected response when user-owned AI credentials are missing is:
That means the instance runtime path is working and correctly refusing to bill the platform AI account. See MCP Instance Runtime for the full tool map, live test record, and OAuth troubleshooting.
The full MCP-first developer surface is documented at:
MCP safety is enforced server-side. OAuth supports read, write, runtime, and destructive scopes; MCP_READ_ONLY=1 forces read-only mode; mutating tools support dry_run where useful; overwrite/destructive tools require exact confirm values; and mcp_audit_log exposes recent MCP write, runtime, dry-run, denied, and destructive events.
The current system map, runtime boundaries, data ownership rules, risk assessment, and refactor roadmap live in Architecture.
pags up)Browser- and coding-capable agents use PAGS as the control-plane brain and a local ProAgentStore browser runtime (runtimePlane: "pags", Playwright + terminal/coding capabilities, bundled into the CLI) as the hands. One public package, one command β no monorepo and no tunnel binary.
pags up is the canonical runner: one process serves every active instance whose capabilities.runtime is non-null. Cloud-only chat/RAG/connector agents (runtime: null) are skipped β they never need a local runner.
Membership is live, not a startup snapshot. pags up passes --watch-instances (CLI β₯ 0.4.30), so the runner re-reads /v1/instances/my/instances every 20s and attaches newly eligible agents β and detaches ones that stopped being eligible β without a restart. Subscribing to a coding agent while the runner is up just works. (Polling, not push: a brand-new instance has no socket to push over; #83 tracks the push path.) A scoped pags up --instance <id> deliberately does not watch β it means that one agent and nothing else.
Transport is a WebSocket relay: the runner connects outbound to a per-(instance, node) RelayDO β no cloudflared, no public server, no inbound port. Cloud -> callRunner() -> RelayDO -> WebSocket -> runner. There is no --tunnel flag or tunnel fallback in the current CLI. The runner mints a short-lived, instance-scoped relay token for the handshake; the 30-day account JWT is never put in the WebSocket URL.
pags up --force β replace the current relay socket when debugging stale local connectionspags up --instance <id> β pin to one agent (debug)pags up --headless β headless modeThe job-application agent runs on this runtime via the LLM-driven apply pipeline below, not a legacy fixed runtime task: POST /v1/instances/:id/apply { url, resumePath } starts JobApplyWorkflow, which drives the runtime's /browser/snapshot + /browser/act endpoints. The Coder agent runs its chosen engine (Claude Code, Codex, Gemini CLI, Grok, or a local command) on the session's assigned runner node; Claude uses a persistent structured session, while other engines run one-shot turns.
The flagship apply flow: a Brain (Cloudflare Workflow JobApplyWorkflow, using the user's BYOK Claude) drives the Hands (the local browser runtime) to fill and submit a real application β snapshot the ARIA tree β pick one action β act β repeat. Durable + resumable (escapes the 30s Worker limit). Retry + attempt tracking per job. Three human-in-the-loop handoffs share one pause/resume machine: captcha (solve in a live takeover, auto-resumes), stuck (do one step + Resume), needs_input (supply a value β saved to Profile β resumes). Per-ATS tips are cached and fed back next run; "Open in Gmail" surfaces confirmation links. dryRun:true fills everything but a workflow-level guard blocks the final Submit click.
ProAgentStore publishes skills through platform-specific plugin marketplaces so users can find them from both Codex and Claude Code.
Codex:
Claude Code:
See Skill Publishing for the publishing layout, marketplace files, and dual Codex/Claude release checklist.
Public discovery pages:
The authoritative catalog is the agents table in D1, read through GET /v1/agents. Nothing
in this repo is a mirror of it. A file in this repo is either a source for one catalog row or
it is not part of the catalog at all β those are different things, and conflating them is what
this section exists to prevent.
| Source | What it is | Authority |
|---|---|---|
agents table in D1 | Every published agent, its capabilities, settings schema and pipelines. | Authoritative. Read GET /v1/agents, or the MCP list_agents tool. |
workers/api/migrations/*seed*.sql | How a first-party agent gets into that table on a fresh database. Idempotent INSERT OR IGNORE. | Authoritative for the agents it seeds. Editing a seed does not change an already-seeded row β that needs a follow-up UPDATE migration. |
agents/<slug>/agent.json | The manifest for a Tier-0 agent whose code the platform itself builds or imports. | Source only. It does not create a catalog row. |
store/registry.json | Dead. See below. | None. |
An agent can therefore be in the catalog with no file in this repo, and have a folder here with no separate catalog row of its own. Both are normal.
agents/ holds exactly three, enforced in CI by scripts/check-agents-allowlist.mjs:
| Folder | Why it is Tier-0 |
|---|---|
agents/coder | agents/coder/web is a pnpm workspace member imported by the console. |
agents/job-application-assistant | Manifest for the apply agent. (Its src/ Worker is legacy and undeployed β see that folder's README.) |
agents/repo-chat | Reference source for the Repo Chat agent. |
Everything else is a standalone org repo under ProAgentStore,
cloned locally to ~/dev/stores/pags/agents/<slug>/. Adding a fourth folder here fails CI on
purpose (epic #50) β the monorepo previously accumulated ten stale vendored copies that were
never built or deployed.
13 agents are published. Grouped by where each one comes from:
Seeded by a migration β reproducible on a fresh database:
| Slug | Name | Seed | Source in repo |
|---|---|---|---|
coder | Coder | 0021 | agents/coder |
repo-chat | Repo Chat | 0032 | agents/repo-chat |
site-builder | Small Business Website Builder | 0057 | none β fully declarative (lib/pipelines/*.json) |
coder-repo | Repo Coder | 0063 | none β declarative capabilities |
coder-lead | Coder Lead | 0063 | none β declarative capabilities |
local-repo-chat | Local Repo Chat | 0066 | none β declarative capabilities |
tmux-operator | tmux Operator | 0072 | none β declarative capabilities |
Created through the API/console by the operator β they exist only as D1 rows, so a fresh database will not have them. Treat this as known drift, not a design:
| Slug | Name | Notes |
|---|---|---|
job-application-assistant | Job Application Assistant | Manifest in agents/, but no seed migration. Migration 0022 only updates its capabilities if the row already exists. |
language-buddy | Language Buddy | Migration 0041 sets its settingsSchema if present; it does not create it. |
doc-chat | Doc Chat | |
small-business-website-lead-finder | Small Business Website Lead Finder | Standalone org repo, cloned to pags/agents/. |
lead-outreach-tj6qrr | Lead Outreach Assistant | The middle link of the lead chain. |
facebook-friend-confirmer | Facebook Friends | Browser-runtime agent. |
The three-agent lead chain is small-business-website-lead-finder β lead-outreach-tj6qrr β
site-builder, wired with agent_connections rather than code.
Publishing is gated: PUT /v1/agents/:id and POST /v1/batch/bulk-visibility both refuse to
publish a smoke-test fixture (#65, #64), which is what stopped the catalog from re-accumulating
the 16 fixtures and scaffold seeds an audit removed.
store/registry.json is intentionally emptyIt is the input to store/build-details.js, a static agent-detail-page generator. Neither is
wired to anything: build-details.js has no package.json script and no CI workflow calls it.
Agent detail pages are served dynamically at /agents/:slug/ from GET /v1/public/agents/:id.
The file is kept as an empty stub so the dead generator does not crash if someone runs it. It is
not a public discovery artifact β for that, use GET /v1/agents, store/llms.txt, or
store/skills.json.
Earlier revisions of this README listed ten agents β site-monitor, lead-qualifier,
content-pipeline, competitor-intel, support-escalator, data-analyst, meeting-notes,
seo-auditor, invoice-parser, email-drafter. They were vendored seed copies under agents/,
removed in platform main commit f9980a8. None of them has a seed migration or a published
catalog row today. Do not re-add them here.
One of them survives as a lookup key, not as an agent: the seed migrations resolve the operator
account with SELECT owner_id FROM agents WHERE slug = 'data-analyst' AND owner_id LIKE 'google:%'.
That is a way to find the operator's user id on the production database, and it falls back to
'system'. It does not mean data-analyst is a catalog agent.
useVoice hook) β pick Dictation (browser, real-time live words) or Whisper (OpenAI via the key proxy, most accurate) STT; browser or OpenAI TTS with a voice/speed picker; a single segmented Chat Β· Tap-to-talk Β· Hands-free mode control (Mute is a Hands-free sub-control; icon-only on mobile); a spoken "repeat" command; and per-turn replay of any voice message's saved recording (R2) from its speaker button β beside a Show what was heard toggle that compares the live dictation with the transcript that was sent, and counts the words the transcript lost. Adaptive VAD + pause/sensitivity/language settings; iOS gesture handling.client:voice*, keys-proxy, job-apply, β¦) surfaced via MCP list_errors; a unified per-run timeline via agent_events + MCP agent_trace.capabilities.boardColumns), one card per job, with move / retry / attempts. Driven from MCP via instance_board. (Replaces the old two-board / "runtime board" design.)pnpm test runs everything. Underneath it is split (vitest.config.ts):
| Project | What | How it runs |
|---|---|---|
unit | ~3100 tests, pure functions and mocked I/O | parallel fork pool |
integration | packages/browser-runner/** β a real Chrome per test over CDP, bound sockets, spawned tmux panes, real git clone | one file at a time, after unit, alone |
Ten tests in integration take longer than the other ~3100 combined. They are also the
only ones people see flake locally β so it is worth being precise about why.
These tests are sensitive to CPU availability, not to anything in the code under test.
There is no race, no port collision, no leaked browser between files. Every failure ever
observed was Test timed out in Nms on code that passes whenever the machine is quiet.
Measured: the same passing browser test took 11.4s alone, 20.6s inside the suite, and 39.3s
with a second full suite running beside it. And when the box was fully saturated, the run
that failed failed in rate-limit.test.ts, publish.test.ts and storage-tools.test.ts β
three pure unit files with no browser and no socket in them. Browser tests starve first
because they are the heaviest, not because they are browser tests.
So if this flakes for you, do not weaken an assertion β look at what else is running. CI is not affected and never has been: it executes the suite alone on a dedicated runner, which is exactly why it is green. The split exists for the shared dev machine, and mostly to give real-I/O tests a timeout budget sized for real I/O instead of vitest's 5s default.
If you add a test that launches a browser or binds a listening socket, put it under
packages/browser-runner/ so it inherits that budget; scripts/check-test-isolation.mjs
fails CI if it lands anywhere else.
Orphaned Chromes. Playwright's cleanup does not run when a test runner is SIGKILLed, so aborted runs leave whole browsers behind β measured on this repo's dev machine: 174 live browser profiles, the oldest 26 hours old, ~1000 processes, load average 190. They are invisible and they make every later run slower, which is most of why "flaky" feels random. If local tests feel inexplicably slow:
ps ax | grep -c playwright_chromiumdev_profile.
| Artifact | Status | How to update |
|---|---|---|
platform-docs/*.md | source | edit directly; add the page to nav in zensical.toml |
store/docs/** | generated, not committed | pnpm docs:build; never hand-edit, never git add |
store/openapi.yaml | source | edit when you add or change a route |
store/llms.txt, store/llms-full.txt | source | edit by hand; they are what an agent reads first |
workers/mcp/README.md tool table | source | add a row whenever you register a tool |
workers/mcp/src/tool-count.ts | source of truth for the count | bump when you add or remove a tool |
store/docs is build output in the same sense as workers/host/src/pages.ts: both
ci.yml and deploy-host.yml run pnpm docs:build before anything reads it, so a
committed copy could only ever be stale β and was. Run pnpm docs:build once on a fresh
checkout before pnpm test:e2e or node workers/host/build.js; both read /docs/*.
Prose is the one part of this repo that nothing else validates, so it rots quietly and then teaches an agent something false. Two commands catch the classes that have actually bitten us (#209, #210):
Both run in CI. When one fails it names the file and the number it expected β fix the docs,
or fix the code they describe, but do not silence a check without moving the thing it was
watching. Deliberately-undocumented routes go in the EXCLUSIONS array in
scripts/openapi-coverage.mjs, each with a reason.
When you add a route, update store/openapi.yaml (or add an exclusion).
When you add an MCP tool, add its row to workers/mcp/README.md and bump
workers/mcp/src/tool-count.ts β index.test.ts asserts that constant against a real
registration run, and /health plus three docs quote it.
When you add a docs page, add it to nav in zensical.toml.
Two things in that one line are load-bearing.
It builds the SDK first, for the same reason pnpm typecheck does: the console and
the agent UIs import @proagentstore/sdk as built dist, so on a checkout that has not
built it, tsc reports "Cannot find module '@proagentstore/sdk/client'" across three
packages. VCQA's types check shells out to tsc and scores that 0/100. Measured
here: types 0 β 100 and the composite 65 β 71, from pnpm --filter @proagentstore/sdk build alone, with no source change. That is exactly what #288 reported as "typecheck
fails" β an unbuilt dist, not broken code. Without the prefix this command manufactures
that false alarm on every fresh checkout.
--skip-tests is deliberate and is what the score is quoted against. VCQA's testing
check otherwise executes the suite itself, which here means the integration project β
real Chromes over CDP, bound sockets, a real git clone β inside a scan that already
runs ~35 other checks. pnpm test is how you run the tests; this command measures
everything else. The CLI version is pinned in the script so two people comparing scores
are comparing the same scanner.
Three files decide what the scan sees, and they are not interchangeable.
| File | Applies to | Why it can't be merged into the others |
|---|---|---|
.vcqa.json | VCQA's own file walker | ignore patterns, read by the in-process runners |
.gitleaks.toml | the secrets check | gitleaks is a subprocess; .vcqa.json never reaches it |
biome.json | the lint check and pnpm lint | Biome resolves its own config before any ignore list applies |
That split is the whole point, and it is why the obvious one-file fix does not work. Measured at the repo root on 2026-08-06, on a machine with live agent worktrees:
pnpm lint was not noisy, it was dead. Biome refuses to start when it finds a
nested root config below the root config it loaded β and .claude/worktrees/<agent>/
contains a copy of this repo's biome.json. It exited 1 with "Found a nested root
configuration" and linted nothing. Fixed by !.claude in files.includes β and it has
to be spelled that way. Every neighbouring entry is !**/x, but !**/.claude matches an
ancestor when you are working inside a worktree (which lives under .claude/), so it
excludes the whole checkout from itself: "Checked 0 files", exit 0. Lint reporting
success having read nothing is worse than the crash. !.claude is resolved against the
config root; verified at 891 files from the repo root and 807 from inside a worktree..claude/worktrees/** β the same
three files re-reported once per agent session, 338 MB scanned in 25.4s. secrets
scored 25/100, the worst check in the report, almost entirely on duplication. With
.gitleaks.toml: 11 findings, 17.5 MB, 1.7s. Those 11 are real paths in real source
and are deliberately left visible.Lint is a gate now, but only where the count is zero (#326). Getting pnpm lint to
run still left every rule advisory β it was in no workflow, which is how 300 findings
accumulated without ever being a regression anyone was told about. ci.yml now runs
pnpm exec biome check --error-on-warnings packages workers/mcp: the two trees measured
at 0 errors and 0 warnings. --error-on-warnings because every finding those trees
ever had was a warning, so a gate that ignored warnings would protect nothing; pnpm exec rather than npx so it is the pinned Biome and a new upstream rule cannot redden a
green main without a commit here. The rest is blocked on its own count β workers/api
~234 (184 of them any), store/** ~54 !important plus the console's hook and a11y
warnings, agents/coder 1. Add a path to that step when a tree reaches zero; do not
widen it early and reach for continue-on-error, which is the step with the teeth
removed.
What is deliberately still in scope. agents/coder and agents/job-application-assistant
are Tier-0 β pnpm workspace members that CI typechecks and builds β so they are scanned.
The inert vendored seed copies that used to sit beside them were deleted on 2026-08-01
(f9980a8) and scripts/check-agents-allowlist.mjs keeps them out; there is nothing
stale under agents/ left to exclude, and an agents/** ignore would now only hide
shipping code. scripts/check-qa-config.mjs fails CI if one is added.
Before you add an ignore pattern, note that VCQA is not a glob engine. It understands
prefix/**, *suffix, and a plain path prefix β nothing else. **/dist/** reads as
correct, matches nothing, and fails silently; VCQA already excludes dist (and
node_modules, .claude, coverage, β¦) by directory name at any depth, so most patterns
you reach for are already covered. The guard rejects a pattern that can never fire.
| Store | URL | Product |
|---|---|---|
| FreeAppStore | freeappstore.online | PWA apps |
| FreeGameStore | freegamestore.online | Browser games |
| FreeWebStore | freewebstore.online | AI-built sites |
| FreeAgentStore | freeagentstore.online | Browser AI tools |
| ProAppStore | proappstore.online | Paid apps |
| ProAgentStore | proagentstore.online | Server AI agents |
MIT
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/proagentstore)<a href="https://allmcps.com/mcp/proagentstore"><img src="https://allmcps.com/api/badge/proagentstore?style=directory" alt="ProAgentStore on AllMCPs" /></a>