3 Commits

Author SHA1 Message Date
76993cf8b3 Merge pull request 'refine' (#9) from FEAT-refine into master
Reviewed-on: #9
2026-09-01 01:20:53 +00:00
KS Jannette
4d17c409be refine 2026-08-31 21:20:19 -04:00
KS Jannette
f96a8541c6 revisions 2026-08-31 16:52:48 -04:00
22 changed files with 3503 additions and 3484 deletions

2
.gitignore vendored
View File

@@ -10,3 +10,5 @@ accountsAndCredentials/token.json.bak
# Runtime output
mailSummaries/
// revised Aug 31

View File

@@ -488,3 +488,4 @@ deClawed-Assity-Kitty/
├── .gitignore
└── README.md
```
// revised Aug 31

View File

@@ -1,12 +1,12 @@
{
"work": {
"label": "",
"tokenFile": "token.json",
"spreadsheetId": "",
"calendarId": "primary"
},
"secondary": {
"label": "",
"tokenFile": "token-secondary.json"
}
"work": {
"label": "",
"tokenFile": "token.json",
"spreadsheetId": "",
"calendarId": "primary"
},
"secondary": {
"label": "",
"tokenFile": "token-secondary.json"
}
}

View File

@@ -1,11 +1,13 @@
{
"installed": {
"client_id": "",
"project_id": "",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "",
"redirect_uris": ["http://localhost"]
}
"installed": {
"client_id": "",
"project_id": "",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "",
"redirect_uris": [
"http://localhost"
]
}
}

View File

@@ -1,7 +1,7 @@
{
"access_token": "",
"refresh_token": "",
"scope": "https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/gmail.modify https://www.googleapis.com/auth/calendar.events",
"token_type": "Bearer",
"expiry_date": 0
"access_token": "",
"refresh_token": "",
"scope": "https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/gmail.modify https://www.googleapis.com/auth/calendar.events",
"token_type": "Bearer",
"expiry_date": 0
}

6742
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +1,31 @@
{
"name": "assistant",
"version": "1.0.0",
"description": "MCP server for Gmail job application management",
"type": "module",
"bin": {
"assistant": "./build/index.js"
},
"scripts": {
"build": "tsc && chmod 755 build/index.js",
"auth": "npm run build && node build/auth.js",
"test": "vitest run",
"test:watch": "vitest"
},
"files": [
"build"
],
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.30.0",
"googleapis": "^171.4.0",
"zod": "^3.25.76"
},
"devDependencies": {
"@types/node": "^25.2.3",
"typescript": "^5.9.3",
"vitest": "^4.0.18"
}
"name": "assistant",
"version": "1.0.0",
"description": "MCP server for Gmail job application management",
"type": "module",
"bin": {
"assistant": "./build/index.js"
},
"scripts": {
"build": "tsc && chmod 755 build/index.js",
"auth": "npm run build && node build/auth.js",
"test": "vitest run",
"test:watch": "vitest"
},
"files": [
"build"
],
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.30.0",
"googleapis": "^171.4.0",
"zod": "^3.25.76"
},
"devDependencies": {
"@types/node": "^25.2.3",
"typescript": "^5.9.3",
"vitest": "^4.0.18"
}
}

View File

@@ -4,3 +4,5 @@ export const server = new McpServer({
name: "assistant",
version: "1.0.0",
});
// revised Aug 31

View File

@@ -117,3 +117,5 @@ authorize().catch((err) => {
console.error("Authorization failed:", err);
process.exit(1);
});
// revised Aug 31

View File

@@ -18,3 +18,5 @@ main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});
// revised Aug 31

View File

@@ -149,3 +149,5 @@ export const getSpreadsheetId = (account: string): string => {
export const getCalendarId = (account: string): string =>
accounts[account]?.calendarId ?? "primary";
// revised Aug 31

View File

@@ -54,3 +54,5 @@ server.registerPrompt(
};
}
);
// revised Aug 31

View File

@@ -1,26 +1,17 @@
You are an expert Executive Assistant AI specialized in email management. Your goal is to organize, prioritize, and summarize incoming emails to maximize efficiency. I have been applying for jobs, which generates a large volume of responses.
You are an expert Executive Assistant AI specialized in email management and productivity. Your goal is to organize, prioritize, and summarize incoming emails to maximize user efficiency. I have been applying for jobs, which generates a large volume of responses.
Review the first 200 inbox emails. Apply the following instructions.
Review the first 200 emails in my inbox. Apply the following instructions to those emails.
STEP 1: Constraint
- NEVER make up information.
STEP 1: Constraints
- Do not make up information.
STEP 2: CLASSIFY each email into exactly one category.
Category A - Acknowledgement Only
The employer confirms receipt of my application but requires no action from me. Typical language: "We received your application," "Your application is under review," "We will contact you if selected."
The employer confirms receipt of my application but requires no action from me. Typical language: "We received your application," "Your application is under review," "We will contact you if selected." No next steps are requested.
Category B - Advancement to a Next Step
The company wants to move forward. This includes, for example:
1. Invitations to schedule a phone screen or interview
2. Requests to complete an assessment or assignment
3. Requests for additional information or documents, from a human. This item is a bit more fine grained than others, because it does not include, i.e. automated requests to provide EEOC demographic information, verify identity, create an account password, etc. An important factor here is automated messaging versus a "human in the loop" on the company side seeking to connect. Use your judgment. Do not stop the process to ask questions about any emails. Rather, when in doubt, err on the side of inclusion and move on.
4. Emails seeking to schedule a "second round", "third round" interview, further discussion or screening.
5. Emails that state that I missed a prior email, appointment or request *and* come from a human, not automation. Again, when in doubt err on the side of inclusion.
6. If an email both acknowledges receipt AND requests action, classify it as B.
This category does *not* include Greenhouse "security code" emails, other "confirm identity codes" or auto-generated "identity-confirmation" type emails, or "verify candidate account" type emails.
Category B - Advancement to Next Step
The employer wants to move forward. This includes: invitations to schedule a phone screen or interview, requests to complete an assessment or assignment, requests for additional information or documents, or any communication that requires a response or action from me. If an email both acknowledges receipt AND requests action, classify it as B.
This does *not* include Greenhouse "security code" emails, other "confirm identity codes" or "identity-confirmation" type emails, "verify candidate account" type emails,
Category C - Rejection
The employer declines to move forward. Typical language: "We have decided to pursue other candidates," "Unfortunately, you were not selected," "We will not be moving forward with your application."
@@ -29,11 +20,9 @@ Category D - Other
The email does not fit into categories A, B, or C. This includes non-job-application emails, newsletters, promotional content, or ambiguous messages that do not clearly match another category.
STEP 3: STAR REVIEWED EMAILS
- For EVERY email processed and reviewed in this run that is in Category A, C, and D (NOT B), apply the Gmail "STARRED" system label or use your email tool to add a star to the message.
For every Category A, C, and D email, apply the Gmail "STARRED" system label or use your email tool to add a star to the message.
DO NOT add a star to any Category B email.
STEP 4: Confirm, via the chat window, the total number of emails fetched.
STEP 4: Confirm, via natural language output in the chat window, the total number of emails fetched for review and starred.
STEP 5: SUMMARIZE emails classified as Category B and Category D, under separate headers, in the chat.
For each, state:
@@ -41,26 +30,15 @@ For each, state:
2. Email subject line
3. Date and time received
4. Category (B or D)
5. Summary of body
5. Suggested action I should take
STEP 6: Process check **STRICT COMPLIANCE REQUIRED** **DO NOT FORGET***:
STEP 6: **STRICT COMPLIANCE REQUIRED** **DO NOT FORGET***:
Summarize all "Category B" emails in the chat.
Star all reviewed email
Summarize all "Category B" and "Category D" emails in the chat.
**STRICT COMPLIANCE REQUIRED** **DO NOT FORGET***
Inlude headers:
From (sender)
Subject (one line)
Date
Time (IN EASTERN STANDARD TIME)
Body Summary
Star all emails reviewed and classified as Category A, C or D.
Do not star emails reviewed and classified as Category B.
Do not star unreviewed emails.
Next, perform the following actions for each "Category B" email:
STEP 7: CREATE CALENDAR EVENTS
Perform the following actions for each "Category B" email:
Immediately after logging to the spreadsheet, check whether ANY of these fields were populated or updated:
- Recruiter Call Scheduled
- Company First Interview
@@ -74,7 +52,11 @@ For EACH of the above fields that contains a date/time, create a Google Calendar
- Description: include recruiter or company contact name/email/phone, and note whether they have your cell number
STRICT CONSTRAINTS:
- Do not make up phone numbers, links, dates, or anything at all. If information does not exist in text within a verifiable email message, IT DOES NOT EXIST.
- Before creating a calendar event: 1) verify today's date from an external, reliable source; 2) compare the proposed meeting date/time against today's date; 3) if the meeting date has already passed, do NOT create a calendar event for it.
- Do not make up phone numbers, links, dates, or anything at all. If it does not exist in text within a verifiable email, IT DOES NOT EXIST.
- PAST-DATE CHECK: Before creating a calendar event: 1) verify today's date from an external, reliable source; 2) compare the proposed meeting date/time against today's date; 3) if the meeting date has already passed, do NOT create a calendar event for it. Still log it to the spreadsheet, but skip the calendar step. The tool will also enforce this server-side.
- As described in more detail below, each new date/time value in a scheduling column = one new calendar event. Never skip this.
- Always use the same account for calendar events as was used for email fetching.
- Do not create duplicate calendar events for the same meeting (same company representative && same job description | same company && same date time)
- If information is not present in the email, leave that field empty (it's OK!) - do not guess or make up information.
// revised Aug 31

View File

@@ -21,3 +21,5 @@ STRICT CONSTRAINTS:
- Always use the same account for calendar events as was used for email fetching.
- Do not create duplicate calendar events for the same meeting (same company representative && same job description | same company && same date time)
- If information is not present in the email, leave that field empty (it's OK!) - do not guess or make up information.
// revised Aug 31

View File

@@ -109,3 +109,5 @@ server.registerTool(
}
}
);
// revised Aug 31

View File

@@ -358,3 +358,5 @@ server.registerTool(
}
}
);
// revised Aug 31

View File

@@ -177,3 +177,5 @@ server.registerTool(
}
}
);
// revised Aug 31

View File

@@ -165,3 +165,5 @@ export const RAW_BODIES = {
"msg-cat-c-001": catCBody,
"msg-cat-d-001": catDBody,
};
// revised Aug 31

View File

@@ -285,3 +285,5 @@ describe("Phase 1: Email Review Workflow", () => {
});
});
});
// revised Aug 31

View File

@@ -84,3 +84,5 @@ describe("decodeBody", () => {
expect(decodeBody(msg)).toBe(htmlContent);
});
});
// revised Aug 31

View File

@@ -1,15 +1,21 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "test", "vitest.config.ts"]
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"test",
"vitest.config.ts"
]
}

View File

@@ -6,3 +6,5 @@ export default defineConfig({
globals: true,
},
});
// revised Aug 31