# doola Formation MCP

Use this server to form a US LLC end to end: company setup, payment, post-payment data collection, and filing with the state.

## Connection

- MCP endpoint: https://mcp.doola.com
- Protected-resource metadata: https://mcp.doola.com/.well-known/oauth-protected-resource
- Transport: Streamable HTTP, one JSON-RPC 2.0 endpoint (`POST /`)
- Protocol revisions supported: 2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26. The revision is negotiated at `initialize`.
- Authorization: OAuth 2.1 with PKCE (S256). Read the protected-resource metadata to locate the authorization server, then register with Dynamic Client Registration (RFC 7591).

A doola account is required. The OAuth handshake covers both signing in and signing up.

## Scope

- LLCs and C-Corps in any of the 50 states or DC. A Wyoming LLC is the default when the user has no preference; the user chooses the entity type. The package is always Starter, enforced server-side.
- Quote the live `pricing` values a response returns. Never quote a price from this document or from memory.
- One customer can hold several companies. Every tool acts on the active company.
- Out of scope: S-Corp elections, packages other than Starter, and tax filings.

## How the flow is driven

The server tracks the flow one step at a time, so there is no need to plan the sequence yourself.

1. Call `get_company_onboarding_status` once, at the start of the session. It needs no arguments.
2. Formation responses carry `nextStep` and `nextQuestion`. `nextStep` is `{tool, missingFields, description}`: the step the flow waits on, the arguments of that tool it still needs, and where the customer stands. `nextQuestion` is that step's question for the customer. Both are `null` once formation is complete.
3. The steps run `start_formation`, `create_checkout_session`, `verify_payment`, then `save_company_details` for each post-payment answer (`search_industries` first for the industry), `request_ssn_entry_link` when the responsible party lives in the US, and `submit_formation` last. `save_company_details` saves whatever fields it is given.
4. `create_checkout_session` and every post-payment write are gated server-side. Calling one too early returns `error: true` with `code: PRECONDITIONS_NOT_MET`, `missing` (the unmet steps in flow order) and the `nextStep` that comes first. The same call is refused again until that step is done.

## Tools

### `start_formation` — Start Company Formation

Starts the user's LLC or C-Corp formation: saves their legal name (only when the profile lacks it), their country of residence, the company name, and the formation state and entity type. Every field is optional and is saved as given, so call it as soon as you have an answer. state and entityType default to a Wyoming LLC, so call it with {} when the user has no preference. Never invent a company name. Formation flow, in order: start_formation, create_checkout_session, verify_payment, save_company_details (industries from search_industries), submit_formation. Each response's nextStep is the step the flow now waits on.

### `create_checkout_session` — Create Checkout Link

Accepts doola's Terms of Service (https://www.doola.com/terms-of-service) for the Starter package on the user's behalf and creates the Stripe checkout for the formation. Show the user the Terms of Service and send termsAccepted: true only once they agree. Returns `pricing` (the first-year list price: quote `pricing.summary` VERBATIM and never call it 'charged today'), `chargeSummary` (what Stripe charges today after any discount: quote it VERBATIM), `checkoutUrl` (paste it verbatim into your reply, never a placeholder), `checkoutSessionId` (what verify_payment checks), and `companyId` / `companyName` (the company being paid for: name it to the user). Refused with PRECONDITIONS_NOT_MET until start_formation has saved the name, country and company name. Formation flow, in order: start_formation, create_checkout_session, verify_payment, save_company_details (industries from search_industries), submit_formation. Each response's nextStep is the step the flow now waits on.

### `verify_payment` — Verify Payment

Checks with Stripe whether the formation checkout was paid. Call it once the user says they've paid, with the checkoutSessionId create_checkout_session returned. Do NOT ask any post-payment question until it returns paymentStatus=Complete. A confirmed payment makes the company it paid for the active one, so the post-payment tools write to it. Formation flow, in order: start_formation, create_checkout_session, verify_payment, save_company_details (industries from search_industries), submit_formation. Each response's nextStep is the step the flow now waits on.

