Skip to content

Frame provider tools around creating accounts; unlisted providers by ID; show the sign-up cap - #66

Merged
sidharth0612 merged 3 commits into
mainfrom
sid/unlisted-provider-descriptions
Sep 29, 2026
Merged

sidharth0612 merged 3 commits into
mainfrom
sid/unlisted-provider-descriptions

Conversation

@sidharth0612

@sidharth0612 sidharth0612 commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

agentmail-to/agentmail-api#1408 (merged 2026-09-21) made GET /providers/{id} and POST /providers/{id}/connect follow the provider's registration rather than the catalog. A registered provider that the catalog doesn't list now resolves (ID and name, no updated_at) and can be connected, as long as the caller has its ID. List and search still show catalog entries only.

The tool descriptions still described the old behavior. get_provider said an unlisted provider resolves "only when your organization holds an account at it — otherwise 404". That steers an agent away from a provider ID the user gives it. These descriptions are what the hosted connector shows to Claude, ChatGPT, and Cursor, so this is the change that makes the by-ID path visible there.

  • get_provider: any registered provider resolves. A missing updatedAt means the provider isn't a reviewed catalog entry, and a 404 means no provider is registered under that ID.
  • connect_provider: works for any registered provider, listed or not.
  • list_providers / search_providers: say they cover catalog entries only, and point at the by-ID path.
  • Updated the ProviderSchema comment to match.

Framed around creating accounts. People reach these tools by asking "create an account at Firecrawl" or "my agent needs a web search API":

  • connect_provider creates an account, or signs an existing one back in, and names the sign-up-limit error and its fix.
  • search_providers matches names only, so a need goes through list_providers descriptions.
  • list_accounts is the check to run before connecting.

ownerSignupLimit is now kept on provider results. The API has published it since agentmail-to/agentmail-api#1315, but ProviderSchema stripped it. connect_provider refuses a new sign-up past that cap, so seeing it up front lets the agent pick an inbox that already holds an account. A new test covers it passing through and SDK internals being stripped.

Behavior is otherwise unchanged. It ships with the pending 0.9.1. After that is published, agentmail-mcp needs its agentmail-toolkit pin moved from 0.9.0 and mcp-manifest.json regenerated.

Related: agentmail-to/agentmail-skills#17, agentmail-to/agentmail-plugins#15

Test plan

  • npx tsup && npx vitest run: 465/465
  • eslint src: clean
  • After publishing, bump agentmail-mcp and regenerate the manifest

Merge order

  1. Frame provider tools around creating accounts; unlisted providers by ID; show the sign-up cap #66, then publish agentmail-toolkit 0.9.1 to npm
  2. Send server instructions that introduce AgentID providers and accounts agentmail-mcp#62 after it gains the 0.9.1 pin bump and a regenerated mcp-manifest.json, then confirm the connector deploy
  3. Add the agentmail-agentid skill for providers and accounts agentmail-skills#17, re-synced with skills.py sync --backend against the regenerated manifest
  4. Ship the agentmail-agentid skill and release 0.4.0 agentmail-plugins#15, re-exported from docs: add Fronteir AI hosted deployment option #17 if docs: add Fronteir AI hosted deployment option #17 changed
  5. docs(agentid): use AgentID from Claude, ChatGPT, and Cursor agentmail-docs#279, then run Publish docs

Skills, plugins, and docs wait for the connector so they don't describe ownerSignupLimit and unlisted-by-ID behavior that the live 0.9.0 tool descriptions contradict.

🤖 Generated with Claude Code

agentmail-api#1408 made GET /providers/{id} and POST
/providers/{id}/connect follow the provider's registration instead of
the catalog, so a registered provider the catalog does not list still
works when the caller has its ID. get_provider still said an unlisted
provider resolves "only when your organization holds an account at it",
which steers an agent away from a provider ID the user hands it.

- get_provider: any registered provider resolves; a missing updatedAt
  means not a reviewed catalog entry; 404 means no such provider.
- connect_provider: works for any registered provider.
- list_providers / search_providers: catalog only, and point at the
  by-ID path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n-up cap

People reach these tools asking "create an account at Firecrawl" or
"get my agent a web search API", not "connect a provider". Say so in
the descriptions: connect_provider creates an account (or signs an
existing one back in), search matches names only so a need goes
through list_providers descriptions, and list_accounts is the check
before connecting.

