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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ Visit the [Carta Developer Platform website here](https://docs.carta.com/api-pla
| Plugin | Description |
|--------|-------------|
| [carta-cap-table](plugins/carta-cap-table) | Skills and MCP server for querying Carta cap tables, grants, SAFEs, 409A valuations, waterfall scenarios, and more |
| [carta-fund-admin](plugins/carta-fund-admin) | Skills and MCP server for querying Carta fund admin data, including NAV, performance, allocations, and regulatory reporting |
| [carta-crm](plugins/carta-crm) | Manage the Carta CRM conversationally β€” search, add, update, and enrich investors, companies, contacts, deals, notes, and fundraisings via the public API |
| [carta-investors](plugins/carta-investors) | Skills and MCP server for querying Carta fund admin data, including NAV, performance, allocations, and regulatory reporting |
6 changes: 3 additions & 3 deletions plugins/carta-crm/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "carta-crm",
"displayName": "Carta CRM",
"version": "0.5.1",
"description": "Add investors, companies, contacts, deals, and notes to the Carta CRM via the public API",
"version": "0.6.0",
"description": "Manage the Carta CRM conversationally β€” search, add, update, and enrich investors, companies, contacts, deals, notes, and fundraisings via the public API",
"author": {
"name": "Ihar Valodzin",
"email": "ihar.valodzin@carta.com"
},
"keywords": ["carta", "crm", "investors", "companies", "contacts", "deals", "notes"]
"keywords": ["carta", "crm", "investors", "companies", "contacts", "deals", "notes", "fundraisings", "search", "enrich"]
}
40 changes: 34 additions & 6 deletions plugins/carta-crm/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Carta CRM Plugin

Add investors, companies, contacts, deals, and notes to the Carta CRM via the public API β€” conversationally.
Manage the Carta CRM conversationally β€” search, add, update, and enrich investors, companies, contacts, deals, notes, and fundraisings via the public API.

## Setup

Expand All @@ -26,10 +26,38 @@ Claude will collect any missing required information, then create the record(s)

## Skills

### Add records
| Skill | Trigger phrases |
|-------|----------------|
| `add-investor` | "/add-investor", "add investor", "add investor to Carta CRM", "create investor record", "add VC fund to CRM" |
| `add-company` | "/add-company", "add a company", "create company record", "add company to CRM", "upload company to Carta CRM" |
| `add-contact` | "/add-contact", "add a contact", "create contact record", "add contact to CRM", "save a contact", "upload contact to Carta CRM" |
| `add-deal` | "/add-deal", "add a deal", "create a deal", "log a deal", "add deal to CRM", "add deal to Carta CRM" |
| `add-note` | "/add-note", "add a note", "create a note", "log a note", "add note to CRM", "add note to Carta CRM" |
| `add-investor` | "add investor", "add investor to Carta CRM", "create investor record", "add VC fund to CRM" |
| `add-company` | "add a company", "create company record", "add company to CRM" |
| `add-contact` | "add a contact", "create contact record", "add contact to CRM", "save a contact" |
| `add-deal` | "add a deal", "create a deal", "log a deal", "add deal to CRM" |
| `add-note` | "add a note", "create a note", "log a note", "add note to CRM" |
| `add-fundraising` | "add a fundraising", "create a fundraising", "log a fundraising round" |

### Search & retrieve
| Skill | Trigger phrases |
|-------|----------------|
| `search-investors` | "find an investor", "search investors", "look up an investor" |
| `search-companies` | "find a company", "search companies", "look up a company" |
| `search-contacts` | "find a contact", "search contacts", "look up a person" |
| `search-deals` | "find a deal", "search deals", "show me deals for [company]" |
| `search-notes` | "find a note", "search notes", "look up a note" |
| `search-fundraisings` | "find a fundraising", "search fundraisings", "show fundraising pipeline" |

### Update records
| Skill | Trigger phrases |
|-------|----------------|
| `update-investor` | "update an investor", "edit investor", "update investor details" |
| `update-company` | "update a company", "edit company", "update company details" |
| `update-contact` | "update a contact", "edit contact", "update contact details" |
| `update-deal` | "update a deal", "move deal to [stage]", "change deal stage" |
| `update-note` | "update a note", "edit note", "update note content" |
| `update-fundraising` | "update a fundraising", "edit fundraising", "update fundraising details" |

