Dashly Docs

Client-portal MCP

A second MCP server that lets an agency's clients use their own AI assistant in their client space.

Agencies give their clients a portal. The client-portal MCP server lets a client (or a partner with a client space) connect their own assistant, in Claude, ChatGPT or any MCP client, to that portal:

https://mcp.usedashly.com/portal

It is a separate server from the agency server, with its own tools and its own sign-in. The assistant acts for one person, in their client space only. It never sees the agency's internal data, the agency's people, internal notes, deals or billing.

Connecting

The client signs in with their own Dashly client-space account, through OAuth. An agency API key (ak_…) does not work here: it is refused like any unknown credential.

Add a custom connector (or MCP server) with the URL https://mcp.usedashly.com/portal.

Click Connect, sign in with the client-space account, and approve the client-portal consent screen. The connection is bound to the client space chosen there.

The flow is the same standard OAuth flow as the agency server (see Connect a client), with its own protected-resource metadata:

https://mcp.usedashly.com/.well-known/oauth-protected-resource/portal
{
  "resource": "https://mcp.usedashly.com/portal",
  "authorization_servers": ["https://app.usedashly.com"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["openid", "profile", "email", "offline_access"]
}

Because the client asks for the /portal resource, the authorization server shows the portal's consent rather than the agency's. A connection approved for a client space is never given access to agency data, even when the person is also agency staff. Clients whose tool takes a header can instead use a personal dpm_… token created in their client space (Settings → AI assistants). The connection ends when the person loses access to the client space.

The server speaks the same protocol as the agency server (stateless JSON-RPC 2.0 over HTTP, same protocol versions) and supports initialize, ping, tools/list and tools/call. It has no prompts or resources.

Tools

Ids are the public ids the tools themselves return. Every call goes through the same rules as the portal's own pages: a section the agency hides from the portal is hidden here too, and a person can only do what their portal permissions allow.

list_my_projects

The projects the agency runs for the client, with their status. Useful before opening a request when there are several projects.

Arguments: none.

list_my_requests

The client's requests and where they stand (received, in progress, awaiting their validation, done). By default only the ones not done.

ArgumentTypeRequiredDescription
open_onlybooleannofalse to include finished requests. Defaults to true.
project_idstringnoKeep only one project's requests (an id from list_my_projects).

get_request

One request in full: its description, its steps and the exchanges with the agency.

ArgumentTypeRequiredDescription
request_idstringyesThe request's id, as list_my_requests gives it.

create_request

Sends a new request to the agency (a change, a problem, a question). It arrives unassigned in the agency's queue, marked as created by the client through an AI assistant, and the agency is notified as for any portal request. The assistant is told to restate the request and confirm it with the person before sending.

ArgumentTypeRequiredDescription
titlestringyesA short, clear title (2 to 160 characters).
descriptionstringnoThe request in detail: context, pages concerned, expected result (up to 4,000 characters).
project_idstringnoThe project concerned (an id from list_my_projects).

comment_request

Adds a message to one of the client's requests, visible to the agency.

ArgumentTypeRequiredDescription
request_idstringyesThe request's id.
messagestringyesThe message, as the person wants it sent (up to 5,000 characters).

list_my_milestones

The main steps of the client's projects, with their dates and progress.

Arguments: none.

list_my_documents

The reports, presentations and documents the agency shared with the client, each with a link to open it.

Arguments: none.

my_services_status

The current status of the services the client's site or business runs on (hosting, CMS, payments…), from their public status pages.

Arguments: none.

Arguments are validated strictly: an argument a tool does not know is refused rather than ignored. There are deliberately no tools to delete, change a status, assign, estimate, or touch deals and billing.

Limits

The agency controls its clients' access, by default for all clients and per client:

LimitDefault
Access switchOn. The agency can turn it off for one client or for all.
Monthly allowance per client2,000 tokens
Monthly allowance per personNone by default
Calls per minute, per person20
Calls per minute, per client60
New requests per client space10 per hour

A read costs 1 token and a write (create_request, comment_request) costs 6. Calls are also counted against the agency's own API allowance, at the same price as an API call. The agency is alerted when a client reaches 80% and 100% of its monthly allowance.

Refusals

A refused call comes back as a tool result with isError: true, a stable code and a message written for the person (pass it on as is):

CodeMeaning
client_disabledThe agency turned off assistant access for this client space.
rate_limitedToo many calls per minute; retry later.
client_quota_exhaustedThe client space's monthly allowance is used up.
user_quota_exhaustedThis person's monthly allowance is used up.
agency_quota_exhaustedThe agency's API allowance is used up.
tickets_rate_limitedToo many new requests this hour.
section_hiddenThe agency does not show this part of the portal to the client.
forbiddenThe person's portal permissions do not allow it.
setup_pendingThe client space's onboarding is not finished yet.
not_foundThe request or project does not exist in this client space.
invalid_inputAn argument is invalid.
server_errorSomething went wrong on Dashly's side.

An expired or revoked connection is answered with an OAuth challenge pointing at the portal's metadata, so the client offers to reconnect.

On this page