wallos-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., "@wallos-mcpWhat's my total monthly cost for all subscriptions?"
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.
Your subscription tracker, readable and writable by your AI assistant, on a server you own.
wallos-mcp connects a self-hosted Wallos instance to Claude and any other MCP client. It can list, create, edit and delete subscriptions, manage categories, payment methods, household members and currencies, and read monthly cost, budgets, settings and the iCal feed.
It runs as a remote server on your own Cloudflare Worker, so the same connection answers from Claude Code on a laptop, claude.ai in a browser, and Claude on a phone. Each connection signs in to one Wallos account by naming an instance and pasting its API key, and that key stays in your Cloudflare account.
Which Wallos it works with
Wallos v5.0.0 or newer — that release, on 2026-07-11, introduced the API-key HTTP API with action=add|edit|delete write endpoints for subscriptions and every master-data list. This server is built on that API alone: no password, no session cookie, no scraped form post. Of the 27 endpoints it calls, 25 exist from v5.0.0; get_period_budget and update_budget arrived in v5.3.0 and are simply absent from the tool list on anything older.
A sign-in naming an instance below 5.0.0 is refused with its version, rather than binding a connection whose every call would fail. Verified end to end against v5.2.0 and v5.4.2.
How it compares
wallos-mcp | |||
Where it runs | Cloudflare Workers | local process | Docker container |
Reachable from a phone | ✅ | ❌ | ✅ if you expose it |
How it authenticates to Wallos | API key | username + password, then a session cookie | API key |
Works against Wallos v5 | ✅ | ❌ writes target | ❌ writes target |
Tools | 26, plus 5 admin and 2 more on Wallos 5.3+ | 7 | 7 |
Delete a subscription | ✅ | ❌ | ❌ |
Several instances at once | ✅ one per connection | ❌ | ❌ |
Last commit | — | August 2025 | April 2026 |
Both existing servers predate the v5 API. The endpoint claims above are checkable: git log upstream shows endpoints/subscription/edit.php removed in the v5.0 UI overhaul, and api/subscriptions/create_subscription.php answers 404 on any v5 instance.
Related MCP server: Remote MCP Server on Cloudflare
Use it
Connect to the hosted deployment
claude mcp add --transport http wallos https://wallos-mcp.mkpo.li/mcpSign in with your instance URL and API key. The key is held encrypted in that deployment's KV, which means trusting whoever runs it with the same authority your Wallos password carries; regenerating the key in Wallos ends that access at once. Anyone who would rather not make that trade deploys their own below — it is the same software and takes about five minutes.
Or deploy your own
The button copies the repository into your GitHub account, creates the KV namespace and the Durable Object, and asks for the two secrets.
From a terminal instead — you need a Cloudflare account, bun, and a Wallos instance reachable over HTTPS:
git clone https://github.com/mkpoli/wallos-mcp && cd wallos-mcp
bun install
bun run setupbun run setup asks which domain to answer on, creates or reuses the KV namespace, takes ALLOWED_HOSTS, generates a cookie key, and deploys. The first two answers land in wrangler.local.jsonc, which git ignores, so wrangler.jsonc names nobody's namespace and nobody's domain and a clone deploys anywhere. Re-running it to rotate one secret is safe.
1 · Copy your Wallos API key
In Wallos, open Settings and find API key on your own profile. Generate one if the field is empty.
2 · Deploy the Worker
git clone https://github.com/mkpoli/wallos-mcp && cd wallos-mcp
bun install
bunx wrangler kv namespace create wallos-mcp-oauth
bunx wrangler secret put COOKIE_ENCRYPTION_KEY # openssl rand -hex 32
bunx wrangler secret put ALLOWED_HOSTS # e.g. wallos.example.com
bun run deployPut the KV namespace id wrangler prints into wrangler.jsonc. Without a custom domain the Worker answers on workers.dev.
3 · Connect a client
Leave any client ID and secret fields empty — MCP clients register themselves.
claude mcp add --transport http wallos https://<your-host>/mcpRun /mcp in Claude Code to sign in: the page asks for the Wallos URL and the API key. In claude.ai it is Settings → Connectors → Add custom connector with the same URL. Any single-segment label after /mcp/ — /mcp/household — is a separate connection with its own grant, which is how one deployment serves two trackers to clients that reject two servers sharing a URL.
Your deployment serves a setup guide at https://<your-host>/.
What it can do
list_subscriptions
get_subscription
create_subscription
update_subscription
delete_subscription
get_monthly_cost
get_ical_feed
get_period_budget ᵛ
update_budget ᵛ
get_master_data
create_category
update_category
delete_category
create_payment_method
update_payment_method
delete_payment_method
create_household_member
update_household_member
delete_household_member
create_currency
update_currency
delete_currency
whoami
get_settings
update_settings
get_notification_settings
get_fixer_settings
update_fixer_settings
Admin ᵃ
get_admin_settings
update_admin_settings
get_oidc_settings
update_oidc_settings
set_password_login_disabled
ᵛ registered when the instance reports Wallos 5.3 or newer · ᵃ registered when ADMIN_TOOLS is 1 and the bound key passes an admin read
Names instead of ids
The Wallos API takes integer ids. An assistant has names, so create_subscription and update_subscription accept both:
"Netflix, ¥1490 monthly, category Entertainment, paid by Visa, from today"category_name, payment_method_name, payer_name and currency_code are matched case-insensitively against the instance's own lists, and created when missing — create_missing: false turns that into an error listing what does exist. An explicit *_id always wins.
billing_period accepts daily, weekly, biweekly, monthly, quarterly, semiannually, yearly, or every N days|weeks|months|years, alongside the raw cycle and frequency the API wants. When next_payment is omitted it is derived by advancing the start date whole periods until it is no longer in the past, because Wallos rejects a past next payment. Month arithmetic counts from the original start day, so a subscription started on the 31st bills on the 30th in November and on the 31st again in December.
How it works
MCP client ──OAuth 2.1──▶ your Worker ──api_key──▶ your WallosThe Worker is an OAuth 2.1 authorization server to its MCP clients, and Wallos issues API keys rather than tokens, so the sign-in step is a form: the Wallos URL and the key. The pair is checked against api/users/get_user.php before any grant exists. What the grant stores — base URL, key, user id, username, instance version — is encrypted at rest in your OAUTH_KV namespace and handed to the session as props. The MCP client never sees the key.
Each session is a Durable Object holding one grant. The bound account travels from the OAuth boundary on a header the Worker sets after stripping any inbound copy, and the object refuses to start on a grant that does not own it.
Three properties of the Wallos API shape the client, all of them documented in docs/wallos-api.md:
Every response is HTTP 200, authentication failures included.
successin the body is the only signal.Writes read
$_POSTonly. A JSON body arrives empty and the endpoint answers "Missing API key", so every request is form-encoded.Some flags are compared with
=== 'true'.convert_currency=1is silently ignored and returns unconverted prices while reporting success; the list filter Wallos reads ispayment, notpayment_method.
Built with
agents · @cloudflare/workers-oauth-provider · @modelcontextprotocol/sdk · hono · zod
Who can sign in
ALLOWED_HOSTS decides which Wallos hosts a connection may name: a comma-separated list, *.example.com, or * for any host. Empty admits nobody. MAX_ACCOUNTS caps how many distinct installations-plus-users may ever complete sign-in.
Whatever a sign-in names, the Worker fetches, so the URL must be https and must not point anywhere private. RFC1918, CGNAT, link-local (cloud metadata at 169.254.169.254 included), IPv6 unique-local and .local / .internal names are refused at sign-in with an explanation, and the global_fetch_strictly_public compatibility flag enforces the same thing at the platform, where a public name resolving to a private address is caught too. An instance on a home network belongs behind a tunnel with a public hostname.
Redirects are refused rather than followed. A 307 or 308 preserves the method and the body, so an instance that answers one would have the request — API key included — replayed at whatever host the Location names, which the allowlist never saw.
Limits
One Wallos account per connection. Two accounts means two connections.
Logos are attached by URL; Wallos fetches them itself. File upload is out of scope.
Notification settings are readable and not writable, because Wallos ships no setter for them.
get_period_budgetandupdate_budgetneed Wallos 5.3 or newer; on an older instance they are absent rather than failing.
Security
The API key lives only in the encrypted grant. It is stripped from error messages, and secret-looking fields — keys, passwords, tokens, webhook credentials — are masked in tool results.
Requests to Wallos are form-encoded POSTs, which keeps the key out of URLs, access logs and proxy history.
Response bodies and tool results are bounded, and each account has its own rate-limit counter.
The administration tools rewrite how everyone signs in to the instance. They stay unregistered unless the operator opts in and the bound key is actually an admin key.
How it was tested
bun test runs 96 tests with fetch stubbed: form encoding, the always-200 error convention, billing-period parsing, next-payment derivation across month ends and leap years, name resolution and creation, the host allowlist, the private-address refusal, the minimum-version floor, the account cap, and grant isolation between sessions.
scripts/e2e.ts runs the client against a real instance, which is where the wire contract is actually settled:
WALLOS_URL=https://wallos.example.com WALLOS_API_KEY=... bun run scripts/e2e.ts
WALLOS_URL=... WALLOS_API_KEY=... bun run scripts/e2e.ts --writeThe read pass checks versions, users, master data, filters, costs and settings, and that a wrong key is refused. The --write pass creates a category and a subscription, edits the subscription and reads the change back, then deletes both and confirms they are gone. It has been run against Wallos v5.2.0 and v5.4.2.
Development
bun install
bun run check # biome + tsc
bun test
bun run dev # wrangler devLicense
MIT
This server cannot be installed
Maintenance
Related MCP Servers
- Flicense-qualityCmaintenanceA Cloudflare Workers-based implementation of Model Context Protocol (MCP) server that enables AI assistants like Claude to access external tools and capabilities through a standardized interface with OAuth authentication.14
- -license-quality-maintenanceA Model Context Protocol server implementation that runs on Cloudflare Workers with OAuth authentication support, allowing users to connect MCP clients like Claude Desktop or the MCP Inspector to utilize remote AI tools.
- -license-quality-maintenanceA Cloudflare Workers-based MCP server that enables connecting AI assistants like Claude Desktop to custom tools without authentication requirements.
- Flicense-qualityCmaintenanceEnables running a remote MCP server on Cloudflare Workers with OAuth login, allowing AI clients like Claude to interact with tools via SSE.15
Related MCP Connectors
Hosted remote MCP server for YNAB on Cloudflare Workers with OAuth
MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
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/mkpoli/wallos-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server