Back to the catalog

Attrove

Catch conversations going quiet — watch outcomes and search Gmail, Slack, and meetings. One MCP.

Open source Open in the app JSON README (API)

About

Catch conversations going quiet — watch outcomes and search Gmail, Slack, and meetings. One MCP.

Details

Kind
MCP servers
Topic
Communication
Publisher
com.attrove
Origin
official
Category
ferramentas
Transport
http
Version
0.6.0
Repository state
sumiu
Added
2026-08-29 03:01:00
Updated
2026-09-03 03:00:17
Origin id
com.attrove/mcp

README

# @attrove/mcp

Catch the conversations going quiet. Attrove watches work across Gmail, Slack, Outlook, Google Calendar, and meetings — watched outcomes (Goals) flag silence and risk with cited evidence, and one MCP gives your AI client search and answers over the same stream. Works in Codex, Claude Code, Cursor, Claude Desktop, and ChatGPT.

## Installation

```bash
npm install @attrove/mcp
# or
yarn add @attrove/mcp
# or
pnpm add @attrove/mcp
```

## Quick Start

### Recommended: Attrove CLI

Use the CLI as the install layer for hosted OAuth MCP:

```bash
npx @attrove/cli install claude-code
```

That writes a remote MCP config pointed at `https://api.attrove.com/mcp`, lets Codex, Claude Code, Cursor, and Claude Desktop discover OAuth, and avoids embedding `sk_` secrets directly into client config files.

Other hosted install commands:

```bash
npx @attrove/cli install cursor
npx @attrove/cli install claude-desktop
npx @attrove/cli install codex
```

Claude Code defaults to project scope (`.mcp.json`). Cursor, Claude Desktop, and Codex default to user scope.

### Codex

Use the CLI to add the hosted MCP endpoint to `~/.codex/config.toml`:

```bash
npx @attrove/cli install codex
```

Then complete OAuth:

```bash
codex mcp login attrove
```

Codex uses a local loopback callback during OAuth, then stores credentials in the configured Codex credential store.

After restarting Codex or reloading tool discovery, verify that the raw hosted server exposes tools such as `attrove_notes`, `attrove_create_goal`, and `attrove_list_goals`. If you only see `mcp__codex_apps__attrove` tools, you are seeing the OpenAI Apps connector named Attrove, not the raw hosted MCP server.

### Verify the first useful answer

After OAuth completes in your AI client, ask:

> "Use Attrove to list my connected integrations."

You should see at least one connected source such as Gmail, Slack, Outlook,
Google Calendar, Google Meet, or Teams. If nothing is connected yet, the agent
calls `attrove_connect` to get one link — open it, connect a source,
and the agent re-checks with `attrove_integrations`. No dashboard visit is
required. Then ask:

> "What needs my attention this week? Include the source messages or meetings you used."

That second prompt is the activation check: it should return an answer grounded
in your connected context, not just confirm that the MCP server is installed.

### Advanced Local Fallback

Use the local stdio server only if you explicitly want local credential-backed MCP:

```bash
npx @attrove/cli login
npx @attrove/cli local install claude-code
npx @attrove/cli connect gmail
```

### Claude Desktop

Claude Desktop supports two transport options:

**HTTP transport (recommended)** — uses OAuth discovery, no API key copy/paste needed:

```json
{
  "mcpServers": {
    "attrove": {
      "type": "streamable-http",
      "url": "https://api.attrove.com/mcp"
    }
  }
}
```

Prefer `npx @attrove/cli install claude-desktop` to write this for you.

**Legacy stdio transport** — use only if you explicitly want local env-based auth:

```json
{
  "mcpServers": {
    "attrove": {
      "command": "npx",
      "args": ["-y", "@attrove/mcp@latest"],
      "env": {
        "ATTROVE_SECRET_KEY": "sk_...",
        "ATTROVE_USER_ID": "user-uuid"
      }
    }
  }
}
```

### Cursor

Preferred hosted install:

```bash
npx @attrove/cli install cursor
```

Or use Cursor's install URL from a partner-issued connect session. Manual remote config also works:

```json
{
  "mcpServers": {
    "attrove": {
      "type": "http",
      "url": "https://api.attrove.com/mcp"
    }
  }
}
```

On first use, Cursor discovers OAuth via `.well-known/oauth-protected-resource` and sends the user through the Attrove connect flow automatically.

### Claude Code (Terminal)

Preferred hosted install:

```bash
npx @attrove/cli install claude-code
```

If you are onboarding a provisioned end user from a terminal or agent, use the durable connect-session handoff:

```bash
npx @attrove/cli connect --session <session-id>
```

Advanced local fallback is still supported:

```bash
npx @attrove/cli login
npx @attrove/cli local install claude-code
```

### ChatGPT (beta / fallback)

ChatGPT and other AI assistants that support MCP connectors can connect via the hosted HTTP endpoint.

> ChatGPT's MCP install UX is still evolving. Treat it as a fallback path behind Codex, Claude Code, Cursor, and Claude Desktop.

**Basic requirement:** add `https://api.attrove.com/mcp` as a remote MCP server. OAuth-capable clients should discover the authorization flow automatically.

**Example setup steps (may vary):**
1. Open ChatGPT Settings → **Connectors** → Enable **Developer Mode**
2. Click **Create Connector** and configure:
   - **Name:** `Attrove`
   - **URL:** `https://api.attrove.com/mcp`
3. If ChatGPT requests auth details manually instead of following OAuth discovery, use this path only as a temporary compatibility fallback.

Once connected, you can ask ChatGPT questions like:
- "What emails need my attention this week?"
- "Summarize my meeting with the marketing team"
- "What has John been asking about lately?"

### Direct CLI Usage

```bash
npx @attrove/cli install claude-code
npx @attrove/cli install codex

# advanced local fallback:
npx @attrove/cli login
npx @attrove/cli local install claude-code
npx @attrove/cli connect gmail

# or manual env injection:
ATTROVE_SECRET_KEY=sk_... ATTROVE_USER_ID=user-uuid npx @attrove/mcp
```

## Common Use Cases

Once connected, you can ask your AI assistant natural language questions. Here are some examples:

**Outcome watching:**
> "Watch the Acme renewal until it closes — flag it if the thread goes quiet for 5 days"

**Needs attention:**
> "Which of my watched outcomes are at risk right now, and what's the evidence?"

**Meeting prep:**
> "What context do I need for my 2pm meeting with the marketing team?"

**Email follow-ups:**
> "Are there any emails from last week that I haven't responded to?"

**Project status:**
> "What's the latest on the Q4 roadmap discussions?"

**People search:**
> "What has John from Acme Corp been asking about recently?"

**Historical context:**
> "Find the thread where we discussed the pricing changes last month"

## Available Tools

### Goal tools — watched outcomes

Goals are how Attrove catches work going quiet: define the outcome once, and the evaluator keeps checking the communication stream, updating health with cited evidence. Ten tools cover the loop:

- `attrove_create_goal` — create a goal with a watch scope (`entity_ids`, `seed_query`, or `keywords`), optional success criteria, deadline, and a `silence_condition` that flags the goal when its conversations go quiet too long
- `attrove_list_goals` — list goals, optionally filtered by lifecycle or health (`health=at_risk` surfaces what needs attention)
- `attrove_get_goal_status` — get a goal with its latest status snapshot (health, risk signals, cited evidence, suggested next actions) and evaluator run
- `attrove_evaluate_goal` — queue a fresh evaluator run for an active goal
- `attrove_add_goal_note` — attach a manual note to a goal as evidence
- `attrove_confirm_goal_status` — manually confirm or override lifecycle/health with a reason (lifecycle never changes autonomously)
- `attrove_goal_events` — tail goal lifecycle transitions with cursor pagination and a composite watermark
- `attrove_acknowledge_goal` — acknowledge that a goal's silence is expected and suppress the silence-driven escalation until a horizon (or until real activity arrives, whichever is first)
- `attrove_clear_goal_acknowledgment` — clear an active acknowledgment and resume silence monitoring immediately
- `attrove_draft_goal_follow_up` — draft an evidence-grounded follow-up email for a quiet goal (read-only; nothing is sent or persisted)

**Example prompts:**
- "Watch the Acme renewal until it closes — alert if it goes quiet for 5 days"
- "Which goals are at risk? Show me the evidence"
- "Mark the Q3 security review goal complete — the sign-off email arrived"

### `attrove_query`

Ask questions about the user's communications and get AI-generated answers.

**Parameters:**
- `query` (required): The question to ask
- `integration_ids` (optional): Filter to specific integration IDs (array of UUID strings)
- `include_sources` (optional): Include source snippets in the response
- `instructions` (optional): Custom instructions for the AI — controls output format, filtering, and behavior. Takes priority over default style. Max 20,000 chars
- `context` (optional): Authoritative reference data for answer generation. Treated as ground truth by the AI. Influences query rewriting but not used for vector search. Max 20,000 chars

**Example prompts:**
- "What did Sarah say about the Q4 budget?"
- "Summarize my meeting with the engineering team"
- "What are the action items from yesterday's standup?"
- "When is my next meeting with the product team?"
- "What context do I need before my 3pm call?"

### `attrove_search`

Search for specific messages or conversations.

**Parameters:**
- `query` (required): The search query
- `after_date` (optional): Only messages after this date (YYYY-MM-DD)
- `before_date` (optional): Only messages before this date (YYYY-MM-DD)
- `sender_domains` (optional): Filter by sender domains
- `include_body_text` (optional): Include message content in results (default: true, bodies truncated to 1000 characters)

**Example prompts:**
- "Find all emails about the product launch"
- "Show me conversations with the marketing team"
- "Search for messages mentioning the deadline extension"
- "Find discussions with acme.com from last month"

### `attrove_integrations`

List the user's connected integrations.

**Parameters:** None

**Example prompts:**
- "What services are connected?"
- "Show me my integrations"

### `attrove_connect`

Create one link the user opens to connect a source (Gmail, Outlook, Slack, Google Calendar, Google Meet, or Microsoft Teams) to their Attrove account. Use it when `attrove_integrations` shows no sources, when a query comes back empty because nothing is connected yet, or when the user asks to add a source. Show the user the returned link. After they finish, call `attrove_integrations` to confirm the source is syncing, then continue. The link is tied to the authenticated user, expires after 7 days, and is safe to return again on later calls.

**Parameters:**
- `provider` (optional): Preselect a source (`gmail`, `outlook`, `slack`, `google_calendar`, `google_meet`, `teams`). Omit to open a source picker.

**Example prompts:**
- "Connect my Gmail"
- "I haven't connected anything yet — help me get set up"
- "Add Slack to my account"

### `attrove_events`

List calendar events from the user's connected calendar accounts.

**Parameters:**
- `start_date` (optional): Start of date range (YYYY-MM-DD)
- `end_date` (optional): End of date range (YYYY-MM-DD)
- `limit` (optional): Max events to return (default 25, max 100)

**Example prompts:**
- "What's on my calendar today?"
- "Do I have any meetings tomorrow?"
- "When is my next meeting with Sarah?"
- "What's my schedule for Friday?"

### `attrove_meetings`

List meetings with AI-generated summaries and action items.

**Parameters:**
- `start_date` (optional): Start of date range (YYYY-MM-DD)
- `end_date` (optional): End of date range (YYYY-MM-DD)
- `provider` (optional): Filter by meeting provider (`google_meet`, `zoom`, `teams`, `manual_meetings`)
- `limit` (optional): Max meetings to return (default 10, max 50)

**Example prompts:**
- "What happened in my last meeting?"
- "Summarize yesterday's standup"
- "What are the action items from the product review?"
- "Show me my recent meetings"

### `attrove_notes`

List notes — analyst observations, partner-pushed context, and session summaries that have been RAG-indexed into the user's context.

**Parameters:**
- `ref_type` (optional): Filter by reference type (`message`, `meeting`, `event`, `entity`, `goal`)
- `ref_id` (optional): Filter by referenced item ID (e.g. `msg_xxx`, `mtg_xxx`, `gol_xxx`). Must be provided together with `ref_type`.
- `limit` (optional): Max notes to return (default 20, max 100)

**Example prompts:**
- "What notes do I have about the pricing discussion?"
- "Show me notes linked to yesterday's standup"
- "Have we captured any observations on this thread?"

### `attrove_push_note`

Save a note to the user's Attrove context. Notes are RAG-indexed and become queryable via `attrove_query` and `attrove_search`, enabling AI assistants to capture decisions and session context that persists across conversations.

For meeting and note pushes, Attrove trims titles and limits them to 500 Unicode code points. A `queued` response means Attrove accepted the push for asynchronous indexing; the content is not query-ready yet.

**Parameters:**
- `body` (required): Note content (server-enforced max 10,000 characters)
- `title` (optional): Short title for the note (max 500 Unicode code points after trimming)
- `ref_type` (optional): Link to an existing item type (`message`, `meeting`, `event`, `entity`, `goal`). Must be provided together with `ref_id`.
- `ref_id` (optional): ID of the item to link (e.g. `msg_xxx`, `mtg_xxx`, `evt_xxx`, `ent_xxx`, `gol_xxx`)
- `external_id` (optional): Dedup key. Re-pushing with the same `external_id` updates the existing note instead of creating a new one.

**Example prompts:**
- "Save a note that we decided to use Redis for caching"
- "Capture the takeaways from this meeting as a note"
- "Remember that the Q4 revenue trend suggests we should pull in the launch"

### `attrove_push_meeting`

Save a meeting transcript or summary to the user's Attrove context. Use this when another meeting MCP (Otter, Read.ai, Fireflies, Fathom) or a user-shared transcript (Granola export, voice memo, manual notes) has meeting content that should become queryable alongside Gmail, Slack, calendar, and native meeting data.

**Parameters:**
- `title` (required): Meeting title (max 500 Unicode code points after trimming)
- `start_time` (required): ISO 8601 datetime with UTC `Z` or a numeric offset (for example, `2026-05-26T12:00:00-07:00`)
- `end_time` (required): ISO 8601 datetime with UTC `Z` or a numeric offset (for example, `2026-05-26T12:25:00-07:00`)
- `transcript` (optional): Full meeting transcript
- `summary` (optional): Detailed summary
- `short_summary` (optional): 1-3 sentence summary
- `attendees` (optional): Attendee objects with `name` and optional `email`
- `action_items` (optional): Action item objects with `text` and optional `assignee`
- `external_id` (optional): Dedup key. Re-pushing with the same `external_id` updates the existing meeting.

**Example prompts:**
- "Save this Granola transcript into Attrove"
- "Import the Fireflies meeting summary so I can query it later"
- "Add these manual meeting notes to my communication context"

### `attrove_delete_meeting`

Reversibly archive a pushed meeting from the user's Attrove context. The meeting is hidden from `attrove_meetings`, `attrove_search`, and `attrove_query`, and can be restored by re-pushing the same `external_id`.

**Parameters:**
- `id` (optional): Opaque meeting ID (`mtg_xxx`)
- `external_id` (optional): External ID used when the meeting was pushed

Provide exactly one of `id` or `external_id`.

**Example prompts:**
- "Archive the duplicate meeting I pushed with external_id standup-2026-06-02"
- "Remove this test meeting from my Attrove context"

### `attrove_delete_note`

Reversibly archive a note from the user's Attrove context. The note is hidden from `attrove_notes`, `attrove_search`, and `attrove_query`, and can be restored by re-pushing the same `external_id`.

**Parameters:**
- `id` (optional): Opaque note ID (`note_xxx`)
- `external_id` (optional): External ID used when the note was pushed

Provide exactly one of `id` or `external_id`.

**Example prompts:**
- "Archive the duplicate note with external_id crm-note-123"
- "Remove this test note from my Attrove context"

### Commitment tools — watched obligations

Commitments are agent accountability that outlives the session: register a promise, delegation, or handoff once, and Attrove watches it until the expected signal arrives — auto-resolving it when the arrival is detectable, and escalating to a human when the signal silently never comes. Three tools cover the loop:

- `attrove_watch_commitment` — register an obligation (a counterparty, an expected signal type, and a `check_after`/`due_at` horizon make it an active watch). Underspecified registrations are kept as low-confidence suggestions that never escalate — the response lists what was missing. Pass `client_dedup_key` to make retries safe: the same key with the same payload returns the original commitment, and the same key with a different payload is rejected
- `attrove_check_my_outcomes` — read back open commitments (`watching`/`at_risk`, optionally `suggested`) at the start of a session, soonest-due first, with cursor pagination. This is a to-do ledger, not memory: it never returns resolved history
- `attrove_resolve_commitment` — record what actually happened: `satisfied` (the signal arrived), `silent_drop` (it never came and the obligation is dead), `dismissed` (not a real commitment), or `at_risk` (flag for attention without closing). Terminal states are immutable

Only register real obligations — a beneficiary, an expected future signal, and a horizon — not ordinary implementation steps or speculative plans.

**Example prompts:**
- "I promised Dana the revised proposal by Friday — watch that commitment and escalate to me if her reply never comes"
- "Check my open commitments and tell me what's due this week"
- "The sign-off email arrived — resolve the proposal commitment as satisfied"

## Environment Variables

These are only required for stdio / manual installs. Remote HTTP MCP installs do not need them.

| Variable | Required | Description |
|----------|----------|-------------|
| `ATTROVE_SECRET_KEY` | Yes | Your Attrove secret key (`sk_...`) |
| `ATTROVE_USER_ID` | Yes | User ID to scope API calls |
| `ATTROVE_BASE_URL` | No | Custom API base URL |
| `ATTROVE_AGENT_ID` | No | Agent identity (name/slug) used as the default attribution for commitment tools |
| `ATTROVE_DEBUG` | No | Set to `true` for verbose error logging |

## Programmatic Usage

You can also use the server programmatically:

