# Acai

> Go CLI and MCP server that exposes Granola meeting intelligence as structured, queryable MCP resources for AI agents and automation pipelines

- **Type:** MCP server
- **Install:** `agentstack add mcp-felixgeelhaar-acai`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [felixgeelhaar](https://agentstack.voostack.com/s/felixgeelhaar)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [felixgeelhaar](https://github.com/felixgeelhaar)
- **Source:** https://github.com/felixgeelhaar/acai

## Install

```sh
agentstack add mcp-felixgeelhaar-acai
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# acai

  

[](https://goreportcard.com/report/github.com/felixgeelhaar/acai)
[](LICENSE)
[](https://github.com/felixgeelhaar/acai/releases)

**[Website](https://felixgeelhaar.github.io/acai/)** | **[Getting Started](#quick-start)** | **[Documentation](#mcp-server)**

Granola meeting intelligence for the MCP ecosystem. A Go CLI and MCP server that exposes [Granola](https://granola.ai) meetings, transcripts, summaries, and action items as structured MCP resources and tools — enabling AI agents to reason over meeting knowledge.

## Features

- **MCP Server** — Typed tools and resources for meetings, transcripts, action items, notes, and embeddings
- **CLI** — Authenticate, sync, search, export, annotate, and manage meetings from the terminal
- **Write-Back** — Agent-generated notes and action item updates persisted locally with outbox pattern for future upstream sync
- **Embedding Export** — Chunk meeting content by speaker turn, time window, or token limit and export as JSONL
- **Agent Policies** — Per-meeting ACL (allow/deny by tool + tags) and content redaction (emails, speakers, keywords, patterns)
- **Resilient** — Circuit breaker, retry with backoff, rate limiting, and timeouts on every API call via [Fortify](https://github.com/felixgeelhaar/fortify)
- **Cached** — SQLite local cache reduces API calls and enables offline access
- **Multi-Workspace** — Query meetings across multiple Granola workspaces
- **Event Streaming** — Real-time meeting events via domain event dispatcher
- **Webhook Support** — Push-based sync with HMAC-SHA256 signature validation

## Installation

### Homebrew

```bash
brew tap felixgeelhaar/tap
brew install acai
```

### Go install

```bash
CGO_ENABLED=1 go install github.com/felixgeelhaar/acai/cmd/acai@latest
```

> CGO is required for the SQLite driver.

### From source

```bash
git clone https://github.com/felixgeelhaar/acai.git
cd acai
make build
```

## Quick Start

```bash
# Authenticate with Granola
export ACAI_GRANOLA_API_TOKEN=gra_xxxxx
acai auth login --method api_token

# List recent meetings
acai list meetings

# Export a meeting as markdown
acai export meeting  --format md

# Add an agent note to a meeting
acai note add  "Key insight from analysis"

# Export meeting chunks for embedding
acai export embeddings --meetings , --strategy speaker_turn

# Start as MCP server (stdio, for Claude Code)
acai serve
```

## CLI Commands

```
acai
  auth
    login         Authenticate with Granola (--method oauth|api_token)
    status        Show current authentication status
  list
    meetings      List meetings (--format table|json, --source, --limit, --since, --until)
  export
    meeting       Export a meeting (--format json|md|text)
    embeddings    Export meeting chunks as JSONL (--meetings, --strategy, --max-tokens)
  note
    add           Add an agent note to a meeting
    list          List agent notes for a meeting (--format table|json)
    delete        Delete an agent note
  action
    complete      Mark an action item as completed
    update        Update an action item's text
  sync            Sync meetings from Granola API (--since)
  serve           Start MCP server on stdio
  version         Show version information
```

## MCP Server

When running as an MCP server (`acai serve`), the following tools and resources are exposed:

### Tools

| Tool | Description |
|------|-------------|
| `list_meetings` | Search and filter meetings with date, source, and text filters |
| `get_meeting` | Get full meeting details including summary and action items |
| `get_transcript` | Get the transcript with speaker utterances |
| `search_transcripts` | Full-text search across all meeting transcripts |
| `get_action_items` | Get action items from a specific meeting |
| `meeting_stats` | Aggregated meeting statistics with interactive D3.js dashboard |
| `list_workspaces` | List all Granola workspaces |
| `add_note` | Add an agent note to a meeting |
| `list_notes` | List agent notes for a meeting |
| `delete_note` | Delete an agent note |
| `complete_action_item` | Mark an action item as completed |
| `update_action_item` | Update an action item's text |
| `export_embeddings` | Export meeting content as chunks for embedding generation |

### Resources

| URI Pattern | Description |
|-------------|-------------|
| `meeting://{id}` | Full meeting details as JSON |
| `transcript://{meeting_id}` | Transcript utterances as JSON |
| `note://{meeting_id}` | Agent notes for a meeting as JSON |
| `workspace://{id}` | Workspace details as JSON |
| `ui://meeting-stats` | Interactive meeting statistics dashboard (HTML) |

### Claude Code Integration

Add to your Claude Code MCP configuration (`~/.claude/mcp.json`):

```json
{
  "mcpServers": {
    "granola": {
      "command": "acai",
      "args": ["serve"],
      "env": {
        "ACAI_GRANOLA_API_TOKEN": "gra_xxxxx"
      }
    }
  }
}
```

## Agent Policies

Control what data AI agents can access and how sensitive content is handled. Create a YAML policy file and set the `ACAI_POLICY_FILE` environment variable:

```yaml
default_effect: allow
rules:
  - name: block-confidential-transcripts
    effect: deny
    tools: [get_transcript, export_embeddings]
    conditions:
      meeting_tags: [confidential]

redaction:
  enabled: true
  rules:
    - type: emails
      replacement: "[EMAIL]"
    - type: speakers
      replacement: "Speaker {n}"
    - type: keywords
      keywords: [salary, confidential]
      replacement: "[REDACTED]"
    - type: patterns
      pattern: '\d{3}-\d{2}-\d{4}'
      replacement: "[SSN]"
```

**ACL** — First-match-wins rule evaluation. Deny rules block tool execution for meetings matching tag conditions.

**Redaction** — Applied to all tool responses. Emails replaced by regex, speakers anonymized consistently (same person always maps to same "Speaker N"), keywords matched case-insensitively with word boundaries, custom regex patterns supported.

## Configuration

Configuration uses 12-factor principles: sensible defaults with environment variable overrides.

| Variable | Default | Description |
|----------|---------|-------------|
| `ACAI_GRANOLA_API_URL` | `https://api.granola.ai` | Granola API base URL |
| `ACAI_GRANOLA_API_TOKEN` | — | API token for authentication |
| `ACAI_MCP_TRANSPORT` | `stdio` | MCP transport (`stdio` or `http`) |
| `ACAI_MCP_HTTP_PORT` | `8080` | HTTP port when using HTTP transport |
| `ACAI_CACHE_TTL` | `15m` | Local cache time-to-live |
| `ACAI_LOGGING_LEVEL` | `info` | Log level (`debug`, `info`, `warn`, `error`) |
| `ACAI_LOGGING_FORMAT` | `console` | Log format (`console` or `json`) |
| `ACAI_WEBHOOK_SECRET` | — | HMAC secret for webhook signature validation |
| `ACAI_POLICY_FILE` | — | Path to YAML policy file (enables ACL + redaction) |

## Architecture

The project follows strict Domain-Driven Design with hexagonal architecture:

```
cmd/acai/main.go                     Composition root (DI wiring)

internal/
  domain/                             Pure business logic, zero dependencies
    meeting/                          Meeting aggregate, value objects, events, chunks
    annotation/                       Agent notes bounded context
    policy/                           ACL rules, redaction config value objects
    auth/                             Token, credential, auth service port
    workspace/                        Workspace aggregate

  application/                        Use cases (one per file)
    meeting/                          ListMeetings, GetMeeting, CompleteActionItem, ...
    annotation/                       AddNote, ListNotes, DeleteNote
    embedding/                        ExportEmbeddings, chunking strategies
    auth/                             Login, CheckStatus
    workspace/                        ListWorkspaces, GetWorkspace
    export/                           ExportMeeting

  infrastructure/                     External adapters
    granola/                          Granola API client + repository (anti-corruption layer)
    resilience/                       Fortify: circuit breaker, retry, rate limit, timeout
    cache/                            SQLite local cache (repository decorator)
    localstore/                       SQLite local store for notes + action item overrides
    outbox/                           Outbox dispatcher for write events
    policy/                           YAML loader, redaction engine
    events/                           Domain event dispatcher + MCP notifier
    sync/                             Background polling sync manager
    webhook/                          HMAC-SHA256 webhook handler
    auth/                             File-based token storage
    config/                           12-factor configuration

  interfaces/                         Inbound adapters
    mcp/                              MCP server with tools, resources, policy middleware
    cli/                              CLI commands (cobra)
```

### Decorator Chain

```
Read path:   Granola API → Resilient Repo → Cached Repo → Use Cases
Write path:  Use Cases → Local SQLite Store → Outbox Dispatcher → Event Dispatcher
```

### Key Libraries

| Library | Purpose |
|---------|---------|
| [felixgeelhaar/mcp-go](https://github.com/felixgeelhaar/mcp-go) | MCP server framework with typed tools, resources, and multi-transport |
| [felixgeelhaar/fortify](https://github.com/felixgeelhaar/fortify) | Resilience patterns: circuit breaker, retry, rate limit, timeout |
| [spf13/cobra](https://github.com/spf13/cobra) | CLI framework |
| [mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) | SQLite driver for local cache and local store |
| [gopkg.in/yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) | YAML parsing for policy files |

## Development

```bash
# Run tests (requires CGO for SQLite)
make test

# Run tests with race detection and coverage
make test-race

# Build
make build

# Lint
make lint

# Clean
make clean
```

### Test Coverage

377 tests with 0 race conditions across all packages:

| Layer | Coverage |
|-------|----------|
| Domain (meeting, annotation, policy, auth, workspace) | 94-100% |
| Application (meeting, annotation, embedding, auth, workspace) | 86-100% |
| Infrastructure (granola, resilience, cache, policy, localstore, outbox) | 85-97% |
| Interfaces (mcp, cli) | 74-81% |

## Website

The project website at [felixgeelhaar.github.io/acai](https://felixgeelhaar.github.io/acai/) is built with Astro, Vue, and Tailwind CSS v4. Source lives in the `site/` directory.

```bash
# Development
cd site && npm install && npm run dev

# Production build
npm run build && npm run preview
```

Deployed automatically to GitHub Pages via `.github/workflows/pages.yml` on push to `main`.

## License

[MIT](LICENSE)

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [felixgeelhaar](https://github.com/felixgeelhaar)
- **Source:** [felixgeelhaar/acai](https://github.com/felixgeelhaar/acai)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-felixgeelhaar-acai
- Seller: https://agentstack.voostack.com/s/felixgeelhaar
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
