Connect an agent to the hosted MeroFoundry MCP
This is the customer connection guide for the canonical, MeroFoundry-operated remote MCP service. It is written for a new user who has registered, confirmed their email address, and has not created an application or API key.
Production status (2026-08-21): deployed. The canonical customer endpoint is the production URL below. Deployment of the protocol does not automatically certify every client: Claude remains the reference client, and each additional client still needs its complete fresh-user journey and evidence recorded before it is described as release-certified.
The new-user journey
Section titled “The new-user journey”A new verified user connects an interactive agent without creating or copying an API key:
-
In the agent, add a custom remote MCP connector named
MeroFoundry. -
Set its server URL to:
https://platform.merofoundry.com/mcp -
Leave optional OAuth client ID and client secret fields blank. A supported client discovers the MeroFoundry authorization server and dynamically registers itself.
-
Select Connect. The agent opens MeroFoundry in a browser.
-
Sign in with the verified MeroFoundry account. Review the client name, workspace, requested permissions, and token lifetime on the consent page.
Sign in with any provider listed on the MeroFoundry sign-in page (GitHub, Google, Microsoft, or Apple), then return to the same consent page to review and approve the connection.
-
Confirm the authorization target shown on the consent page:
- If the workspace has no applications, the page offers a one-use connection that can create exactly the first application.
- If the user owns one application, that application is selected automatically.
- If the user owns multiple applications, choose the one this connection may use. Each normal OAuth grant is bound to only the selected application. Approve only if the target and permissions are correct.
-
Return to the agent and enable the MeroFoundry connector for the conversation.
-
Ask the agent to create the first application, giving it a name and a URL-safe slug. For example:
Use MeroFoundry to create my first application. Name it Customer Portal and usecustomer-portal as its slug. -
Complete the second MeroFoundry authorization when the agent prompts. If the client does not prompt automatically, disconnect and reconnect the MeroFoundry connector. This second exchange is expected in the initial release: creating the first application consumes the one-use workspace bootstrap grant, and reauthorization gives the client a separate grant bound to the new application.
-
Ask the agent to build, style, publish, and verify the application. The agent should finish by reporting the assigned public URL.
The agent receives OAuth access; it never needs to see or store a MeroFoundry application API key. The bootstrap credential can discover its target and create exactly one first application. It cannot author models, pages, records, domains, or other application resources.
Reference client: Claude
Section titled “Reference client: Claude”Claude is the reference interactive client for the initial acceptance run. On an individual Claude plan:
- Open Customize > Connectors.
- Select + > Add custom connector.
- Enter
MeroFoundryand the complete/mcpURL above. - Leave Advanced settings empty, add the connector, and select Connect.
- Complete MeroFoundry login and consent in the browser.
- Enable the connector in a conversation from the + > Connectors menu.
On Claude Team or Enterprise, an Owner or Primary Owner first adds the custom web connector under the organization’s connector settings. Each member then connects it with their own MeroFoundry account. Anthropic brokers remote connectors from its cloud, so the MCP endpoint must be publicly reachable; a URL available only on a user’s laptop or private network will not work.
Anthropic’s current instructions are in Get started with custom connectors using remote MCP.
Current Codex CLI, the ChatGPT desktop app, and the Codex IDE extension support Streamable HTTP MCP servers with OAuth, PKCE, and dynamic client registration. For Codex CLI, add the server and start OAuth with:
codex mcp add merofoundry --url https://platform.merofoundry.com/mcpcodex mcp login merofoundry --oauth-client-registration dcrThe login command opens the MeroFoundry browser flow. Use /mcp in the Codex TUI to inspect the
connection. After the agent creates the first application, run the login command again when the
bootstrap credential is consumed. Do not use --bearer-token-env-var with a MeroFoundry API key;
that option places its value in Authorization, while MeroFoundry API keys belong only in
X-API-Key.
In the ChatGPT desktop app or Codex IDE extension, add a Streamable HTTP server with the same URL, restart the client when asked, and select Authenticate. Local Codex MCP configuration is not the ChatGPT web connector mechanism. OpenAI documents the current client and OAuth behavior in Model Context Protocol.
Codex is protocol-compatible by design, but it is not release-certified for this MeroFoundry flow until its zero-app creation, second authorization, full authoring, publication, and revocation path has passed against staging.
Agy 1.1.14 supports remote MCP URLs, protected-resource and authorization-server discovery, PKCE,
dynamic client registration, refresh tokens, and an interactive MCP authentication action. Add the
hosted server to ~/.gemini/config/mcp_config.json:
{ "mcpServers": { "merofoundry": { "serverUrl": "https://platform.merofoundry.com/mcp" } }}Restart Agy, open its MCP server panel, and select Authenticate for merofoundry. Authenticate
again after first-app creation consumes the bootstrap credential. As with Codex, this is
expected-compatible rather than release-certified until the complete staging journey passes on the
documented Agy version.
Client compatibility rule
Section titled “Client compatibility rule”Do not describe every MCP client as supported merely because it accepts an MCP URL. A supported interactive client must correctly handle:
- Streamable HTTP at
/mcp; - OAuth protected-resource and authorization-server metadata discovery;
- Authorization Code with PKCE;
- dynamic client registration, or a deliberately pre-registered client;
- browser login and consent;
- refresh, denial, expiry, and revocation; and
- the one-time bootstrap followed by normal reauthorization.
The MCP authorization specification defines these protocol responsibilities in Authorization. Document another agent as supported only after its complete fresh-user journey has passed and the evidence has been recorded. A local stdio bridge is not the canonical customer path and does not substitute for that acceptance run.
OAuth discovery and credential separation
Section titled “OAuth discovery and credential separation”For the production MCP resource:
https://platform.merofoundry.com/mcpthe public discovery documents are:
https://platform.merofoundry.com/.well-known/oauth-protected-resource/mcphttps://platform.merofoundry.com/.well-known/oauth-protected-resourcehttps://platform.merofoundry.com/.well-known/oauth-authorization-serverAfter authorization, an interactive client sends the OAuth access token as:
Authorization: Bearer <oauth-access-token>MeroFoundry keeps OAuth credentials and application API keys distinct:
- interactive hosted-MCP users use an OAuth bearer token in
Authorization; - SDK and other headless integrations use an application API key in
X-API-Key; - an application API key is not accepted as an OAuth bearer token; and
- an OAuth access token is not accepted in
X-API-Key.
Do not configure a new user’s agent with an API key or place an API key in a client’s static bearer token setting. See Hosted MCP and package boundaries for the separate SDK and standalone MCP use cases.
whoami response contract
Section titled “whoami response contract”Call whoami with no arguments after connecting to inspect the non-secret grant context that the
hosted MCP server resolved for the current request. The response is a WhoamiResponse. Its Python
field names are implementation names on the server; a client only ever sees the serialized keys,
which are the fields’ camelCase aliases:
| Serialized key | Python field | Present |
|---|---|---|
authenticated |
authenticated |
Always |
clientId |
client_id |
Always |
scopes |
scopes |
Always |
baasPermissions |
public_api_permissions |
Always |
applicationId |
application_id |
Always |
workspaceId |
workspace_id |
Always |
grantType |
grant_type |
Always |
documentationUrl |
documentation_url |
Always |
reauthorizationRequired |
reauthorization_required |
Always |
missingScopes |
missing_scopes |
Always |
nextStep |
next_step |
Only when there is advice |
scopes are the OAuth scopes the grant holds. The effective permission list resolved from them is
the implementation field public_api_permissions, which the response carries under its wire alias
baasPermissions. That key is a preserved wire name: clients must read baasPermissions, and the
field name public_api_permissions never appears in a response. missingScopes lists the scopes a
reconnect would add, and is an empty array when nothing is missing.
The tool’s MCP outputSchema is exactly:
{ "description": "The non-secret OAuth grant context available to an MCP client.", "properties": { "authenticated": { "title": "Authenticated", "type": "boolean" }, "clientId": { "title": "Clientid", "type": "string" }, "scopes": { "items": { "type": "string" }, "title": "Scopes", "type": "array" }, "baasPermissions": { "items": { "type": "string" }, "title": "Baaspermissions", "type": "array" }, "applicationId": { "anyOf": [ { "format": "uuid", "type": "string" }, { "type": "null" } ], "title": "Applicationid" }, "workspaceId": { "anyOf": [ { "format": "uuid", "type": "string" }, { "type": "null" } ], "title": "Workspaceid" }, "grantType": { "anyOf": [ { "enum": [ "application", "bootstrap" ], "type": "string" }, { "type": "null" } ], "title": "Granttype" }, "documentationUrl": { "const": "https://docs.merofoundry.app/llms.txt", "title": "Documentationurl", "type": "string" }, "reauthorizationRequired": { "title": "Reauthorizationrequired", "type": "boolean" }, "missingScopes": { "items": { "type": "string" }, "title": "Missingscopes", "type": "array" }, "nextStep": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Nextstep" } }, "required": [ "authenticated", "clientId", "scopes", "baasPermissions", "applicationId", "workspaceId", "grantType", "documentationUrl", "reauthorizationRequired" ], "title": "WhoamiResponse", "type": "object"}nextStep is omitted from an ordinary response and present when there is advice to act on; the
schema permits null because it describes the model, while the serialized tool response follows
that omission rule. missingScopes is not listed under required because the model defaults it,
but the serialized response always includes it. documentationUrl is always the server constant
https://docs.merofoundry.app/llms.txt, not a client-supplied URL.
Application grant
Section titled “Application grant”An application grant has an application boundary and permits application-scoped work. The scope
list below is shortened to three entries; a grant that holds every currently defaulted scope has
nothing to reconnect for, so its missingScopes is empty and nextStep is absent:
{ "authenticated": true, "clientId": "claude-desktop", "scopes": ["app:read", "models:read", "records:read"], "baasPermissions": ["app:read", "models:read", "records:read"], "applicationId": "11111111-1111-4111-8111-111111111111", "workspaceId": "22222222-2222-4222-8222-222222222222", "grantType": "application", "documentationUrl": "https://docs.merofoundry.app/llms.txt", "reauthorizationRequired": false, "missingScopes": []}Bootstrap grant
Section titled “Bootstrap grant”A new workspace has no application boundary yet. Its one-use bootstrap grant has
applicationId: null and is used only to create the first application. Its baasPermissions
list the permissions its scopes map to, including applications:create:
{ "authenticated": true, "clientId": "claude-desktop", "scopes": ["app:read", "applications:write"], "baasPermissions": ["app:read", "applications:create", "applications:delete", "applications:update"], "applicationId": null, "workspaceId": "22222222-2222-4222-8222-222222222222", "grantType": "bootstrap", "documentationUrl": "https://docs.merofoundry.app/llms.txt", "reauthorizationRequired": false, "missingScopes": []}Reconnect-required grant
Section titled “Reconnect-required grant”After the first application is created, the consumed bootstrap connection must be replaced by a
new application grant. Until the client disconnects and reconnects, whoami reports this state,
and baasPermissions is applications:create only:
{ "authenticated": true, "clientId": "claude-desktop", "scopes": ["app:read", "applications:write"], "baasPermissions": ["applications:create"], "applicationId": null, "workspaceId": "22222222-2222-4222-8222-222222222222", "grantType": "bootstrap", "documentationUrl": "https://docs.merofoundry.app/llms.txt", "reauthorizationRequired": true, "missingScopes": [], "nextStep": "Disconnect and reconnect MeroFoundry to authorize application access. Reconnecting is sufficient; no client re-registration is needed."}For an older application grant, missingScopes lists any missing advisory or registered
scopes. When scopes are missing, nextStep names them as a comma-separated list. For example,
if only pages:read is missing, missingScopes is ["pages:read"] and the advice is:
Disconnect and reconnect MeroFoundry to grant the missing scopes: pages:read. Reconnecting is sufficient; no client re-registration is needed.Reconnecting lets an existing client consent to newly defaulted scopes. Advisory-only gaps
do not set reauthorizationRequired to true.
applicationId is the application boundary for application-scoped MCP tools. It is never a
model identifier: model IDs belong in modelId arguments or nested model paths. Do not substitute
a model ID for applicationId, and do not use a bootstrap grant for model, page, record, or other
application-scoped work.
Visual verification
Section titled “Visual verification”Connected clients should verify published pages visually with the capture_page_screenshot
and capture_site_screenshots tools: capture, inspect the screenshots and diagnostics,
repair, and recapture. The canonical loop, executable examples, and remediation guide live in
the MCP tool reference. A successful authoring API response is not visual
evidence.
Acceptance and troubleshooting
Section titled “Acceptance and troubleshooting”Client certification runs use https://staging.merofoundry.com/mcp; each run must start with a newly
registered and verified user, no application, and no application API key. It must also verify denial,
refresh, revocation, restart or multi-replica behavior, correct user attribution, and a complete
author-publish-discover-live-check sequence. MCP_BACKEND_API_KEY must remain unset.
If connection fails:
- No browser opens: confirm the client supports remote MCP OAuth, not only local stdio servers.
- Discovery or registration fails: check the three well-known documents above and
/oauth/registeron the same public origin. - Claude times out before OAuth: confirm the endpoint is reachable from the public internet, not only from the operator or user’s network.
- First application succeeds, then authoring returns unauthorized: complete the expected second authorization, or disconnect and reconnect the connector.
- Consent offers neither an application nor first-app creation: verify the user’s email, workspace membership, create-application permission, zero-application state, and plan entitlement.
- A credential works only after moving it to a different header: stop and investigate. Header-based credential-type separation is an intentional security boundary.
The detailed security and transition decisions are in Secure OAuth MCP first-application design.