ProviderSchema now keeps ownerSignupLimit (published by the API since
agentmail-api#1315). connect_provider refuses a new sign-up past that
cap; seeing it up front lets the agent pick an inbox that already holds
an account instead of minting a URL that fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sidharth0612 sidharth0612 changed the title Say that an unlisted provider resolves and connects by ID Frame provider tools around creating accounts; unlisted providers by ID; show the sign-up cap Sep 29, 2026

@shalim786 shalim786 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked against the deployed prod get-provider / connect-provider bundles (2026-09-28). The by-ID behaviour matches #1408, and the ownerSignupLimit semantics are right (per org; 0 pauses new sign-ups; an existing account always signs in). Two wording notes inline.

Merge/deploy order. The hosted connector runs agentmail-toolkit 0.9.0 (npm latest; 0.9.1 is unpublished). Live get_provider still says an unlisted provider 404s unless the org holds an account, and 0.9.0 strips ownerSignupLimit. Suggested order: toolkit#66 → publish 0.9.1 → bump the pin + regenerate mcp-manifest.json → deploy the connector → then skills#17, plugins#15, docs#279.

logoUrl: z.string().optional(),
termsUrl: z.string().optional(),
privacyUrl: z.string().optional(),
ownerSignupLimit: z

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth adding what the cap counts, so agents don't try to compute headroom from list_accounts. The deployed counter (organization_signup_count#<provider>#<org>) increments on every first-time sign-up and I found no decrement, so disabled accounts still count. list_accounts doesn't publish disabled rows, so counting its items undercounts. The directory value is also a snapshot as of updated_at, while /token reads it live. Maybe: "…Counts every inbox that has ever signed up, including disabled accounts; treat it as a hint and rely on connect's limit error."

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 38a4c40, on both the ownerSignupLimit field and the get_provider description. It says the cap counts every inbox that has ever signed up, including disabled accounts list_accounts does not show, and that it can lag the live value, so treat it as a hint and rely on connect_provider's limit error.

Comment thread node/src/tools.ts Outdated
title: 'Connect Provider',
description:
"Start signing an inbox in to a provider: mints a browser sign-in session and returns a single-use magic URL to open in the client that will hold the sign-in (usually the agent's own browser session), plus the ID of the pending sign-in key. The URL expires, is never re-issued, and nothing is connected until the sign-in completes — do not call again for the same provider and inbox while a previous URL is still live (live sessions are limited per caller). Confirm completion with list_accounts for that providerId. Requires the provider_connect permission. inboxId is required unless the credential is scoped to one inbox.",
"Create an account at a provider as an inbox, or sign an inbox that already holds one back in: mints a browser sign-in session and returns a single-use magic URL to open in the client that will hold the sign-in (usually the agent's own browser session), plus the ID of the pending sign-in key. The URL expires, is never re-issued, and nothing is connected until the sign-in completes — do not call again for the same provider and inbox while a previous URL is still live (live sessions are limited per caller). Confirm completion with list_accounts for that providerId. Works for any registered provider, listed in the catalog or not. A provider can cap sign-ups per organization; when the cap is reached this fails with a limit error, and an inbox that already holds an account there (see list_accounts) can still sign in. Requires the provider_connect permission. inboxId is required unless the credential is scoped to one inbox.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: "Works for any registered provider" is slightly broad. Connect resolves via findProviderHandoffPrimary, which also requires a valid initiate_login_uri, so a provider get_provider resolves can still 404 here. The limit error could also be named: it's 403 limit_exceeded, and its fix text already says which inbox to use.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 38a4c40. It now says "Works by ID for a registered provider whether or not the catalog lists it, provided it has a sign-in entry point". It names the cap error as 403 limit_exceeded, whose fix says to sign in with an inbox that already holds an account. A 404 names Provider (unknown ID, or no sign-in entry point) or Inbox (not in the org or scope), and with acceptDisclosure can mean it isn't supported, so retry without.

Review against the deployed handlers:
- ownerSignupLimit counts every inbox that ever signed up, including
  disabled accounts list_accounts hides, and can lag the live value.
  Describe it as a hint and point at connect's limit error.
- connect_provider needs a sign-in entry point, so "any registered
  provider" was too broad. Name the cap error (403 limit_exceeded) and
  the 404 cases: Provider, Inbox, and acceptDisclosure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sidharth0612

Copy link
Copy Markdown
Contributor Author

@shalim786 Thanks for checking against the deployed bundles. Both wording notes are addressed in 38a4c40 (replies inline). Your merge order is now in every PR description: this PR → publish 0.9.1 → mcp#62 with the pin bump and manifest regen → skills#17 → plugins#15 → docs#279.

@shalim786 shalim786 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All review comments addressed in 38a4c40. LGTM. Merge order still applies: publish agentmail-toolkit 0.9.1 from #66, bump the connector's pin to it, regenerate mcp-manifest.json and deploy; then merge skills#17, plugins#15 and docs#279.

@sidharth0612
sidharth0612 merged commit 4c5dbb6 into main Sep 29, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants