npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@triplebooks/mcp

v0.1.0

Published

TripleBooks MCP server — connect Claude Desktop, Cursor, and other MCP clients to your books via the workspace API.

Downloads

101

Readme

@triplebooks/mcp

Stdio Model Context Protocol server that proxies tool calls to the workspace JSON API with Authorization: Bearer ak_… and x-entity-id. No tenant DB or Cortex logic lives here—only HTTP.

Quick start (users)

After this package is published to npm, use Settings → MCP or:

{
  "mcpServers": {
    "triplebooks": {
      "command": "npx",
      "args": ["-y", "@triplebooks/mcp@latest"],
      "env": {
        "AXIOMATIC_BASE_URL": "https://app.triplebooks.com",
        "AXIOMATIC_API_KEY": "ak_…",
        "AXIOMATIC_ENTITY_ID": "…"
      }
    }
  }
}

Quick start (developers)

  1. Copy .env.example to .env.local and set AXIOMATIC_BASE_URL, AXIOMATIC_API_KEY, AXIOMATIC_ENTITY_ID.

  2. Run the workspace (local dev, or pnpm dev:workspace:prod-env from repo root for production-backed env + http://localhost:…).

  3. From this directory:

    pnpm mcp-doctor
    pnpm build
  4. Point Cursor / Claude Desktop at dist/cli.js (local mode) or use npx after publish. In-app: Settings → MCP.

Tool UX: installToolUx adds human titles (e.g. Ledger: List journal) and MCP annotations (readOnlyHint, destructiveHint, openWorldHint) on every tool. After pulling, pnpm build here and fully quit Claude so stdio reloads.

Publish to npm

cd apps/mcp
pnpm pack:npm
npm publish --access public

Requires npm auth for the @triplebooks scope. build:cli bundles workspace code (including @axiomatic/crypto sanitization) into dist/cli.js so the published tarball only depends on @modelcontextprotocol/sdk and zod.

Production usage (HTTP tool path)

What “production” means for MCP: the workspace process behind AXIOMATIC_BASE_URL resolves real control-plane and tenant data, and your key is a real ak_… with correct RBAC scopes. That is true when:

  • AXIOMATIC_BASE_URL is your deployed app origin, or
  • AXIOMATIC_BASE_URL is localhost while the workspace runs with prod-backed env (pnpm dev:workspace:prod-env).

Both are valid; only the network hop to Next changes.

Entity alignment: API keys are pinned to one entity. AXIOMATIC_ENTITY_ID must match that key; withTenant rejects mismatches.

Scopes: Create keys from the workspace (Ledger API keys UI or /api/ledger/api-keys). Use least privilege—e.g. read:ledger for ledger/cap-table/entity_get; read:settings for entity_list_addresses; write:settings for entity_upsert_address and entity_update_profile (NAICS/tax ID); read:crm for CRM reads; write:crm for crm_update_company, crm_create_*, crm_advance_lead_stage, etc.; read:sales / write:sales for quotes/orders/deal pricing and fundraising_create_pipeline_entry; read:admin for parties_list / parties_get; write:admin for parties_create; read:sales for fundraising_get_investor; add read:invoicing / write:invoicing for invoice automation (including projects_invoice_milestone); read:inventory / write:inventory for catalog SKUs; read:projects / write:projects for client projects and internal Work. The API key owner’s RBAC still applies on every route.

Common URL / env mistakes

  • AXIOMATIC_BASE_URL doesn’t match where Next is listening (wrong host/port after a port change).
  • Production ak_ key against a dev workspace that points at a different tenant DB than you expect—or the reverse—so entity UUIDs don’t exist.
  • AXIOMATIC_ENTITY_ID doesn’t match the entity the key was issued for (middleware returns 403).
  • 402 = tenant credits exhausted, not a “wrong URL” (but looks like random API failure if you don’t check body).

Credits: API-key requests debit api_calls per hit. Tenant balance 0 returns 402 (credits_exhausted). Top up tenant credits in-app if tools suddenly fail.

Secrets: Never commit .env.local. Prefer separate keys for read-only vs automation that can write.

Directory (entity, CRM, parties)

| Tool | Purpose | |------|---------| | entity_get | Active entity profile (read:ledger) | | entity_update_profile | Set NAICS / tax ID (EIN, encrypted) / industry / jurisdiction (write:settings, OWNER/ADMIN) | | entity_list_addresses | Entity HQ / registered / mailing addresses (read:settings) | | entity_upsert_address | Create/update entity self-address (write:settings, OWNER/ADMIN) | | crm_list_companies | Paginated companies (read:crm) | | crm_get_company | Company + counterparty detail | | crm_create_company | Create company (write:crm) | | crm_update_company | Patch company; metadata.billingTenantId for credits grant mapping (write:crm) | | crm_list_company_addresses | Addresses for a company | | crm_upsert_company_address | Create/update company address (write:crm) | | crm_list_contacts | People; optional companyId filter | | crm_get_contact | Contact detail | | crm_create_contact | Create contact (write:crm) | | crm_update_contact | Patch contact (write:crm) | | crm_list_leads | Leads/opportunities | | crm_get_lead | Single lead detail | | crm_list_pipeline_stages | Pipeline stages + lead counts | | crm_create_pipeline_stage | Add open stage (write:crm, crm.pipeline.manage) | | crm_update_pipeline_stage | Rename/restyle stage (write:crm, crm.pipeline.manage) | | crm_delete_pipeline_stage | Delete open stage; optional lead reassignment (write:crm) | | crm_reorder_pipeline_stages | Reorder stage columns (write:crm) | | crm_create_lead | Create lead (write:crm) | | crm_update_lead | Patch lead fields (write:crm) | | crm_advance_lead_stage | Move lead stage; won automation (write:crm) | | crm_batch_update_companies | Uniform patch many companies (write:crm) | | crm_archive_company | Set company status inactive (write:crm) | | crm_delete_company | Permanent company delete (write:crm) | | crm_search_prospecting_places | Google Maps Discover search (read:crm) | | crm_get_prospecting_place | Place details by id (read:crm) | | crm_import_prospect_from_place | Import place → prospect company (write:crm) | | crm_discover_company_contacts | Website contact/email discovery (write:crm) | | crm_enrich_company_from_website | Website crawl + apply proposals (write:crm) | | crm_start_succession_scan | Queue batch succession scan (write:admin + crm.leads.edit) | | crm_get_succession_scan_run | Scan run progress + proposals (read:admin) | | crm_list_outbound_email_connections | Gmail/Resend connections for CRM drafts (read:crm) | | crm_create_email_draft | Create CRM email draft only (Gmail Drafts + outbound_messages); optional attachmentDocumentIds (write:crm) | | crm_send_email_draft | Send an approved draft by outboundMessageId (write:crm) | | parties_list | Legal parties search (read:admin, governance.view) | | parties_get | Party detail (seats, holders, links) | | parties_create | Create or dedupe legal party (write:admin, governance.manage) | | fundraising_get_investor | Investor profile + pipeline (read:sales, fundraising.view) | | fundraising_create_pipeline_entry | Add prospect to a round pipeline (write:sales, fundraising.pipeline.manage) | | fundraising_list_pipeline_stages | Round pipeline stages + entry counts (read:sales) | | fundraising_create_pipeline_stage | Add open stage; optional insertAfterStageId (write:sales, fundraising.pipeline.manage) | | fundraising_update_pipeline_stage | Rename/restyle stage (write:sales) | | fundraising_delete_pipeline_stage | Delete open stage; optional entry reassignment (write:sales) | | fundraising_reorder_pipeline_stages | Reorder all stage columns for a round (write:sales) |

Documents & RAG

| Tool | Purpose | |------|---------| | documents_list_folders | Folder tree (read:documents) | | documents_list | List docs; filter folderId or linkableType+linkableId (e.g. counterparty) | | documents_get_text | Full text / PDF extract / OCR for one document | | documents_list_revisions | Revision history (number, source, label, author) for editable docs | | documents_get_revision | One revision: metadata, text body, derived PDFs linked to that revision | | documents_get_derivation | PDF lineage → source document + revision (pass child PDF id) | | documents_create_revision_checkpoint | Named version checkpoint without changing live file (write:documents) | | documents_update_revision_label | Rename/clear revision label (write:documents) | | documents_restore_revision | Restore prior revision as live doc (write:documents) | | documents_update_content | Replace text body; prior version auto-snapshotted (write:documents) | | documents_update_metadata | Rename or retag any file — PDF, PNG, MP4, etc. (write:documents) | | documents_replace_file | Replace binary bytes from a local path on the MCP host (write:documents) | | documents_save_html_pdf | Server-side HTML → PDF save/replace in folder (write:documents) | | documents_list_signature_requests | List e-sign envelopes; optional status filter (read:documents) | | documents_get_signature_request | Detail + signers + placed field overlays / fieldCount (read:documents) | | documents_create_signature_request | Create draft (or send: true); reuses fielded draft for same PDF (write:documents, documents.sign) | | documents_send_signature_request | Send draft invitations (write:documents, documents.sign) | | documents_cancel_signature_request | Cancel envelope (write:documents, documents.sign) | | documents_remind_signature_request | Reminder emails to pending signers (write:documents, documents.sign) | | data_room_sync | Local export-pdfs.sh + data room upload scripts (requires pandoc + Chrome) | | kb_retrieve_context | Semantic RAG (documents + optional kb_page scope); read:documents | | kb_list_spaces | List KB spaces (read:kb) | | kb_list_pages | Pages in a space (read:kb) | | kb_create_space | Create KB space (write:kb) | | kb_create_page | Create KB page with markdown (write:kb) | | kb_update_page | Patch page body / publish (write:kb) | | kb_search_lexical | Full-text search KB titles (read:kb) |

Add read:documents to your API key. After upload, OCR + embedding index runs via the document pipeline/cron — then RAG returns chunks.

Invoicing & printable HTML

MCP tools (requires scopes on the key + RBAC on the key owner):

| Tool | Purpose | |------|---------| | invoicing_list_invoices | Paginated invoice list (GET /api/invoicing/invoicesinvoicing.view or ledger.view on owner) | | invoicing_get_invoice | Full invoice JSON (GET /api/invoicing/invoices/:idinvoicing.view on key owner) | | invoicing_create_invoice | Create DRAFT invoice (POST /api/invoicing/invoiceswrite:invoicing, ledger.post) | | invoicing_update_invoice | Update DRAFT invoice lines/metadata (PATCH without action) | | invoicing_invoice_action | send / void / unvoid / record_payment / mark_paid / void_payment | | invoicing_void_payment | Void one payment (reverse payment/deposit JEs; reopen invoice to SENT when unpaid) | | invoicing_backfill_line_catalog | Attach catalog SKU snapshots to existing lines (PAID ok) without changing amounts | | invoicing_invoice_print_meta | Print / template metadata without full HTML: printPath, default vs invoicing.print template, MIME OK for merge, totals, line sample | | invoicing_invoice_send_readiness | Send pre-flight: customer billing email, Gmail/Resend connections, HTML_TO_PDF_ENABLED, blockers/warnings, suggested billing period | | invoicing_send_invoice | Email invoice PDF (same as Invoicing → Send): posts AR, marks SENT. Optional to / deliveryMemo; defaults connection + billing period from readiness. dryRun: true previews without emailing | | invoicing_list_outbound_email_connections | Active outbound email connections (connectionId + channel for send) | | invoicing_list_print_templates | Rows with category invoicing.print (linked document for HTML merge) — needs read:documents | | invoicing_ar_subledger_grid | AR subledger vs GL (moduleKey=ar slice of subledger grid); optional onlyDrift |

Add read:invoicing / write:invoicing to your API key for invoice automation.

Sales — quotes, orders, deal pricing

| Tool | Purpose | |------|---------| | sales_list_quotes | Paginated quotes — read:sales | | sales_get_quote | Quote + lines + linked Order Form hint | | sales_update_quote | Patch quote; lines on draft with milestone_servicewrite:sales | | sales_propose_quote_milestones_from_document | Propose milestone rows from OF/SOW (no write) — write:sales | | sales_convert_quote_to_order | Quote → draft order (full line copy) — write:sales | | sales_list_orders / sales_get_order | Order list + detail — read:sales | | sales_update_order | Confirm order (spawn project), finalize one-time invoice — write:sales |

Catalog / inventory

| Tool | Purpose | |------|---------| | catalog_search | Line-picker search (GET /api/inventory/catalog) — read:inventory | | inventory_list_items | Paginated item list (GET /api/inventory?view=items) | | inventory_get_item | Single item detail | | inventory_create_item | Create SKU (POST /api/inventory create-item) — write:inventory | | inventory_update_item | Update SKU (PUT /api/inventory) |

Client projects / service jobs

| Tool | Purpose | |------|---------| | projects_list | List client jobs/projects (GET /api/projects/services) — read:projects | | projects_get | Job detail with lines/milestones | | projects_get_finance | WIP, recognized revenue, billable milestones + invoiceId | | projects_invoice_milestone | DRAFT AR invoice for one milestone (idempotent) — write:invoicing | | projects_create | Create client project — write:projects | | projects_update | Patch job status, notes, dates |

Internal Work backlog uses work_* tools (same projects API scope).

Period close (checklists + soft/hard close)

| Tool | Purpose | |------|---------| | ledger_close_calendar | Templates / checklists / checklist-items (+ system checks) — read:ledger | | ledger_close_dashboard | Focus period, checklist progress, blockers — read:ledger | | ledger_generate_close_checklist | Spawn checklist for a period — write:ledger + ledger.close | | ledger_update_close_checklist_item | Status / assignee / notes on one item — write:ledger + ledger.close | | ledger_update_close_checklist | Checklist IN_PROGRESS / COMPLETEDwrite:ledger + ledger.close | | ledger_close_period | SOFT_CLOSE / HARD_CLOSEwrite:ledger + ledger.close | | ledger_reopen_period | Reopen soft/hard-closed period — write:ledger + ledger.close |

Shipped on main in eebd227d. Cursor loads tsx src/index.ts; after a pull that adds tools, run Developer: Reload Window or the IDE keeps a stale tool list.

Audit chain (tamper-evident log)

| Tool | Purpose | |------|---------| | ledger_audit_chain_summary | Entry counts, head/genesis hashes, needsBackfill | | ledger_audit_chain_verify | Full SHA-256 chain recompute — valid, brokenAt | | ledger_audit_chain_inspect | Diagnose break: stored vs recomputed hashes, breakReason, duplicate sequences | | ledger_query_audit_trail | Paginated human-readable rows (no hash fields) |

Requires read:ledger scope and key owner admin.view RBAC (same as /accounting/audit-verify UI).

Verification

pnpm mcp-doctor

Loads .env.local, validates env, GETs /api/ledger/subledgers?action=specs, lists period-close tool names, and checks GET /api/ledger/close-dashboard.

Extra smoke checks (cap-table summary; 403 is OK if the key lacks cap_table.view):

pnpm mcp-doctor -- --smoke

Spot-check tools you rely on (same URL + headers as MCP): cap table summary, trial balance, etc.

Cursor

Repo .cursor/mcp.json runs tsx src/index.ts with envFileplatform/apps/mcp/.env.local.

Composer agent server id is often project-0-axiomatic-axiomatic (not axiomatic); see workspace Cursor rules.

Missing tools after git pull? Doctor passing only proves the API is reachable. Cursor caches the MCP tool list until Command Palette → Developer: Reload Window (or toggle the server off/on). Claude Desktop users who run node dist/index.js must also pnpm build in apps/mcp after tool registration changes.

Second MCP server (another entity)

Copy .env.example to platform/apps/mcp/.env.harvest-blade.local (gitignored) with a separate ak_… key and that entity's AXIOMATIC_ENTITY_ID. The repo registers server axiomatic-hb in .cursor/mcp.json (short id — Cursor limits combined server+tool name length). Reload Cursor after editing; agent server id becomes project-0-axiomatic-axiomatic-hb.

CapSign Inc. (separate tenant): .env.capsign.local + server axiomatic-capsign. Verify: pnpm mcp-doctor:capsign. Agent id: project-0-axiomatic-axiomatic-capsign.

Import / QuickBooks inspection

| Tool | Purpose | |------|---------| | ledger_list_import_batches | Batch list with counts and match status | | ledger_get_import_batch | Rows in one batch | | ledger_staged_import_breakdown | Group by source_format + status; pass importMethod: QUICKBOOKS | | ledger_save_match_pattern | Save bank-feed match_patterns rule from a NEEDS_REVIEW row; optional reapply to siblings | | ledger_list_match_patterns | List all Rules (match_patterns) for the entity | | ledger_upsert_match_pattern | Create or update a rule by counterpartyPattern | | ledger_update_match_pattern | Patch one rule by id | | ledger_delete_match_pattern | Delete one rule by id | | ledger_get_settings | Read Autopilot mode, confidence threshold, require AI approval (read:ledger) | | ledger_update_settings | Patch Autopilot / controls (write:ledger, ledger.edit) | | integrations_list_connections | QBO/Plaid connection + last sync error | | integrations_get_sync_logs | Per-connection sync history | | ledger_migration_sources | Migration wizard connected sources |

Requires read:ledger on the API key.

Claude Desktop

Recommended (after npm publish):

{
  "mcpServers": {
    "triplebooks": {
      "command": "npx",
      "args": ["-y", "@triplebooks/mcp@latest"],
      "env": {
        "AXIOMATIC_BASE_URL": "https://app.triplebooks.com",
        "AXIOMATIC_API_KEY": "ak_…",
        "AXIOMATIC_ENTITY_ID": "…"
      }
    }
  }
}

Local checkout (after pnpm build):

{
  "mcpServers": {
    "triplebooks": {
      "command": "node",
      "args": ["/ABS/PATH/platform/apps/mcp/dist/cli.js"],
      "env": {
        "AXIOMATIC_BASE_URL": "http://localhost:3010",
        "AXIOMATIC_API_KEY": "ak_…",
        "AXIOMATIC_ENTITY_ID": "…"
      }
    }
  }
}

During development you can use pnpm exec tsx src/index.ts with the same env map.

CI

pnpm build at the repo root runs Turbo build, which includes @triplebooks/mcp (tsc + bundled dist/cli.js). The GitHub Actions TypeScript workflow runs that full build so MCP must compile on every PR.

Remote / hosted MCP (next stage)

Claude Desktop and Cursor default to local stdio (spawn process). Hosting MCP over HTTP/SSE for claude.ai requires remote MCP + OAuth — Stage 3.

Scripts

| Script | Purpose | |--------|---------| | pnpm build | tsc + bundled dist/cli.js | | pnpm pack:npm | Build and create an npm tarball for inspection | | pnpm mcp-doctor | Env + subledger specs + close-dashboard API + period-close tool name list | | pnpm mcp-doctor -- --smoke | Above + optional cap-table summary + audit chain verify | | pnpm start | node dist/cli.js (stdio server) |

See src/index.ts header comment for full context.