Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add instructions/mspstack/mcp-connectwise-psa/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.svg" alt="Measured on agentmods" 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 | $0.03474 | $0.03474 |
| Opus 5 | $0.01737 | $0.01737 |
| Sonnet 5 | $0.00695 | $0.00695 |
| Haiku 4.5 | $0.00347 | $0.00347 |
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 3d 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 — 62 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-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.
- 3d 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 (5 stars, last pushed 6d ago), licensed MIT. It adds 3,474 tokens to every session, about $0.0174 per session on Opus 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.
Other instructions, from other repositories
vscode buildNext.instructions.md
Working notes and architecture documentation for the new esbuild-based build system in build/next. Use when making changes to the new build pipeline (transpile/bundle commands, NLS plugin, source-map handling, resource copying, or self-hosting watch tasks).
spec-kit AGENTS.md
AGENTS.md instructions for github/spec-kit, covering agents.md, about spec kit and specify, quickstart — add a new integration in 5 steps, integration architecture and integrationmanifest — file tracking.
codex AGENTS.md
AGENTS.md instructions for openai/codex, covering rust/codex-rs, the codex-core crate, code review rules, crate api surface and model visible context.
langchain AGENTS.md
AGENTS.md instructions for langchain-ai/langchain, covering global development guidelines for the langchain monorepo, corridor security analysis, project architecture and context, monorepo structure and development tools & commands.
vscode oss-third-party-notices.instructions.md
Instructions for microsoft/vscode, covering vs code oss third-party-notices pipeline, architecture, pipeline flow in ci, applying the notice (cutover) and fallback chain (never fail the build).
next.js AGENTS.md
Instructions for vercel/next.js, covering next.js development guide, codebase structure, monorepo overview, core package: packages/next and other important packages.