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
2 changes: 1 addition & 1 deletion gemini-extension.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "email-agent-mcp",
"version": "0.1.5",
"version": "0.1.6",
"description": "Local email connectivity for AI agents — read, draft, send, and organize Microsoft 365 / Outlook mail via MCP.",
"contextFileName": "GEMINI.md",
"entrypoint": "GEMINI.md",
Expand Down
26 changes: 13 additions & 13 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "email-agent-mcp-suite",
"version": "0.1.5",
"version": "0.1.6",
"private": true,
"description": "Local email connectivity for AI agents — MCP server for Microsoft 365 and manual-token Gmail setup",
"type": "module",
Expand Down
4 changes: 2 additions & 2 deletions packages/email-agent-mcp/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "email-agent-mcp",
"version": "0.1.5",
"version": "0.1.6",
"description": "Local email connectivity for AI agents — MCP server for Microsoft 365 / Outlook and manual-token Gmail setup",
"type": "module",
"main": "./index.js",
Expand All @@ -15,7 +15,7 @@
}
},
"dependencies": {
"@usejunior/email-mcp": "^0.1.5"
"@usejunior/email-mcp": "^0.1.6"
},
"mcpName": "io.github.UseJunior/email-agent-mcp",
"engines": {
Expand Down
4 changes: 2 additions & 2 deletions packages/email-agent-mcp/server.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "io.github.UseJunior/email-agent-mcp",
"title": "Agent Email",
"description": "Local email connectivity for AI agents — read, draft, send, and organize Outlook mail via MCP",
"version": "0.1.5",
"version": "0.1.6",
"websiteUrl": "https://github.com/UseJunior/email-agent-mcp",
"repository": {
"url": "https://github.com/UseJunior/email-agent-mcp",
Expand All @@ -26,7 +26,7 @@
{
"registryType": "npm",
"identifier": "email-agent-mcp",
"version": "0.1.5",
"version": "0.1.6",
"transport": {
"type": "stdio"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/email-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@usejunior/email-core",
"version": "0.1.5",
"version": "0.1.6",
"description": "Core email actions, content engine, security, and provider interfaces for email-agent-mcp",
"type": "module",
"main": "dist/index.js",
Expand Down
8 changes: 4 additions & 4 deletions packages/email-mcp/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@usejunior/email-mcp",
"version": "0.1.5",
"version": "0.1.6",
"description": "MCP server adapter + CLI + watcher for email-agent-mcp",
"type": "module",
"main": "dist/index.js",
Expand All @@ -24,9 +24,9 @@
"dependencies": {
"@clack/prompts": "^1.1.0",
"@modelcontextprotocol/sdk": "^1.0.0",
"@usejunior/email-core": "^0.1.5",
"@usejunior/provider-gmail": "^0.1.5",
"@usejunior/provider-microsoft": "^0.1.5"
"@usejunior/email-core": "^0.1.6",
"@usejunior/provider-gmail": "^0.1.6",
"@usejunior/provider-microsoft": "^0.1.6"
},
"devDependencies": {
"@types/node": "^25.5.0",
Expand Down
24 changes: 23 additions & 1 deletion packages/email-mcp/src/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import {
getEffectiveSendAllowlistPath,
loadConfig,
saveConfig,
isDirectCliRun,
} from './cli.js';
import { mkdtemp, rm, readFile } from 'node:fs/promises';
import { mkdtemp, rm, readFile, symlink } from 'node:fs/promises';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { fileURLToPath } from 'node:url';

// Linux CI runners do not provide libsecret, so auth imports must not load the real cache plugin.
vi.mock('@azure/identity-cache-persistence', () => ({
Expand Down Expand Up @@ -311,6 +313,26 @@ afterEach(() => {
vi.restoreAllMocks();
});

describe('cli/Direct Run Detection', () => {
it('Scenario: npm bin symlink resolves to the CLI entrypoint', async () => {
const tempDir = await mkdtemp(join(tmpdir(), 'email-agent-mcp-symlink-'));
const cliModuleUrl = new URL('./cli.ts', import.meta.url);
const symlinkPath = join(tempDir, 'email-agent-mcp');

try {
await symlink(fileURLToPath(cliModuleUrl), symlinkPath);
expect(isDirectCliRun(symlinkPath, cliModuleUrl.href)).toBe(true);
} finally {
await rm(tempDir, { recursive: true, force: true });
}
});

it('Scenario: wrapper entrypoints do not trigger CLI self-execution', () => {
const cliModuleUrl = new URL('./cli.ts', import.meta.url);
expect(isDirectCliRun('/tmp/email-agent-mcp-wrapper.js', cliModuleUrl.href)).toBe(false);
});
});

describe('cli/Serve Subcommand', () => {
it('Scenario: Start MCP server', async () => {
const exitCode = await runCli(['serve']);
Expand Down
16 changes: 14 additions & 2 deletions packages/email-mcp/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
// CLI entry point — serve, watch, configure, setup subcommands + TTY-aware default

import { randomUUID } from 'node:crypto';
import { realpathSync } from 'node:fs';
import { createServer } from 'node:http';
import { createRequire } from 'node:module';
import { dirname, join } from 'node:path';
import { homedir } from 'node:os';
import { readFile, writeFile, mkdir } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';

const require = createRequire(import.meta.url);
const { version: PACKAGE_VERSION } = require('../package.json') as { version: string };
Expand Down Expand Up @@ -1171,8 +1173,18 @@ export async function runCliDirect(args: string[]): Promise<void> {
}
}

// Auto-execute when run directly (not imported as a module in tests)
const isDirectRun = process.argv[1]?.endsWith('cli.ts') || process.argv[1]?.endsWith('cli.js');
export function isDirectCliRun(argv1: string | undefined, moduleUrl: string = import.meta.url): boolean {
if (!argv1) return false;

try {
return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
} catch {
return false;
}
}

// Auto-execute when run directly (including npm bin symlinks and shims)
const isDirectRun = isDirectCliRun(process.argv[1]);
if (isDirectRun) {
void runCliDirect(process.argv.slice(2));
}
4 changes: 2 additions & 2 deletions packages/provider-gmail/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@usejunior/provider-gmail",
"version": "0.1.5",
"version": "0.1.6",
"description": "Gmail API email provider for email-agent-mcp",
"type": "module",
"main": "dist/index.js",
Expand All @@ -20,7 +20,7 @@
},
"dependencies": {
"@googleapis/gmail": "^4.0.0",
"@usejunior/email-core": "^0.1.5"
"@usejunior/email-core": "^0.1.6"
},
"devDependencies": {
"@types/node": "^25.5.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/provider-microsoft/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@usejunior/provider-microsoft",
"version": "0.1.5",
"version": "0.1.6",
"description": "Microsoft Graph API email provider for email-agent-mcp",
"type": "module",
"main": "dist/index.js",
Expand All @@ -22,7 +22,7 @@
"@azure/identity": "^4.0.0",
"@azure/identity-cache-persistence": "^1.2.0",
"@microsoft/microsoft-graph-client": "^3.0.0",
"@usejunior/email-core": "^0.1.5"
"@usejunior/email-core": "^0.1.6"
},
"devDependencies": {
"@types/node": "^25.5.0",
Expand Down
Loading