Allows AI to query your CRM data using raw SQL via MCP, and build custom dashboards with the API
Overview
MCP (Model Context Protocol) lets LLMs interact with external tools and data sources. HighLevel has its own MCP, but it wraps the REST API — meaning the LLM can only fetch lists of records and try to reason about them in-context.
This creates real limitations. If you ask "how many duplicate opportunities do we have?", the HighLevel MCP has to pull records page by page, hold them in memory, and estimate. It can't join tables, count distinct values, or cross-reference contacts against phone calls and emails.
Streamlined's MCP is different. Because we sync your CRM data into a relational database, the LLM can write and execute real SQL queries — giving you deterministic, exact results across any combination of tables.
Why Relational Matters
Full Query Flexibility
You're not limited to pre-built dashboard widgets or fixed report templates. Need speed-to-lead broken down by sub-account? Duplicate opportunity counts grouped by pipeline stage? Engagement rates filtered by call direction and email status? Just ask — the LLM writes the SQL, and the database returns exact results. If you can describe it, you can query it.
Plain English, No SQL Required
The MCP exposes your full schema — table names, column descriptions, foreign keys, and enum values — so the LLM understands your data structure automatically. You just describe what you want to know in plain English, and the LLM crafts the right query. You never have to write or even see SQL unless you want to.
Build Custom Dashboards with the API
The same query engine that powers the MCP is also available as a standalone API. Generate an API key, point any frontend tool at it — Looker Studio, Retool, Lovable, or your own app — and build live dashboards with real-time CRM data. No export files, no stale snapshots.
Best-in-Class Data Sync
All of this is powered by Streamlined's data integration layer, which continuously syncs your HighLevel data into a clean, relational database. We handle the hard part — pulling, normalizing, and keeping your data accurate — so that every query you run, whether through an LLM or a dashboard, reflects reality.
What You Can Do
Here are a few examples of questions you can ask through the MCP. These would be difficult or impossible with a REST API-based MCP:
- "How many duplicate opportunities do we have per contact, and which pipeline stage has the most?"
- "What's our average speed-to-lead for missed inbound calls, broken down by sub-account?"
- "Which contacts were created this week and have engaged with us via a completed call, clicked email, or inbound message?"
- "Show me all contacts who booked an appointment but never showed, grouped by calendar."
- "What percentage of inbound callers do we actually call back, and how quickly?"
The MCP has access to all synced tables — contacts, opportunities, pipelines, pipeline stages, phone calls, emails, appointments, calendars, accounts, and more.
MCP Tools
When you connect the Streamlined MCP, the LLM gets access to the tools below. Which of them it actually sees depends on the capabilities you granted the connection — a connection scoped to events gets the event tools and nothing else.
Every tool is named <module>_<method>, matching the REST API exactly: custom_event_create is POST /gateway/v2/custom-event, grouping_read is GET /gateway/v2/grouping. Anything you can do over the API you can do here, under the same name.
Exploring your data
Tool | What it does |
schema_list | Lists all available tables, accounts, users, groupings, and query rules. This is typically the first tool the LLM calls, to understand what data is available. |
schema_explain | Returns detailed column descriptions, data types, foreign keys, enum values and ready-to-use JOIN hints for one or more tables. The LLM uses this to write correct queries. |
query_run | Runs a read-only SQL SELECT query against your CRM database. All queries are scoped to your account — you can only see your own data. |
object_read | Reads the full text of stored content the CRM tables reference but don’t hold — today, email bodies. This is its own capability, so a connection can be allowed to query your CRM without being allowed to read the text of anyone’s mail. |
Learning how something works
Tool | What it does |
guide_read | Returns a written guide for one area of the product — the vocabulary its methods carry, the orderings that matter, and the mistakes that look reasonable. For dashboards it returns the full authoring playbook. |
utilize_api | Provides instructions for building custom dashboards and apps outside Streamlined that query your CRM data via the REST API — a Claude Artifact, a Lovable app, a Claude Code project, Looker Studio, Retool. |
Building dashboards inside Streamlined
These author dashboards that live in Streamlined, visible to your team and shareable through your existing permissions — no API key needed.
Tools | What they do |
dashboard_create
dashboard_read
dashboard_update
dashboard_delete | The dashboards themselves. dashboard_read with no id lists every dashboard you can see; with one, level controls how deep it goes — settings, sections, cards, or a live fetch that runs every card’s query. |
dashboard_section_create
dashboard_section_read
dashboard_section_update
dashboard_section_delete | The ordered groups inside a dashboard. A section’s type — stat, chart or table — is fixed when it is created and decides what may live in it. |
dashboard_card_create
dashboard_card_read
dashboard_card_update
dashboard_card_delete | The metric, chart and table tiles themselves. This is where the real work is — read guide_read on dashboard-card before authoring one. |
Two things are payload fields rather than tools of their own: moving a section or card is _update with a position (first, last, or before / after a sibling — the server computes the rank), and duplicating one is _create with from_template, which clones it byte for byte.
Managing your account
Tools | What they do |
grouping_* | Create, read, update and delete account groupings — the named sets of sub-accounts you filter and report by. |
custom_event_* | Create, update and delete custom events. See Custom Events API. |
access_token_* | Create, read, update and revoke API keys. |
configuration_read
workflow_read
workflow_folder_read | Read-only views of your AI automation settings and analysis workflows. |
Seeing names that aren’t in the tables above? Your client is holding a cached tool list. MCP clients cache the tool list on connect, so refresh or reconnect it and you will get the current set.
API Reference
The MCP wraps a REST API that you can also use directly to build dashboards, integrations, or custom tooling. All endpoints live under:
https://api.streamlined.so/gateway/v2All routes require authentication via an Authorization: Bearer header or an X-API-Key header. You can generate an API key from Settings → Integrations in Streamlined.
The response shape
Every response carries an ok field:
{ "ok": true, "result": ... }
{ "ok": false, "error": "..." }Branch on ok, not on the status code. The status agrees with it, but ok is the field the gateway actually writes, and it survives anything that reads the body without the response object — an MCP tool result, a no-code HTTP node, a template language.
GET /query — describe the data
Returns a high-level catalog of the data available to your account. Use this to discover what tables exist and how to query them.
GET https://api.streamlined.so/gateway/v2/query
X-API-Key: <access-token>Parameters: None.
Response:
Field | Description |
tables | List of available table slugs with descriptions, column counts, foreign key counts, and pivot join counts. |
accounts | All accounts (locations) belonging to your company, with ID and name. |
groupings | Pre-defined sets of accounts with their constituent account_ids. |
rules | Plain-text instructions for how to use the query API (e.g. "only SELECT allowed", "describe a table before writing SQL against it"). |
Tables that require Fivetran are excluded if your account doesn't have Fivetran enabled.
GET /query?table= — explain tables
Returns detailed schema information for one or more tables. Use this to understand column types, relationships, and how to write correct joins.
GET https://api.streamlined.so/gateway/v2/query?table=contacts,opportunities
X-API-Key: <access-token>Parameters:
Parameter | Type | Required | Description |
table | Query string (comma-separated) | Yes | One or more table slugs to describe. Omit it entirely to get the catalog above instead. |
Comma-separated, not a repeated parameter. ?table=contacts,opportunities is right; ?table=contacts&table=opportunities keeps only the last one.
Response (per table):
Field | Description |
columns | Column name, description, type, nullable flag, and enum values (for local enums). |
foreign_keys | FK column, referenced table, description, nullable flag, and a ready-to-use JOIN hint. |
pivot_joins | Pivot table name, target table, description, and a multi-line JOIN hint. |
links | URL templates with placeholders that reference column values. |
Returns 400 if any of the slugs are unrecognized. Omitting table altogether is not an error — it returns the catalog described above.
POST /query — run SQL
Executes a read-only SQL query scoped to your account.
POST https://api.streamlined.so/gateway/v2/query
X-API-Key: <access-token>
Content-Type: application/jsonRequest Body:
{
"sql": "SELECT COUNT(*) FROM contacts WHERE date_created > '2026-01-01'"
}Behavior:
- Only
SELECTandWITHstatements are allowed — anything else is rejected. - Row-level security is automatically applied using your company's location IDs.
- Queries run as a read-only role with a 60-second timeout.
- Results are capped at 5,000 rows. If exceeded,
truncatedis set totrue.
Success Response:
{
"ok": true,
"result": {
"rows": [...],
"truncated": false
}
}Error Response (400):
{
"ok": false,
"error": "Only SELECT statements are allowed"
}GET /guide — how an area of the product behaves
Returns the same written guides the guide_read MCP tool serves. Call it bare for the catalog, then name one to read it. This endpoint needs no API key — a guide carries no data of yours.
GET https://api.streamlined.so/gateway/v2/guide
GET https://api.streamlined.so/gateway/v2/guide?module=custom-eventWriting data: /<module>
The query endpoints above are read-only. Everything the API can write follows one shape — a noun in the path, and the HTTP verb picks what happens:
Verb | Means | Example |
POST | Create | POST /gateway/v2/custom-event records an event |
GET | Read | GET /gateway/v2/grouping lists your groupings |
PATCH | Update | PATCH /gateway/v2/dashboard?id=... edits a dashboard |
DELETE | Delete | DELETE /gateway/v2/meeting?id=... removes a meeting |
The nouns available today are access-token, ad-connection, app-update, configuration, connection, custom-event, dashboard, dashboard-section, dashboard-card, grouping, meeting, object, workflow and workflow-folder. Not every noun implements every verb — a verb a module does not have answers 405 and names the ones it does.
Call GET /guide?module=<noun> before your first write to one. The guide is what the endpoint shape alone cannot tell you: what each verb means for that noun, the orderings that matter, and the mistakes that look reasonable.
These endpoints also accept the token in the URL — ?token=<access-token> — for senders that cannot set headers at all, such as a note-taker webhook whose config is a destination URL and nothing else.
Use the header wherever your sender allows one: a URL travels through logs, referrers and proxies in ways a header does not. The query endpoints above do not accept it — SQL is header-only.
Connecting the MCP
The MCP endpoint for all platforms is:
https://mcp.streamlined.soAuthentication is handled via OAuth. When you connect for the first time, you'll be redirected to an authorization screen that says "<client> wants to connect to your CRM data” — click Allow Access, choose what it may reach and which sub-accounts it may see, then Approve Connection and you're done.
ChatGPT
- Open ChatGPT and go to Settings → Apps
- Click Create App
- Enter a name (e.g. "Streamlined")
- Paste the MCP URL:
https://mcp.streamlined.so - Set authentication to OAuth
- Check the box to enable dev mode (required by ChatGPT)
- Click Create — you'll be redirected to authorize access
- Click Allow Access, choose what it may reach, and approve — you’re connected
Claude
- Open Claude and go to Settings → Connectors
- Click Add a custom connector
- Enter a name (e.g. "Streamlined")
- Paste the MCP URL:
https://mcp.streamlined.so - Click Add — no advanced settings needed
- Authorize access when prompted
Other Platforms (Cursor, Claude Code, etc.)
Any LLM client that supports MCP can connect using the same URL. If your client supports OAuth-based MCP authentication, use the URL above. If it requires an API key instead, you can generate one from Settings → Integrations inside Streamlined.
To use the MCP or API via API key, pass an X-API-Key header in your requests.
What a Connection Can Reach
Every connection — whether it authorizes over OAuth or carries an API key — is bounded on two independent axes. Both are chosen by you when the credential is created, and both can be narrowed later by revoking it and making a new one.
Capabilities
What the credential may do. The picker offers three rungs:
Rung | What it means |
Full access | Everything, including capabilities we add later. This is what every credential made before capabilities existed carries, so nothing you already had has changed. |
Use a preset | A named job. Build a dashboard grants querying and dashboard authoring; Sync external meetings grants posting and deleting meetings; Send custom events grants the three event capabilities. Picking one shows you exactly what it grants before you approve. |
Choose specific scopes | Tick the individual capabilities yourself. Starts empty — an empty grant is refused, so you have to say what you mean. Coming here from a preset keeps that preset’s ticks, so you can start from one and adjust. |
A credential that reaches for something outside its capabilities gets a 403 naming the capability it is missing, not a silent empty result — so a misconfigured integration tells you what to fix.
Sub-accounts
Which sub-accounts the credential may act on. Either Current & future sub-accounts, which also reaches ones you add later, or Select limited sub-accounts for a fixed list.
A pin bounds SQL too, not just the write endpoints. A token pinned to two sub-accounts runs SELECT * FROM contacts and sees those two sub-accounts’ contacts — the pin is applied inside the query, so there is no way to write around it.
The picker only offers sub-accounts you can see yourself, so a credential can never be broader than the person who made it.
Managing Connections
Everything that can reach your data lives on one page: Settings → Integrations, in two lists. Access Tokens are the API keys you minted; OAuth Connections are the MCP clients you authorized. From there you can:
- See every live credential, and what each one is allowed to do — each row names its preset (“Sync external meetings”), its single capability, or a count
- Open any of them for the full detail: capabilities, pinned sub-accounts, who created it and when
- Rename an access token, or revoke any credential at any time
Revoking takes effect immediately and cannot be undone — mint a new credential rather than trying to restore one.
Your data is scoped per-account. Other users or accounts cannot see your data through the MCP.
Other Details
Security & Data Access
SQL is read-only — only SELECT and WITH statements run, and every query is scoped to your account. The MCP can do more than query, though: depending on the capabilities you grant a connection, it can author dashboards, manage groupings and record custom events. What no credential can ever do is reach data belonging to anyone else, or reach a sub-account outside its pin.
Schema Reasoning
The MCP includes built-in schema descriptions so that LLMs can understand your tables and write correct queries without any guidance from you. You just ask your question in plain English.
Rate Limits
500 requests per 10 seconds, counted per credential. Exceed it and you get a 429 that names the limit, along with a Retry-After header telling you how long to wait.
The count is per credential rather than per company, so a runaway script on one API key cannot throttle your dashboards or your other integrations.
Per-customer MCP endpoints
Agencies managing several Streamlined customers can connect to a customer-specific address — https://mcp.streamlined.so/<your-slug> — which keeps a separate sign-in per customer rather than sharing one browser session across all of them. Get in touch if you want one set up.
Ready to Install?
When you’re ready to install any app, click the link below to be taken through our installation wizard which can help you get it installed!
Frequent Questions
Do you offer custom development work?
Should I install your app at the agency level or location level?
What’s your support like?
How do I install your app?
Do you offer a free trial?
Can I request a feature or product?
Are there any usage limits on your apps?
Can I use your app on multiple accounts?
How do I uninstall the app?
Need to Get in Touch?
If you have any questions, concerns, or ideas, I’d love to hear them!
Visit the page below to book a call or get in touch right away.