### `search_industries` — Search Industries

Lists the industries a company can be filed under. Match the user's description of their business against the list and offer the 3-5 closest entries. The one they pick, verbatim, is the `industry` save_company_details accepts; no other value is. Read-only; takes no arguments. Formation flow, in order: start_formation, create_checkout_session, verify_payment, save_company_details (industries from search_industries), submit_formation. Each response's nextStep is the step the flow now waits on.

### `save_company_details` — Save Company Details

Saves the company's post-payment details: industry and description, backup names, registered and mailing addresses, the IRS responsible party, and either an LLC's members with their ownership or a C-Corp's officers, directors and share structure. Every field is optional and is saved as given, so save each answer as soon as the user gives it; the response lists what is still `missing`. Refused with PRECONDITIONS_NOT_MET until verify_payment has confirmed payment. Formation flow, in order: start_formation, create_checkout_session, verify_payment, save_company_details (industries from search_industries), submit_formation. Each response's nextStep is the step the flow now waits on.

### `request_ssn_entry_link` — Get Secure SSN Link

For a responsible party who lives in the US, gets a one-time link to doola's secure page where the customer, signed in to the same doola account they use here, types the responsible party's Social Security Number for the EIN application. The SSN never passes through you, this chat or any tool: never ask for it here and never accept it if offered. Clients that support URL elicitation are asked to open the page directly; otherwise paste `ssnEntryUrl` verbatim. The link works once and expires after 15 minutes; call this again for a fresh one. Returns `responsiblePartySsnOnFile` (never the SSN itself). Refused with PRECONDITIONS_NOT_MET until the responsible party is saved. Takes no arguments.

### `submit_formation` — Submit Formation

Files the company with its formation state through doola's registered agent and emails the responsible party what they must sign: the SS-4, plus Form 8821 for Expedited EIN, or nothing when the responsible party's SSN lets doola apply for the EIN online. Filing cannot be undone. Call it ONLY after presenting a complete summary table of everything collected and the user explicitly replied 'submit', with {userConfirmed: true}. Refused with PRECONDITIONS_NOT_MET, listing `missing`, while any earlier step is incomplete. Formation flow, in order: start_formation, create_checkout_session, verify_payment, save_company_details (industries from search_industries), submit_formation. Each response's nextStep is the step the flow now waits on.

### `get_company_onboarding_status` — Check Formation Progress

Canonical 'where am I?' entry point — call this ONCE per user session, at the start, right after the OAuth handshake. No arguments required; customerId is read from the bearer. Returns the customer's progress: `completedSteps`, `blockers` (unmet prerequisites in flow order), `suggestedNextStep` (the tool for the step the flow waits on), and `nextStep` ({tool, missingFields, description}) with `nextQuestion`, all null once formation is complete.

DO NOT call this before every formation call. Each formation tool's response already carries nextStep, so calling this between steps only adds latency and burns rate limit.

Only call this AGAIN when one of these is true: (a) the user returns mid-flow after a long pause and asks 'where are we?', (b) you need to verify state after an unexpected error or a failed call, or (c) the active company changed through switch_active_company. Outside those cases, treat the first call's state as authoritative for the rest of the session.

Derivation mirrors /web's onboarding routing (Company.gql): each step is marked completed when its corresponding Company / Customer field is populated. If the customer has no active company yet (post-OAuth, pre-formation), nextStep is start_formation.

If the response contains `error: true` or `nextStep` looks inconsistent with the user's actual progress (e.g. the company name was just saved but nextStep is the company name again), the upstream data fetch likely transiently failed. Wait ~10 seconds and call this tool again before deciding what to do next — do NOT redo earlier steps the user has already completed.
Formation flow, in order: start_formation, create_checkout_session, verify_payment, save_company_details (industries from search_industries), submit_formation. Each response's nextStep is the step the flow now waits on.

### `list_companies` — List Companies

