feat: WhatsApp + LinkedIn integrations, SquareMCP rebrand, opencode docs
WhatsApp Business API (Meta Cloud API)
- New client: src/clients/whatsapp.ts
- Tools: whatsapp_send_message, whatsapp_send_template, whatsapp_list_templates
- REST endpoints: POST /api/whatsapp/send, POST /api/whatsapp/template, GET /api/whatsapp/templates
- Multi-account env var pattern: WHATSAPP_{ACCOUNT}_*
LinkedIn API (OpenID Connect)
- New client: src/clients/linkedin.ts
- Tools: linkedin_get_profile, linkedin_create_post, linkedin_search_connections, linkedin_send_message
- REST endpoints: GET /api/linkedin/profile, POST /api/linkedin/post, POST /api/linkedin/search-connections, POST /api/linkedin/message
- Multi-account env var pattern: LINKEDIN_{ACCOUNT}_*
- Uses /v2/userinfo (OpenID Connect) for profile reads
Domain migration
- hermes.fetcherpay.com -> hermes.squaremcp.com
- Updated K8s ingress, TLS cert, SERVER_URL env var
- Updated OPENCODE.md and opencode.json references
SquareMCP site
- Added logo assets (SVG, LinkedIn variants)
- Added terms.html
- Updated Dockerfile, nginx config, styles, index, privacy pages
Docs
- Added OPENCODE.md for opencode AI integration setup
- Updated .env.example with WhatsApp and LinkedIn credentials
- Added opencode.json to .gitignore (contains live API key)
Total tools: 19 (email 6, obsidian 5, whatsapp 4, linkedin 4)
This commit is contained in:
185
src/manifest.ts
185
src/manifest.ts
@@ -390,6 +390,183 @@ export function getManifest(serverUrl: string, authEnabled: boolean) {
|
||||
],
|
||||
},
|
||||
|
||||
// ── WhatsApp Business API tools ───────────────────────────────────────
|
||||
{
|
||||
name: 'whatsapp_send_message',
|
||||
category: 'whatsapp',
|
||||
description: 'Send a WhatsApp text message to a phone number',
|
||||
when_to_use:
|
||||
'User asks to send a WhatsApp message, text someone on WhatsApp, or notify via WhatsApp. Only works if the recipient has messaged you within the last 24 hours.',
|
||||
input_schema: {
|
||||
type: 'object',
|
||||
required: ['to', 'message'],
|
||||
properties: {
|
||||
to: { type: 'string', description: 'Recipient phone number in international format (e.g. +1234567890)' },
|
||||
message: { type: 'string', description: 'Message text to send' },
|
||||
account: { type: 'string', description: 'Which WhatsApp account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
returns: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
success: { type: 'boolean' },
|
||||
message_id: { type: 'string', description: 'WhatsApp message ID' },
|
||||
},
|
||||
},
|
||||
examples: [{ to: '+1234567890', message: 'Hello from Hermes', account: 'default' }],
|
||||
},
|
||||
{
|
||||
name: 'whatsapp_send_template',
|
||||
category: 'whatsapp',
|
||||
description: 'Send an approved WhatsApp template message',
|
||||
when_to_use:
|
||||
'User wants to send a structured notification or alert via an approved WhatsApp template. Required when outside the 24-hour customer-service window.',
|
||||
input_schema: {
|
||||
type: 'object',
|
||||
required: ['to', 'template_name'],
|
||||
properties: {
|
||||
to: { type: 'string', description: 'Recipient phone number in international format' },
|
||||
template_name: { type: 'string', description: 'Name of the approved WhatsApp template' },
|
||||
language: { type: 'string', description: 'Template language code (default: "en")' },
|
||||
components: { type: 'array', description: 'Template components (header, body, buttons) with parameters' },
|
||||
account: { type: 'string', description: 'Which WhatsApp account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
returns: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
success: { type: 'boolean' },
|
||||
message_id: { type: 'string', description: 'WhatsApp message ID' },
|
||||
},
|
||||
},
|
||||
examples: [{ to: '+1234567890', template_name: 'hello_world', language: 'en', account: 'default' }],
|
||||
},
|
||||
{
|
||||
name: 'whatsapp_list_templates',
|
||||
category: 'whatsapp',
|
||||
description: 'List all approved WhatsApp message templates for the business account',
|
||||
when_to_use:
|
||||
'User asks what WhatsApp templates are available or wants to know which templates can be sent.',
|
||||
input_schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
account: { type: 'string', description: 'Which WhatsApp account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
returns: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
templates: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string' },
|
||||
language: { type: 'string' },
|
||||
status: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
examples: [{ account: 'default' }],
|
||||
},
|
||||
|
||||
// ── LinkedIn tools ──────────────────────────────────────────────────────
|
||||
{
|
||||
name: 'linkedin_get_profile',
|
||||
category: 'linkedin',
|
||||
description: 'Get the LinkedIn profile of the authenticated user',
|
||||
when_to_use:
|
||||
'User asks about their LinkedIn profile, name, headline, or wants to verify which LinkedIn account is connected.',
|
||||
input_schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
account: { type: 'string', description: 'Which LinkedIn account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
returns: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'LinkedIn person ID (OpenID sub)' },
|
||||
firstName: { type: 'string' },
|
||||
lastName: { type: 'string' },
|
||||
email: { type: 'string' },
|
||||
picture: { type: 'string', description: 'Profile photo URL' },
|
||||
},
|
||||
},
|
||||
examples: [{ account: 'default' }],
|
||||
},
|
||||
{
|
||||
name: 'linkedin_create_post',
|
||||
category: 'linkedin',
|
||||
description: 'Create a post on LinkedIn',
|
||||
when_to_use:
|
||||
'User wants to publish an update, share content, or post to their LinkedIn feed.',
|
||||
input_schema: {
|
||||
type: 'object',
|
||||
required: ['text'],
|
||||
properties: {
|
||||
text: { type: 'string', description: 'Post content text' },
|
||||
visibility: { type: 'string', enum: ['PUBLIC', 'CONNECTIONS'], description: 'PUBLIC (anyone) or CONNECTIONS (1st degree only)' },
|
||||
account: { type: 'string', description: 'Which LinkedIn account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
returns: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
success: { type: 'boolean' },
|
||||
post_id: { type: 'string' },
|
||||
url: { type: 'string', description: 'Direct link to the post' },
|
||||
},
|
||||
},
|
||||
examples: [{ text: 'Excited to share our latest product update!', visibility: 'PUBLIC', account: 'default' }],
|
||||
},
|
||||
{
|
||||
name: 'linkedin_search_connections',
|
||||
category: 'linkedin',
|
||||
description: 'Search LinkedIn connections [REQUIRES PARTNERSHIP]',
|
||||
when_to_use:
|
||||
'User wants to search their LinkedIn network. NOTE: Requires LinkedIn Partnership Program — public API access was removed.',
|
||||
input_schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
keywords: { type: 'string', description: 'Search keywords' },
|
||||
account: { type: 'string', description: 'Which LinkedIn account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
returns: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
message: { type: 'string', description: 'Error or guidance message' },
|
||||
},
|
||||
},
|
||||
examples: [{ keywords: 'software engineer', account: 'default' }],
|
||||
},
|
||||
{
|
||||
name: 'linkedin_send_message',
|
||||
category: 'linkedin',
|
||||
description: 'Send a direct message on LinkedIn [REQUIRES PARTNERSHIP]',
|
||||
when_to_use:
|
||||
'User wants to send a LinkedIn DM. NOTE: Requires LinkedIn Partnership Program — messaging is not available through the public API.',
|
||||
input_schema: {
|
||||
type: 'object',
|
||||
required: ['recipient_id', 'message'],
|
||||
properties: {
|
||||
recipient_id: { type: 'string', description: 'LinkedIn person URN or ID' },
|
||||
message: { type: 'string', description: 'Message text' },
|
||||
account: { type: 'string', description: 'Which LinkedIn account to use (default: "default")' },
|
||||
},
|
||||
},
|
||||
returns: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
message: { type: 'string', description: 'Error or guidance message' },
|
||||
},
|
||||
},
|
||||
examples: [{ recipient_id: 'urn:li:person:abc123', message: 'Hi, thanks for connecting!', account: 'default' }],
|
||||
},
|
||||
|
||||
// ── Obsidian tools ──────────────────────────────────────────────────────
|
||||
{
|
||||
name: 'obsidian_search_notes',
|
||||
@@ -549,6 +726,14 @@ export function getManifest(serverUrl: string, authEnabled: boolean) {
|
||||
description: 'Email operations for Yahoo, FetcherPay, and Gmail accounts',
|
||||
icon: '📧',
|
||||
},
|
||||
whatsapp: {
|
||||
description: 'WhatsApp Business API messaging via Meta Cloud API',
|
||||
icon: '💬',
|
||||
},
|
||||
linkedin: {
|
||||
description: 'LinkedIn profile and posting via LinkedIn API',
|
||||
icon: '🔗',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user