273 lines
8.4 KiB
Markdown
273 lines
8.4 KiB
Markdown
# Declawed: A Configurable, Promptable AI Mail Assisty Kitty
|
||
|
||
A local Model Context Protocol (MCP) server and LLM integration platform. Built to connect to LLM APIs - be itClaude Desktop, *others*... or locally hosted models. Executes your prompts to manage your mail, while you... watch Fellini films, solve climate change, sip Mai Tais, or.... whatever.
|
||
|
||
Ssssimple. Siamsese, if you please.... Eats the blue-plate-crustacean for breakfast.
|
||
|
||
Infinitely mod-able. Dead simple. Privacy centric.
|
||
|
||
---
|
||
|
||
# Scope
|
||
|
||
## Current implementation contemplates: Claude Desktop + Custom, Local Model Context Protocol Server + Commercial SMTP Server (MX'config’d properly) + your DNS-config’d XXX.YYY
|
||
|
||
---
|
||
|
||
### 1. Install: Node.js
|
||
|
||
Node.js v16 or higher must be installed.
|
||
|
||
```bash
|
||
node --version
|
||
npm --version
|
||
```
|
||
|
||
If not installed, download from [nodejs.org](https://nodejs.org/).
|
||
|
||
### 2. Initialize the Project
|
||
|
||
```bash
|
||
mkdir assistant
|
||
cd assistant
|
||
npm init -y
|
||
```
|
||
|
||
### 3. Install Dependencies
|
||
|
||
```bash
|
||
npm install @modelcontextprotocol/sdk zod@3 googleapis
|
||
npm install -D @types/node typescript
|
||
```
|
||
|
||
Create the source directory and entry file:
|
||
|
||
```bash
|
||
mkdir src
|
||
touch src/index.ts
|
||
```
|
||
|
||
### 4. Configure the Project
|
||
|
||
#### 4a. Update `package.json`
|
||
|
||
Set the module type, binary entry, and build scripts:
|
||
|
||
```json
|
||
{
|
||
"type": "module",
|
||
"bin": {
|
||
"assistant": "./build/index.js"
|
||
},
|
||
"scripts": {
|
||
"build": "tsc && chmod 755 build/index.js",
|
||
"auth": "npm run build && node build/auth.js"
|
||
},
|
||
"files": ["build"]
|
||
}
|
||
```
|
||
|
||
#### 4b. Create `tsconfig.json` in the project root
|
||
|
||
```json
|
||
{
|
||
"compilerOptions": {
|
||
"target": "ES2022",
|
||
"module": "Node16",
|
||
"moduleResolution": "Node16",
|
||
"outDir": "./build",
|
||
"rootDir": "./src",
|
||
"strict": true,
|
||
"esModuleInterop": true,
|
||
"skipLibCheck": true,
|
||
"forceConsistentCasingInFileNames": true
|
||
},
|
||
"include": ["src/**/*"],
|
||
"exclude": ["node_modules"]
|
||
}
|
||
```
|
||
|
||
### 5. Write the Server Code
|
||
|
||
The server source lives in `src/index.ts`. It registers three tools and one prompt with the MCP server:
|
||
|
||
- **`fetch_new_emails`** -- fetches unread Gmail messages
|
||
- **`delete_emails`** -- trashes messages by ID
|
||
- **`append_to_summary`** -- logs classified emails to `summary.json`
|
||
- **`review_emails`** (prompt) -- feeds Claude the classification instructions
|
||
|
||
The auth helper lives in `src/auth.ts`, used only for the one-time OAuth setup.
|
||
|
||
### 6. Set Up Google Cloud Credentials
|
||
|
||
#### 6a. Create a Google Cloud Project
|
||
|
||
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
|
||
2. Sign in with the Google account that owns the target Gmail
|
||
3. Click the project dropdown (top-left) and select **New Project**
|
||
4. Name it (e.g., `assistant-mcp`) and click **Create**
|
||
5. Select the new project from the dropdown
|
||
|
||
#### 6b. Enable the Gmail API
|
||
|
||
1. Go to **APIs & Services > Library** ([direct link](https://console.cloud.google.com/apis/library))
|
||
2. Search for **Gmail API**
|
||
3. Click it, then click **Enable**
|
||
|
||
#### 6c. Configure the OAuth Consent Screen
|
||
|
||
1. Go to **Google Auth Platform > Branding** (or **APIs & Services > OAuth consent screen**)
|
||
2. Set user type to **External**, click **Create**
|
||
3. Fill in app name, support email, and developer contact email
|
||
4. Save and continue
|
||
|
||
#### 6d. Add the Gmail Scope
|
||
|
||
1. Go to **Google Auth Platform > Data Access** (or the Scopes page)
|
||
2. Click **Add or remove scopes**
|
||
3. Add: `https://www.googleapis.com/auth/gmail.modify`
|
||
4. Save
|
||
|
||
#### 6e. Add Yourself as a Test User
|
||
|
||
1. Go to **Google Auth Platform > Audience**
|
||
2. Add your Gmail address as a test user
|
||
|
||
#### 6f. Create OAuth Client Credentials
|
||
|
||
1. Go to **Google Auth Platform > Clients** (or **APIs & Services > Credentials**)
|
||
2. Click **Create Client** (or **+ Create Credentials > OAuth client ID**)
|
||
3. Application type: **Desktop app**
|
||
4. Name it anything (e.g., `Assistant MCP Desktop`)
|
||
5. Click **Create**
|
||
6. **Download the JSON** file
|
||
7. Rename it to `credentials.json`
|
||
8. Move it to the project root: `/Users/kjannette/assistant/credentials.json`
|
||
|
||
### 7. Authorize Your Gmail Account
|
||
|
||
Build the project and run the auth script:
|
||
|
||
```bash
|
||
npm run auth
|
||
```
|
||
|
||
This will:
|
||
1. Print a URL -- open it in your browser
|
||
2. Sign in with your Google account and click **Allow**
|
||
3. You'll land on a "localhost refused to connect" page (this is normal)
|
||
4. Copy the **entire URL** from the browser address bar
|
||
5. Paste it into the terminal prompt
|
||
6. The script extracts the auth code and saves `token.json`
|
||
|
||
You only need to do this once. The token auto-refreshes.
|
||
|
||
### 8. Build the Server
|
||
|
||
```bash
|
||
npm run build
|
||
```
|
||
|
||
This compiles `src/*.ts` into `build/*.js`.
|
||
|
||
### 9. Write the Classification Prompt
|
||
|
||
Create a file called `classify-emails.txt` in the project root. This file contains the plain-text instructions that tell Claude how to classify your emails.
|
||
|
||
**Tips for writing the prompt:**
|
||
- Use clear, explicit category definitions with example language for each
|
||
- Handle ambiguous cases (e.g., "If an email both acknowledges receipt AND requests action, classify it as B")
|
||
- Define the exact actions to take for each category (delete, summarize, etc.)
|
||
- Specify what fields to include in summaries
|
||
- Keep it in plain text -- no JSON or special formatting needed
|
||
- The file is loaded at runtime, so you can edit it without rebuilding the server
|
||
|
||
**File location:** Must be at the project root as `classify-emails.txt`.
|
||
|
||
### 10. Configure Claude Desktop
|
||
|
||
Edit the Claude Desktop config file:
|
||
|
||
```bash
|
||
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
|
||
```
|
||
|
||
Add the `assistant` server to the `mcpServers` object:
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"assistant": {
|
||
"command": "/ABSOLUTE/PATH/TO/node",
|
||
"args": [
|
||
"/Users/kjannette/assistant/build/index.js"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
Replace `/ABSOLUTE/PATH/TO/node` with the output of `which node`.
|
||
|
||
### 11. Restart Claude Desktop
|
||
|
||
Fully quit Claude Desktop (**Cmd+Q**, not just close the window) and reopen it. The `assistant` server should now appear under **Connectors** in the chat input.
|
||
|
||
---
|
||
|
||
## Usage Guide
|
||
|
||
### Prompt Loader
|
||
|
||
The server reads `classify-emails.txt` from the project root at runtime. To change classification behavior, edit that file directly -- no rebuild required. The updated instructions take effect on the next tool call.
|
||
|
||
### MCP Prompt: `review_emails`
|
||
|
||
A registered MCP prompt available in Claude Desktop's Connectors menu. When invoked, it feeds Claude the full contents of `classify-emails.txt` as a user message, giving Claude all the classification criteria before it calls any tools. This is the recommended way to trigger the workflow -- it ensures Claude has the complete instructions every time.
|
||
|
||
### `fetch_new_emails` Enrichment
|
||
|
||
Every time `fetch_new_emails` is called, the classification instructions from `classify-emails.txt` are appended to the response alongside the email data. This means Claude always sees the rules with the data, even if the `review_emails` prompt was not explicitly invoked. Belt and suspenders.
|
||
|
||
### Running the Workflow
|
||
|
||
1. Open Claude Desktop
|
||
2. Type: **"Review my inbox"** (or invoke the `review_emails` prompt from Connectors)
|
||
3. Claude will:
|
||
- Call `fetch_new_emails` to retrieve unread messages
|
||
- Classify each email as A, B, C, or D using the prompt instructions
|
||
- Call `delete_emails` for categories A and C
|
||
- Call `append_to_summary` for categories B and D
|
||
4. Results are displayed in the chat and saved to `summary.json`
|
||
|
||
### Key Commands
|
||
|
||
| Command | Purpose |
|
||
|---------|---------|
|
||
| `npm run build` | Recompile after editing `src/index.ts` |
|
||
| `npm run auth` | Re-authorize Gmail (only if `token.json` deleted/expired) |
|
||
| Cmd+Q Claude Desktop, reopen | Pick up server changes after a rebuild |
|
||
|
||
---
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
assistant/
|
||
├── src/
|
||
│ ├── index.ts # MCP server source (tools + prompt)
|
||
│ └── auth.ts # One-time OAuth setup script
|
||
├── build/
|
||
│ ├── index.js # Compiled server (Claude Desktop runs this)
|
||
│ └── auth.js # Compiled auth script
|
||
├── classify-emails.txt # Classification prompt (plain text, edit anytime)
|
||
├── credentials.json # Google OAuth client credentials (from Cloud Console)
|
||
├── token.json # Gmail access/refresh token (auto-generated)
|
||
├── summary.json # Output file where B/D emails are logged
|
||
├── package.json # Project config and scripts
|
||
├── tsconfig.json # TypeScript compiler config
|
||
└── README.md # This file
|
||
```
|
||
|
||
|