Borrowing it
Nothing to install: this file belongs to mspstack/mcp-connectwise-psa. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.
curl -O https://raw.githubusercontent.com/mspstack/mcp-connectwise-psa/main/CLAUDE.mdgit clone --depth 1 https://github.com/mspstack/mcp-connectwise-psaWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/instructions/mspstack/mcp-connectwise-psa/claude-md)<a href="https://agentmods.dev/instructions/mspstack/mcp-connectwise-psa/claude-md"><img src="https://agentmods.dev/badge/instructions/mspstack/mcp-connectwise-psa/claude-md/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/instructions/mspstack/mcp-connectwise-psa/claude-md"><img src="https://agentmods.dev/badge/instructions/mspstack/mcp-connectwise-psa/claude-md.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.03725 | $0.03725 |
| Opus 5.5 | $0.01490 | $0.01490 |
| Sonnet 5.5 | $0.00745 | $0.00745 |
| Haiku 4.5 | $0.00373 | $0.00373 |
Grade A, and why
mcp-connectwise-psa CLAUDE.md scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 1mo ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 64 lines — stays where its author put it; the contents beside it link to each section on GitHub.
mcp-connectwise-psa
MCP server for ConnectWise PSA (Manage). TypeScript, ESM, Node ≥20. Transports: stdio (local) and streamable HTTP (shared deployments). Sibling project to mcp-itglue — same auth architecture.
Commands
npm run build— tsc →dist/(tests excluded from build)npm test— vitest, test files beside sources (src/**/*.test.ts)npm run dev/npm run dev:http— run from source via tsx
Architecture
src/config.ts— env/flag parsing;CW_SITEaccepts full URLs (normalized to host)src/cw/client.ts— fetch-based CW Manage REST client (API 3.0). Basic authcompanyId+publicKey:privateKey+ mandatoryclientIdheader. List queries use CW's grammar:conditions(exact for names/ids,containsfor text, date literals in[brackets]),orderBy,page/pageSize, andfields(always pass fields — CW records are huge).q()quotes condition values;allOf()joins fragmentssrc/tools/registrar.ts—ToolRegistrarregisters the full tool surface; no MCP-level role gating (ConnectWise enforces the member's security role — unlike mcp-itglue's single account key, PSA is per-member BYOK)src/http/app.ts— pure BYOK: every/mcpsession presents its ownx-cw-public-key/x-cw-private-key(+ optionalx-cw-member-id) headers; no keys → 401; sessions bound to the SHA-256 of the key pair; a different pair on the same session id → 403. stdio uses the server-wideCW_PUBLIC_KEY/CW_PRIVATE_KEYsrc/server.ts— one McpServer per session; the session's CW credentials build itsCWClient. Holds theTOOLSETSregistry (key →register*Tools);createServerregisters onlysession.toolsetssrc/tools/toolsets.ts— capability keys (tickets/time/companies/configurations/schedule/finance/advanced/sql), persona presets (tech/dispatch/invoicing/all), andresolveToolsets(). Selection:CW_TOOLSETS/--toolsets(stdio, unknown key →ConfigError) or thex-cw-toolsetsheader (HTTP, unknown token ignored).allandDEFAULT_TOOLSETSare both[...TOOLSET_KEYS]—advancedandsqlare ordinary keys there, though the persona presets exclude both. What gates the database isCW_DB_*:withoutDbToolsets()prunesDB_TOOLSETSinloadConfig,sessionToolsetsandcreateServerwhen no database is configured, andloadConfigonly errors whensqlwas named outright (namesDbToolset) — otherwise a server without a database would refuse to start over the default it never chosesrc/tools/— tickets, time, companies, configurations (tech); schedule (dispatch); finance (invoicing, read-only); advanced (opt-in escape hatch); helpers intools/shared.tssrc/tools/ticket-classification.ts— board-scoped classification (type→subType→item,team,source) and bundling helpers. Values are passed as name or id and sent as{name}/{id}for CW to resolve against the ticket's board — no local resolver, since the same name means a different id per board (cw_get_boardlists statuses, types, sub-types, items and teams for discovery).copy_classification_fromoncw_create_ticketlifts those fields by id off an existing ticket; explicit args win.partitionBundleCandidatesrefuses a child that already has a parent instead of re-parenting it — detaching is UI-only, so a wrong bundle is expensive to undosrc/tools/ticket-kind.ts— service vs project tickets. CW splits them across/service/ticketsand/project/ticketswith differentchargeToTypevalues, so: list tools taketicket_type(bothdefault) and go throughlistAcrossKinds(one resource failing yields a partial answer plus a note, never an error — a security role can allow one and refuse the other); by-id tools takeauto|service|projectandresolveTicketKindprobes service then project, treating only 404 as "try the other one".TICKET_LIST_FIELDSis deliberately identical for both resources — one unknown field fails the whole callsrc/tools/advanced.ts—cw_get(read-only GET on any path viaCWClient.rawGet; strips host//apis/3.0/inline query, then passesconditions/fields/orderBy/page) andcw_find_endpoint(lexical search oversrc/reference/cw-endpoints.ts). Write passthrough is a deliberate later addsrc/sql/client.ts—SqlClientover the on-premcwwebapp_*database: lazyawait import("mssql")(CJS →.default), one process-wide pool created inindex.ts(never per session — the login is server-wide), cleared on a failed connect so an outage isn't permanent. Results are bounded while streaming (request.stream+cancel()at the row cap / ~20k char budget) — slicing afterwards would OOM onSELECT * FROM SR_Service. Isolation is READ UNCOMMITTED viaoptions.connectionIsolationLevel, not a prependedSET(which shifts SQL error line numbers).describeSqlErrorgives connection errors fixed prose and statement errors the redacted server text;redactSqlMessagestrips host/db/user. No statement validation — thedb_datareaderlogin is the boundary (deliberate; see README)src/sql/library.ts— saved-query library: committed core (src/reference/cw-db-queries.ts) ∪ writable overlay atCW_DB_QUERY_LIBRARY, overlay wins by slug, mtime-based reload, atomic.tmp+rename write, in-process promise chain for concurrent saves.cw_db_save_queryis the only tool in the server that writes anything — and it writes to that file, never to ConnectWisesrc/tools/sql.ts—cw_db_query(shape-adaptive rendering: pipe table ≤10 columns, record blocks above),cw_db_find_table,cw_db_find_query,cw_db_save_query(registered only when the library is writable). Takes aSqlContext { client, library }as the third registrar argumentsrc/reference/cw-db-schema.ts— generated table catalog (84 entries) fromscripts/gen-db-schema.mjs+ the hand annotations inscripts/db-enrich.mjs. Curated core only, never a full inventory: no row counts, no custom/UDF tables, nothing identifying an instance — the repo is public. Names came from reading production reporting queries;scripts/dump-db-schema.sql+ the generator's dump mode verify them against a live schemasrc/reference/search.ts—lexicalRank()shared bycw_find_endpoint,cw_db_find_tableand the query library;findEndpointskept its signature soadvanced.test.tsstayed untouched through the extractionsrc/reference/cw-endpoints.ts— generated endpoint catalog (~1145 paths). CW publishes no fetchable OpenAPI (swagger UI is behind the Manage web login), so a spec is obtained manually andscripts/gen-endpoints.mjsderives this file from it (source kept local under.claude/, gitignored; the generated.tsis committed). Hand annotations (better summaries +keyParams/commonFields/coveredBy) live in the generator'sENRICHmap;/countand/infohelper paths are dropped
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 1mo ago Changed · +2 lines · +251 tokens per session 832e91cc93af
- 2mo ago First seen · 62 lines · 3,474 tokens per session scan A b48ccaf24f34
mcp-connectwise-psa CLAUDE.md is an instructions file published in the GitHub repository mspstack/mcp-connectwise-psa (6 stars, last pushed 1mo ago), licensed MIT. It adds 3,725 tokens to every session, about $0.0149 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.
mcp-connectwise-psa CLAUDE.md compared with instructions from other repositories
| Mod | Type | Stars | Last push | Licence | Scan | Tokens | Works with |
|---|---|---|---|---|---|---|---|
| mcp-connectwise-psa CLAUDE.mdmspstack/mcp-connectwise-psa | Instructions file | 6 | 1mo ago | MIT | A | 3,725 | Claude Code |
| vscode buildNext.instructions.mdmicrosoft/vscode | Instructions file | 195k | today | MIT | A | 9,719 | GitHub Copilot |
| next.js AGENTS.mdvercel/next.js | Instructions file | 143k | today | MIT | A | 7,461 | Codex, OpenCode |
| vscode oss-third-party-notices.instructions.mdmicrosoft/vscode | Instructions file | 195k | today | MIT | A | 5,685 | GitHub Copilot |
| langchain AGENTS.mdlangchain-ai/langchain | Instructions file | 149k | today | MIT | A | 4,680 | Codex, OpenCode |
| deepseek-harness AGENTS.mddeepseek-ai/deepseek-harness | Instructions file | 279k | yesterday | MIT | A | 4,325 | Codex, OpenCode |
| vscode copilot-instructions.mdmicrosoft/vscode | Instructions file | 195k | today | MIT | A | 3,086 | GitHub Copilot |