getprismo 0.1.13 → 0.1.14

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 CHANGED
@@ -22,18 +22,21 @@ prismodev catches it before, during, and after.
22
22
 
23
23
  ## the loop
24
24
 
25
- prismodev is three commands that cover an entire coding session:
25
+ prismodev covers the full AI coding session:
26
26
 
27
27
  ```
28
28
  before you code npx getprismo doctor
29
29
  while you code npx getprismo watch
30
+ noisy commands npx getprismo shield -- npm test
30
31
  after you code npx getprismo cc timeline
32
+ agent-native npx getprismo mcp
31
33
  ```
32
34
 
33
35
  **doctor** diagnoses the repo, applies safe fixes, and shows the before/after score.
34
36
  **watch** monitors context pressure live and warns when things go wrong.
35
37
  **cc timeline** reconstructs what happened in the session so you learn from it.
36
38
  **shield** runs noisy commands without dumping full output back into the agent context.
39
+ **mcp** exposes PrismoDev as local tools so compatible agents can scan, search shield output, and request scoped context directly.
37
40
 
38
41
  ---
39
42
 
@@ -532,6 +535,7 @@ no install needed. npx runs it directly.
532
535
  | `optimize` | generate `.prismo/` context packs |
533
536
  | `context` | print paste-ready prompt for agents |
534
537
  | `shield` | run noisy commands while keeping full output out of chat |
538
+ | `mcp` | expose PrismoDev tools over local MCP stdio |
535
539
  | `setup` | detect tools, logs, proxy readiness |
536
540
  | `usage` | show raw session token usage |
537
541
  | `init` | add npm scripts and .prismo/README.md |
@@ -583,6 +587,53 @@ npx getprismo shield last
583
587
  npx getprismo shield search "auth failure"
584
588
  ```
585
589
 
590
+ ### mcp mode
591
+
592
+ ```bash
593
+ npx getprismo mcp
594
+ npx getprismo mcp /path/to/repo
595
+ ```
596
+
597
+ `mcp` starts a local stdio MCP server for agent clients. It exposes:
598
+
599
+ - `prismo_scan`
600
+ - `prismo_doctor_dry_run`
601
+ - `prismo_watch_snapshot`
602
+ - `prismo_shield_run`
603
+ - `prismo_shield_search`
604
+ - `prismo_shield_last`
605
+ - `prismo_context_pack`
606
+ - `prismo_firewall`
607
+ - `prismo_cc_timeline`
608
+
609
+ This lets an MCP-compatible agent search prior shielded test/build output, request scoped context packs, or inspect token-waste signals without pasting giant logs into the conversation.
610
+
611
+ Generic MCP client config:
612
+
613
+ ```json
614
+ {
615
+ "mcpServers": {
616
+ "prismodev": {
617
+ "command": "npx",
618
+ "args": ["-y", "getprismo", "mcp", "/path/to/your/repo"]
619
+ }
620
+ }
621
+ }
622
+ ```
623
+
624
+ For local development from this repo:
625
+
626
+ ```json
627
+ {
628
+ "mcpServers": {
629
+ "prismodev": {
630
+ "command": "node",
631
+ "args": ["/path/to/prismodev/bin/prismo.js", "mcp", "/path/to/your/repo"]
632
+ }
633
+ }
634
+ }
635
+ ```
636
+
586
637
  ---
587
638
 
588
639
  ## cc modes
@@ -728,8 +779,10 @@ lib/prismo-dev/constants.js shared defaults, pricing, patterns
728
779
  lib/prismo-dev/context-optimize.js context packs, scoped prompts
729
780
  lib/prismo-dev/doctor.js doctor/dev/init orchestration
730
781
  lib/prismo-dev/fixes.js safe ignore/template generation
782
+ lib/prismo-dev/mcp.js local MCP server and Prismo tool bindings
731
783
  lib/prismo-dev/report.js terminal, markdown, ci reports
732
784
  lib/prismo-dev/scan.js repo scanning, scoring, readiness
785
+ lib/prismo-dev/shield.js local command shield and searchable output index
733
786
  lib/prismo-dev/usage-watch.js local logs, watch, cost, timeline
734
787
  ```
