Skip to content

Connect an agent to your application's MCP endpoint

This is the application-endpoint counterpart of Connect an agent. That guide connects an agent to the MeroFoundry platform so it can build applications. This one connects an agent to an application you have built, so one of the application’s own users can use its tools from their AI app, with exactly that user’s access.

The agent always acts as one signed-in application user. It never holds a shared key, and the endpoint service’s API key does not open MCP.

The application must serve an MCP endpoint: a webhook_in endpoint service, a tool catalog and mcpSettings.enabled set to true (see the MCP endpoint recipe). The application also needs a sign-in page for its users. On a page-builder site that is the page at /login with a sign-in form; another path can be named in mcpSettings.login_path.

You need the application’s public host, for example orders.merofoundry.app or your own custom domain.

  1. In the AI app, add a custom remote MCP connector. Name it after your application.

  2. Set its server URL to the application’s /mcp URL:

    https://<your application host>/mcp
  3. Leave the optional OAuth client ID and client secret fields blank. A supported client reads the application’s OAuth discovery documents and registers itself with the application.

  4. Select Connect. The AI app opens a browser tab on the application host.

If you are not already signed in to the application in that browser, the tab opens the application’s sign-in page. Sign in with your application account, the same one you use on the application’s site. How you sign in, with a password or with a provider the application offers, is the application’s choice; either way you end with an application session.

After a successful sign-in the page returns you to the consent page automatically. If you were already signed in, you see the consent page straight away.

The consent page is served by the application host itself and shows:

  • the name the AI app registered with, and the application it wants to use;

  • the account you are signed in as;

  • what the app is asking to do, in plain words:

    Permission What it allows
    mcp:tools:list See the list of tools this application offers
    mcp:tools:call Use this application’s tools on your behalf
    mcp:stream Receive streamed results from those tools
    consumer:read Read your account information in this application
  • where your browser goes after you choose: the AI app’s registered callback.

Approve only if the app, the account and the permissions are what you expect.

  • Approve records your consent and returns you to the AI app, which finishes the connection and holds an access token for your account. Token lifetimes are the platform’s standard OAuth lifetimes.
  • Deny returns you to the AI app with access_denied. No access is granted.

Each consent form can be submitted once and is valid for ten minutes. If you leave it open longer, or submit it twice, the page says so: start again from the AI app.

Return to the AI app and enable the connector for the conversation. The agent can now list the application’s tools and call them. Every call runs as you: tools scoped to the signed-in user (for example a “my orders” tool built with the MCP consumer tools recipe) return only your rows, never another user’s.

The consent page never sends your browser anywhere when the request is wrong. It shows an error and an error code instead:

Code Meaning
invalid_request The request is malformed, uses an unregistered callback, or lacks PKCE (S256).
unauthorized_client The AI app is not registered with this application. Reconnect it.
invalid_scope The app asked for a permission this application does not offer.
invalid_target The app asked for a token for a different service.
consent_invalid The consent form expired, was altered, or belongs to another sign-in.
consent_used The consent form was already submitted.
session_required You were signed out before choosing.

Bring your own sign-in page: the returnTo contract

Section titled “Bring your own sign-in page: the returnTo contract”

On a page-builder site the /login page already honours this contract. A bring-your-own front end serves its own sign-in page, and must honour the same contract there.

When a signed-out browser reaches the consent page, the application host redirects it to the sign-in page with one query parameter:

https://<your application host>/login?returnTo=%2Foauth%2Fauthorize%3Fresponse_type%3Dcode%26client_id%3D...

After a successful sign-in, send the browser to the decoded returnTo value with a full page load, keeping its path and its whole query string exactly as received. Accept returnTo only when it:

  • begins with a single /;
  • does not begin with //, and its decoded path does not begin with //;
  • contains no backslash, encoded or not, and no whitespace or control characters;
  • therefore names no scheme and no other host.

Ignore any other value and continue with your usual post-sign-in page. A sketch:

function safeReturnTo(value) {
if (typeof value !== 'string' || !value.startsWith('/') || value.startsWith('//')) return null;
if (/[\\\u0000- \u007f]/.test(value)) return null;
let path;
try {
path = decodeURIComponent(value.split(/[?#]/, 1)[0]);
} catch {
return null;
}
if (path.startsWith('//') || path.includes('\\')) return null;
return value;
}
const target = safeReturnTo(new URLSearchParams(location.search).get('returnTo'));
location.assign(target ?? '/');

The sign-in must leave the application’s own session cookies on the application host, which the platform sign-in endpoints do. The consent page only checks that such a session exists; it does not depend on your front end in any other way.