invoicepig-mcp-server
v1.0.0
Published
MCP (stdio) server for InvoicePig — manage invoice drafts and history via AI agents.
Maintainers
Readme
invoicepig-mcp-server
TypeScript MCP server (stdio) for InvoicePig. It calls your Next.js app’s /api/mcp/* routes with a single API key generated from Settings in the web app.
Prerequisites
- Run the Supabase migration
../supabase/migrations/20260325000000_mcp_api_keys.sqlon your project. - Set
SUPABASE_SERVICE_ROLE_KEYin the Next.js app (.env.local). MCP routes use the service role client after validating the user’s API key. - Sign in to InvoicePig, open Settings, generate a key, and copy it once.
Environment variables
| Variable | Required | Description |
|----------|----------|-------------|
| INVOICEPIG_API_KEY | Yes | Raw key from Settings (full string; prefix pig_live_) |
| INVOICEPIG_API_URL | No | Base URL of the Next app (default https://invoicepig.com) — set to http://localhost:3000 (or your preview URL) when not using production |
Install and build
cd invoicepig-mcp-server
bun install
bun run buildEntry point: dist/index.js (Node ≥ 20).
Hosted MCP (Streamable HTTP) — URL + headers
When the Next.js app is deployed, you can point clients at https://<your-domain>/api/invoicepig-mcp with the same API key in Authorization (no local dist/index.js). Implemented with mcp-handler (createMcpHandler). Paste into your client MCP config and replace <API_KEY> with the full key from Settings:
{
"mcpServers": {
"invoicepig": {
"url": "https://invoicepig.com/api/invoicepig-mcp",
"headers": {
"Authorization": "Bearer <API_KEY>"
}
}
}
}Clients that only support stdio can use mcp-remote against that URL.
Publish to npm (optional, npx like other MCPs)
The package is not private and includes bin.invoicepig-mcp → dist/index.js. prepublishOnly runs npm run build (TypeScript → dist/).
From this directory, after npm login:
npm pack --dry-run # optional: inspect tarball
npm publish # first publish; bump version in package.json for later releasesnpm may strip bin if the path is wrong — use "invoicepig-mcp": "dist/index.js" (no ./ prefix). Run npm pkg fix in this folder if publish warns about package.json.
403 “Two-factor authentication … is required” — npm requires 2FA (or a granular access token) to publish. Enable it under npm account → Access Tokens / Two-Factor Authentication, mode Authorization and writes, then run npm publish again (CLI may prompt for an OTP). Alternatively create a granular access token with Publish permission (and “bypass 2FA” only if your org policy allows).
If the name invoicepig-mcp-server is already taken on npm, rename to a scoped package (e.g. @your-org/invoicepig-mcp) and add "publishConfig": { "access": "public" }, then npm publish --access public.
Users can then configure:
{
"mcpServers": {
"invoicepig": {
"command": "npx",
"args": ["-y", "invoicepig-mcp-server@latest"],
"env": { "INVOICEPIG_API_KEY": "<API_KEY>" }
}
}
}Cursor / Claude Desktop
Add to your MCP config (adjust the path to dist/index.js):
{
"mcpServers": {
"invoicepig": {
"command": "node",
"args": ["/absolute/path/to/invoicepig-adv/invoicepig-mcp-server/dist/index.js"],
"env": {
"INVOICEPIG_API_KEY": "<API_KEY>"
}
}
}
}Production uses https://invoicepig.com automatically. For a preview or self-hosted app, add INVOICEPIG_API_URL:
{
"mcpServers": {
"invoicepig": {
"command": "node",
"args": ["/absolute/path/to/invoicepig-adv/invoicepig-mcp-server/dist/index.js"],
"env": {
"INVOICEPIG_API_URL": "https://your-preview.vercel.app",
"INVOICEPIG_API_KEY": "<API_KEY>"
}
}
}
}Premium behavior
- Layouts: Free accounts can only persist classic, corporate, formal, minimal. Premium layouts return 403 from the API if the Clerk user is not premium/trialing.
- PDF watermark: The MCP does not render PDFs. Watermark vs no watermark is decided in the web app from the same subscription metadata when the user downloads/previews a PDF (
isPremiumingenerateInvoicePdf).
Tools
| Tool | Purpose |
|------|---------|
| invoicepig_get_draft | Load cloud draft |
| invoicepig_update_draft | Partial merge into draft |
| invoicepig_create_invoice | Replace draft (replaceDraft) |
| invoicepig_add_line_item | Append line |
| invoicepig_remove_line_item | Remove line by id |
| invoicepig_save_to_history | POST history from current draft |
| invoicepig_list_invoices | Paginated history |
| invoicepig_get_invoice | One history entry |
| invoicepig_delete_invoice | Delete history entry |
| invoicepig_calculate_totals | Local math helper |
| invoicepig_list_layouts | Free vs premium layouts for this key |
Local testing
bun run build
# Use MCP Inspector (example):
# npx @modelcontextprotocol/inspector node ./dist/index.jsEvaluation scenarios (multi-step)
- Layouts first: Call
invoicepig_list_layouts, theninvoicepig_create_invoicewithselected_layout: "classic"; verify draft saves. - Premium gate: On a free account,
invoicepig_update_draftwithselected_layout: "luxury"must fail with 403 from the API (tool surfaces error). - Fresh invoice:
invoicepig_create_invoicewithcompany_name, twoitems, theninvoicepig_get_draftand confirm line count. - Line ops:
invoicepig_add_line_item, theninvoicepig_remove_line_itemwith the new item’s id; draft should still have ≥1 row. - History: After a valid draft,
invoicepig_save_to_historywith a customlabel, theninvoicepig_list_invoiceswithlimit: 5and find the new id. - Pagination:
invoicepig_list_invoiceswithoffset: 10, checkhas_more/next_offsetwhen total > 10. - Round-trip:
invoicepig_get_invoicefor an id from the list; comparestate.invoiceNumberValueto what was set. - Delete:
invoicepig_delete_invoiceon a test entry;invoicepig_get_invoiceon same id should error. - Totals:
invoicepig_calculate_totalswith discount percent and tax; verifybalance_duematches manual calculation. - Replace draft:
invoicepig_create_invoiceto set A, theninvoicepig_create_invoiceagain with differentcompany_name;get_draftshould show B only.
Verified against Model Context Protocol TypeScript SDK (@modelcontextprotocol/sdk 1.27.x) and Next.js 16 app-router patterns used in this repo.