735
788
 
@@ -739,8 +792,11 @@ lib/prismo-dev/usage-watch.js local logs, watch, cost, timeline
739
792
 
740
793
  ```bash
741
794
  npx getprismo --help
795
+ npx getprismo --version
742
796
  npx getprismo doctor --help
743
797
  npx getprismo watch --help
798
+ npx getprismo shield --help
799
+ npx getprismo mcp --help
744
800
  npx getprismo cc --help
745
801
  npx getprismo scan --help
746
802
  ```
@@ -0,0 +1,264 @@
1
+ function createTextResult(payload) {
2
+ const text = typeof payload === "string" ? payload : JSON.stringify(payload, null, 2);
3
+ return {
4
+ content: [{ type: "text", text }],
5
+ };
6
+ }
7
+
8
+ function normalizeArgs(args) {
9
+ return args && typeof args === "object" ? args : {};
10
+ }
11
+
12
+ function makeTool(name, description, properties = {}, required = []) {
13
+ return {
14
+ name,
15
+ description,
16
+ inputSchema: {
17
+ type: "object",
18
+ properties,
19
+ required,
20
+ additionalProperties: false,
21
+ },
22
+ };
23
+ }
24
+
25
+ function createMcpTools(deps) {
26
+ const {
27
+ rootDir,
28
+ scanRepo,
29
+ toJsonPayload,
30
+ runDoctor,
31
+ toDoctorJsonPayload,
32
+ getUsageSummary,
33
+ getClaudeCodeCostSummary,
34
+ runOptimize,
35
+ createOptimizeContext,
36
+ renderStarterPrompt,
37
+ runFirewall,
38
+ runShield,
39
+ runShieldLast,
40
+ runShieldSearch,
41
+ } = deps;
42
+
43
+ const pathProperty = {
44
+ type: "string",
45
+ description: "Repository path. Defaults to the repo used when the MCP server started.",
46
+ };
47
+ const limitProperty = {
48
+ type: "number",
49
+ description: "Maximum number of recent sessions or runs to inspect.",
50
+ };
51
+ const scopeProperty = {
52
+ type: "string",
53
+ description: "Optional scope such as frontend, backend, auth, tests, billing, or routing.",
54
+ };
55
+
56
+ const tools = [
57
+ makeTool("prismo_scan", "Scan a repo for AI coding token/context waste.", {
58
+ path: pathProperty,
59
+ includeUsage: { type: "boolean", description: "Include local Claude/Codex usage logs when available." },
60
+ limit: limitProperty,
61
+ }),
62
+ makeTool("prismo_doctor_dry_run", "Preview PrismoDev doctor fixes and before/after payoff without writing files.", {
63
+ path: pathProperty,
64
+ scope: scopeProperty,
65
+ limit: limitProperty,
66
+ }),
67
+ makeTool("prismo_watch_snapshot", "Return a one-shot local session/context pressure snapshot.", {
68
+ path: pathProperty,
69
+ tool: { type: "string", enum: ["all", "codex", "claude"], description: "Which local session logs to inspect." },
70
+ limit: limitProperty,
71
+ }),
72
+ makeTool("prismo_shield_run", "Run a noisy command through Prismo shield and store full output locally.", {
73
+ path: pathProperty,
74
+ command: {
75
+ type: "array",
76
+ items: { type: "string" },
77
+ description: "Command argv array, for example [\"npm\", \"test\"].",
78
+ },
79
+ }, ["command"]),
80
+ makeTool("prismo_shield_search", "Search stored shield stdout/stderr without loading full logs into context.", {
81
+ path: pathProperty,
82
+ query: { type: "string", description: "Text to search for in stored shield output." },
83
+ limit: limitProperty,
84
+ }, ["query"]),
85
+ makeTool("prismo_shield_last", "List recent shielded command runs.", {
86
+ path: pathProperty,
87
+ limit: limitProperty,
88
+ }),
89
+ makeTool("prismo_context_pack", "Generate or preview a scoped Prismo context pack/starter prompt.", {
90
+ path: pathProperty,
91
+ scope: scopeProperty,
92
+ dryRun: { type: "boolean", description: "When true, do not write .prismo files." },
93
+ }),
94
+ makeTool("prismo_firewall", "Generate a scoped context firewall policy for a task.", {
95
+ path: pathProperty,
96
+ task: { type: "string", description: "Task description such as auth-bug or frontend-test-failure." },
97
+ scope: scopeProperty,
98
+ dryRun: { type: "boolean", description: "When true, preview allowed/blocked context without writing files." },
99
+ }),
100
+ makeTool("prismo_cc_timeline", "Return the latest Claude Code session timeline/postmortem data.", {
101
+ path: pathProperty,
102
+ limit: limitProperty,
103
+ }),
104
+ ];
105
+
106
+ function resolveRoot(args) {
107
+ return args.path || rootDir || process.cwd();
108
+ }
109
+
110
+ async function callTool(name, rawArgs) {
111
+ const args = normalizeArgs(rawArgs);
112
+ const target = resolveRoot(args);
113
+
114
+ if (name === "prismo_scan") {
115
+ return createTextResult(toJsonPayload(scanRepo(target, {
116
+ includeUsage: Boolean(args.includeUsage),
117
+ usageLimit: Number(args.limit) || 5,
118
+ })));
119
+ }
120
+
121
+ if (name === "prismo_doctor_dry_run") {
122
+ const result = runDoctor(target, {
123
+ dryRun: true,
124
+ scope: args.scope || null,
125
+ limit: Number(args.limit) || 3,
126
+ });
127
+ return createTextResult(toDoctorJsonPayload(result));
128
+ }
129
+
130
+ if (name === "prismo_watch_snapshot") {
131
+ const summary = getUsageSummary({
132
+ cwd: target,
133
+ limit: Number(args.limit) || 3,
134
+ usageTool: args.tool || "all",
135
+ });
136
+ return createTextResult(summary);
137
+ }
138
+
139
+ if (name === "prismo_shield_run") {
140
+ return createTextResult(runShield(target, args.command));
141
+ }
142
+
143
+ if (name === "prismo_shield_search") {
144
+ return createTextResult(runShieldSearch(target, args.query, { limit: Number(args.limit) || 5 }));
145
+ }
146
+
147
+ if (name === "prismo_shield_last") {
148
+ return createTextResult(runShieldLast(target, { limit: Number(args.limit) || 5 }));
149
+ }
150
+
151
+ if (name === "prismo_context_pack") {
152
+ const scope = args.scope || null;
153
+ const result = runOptimize(target, { scope, dryRun: args.dryRun !== false });
154
+ const context = createOptimizeContext(target, scope);
155
+ return createTextResult({
156
+ ...result,
157
+ starterPrompt: renderStarterPrompt(context, scope),
158
+ });
159
+ }
160
+
161
+ if (name === "prismo_firewall") {
162
+ return createTextResult(runFirewall(target, {
163
+ task: args.task || args.scope || "general",
164
+ scope: args.scope || null,
165
+ dryRun: args.dryRun !== false,
166
+ }));
167
+ }
168
+
169
+ if (name === "prismo_cc_timeline") {
170
+ return createTextResult(getClaudeCodeCostSummary({
171
+ cwd: target,
172
+ limit: Number(args.limit) || 1,
173
+ mode: "timeline",
174
+ }));
175
+ }
176
+
177
+ throw new Error(`Unknown MCP tool: ${name}`);
178
+ }
179
+
180
+ return { tools, callTool };
181
+ }
182
+
183
+ function runMcpServer(deps) {
184
+ const readline = require("readline");
185
+ const { packageVersion = "0.0.0" } = deps;
186
+ const { tools, callTool } = createMcpTools(deps);
187
+ const rl = readline.createInterface({
188
+ input: process.stdin,
189
+ output: process.stdout,
190
+ terminal: false,
191
+ });
192
+
193
+ function send(message) {
194
+ process.stdout.write(`${JSON.stringify(message)}\n`);
195
+ }
196
+
197
+ async function handle(message) {
198
+ if (!message || !message.method) return;
199
+ if (!Object.prototype.hasOwnProperty.call(message, "id")) return;
200
+
201
+ try {
202
+ if (message.method === "initialize") {
203
+ send({
204
+ jsonrpc: "2.0",
205
+ id: message.id,
206
+ result: {
207
+ protocolVersion: "2024-11-05",
208
+ capabilities: { tools: {} },
209
+ serverInfo: { name: "prismodev", version: packageVersion },
210
+ },
211
+ });
212
+ return;
213
+ }
214
+
215
+ if (message.method === "tools/list") {
216
+ send({ jsonrpc: "2.0", id: message.id, result: { tools } });
217
+ return;
218
+ }
219
+
220
+ if (message.method === "tools/call") {
221
+ const params = normalizeArgs(message.params);
222
+ const result = await callTool(params.name, params.arguments);
223
+ send({ jsonrpc: "2.0", id: message.id, result });
224
+ return;
225
+ }
226
+
227
+ send({
228
+ jsonrpc: "2.0",
229
+ id: message.id,
230
+ error: { code: -32601, message: `Method not found: ${message.method}` },
231
+ });
232
+ } catch (error) {
233
+ send({
234
+ jsonrpc: "2.0",
235
+ id: message.id,
236
+ error: {
237
+ code: -32000,
238
+ message: error && error.message ? error.message : String(error),
239
+ },
240
+ });
241
+ }
242
+ }
243
+
244
+ rl.on("line", (line) => {
245
+ if (!line.trim()) return;
246
+ try {
247
+ handle(JSON.parse(line));
248
+ } catch (error) {
249
+ send({
250
+ jsonrpc: "2.0",
251
+ id: null,
252
+ error: {
253
+ code: -32700,
254
+ message: error && error.message ? error.message : String(error),
255
+ },
256
+ });
257
+ }
258
+ });
259
+ }
260
+
261
+ module.exports = {
262
+ createMcpTools,
263
+ runMcpServer,
264
+ };
@@ -3,6 +3,7 @@ const http = require("http");
3
3
  const https = require("https");