```typescript
import { createServer, startServer } from '@attrove/mcp';

// Create a server instance
const server = createServer({
  apiKey: 'sk_...',
  userId: 'user-uuid'
});

// Or start directly with stdio transport
await startServer({
  apiKey: 'sk_...',
  userId: 'user-uuid'
});
```

### HTTP Endpoint (Hosted)

For AI assistants that connect via HTTP, prefer adding the hosted endpoint directly and letting the client discover OAuth:

- MCP URL: `https://api.attrove.com/mcp`
- OAuth discovery: `https://api.attrove.com/.well-known/oauth-protected-resource`

Manual curl testing can still use bearer auth:

```bash
# Test the endpoint
curl -X POST https://api.attrove.com/mcp \
  -H "Authorization: Bearer sk_..." \
  -H "X-Attrove-User-Id: user-uuid" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
```

Or integrate in your own server using the HTTP handler:

```typescript
import { createHttpHandler } from '@attrove/mcp';

const handler = createHttpHandler(
  {
    apiKey: 'sk_...',
    userId: 'user-uuid',
    baseUrl: 'https://api.attrove.com', // optional: custom API endpoint
  },
  {
    enableJsonResponse: true, // optional: use JSON instead of SSE (default: true)
    timeoutMs: 30000, // optional: request timeout in ms (default: 30000)
  }
);

// With Fastify (recommended)
fastify.post('/mcp', async (request, reply) => {
  const result = await handler.handleRequest(request.raw, reply.raw, request.body);

  if (!result.handled) {
    // Handle timeout with 504, other errors with 500
    const statusCode = result.isTimeout ? 504 : 500;
    const userMessage = result.isTimeout
      ? 'Request timed out. Try a simpler query or reduce the scope.'
      : 'An unexpected error occurred. Please try again.';

    // Only send response if headers haven't been sent (e.g., during streaming)
    if (!reply.raw.headersSent) {
      reply.code(statusCode).send({
        success: false,
        error: { code: result.isTimeout ? 'REQUEST_TIMEOUT' : 'INTERNAL_ERROR', message: userMessage }
      });
    } else if (!reply.raw.writableEnded) {
      reply.raw.end(); // Ensure stream is closed
    }
    return;
  }

  // Optional: monitor cleanup failures for resource leak detection
  if (result.cleanupFailed) {
    console.warn('MCP cleanup failed - potential resource leak');
  }
});

// With raw Node.js HTTP server
import { createServer } from 'node:http';
const server = createServer(async (req, res) => {
  // Note: You'll need to parse the body yourself for raw HTTP
  const result = await handler.handleRequest(req, res);
  if (!result.handled) {
    res.writeHead(500, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: result.error }));
  }
});
```

## Getting API Credentials

1. Sign up at [attrove.com](https://attrove.com)
2. Create an organization in the dashboard
3. Generate an API key (`sk_...`)
4. Provision a user to get a user ID

```typescript
import { Attrove } from '@attrove/sdk';

const admin = Attrove.admin({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret'
});

// Create a user
const { id, apiKey } = await admin.users.create({
  email: 'user@example.com'
});

// Use `apiKey` as ATTROVE_SECRET_KEY and `id` as ATTROVE_USER_ID
```

## Troubleshooting

### "ATTROVE_SECRET_KEY environment variable is required"

Make sure you've set the environment variables correctly in your MCP configuration.

### Tools not showing up

1. Restart Codex, Claude, or Cursor after configuration changes
2. Check the MCP server logs for errors
3. Verify your API key is valid

### Debugging errors

Set `ATTROVE_DEBUG=true` to enable verbose error logging with stack traces:

```json
{
  "mcpServers": {
    "attrove": {
      "command": "npx",
      "args": ["-y", "@attrove/mcp@latest"],
      "env": {
        "ATTROVE_SECRET_KEY": "sk_...",
        "ATTROVE_USER_ID": "user-uuid",
        "ATTROVE_DEBUG": "true"
      }
    }
  }
}
```

### Rate limiting

The Attrove API has rate limits. If you're making many requests, you may need to wait before trying again.

## Requirements

- Node.js 18.0.0 or later

## AI-Friendly Documentation

For AI assistants and code generation tools, Attrove provides machine-readable documentation:

- **llms.txt**: `https://attrove.com/llms.txt` - Condensed API reference for LLMs
- **Examples**: `https://github.com/attrove/examples` - Example code with CLAUDE.md context

## Links

- [Documentation](https://attrove.com/docs)
- [API Reference](https://attrove.com/docs/api-reference)
- [TypeScript SDK](https://www.npmjs.com/package/@attrove/sdk)
- [Examples](https://github.com/attrove/examples)

## License

MIT

More