Plannr MCP Server
Click on "Deploy 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., "@Plannr MCP Server Whose annual review is due in the next 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.
Plannr MCP server
An MCP server that lets Claude, ChatGPT and other MCP clients work with a financial adviser's Plannr CRM: clients, households, reviews due, tasks, cases, plans and notes, and (when enabled) creating tasks and notes. It is built from Plannr's public documentation: the OpenAPI 3.0.3 spec "Plannr API Documentation" at apidocs.plannrcrm.com/source.json and the API guide at api-how-to.plannrcrm.com (authentication, required headers, pagination, rate limits).
Once it's connected, an adviser or administrator can ask things like:
"Whose annual review is due in the next month, and who is their adviser?"
"What's open for the Evans family: tasks, cases and plans?"
"Which of Sam Evans's pensions are under advice, and with which providers?"
"What did we last discuss with Sam? Show me the call notes since September."
With writes enabled: "Create a high-priority task to call Sam about drawdown on Friday, and log a meeting note on his record."
Tools
Tool | What it does | API calls |
| The logins of the user behind the token: the account each acts as (UUID, name, type, role) and the firm. Shows which account the server acts for: |
|
| Accounts (clients by default) by name, role, prospect flag, status, tags, assigned adviser or household, with sort. |
|
| Clients whose next review date falls in a window (today to +30 days by default), soonest first. |
|
| One account: adviser, administrator, paraplanner, owners, groups, tags, households, service level, review and agreement dates, custom field names. |
|
| Circles (households) with members by name, portal access and engagement rating. |
|
| One circle with members, groups and last portal login. |
|
| Tasks by client, assignee, related plan or case, priority, due-date range, open only, name, status, with sort; each with its author and who completed it. |
|
| One task with its description, workflow and custom field names. |
|
| The firm's task statuses in board order (needed by |
|
| Cases by client, household, employee, progress, review or completion dates, status or type, with participants by name. Sorting by value is not offered. |
|
| One case with its linked plans and custom field names. |
|
| Plans by client, household, type, abstract type, status, provider, name or under-advice flag: type, provider, status, owners, review date. Sorting by value is not offered. |
|
| One plan with seller, sub-accounts by name and custom field names. |
|
| A client's notes, including notes on their plans, cases, tasks and risks, newest first, by type, date range, text or what they are attached to. |
|
| Creates a task on a client, employee, case or plan. Only registered when writes are enabled. |
|
| Adds a call, note, meeting or email note to an account, household, case, plan or task, not visible to clients unless asked. Only registered when writes are enabled. |
|
Not covered on purpose: everything else in an 875-operation API, including contact details and addresses endpoints, documents and files, fact finds, valuations, holdings, transactions, charges and fees, bank feeds, messages, webhooks, and every update and delete. Searching clients by email, phone number, National Insurance number or date of birth (all documented filters) is not offered either.
Related MCP server: Carebit MCP server
Setup
Requires Node 18 or later.
npm install
npm run buildYou need a personal access token: in Plannr, go to Settings > Account Details and scroll to Personal Access Tokens. The guide recommends these for personal use and for agencies working on behalf of a Plannr customer. Plannr's OAuth2 authorization code flow (for apps used by many firms; client credentials are issued by emailing integrations@plannrcrm.com) is out of scope for this local version; see Going to production.
Most endpoints need the account to act for in an X-PLANNR-ACCOUNT-UUID header. Set PLANNR_ACCOUNT_UUID to the account.uuid of your employee login (the list_logins tool shows them). If it is not set, the server calls GET /api/v1/logins once and uses the response's preferred_account_uuid if there is one, otherwise your only employee login; if you have several employee logins it refuses and lists them so you can choose.
Claude Desktop: add this to claude_desktop_config.json:
{
"mcpServers": {
"plannr": {
"command": "node",
"args": ["/absolute/path/to/plannr-mcp/dist/index.js"],
"env": { "PLANNR_ACCESS_TOKEN": "your-personal-access-token", "PLANNR_ACCOUNT_UUID": "your-employee-account-uuid" }
}
}
}Claude Code:
claude mcp add plannr -e PLANNR_ACCESS_TOKEN=your-personal-access-token -e PLANNR_ACCOUNT_UUID=your-employee-account-uuid -- node /absolute/path/to/plannr-mcp/dist/index.jsVariable | Required | Meaning |
| yes | Your personal access token, sent as |
| no | The account to act for, sent as |
| no |
|
| no | Defaults to |
| no | Time budget per tool call in seconds (default 45; see Safety defaults). Lowered by the tests. |
Every request carries Accept: application/json and Content-Type: application/json, which the guide lists as required, and every request except GET /api/v1/logins carries X-PLANNR-ACCOUNT-UUID.
Safety defaults
Read-only unless
PLANNR_ALLOW_WRITES=true. Read tools carry the MCPreadOnlyHintannotation; the two write tools are marked not read-only, not destructive and not idempotent. There is no update or delete tool.Clients and everyone else are identified by UUID and name by default. Only with
include_contact_details=truedoes a tool return email addresses (of accounts, logins, members, assignees, authors and participants), the primary email and phone number, custom field values (only their names are shown by default, because a firm can record income, health or anything else in them), third-party references (platform and provider references) and policy, proposal, linked-policy and sub-account policy numbers.Never read from the records: money fields (plan values, valuations, case values, benefit amounts; see Status), bank details, National Insurance numbers, dates of birth and addresses. Every output is built field by field from a list of known fields, so a field of that kind is not copied even if a response carries it (the test suite serves records with
date_of_birth,ni_number,bank_accounts, an address, an income and money objects and checks none of them comes back, with or withoutinclude_contact_details). The endpoints that hold contact details, addresses, documents and bank data are never called (the suite asserts the exact set of endpoints used). Sorting by value, which the API documents for cases and plans, is not offered, because the order would reveal the relative values the server otherwise withholds. No file is ever downloaded.Free text (client, household, task, case, plan and sub-account names; tag, group, status, type, provider, service level, workflow and custom field names; firm names; task descriptions; note contents; the error messages Plannr returns) is redacted by pattern. Always, with or without
include_contact_details: a sort code with an account number, a sort code or account number introduced as such ("sort code", "acct", "account no."), a GB IBAN ([bank details redacted]), a 13 to 19 digit number that passes the Luhn check ([card number redacted]), a National Insurance number in theQQ 12 34 56 Cshape ([NI number redacted]) and a date written after "DOB", "born", "date of birth" or "birthday" ([date of birth redacted]). By default, and not withinclude_contact_details: email addresses ([email redacted]), phone-number-like sequences ([phone redacted]) and UK postcodes ([postcode redacted]). Custom field values, returned only on request, go through the always-on part.These are heuristics. The phone match covers international numbers written with
+or00(including+44 (0)7700 …), UK numbers with a bracketed area code, and UK-style0…numbers of 9 to 11 digits with spaces, dots or hyphens between groups; other digit strings starting with0are redacted too, and so is any other 13 to 19 digit string that happens to pass the Luhn check (about one in ten), while UUIDs and timestamps are left alone. A bare date of birth, a bare six- or eight-digit number, a street address, an amount such as "salary £85,000" and a health detail are not caught and are returned as written, as is the rest of a note, since calling the notes tool is itself the request for notes. HTML tags in notes (such as the<span>of an @mention) are stripped.IDs are checked before any call: every ID must be a UUID. Dates must be real calendar dates in
YYYY-MM-DDform, a review window must not end before it starts, and a tag, status, provider or plan name may not contain a comma (the API takes these as comma-separated lists).Rate limits: Plannr documents 500 requests per minute per user, an
X-Ratelimit-Remainingheader on every response and a 429 when the limit is exceeded, with the advice to back off; it does not mentionRetry-After. Requests are spaced 150 ms apart (at most 400 a minute). A 429 is retried at most twice, waiting forRetry-Afterwhen present (in seconds or as an HTTP-date) and 2 s then 4 s when absent. Each wait is capped at 10 seconds; if Plannr asks for a longer wait the call gives up at once and says how long. Because one tool call can make several requests (the account lookup, then up to 10 pages of a list), every tool call also has a 45 s time budget (PLANNR_TOOL_BUDGET_S), under the MCP SDK's default 60 s request timeout: a retry wait that would end past it is not started and no further page is requested, the call fails at once saying so, and nothing is sent to Plannr after the client has given up. The server does not readX-Ratelimit-Remaining.502, 503 and 504 are retried the same way for
GETonly; when all three attempts fail the error says the service may be unavailable, without the gateway's page.POST /api/v1/taskandPOST /api/v1/noteare never retried after a gateway error, because the task or note may already exist; the error says to checklist_tasksorlist_client_notesfirst.A 200 whose body is not JSON (a proxy or login page in the way) is reported as an error naming
PLANNR_BASE_URL, described by content type and size without quoting it. From error responses only Plannr's documentedmessageanderrorsfields are passed on, redacted as above, and the access token is scrubbed from every message.Pagination follows the
links.nextURL Plannr returns. The server never builds a page number itself, re-adds any of its own filters the link leaves out, and refuses to follow a link to another host or another endpoint.A rejected token (401) produces a message that says which variable to fix and where tokens are created; a 403 names the account in use and points to
PLANNR_ACCOUNT_UUIDandlist_logins; a 422 is passed on with Plannr's field errors.
Tests
npm testThe test suite:
Validates every fixture record against the component schemas in Plannr's published OpenAPI spec (
LoginResource,AccountResource,CircleResource,TaskStatusResource,TaskResource,IndexTaskResource,CasesResource,Plans_PlanResource,NoteResource) with Ajv andajv-formats. Because the schemas set noadditionalProperties: falseand mark almost nothing as required, every fixture is also walked key by key (following$ref,allOfanditems) and a key the schema does not declare fails the check. Negative controls check that a schema still rejects wrong types and that the walk reports undeclared keys at any depth. The spec is downloaded fromapidocs.plannrcrm.com/source.jsontospec.jsonon the first run.Starts a local mock of the API that serves those fixtures with the documented filters (every filter the server sends is applied, except
filter[is_prospect]andfilter[status]on/api/v1/account, sinceAccountResourcedeclares neither a prospect flag nor a status; their pass-through is still asserted), the include-only relationships of the task index (authorandcompleted_byonly when included),per_pageand the Links/Meta envelope the guide describes (on/api/v1/taskthe next link carries only the page number, elsewhere it keeps the query), Bearer auth with the spec's 401 body, a 403 for a missing or unknownX-PLANNR-ACCOUNT-UUID, 404s, 422s in thePlannr_ValidationErrorshape, anX-Ratelimit-Remainingheader, a one-off 429 withRetry-AfteronGET /api/v1/task-status, and injected failures or replacement records on any endpoint (including a 429 on every other request, so that each page of a list is refused once). The mock's list, detail, created-task and error responses are validated against the response schemas the spec gives for each operation.Starts the built server and drives it over stdio with the official MCP client: 31 checks covering tools/list and annotations, every read tool, pagination across two pages to the point where
links.nextis null (and amax_resultscut reported as incomplete), a next link without the filters (they are re-added) and requests on one call spaced at least 140 ms apart, every documented filter each tool offers passed through exactly, the reviews-due operator filter, redaction of emails, phone numbers, custom field values, references and policy numbers by default and their return on request, contact details typed into client, household, tag, group, service level and custom field names and descriptions redacted, a fact-find note whose NI number, date of birth, bank details and card number are redacted in both modes and its postcode by default only, planted records served in place of every read (and of the created task and note, and of a 422) with those details and contact details in every free-text field and undeclareddate_of_birth,ni_number,bank_accounts, address, income and money fields, none of which comes back, HTML stripped from notes, no money fields in plan and case output, a detail answer and a created task or note wrapped in{"data": …}unwrapped, thePOST /api/v1/taskandPOST /api/v1/notebodies validated against the spec's request schemas (StoreTaskRequest,StoreNoteRequest), a 422 passed on with field errors, an empty 204 on a note handled, writes absent withPLANNR_ALLOW_WRITESunset and set tofalse, bad UUIDs, dates, reversed review windows and comma-containing names rejected before any request, the 404 message, the 429 retry waiting forRetry-Afterin the seconds and HTTP-date forms and 2 s then 4 s without it, giving up after three attempts and at once above the cap, a 429 onPOST /api/v1/noteretried once, a 429 on the firstGET /api/v1/loginswith two calls at once resolving the account once, the per-call time budget (lowered to 3 s) stopping a list whose pages each get a 429 with a clean error and no later request, a 502 retried forGET, aGETfailing three times with 503 reported without the HTML, a 502 onPOST /api/v1/taskand a 503 onPOST /api/v1/notenot retried, a non-JSON 200 reported as an error, next links to another host or another endpoint refused, an error message passed on with its email, phone number and the token redacted, the account resolved from/api/v1/logins(the only employee login,preferred_account_uuid, and a refusal listing the choices when ambiguous),list_loginsshowing the account it acts for withPLANNR_ACCOUNT_UUIDunset (or that none was chosen), the 401 message for a wrong token (pasted with aBearerprefix, not doubled), the 403 message for a wrong account, and that every request used the Bearer token, the required headers, a documented method and path and only query parameters that operation documents (apart from the page number taken from Plannr's next link), with the exact set of 15 endpoints used.
Status
This is a working prototype. It has not yet been run against the live API, because it was built without a Plannr account (no public trial or sandbox was found; personal access tokens come from customers' own accounts). Everything below is taken from the published documentation and should be confirmed on a real account:
Pagination. The spec documents only
per_page(default 15, max 500) and declares onlydatain its list responses; the guide describes a Links block with four page links and a Meta block (per page, total, current and last page) in a screenshot. The key names used here (links.first/last/prev/next,meta.current_page/last_page/per_page/total) are the Laravel convention that description matches. Whetherlinks.nextkeeps the filters is not documented; both cases are handled. Whetherper_page=100is accepted everywhere this server uses it.Get-by-UUID and create responses. The spec types them as the resource itself; if the live API wraps them in
{"data": …}they are unwrapped.POST /api/v1/note: the spec documents no success response (only 401 and 422). The mock answers 201 with aNoteResource; the tool also accepts an empty answer.The account header: what status a missing or wrong
X-PLANNR-ACCOUNT-UUIDgets (the mock answers 403), whetherGET /api/v1/account/{uuid}and the notes endpoints need it (the spec does not declare it there; the guide says every endpoint but the logins list does, so it is always sent), and wherepreferred_account_uuidsits in theGET /api/v1/loginsresponse (the guide names it but it is not in the spec; the server looks at the top level and on each login).Filter encoding and semantics: booleans are sent as
true/false; the operator filterfilter[next_review_date]=>=2026-10-01,<=2026-10-31is sent URL-encoded; whetherfilter[client_uuid]on tasks includes tasks on the client's cases and plans (the mock matches tasks on the client only); whetherfilter[status]on accounts matches what the UI calls a client status (theAccountResourceschema has no status field); which relationships the index routes return without aninclude(the mock returns only those included).Relationship shapes: the spec types a case's
participantsandplansas single objects and every*_Summaryrelationship without property types; the fixtures follow the spec, and the server reads either an object or an array.Money: the spec's money objects (
value,total_benefit_amount, valuations) describeexampleanddescriptionas properties ofamount,formattedandcurrency, so no real money value can pass the schema. This version therefore returns no money fields at all (amounts typed into free text are returned as written, see Safety defaults); valuations are the first thing to add once the live shape is known.Dates: task due dates follow the spec's example format
2021-01-01 00:00:00; review dates are ISO 8601 with an offset. The server passes both through as given.The wording of Plannr's 404 and 422 messages for these endpoints (the mock uses the forms the spec documents for other endpoints) and of a 429 body (not documented; the mock uses Laravel's "Too Many Attempts.").
Visibility: the spec says task lists are constrained by the user's role; the server returns whatever the token's login may see.
How the API reacts to requests at the spaced rate here; the documented limit is 500 a minute per user.
Going to production
This version runs locally over stdio with the user's own personal access token. For advisers to connect from claude.ai or ChatGPT without handling tokens, the next step is a remote server (Streamable HTTP) that uses the OAuth2 authorization code flow Plannr already offers, hosted by Plannr, so each user's own login and permissions apply, and then a listing in the Claude and ChatGPT connector directories. Valuations and other amounts can follow once the money shape is confirmed on a live account, and more write tools (completing tasks, updating review dates) once they can be tested on a test firm.
Licence
MIT. Built by Alexandru Dragoș (alexandru.dragos96@gmail.com) with an AI agent (Claude) working under his direction.
Available Tools
14 toolsget_caseGet caseARead-onlyIdempotent
One case by UUID: type, status, review and completion dates, participants by name, linked plans by name and type, custom field names. Uses GET /api/v1/cases/{uuid}.
Inputs: case_uuid (required), include_contact_details.
get_clientGet clientARead-onlyIdempotent
One account (usually a client) by UUID: name, type and role, adviser, administrator and paraplanner, owners, groups, tags, households, service level, review, agreement and first-contact dates, and custom field names. Email, phone, custom field values and third-party references only with include_contact_details. Uses GET /api/v1/account/{uuid}.
Inputs: client_uuid (required), include_contact_details.
get_householdGet householdARead-onlyIdempotent
One circle (household) by UUID with its members by name, groups, portal access, engagement rating and last portal login. Uses GET /api/v1/circles/{uuid}.
Inputs: household_uuid (required), include_contact_details.
get_planGet planARead-onlyIdempotent
One plan by UUID: type, provider, status, owners, seller, sub-accounts by name, review and valuation dates, custom field names. Policy numbers, linked policy numbers, third-party references and custom field values only with include_contact_details; money amounts never. Uses GET /api/v1/plans/{uuid}.
Inputs: plan_uuid (required), include_contact_details.
get_taskGet taskARead-onlyIdempotent
One task by UUID, with its description, status, what it relates to, assignees, workflow and custom field names. Uses GET /api/v1/task/{uuid}.
Inputs: task_uuid (required), include_contact_details.
list_casesList casesARead-onlyIdempotent
Cases (pieces of advice work such as a pension transfer or a mortgage) with type, status, review date, completion and participants by name, filtered as GET /api/v1/cases documents: by client, household, employee, progress, review or completion date range, status or type. Case values are not returned.
Inputs: sort, statuses, completed, type_uuids, +10 more.
list_client_notesClient notesARead-onlyIdempotent
Notes for one client, including notes on their plans, cases, tasks and risks, newest first by default: type (call, note, meeting, email), what the note is about, author, contents. Filter by type, date range, text, or what the note is attached to. Emails, phone numbers and postcodes in the contents are redacted unless include_contact_details; bank details, card and National Insurance numbers and dates of birth always. Uses GET /api/v1/client/{client_uuid}/all-notes.
Inputs: client_uuid (required), to, from, sort, +5 more.
list_householdsList householdsARead-onlyIdempotent
Circles (households and other groups of client accounts) with their members by name, portal access and engagement rating. Filter by name or member account. Uses GET /api/v1/circles with include=accounts.
Inputs: name, sort, max_results, member_uuids, +1 more.
list_loginsList loginsARead-onlyIdempotent
The logins of the user behind the access token: for each, the account it acts as (UUID, name, type such as employee or client, role) and the firm, plus the account this server acts for (PLANNR_ACCOUNT_UUID, or the one chosen from these logins). Use it to find the account UUID for PLANNR_ACCOUNT_UUID. Uses GET /api/v1/logins.
Inputs: include_contact_details.
list_plansList plansARead-onlyIdempotent
Plans (pensions, investments, protection, mortgages and other products) with type, provider, status, owners by name, review date and whether they are under advice, filtered as GET /api/v1/plans documents. Policy numbers only with include_contact_details; valuations and other money amounts are not returned.
Inputs: name, sort, types, provider, +7 more.
list_reviews_dueReviews dueARead-onlyIdempotent
Clients whose next review date falls between two dates (today to 30 days ahead by default), soonest first, with their adviser and previous review date. Uses GET /api/v1/account with filter[type]=client, the documented operator form filter[next_review_date]=>=FROM,<=TO and sort=next_review_date.
Inputs: to, from, max_results, assigned_adviser_uuids, +1 more.
list_tasksList tasksARead-onlyIdempotent
Tasks on the firm, filtered as GET /api/v1/task documents: by client, assignee, related plan or case, priority, due date range, open only, name or status. Each task has its status, priority, due date, what it relates to, who it is assigned to, its author and who completed it (include=author,completed_by). What a user sees depends on their Plannr role.
Inputs: name, sort, due_after, open_only, +9 more.
list_task_statusesList task statusesARead-onlyIdempotent
The task statuses defined in the firm's settings, in board order, with which ones count as completed, archived or not started. create_task needs one of these UUIDs. Uses GET /api/v1/task-status with sort=position.
Inputs: no named parameters.
search_clientsSearch clientsARead-onlyIdempotent
Search the firm's accounts (clients by default) by name, role, prospect flag, status, tags, assigned adviser or household, with the documented filters of GET /api/v1/account. Each result has the UUID, name, type and role, assigned adviser, review dates, tags and households. Email and phone only with include_contact_details.
Inputs: name, sort, tags, type, +7 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 14 tools
Most tools are clearly distinct list/get pairs for clients, households, tasks, cases, and plans. There is mild overlap between search_clients and list_reviews_due (both surface clients from the same account endpoint), but descriptions describe distinct purposes (general search vs review-date filtering) adequately.
Strong underlying list_*/get_* verb_noun pattern across clients, households, tasks, cases, and plans. Minor deviations: search_clients uses a different verb than the otherwise dominant list_* convention, and list_reviews_due/list_client_notes are more descriptive than schematic, but overall it is readable and predictable.
14 tools is well within the sweet spot and each maps to a distinct resource or lookup. No redundant or trivial tools pad the set.
Read coverage is thorough (list+get for nearly every entity plus lookups like task statuses and logins), but there are no write/lifecycle operations such as update_task, create_case, or delete_plan. The mention that 'create_task needs one of these UUIDs' implies mutation tools exist elsewhere but are absent here, leaving a notable gap for a CRM-style server.
Related MCP Connectors
Create contacts, move deals, send proposals and invoices, read your inbox, from Claude or ChatGPT.
Read-only access to your own bank, card and brokerage accounts for Claude, ChatGPT and other AI agents: balances, transactions, spending, subscriptions, cashflow and investment holdings. It can never move money.
Personal finance, bank account, and shared memory connector for Claude, ChatGPT, Gemini Spark & more
Connect your First AI Employee workspace to review authorized business records, including contacts, tasks, calls, bookings, forms and reports. Prepare supported changes as an exact preview for approval before applying them. OAuth sign-in is required; available tools depend on account permissions, enabled products and access. Website: https://firstaiemployee.com/ . Setup: https://developer.firstaiemployee.com/mcp/
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables querying and managing a CRM database through natural language conversations with Claude Desktop.-
- AlicenseBqualityCmaintenanceEnables Claude, ChatGPT and other MCP clients to read practice-management data including organization, clinicians, diaries, availability, bookings, patients, invoices, payments, staff tasks, services, and locations, and optionally create staff tasks, create bookings, and cancel bookings.15MIT
- AlicenseNot gradedqualityCmaintenanceEnables Claude, ChatGPT and other MCP clients to read NewZapp account details, campaign reports, open heatmaps, contact groups and contact counts, and to search contacts with personal data withheld by default; when writes are enabled, it can also create and update contacts.MIT
- AlicenseNot gradedqualityCmaintenanceEnables Claude, ChatGPT and other MCP clients to search a membership database's people and organisations, read a contact's summary and membership history, list events with ticket types and attendance lists, read invoices, and find and count segments. When writes are enabled, it also lets clients record who attended an event.MIT