keyid-agent-kit-mcp
Give AI agents (Claude, Cursor) a real email address with 27 MCP tools for inbox, send, reply, contacts, search, and more via KeyID.ai
How do I install this agent skill?
npx skills add https://github.com/aradotso/trending-skills --skill keyid-agent-kit-mcpIs this agent skill safe to install?
- Gen Agent Trust Hubpass
This skill provides a suite of email management tools for AI agents using the KeyID service. While it utilizes standard Model Context Protocol (MCP) patterns, it presents a risk of indirect prompt injection because the agent processes content from external emails, which could contain malicious instructions.
- Socketwarn
1 alert: gptSecurity
- Snykwarn
Risk: MEDIUM · 2 issues
- ZeroLeakspass
1 finding · Score: 86/100
What does this agent skill do?
KeyID Agent Kit — MCP Email Tools for AI Agents
Skill by ara.so — Daily 2026 Skills collection.
KeyID Agent Kit gives AI agents (Claude, Cursor, or any MCP client) a real, working email address with 27 tools via the Model Context Protocol. No signup, no API keys to acquire manually, no cost. Powered by KeyID.ai.
What It Does
- Provisions a real email address for your AI agent automatically
- Exposes 27 MCP tools: send, receive, reply, forward, search, contacts, drafts, webhooks, auto-reply, signatures, forwarding rules, metrics
- Runs as a stdio MCP server — compatible with Claude Desktop, Cursor, and any MCP client
- Uses Ed25519 keypairs for identity — auto-generated if not provided
Installation
npm install @keyid/agent-kit
# or
yarn add @keyid/agent-kit
# or run directly without installing
npx @keyid/agent-kit
Configuration
Environment Variables
| Variable | Description | Default |
|---|---|---|
KEYID_PUBLIC_KEY | Ed25519 public key (hex) | Auto-generated on first run |
KEYID_PRIVATE_KEY | Ed25519 private key (hex) | Auto-generated on first run |
KEYID_BASE_URL | API base URL | https://keyid.ai |
Important: Save the auto-generated keys after first run so your agent keeps the same email address across sessions. The keys are printed to stderr on first launch.
Claude Desktop Setup
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"keyid": {
"command": "npx",
"args": ["@keyid/agent-kit"],
"env": {
"KEYID_PUBLIC_KEY": "$KEYID_PUBLIC_KEY",
"KEYID_PRIVATE_KEY": "$KEYID_PRIVATE_KEY"
}
}
}
}
Cursor Setup
In .cursor/mcp.json at project root or global Cursor settings:
{
"mcpServers": {
"keyid": {
"command": "npx",
"args": ["@keyid/agent-kit"],
"env": {
"KEYID_PUBLIC_KEY": "$KEYID_PUBLIC_KEY",
"KEYID_PRIVATE_KEY": "$KEYID_PRIVATE_KEY"
}
}
}
}
First Run — Get Your Email Address
# Run once to generate keys and register the agent
npx @keyid/agent-kit
# Keys are printed to stderr — save them!
# Then set them in your environment or config
export KEYID_PUBLIC_KEY=<hex-from-output>
export KEYID_PRIVATE_KEY=<hex-from-output>
All 27 Tools Reference
Identity & Auth
keyid_provision — Register agent, get assigned email address
keyid_get_email — Get the current active email address
Messages
keyid_get_inbox — Fetch inbox; supports search query, filtering, pagination
keyid_send — Send email (to, subject, body, HTML, scheduled time, display name)
keyid_reply — Reply to a message by message_id
keyid_forward — Forward a message to another address
keyid_update_message — Mark read/unread, star/unstar
keyid_get_unread_count — Get count of unread messages
Threads & Drafts
keyid_list_threads — List conversation threads
keyid_get_thread — Get a thread with all its messages
keyid_create_draft — Save a draft
keyid_send_draft — Send a previously saved draft
Settings
keyid_get_auto_reply — Get current auto-reply/vacation responder config
keyid_set_auto_reply — Enable/disable auto-reply with custom message
keyid_get_signature — Get email signature
keyid_set_signature — Set email signature text/HTML
keyid_get_forwarding — Get forwarding rules
keyid_set_forwarding — Add or update forwarding to another address
Contacts
keyid_list_contacts — List all saved contacts
keyid_create_contact — Create a contact (name, email, notes)
keyid_delete_contact — Delete a contact by ID
Webhooks
keyid_list_webhooks — List configured webhooks
keyid_create_webhook — Register a webhook URL for inbound events
keyid_get_webhook_deliveries — View delivery history and failures
Lists & Metrics
keyid_manage_list — Add/remove addresses from allow or blocklist
keyid_get_metrics — Query usage metrics (sent, received, bounces)
Real Code Examples
Programmatic MCP Client (Node.js)
import { spawn } from 'child_process';
import { createInterface } from 'readline';
// Start the MCP server as a child process
const server = spawn('npx', ['@keyid/agent-kit'], {
env: {
...process.env,
KEYID_PUBLIC_KEY: process.env.KEYID_PUBLIC_KEY,
KEYID_PRIVATE_KEY: process.env.KEYID_PRIVATE_KEY,
},
stdio: ['pipe', 'pipe', 'inherit'],
});
// Send a JSON-RPC request
function sendRequest(method, params = {}) {
const request = {
jsonrpc: '2.0',
id: Date.now(),
method,
params,
};
server.stdin.write(JSON.stringify(request) + '\n');
}
// Read responses
const rl = createInterface({ input: server.stdout });
rl.on('line', (line) => {
const response = JSON.parse(line);
console.log('Response:', JSON.stringify(response, null, 2));
});
// Initialize MCP session
sendRequest('initialize', {
protocolVersion: '2024-11-05',
capabilities: {},
clientInfo: { name: 'my-app', version: '1.0.0' },
});
Call a Tool via MCP JSON-RPC
// After initialization, call tools/call
function callTool(toolName, toolArgs) {
const request = {
jsonrpc: '2.0',
id: Date.now(),
method: 'tools/call',
params: {
name: toolName,
arguments: toolArgs,
},
};
server.stdin.write(JSON.stringify(request) + '\n');
}
// Get inbox
callTool('keyid_get_inbox', { limit: 10 });
// Send an email
callTool('keyid_send', {
to: 'colleague@example.com',
subject: 'Hello from my AI agent',
body: 'This email was sent by an AI agent using KeyID.',
});
// Reply to a message
callTool('keyid_reply', {
message_id: 'msg_abc123',
body: 'Thanks, I will review this today.',
});
// Search inbox
callTool('keyid_get_inbox', {
query: 'from:alice@company.com subject:report',
unread_only: true,
});
// Set auto-reply
callTool('keyid_set_auto_reply', {
enabled: true,
subject: 'Out of Office',
body: 'I am currently unavailable. My AI agent will respond shortly.',
});
// Create a contact
callTool('keyid_create_contact', {
name: 'Alice Smith',
email: 'alice@company.com',
notes: 'Project lead for Q1 initiative',
});
// Schedule an email
callTool('keyid_send', {
to: 'team@company.com',
subject: 'Weekly Update',
body: 'Here is the weekly status...',
scheduled_at: '2026-03-25T09:00:00Z',
});
// Set email signature
callTool('keyid_set_signature', {
signature: 'Best regards,\nAI Agent\npowered by KeyID.ai',
});
// Get metrics
callTool('keyid_get_metrics', {
period: '7d',
});
Using with the MCP SDK (if building a custom client)
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
const transport = new StdioClientTransport({
command: 'npx',
args: ['@keyid/agent-kit'],
env: {
KEYID_PUBLIC_KEY: process.env.KEYID_PUBLIC_KEY,
KEYID_PRIVATE_KEY: process.env.KEYID_PRIVATE_KEY,
},
});
const client = new Client(
{ name: 'my-email-agent', version: '1.0.0' },
{ capabilities: {} }
);
await client.connect(transport);
// List available tools
const tools = await client.listTools();
console.log('Available tools:', tools.tools.map(t => t.name));
// Get email address
const emailResult = await client.callTool({
name: 'keyid_get_email',
arguments: {},
});
console.log('Agent email:', emailResult.content[0].text);
// Check unread
const unread = await client.callTool({
name: 'keyid_get_unread_count',
arguments: {},
});
console.log('Unread count:', unread.content[0].text);
// Send email
await client.callTool({
name: 'keyid_send',
arguments: {
to: 'recipient@example.com',
subject: 'Automated report',
body: 'Your daily report is attached.',
html: '<p>Your <strong>daily report</strong> is attached.</p>',
},
});
await client.close();
Webhook Integration
import express from 'express';
const app = express();
app.use(express.json());
// Endpoint to receive KeyID webhook events
app.post('/keyid-webhook', (req, res) => {
const event = req.body;
if (event.type === 'message.received') {
const { from, subject, body, message_id } = event.data;
console.log(`New email from ${from}: ${subject}`);
// Trigger your agent logic here
handleIncomingEmail({ from, subject, body, message_id });
}
res.json({ ok: true });
});
app.listen(3000);
// Register the webhook via the MCP tool
// (call this once via your agent)
// callTool('keyid_create_webhook', {
// url: 'https://your-server.com/keyid-webhook',
// events: ['message.received'],
// });
Common Patterns
Pattern: Agent with Persistent Identity
// Generate and store keys once, reuse forever
import { writeFileSync, readFileSync, existsSync } from 'fs';
import { generateKeyPairSync } from 'crypto'; // or use @noble/ed25519
const KEY_FILE = '.keyid-keys.json';
function loadOrCreateKeys() {
if (existsSync(KEY_FILE)) {
return JSON.parse(readFileSync(KEY_FILE, 'utf8'));
}
// Let @keyid/agent-kit auto-generate on first run,
// then save what it prints to stderr
// Or pre-generate using @noble/ed25519:
// const privKey = randomBytes(32);
// const pubKey = await ed.getPublicKeyAsync(privKey);
return null; // will auto-generate
}
Pattern: Email-Triggered Agent Loop
// Poll inbox and process new messages
async function agentEmailLoop(client) {
while (true) {
const result = await client.callTool({
name: 'keyid_get_inbox',
arguments: { unread_only: true, limit: 5 },
});
const messages = JSON.parse(result.content[0].text);
for (const msg of messages) {
// Process with your LLM/agent logic
const agentResponse = await processWithAgent(msg);
// Reply
await client.callTool({
name: 'keyid_reply',
arguments: {
message_id: msg.id,
body: agentResponse,
},
});
// Mark as read
await client.callTool({
name: 'keyid_update_message',
arguments: { message_id: msg.id, read: true },
});
}
// Wait 60 seconds before next poll
await new Promise(r => setTimeout(r, 60_000));
}
}
Pattern: Draft-Review-Send Workflow
// Create draft, review, then send
const draft = await client.callTool({
name: 'keyid_create_draft',
arguments: {
to: 'client@example.com',
subject: 'Proposal',
body: draftBody,
},
});
const draftId = JSON.parse(draft.content[0].text).id;
// Human or agent reviews...
// Then send:
await client.callTool({
name: 'keyid_send_draft',
arguments: { draft_id: draftId },
});
Troubleshooting
Agent gets a new email address every run
Cause: Keys not persisted between runs.
Fix: Save KEYID_PUBLIC_KEY and KEYID_PRIVATE_KEY from first run output and set them in your config or environment.
MCP server not appearing in Claude Desktop
Fix: Restart Claude Desktop after editing config. Verify JSON is valid (no trailing commas). Check that npx is in your PATH.
Tool calls return errors
Fix: Ensure the agent is provisioned first — call keyid_provision before other tools, or call keyid_get_email to confirm the agent has an address.
Emails not being received
Fix: Check keyid_manage_list to ensure the sender isn't blocklisted. Check keyid_get_metrics for bounce data.
Connection drops / server crashes
Fix: The server uses stdio — make sure nothing else is writing to stdout in the same process. Restart the MCP server process.
Keys auto-generated but not shown
Cause: stderr may be suppressed by your MCP client.
Fix: Run npx @keyid/agent-kit directly in a terminal first to capture the key output before adding to your MCP config.
Protocol Details
- Transport: stdio (JSON-RPC over stdin/stdout)
- MCP Protocol Version:
2024-11-05 - Auth: Ed25519 keypair — public key becomes agent identity, private key signs requests
- Compatibility: Claude Desktop, Cursor, any MCP-compatible client
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/aradotso/trending-skills/keyid-agent-kit-mcp">View keyid-agent-kit-mcp on skillZs</a>