diff --git a/gemini-extension.json b/gemini-extension.json index c2ae611..add23d5 100644 --- a/gemini-extension.json +++ b/gemini-extension.json @@ -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", diff --git a/package-lock.json b/package-lock.json index fcac20f..48b56a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "email-agent-mcp-suite", - "version": "0.1.5", + "version": "0.1.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "email-agent-mcp-suite", - "version": "0.1.5", + "version": "0.1.6", "license": "Apache-2.0", "workspaces": [ "packages/*" @@ -4082,10 +4082,10 @@ } }, "packages/email-agent-mcp": { - "version": "0.1.5", + "version": "0.1.6", "license": "Apache-2.0", "dependencies": { - "@usejunior/email-mcp": "^0.1.5" + "@usejunior/email-mcp": "^0.1.6" }, "bin": { "email-agent-mcp": "bin/email-agent-mcp.js" @@ -4096,7 +4096,7 @@ }, "packages/email-core": { "name": "@usejunior/email-core", - "version": "0.1.5", + "version": "0.1.6", "license": "Apache-2.0", "dependencies": { "marked": "^18.0.0", @@ -4115,14 +4115,14 @@ }, "packages/email-mcp": { "name": "@usejunior/email-mcp", - "version": "0.1.5", + "version": "0.1.6", "license": "Apache-2.0", "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" }, "bin": { "email-agent-mcp": "dist/cli.js" @@ -4139,11 +4139,11 @@ }, "packages/provider-gmail": { "name": "@usejunior/provider-gmail", - "version": "0.1.5", + "version": "0.1.6", "license": "Apache-2.0", "dependencies": { "@googleapis/gmail": "^4.0.0", - "@usejunior/email-core": "^0.1.5" + "@usejunior/email-core": "^0.1.6" }, "devDependencies": { "@types/node": "^25.5.0", @@ -4157,13 +4157,13 @@ }, "packages/provider-microsoft": { "name": "@usejunior/provider-microsoft", - "version": "0.1.5", + "version": "0.1.6", "license": "Apache-2.0", "dependencies": { "@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", diff --git a/package.json b/package.json index 0a256e0..01cf1d7 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/packages/email-agent-mcp/package.json b/packages/email-agent-mcp/package.json index 5ba0872..9321b70 100644 --- a/packages/email-agent-mcp/package.json +++ b/packages/email-agent-mcp/package.json @@ -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", @@ -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": { diff --git a/packages/email-agent-mcp/server.json b/packages/email-agent-mcp/server.json index 9de3a08..34af1e3 100644 --- a/packages/email-agent-mcp/server.json +++ b/packages/email-agent-mcp/server.json @@ -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", @@ -26,7 +26,7 @@ { "registryType": "npm", "identifier": "email-agent-mcp", - "version": "0.1.5", + "version": "0.1.6", "transport": { "type": "stdio" }, diff --git a/packages/email-core/package.json b/packages/email-core/package.json index fd79602..4ce4cfb 100644 --- a/packages/email-core/package.json +++ b/packages/email-core/package.json @@ -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", diff --git a/packages/email-mcp/package.json b/packages/email-mcp/package.json index d21b04b..947011d 100644 --- a/packages/email-mcp/package.json +++ b/packages/email-mcp/package.json @@ -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", @@ -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", diff --git a/packages/email-mcp/src/cli.test.ts b/packages/email-mcp/src/cli.test.ts index ec82455..e53ce38 100644 --- a/packages/email-mcp/src/cli.test.ts +++ b/packages/email-mcp/src/cli.test.ts @@ -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', () => ({ @@ -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']); diff --git a/packages/email-mcp/src/cli.ts b/packages/email-mcp/src/cli.ts index 33f9e64..f362127 100644 --- a/packages/email-mcp/src/cli.ts +++ b/packages/email-mcp/src/cli.ts @@ -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 }; @@ -1171,8 +1173,18 @@ export async function runCliDirect(args: string[]): Promise { } } -// 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)); } diff --git a/packages/provider-gmail/package.json b/packages/provider-gmail/package.json index ddf614b..9f88e33 100644 --- a/packages/provider-gmail/package.json +++ b/packages/provider-gmail/package.json @@ -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", @@ -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", diff --git a/packages/provider-microsoft/package.json b/packages/provider-microsoft/package.json index 813dca5..87e74cc 100644 --- a/packages/provider-microsoft/package.json +++ b/packages/provider-microsoft/package.json @@ -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", @@ -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",