Returns every company the authenticated customer owns — call when the user asks 'which companies do I have?', wants to switch context, or before starting a brand-new formation so you know whether a previous attempt is already in progress. The entry with `isActive: true` is the one every other formation tool currently operates on; `switch_active_company` changes which one that is, and `start_new_company` adds a new in-progress company.

### `start_new_company` — Start a New Company

Begin a brand-new company formation alongside any existing companies the customer already has — call when the customer explicitly asks to form a SECOND (or further) company. Creates an empty in-progress Company row, links it to the customer, and pins it as the active company so the next tool calls operate on it. The response's nextStep is the new company's first formation step. The previously active company is untouched and remains in `list_companies`, and `switch_active_company` makes it active again.

### `switch_active_company` — Switch Active Company

Point the formation tools at a different company the customer already owns. Use when the customer asks to manage / continue / inspect a specific company by name or ID. The companyId must come from `list_companies` — unknown IDs are rejected. After switching, the response carries the same shape as `get_company_onboarding_status` for the new active company, so the agent knows immediately which step to resume from. The override is process-local; if the customer reconnects and ends up on a different MCP replica, just call this tool again.

### `get_company_info` — Get Company Details

Returns the active company's full profile — basic info (name, state, entity type, EIN, industry, dashboard status, formation filing date), member list, responsible party, addresses, name options, and provisioned services. Mirrors what the customer sees on /web's Company Information page (https://app.doola.com/company). Use when the customer asks 'tell me about my company', 'what's my EIN?', 'who are the members?', or similar — distinct from `get_company_onboarding_status` which returns derived next-step routing rather than raw company data. It reads the active company, which `switch_active_company` changes.

### `report_missing_capability` — Report Missing Capability

Call this when the user wants something none of the other tools can do. Describe the goal and the kind of tool that would help in `context`. Doing so records the request for doola's team and changes nothing on the customer's account. It returns no new tools, so after calling it tell the user this isn't available here and point them to the doola dashboard.

### `search_doola_help_center` — Search doola Help Center

Searches doola's help center for how doola's services, prices, timelines and dashboard work, e.g. 'how long does an EIN take' or 'what does the registered agent service include'. Returns the most relevant passages with their article title. Use it for general questions about doola; for the user's own company, EIN, documents, invoices or deadlines, call the matching account tool instead. The passages are background, so prefer an account tool's answer when the two disagree.

### `get_ein_application_status` — Get EIN Application Status

Returns the status of the active company's EIN (Employer Identification Number) application with the IRS: einStatus is Not started, In progress or Completed. When expediteEligible is true it also returns how long standard and expedited processing take and an expediteLink to doola's Expedite EIN service; mention that offer only then, and only with that exact link. Answer in plain language and never show the user the field names.

### `list_company_documents` — List Company Documents

Lists the doola-managed documents on file for the company: formation documents (SS-4, EIN letter, Articles of Organization), tax filings, IRS and state notices, registered agent mail and more, each with its name and type. Some files the user uploaded themselves are not listed: when a document is missing here, tell them to check the Documents page of their doola dashboard, where they can also download any file.

### `list_invoices` — List Invoices

Lists the invoices the company sends its own clients from doola Bookkeeping (not doola's bills to the user), with their payment status. limit caps the rows (1 to 100, default 25); pass the returned cursor to get the next page.

### `get_invoice_detail` — Get Invoice Detail

Returns one invoice the company sends its own clients from doola Bookkeeping: line items, client and payment status. invoiceId is the numeric invoiceId from list_invoices (e.g. 305207437), not the invoice number like INV-108.

### `get_doola_plan` — Get doola Plan

Returns the doola plan the company holds, in a plans list with each plan's name. An empty list means the company holds no doola plan. For prices, renewals and invoices from doola, point the user to the plan and billing page of their doola dashboard.

### `get_compliance_checklist` — Get Compliance Checklist

Returns the company's compliance checklist exactly as the Compliance page of the doola dashboard shows it: the banner, how many tasks sit under each filter, and each task with its due date and status (Overdue, Due soon, Upcoming, Plan ahead or Completed). When checklistStarted is false the user has not set it up yet: never say they are in good standing, tell them to answer the short questionnaire on the Compliance page. When includedInPlan is true doola handles that task as part of their plan. Report statuses as given; the dashboard shows no completion dates. Answer in plain language and never show the user the field names.

### `get_compliance_calendar` — Get Compliance Calendar

Returns the compliance and filing deadlines that generally apply to a company of this state and entity type. These are dates to be aware of, not bills or confirmed obligations: never tell the user they owe a payment or will be penalised because of an entry. When formationCompleted is false the company is not formed yet, so the dates are informational. For the user's own task list, call get_compliance_checklist instead.

### `get_tax_filing_status` — Get Tax Filing Status

Returns the status of the company's federal tax filing with doola as the dashboard shows it: clientPrimaryStatusDisplay is the status and clientDashboardStatusContext explains it. A message instead means the company has no doola tax filing yet. Report the status as given. Questions about what the user owes or how to treat an item go to a tax professional. Answer in plain language and never show the user the field names.

### `get_dissolution_status` — Get Dissolution Status

Returns the status of the user's request to dissolve (close) their company with doola, as the dashboard shows it: In Progress, Awaiting Payment or Completed, and the date it was submitted, plus the same for the Short Year Tax Return when they added it. When dissolutionOnFile is false there is no dissolution request: never suggest one is in progress. For why it is taking longer or what the state still needs, point the user to doola support. Answer in plain language and never show the user the field names.

### `get_service_offers` — Get doola Service Offers

Returns what doola and its partners offer the company for one serviceCategory, with a sign-up link for each offer and the deal that matches the company's doola plan. doola services: ITIN, Bookkeeping, Amendments, DBA, Dissolution, Foreign Qualification, Certificate of Good Standing, Tax/Annual Report. Partner services: Banking, Business Insurance, Legal, Payroll and HR, Lending, Sales Tax, Trademark registration, Website, Payments, Mail, E-Commerce, Cloud Services, Marketing. Pass one of these names. Use it when the user asks what doola can do for them next or needs one of these services. Share an offer only with its own link, exactly as returned, and never invent a price or a deal. For a bank, offer only the one bank in affiliated_partner_offers. alternative_banks lists the next banks in order: offer the first only when the user asks for another bank or says theirs rejected or closed their account. When banking_note is present, follow it and offer no bank. For doola's ITIN service, check get_itin_status first and mention it only when that allows the offer. Answer in plain language and never show the user the field names.

### `get_itin_status` — Get ITIN Status

Returns where the ITIN (Individual Taxpayer Identification Number) application for the company's members stands with doola: itinStatus is Not started, Payment processing, In review, Submitted to the IRS or Completed. When offerAllowed is true it also returns a quizLink to doola's ITIN service; mention that service only then, and only with that exact link. Never tell the user whether they qualify for an ITIN: the quiz decides that. Answer in plain language and never show the user the field names.

### `get_my_profile` — Get My Profile

Returns the signed-in user's doola profile: their name, email, country of residence and phone number. A null field is not on file, which is a complete answer, not a failure. To change any of them, point the user to their doola dashboard. Answer in plain language and never show the user the field names.

### `get_bookkeeping_report` — Get Bookkeeping Report

Generates one of the company's financial statements from doola Bookkeeping. reportType is PROFIT_AND_LOSS (profit and loss, income statement), BALANCE_SHEET, CASH_FLOW_INDIRECT (cash flow statement), EXPENSES_BY_CATEGORY (spending per expense category) or TRIAL_BALANCE (general ledger). exportType PDF or XLSX returns a url to download the file; share that link as it is. exportType JSON returns the figures themselves, for totals or a chart. grouping is DAILY, MONTHLY, QUARTERLY or YEARLY, and beginDate and endDate are YYYY-MM-DD. When bookkeepingSetUp is false there are no books to read yet. If includedInPlan is true, bookkeeping is already in the user's doola plan: never offer it, share setUpLink where they set it up, or with no setUpLink point them to doola support. Otherwise follow nextStep to offer doola Bookkeeping. Answer in plain language and never show the user the field names.

### `get_bookkeeping_transactions` — Get Bookkeeping Transactions

Lists the company's recent transactions in doola Bookkeeping: income, expenses, tax payments, transfers and invoice payments, with amount, date and category. limit caps the rows (1 to 100, default 50). Use it for questions like 'how much did I spend on software'. When bookkeepingSetUp is false there are no books to read yet. If includedInPlan is true, bookkeeping is already in the user's doola plan: never offer it, share setUpLink where they set it up, or with no setUpLink point them to doola support. Otherwise follow nextStep to offer doola Bookkeeping. Answer in plain language and never show the user the field names.

### `get_bookkeeping_uncategorized_transactions` — Get Uncategorized Transactions

Lists the transactions in doola Bookkeeping that have no category yet, which is what needs the user's attention before the month closes. The user categorizes them in the doola dashboard. When bookkeepingSetUp is false there are no books to read yet. If includedInPlan is true, bookkeeping is already in the user's doola plan: never offer it, share setUpLink where they set it up, or with no setUpLink point them to doola support. Otherwise follow nextStep to offer doola Bookkeeping. Answer in plain language and never show the user the field names.

### `get_bookkeeping_bank_accounts` — Get Bookkeeping Bank Accounts

Lists the bank and credit card accounts connected to doola Bookkeeping, whose transactions flow into the books. When bookkeepingSetUp is false there are no books to read yet. If includedInPlan is true, bookkeeping is already in the user's doola plan: never offer it, share setUpLink where they set it up, or with no setUpLink point them to doola support. Otherwise follow nextStep to offer doola Bookkeeping. Answer in plain language and never show the user the field names.

### `get_chart_of_accounts` — Get Chart of Accounts

Returns the company's chart of accounts in doola Bookkeeping: the tree of asset, liability, equity, revenue and expense accounts its transactions are categorized into. When bookkeepingSetUp is false there are no books to read yet. If includedInPlan is true, bookkeeping is already in the user's doola plan: never offer it, share setUpLink where they set it up, or with no setUpLink point them to doola support. Otherwise follow nextStep to offer doola Bookkeeping. Answer in plain language and never show the user the field names.

### `get_bookkeeping_vendors` — Get Bookkeeping Vendors

Lists the vendors the company pays, as doola Bookkeeping keeps them. statuses filters them, comma-separated; omit it for ACTIVE and PENDING. When bookkeepingSetUp is false there are no books to read yet. If includedInPlan is true, bookkeeping is already in the user's doola plan: never offer it, share setUpLink where they set it up, or with no setUpLink point them to doola support. Otherwise follow nextStep to offer doola Bookkeeping. Answer in plain language and never show the user the field names.

### `get_bookkeeping_clients` — Get Bookkeeping Clients

Lists the company's own clients, the people and businesses it invoices from doola Bookkeeping, not doola's customers. When bookkeepingSetUp is false there are no books to read yet. If includedInPlan is true, bookkeeping is already in the user's doola plan: never offer it, share setUpLink where they set it up, or with no setUpLink point them to doola support. Otherwise follow nextStep to offer doola Bookkeeping. Answer in plain language and never show the user the field names.

### `get_sales_platforms` — Get Sales Platforms

Lists the online store platforms connected to the company, such as SHOPIFY or AMAZON. Whether each connection works comes from get_ecommerce_connection_status.

### `get_ads_platforms` — Get Ad Platforms

Lists the advertising platforms connected to the company, such as FACEBOOK, GOOGLE or TIKTOK. For spend and campaigns call get_ads_time_series or get_ads_campaigns.

### `get_ecommerce_connection_status` — Get Store and Ad Connection Status

Returns each store and ad account connected to the company with its status, as the doola dashboard shows it. type is 'sales' for stores or 'ads' for ad accounts; omit it for both. Call it before answering from orders, products, sales or ad data. When dataMayBeOutOfDate is true, still answer from the data but say that platform's numbers may be out of date: with reconnectInApp true the user reconnects it on the page at integrationsPageLink, otherwise they contact doola support. When syncInProgress is true its first sync is still running, so never report zero for it. An Unknown status could not be checked right now: answer from the data, say its numbers may be out of date and suggest asking again shortly. A Pending connection was never finished: report no numbers for it and point to integrationsPageLink. An empty connections list means nothing is connected: say so instead of reporting zero and share integrationsPageLink, where stores and ad accounts are connected once doola bookkeeping is set up. Never mention sync dates or why a platform rejected the connection. Answer in plain language and never show the user the field names.

### `get_orders` — Get Store Orders

Lists the orders from the company's connected online stores in a date range. limit caps the rows (1 to 100, default 50). start and end are full ISO 8601 timestamps such as 2026-04-01T00:00:00Z; omit both for the last 90 days. Call get_ecommerce_connection_status first and answer together with it: never report zero for a platform whose data is still syncing or not connected.

### `get_orders_time_series` — Get Sales Trend

Returns the company's store orders and sales over time in a date range, in daily or weekly buckets, for a sales trend or chart. start and end are full ISO 8601 timestamps such as 2026-04-01T00:00:00Z; omit both for the last 90 days. Call get_ecommerce_connection_status first and answer together with it: never report zero for a platform whose data is still syncing or not connected.

### `get_top_selling_products` — Get Top Selling Products

Returns the company's five best-selling products in a date range. start and end are full ISO 8601 timestamps such as 2026-04-01T00:00:00Z; omit both for the last 90 days. Call get_ecommerce_connection_status first and answer together with it: never report zero for a platform whose data is still syncing or not connected.

### `get_total_sales_by_platform` — Get Total Sales by Platform

Returns the company's total sales in a date range, broken down by store platform. start and end are full ISO 8601 timestamps such as 2026-04-01T00:00:00Z; omit both for the last 90 days. Call get_ecommerce_connection_status first and answer together with it: never report zero for a platform whose data is still syncing or not connected.

### `get_ads_campaigns` — Get Ad Campaigns

Lists the company's ad campaigns in a date range with their spend, impressions, clicks and conversions. limit caps the rows (1 to 100, default 50). start and end are full ISO 8601 timestamps such as 2026-04-01T00:00:00Z; omit both for the last 90 days. Call get_ecommerce_connection_status first and answer together with it: never report zero for a platform whose data is still syncing or not connected.

### `get_ads_time_series` — Get Ad Spend Trend

Returns the company's ad spend, impressions, clicks and conversions over time in a date range, for total ad spend or a spend trend chart. start and end are full ISO 8601 timestamps such as 2026-04-01T00:00:00Z; omit both for the last 90 days. Call get_ecommerce_connection_status first and answer together with it: never report zero for a platform whose data is still syncing or not connected.

## What never travels through a tool

- No tool accepts an SSN, an ITIN, or a signature. doola collects the IRS signatures it needs by emailing the responsible party directly.
- When the responsible party lives in the US, `request_ssn_entry_link` hands the customer a single-use link to a doola-hosted page, through URL elicitation when the client supports it. The customer signs in to doola with the account they use with the agent and types the SSN there; the agent only learns whether one is on file (`responsiblePartySsnOnFile`), never the value or any part of it. Never ask for the SSN in the chat, and never repeat it if the customer types it anyway. A responsible party living elsewhere gets no link and completes the emailed SS-4 as before.
- Card details never reach a tool. `create_checkout_session` returns a Stripe hosted checkout URL; paste it verbatim and let the customer pay there.
- Never invent a company name. Names must come from the customer.
- The responsible party's email (`save_company_details` `responsibleParty.email`) receives any IRS forms that need signing (the SS-4, plus Form 8821 for Expedited EIN). Confirm it with the customer before sending it.

## Full documentation

https://docs.doola.com/mcp/introduction