4
4
  const os = require("os");
5
5
  const path = require("path");
6
+ const { version: PACKAGE_VERSION } = require("../package.json");
6
7
 
7
8
  const {
8
9
  HIGH_RISK_DIRS,
@@ -282,10 +283,13 @@ const {
282
283
  color,
283
284
  });
284
285
 
286
+ const { runMcpServer } = require("./prismo-dev/mcp");
287
+
285
288
  function printHelp() {
286
289
  console.log(`Prismo CLI
287
290
 
288
291
  Usage:
292
+ prismo --version
289
293
  prismo dev [path]
290
294
  prismo init [--json] [--dry-run] [path]
291
295
  prismo doctor [--json] [--dry-run] [--apply-ignores-only] [--no-context-packs] [--limit N] [path]
@@ -293,6 +297,7 @@ Usage:
293
297
  prismo shield [--json] [path] -- <command ...>
294
298
  prismo shield last [--json] [--limit N] [path]
295
299
  prismo shield search <query> [--json] [--limit N] [path]
300
+ prismo mcp [path]
296
301
  prismo setup [--json] [--proxy-url URL] [path]
297
302
  prismo scan [--fix] [--ci] [--json] [--usage] [--simple] [--no-report] [path]
298
303
  prismo optimize [scope] [--json] [path]
@@ -308,6 +313,7 @@ Commands:
308
313
  doctor Diagnose, safely optimize, re-scan, and show before/after payoff.
309
314
  firewall Generate allowed/blocked context policy files for an AI coding task.
310
315
  shield Run a noisy command, store full output locally, and return a compact summary.
316
+ mcp Start a local MCP server exposing Prismo tools over stdio.
311
317
  scan Run PrismoDev for Claude Code, Codex, Cursor, and AI coding workflows.
312
318
  optimize Generate lightweight AI-readable project context files in .prismo/.
313
319
  context Print a copy-pasteable compact context prompt for AI coding tools.
@@ -511,6 +517,28 @@ Examples:
511
517
  Output:
512
518
  Runs the command locally, stores full stdout/stderr under .prismo/shield/runs/, indexes output in SQLite FTS5 when available, and prints only a compact summary plus useful error lines.
513
519
  Search and last retrieve prior shield runs without re-feeding full output into agent context.`,
520
+ mcp: `Prismo MCP Server
521
+
522
+ Usage:
523
+ prismo mcp [path]
524
+
525
+ Examples:
526
+ prismo mcp
527
+ prismo mcp /path/to/repo
528
+
529
+ Tools exposed:
530
+ prismo_scan
531
+ prismo_doctor_dry_run
532
+ prismo_watch_snapshot
533
+ prismo_shield_run
534
+ prismo_shield_search
535
+ prismo_shield_last
536
+ prismo_context_pack
537
+ prismo_firewall
538
+ prismo_cc_timeline
539
+
540
+ Output:
541
+ Starts a local JSON-RPC MCP server over stdio. Use it from MCP-compatible clients so agents can scan context waste, search shielded command output, and request scoped context without loading huge logs into chat.`,
514
542
  ci: `Prismo CI
515
543
 
516
544
  Usage:
@@ -549,6 +577,10 @@ Good first command for people who want to see the value before scanning a repo.`
549
577
 
550
578
  async function runCli(argv) {
551
579
  const [command, ...rest] = argv;
580
+ if (command === "--version" || command === "-v" || command === "version") {
581
+ console.log(PACKAGE_VERSION);
582
+ return;
583
+ }
552
584
  if (!command || command === "--help" || command === "-h") {
553
585
  printHelp();
554
586
  return;
@@ -557,8 +589,8 @@ async function runCli(argv) {
557
589
  printCommandHelp(command);
558
590
  return;
559
591
  }
560
- if (!["dev", "init", "doctor", "firewall", "shield", "setup", "scan", "optimize", "context", "cc", "usage", "watch", "demo"].includes(command)) {
561
- throw new Error(`Unknown command: ${command}. Try: prismo doctor, prismo watch, prismo shield, prismo firewall, prismo init, prismo scan, prismo optimize, prismo context, prismo cc, or prismo usage`);
592
+ if (!["dev", "init", "doctor", "firewall", "shield", "mcp", "setup", "scan", "optimize", "context", "cc", "usage", "watch", "demo"].includes(command)) {
593
+ throw new Error(`Unknown command: ${command}. Try: prismo doctor, prismo watch, prismo shield, prismo mcp, prismo firewall, prismo init, prismo scan, prismo optimize, prismo context, prismo cc, or prismo usage`);
562
594
  }
563
595
 
564
596
  if (command === "demo") {
@@ -674,6 +706,28 @@ async function runCli(argv) {
674
706
  return;
675
707
  }
676
708
 
709
+ if (command === "mcp") {
710
+ const target = getPositionals(rest)[0] || process.cwd();
711
+ runMcpServer({
712
+ rootDir: path.resolve(target),
713
+ packageVersion: PACKAGE_VERSION,
714
+ scanRepo,
715
+ toJsonPayload,
716
+ runDoctor,
717
+ toDoctorJsonPayload,
718
+ getUsageSummary,
719
+ getClaudeCodeCostSummary,
720
+ runOptimize,
721
+ createOptimizeContext,
722
+ renderStarterPrompt,
723
+ runFirewall,
724
+ runShield,
725
+ runShieldLast,
726
+ runShieldSearch,
727
+ });
728
+ return;
729
+ }
730
+
677
731
  if (command === "setup") {
678
732
  const json = rest.includes("--json");
679
733
  const limitIndex = rest.indexOf("--limit");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getprismo",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Local AI coding workflow scanner for Codex, Claude Code, Cursor, and token-waste diagnostics.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/shanirsh/prismodev#readme",