Invoice-MCP
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Invoice-MCPsummarize my subscription spend for last month"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Rayshio
Rayshio is an invoice aggregator software for businesses that gives your AI agents MCP access to your expenses.
How it Works
Rayshio aggregates invoices directly from a company's billing email address:
User signs in with whatever provider their work email lives on
Pulls a sample of invoices from the email to find the recipient email. Sometimes, billing emails are aliases that forward emails to the user's email address.
Poll through all emails to the billed email address(es) to find all invoices
Invoice PDF is stored in MongoDB
Invoice data is stored in PostgreSQL
See
SPEC.mdfor the full design.
Related MCP server: mcp-ai-fiskalizacija
Setup
cp .env.example .envand fill in values (scripts/has key generators noted inline)docker compose up -dpnpm installpnpm migrate up— appliesmigrations/to Postgrespnpm cli seed-org --name "Your Org"pnpm cli auth— browser OAuth consent, stores encrypted refresh tokenpnpm cli check-connections— sanity check all three databases
Running
Command | What |
| ingestion worker (BullMQ; registers the monthly sync cron) |
| MCP server + dashboard API on |
| Vite dev server on |
| whole-mailbox billing-sender discovery → auto-backfill |
| full history for one sender |
| incremental sync now (otherwise monthly via |
| backfill usage categories onto invoice line items |
just
A root justfile wraps the common loops so nothing depends on remembering
which pnpm script maps to which process. Recipe names cannot contain a colon —
just rejects it at parse time — hence dev-web rather than dev:web.
Command | What |
| list recipes |
|
|
|
|
| both of the above in one terminal; Ctrl-C stops both |
| alias for |
|
|
|
|
|
|
| kill whatever holds a port, when a dev server outlives its terminal |
dev-all runs each server in its own process group so Ctrl-C reaches the
tsx/vite child, not just the pnpm wrapper it was launched through.
Dashboard
A React SPA at /, served by the same process as the MCP server. Pages:
Dashboard (spend, budget, top vendors, recent invoices), Breakdown (usage
categories rolled up across vendors), Invoices (paginated, searchable),
Reports (the same views over fiscal quarters and years), Calendar (received +
projected), and MCP (connection recipes).
Fiscal periods derive from client.org.fiscal_year_start_month (default
January, changeable on the Reports page). Fiscal years are named for the year
they end in — an April start makes Apr 2025 – Mar 2026 into "FY2026" — and
every label carries its date range, since that convention is not universal.
Sign in with Google (Better Auth). Signing in creates a user but grants no access: membership in an org is a deliberate act, so the first person through the door does not inherit a tenant. Grant it with
pnpm cli grant-membership --org 1 --email you@example.com --role ownerSign-up is allowlisted by ALLOWED_SIGNUP_EMAILS; an address outside it can
still join by holding a pending invitation (pnpm cli invite).
MCP keys live in client.api_key — pnpm cli create-api-key --org 1 mints one
and prints it once. No key is ever sent to the browser.
Two behaviours worth knowing:
Currency conversion is query-time only. Invoices are stored in the currency the vendor billed; the dashboard's currency selector is a display target, and every invoice is converted to it at the ECB rate on that invoice's own date, so a past month's total does not move when today's rate does. Converted values are never written back (
SPEC.md:190-196), and converted figures are labeled with the rate date. The ECB publishes ~30 currencies — hard-pegged currencies outside that set (AED) use an explicit peg table insrc/fx/rates.ts. The MCP tools are unaffected and still sum per-currency with no conversion, which is the spec's documented default.Categories live on line items.
billing.invoice_line_items.categoryis assigned by an LLM from a fixed five-value set, so a single vendor invoice can split across categories. Classification never fails an invoice — anything unclassified reads asOtheruntilpnpm cli categorizeretries it.
Local development runs two processes: pnpm mcp and pnpm dev:web (or
just dev-all for both), then open http://localhost:5173. In production only
pnpm start:mcp is needed, provided pnpm build has produced web/dist.
MCP tools
list_services, list_invoices, get_invoice, get_invoice_pdf,
spend_summary — all scoped to the org the presented API key belongs to; money
in minor units, per-currency aggregation, no FX conversion.
Claude Desktop's connector UI expects OAuth, which this MVP doesn't
implement — bridge with mcp-remote
in claude_desktop_config.json instead:
{
"mcpServers": {
"invoice-mcp": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://<host>/mcp",
"--header",
"Authorization: Bearer <MCP_API_KEY>"
]
}
}
}Development
pnpm test/pnpm typecheck/pnpm lint(orjust test/just clean)pnpm codegen— regeneratesrc/db/types.tsafter schema changestsx scripts/smoke-extract.ts [pdf]— live LLM extraction smoke testtsx scripts/make-fixture-pdf.ts— regenerate the multi-page fixture PDFtsx scripts/probe-mailbox.ts [query]— read-only audit of discovery coverage: replays sender attribution over the live mailbox and lists which vendors would be found, which arrive via a billing alias, and which are already ingested
Billing aliases and shared inboxes
Vendor invoices frequently arrive through a shared billing alias or Google Group
(billing@, techteam@, …) rather than direct to the connected mailbox. The
group re-sends the mail with itself as the RFC From: address, leaving the
vendor only in the display name ("'OpenRouter, Inc' via Tech Team"). Keying on
From alone therefore collapses every vendor behind an alias into one
pseudo-sender that no classifier will accept as a vendor.
resolveSender (src/gmail/messages.ts) prefers X-Original-Sender — which
Google sets on exactly these rewrites — and records the alias as
ParsedMessage.deliveredVia. Discovery additionally refuses to treat the org's
own addresses as vendors, so invoices you forward to yourself or to a
bookkeeping tool don't get ingested a second time.
Deploy (Railway)
One repo, two services:
worker — start
pnpm start:workermcp — start
pnpm start:mcp(health check/healthz); serves the MCP endpoint, the dashboard API, and the built SPA from one port
Both services are connected to this repository on main, so a push to main
deploys them. railway up still works and deploys the working tree instead,
which is the escape hatch for testing a change that is not committed — but it
is no longer how a release happens.
Both build with pnpm install && pnpm build (which also builds web/dist).
Migrations run automatically at boot for both roles — the web service can
otherwise start before the worker has applied one and serve sign-ins against a
missing table — so no pre-deploy command is needed. A simultaneous deploy is
safe: node-pg-migrate locks with pg_try_advisory_lock, which does not wait, so
the loser is retried by src/main.ts rather than crashing.
Set env vars per .env.example (Railway injects database URLs for linked
Postgres/Mongo/Redis services). Both services need BETTER_AUTH_SECRET,
AUTH_GOOGLE_CLIENT_ID, AUTH_GOOGLE_CLIENT_SECRET, PUBLIC_APP_URL and
ALLOWED_SIGNUP_EMAILS; the mcp service additionally needs PUBLIC_MCP_URL
set to its public https://<host>/mcp. Build the SPA with
VITE_PUBLIC_ORIGIN=https://<host> so canonical, OG and sitemap URLs are
absolute and correct.
Sign-in uses a separate Google OAuth client from Gmail ingestion. The
ingestion client carries gmail.readonly, a restricted scope, so sharing it
would show a mailbox-access consent screen for a plain login. Register
https://<host>/api/auth/callback/google on the sign-in client.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server for document intelligence via x402 micropayments. 6 tools: document analysis, invoice extraction, screenshot data, alt text, PII detection, sentiment analysis. Pay-per-use with USDC on Base — no API keys needed.61MIT
- AlicenseAqualityCmaintenanceMCP server for creating and fiscalizing invoices via solo.com.hr API. Enables AI agents to generate invoices, retrieve invoice details, list invoices, and check next invoice number.4MIT
- AlicenseAqualityBmaintenanceOne MCP server for the SaaS back office. Stripe, HubSpot, and Google Sheets exposed as typed, read-only-by-default tools for Claude and any MCP client.1MIT
- Alicense-qualityDmaintenanceMCP server for ReceiptConverter that allows AI assistants to parse any receipt or invoice image/PDF into structured JSON with a single tool call.7MIT
Related MCP Connectors
Hosted MCP server for Mini Accountant: invoices, expenses, customers, analytics, tax estimates.
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
Hosted email MCP for AI agents with inboxes, send/receive, memory, recovery, and credits.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/CourtimusPrime/Rayshio'
If you have feedback or need assistance with the MCP directory API, please join our Discord server