The current Python path is LangChain's built-in MCPAdapter. Install LangChain's MCP extra, give a FastMCP client your DeepLedger bearer token, discover the server tools, and pass only the tools needed for the job to create_agent.
This article uses a company-checked Profit and Loss report as the first test. It does not record anything in QuickBooks. That is deliberate: a successful read proves the connection and company, runs a fixed period with an explicit accounting basis, and exposes the report shape before you consider a workflow with side effects.
LangChain introduced the langchain.mcp namespace in version 1.4.0. It is currently beta, so check the linked documentation if an import or constructor changes.
What Connects to What
There are two separate authorizations:
- A person connects a QuickBooks Online company to DeepLedger through Intuit authorization.
- Your Python process sends a DeepLedger API key to the DeepLedger MCP endpoint.
The LangChain process never receives the Intuit refresh token. The DeepLedger MCP server exposes accounting tools, and LangChain adapts those MCP tools into tools its agent loop can call. See the QuickBooks MCP server guide for the broader architecture and trade-offs.
Prerequisites
- Python 3.10 or newer
- A DeepLedger account with at least one QuickBooks Online company connected
- Owner or admin access in DeepLedger if you need to create a personal API key
- A model provider account and its environment variable, such as
OPENAI_API_KEY
Use a demo company while you test. Do not use a live customer's books to discover what an unfamiliar tool does.
Step 1: Install the Current LangChain MCP Packages
For a new Python project:
pip install "langchain[mcp]>=1.4.0" langchain-openai
This example uses an OpenAI model string. If you use another provider, install that provider's LangChain package and change LANGCHAIN_MODEL accordingly.
Older examples use langchain-mcp-adapters and MultiServerMCPClient. LangChain now documents langchain.mcp.MCPAdapter as the replacement. Existing code should follow the official migration guide rather than mixing the two APIs in one example.
Step 2: Create and Store the DeepLedger API Key
In DeepLedger, open Settings > API Access, then choose Create API Key. Give the key a purpose-specific name and an expiration date. Copy it when it is shown and store it in a secret manager or local environment, never in source control.
export DEEPLEDGER_API_KEY="dl_live_..."
export OPENAI_API_KEY="..."
export LANGCHAIN_MODEL="openai:gpt-5.5"
export EXPECTED_QB_COMPANY="Demo Company"
A personal key acts as the person who created it and can reach every company that person can access. It is not a read-only credential. Expiration and revocation are useful controls, but the application must still decide which tools the model can use.
Step 3: Discover the Tools and Keep a Small Set
For the first run, expose only qbCompanyProfile and qbReports:
import os
from fastmcp.client import Client
from langchain.mcp import MCPAdapter
async def load_report_tools():
token = os.environ["DEEPLEDGER_API_KEY"]
client = Client("https://mcp.deepledger.ai/mcp", auth=token)
async with MCPAdapter(client) as adapter:
available = await adapter.list_tools()
wanted = {"qbCompanyProfile", "qbReports"}
selected = [tool for tool in available if tool.name in wanted]
missing = wanted - {tool.name for tool in selected}
if missing:
raise RuntimeError(f"DeepLedger tools not found: {sorted(missing)}")
return selected
Do not make the program depend on a fixed total tool count. Tool catalogs change. Check for the exact tools the workflow needs and fail clearly if one is absent.
This selection prevents this agent from choosing a QuickBooks recording tool. It does not narrow the underlying API key. Code elsewhere that has the same key could still discover and invoke other tools.
Step 4: Run a Company-Checked First Report
The first prompt should name the expected company, fixed dates, and accounting basis. It should stop if the company is wrong.
import asyncio
import os
from langchain.agents import create_agent
async def main():
tools = await load_report_tools()
expected_company = os.environ["EXPECTED_QB_COMPANY"]
model = os.environ.get("LANGCHAIN_MODEL", "openai:gpt-5.5")
agent = create_agent(model, tools)
result = await agent.ainvoke(
{
"messages": [
{
"role": "user",
"content": f"""
Call qbCompanyProfile with operation "profile".
The expected QuickBooks company is "{expected_company}".
If the returned company does not match, stop and explain the mismatch.
If it matches, call qbReports for a ProfitAndLoss report from
2026-08-01 through 2026-08-31 on the Accrual basis.
Return the company name, home currency, report dates, accounting basis,
net income, and whether totalRows is greater than count. Do not call any
other tool.
""".strip(),
}
]
}
)
print(result["messages"][-1].content)
asyncio.run(main())
Replace the dates with the period you intend to review. Then run the same report in QuickBooks with the same dates and basis. A matching company name is necessary but not sufficient; the period and basis can change the answer materially.
Detail reports may be paged. On the first page, totalRows > count means more rows remain. On later pages, continue while rowOffset + count < totalRows. A short page is not a complete ledger merely because the call succeeded.
In a notebook, call await main() instead of asyncio.run(main()), because the notebook already owns an event loop.
How This Works With LangGraph
create_agent returns a compiled LangGraph graph, so the example above is already a LangGraph application. Use that standard loop until you have a concrete reason to control the topology yourself.
If you later need deterministic steps before or after the model, the tools returned by MCPAdapter.list_tools() are regular LangChain tools. You can place them in a ToolNode, add routing, or embed the created agent as a subgraph. Keep the company check before any branch that can write.
LangGraph also provides human-in-the-loop middleware that can pause selected tool calls for approval. That approval needs a checkpointer and an actual reviewer process that resumes or rejects the call. Adding the middleware import alone does not create a working review system.
Multiple QuickBooks Companies
First ask qbCompanyProfile to list available companies. Switch by the returned organization ID, not a guessed display name, and then read the profile again before the report.
A company switch changes the active company for that person across DeepLedger AI clients. Two concurrent jobs sharing one personal key can therefore interfere with each other by switching the shared active company. For concurrent or scheduled multi-company work, design explicit serialization or separate organization-scoped automation rather than assuming each process has private company state. The multiple-company guide explains the shared state in more detail.
Before You Add QuickBooks Write Tools
Filtering the discovered tools is a model-facing boundary, not a new permission on the API key. A personal key remains as powerful as the person who created it.
Before exposing recording tools:
- Name the exact write tools required by the workflow. Do not pass the full catalog for convenience.
- Add LangGraph human-in-the-loop approval for those tool names and persist the interrupted state.
- Verify the active company again immediately before the approved write.
- Keep duplicate, open-document, amount, date, and account checks in the workflow.
- Revoke the key when the job ends or the operator changes.
Do not put a personal API key into a cron job and treat a prompt such as "ask before writing" as an access control. DeepLedger's product-managed automatic runs use a separate company-scoped credential whose allowed operations are enforced by the server; that secret is not exported for custom scripts. Read what AI write access needs to protect before designing a recording workflow.
Troubleshooting
ImportError: cannot import name 'MCPAdapter'. Confirm that the environment has langchain[mcp]>=1.4.0. The standalone adapter package uses different import paths.
401 Unauthorized. The DeepLedger key may be mistyped, expired, or revoked. Create a replacement in Settings > API Access rather than logging the full failing token.
NO_ACTIVE_COMPANY. Use qbCompanyProfile with operation: "list", then switch with the returned organization ID. Read the profile after switching.
QB_NOT_CONNECTED or a token error. Reconnect that company from DeepLedger's Settings > Clients area. Retrying Python code does not repair a disconnected QuickBooks authorization.
The report differs from QuickBooks. Check the company, start date, end date, accounting basis, and whether the tool response was paged. Compare the same report settings before treating it as a data defect.
The import works but beta warnings appear. That is expected for langchain.mcp today. Pin and test the version you deploy, and recheck the official migration notes when upgrading.
For client-neutral connection issues, see the QuickBooks MCP troubleshooting hub.
Current Primary Documentation
- LangChain MCPAdapter overview
- LangChain MCP authentication
- Migrate from langchain-mcp-adapters
- LangChain human-in-the-loop middleware
The DeepLedger-specific tool names, API-key behavior, company switching, and report fields in this article were checked against the production MCP and portal source on September 3, 2026. No customer data or bookkeeping write was used to verify the article.
Frequently Asked Questions
How do I connect LangChain to QuickBooks Online?
Install langchain with its MCP extra, create a DeepLedger API key, build a FastMCP Client with that key, and pass the client to LangChain's MCPAdapter. Call list_tools(), keep only the tools your agent needs, and pass them to create_agent.
Does the same connection work with LangGraph?
Yes. LangChain's create_agent returns a compiled LangGraph graph, and the tools returned by MCPAdapter are standard LangChain tools. You can use the simple agent loop first or place those tools in a custom LangGraph workflow later.
Should a new project still use langchain-mcp-adapters?
No. Current LangChain documentation directs new Python projects to the built-in langchain.mcp namespace in langchain 1.4.0 or newer. It replaces MultiServerMCPClient with MCPAdapter, but the new namespace is still beta and may change.
Do I need an Intuit developer app?
Not for this hosted setup. You connect the QuickBooks company to DeepLedger once through Intuit authorization, then the LangChain process authenticates to DeepLedger with its own API key. A direct QuickBooks API integration is a different architecture and does require your own Intuit app.
Does filtering the LangChain tool list make the API key read-only?
No. It limits which tools that particular agent can choose, but a personal DeepLedger API key still carries the access of the person who created it. Keep the key secret, revoke it when it is no longer needed, and do not hand recording tools to an unattended agent without a separate approval design.
Can one LangChain agent work with several QuickBooks companies?
A personal API key can reach every company its creator can access. Use qbCompanyProfile to list and explicitly switch companies, then verify the returned company before each report or write. A switch changes the person's shared active company across their DeepLedger AI clients.