### Research & enrichment
| Skill | Trigger phrases |
|-------|----------------|
| `enrich-company` | "enrich this company", "look up company info", "research this company" |
| `lookup-fund-portfolio` | "look up portfolio of [fund]", "get portfolio companies for [fund website]" |
91 changes: 91 additions & 0 deletions plugins/carta-crm/skills/add-fundraising/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
name: add-fundraising
description: >
Creates one or more fundraising records in the Carta CRM via the public API.
Use this skill when the user says things like "add a fundraising", "create a fundraising",
"log a fundraising round", "add fundraising to CRM", "create fundraising record",
or "/add-fundraising". Collects fundraising information conversationally, then POSTs
it to the Carta CRM API.
allowed-tools:
- Bash
---

## Overview

Help the user create one or more fundraising records in the Carta CRM by calling
`POST /v1/fundraisings`. Collect the fundraising details conversationally, validate the
required fields, then make the API call using curl.

## Step 1 β€” Check credentials

Check that the required environment variables are set:

```bash
echo "API_KEY=${LISTALPHA_API_KEY:+set}"
```

If `LISTALPHA_API_KEY` is missing, tell the user:
> "You need to set the `LISTALPHA_API_KEY` environment variable to your Carta CRM API key before using this skill. You can add it in Claude's environment settings."

## Step 2 β€” Discover available custom fields (optional but recommended)

Call the custom fields endpoint to see what fields the tenant has configured for fundraisings:

```bash
curl -s -X GET "https://api.listalpha.com/v1/fundraisings/custom-fields" \
-H "Authorization: ${LISTALPHA_API_KEY}"
```

Use the returned field names as hints when collecting fundraising data. If the call
fails, proceed without it β€” custom fields are optional.

## Step 3 β€” Collect fundraising information

Ask the user for:
- **Name** (required) β€” the fundraising round name (e.g., "Acme Corp Series B", "Project Atlas Seed Round")
- **Additional fields** (optional) β€” any custom fields returned in Step 2

If the user has already provided details in their message, extract them directly
without re-asking.

## Step 4 β€” Create the fundraising via API

Build the request body:
```json
{
"name": "<fundraising name>",
"fields": {
"<field_key>": "<value>"
}
}
```

Omit `fields` entirely if no field data was provided.

Make the API call:
```bash
curl -s -X POST "https://api.listalpha.com/v1/fundraisings" \
-H "Authorization: ${LISTALPHA_API_KEY}" \
-H "Content-Type: application/json" \
-d '<json_body>'
```

## Step 5 β€” Report result

On success (HTTP 200), respond with:
> "Fundraising **{name}** created successfully (ID: `{id}`)."

On error, show the status code and error message from the response, and suggest fixes:
- **401** β€” API key is invalid or missing
- **400** β€” Check that `name` is provided and `fields` contains valid keys
- **500** β€” Server error; try again or contact support

## Adding multiple fundraisings

If the user wants to add multiple fundraisings at once, repeat Steps 3–5 for each
one. After all are done, summarize:
> "Created N fundraisings: [list of names with IDs]"

## Reference

See `references/api-reference.md` for endpoint details and field schema.
103 changes: 103 additions & 0 deletions plugins/carta-crm/skills/add-fundraising/references/api-reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Carta CRM Fundraising API Reference

## Authentication

All requests require an API key in the `Authorization` header (no `Bearer` prefix):

```
Authorization: <your-api-key>
```

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `LISTALPHA_API_KEY` | Yes | Your Carta CRM API key |

---

## Endpoints

### GET /v1/fundraisings/custom-fields

Returns the custom field schema configured for your tenant's fundraising records.
Use this to discover which field keys are valid before creating fundraisings.

**Example:**
```bash
curl -s "https://api.listalpha.com/v1/fundraisings/custom-fields" \
-H "Authorization: ${LISTALPHA_API_KEY}"
```

**Response:**
```json
{
"fields": [
{ "key": "amount", "label": "Amount", "type": "string" },
{ "key": "stage", "label": "Stage", "type": "string" },
{ "key": "status", "label": "Status", "type": "string" },
{ "key": "closeDate", "label": "Close Date", "type": "date" },
{ "key": "tags", "label": "Tags", "type": "array" }
]
}
```

> The actual fields returned depend on your tenant's configuration.

---

### POST /v1/fundraisings

Creates a new fundraising record.

