MCP server
Lelemon has one MCP server. It lives at https://api.lelemon.cl/mcp: you paste the URL in your client, sign in with your Lelemon account and choose what the client can do. There is nothing to install and no API key to copy.
It turns every operation of the v2 API into a tool named by its operationId, such as agents.list or cases.close, so a model can set up an account the way this documentation does. It also keeps the tools of the Lelemon CRM (find_contact, get_deal_summary, send_message and others), which work on deals; see CRM tools.
This is the MCP server of Lelemon. If you want your agents to call tools of an MCP server of yours, see Actions and MCP.
Connect in two minutes
The URL is the same everywhere:
Code
- Claude Desktop and claude.ai: open Settings, Connectors, add a custom connector and paste the URL. Claude opens the Lelemon sign-in.
- Claude Code: run the command above, then type
/mcpinside Claude Code, chooselelemonand authenticate. Add--scope userto have it in every project. - Cursor: put the block in
~/.cursor/mcp.jsonfor every project or in.cursor/mcp.jsonfor one project. Cursor shows a sign-in button on the server. - ChatGPT: turn on developer mode in the connector settings, create a connector with the URL and choose OAuth as its authentication. The menus change from version to version; if you do not find them, search the settings of ChatGPT for "connectors".
The client registers itself, so there is no client id or secret to enter. After you sign in, Lelemon shows a screen where you choose two things:
- The organization the client works on.
- The permissions it gets, written in plain language and grouped by area. Mark only what you need.
Then ask: "List my Lelemon agents." The client calls agents.list and answers with what it finds.
Who can connect
The connector works for people who see every case of the organization: the owner, the admins and the members whose case scope is all. If you cannot connect, the consent screen and the sign-in answer access_denied with "Tu usuario no ve todos los casos de la organización". An owner or admin gives you access with PATCH /v2/members/{id}/case-scope (members.updateCaseScope) or from the Team screen of the dashboard.
What you grant
The permissions are the scopes of the API. A client sees only the tools whose scopes you granted, and every call goes through the same rules as a call with an API key: scopes, roles, subaccounts, idempotency and the request log.
- A member can grant what the dashboard lets a member do: read cases, contacts, conversations, agents, knowledge, skills, pipelines, approvals, team questions, runs, meetings and the team, and write cases, contacts and meetings. Reading connectors, webhooks, budgets, usage, triggers, subaccounts, files, messages, turns and actions needs an owner or admin, like in the dashboard. An owner or admin can grant any permission from the list.
- Some permissions are never granted through the MCP: giving an agent new actions, approving what an agent wants to do, revealing sensitive values, webhooks, connectors and the recipient allowlist. Use an API key for those.
- If your role drops, the permissions it no longer allows stop working at once, even in a connection you already approved.
Every connection shows in the dashboard, under Developers: the client, its permissions, when it connected and when it was last used. Remove access cuts it right away, including its refresh token. A person who leaves the organization loses their connections too.
How it is secured
The server follows the MCP authorization specification:
- OAuth 2.1 with dynamic client registration and PKCE with
S256. Codes live for 60 seconds and work once. Registration is limited to 20 new clients per hour from one address and 20 clients per name. - The consent screen shows the name the client registered, the host it will send you back to and a warning when the name looks like a known client (Claude, ChatGPT, Cursor) but the address is not theirs, or when the address is your own computer. It starts with only the reads checked, and the permissions that change data need a separate confirmation.
- Access tokens last one hour and refresh tokens rotate. Using a refresh token twice revokes the connection.
- Tokens are bound to the server with the
resourceparameter (RFC 8707). The MCP rejects a token issued for another resource, and the API rejects an MCP token: it is not an API key. - The server never forwards your token. It calls the API with a key of its own for each connection, which only exists for that connection and dies with it.
- A request without a valid token answers
401withWWW-Authenticatepointing at/.well-known/oauth-protected-resource, which is how clients find the sign-in.
Act on a subaccount
A connection to a platform organization acts on a customer's subaccount when a call passes subaccount:
Code
A subaccount of another platform answers 404. See Run Lelemon for your customers.
What the tools look like
Each tool takes the path and query values of its operation as arguments, the JSON request body as body, and an optional subaccount. This is the call behind "create a draft agent":
Code
And this one lists the active agents:
Code
Each tool also declares an outputSchema: the top-level properties of the answer when the call works. It returns that answer as structuredContent next to the same JSON as text. A failed call returns an error without structuredContent. Errors name tools and arguments, never routes or headers, and keep the code, the message and the fix of the API, with fix.endpoint as a tool name and fix.param as an argument name. A mistake found before the call comes back with a code such as unknown_argument, missing_argument or invalid_argument and the list of valid arguments.
CRM tools
The server keeps the tools of the Lelemon CRM. They work on deals and use CRM ids, not the case_ ids of the API: find_contact, get_deal_summary, list_deals_by_stage, list_pipelines, list_today_agenda, summary_today, pending_followups, pipeline_health, recent_messages, move_deal_stage, move_deal_to_pipeline, update_deal_note, create_followup_reminder, qualify_lead, create_lead, send_message, take_control, release_control, consultas_pendientes, responder_consulta, schedule_meeting, reschedule_meeting and cancel_meeting.
They appear when you grant cases:read (reads) and cases:write (writes). Tools that write ask for confirm: true before they act. Each write tool follows what the dashboard lets the role of the person do: a member does not see move_deal_to_pipeline (moving a case to another pipeline is for admins and the owner), and create_lead with assign_to only assigns a member to people of their own team. If you work with the API, use the tools named like cases.list; if you work with the CRM, use the others.
Without a browser: the npm package
For CI, scripts and servers where nobody can sign in, @lelemon-ai/mcp runs the same API tools from your machine with an API key. Add it to the client with npx -y @lelemon-ai/mcp:
Only LELEMON_API_KEY is required. It lists the tools your key covers, and it needs Node.js 20 or later. The rest are optional:
| Variable | Use |
|---|---|
LELEMON_API_URL | Optional. The API to talk to. Defaults to https://api.lelemon.cl. It must be https, except http for localhost, 127.0.0.1 and [::1], so the key never travels in clear text |
LELEMON_SUBACCOUNT | Optional. A sub_... id. Every call acts on that subaccount unless the call passes its own subaccount. Only for platform keys |
LELEMON_MCP_TOOLS | Optional. Keeps only these tools, comma separated. Each entry is an operation id or a prefix ending in .*, like cases.*,agents.list. An entry that matches no operation stops the server at start |
LELEMON_MCP_ALLOW | Optional. Turns on hidden groups, comma separated |
LELEMON_OPENAPI_FILE | Optional. Reads the contract from a file instead of downloading it. The scopes of the key are still read from the API |
On every start the package downloads GET /v2/openapi.json and reads GET /v2/me with your key, then writes one line to stderr with the number of tools it exposes. If the API does not answer, it exits with code 1 and names the URL it tried.
Only the tools you can use
The server lists only the tools whose required scopes (x-required-scopes in the contract) are covered by the permissions you granted. A connection with agents:read and cases:read sees the reads of agents and cases, not the whole API. That keeps the model focused and saves context.
Retry without doing things twice
Every tool that creates something or has a side effect takes an idempotencyKey. Tools whose effect is money (they send a message or cost money) require it: the model chooses a key and remembers it. For the others the server generates one when you leave it out.
Every result and every error of those tools returns the key it used, so a call that failed or timed out is repeated with the same idempotencyKey: if the first call went through, the API answers with the original result instead of doing it again.
A call waits 50 seconds for the API, less than the 60 seconds an MCP client waits by default. The client then receives the error timeout, which says whether to retry with the same idempotencyKey. A client configured to wait less than 50 seconds gives up first and reports its own timeout (-32001): retry with the same key then too.
Try before you do
Routes that send messages, spend money or change something hard to undo accept dryRun. Pass "dryRun": true in the arguments of the tool and it answers what would happen without doing it:
Code
What the server does not offer
Both servers hide three groups by default, so a model cannot be talked into calling them. A group hides what changes something in it or returns a secret. Harmless reads such as scopes.list, approvals.list or suppressions.retrieve are always there. The remote server keeps the groups off. With the npm package you turn a group on with LELEMON_MCP_ALLOW:
| Group | What it hides | To turn it on |
|---|---|---|
keys | Every tool whose answer carries a secret: subaccounts.apiKeys.create, webhookEndpoints.create, webhookEndpoints.rotateSecret, mcpServers.runIdentity.activate. The model never sees a secret unless you turn this on | LELEMON_MCP_ALLOW=keys |
approvals | Approving, rejecting or asking for review of what an agent wants to do, and the approval floor of actions | LELEMON_MCP_ALLOW=approvals |
suppression | Deleting a contact, changing opt-outs and redacting messages | LELEMON_MCP_ALLOW=suppression |
Code
Turning on keys is how a model creates a webhook endpoint, because the secret of the endpoint comes back in the answer. File uploads and downloads cannot be tools, because a tool call carries JSON, not files; the server prints the left-out operations to stderr with the reason. An operation that accepts JSON as well as a file, such as creating a knowledge document with text, is offered through JSON.
Effects and annotations
Every route declares its effect in the contract as x-lelemon-effect. The server turns it into the annotations MCP clients use to decide when to ask the person first.
x-lelemon-effect | Meaning | readOnlyHint | destructiveHint |
|---|---|---|---|
read | Changes nothing | true | false |
write | Creates or changes data | false | false |
destructive | Deletes, revokes or replaces, and may not be undoable | false | true |
money | Reaches a real person or costs money, and cannot be undone | false | true |
idempotentHint is true for reads, PUT and DELETE. openWorldHint is true for the tools that reach people or systems outside Lelemon: sending messages, testing an action or a webhook, resending an event, discovering an MCP server of yours, and reading the text your contacts wrote. Annotations are hints, not guarantees. A client should trust them only because it trusts this server; the API enforces scopes and the recipient allowlist regardless.
Good practice
- Grant only the permissions of the job.
- Let the client ask you before it runs a tool marked destructive or money.
- Grant few permissions for a task: a model with a dozen tools chooses better than one with a hundred.
- Ask the model to run
agents.activatewithdryRunbefore it turns an agent on.
What's next
- Build with AI for ways to give a coding agent the documentation.
- Set up an account from zero shows the calls a client makes to configure an account.
- Error codes for the
fixa failed call carries.