Back to the catalog

io.github.Kinnectd/a2me-mcp-server

Read-only A2Me family context tools for AI assistants (members, dates, activity, relationships)

Open source Repository Open in the app JSON README (API)

About

Read-only A2Me family context tools for AI assistants (members, dates, activity, relationships)

Details

Kind
MCP servers
Topic
No topic detected
Publisher
kinnectd
Origin
official
Category
ferramentas
Transport
http
Version
1.0.0
Open pull requests
2
Last push
2026-09-03T11:28:04Z
Repository state
ativo
Language
TypeScript
License
MIT
Added
2026-08-29 03:02:00
Updated
2026-08-29 03:02:00
Origin id
io.github.Kinnectd/a2me-mcp-server

README

# A2Me MCP Server

> **v1 · read-only.** A [Model Context Protocol](https://modelcontextprotocol.io) server that exposes **read-only, privacy-redacted** family-context tools for the [A2Me](https://a2me.app) family social platform — so assistants like Claude, ChatGPT, or KAI can answer "when is mom's birthday?" or help write a message to grandma, scoped to your own family.

Hosted at **`https://mcp.a2me.app/mcp`** and used in production for A2Me's [Connect a2me](https://a2me.app/features/ai-integration) feature.

## Connect from an AI assistant

In Claude or ChatGPT, add a **custom connector** using the URL:

```
https://mcp.a2me.app/mcp
```

You'll be sent through OAuth to sign in to A2Me and grant **read-only** access; the assistant then has family-aware context scoped to your account.

## Run it locally

```bash
npm install
npm run dev        # stdio transport, mock data by default
```

It runs on **stdio** by default (for local MCP clients) and supports a remote **HTTP** transport (`MCP_TRANSPORT=http`) for the hosted deployment. By default it uses **mock data** (`A2ME_USE_MOCK=true`); set `A2ME_API_URL` + `A2ME_USE_MOCK=false` to call a real API. See [`.env.example`](./.env.example).

## Available Tools

| Tool                              | Description                                                         |
| --------------------------------- | ------------------------------------------------------------------- |
| `get_family_members`              | Returns the user's family members with relationship labels          |
| `get_upcoming_family_dates`       | Birthdays, anniversaries, and events in the next N days             |
| `get_recent_family_activity`      | Recent posts, photos, videos, birthday cards                        |
| `get_person_profile`              | A family member's profile, interests, and activity summary          |
| `get_relationship_between_people` | How two family members are related                                  |
| `get_birthday_card_context`       | Context for writing a birthday card (memories, interests, tone)     |
| `find_family_member`              | Fuzzy search by name or relationship ("mom", "my grandmother")      |
| `answer_family_date_question`     | Natural language date questions ("When is mom's birthday?")         |
| `get_message_context_for_person`  | Context for writing a message with suggestions                      |
| `get_upcoming_events`             | Upcoming events with the user's RSVP status and RSVP counts         |
| `get_trip_overview`               | A trip's dates, roster, travel details (flights/lodging), itinerary |
| `get_life_story`                  | A family member's life story chapters (or recent story answers)     |
| `get_unanswered_story_questions`  | Unanswered story questions — interview prep for a visit             |
| `get_person_wishlist`             | A family member's wishlist for gift ideas                           |
| `search_family_memories`          | Keyword search over recent family posts and memories                |
| `whats_new`                       | Catch-up bundle: recent posts + what's coming up                    |

## Prompts

The server also exposes **prompts** — one-click starting points that appear as
connector commands in Claude (and suggestions in ChatGPT), so users get value without
knowing tool names. Each steers the assistant to the read-only tools above:

| Prompt                  | What it does                                           |
| ----------------------- | ------------------------------------------------------ |
| `write_birthday_card`   | Draft a birthday card grounded in a person's context   |
| `write_family_message`  | Draft a message for any occasion/tone                  |
| `family_catch_up`       | Summarize what's new with the family                   |
| `upcoming_family_dates` | List upcoming birthdays/anniversaries with suggestions |
| `about_person`          | Warm summary of a family member and how you're related |

The `person` argument on these prompts **autocompletes from your family roster**
(names + relationship labels) as you type — MCP argument completion, scoped to your
family. See [`src/prompts/index.ts`](src/prompts/index.ts) and
[`src/completions.ts`](src/completions.ts).

## Example Scenarios

1. **"Help me write a birthday card for my sister"**
   - `find_family_member` → resolves "my sister" to Sarah Walker
   - `get_birthday_card_context` → returns interests (painting, hiking, coffee), tone suggestions

2. **"When is grandma's birthday?"**
   - `answer_family_date_question` → returns Margaret Walker's birthday (November 8)

3. **"What's been happening in the family?"**
   - `get_recent_family_activity` → returns recent posts, photos, events

4. **"Help me write a thank you message to my dad"**
   - `get_message_context_for_person` → returns Robert Walker's context, interests, suggestions

5. **"Who's in my family?"**
   - `get_family_members` → returns all family members with relationships

6. **"What events are coming up?"**
   - `get_upcoming_family_dates` → returns upcoming birthdays, anniversaries, events

## Architecture

```
┌─────────────────────────────────────────────────────────┐
│                    MCP Client (LLM)                       │
│              (Claude, ChatGPT, KAI, etc.)                │
└───────────────────────┬─────────────────────────────────┘
                        │ stdio (MCP Protocol)
┌───────────────────────▼─────────────────────────────────┐
│                  A2Me MCP Server                          │
│  ┌─────────────────────────────────────────────────┐    │
│  │              Tool Registry (16 tools)             │    │
│  └──────────────────────┬──────────────────────────┘    │
│                         │                                │
│  ┌──────────────────────▼──────────────────────────┐    │
│  │         Family Context Resolver                   │    │
│  │   (fuzzy matching, relationship resolution)       │    │
│  └──────────────────────┬──────────────────────────┘    │
│                         │                                │
│  ┌──────────────────────▼──────────────────────────┐    │
│  │            A2Me API Client                        │    │
│  │   (currently mock, future: real HTTP calls)       │    │
│  └──────────────────────┬──────────────────────────┘    │
│                         │                                │
│  ┌──────────────────────▼──────────────────────────┐    │
│  │            Auth Context                           │    │
│  │   (currently mock, future: OAuth/Firebase)        │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘
                        │ (future)
┌───────────────────────▼─────────────────────────────────┐
│                   A2Me REST API                           │
│               (kinnectd-api service)                     │
└─────────────────────────────────────────────────────────┘
```

## Authentication

Currently uses **mock authentication** — always returns an authenticated user ("Alex Walker") for local development.

**Future production integration:**

- OAuth2/Firebase token validation via A2Me API
- Token passed via MCP session context or environment
- Per-user data isolation (users only see their own family)

## Required A2Me API Endpoints (Future)

| Method | Endpoint                             | Description                          |
| ------ | ------------------------------------ | ------------------------------------ |
| GET    | `/family/members`                    | List user's family members           |
| GET    | `/family/dates/upcoming`             | Upcoming dates with filters          |
| GET    | `/family/activity/recent`            | Recent family activity feed          |
| GET    | `/people/{personId}/context`         | Person profile with safe context     |
| GET    | `/relationships/path`                | Relationship path between two people |
| GET    | `/birthday-cards/context/{personId}` | Birthday card writing context        |

## ChatGPT app widgets

For ChatGPT (Apps SDK), four tools render an interactive inline widget instead of
plain JSON:

- `get_upcoming_family_dates` → an **Upcoming family dates** card
- `get_family_members` → a **Your family** roster
- `get_person_profile` → a **Family member** profile card
- `get_recent_family_activity` → a **Recent family activity** feed

Each widget is a small React bundle in [`widgets/src/`](widgets/src) built by
`npm run build:widgets` into `dist-widgets/<name>.js|.css`. The server serves those as
static assets (`/widgets/...`) and exposes each as a `ui://widget/<name>.html`
resource (MIME `text/html+skybridge`); the paired tool carries
`_meta["openai/outputTemplate"]` pointing at it. The widget reads the tool's
`structuredContent` from `window.openai.toolOutput` and renders it. Other MCP clients
(Claude, KAI) ignore the widgets and use the same tools' text output. See
[`src/widgets/registry.ts`](src/widgets/registry.ts).

## Development

```bash
npm run dev            # Run the server with tsx (hot reload)
npm run build          # Compile server (tsc) + build widget bundles
npm run build:server   # Server only
npm run build:widgets  # Widget bundles only (-> dist-widgets/)
npm run test           # Run tests (incl. widget render tests)
npm run test:watch     # Watch mode
npm run lint           # ESLint
npm run format         # Prettier
npm run check          # Type check only
```

## Privacy Design

This server is designed to be **privacy-first**:

- No email addresses, phone numbers, or physical addresses are ever returned
- Birthdays are shown as month-day only (no birth year)
- No financial or health information
- All data scoped to the authenticated user's family only
- Managed accounts (children) have additional protections

## Privacy Policy

**Privacy policy:** <https://a2me.app/privacy>

This connector accesses A2Me data on behalf of the authenticated user, over an
OAuth 2.0 "Connect A2Me" flow, and is bound by the A2Me privacy policy above.

- **What we collect / access:** read-only family-context data for the
  authenticated user's own family — member names, relationship labels,
  month–day of birthdays and events, and recent activity summaries. We never
  return email addresses, phone numbers, physical addresses, birth years,
  or financial/health data.
- **How it's used:** returned to the connected AI assistant solely to answer
  the user's request in-session. The connector does not train models on this
  data and performs no writes back to A2Me.
- **Storage & retention:** the connector holds no family data at rest. For
  transparency and abuse prevention we log access metadata (timestamp,
  tool name, calling assistant, scopes) in an append-only audit log; users can
  review this under **Settings → Connected apps** in A2Me.
- **Third-party sharing:** OAuth tokens are issued and validated via our auth
  provider (Scalekit); no family data is shared with third parties beyond the
  AI assistant the user explicitly connected.
- **Contact:** privacy@a2me.app · security disclosures per [SECURITY.md](SECURITY.md).

## Tech Stack

- **Runtime:** Node.js 20+
- **Language:** TypeScript (strict mode)
- **MCP SDK:** `@modelcontextprotocol/sdk`
- **Validation:** Zod
- **Testing:** Vitest
- **Transport:** Streamable HTTP (remote/production) and stdio (local dev)

## License

Private — Kinnectd / A2Me

More