Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "agentmail",
"displayName": "AgentMail",
"version": "0.5.0",
"version": "0.6.0",
"description": "Email inboxes for agents. Create inboxes, send and receive emails, automate email workflows, and create accounts with AgentID.",
"author": {
"name": "AgentMail",
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "agentmail",
"version": "0.5.0",
"version": "0.6.0",
"description": "Email inboxes for agents. Create inboxes, send and receive emails, automate email workflows, and create accounts with AgentID.",
"author": {
"name": "AgentMail",
Expand Down
2 changes: 1 addition & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "agentmail",
"version": "0.5.0",
"version": "0.6.0",
"description": "Email inboxes for agents. Create inboxes, send and receive emails, automate email workflows, and create accounts with AgentID.",
"author": {
"name": "AgentMail",
Expand Down
2 changes: 1 addition & 1 deletion .plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "agentmail",
"version": "0.5.0",
"version": "0.6.0",
"description": "Email inboxes for agents. Create inboxes, send and receive emails, automate email workflows, and create accounts with AgentID.",
"author": {
"name": "AgentMail",
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

All notable changes to the AgentMail plugin are documented here.

## 0.6.0 - 2026-10-06

- The `agentid` skill finds a named app with `get_app` and the app's slug (`firecrawl`), falling back to `search_apps` when the slug 404s, as the hosted MCP's instructions now direct. Later steps pass the `appId` it returns; `list_accounts` and `connect_app` accept the slug too, but the ID is the permanent one to store.
- To find an app for a need, the `agentid` skill filters `list_apps` by `category` (such as `search`, `scraping`, or `payments`), pages until `nextPageToken` is absent since filtered pages can come back short, and falls back to the unfiltered list for apps without categories.
- The `agentmail-mcp` skill mentions slugs and the category filter, and explains that a session keeps the tool list it connected with: a tool or parameter missing from the session needs a new session or a connector reconnect.
- Track AgentMail SDK TypeScript 0.5.40 and Python 2.0.12, CLI 1.9.0, and AgentMail Toolkit TypeScript 0.11.0. The signature fixtures cover inbox `status` (pause and resume) and the `apps.list` category filter.

## 0.5.0 - 2026-10-02

- AgentID calls the services an agent creates accounts at "apps" now, not "providers". The `agentid` and `agentmail-mcp` skills use the renamed hosted MCP tools: `list_apps`, `search_apps`, `get_app`, and `connect_app` replace `list_providers`, `search_providers`, `get_provider`, and `connect_provider`, with no aliases. They take `appId` and return `appId` and `appName`. `list_accounts` keeps its name.
Expand Down
10 changes: 5 additions & 5 deletions compatibility.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"verifiedAt": "2026-10-02",
"verifiedAt": "2026-10-06",
"agentmail": {
"typescript": "0.5.35",
"python": "2.0.8"
"typescript": "0.5.40",
"python": "2.0.12"
},
"cli": "1.8.0",
"cli": "1.9.0",
"toolkit": {
"typescript": "0.10.0",
"typescript": "0.11.0",
"python": "0.3.0"
}
}
14 changes: 10 additions & 4 deletions skills/agentid/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ The goal is almost never the sign-in itself. It is a working account the agent c

## Create an account

1. **Find the app.** Call `search_apps` with the name. One match: use it. Several: show name, description, and ID, and ask. Never pick between look-alike names yourself. No match and no ID: see [Not on AgentID](#not-on-agentid). If the user gave an app ID, skip search and call `get_app`; list and search show only the curated catalog, but any registered app resolves by ID and can be connected once it has a sign-in entry point.
1. **Find the app.**
- The user named the app: call `get_app` with its slug, the name lowercased without spaces or punctuation (`firecrawl`). A catalog app resolves in one call.
- The slug 404s: call `search_apps` with the name. One match: use it. Several: show name, description, and ID, and ask. Never pick between look-alike names yourself. No match: see [Not on AgentID](#not-on-agentid).
- The user gave an app ID: call `get_app` with it. List, search, and slugs cover only the curated catalog, but any registered app resolves by ID and can be connected once it has a sign-in entry point.

From here on, pass the `appId` that `get_app` returned. `list_accounts` and `connect_app` also accept the slug, but the ID is permanent: use it in anything you store or report.
2. **Pick the inbox that will own the account.** The inbox is the agent's identity at the app.
- The user named one: use it.
- The organization has one inbox (`list_inboxes`): use it and say which.
Expand All @@ -48,7 +53,7 @@ After the account exists, do what the user came for:

## Find an app for a need

`search_apps` matches names only, so a need like "web search" or "a database" will not match. Page through `list_apps` and match descriptions to the need. Offer the one to three best fits with a one-line description each, and any sign-up cap. Let the user choose, then [create an account](#create-an-account).
`search_apps` matches names only, so a need like "web search" or "a database" will not match. Call `list_apps` with the `category` that fits the need (such as `search`, `scraping`, `browser`, `data`, or `payments`; the tool schema lists every value), and match descriptions to the need. A filtered page can hold fewer apps than the limit while more remain: page until `nextPageToken` is absent, and reuse a `pageToken` only with the category it came from. Apps carry up to three `categories` and some carry none, so if the category comes up empty or close, page through `list_apps` without one before saying nothing fits. Offer the one to three best fits with a one-line description each, and any sign-up cap. Let the user choose, then [create an account](#create-an-account).

## Sign back in

Expand All @@ -62,7 +67,7 @@ Signing in is the same call as creating an account: `connect_app` with the inbox

## Not on AgentID

If search and the full list both miss and the user has no app ID, say the service is not available through AgentID. Then offer:
If the slug, search, and the full list all miss and the user has no app ID, say the service is not available through AgentID. Then offer:

- a catalog app that meets the same need, or
- that the user signs up on the app's own site with the inbox address as the email. You can read the verification email for them with check-email.
Expand All @@ -82,7 +87,8 @@ Do not fill in a third-party sign-up form on your own, and never solve a CAPTCHA
- **403 `missing_permission`**: the credential lacks `app_connect`, or the organization is not verified yet. The user can enable `app_connect` on the API key in the AgentMail console; do not look for another key.
- **404**: read which resource the error names before asking the user anything.
- **Inbox**: the inbox is not in the organization, or not in the credential's scope. Check the inbox.
- **App** from `get_app`: no app is registered under that ID. Check the ID with the user; do not guess another.
- **App** from `get_app` with a slug: no catalog app has that slug. Fall back to `search_apps` with the name.
- **App** from `get_app` with an ID: no app is registered under that ID. Check the ID with the user; do not guess another.
- **App** from `connect_app` for an app that `get_app` resolves: the app has no working sign-in entry point yet. Tell the user it cannot be connected right now.
- With `acceptDisclosure: true`, the app may not support accepting the disclosure up front. Retry once without it.
- To stop an inbox from signing in to an app, or to revoke a sign-in key, point the user to https://docs.agentmail.to/agentid-sign-in. The MCP server has no tool for either.
Expand Down
3 changes: 2 additions & 1 deletion skills/agentmail-mcp/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ MCP clients get the tool catalog and schemas live from the hosted runtime; do no
The catalog covers more than mail. Point users at these groups when they ask what the connector can do:

- **Inboxes, threads, messages, drafts, attachments, and allow/block lists** — the mail workflows in the sibling action skills.
- **AgentID apps and accounts** — `list_apps`, `search_apps`, `get_app`, `connect_app`, and `list_accounts` create accounts for an agent at third-party apps (for example "create an account at Firecrawl") and show where each inbox already has one. Use the `agentid` skill for that workflow.
- **AgentID apps and accounts** — `list_apps`, `search_apps`, `get_app`, `connect_app`, and `list_accounts` create accounts for an agent at third-party apps (for example "create an account at Firecrawl") and show where each inbox already has one. Catalog apps can be named by slug (`firecrawl`), and `list_apps` filters by category. Use the `agentid` skill for that workflow.
- **Agent sign-up** — `agent_attach_human` and `agent_verify` lift an unverified agent organization's limits.

## Stdio Compatibility
Expand All @@ -103,6 +103,7 @@ For a stdio-only client, use the supported npm or PyPI `agentmail-mcp` package.
## Troubleshoot

- A 404 usually means the URL is missing `/mcp`.
- A tool or parameter in the published manifest is missing from the session (for example `list_apps` has no `category`): the hosted server does not announce catalog changes, so a session keeps the tool list it had at connect. Start a new session or reconnect the connector.
- "Invalid API key" or a 401 with API-key auth usually means the key is wrong, revoked, lacks the necessary permissions, or `AGENTMAIL_API_KEY` was not available to the client process.
- "Unauthorized" or a 401 with OAuth usually means the sign-in is incomplete or the session expired — drop any `apiKey` query param and let the client complete the browser-based OAuth flow instead.
- Use the full `am_` key value and prefer the narrowest suitable organization, pod, or inbox scope.
Expand Down
9 changes: 9 additions & 0 deletions tests/sdk_typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ async function typecheckCurrentSdk(client: AgentMailClient): Promise<void> {
await client.inboxes.list({ limit: 20 });
await client.inboxes.get(inbox.inboxId);
await client.inboxes.update(inbox.inboxId, { displayName: "Customer Support" });
const paused = await client.inboxes.update(inbox.inboxId, { status: "paused" });
void (paused.status === "paused");
await client.inboxes.update(inbox.inboxId, { status: "active" });
await client.inboxes.create({ username: "staging", status: "paused" });

const apps = await client.apps.list({ category: "search", limit: 20 });
for (const app of apps.apps) {
void app.categories;
}

const sent = await client.inboxes.messages.send(inbox.inboxId, {
to: ["customer@example.com"],
Expand Down
4 changes: 3 additions & 1 deletion tests/test_sdk_signatures.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Check documented Python calls against agentmail 0.5.6 signatures."""
"""Check documented Python calls against the agentmail version pinned in compatibility.json."""

import inspect

Expand All @@ -16,6 +16,8 @@ def params(callable_object: object) -> set:
assert "request" in create_params
assert "username" not in create_params
assert "client_id" not in create_params
assert {"inbox_id", "display_name", "status", "metadata"} <= params(client.inboxes.update)
assert {"limit", "page_token", "category"} <= params(client.apps.list)

assert {"inbox_id", "to", "subject", "text"} <= params(client.inboxes.messages.send)
assert {"inbox_id", "message_id"} <= params(client.inboxes.messages.get)
Expand Down
Loading