Skip to content

Commit 674056d

Browse files
napoleondclaude
andcommitted
feat: Add email read command for fetching full message content
- Add `npx atxp email read <messageId>` command to read full message body - Update inbox display to show message IDs - Integrate with new `email_get_message` MCP tool - Update skill documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent a28b673 commit 674056d

4 files changed

Lines changed: 64 additions & 8 deletions

File tree

packages/atxp/src/commands/email.ts

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ interface EmailOptions {
1212
function showEmailHelp(): void {
1313
console.log(chalk.bold('Email Commands:'));
1414
console.log();
15-
console.log(' ' + chalk.cyan('npx atxp email inbox') + ' ' + 'Check your inbox');
16-
console.log(' ' + chalk.cyan('npx atxp email send') + ' ' + chalk.yellow('<options>') + ' ' + 'Send an email');
15+
console.log(' ' + chalk.cyan('npx atxp email inbox') + ' ' + 'Check your inbox');
16+
console.log(' ' + chalk.cyan('npx atxp email read') + ' ' + chalk.yellow('<messageId>') + ' ' + 'Read a specific message');
17+
console.log(' ' + chalk.cyan('npx atxp email send') + ' ' + chalk.yellow('<options>') + ' ' + 'Send an email');
1718
console.log();
1819
console.log(chalk.bold('Send Options:'));
1920
console.log(' ' + chalk.yellow('--to') + ' ' + chalk.gray('<email>') + ' ' + 'Recipient email address (required)');
@@ -22,17 +23,19 @@ function showEmailHelp(): void {
2223
console.log();
2324
console.log(chalk.bold('Examples:'));
2425
console.log(' npx atxp email inbox');
26+
console.log(' npx atxp email read msg_abc123');
2527
console.log(' npx atxp email send --to user@example.com --subject "Hello" --body "Hi there!"');
2628
console.log();
2729
console.log(chalk.bold('Pricing:'));
2830
console.log(' Inbox check: ' + chalk.green('FREE'));
31+
console.log(' Read message: ' + chalk.green('FREE'));
2932
console.log(' Send email: ' + chalk.yellow('$0.01 per email'));
3033
console.log();
3134
console.log(chalk.bold('Your Email Address:'));
3235
console.log(' Each ATXP user gets a unique address: ' + chalk.cyan('{user_id}@atxp.email'));
3336
}
3437

35-
export async function emailCommand(subCommand: string, options: EmailOptions): Promise<void> {
38+
export async function emailCommand(subCommand: string, options: EmailOptions, messageId?: string): Promise<void> {
3639
if (!subCommand || subCommand === 'help' || subCommand === '--help' || subCommand === '-h') {
3740
showEmailHelp();
3841
return;
@@ -43,6 +46,10 @@ export async function emailCommand(subCommand: string, options: EmailOptions): P
4346
await checkInbox();
4447
break;
4548

49+
case 'read':
50+
await readMessage(messageId);
51+
break;
52+
4653
case 'send':
4754
await sendEmail(options);
4855
break;
@@ -77,14 +84,53 @@ async function checkInbox(): Promise<void> {
7784
console.log();
7885

7986
for (const email of parsed.messages) {
87+
console.log(chalk.gray('ID: ' + email.messageId));
8088
console.log(chalk.bold('From: ') + email.from);
8189
console.log(chalk.bold('Subject: ') + email.subject);
8290
console.log(chalk.bold('Date: ') + email.date);
83-
if (email.text) {
84-
console.log(chalk.bold('Body: ') + email.text.substring(0, 200) + (email.text.length > 200 ? '...' : ''));
85-
}
8691
console.log(chalk.gray('─'.repeat(50)));
8792
}
93+
94+
console.log();
95+
console.log(chalk.gray('Use `npx atxp email read <messageId>` to read a message'));
96+
} catch {
97+
// If not JSON, just print raw result
98+
console.log(result);
99+
}
100+
}
101+
102+
async function readMessage(messageId?: string): Promise<void> {
103+
if (!messageId) {
104+
console.error(chalk.red('Error: messageId is required'));
105+
console.log(`Usage: ${chalk.cyan('npx atxp email read <messageId>')}`);
106+
console.log(chalk.gray('Use `npx atxp email inbox` to see message IDs'));
107+
process.exit(1);
108+
}
109+
110+
const result = await callTool(SERVER, 'email_get_message', { messageId });
111+
112+
try {
113+
const parsed = JSON.parse(result);
114+
if (parsed.status === 'error') {
115+
console.error(chalk.red('Error: ' + parsed.errorMessage));
116+
process.exit(1);
117+
}
118+
119+
const msg = parsed.message;
120+
console.log(chalk.bold('From: ') + msg.from);
121+
console.log(chalk.bold('To: ') + (Array.isArray(msg.to) ? msg.to.join(', ') : msg.to));
122+
console.log(chalk.bold('Subject: ') + msg.subject);
123+
console.log(chalk.bold('Date: ') + msg.date);
124+
console.log(chalk.gray('─'.repeat(50)));
125+
console.log();
126+
if (msg.text) {
127+
console.log(msg.text);
128+
} else if (msg.html) {
129+
console.log(chalk.gray('(HTML content - plain text not available)'));
130+
console.log(msg.html);
131+
} else {
132+
console.log(chalk.gray('(No message body)'));
133+
}
88134
} catch {
89135
// If not JSON, just print raw result
90136
console.log(result);

packages/atxp/src/help.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export function showHelp(): void {
7676
console.log(' npx atxp video "ocean waves" # Generate a video');
7777
console.log(' npx atxp x "trending topics" # Search X/Twitter');
7878
console.log(' npx atxp email inbox # Check your email inbox');
79+
console.log(' npx atxp email read <messageId> # Read a specific message');
7980
console.log(' npx atxp email send --to user@example.com --subject "Hi" --body "Hello!"');
8081
console.log(' npx atxp dev demo # Run the demo');
8182
console.log(' npx atxp dev create my-app # Create a new project');

packages/atxp/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,8 @@ async function main() {
302302
break;
303303

304304
case 'email':
305-
await emailCommand(subCommand || '', emailOptions);
305+
// For 'email read <messageId>', the messageId is in argv[4]
306+
await emailCommand(subCommand || '', emailOptions, process.argv[4]);
306307
break;
307308

308309
case 'paas':

skills/atxp/SKILL.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ source ~/.atxp/config
2828
| `npx atxp video <prompt>` | AI video generation |
2929
| `npx atxp x <query>` | X/Twitter search |
3030
| `npx atxp email inbox` | Check your email inbox (FREE) |
31+
| `npx atxp email read <messageId>` | Read a specific message (FREE) |
3132
| `npx atxp email send <options>` | Send an email ($0.01/email) |
3233

3334
## Email
@@ -38,6 +39,13 @@ Each ATXP user gets a unique email address: `{user_id}@atxp.email`
3839
```bash
3940
npx atxp email inbox
4041
```
42+
Returns message metadata (from, subject, date, messageId). Use `email read` to get full message content.
43+
44+
### Read Message
45+
```bash
46+
npx atxp email read <messageId>
47+
```
48+
Retrieves the full content of a specific message including the body. Get the messageId from `email inbox` output.
4149

4250
### Send Email
4351
```bash
@@ -89,5 +97,5 @@ const result = await client.callTool({
8997
| `music.mcp.atxp.ai` | `music_create` |
9098
| `video.mcp.atxp.ai` | `create_video` |
9199
| `x-live-search.mcp.atxp.ai` | `x_live_search` |
92-
| `email.mcp.atxp.ai` | `email_check_inbox`, `email_send_email` |
100+
| `email.mcp.atxp.ai` | `email_check_inbox`, `email_get_message`, `email_send_email` |
93101
| `paas.mcp.atxp.ai` | PaaS tools (see `atxp-paas` skill) |

0 commit comments

Comments
 (0)