premanmcp 0.16.3 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -371
- package/bin/api_tools.js +37 -8
- package/bin/cli.js +19 -3
- package/bin/desktop.js +233 -25
- package/bin/integrations.js +27 -3
- package/bin/link.js +3 -18
- package/bin/shared.js +25 -2
- package/bin/status.js +13 -3
- package/bin/tests.js +9 -13
- package/bin/verify.js +2 -5
- package/dist/server.d.ts +7 -2
- package/dist/server.js +109 -1843
- package/package.json +10 -15
package/README.md
CHANGED
|
@@ -1,223 +1,38 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `premanmcp` 1.0
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Start
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm exec -y premanmcp@latest -- onboard
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Create the account, verify the email, get the PreMan app installed and opened already
|
|
14
|
-
signed in, and hook this repo so `git push` checks the endpoints you touched. A bare
|
|
15
|
-
`preman` in a terminal does the same thing.
|
|
16
|
-
|
|
17
|
-
## Connect a coding agent
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
npm exec -y premanmcp@latest -- connect
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Optional, and separate from starting out. Pick your coding agent from the list — Cursor,
|
|
24
|
-
Claude Code, or Codex — and PreMan writes that agent's MCP config for you. No hand-edited
|
|
25
|
-
config anywhere.
|
|
26
|
-
|
|
27
|
-
Local development form:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
node bin/cli.js connect
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
First-time users are asked for an email and the code sent to it — no password: the
|
|
34
|
-
terminal's credential is the `pm_live_` key. Pass `--password` to also set one for
|
|
35
|
-
dashboard sign-in, or set it later from the dashboard. PreMan creates or connects the
|
|
36
|
-
account, generates an API key, saves it to `~/.preman/credentials.json`, then writes a
|
|
37
|
-
`preman` MCP server into the config your agent actually reads (`~/.cursor/mcp.json`,
|
|
38
|
-
Claude Code's MCP config, or `~/.codex/config.toml`):
|
|
39
|
-
|
|
40
|
-
```json
|
|
41
|
-
{
|
|
42
|
-
"mcpServers": {
|
|
43
|
-
"preman": {
|
|
44
|
-
"command": "npm",
|
|
45
|
-
"args": ["exec", "-y", "premanmcp@latest", "--"],
|
|
46
|
-
"env": {
|
|
47
|
-
"PREMAN_BACKEND": "https://api.preman.live",
|
|
48
|
-
"PREMAN_FRONTEND": "https://app.preman.live"
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
`connect` reads the config back after writing it, and prints a copy-paste snippet if it
|
|
56
|
-
cannot confirm the entry landed. Then it finishes the link itself rather than asking you
|
|
57
|
-
to go restart anything, in cheapest-first order:
|
|
58
|
-
|
|
59
|
-
1. **Self-test.** It starts the MCP server exactly as your agent will and calls
|
|
60
|
-
`preman_status` over stdio. That both completes the link and proves the whole chain —
|
|
61
|
-
launcher, package, key, backend. `--no-self-test` turns it off.
|
|
62
|
-
2. **Agent run**, which also proves your agent can load what was written. For Cursor it
|
|
63
|
-
runs `cursor-agent mcp enable` after writing `mcp.json` (new servers stay off the CLI
|
|
64
|
-
approved list otherwise) and launches the agent with `--approve-mcps` so the check-in
|
|
65
|
-
can actually call `preman_status`. It opens your agent interactively in a new terminal
|
|
66
|
-
window — the session you go on to use — and falls back to a headless run (`claude -p`,
|
|
67
|
-
`cursor-agent --approve-mcps -p`, `codex exec`) where no window can be opened, such as
|
|
68
|
-
CI or SSH. `--no-auto-checkin` turns it off, `PREMAN_NO_TERMINAL=1` keeps it headless.
|
|
69
|
-
3. **Wait**, if neither is possible: restart your agent and it links on its first call.
|
|
70
|
-
|
|
71
|
-
A self-test that answers from an unexpected backend is reported with the file that
|
|
72
|
-
redirected it — a repo-local `preman-mcp.config.json` with `"PREMAN_CONFIG_OVERRIDE": true`
|
|
73
|
-
wins over the MCP config env, and otherwise only fills in what the env leaves unset. When
|
|
74
|
-
that file overrides `PREMAN_BACKEND`, the config `connect` wrote is still correct: the
|
|
75
|
-
server reads that file only from the directory it starts in, so `connect` names the file
|
|
76
|
-
and then retries from your home directory, where the override cannot reach it — self-test
|
|
77
|
-
first, then your agent. Agents you start in the overriding directory keep using its
|
|
78
|
-
backend, which is the point of the file.
|
|
79
|
-
|
|
80
|
-
Once linked, `connect` installs the git pre-push hook — so `git push` checks the endpoints
|
|
81
|
-
you touched — prints what is left, and stops. It asks nothing. Everything else it used to
|
|
82
|
-
run is its own command, because each one can fail on its own and none of them should hold
|
|
83
|
-
up a link that already worked:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
preman endpoints discover # map this repo's endpoints
|
|
87
|
-
preman tests generate # heuristic suites on saved Collections requests
|
|
88
|
-
preman tests review # list flagged suites; --approve <id> enables schedule
|
|
89
|
-
preman tests setup # harvest path-param fixture IDs into a .env snippet
|
|
90
|
-
preman tests enrich # optional LLM cases on remaining heuristic suites
|
|
91
|
-
preman runner start --background # let PreMan apply fixes on this machine
|
|
92
|
-
preman github # or connect it in the dashboard
|
|
93
|
-
preman status # which of those are done
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
`preman onboard` (or `setup`, or a bare `preman` in a terminal) is what someone starting
|
|
97
|
-
out runs: create the account and verify the email, install the PreMan app and open it
|
|
98
|
-
already signed in, then write the pre-push hook into this repo — one question per step, `b`
|
|
99
|
-
to go back, and a summary at the end. GitHub, AWS and Slack are their own commands now.
|
|
100
|
-
Onboarding outside a git repository skips the hook rather than failing; run `preman hook
|
|
101
|
-
install` in the repo you meant. Connecting a coding agent is no longer part of starting out; run
|
|
102
|
-
`preman connect` when you actually want one wired into an IDE. `connect --guide` still runs
|
|
103
|
-
the full pass inside connect itself: discovery, a first test, the runner, the desktop app
|
|
104
|
-
and the integration prompts.
|
|
105
|
-
|
|
106
|
-
The app opens signed in because the CLI leaves the key it just minted in
|
|
107
|
-
`~/.preman/desktop-session.json`, which the app reads once and deletes. An app too old to
|
|
108
|
-
look for it, or a machine that is not macOS, falls back to signing in on the app's own
|
|
109
|
-
login screen with the account you just created.
|
|
110
|
-
|
|
111
|
-
Useful flags: `--agent cursor|claude-code|codex` skips the picker, `--project` writes
|
|
112
|
-
project-local config, `--print` shows the config without writing it, `--no-hook` leaves
|
|
113
|
-
push testing alone, and `--no-guide` connects and nothing else. With `--guide`, `--yes`
|
|
114
|
-
takes every step's default without asking and `--no-runner` / `--no-desktop` /
|
|
115
|
-
`--no-integrations` skip one each.
|
|
116
|
-
|
|
117
|
-
The desktop app is installed rather than offered. It was a question for a while, defaulted
|
|
118
|
-
to no on the grounds that nobody should get a 150MB download by pressing Enter, and what
|
|
119
|
-
that produced was a setup whose last act was to describe the app and decline to install
|
|
120
|
-
it. The build is Developer ID signed and notarized, it is checked against the sha512
|
|
121
|
-
published with the release before anything is copied into `/Applications`, and nothing
|
|
122
|
-
arrives through a browser so there is no quarantine flag and no Gatekeeper warning on
|
|
123
|
-
first launch. `--no-desktop`, or `PREMAN_NO_DESKTOP=1` where no flag can be passed, skips
|
|
124
|
-
it; `install-desktop` does it on its own.
|
|
125
|
-
|
|
126
|
-
In CI or any non-interactive shell, run `connect --agent <name> --api-key pm_live_…`.
|
|
127
|
-
Without `--agent` there is nothing to prompt on, so `connect` prints ready-to-paste
|
|
128
|
-
setup blocks for all three agents and exits 2.
|
|
129
|
-
|
|
130
|
-
`preman install` still exists and does the Cursor-only half of this.
|
|
131
|
-
|
|
132
|
-
### Cloud dispatch (optional)
|
|
133
|
-
|
|
134
|
-
With a coding-agent credential saved — a Cursor API key from
|
|
135
|
-
`cursor.com/dashboard → Integrations → API Keys`, or a Claude Code routine token and id
|
|
136
|
-
from `claude.ai/code/routines → your routine → Add API trigger` — PreMan can start an
|
|
137
|
-
agent run for you when it finds a failing endpoint, instead of handing back a prompt to
|
|
138
|
-
paste.
|
|
139
|
-
|
|
140
|
-
`connect` asks for it once you are already set up, so skipping costs nothing. Come back
|
|
141
|
-
to it any time:
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
npm exec -y premanmcp@latest -- dispatch
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
You can also create or connect your account first:
|
|
148
|
-
|
|
149
|
-
```bash
|
|
150
|
-
npm exec -y premanmcp@latest -- login
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
You can also pass the key directly:
|
|
154
|
-
|
|
155
|
-
```bash
|
|
156
|
-
npm exec -y premanmcp@latest -- connect --api-key pm_live_xxx
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
For project-local config:
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
npm exec -y premanmcp@latest -- connect --project
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
## What It Does
|
|
166
|
-
|
|
167
|
-
- Converts API endpoints into agent-callable MCP tools.
|
|
168
|
-
- Migrates a Postman collection in one call (`migrate_from_postman`): keeps the assertions your `pm.test` blocks declared, splits the environment into shared variables and encrypted secrets, and schedules a monitored test suite per request.
|
|
169
|
-
- Creates/connects a PreMan account from the terminal or IDE agent.
|
|
170
|
-
- Lets agents test real backend endpoints from the IDE.
|
|
171
|
-
- Syncs endpoint inventory across backend and frontend workflows.
|
|
172
|
-
- Adds API-key auth for PreMan MCP access.
|
|
173
|
-
- Supports hosted MCPs with consumer tokens for customer-facing agent access.
|
|
174
|
-
- Records per-call observability so teams can audit which agent did what.
|
|
175
|
-
- Hands failing-endpoint alerts to your agent as fix tasks (`preman_get_fix_task` → repro curl → `preman_complete_fix_task`).
|
|
176
|
-
- Connects your production logs from the terminal (`connect_logs`): your agent asks where the logs live, then deploys a read-only CloudFormation role for AWS, or wires a shipper to the ingest endpoint for everything else.
|
|
177
|
-
|
|
178
|
-
## Common Agent Commands
|
|
179
|
-
|
|
180
|
-
After installing, ask your coding agent:
|
|
181
|
-
|
|
182
|
-
```text
|
|
183
|
-
Use PreMan to convert the endpoints I choose into a hosted MCP server, then give me the Cursor/Claude install snippet.
|
|
184
|
-
```
|
|
3
|
+
`premanmcp` is the compatibility client for agents that can start only a local
|
|
4
|
+
stdio MCP process. It forwards MCP initialization, discovery, notifications,
|
|
5
|
+
and tool calls to PreMan's authoritative hosted server at:
|
|
185
6
|
|
|
186
7
|
```text
|
|
187
|
-
|
|
8
|
+
https://api.preman.live/mcp
|
|
188
9
|
```
|
|
189
10
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
```
|
|
11
|
+
It defines no tools or schemas locally. The hosted service exposes the stable
|
|
12
|
+
four-tool PreMan conversation protocol:
|
|
193
13
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
14
|
+
- `preman_chat`
|
|
15
|
+
- `preman_get_turn`
|
|
16
|
+
- `preman_confirm_action`
|
|
17
|
+
- `preman_cancel_turn`
|
|
197
18
|
|
|
198
|
-
|
|
199
|
-
Show me the audit log for this hosted MCP.
|
|
200
|
-
```
|
|
19
|
+
PreMan can add private agent capabilities without publishing a new npm package.
|
|
201
20
|
|
|
202
|
-
|
|
203
|
-
Move my Postman collection over to PreMan.
|
|
204
|
-
```
|
|
21
|
+
## Marketplace users
|
|
205
22
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
```
|
|
23
|
+
Do not install this package. The PreMan Codex/ChatGPT plugin connects directly
|
|
24
|
+
to the hosted Streamable HTTP MCP server with OAuth.
|
|
209
25
|
|
|
210
|
-
|
|
211
|
-
Connect my production logs to PreMan.
|
|
212
|
-
```
|
|
26
|
+
## Local-agent compatibility
|
|
213
27
|
|
|
214
|
-
|
|
28
|
+
Create a PreMan API key in the app, then export it or store it locally:
|
|
215
29
|
|
|
216
30
|
```bash
|
|
217
|
-
|
|
31
|
+
export PREMAN_API_KEY=pm_live_xxx
|
|
32
|
+
# or: ~/.preman/credentials.json -> {"api_key":"pm_live_xxx"}
|
|
218
33
|
```
|
|
219
34
|
|
|
220
|
-
|
|
35
|
+
Then configure an agent that requires stdio:
|
|
221
36
|
|
|
222
37
|
```json
|
|
223
38
|
{
|
|
@@ -230,179 +45,33 @@ Manual Cursor config, if you would rather write it yourself:
|
|
|
230
45
|
}
|
|
231
46
|
```
|
|
232
47
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
```bash
|
|
236
|
-
npm exec -y premanmcp@latest -- connect --agent claude-code
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
Equivalent manual command:
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
|
-
claude mcp add preman -- npm exec -y premanmcp@latest --
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
## Codex
|
|
246
|
-
|
|
247
|
-
```bash
|
|
248
|
-
npm exec -y premanmcp@latest -- connect --agent codex
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
Writes an `[mcp_servers.preman]` block into `~/.codex/config.toml`.
|
|
252
|
-
|
|
253
|
-
## CLI
|
|
254
|
-
|
|
255
|
-
```bash
|
|
256
|
-
npm exec -y premanmcp@latest -- connect # Pick an agent and connect it
|
|
257
|
-
npm exec -y premanmcp@latest -- connect --agent codex # Skip the picker
|
|
258
|
-
npm exec -y premanmcp@latest -- connect --project # Write project-local config
|
|
259
|
-
npm exec -y premanmcp@latest -- connect --print # Print config without writing
|
|
260
|
-
npm exec -y premanmcp@latest -- # Start the MCP server
|
|
261
|
-
npm exec -y premanmcp@latest -- login # Create/login and generate a PreMan API key
|
|
262
|
-
npm exec -y premanmcp@latest -- install # Cursor-only installer (legacy)
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
### Push testing
|
|
48
|
+
The proxy reads `PREMAN_API_KEY` or `~/.preman/credentials.json`. Optional
|
|
49
|
+
transport overrides are `PREMAN_MCP_URL` and `PREMAN_BACKEND`.
|
|
266
50
|
|
|
267
|
-
|
|
268
|
-
preman hook install # Write the pre-push hook (onboard and connect do this too)
|
|
269
|
-
preman hook status # Installed? And does the command in it still answer?
|
|
270
|
-
preman hook repair # Rewrite it if it stopped working (usually automatic)
|
|
271
|
-
preman hook uninstall # Remove it, restoring any hook it replaced
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
The hook is generated shell that runs `preman verify --pre-push` and can only ever be
|
|
275
|
-
advisory: no backend, no credentials, a crash or a timeout all exit 0 with a notice. Before
|
|
276
|
-
writing it, `install` runs the command it is about to embed and requires an answer — a hook
|
|
277
|
-
holding a `preman` that belongs to another package prints `checks skipped` at every push and
|
|
278
|
-
looks installed forever. The embedded command is pinned to the version that wrote it rather
|
|
279
|
-
than `@latest`, so upgrading us never changes what your pushes run; re-run `hook install`
|
|
280
|
-
to move it. Set `PREMAN_HOOK_INVOCATION` to write a command of your own instead, and
|
|
281
|
-
`PREMAN_SKIP_HOOK=1` to silence the hook for a push.
|
|
282
|
-
|
|
283
|
-
You should not have to run `repair`. A hook of ours that stops answering is rewritten in the
|
|
284
|
-
background by anything that proves PreMan runs here — any command, or your agent starting the
|
|
285
|
-
MCP server — because nothing re-runs `connect` after an upgrade to notice, and the broken
|
|
286
|
-
state is silent. It is narrow on purpose: a hook that still works keeps the version it pins, a
|
|
287
|
-
hook we did not write is never touched, and no hook is installed where you never asked for
|
|
288
|
-
one. The answer is remembered for an hour per directory, and `PREMAN_NO_HOOK_REPAIR=1` turns
|
|
289
|
-
it off.
|
|
290
|
-
|
|
291
|
-
#### The link a push leaves behind
|
|
292
|
-
|
|
293
|
-
Once runs are stored, the hook prints a line you can click straight through to that push:
|
|
294
|
-
|
|
295
|
-
```
|
|
296
|
-
◆ PreMan · check #a3f21c passed — view results
|
|
297
|
-
https://app.preman.live/observability/endpoints?batch=a3f21c9e-…
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
Where the click lands is decided before anything is printed, because a terminal hands the
|
|
301
|
-
URL it was given to the OS and there is nothing left of the hook by then:
|
|
302
|
-
|
|
303
|
-
| What is true when the hook runs | What the link opens |
|
|
304
|
-
| --- | --- |
|
|
305
|
-
| A frontend other than `app.preman.live` | That frontend, in the browser |
|
|
306
|
-
| PreMan.app installed and new enough to route | The desktop app, via `preman://` |
|
|
307
|
-
| Anything else | `app.preman.live`, in the browser |
|
|
308
|
-
|
|
309
|
-
The frontend is read from `--frontend`, then `PREMAN_FRONTEND`, then the one saved at login
|
|
310
|
-
in `~/.preman/credentials.json`. That last fallback is what makes a local setup work from a
|
|
311
|
-
hook at all: `git push` does not carry the shell that exported the variable, and a `dev.env`
|
|
312
|
-
file is not an environment.
|
|
51
|
+
## Security model
|
|
313
52
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
53
|
+
- OAuth is used by marketplace clients; API keys remain for CLI compatibility.
|
|
54
|
+
- Risky actions are stored server-side as exact, expiring proposals.
|
|
55
|
+
- Chat text never approves an action. Approval uses
|
|
56
|
+
`preman_confirm_action` or the matching control in the PreMan app.
|
|
57
|
+
- The proxy never receives private PreMan tool schemas or raw proposal payloads.
|
|
317
58
|
|
|
318
|
-
|
|
319
|
-
`preman://open?source=push&route=<url-encoded path>` and navigate to that path. Older builds
|
|
320
|
-
raise the window and ignore the query, so the CLI reads `CFBundleShortVersionString` out of
|
|
321
|
-
the installed bundle and falls back to https rather than sending them somewhere they cannot
|
|
322
|
-
follow.
|
|
323
|
-
|
|
324
|
-
### Runner
|
|
325
|
-
|
|
326
|
-
`preman onboard` and `connect --guide` set this up for you; these are for managing it
|
|
327
|
-
afterwards.
|
|
59
|
+
## Development
|
|
328
60
|
|
|
329
61
|
```bash
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
preman runner register --agent claude-code # Pair without starting
|
|
62
|
+
npm ci
|
|
63
|
+
npm test
|
|
64
|
+
npm pack --dry-run
|
|
334
65
|
```
|
|
335
66
|
|
|
336
|
-
`
|
|
337
|
-
|
|
338
|
-
It works out which agent to pair as from the session it is running in, then from the agent
|
|
339
|
-
PreMan is already configured in, then from the only one installed — and asks only when
|
|
340
|
-
those disagree. Pass `--agent cursor|claude-code|codex` to settle it yourself, which is
|
|
341
|
-
also what a machine with no terminal to ask in needs.
|
|
342
|
-
|
|
343
|
-
The runner holds one outbound connection to PreMan and runs the work PreMan queues for
|
|
344
|
-
this machine — a failing endpoint becomes an agent run in your own repo instead of a
|
|
345
|
-
prompt you have to paste. It is bound to the agent and directory it was registered with
|
|
346
|
-
and refuses any job that names a different one. The agent may edit files; running commands
|
|
347
|
-
needs `--full-access` (or `PREMAN_RUNNER_FULL_ACCESS=1`). Nothing runs until PreMan has
|
|
348
|
-
something to fix, and `preman runner stop` ends it.
|
|
349
|
-
|
|
350
|
-
Options:
|
|
351
|
-
|
|
352
|
-
- `--api-key <key>`: PreMan API key.
|
|
353
|
-
- `--backend <url>`: PreMan backend URL. Defaults to `https://api.preman.live`.
|
|
354
|
-
- `--frontend <url>`: PreMan frontend URL. Defaults to `https://app.preman.live`.
|
|
355
|
-
- `--name <name>`: MCP server name. Defaults to `preman`.
|
|
356
|
-
- `--project`: Write `.cursor/mcp.json` in the current project.
|
|
357
|
-
- `--skip-login`: Install config without interactive terminal auth.
|
|
358
|
-
- `--print`: Print the generated MCP config without writing it.
|
|
359
|
-
|
|
360
|
-
## Run a hosted MCP from the terminal
|
|
361
|
-
|
|
362
|
-
Installing the package also gives you a `preman` command. Once a selection is published as a
|
|
363
|
-
hosted MCP, you can call its tools straight from a shell — same published selection, same
|
|
364
|
-
consumer token, and same audit trail as an agent calling `POST /h/<id>/mcp`. Updating the
|
|
365
|
-
selection updates the terminal; there is nothing to re-install.
|
|
366
|
-
|
|
367
|
-
```bash
|
|
368
|
-
preman link https://api.preman.live/h/<id>/mcp --env staging --token pm_hmcp_xxx
|
|
369
|
-
preman tools --env staging
|
|
370
|
-
preman run post_users_id_orders --env staging --arg id=42 --json '{"body":{"sku":"A1"}}'
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
`link` takes the URL straight from the deploy install snippet (a bare hosted MCP id works too,
|
|
374
|
-
with `--backend`). Profiles are stored in `~/.preman/cli.json` (mode 0600); `--env <name>`
|
|
375
|
-
picks one. Tool names are the ones the runtime publishes — run `preman tools` to see them.
|
|
376
|
-
|
|
377
|
-
Run options:
|
|
378
|
-
|
|
379
|
-
- `--env <name>`: Profile to use. Falls back to `PREMAN_MCP_URL`, then the default profile.
|
|
380
|
-
- `--arg key=value`: String argument (repeatable). `--arg key:=json` sends a JSON-typed value.
|
|
381
|
-
- `--json '{...}'`: Full arguments object. `--json -` reads it from stdin.
|
|
382
|
-
- `--timeout <seconds>`: Client-side timeout. Defaults to 60.
|
|
383
|
-
- `--json-out`: Print the raw JSON-RPC result.
|
|
384
|
-
- `<tool>` may be dotted — `preman run staging.get_orders` selects the profile inline.
|
|
385
|
-
|
|
386
|
-
Exit codes: `0` success, `1` the tool returned an error, `2` usage, `3` authentication,
|
|
387
|
-
`4` JSON-RPC error (e.g. unknown tool), `5` network failure.
|
|
388
|
-
|
|
389
|
-
## Environment Variables
|
|
390
|
-
|
|
391
|
-
- `PREMAN_API_KEY`: PreMan API key.
|
|
392
|
-
- `PREMAN_BACKEND`: PreMan backend URL.
|
|
393
|
-
- `PREMAN_FRONTEND`: PreMan frontend URL.
|
|
394
|
-
- `PREMAN_MCP_URL`: Hosted MCP endpoint (`…/h/<id>/mcp`) for `preman run`/`preman tools` when
|
|
395
|
-
`--env` is omitted — useful in CI, where no profile file exists.
|
|
396
|
-
- `PREMAN_MCP_TOKEN`: Consumer token for `PREMAN_MCP_URL`.
|
|
397
|
-
|
|
398
|
-
If `PREMAN_API_KEY` is omitted, the MCP server loads credentials from `~/.preman/credentials.json`.
|
|
399
|
-
|
|
400
|
-
## Product
|
|
401
|
-
|
|
402
|
-
PreMan helps teams make APIs usable by agents without giving up control. Developers can turn endpoints into MCP servers, hand customers an install snippet or hosted MCP URL, and audit every tool call through PreMan.
|
|
67
|
+
`npm test` builds the TypeScript proxy and checks transparent forwarding against
|
|
68
|
+
a mock Streamable HTTP MCP server.
|
|
403
69
|
|
|
404
|
-
|
|
70
|
+
## Links
|
|
405
71
|
|
|
406
|
-
|
|
72
|
+
- Documentation: https://app.preman.live/docs/preman-plugin
|
|
73
|
+
- Support: https://app.preman.live/support
|
|
74
|
+
- Privacy: https://app.preman.live/privacy
|
|
75
|
+
- Terms: https://app.preman.live/terms
|
|
407
76
|
|
|
408
|
-
MIT
|
|
77
|
+
License: MIT
|
package/bin/api_tools.js
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `preman endpoints` and `preman test` — the API-testing surface of the CLI.
|
|
3
3
|
*
|
|
4
|
-
* Both are thin proxies over `
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Both are thin proxies over the `/cli` REST routes, which call the same
|
|
5
|
+
* implementations the MCP tools did, so the CLI and an agent asking for the
|
|
6
|
+
* same thing see identical data. Requires a pm_live_ key (flag, env, or stored
|
|
7
|
+
* credentials).
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
import { readFileSync } from "node:fs";
|
|
10
11
|
|
|
11
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
callBackendJson,
|
|
14
|
+
cliInvocation,
|
|
15
|
+
describeFailure,
|
|
16
|
+
makeArgs,
|
|
17
|
+
resolveApiKey,
|
|
18
|
+
} from "./shared.js";
|
|
12
19
|
import { printPlayground } from "./desktop.js";
|
|
13
20
|
|
|
14
21
|
export const ENDPOINTS_HELP = `
|
|
@@ -42,6 +49,24 @@ class CliError extends Error {
|
|
|
42
49
|
}
|
|
43
50
|
}
|
|
44
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Where each tool's data comes from now.
|
|
54
|
+
*
|
|
55
|
+
* These were one POST to `/mcp/call-tool` until the four-tool chat gateway
|
|
56
|
+
* retired that catalog. `/mcp` is now a conversation, which is the wrong shape
|
|
57
|
+
* for a CLI that wants a list of endpoints and an exit code. The `/cli` routes
|
|
58
|
+
* call the same implementations the tools did, so the two surfaces cannot
|
|
59
|
+
* drift apart. A tool absent from this table is one the CLI cannot reach.
|
|
60
|
+
*/
|
|
61
|
+
const TOOL_ROUTES = {
|
|
62
|
+
get_endpoints: { method: "GET", path: "/cli/endpoints" },
|
|
63
|
+
discover_endpoints_from_codebase: { method: "POST", path: "/cli/discovery-brief" },
|
|
64
|
+
register_discovered_endpoints: { method: "POST", path: "/cli/endpoints/register" },
|
|
65
|
+
generate_endpoint_tests: { method: "POST", path: "/cli/tests/generate" },
|
|
66
|
+
run_stress_test: { method: "POST", path: "/cli/stress-test" },
|
|
67
|
+
share_endpoints_with_ui: { method: "POST", path: "/cli/playground-session" },
|
|
68
|
+
};
|
|
69
|
+
|
|
45
70
|
export async function callTool(args, tool, toolArguments) {
|
|
46
71
|
const token = resolveApiKey(args);
|
|
47
72
|
if (!token) {
|
|
@@ -50,13 +75,17 @@ export async function callTool(args, tool, toolArguments) {
|
|
|
50
75
|
2,
|
|
51
76
|
);
|
|
52
77
|
}
|
|
53
|
-
const
|
|
54
|
-
|
|
78
|
+
const route = TOOL_ROUTES[tool];
|
|
79
|
+
if (!route) {
|
|
80
|
+
throw new CliError(`${tool} is not reachable from the CLI`);
|
|
81
|
+
}
|
|
82
|
+
const payload = toolArguments || {};
|
|
83
|
+
const result = await callBackendJson(args, route.method, route.path, {
|
|
55
84
|
token,
|
|
85
|
+
...(route.method === "GET" ? { query: payload } : { json: payload }),
|
|
56
86
|
});
|
|
57
87
|
if (!result.ok) {
|
|
58
|
-
|
|
59
|
-
throw new CliError(`${tool} failed: ${result.status_code} ${detail}`);
|
|
88
|
+
throw new CliError(`${tool} failed: ${result.status_code} ${describeFailure(result)}`);
|
|
60
89
|
}
|
|
61
90
|
return result;
|
|
62
91
|
}
|
package/bin/cli.js
CHANGED
|
@@ -38,7 +38,12 @@ import { STATUS_HELP, statusCommand } from "./status.js";
|
|
|
38
38
|
import { HOOK_HELP, hookCommand, installHook, scheduleHookRepair } from "./hook.js";
|
|
39
39
|
import { RUNNER_HELP, runnerCommand } from "./runner.js";
|
|
40
40
|
import { VERIFY_HELP, verifyCommand } from "./verify.js";
|
|
41
|
-
import {
|
|
41
|
+
import {
|
|
42
|
+
DESKTOP_HELP,
|
|
43
|
+
desktopAppRunning,
|
|
44
|
+
installDesktopCommand,
|
|
45
|
+
openDesktopSignedIn,
|
|
46
|
+
} from "./desktop.js";
|
|
42
47
|
import { ACCOUNT_HELP, doctorCommand, loginBrowser, logoutCommand, watchCommand } from "./account.js";
|
|
43
48
|
import {
|
|
44
49
|
CREDENTIALS_FILE,
|
|
@@ -91,7 +96,7 @@ function printHelp() {
|
|
|
91
96
|
["runner start|status|stop", "Run PreMan's queued agent work on this machine"],
|
|
92
97
|
["doctor", "Diagnose credentials, backend, target, integrations"],
|
|
93
98
|
["install-desktop", "Download and install the PreMan desktop app"],
|
|
94
|
-
["onboard", "
|
|
99
|
+
["onboard", "Create an account, install the app signed in, then integrations"],
|
|
95
100
|
["connect [options]", "Pick a coding agent and connect it (optional)"],
|
|
96
101
|
["dispatch [options]", "Let PreMan start agent runs for you"],
|
|
97
102
|
["aws | github | slack", "Connect one integration on its own"],
|
|
@@ -150,7 +155,18 @@ Email: ${creds.user_email || "unknown"}
|
|
|
150
155
|
Backend: ${creds.backend_url}
|
|
151
156
|
API key: ${creds.api_key}
|
|
152
157
|
Saved to: ${CREDENTIALS_FILE}
|
|
153
|
-
|
|
158
|
+
`);
|
|
159
|
+
// `authenticateTerminal` has already left the session for the app to pick up,
|
|
160
|
+
// but only a launch reads it. Signing in here while the app is open otherwise
|
|
161
|
+
// changes nothing on screen, and the window carries on showing the previous
|
|
162
|
+
// account with no sign that a different one is now signed in.
|
|
163
|
+
if (desktopAppRunning()) {
|
|
164
|
+
process.stdout.write(
|
|
165
|
+
`\nPreMan is open and still signed in as before.\n` +
|
|
166
|
+
` Quit and reopen it to switch${creds.user_email ? ` to ${creds.user_email}` : ""}.\n`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
process.stdout.write(`
|
|
154
170
|
You can now run:
|
|
155
171
|
${cli} connect
|
|
156
172
|
`);
|