**Request body:**
```json
{
"name": "Acme Corp Series B",
"fields": {
"amount": "50000000",
"stage": "Series B",
"status": "open",
"closeDate": "2026-06-30"
}
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | **Yes** | Fundraising round name |
| `fields` | object | No | Key/value map of custom fields |

**Success response (200):**
```json
{
"id": "64f1a2b3c4d5e6f7a8b9c0d1",
"name": "Acme Corp Series B",
"fields": {
"amount": "50000000",
"stage": "Series B"
}
}
```

**Error responses:**

| Status | Meaning |
|--------|---------|
| 400 | Bad request β€” `name` missing or invalid field keys |
| 401 | Unauthorized β€” invalid or missing API key |
| 500 | Internal server error |

---

### GET /v1/fundraisings

List or search existing fundraisings.

**Query params:** `search` (string), `limit` (number), `offset` (number)

**Example:**
```bash
curl -s "https://api.listalpha.com/v1/fundraisings?search=acme&limit=10" \
-H "Authorization: ${LISTALPHA_API_KEY}"
```
106 changes: 106 additions & 0 deletions plugins/carta-crm/skills/enrich-company/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
---
name: enrich-company
description: >
Researches a company by fetching its website and returning structured profile data.
Use this skill when the user says things like "enrich this company", "look up company info",
"research this company", "what does [domain] do", "get company details for [url]",
"find info on [company]", or "/enrich-company".
Input: target (domain name or website URL).
Output: structured JSON with name, industry, tags, description, and website.
Saves the result locally at ~/.carta-crm/enriched-companies/ for auditing.
user-invocable: false
allowed-tools:
- WebFetch
- WebSearch
- Bash
---

## Overview

Enrich a company profile by fetching its website and extracting key business information.
The result is returned as structured JSON and saved locally for auditing.

## Step 1 β€” Normalize the target URL

Take the `target` input and produce a clean `https://` URL:
- If it already starts with `http://` or `https://`, use it as-is.
- If it looks like a bare domain (e.g., `acme.com`), prepend `https://`.
- Strip any trailing paths β€” use only the root URL (e.g., `https://acme.com`).

Also extract the bare domain (e.g., `acme.com`) β€” you'll need it for the output filename.

## Step 2 β€” Fetch the company website

Use WebFetch to retrieve the homepage. Look for:
- Page `<title>` and `<meta name="description">` content
- `<h1>` / `<h2>` headings and hero/tagline text
- Any "About", "What we do", or "Our mission" sections

If the homepage returns insufficient content (e.g., a login wall, placeholder, or very sparse text),
also try fetching `[root-url]/about` as a fallback.

## Step 3 β€” Supplement with web search if needed

If the website alone doesn't clearly reveal the company's industry or what it does,
run a WebSearch for:

```
"[company name]" company what does it do
```

Use the top 2–3 results to fill in gaps β€” especially for `industry` and `description`.

## Step 4 β€” Extract structured data

From the gathered content, produce the following fields:

| Field | Type | Notes |
|-------|------|-------|
| `name` | string | Official company name (not the domain) |
| `industry` | string | Primary industry, e.g. "FinTech", "SaaS", "Healthcare IT", "Climate Tech" |
| `tags` | array of strings | 3–6 short topic tags, e.g. `["payments", "B2B", "API", "embedded finance"]` |
| `description` | string | 1–2 sentence plain-English summary of what the company does |
| `website` | string | Canonical root URL, e.g. `https://acme.com` |

Use specific, meaningful tags β€” avoid generic ones like "technology" or "software" on their own.

## Step 5 β€” Save the enrichment record

Write the JSON to a local audit file:

```bash
mkdir -p ~/.carta-crm/enriched-companies
cat > ~/.carta-crm/enriched-companies/[domain].json << 'ENDJSON'
{
"name": "...",
"industry": "...",
"tags": [...],
"description": "...",
"website": "..."
}
ENDJSON
```

Replace `[domain]` with the bare domain (e.g., `acme.com`).
Confirm the file was written with `echo $?` (should be 0).

## Step 6 β€” Return the result

Return the enrichment record as a JSON block, followed by the save path:

```json
{
"name": "...",
"industry": "...",
"tags": [...],
"description": "...",
"website": "..."
}
```

State: `Saved to ~/.carta-crm/enriched-companies/[domain].json`

## Handling multiple companies

If the user provides multiple targets, repeat Steps 1–5 for each one, then return all
results together and summarize: `Enriched N companies β€” saved to ~/.carta-crm/enriched-companies/`
Loading
Loading