feat: friendly tool names per MCP title field or manifest

- Aggiunto campo 'title' a tools/list in tutti gli script MCP locali
  (Gmail, Gcal, Drive, Email, SSH, Weather, Wikipedia, WhatsApp)
- Aggiunto tools[]/display_name nel manifest per connector remoti/package
  esterni (Firecrawl, HTTP Fetch, Exa, Tavily, SerpAPI Flights)
- Documentata convenzione e resolution order in SKALD.md
- Aggiornata manifest_guide.md per tools[] in connectors.json
- Bumped version e sha256 per tutti i 13 connector
This commit is contained in:
2026-07-21 23:43:24 +01:00
parent ad0909b18d
commit 955b1ba069
23 changed files with 536 additions and 122 deletions
+16 -1
View File
@@ -1,6 +1,6 @@
# Skald Connectors Marketplace
_Updated: 2026-07-19_
_Updated: 2026-07-21_
**Remote**: `https://git.skaldagent.net/dguiducci/skald-connectors.git`
**Live**: `https://connectors.skaldagent.net/`
@@ -33,6 +33,21 @@ Due tipi di connector:
- **`mcp_remote`** — un MCP server già hosted, accessibile via URL (es. Tavily).
- **`mcp_local`** — script Python/Node da eseguire lato client (es. Gmail, Google Calendar).
## Friendly tool names (2026-07-21)
Ogni tool MCP deve esporre un nome friendly per la UI di Skald. Due modi, in ordine di preferenza:
1. **Via script MCP (preferito)** — aggiungere `"title": "Friendly Name"` nella definizione di ogni tool dentro `tools/list`. Funziona per tutti gli script locali (Python/Node) che controlliamo.
2. **Via manifest (fallback)** — aggiungere `"tools": [{"name": "...", "display_name": "..."}]` in `connector.json` **e** in `connectors.json`. Usato solo per connector remoti o package esterni (es. `npx -y firecrawl-mcp`).
**Ordine di risoluzione** (Skald li prova in quest'ordine):
1. `tools[].display_name` dal manifest
2. `title` dal `tools/list` dell'MCP server
3. Prettify automatico del nome raw (`send_message` → "Send Message")
Stato attuale (2026-07-21): tutti i 13 connector del marketplace hanno `title` nello script o `tools[]` nel manifest.
## Struttura directory
```
+223 -53
View File
@@ -28,9 +28,9 @@
]
},
"folder": "gmail",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "connector.json",
@@ -39,7 +39,7 @@
},
{
"path": "gmail_mcp_server.py",
"sha256": "e96568dda3d0198be0a34092458dac2aaafee4a7e282a3fb427923f517e536e3",
"sha256": "4607ec1fee8fcbdb81619286900e44e4c04a479156f8959f553dce28b69bba66",
"size": 47789
},
{
@@ -85,9 +85,9 @@
]
},
"folder": "gcal",
"version": 1,
"version_string": "0.3.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "0.3.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "connector.json",
@@ -96,7 +96,7 @@
},
{
"path": "gcal_mcp_server.py",
"sha256": "c526751c8891a8d97ba37d14da282d223be7cd061eb67c76cea6a12672921db0",
"sha256": "a4a58a04b1df28fc45ea3bcdc5837ba00d740a9bae972a67c6c690dcd2c21bbe",
"size": 38177
},
{
@@ -149,9 +149,9 @@
]
},
"folder": "drive",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "connector.json",
@@ -160,7 +160,7 @@
},
{
"path": "drive_mcp_server.py",
"sha256": "d8cd3d96abebb2a2ab333c5489eb07d28d906c21a0aeaa7551dee49bdbebc527",
"sha256": "422b63e55b5d33aba0650cccd29def007dd4fd8d25497a94b051b2ba7eec3e44",
"size": 19971
},
{
@@ -207,9 +207,9 @@
"type": "password"
},
"folder": "email",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "connector.json",
@@ -218,7 +218,7 @@
},
{
"path": "email_mcp_server.py",
"sha256": "e8e0efc7d07be0d743f73ae80b15c924a763e57fc19000b1ef1e98237465da0f",
"sha256": "3018e44460f10f41e303bfd2fbca0eee4f1f0ad58a13c5c480e28e4d6be126c3",
"size": 54522
},
{
@@ -256,13 +256,13 @@
"type": "api_key"
},
"folder": "exa",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "connector.json",
"sha256": "65d979906e37daee32c0f9e53f29b62a2003f44c8c3ae7899c0bdab78e4c78c0",
"sha256": "7f5cd8fbd8aaa9e65b6b90411e3d1121e1d8be8d6c56a49930b1ccf83cd5c46c",
"size": 1409
},
{
@@ -280,6 +280,16 @@
"sha256": "a1b698035af2cb146dccd57f992155359d55a48bc85802e2a02e8148dcec1558",
"size": 3730
}
],
"tools": [
{
"name": "web_search_exa",
"display_name": "Web Search"
},
{
"name": "web_fetch_exa",
"display_name": "Web Fetch"
}
]
},
{
@@ -306,13 +316,13 @@
"type": "api_key"
},
"folder": "firecrawl",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "connector.json",
"sha256": "39002ac49f6ebd93aabb9f80c1fa33c0298344f5e3a734151a6ea1e4d00639b9",
"sha256": "550dcee80d84833d4c0f9aa305096544dcff2f300a206120e640e0741c71ed89",
"size": 2600
},
{
@@ -325,6 +335,112 @@
"sha256": "3a4be30d4c16ce93a1d132e063dfdffb8bd27b6c97715c9f3b12414439aaeb01",
"size": 6858
}
],
"tools": [
{
"name": "firecrawl_scrape",
"display_name": "Scrape URL"
},
{
"name": "firecrawl_map",
"display_name": "Map Site"
},
{
"name": "firecrawl_search",
"display_name": "Web Search"
},
{
"name": "firecrawl_search_feedback",
"display_name": "Search Feedback"
},
{
"name": "firecrawl_feedback",
"display_name": "Feedback"
},
{
"name": "firecrawl_crawl",
"display_name": "Crawl Site"
},
{
"name": "firecrawl_check_crawl_status",
"display_name": "Check Crawl Status"
},
{
"name": "firecrawl_extract",
"display_name": "Extract Data"
},
{
"name": "firecrawl_agent",
"display_name": "Research Agent"
},
{
"name": "firecrawl_agent_status",
"display_name": "Agent Status"
},
{
"name": "firecrawl_interact",
"display_name": "Interact with Page"
},
{
"name": "firecrawl_interact_stop",
"display_name": "Stop Interact"
},
{
"name": "firecrawl_parse",
"display_name": "Parse"
},
{
"name": "firecrawl_monitor_create",
"display_name": "Create Monitor"
},
{
"name": "firecrawl_monitor_list",
"display_name": "List Monitors"
},
{
"name": "firecrawl_monitor_get",
"display_name": "Get Monitor"
},
{
"name": "firecrawl_monitor_update",
"display_name": "Update Monitor"
},
{
"name": "firecrawl_monitor_delete",
"display_name": "Delete Monitor"
},
{
"name": "firecrawl_monitor_run",
"display_name": "Run Monitor"
},
{
"name": "firecrawl_monitor_checks",
"display_name": "List Checks"
},
{
"name": "firecrawl_monitor_check",
"display_name": "Get Check"
},
{
"name": "firecrawl_research_search_papers",
"display_name": "Search Papers"
},
{
"name": "firecrawl_research_inspect_paper",
"display_name": "Inspect Paper"
},
{
"name": "firecrawl_research_related_papers",
"display_name": "Related Papers"
},
{
"name": "firecrawl_research_read_paper",
"display_name": "Read Paper"
},
{
"name": "firecrawl_research_search_github",
"display_name": "Search GitHub"
}
]
},
{
@@ -351,13 +467,13 @@
"type": "none"
},
"folder": "http-fetch",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "connector.json",
"sha256": "67d44752fddca27f6093193264963c6658d66ce36917591eba7bde9e904389f2",
"sha256": "82dd6405f0b2cebd5361a47f04c3366b64958e9fd0a5386d1b48997acc4c632a",
"size": 1259
},
{
@@ -370,6 +486,32 @@
"sha256": "3e5496d949062678ae44cd74430b29232bbfe28a7600038deb3159c4b26adee1",
"size": 382
}
],
"tools": [
{
"name": "fetch_html",
"display_name": "Fetch as HTML"
},
{
"name": "fetch_markdown",
"display_name": "Fetch as Markdown"
},
{
"name": "fetch_txt",
"display_name": "Fetch as Text"
},
{
"name": "fetch_json",
"display_name": "Fetch as JSON"
},
{
"name": "fetch_readable",
"display_name": "Fetch Readable Content"
},
{
"name": "fetch_youtube_transcript",
"display_name": "Get YouTube Transcript"
}
]
},
{
@@ -391,13 +533,13 @@
"type": "api_key"
},
"folder": "serpapi-flights",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "connector.json",
"sha256": "7c2bd621f461001483787036c5692021f34f3838b90e215be00cae470103526a",
"sha256": "14793ce1dd53440203f451d4fd43a24daa104403849c7d72dea8b36773ee72e2",
"size": 1352
},
{
@@ -415,6 +557,12 @@
"sha256": "5a2ffa7f2502fd27dc0027395db2c863bb544c8de1eef8131a5228d87402c8e6",
"size": 574
}
],
"tools": [
{
"name": "serpapi_search_flights",
"display_name": "Search Flights"
}
]
},
{
@@ -440,9 +588,9 @@
"type": "none"
},
"folder": "ssh",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "connector.json",
@@ -451,7 +599,7 @@
},
{
"path": "ssh_mcp_server.py",
"sha256": "fbd7aa9dfad0da57f4b3d9d437c76fd978145c8364ed5fdfdfc3ba7ccfaf117b",
"sha256": "68509094a35578ffaaf357e13b55e1bfcf397f16a3b993719c4c3b97ab2dc798",
"size": 49764
},
{
@@ -488,13 +636,13 @@
"type": "api_key"
},
"folder": "tavily",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "connector.json",
"sha256": "40f191b9112f6e05e906836ead22db4c96a73c89a68db9c0ac5820473edcaad0",
"sha256": "c5ca9a7c848c0e55a8a55e482028e8607bd8adea3d94f25e210fce9833563e87",
"size": 1072
},
{
@@ -512,6 +660,28 @@
"sha256": "35a4f3b518c79363893c0438b1932b68e2dc5b4b61303037984488f6967b73a4",
"size": 2057
}
],
"tools": [
{
"name": "tavily_search",
"display_name": "Web Search"
},
{
"name": "tavily_extract",
"display_name": "Extract Content"
},
{
"name": "tavily_crawl",
"display_name": "Crawl Site"
},
{
"name": "tavily_map",
"display_name": "Map Site"
},
{
"name": "tavily_research",
"display_name": "Deep Research"
}
]
},
{
@@ -534,13 +704,13 @@
"type": "none"
},
"folder": "weather",
"version": 3,
"version_string": "3.0.0",
"version_release_date": "2026-07-19",
"version": 4,
"version_string": "3.0.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "weather_mcp_server.py",
"sha256": "5927333dee45ec5db1134034ee5af51d9e2fd95b6d128834de9a882e499b0ce4",
"sha256": "2b1c40f927d3095806504ae3c82ace156e6079294cf15c6c2c47df1422068185",
"size": 29865
},
{
@@ -587,9 +757,9 @@
"type": "qr"
},
"folder": "whatsapp",
"version": 2,
"version_string": "2.0.2",
"version_release_date": "2026-07-19",
"version": 3,
"version_string": "2.0.3",
"version_release_date": "2026-07-21",
"files": [
{
"path": "connector.json",
@@ -598,7 +768,7 @@
},
{
"path": "index.js",
"sha256": "1627f115a1bfb5a954abd412dba76c38f7202640258d3cbc08c313c00446a14a",
"sha256": "0bfaa3c5449f22a4e2c4c99c6e9402bb24651647eca9a36dbd7a639c95a6bfd6",
"size": 21668
},
{
@@ -638,13 +808,13 @@
"type": "none"
},
"folder": "wikipedia",
"version": 3,
"version_string": "3.0.0",
"version_release_date": "2026-07-19",
"version": 4,
"version_string": "3.0.1",
"version_release_date": "2026-07-21",
"files": [
{
"path": "wikipedia_mcp_server.py",
"sha256": "e8dcf08a23c2b61c366acc1f46ca2d18332438b8a1d832d46d7b680641b68c59",
"sha256": "ce9feed6a8b0a29ed405dbfe90743816d7f0714f1b580671bac722112bb54146",
"size": 12110
},
{
@@ -670,4 +840,4 @@
]
}
]
}
}
+5 -5
View File
@@ -1,9 +1,9 @@
{
"id": "drive",
"name": "Google Drive",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"type": "mcp_local",
"scope": "user",
"launch_command": "python3 drive_mcp_server.py",
@@ -31,7 +31,7 @@
"docs": [
{
"lang": "en",
"description": "Full Google Drive integration: list, search, upload, download, delete files and folders. Uses the same OAuth pattern as Gmail and Google Calendar your Google Drive credentials are managed by Skald.",
"description": "Full Google Drive integration: list, search, upload, download, delete files and folders. Uses the same OAuth pattern as Gmail and Google Calendar \u2014 your Google Drive credentials are managed by Skald.",
"llm_short_description": "Google Drive MCP server: list_files, search_files, upload_file, download_file, delete_file, create_folder, get_file_metadata. Manages files and folders on the user's Google Drive. Requires OAuth setup."
}
],
@@ -60,4 +60,4 @@
"homepage": "https://drive.google.com",
"icon_small": "icon_sm.svg",
"icon_large": "icon_lg.svg"
}
}
+11 -10
View File
@@ -318,7 +318,7 @@ def _status() -> dict:
# ── Tool registry ──────────────────────────────────────────────────────────
TOOLS: dict[str, tuple[Callable, str, dict]] = {
TOOLS: dict[str, tuple[Callable, str, dict, str]] = {
"status": (
_status,
"Check if the Drive API is reachable and credentials are valid.",
@@ -327,7 +327,7 @@ TOOLS: dict[str, tuple[Callable, str, dict]] = {
"properties": {},
"required": [],
},
),
"Status"),
"list_files": (
_list_files,
"List files in a folder (or root if no folder_id given). Returns paginated results.",
@@ -352,7 +352,7 @@ TOOLS: dict[str, tuple[Callable, str, dict]] = {
},
"required": [],
},
),
"List Files"),
"search_files": (
_search_files,
"Search files across Drive by name or content.",
@@ -371,7 +371,7 @@ TOOLS: dict[str, tuple[Callable, str, dict]] = {
},
"required": ["query"],
},
),
"Search Files"),
"get_file_metadata": (
_get_file_metadata,
"Get detailed metadata for a specific file by ID.",
@@ -385,7 +385,7 @@ TOOLS: dict[str, tuple[Callable, str, dict]] = {
},
"required": ["file_id"],
},
),
"Get File Metadata"),
"upload_file": (
_upload_file,
"Upload a local file to Google Drive.",
@@ -409,7 +409,7 @@ TOOLS: dict[str, tuple[Callable, str, dict]] = {
},
"required": ["local_path"],
},
),
"Upload File"),
"download_file": (
_download_file,
"Download a file from Drive. Returns base64 content if no output_path, or saves to disk.",
@@ -428,7 +428,7 @@ TOOLS: dict[str, tuple[Callable, str, dict]] = {
},
"required": ["file_id"],
},
),
"Download File"),
"delete_file": (
_delete_file,
"Permanently delete a file from Google Drive.",
@@ -442,7 +442,7 @@ TOOLS: dict[str, tuple[Callable, str, dict]] = {
},
"required": ["file_id"],
},
),
"Delete File"),
"create_folder": (
_create_folder,
"Create a new folder in Google Drive.",
@@ -461,7 +461,7 @@ TOOLS: dict[str, tuple[Callable, str, dict]] = {
},
"required": ["name"],
},
),
"Create Folder"),
}
@@ -496,10 +496,11 @@ def _handle_request(req: dict) -> None:
# List available tools
if method == "tools/list":
tool_list = []
for name, (fn, desc, schema) in sorted(TOOLS.items()):
for name, (fn, desc, schema, title) in sorted(TOOLS.items()):
tool_list.append({
"name": name,
"description": desc,
"title": title,
"inputSchema": schema,
})
_send_response(rid, {"tools": tool_list})
+4 -4
View File
@@ -125,7 +125,7 @@
"auth": {
"type": "password"
},
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19"
}
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21"
}
+10
View File
@@ -1152,6 +1152,7 @@ def _email_download_attachments(args: dict) -> str:
TOOLS = [
{
"name": "status",
"title": "Status",
"description": (
"Self-check that the email integration is operational: verifies IMAP and SMTP both "
"authenticate with the configured credentials. Call this first whenever another email "
@@ -1161,6 +1162,7 @@ TOOLS = [
},
{
"name": "list_messages",
"title": "List Messages",
"description": (
"List messages in a folder (default INBOX), newest first. The optional 'query' supports "
"a Gmail-like mini-syntax: from:x, to:x, subject:x, since:YYYY-MM-DD, before:YYYY-MM-DD, "
@@ -1180,6 +1182,7 @@ TOOLS = [
},
{
"name": "get_message",
"title": "Get Message",
"description": (
"Get the full content of a message by its UID, including body text (truncated at 10000 "
"chars; HTML-only emails are converted to readable text). Attachment filenames are "
@@ -1198,6 +1201,7 @@ TOOLS = [
},
{
"name": "get_thread",
"title": "Get Thread",
"description": (
"Best-effort thread reconstruction for a message UID: gathers messages in the same "
"folder that share the Message-ID reference chain (In-Reply-To/References) or the same "
@@ -1214,11 +1218,13 @@ TOOLS = [
},
{
"name": "list_folders",
"title": "List Folders",
"description": "List all IMAP folders/mailboxes with total and unread message counts. Use to discover folder names for the other tools.",
"inputSchema": {"type": "object", "properties": {}},
},
{
"name": "modify_message",
"title": "Modify Message",
"description": (
"Change a message's state: add/remove flags, mark read/unread, move to another folder, "
"archive or delete. Friendly flag names: 'read'/'seen', 'flagged'/'starred', 'answered', "
@@ -1243,6 +1249,7 @@ TOOLS = [
},
{
"name": "send_message",
"title": "Send Message",
"description": (
"Send an email via SMTP. Supports in-thread replies by passing in_reply_to (the "
"Message-ID of the message being replied to, with or without angle brackets), which sets "
@@ -1267,11 +1274,13 @@ TOOLS = [
},
{
"name": "get_profile",
"title": "Get Profile",
"description": "Show the configured account: username, From address, IMAP/SMTP servers, folder count, and INBOX total/unread.",
"inputSchema": {"type": "object", "properties": {}},
},
{
"name": "create_folder",
"title": "Create Folder",
"description": "Create a new IMAP folder/mailbox. Fails if it already exists.",
"inputSchema": {
"type": "object",
@@ -1283,6 +1292,7 @@ TOOLS = [
},
{
"name": "download_attachments",
"title": "Download Attachments",
"description": (
"Download all attachments from a message to a local folder (default data/email_attachments/). "
"Returns the absolute path and size of each saved file. Pass 'folder' if the message is not in INBOX."
+16 -6
View File
@@ -1,9 +1,9 @@
{
"id": "exa",
"name": "Exa",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"type": "mcp_remote",
"scope": "global",
"tags": [
@@ -15,7 +15,7 @@
"docs": [
{
"lang": "en",
"description": "AI-powered web search, content extraction, and embeddings via Exa's neural search engine. Perfect for deep research, finding specific information, and analyzing page content. Works without an API key (free rate-limited tier) add your own key for higher limits.",
"description": "AI-powered web search, content extraction, and embeddings via Exa's neural search engine. Perfect for deep research, finding specific information, and analyzing page content. Works without an API key (free rate-limited tier) \u2014 add your own key for higher limits.",
"llm_short_description": "Search the web and extract page content using Exa's neural search engine. Tools: web_search_exa, web_fetch_exa."
}
],
@@ -42,5 +42,15 @@
},
"homepage": "https://exa.ai",
"icon_small": "icon_sm.png",
"icon_large": "icon_lg.png"
}
"icon_large": "icon_lg.png",
"tools": [
{
"name": "web_search_exa",
"display_name": "Web Search"
},
{
"name": "web_fetch_exa",
"display_name": "Web Fetch"
}
]
}
+110 -4
View File
@@ -60,7 +60,113 @@
"browser",
"research"
],
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19"
}
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"tools": [
{
"name": "firecrawl_scrape",
"display_name": "Scrape URL"
},
{
"name": "firecrawl_map",
"display_name": "Map Site"
},
{
"name": "firecrawl_search",
"display_name": "Web Search"
},
{
"name": "firecrawl_search_feedback",
"display_name": "Search Feedback"
},
{
"name": "firecrawl_feedback",
"display_name": "Feedback"
},
{
"name": "firecrawl_crawl",
"display_name": "Crawl Site"
},
{
"name": "firecrawl_check_crawl_status",
"display_name": "Check Crawl Status"
},
{
"name": "firecrawl_extract",
"display_name": "Extract Data"
},
{
"name": "firecrawl_agent",
"display_name": "Research Agent"
},
{
"name": "firecrawl_agent_status",
"display_name": "Agent Status"
},
{
"name": "firecrawl_interact",
"display_name": "Interact with Page"
},
{
"name": "firecrawl_interact_stop",
"display_name": "Stop Interact"
},
{
"name": "firecrawl_parse",
"display_name": "Parse"
},
{
"name": "firecrawl_monitor_create",
"display_name": "Create Monitor"
},
{
"name": "firecrawl_monitor_list",
"display_name": "List Monitors"
},
{
"name": "firecrawl_monitor_get",
"display_name": "Get Monitor"
},
{
"name": "firecrawl_monitor_update",
"display_name": "Update Monitor"
},
{
"name": "firecrawl_monitor_delete",
"display_name": "Delete Monitor"
},
{
"name": "firecrawl_monitor_run",
"display_name": "Run Monitor"
},
{
"name": "firecrawl_monitor_checks",
"display_name": "List Checks"
},
{
"name": "firecrawl_monitor_check",
"display_name": "Get Check"
},
{
"name": "firecrawl_research_search_papers",
"display_name": "Search Papers"
},
{
"name": "firecrawl_research_inspect_paper",
"display_name": "Inspect Paper"
},
{
"name": "firecrawl_research_related_papers",
"display_name": "Related Papers"
},
{
"name": "firecrawl_research_read_paper",
"display_name": "Read Paper"
},
{
"name": "firecrawl_research_search_github",
"display_name": "Search GitHub"
}
]
}
+4 -4
View File
@@ -54,7 +54,7 @@
"homepage": "https://calendar.google.com",
"icon_small": "icon_sm.svg",
"icon_large": "icon_lg.svg",
"version": 1,
"version_string": "0.3.0",
"version_release_date": "2026-07-19"
}
"version": 2,
"version_string": "0.3.1",
"version_release_date": "2026-07-21"
}
+8
View File
@@ -684,6 +684,7 @@ TOOLS = [
# ── Self-check ─────────────────────────────────────────────────────────────
{
"name": "status",
"title": "Status",
"description": (
"Self-check that the Google Calendar integration is operational: verifies the OAuth "
"credentials load, the access token refreshes when needed, and the Calendar API responds, "
@@ -695,11 +696,13 @@ TOOLS = [
# ── Read-only ──────────────────────────────────────────────────────────────
{
"name": "list_calendars",
"title": "List Calendars",
"description": "Lists all calendars accessible to the authenticated user. Use it to discover calendar_id values to pass to the other gcal tools.",
"inputSchema": {"type": "object", "properties": {}},
},
{
"name": "list_events",
"title": "List Events",
"description": (
"Lists calendar events from a given calendar, ordered chronologically. "
"If time_min is omitted, defaults to NOW (current UTC time) — so you never get past events by accident. "
@@ -738,6 +741,7 @@ TOOLS = [
},
{
"name": "get_event",
"title": "Get Event",
"description": "Returns a single calendar event by ID, including attendees with their RSVP status.",
"inputSchema": {
"type": "object",
@@ -757,6 +761,7 @@ TOOLS = [
# ── Write ──────────────────────────────────────────────────────────────────
{
"name": "create_event",
"title": "Create Event",
"description": (
"Creates a new event in the specified calendar and returns its ID + HTML link. "
"Use ISO 8601 for start/end (e.g. '2025-06-15T10:00:00' for timed events, "
@@ -814,6 +819,7 @@ TOOLS = [
},
{
"name": "update_event",
"title": "Update Event",
"description": (
"Updates an existing event. Only fields provided are changed; omitted fields keep their "
"current values. Returns the updated event ID."
@@ -854,6 +860,7 @@ TOOLS = [
},
{
"name": "delete_event",
"title": "Delete Event",
"description": "Permanently deletes a calendar event. Irreversible.",
"inputSchema": {
"type": "object",
@@ -872,6 +879,7 @@ TOOLS = [
},
{
"name": "respond_to_event",
"title": "Respond to Event",
"description": "Set your RSVP / attendance response (accepted, declined, tentative, needsAction) for a calendar event.",
"inputSchema": {
"type": "object",
+4 -4
View File
@@ -51,7 +51,7 @@
"env": "GMAIL_CREDS_JSON"
}
},
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19"
}
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21"
}
+10
View File
@@ -936,6 +936,7 @@ def _gmail_download_attachments(args: dict) -> str:
TOOLS = [
{
"name": "status",
"title": "Status",
"description": (
"Self-check that the Google Gmail integration is operational: verifies the OAuth "
"credentials load, the access token refreshes when needed, and the Gmail API responds, "
@@ -946,6 +947,7 @@ TOOLS = [
},
{
"name": "list_messages",
"title": "List Messages",
"description": (
"List Gmail messages with optional query and label filter. Returns summaries with "
"subject, sender, date, message ID and thread ID. Use Gmail search syntax in 'query' "
@@ -977,6 +979,7 @@ TOOLS = [
},
{
"name": "get_message",
"title": "Get Message",
"description": (
"Get full content of a Gmail message by ID, including body text (truncated at 10000 "
"chars). HTML-only emails are converted to readable text, and any attachment filenames "
@@ -999,6 +1002,7 @@ TOOLS = [
},
{
"name": "get_thread",
"title": "Get Thread",
"description": "Get all messages in a thread by thread ID, newest last.",
"inputSchema": {
"type": "object",
@@ -1013,6 +1017,7 @@ TOOLS = [
},
{
"name": "list_labels",
"title": "List Labels",
"description": "List all Gmail labels/folders/categories with total and unread message counts. Use to resolve label IDs for modify_message.",
"inputSchema": {
"type": "object",
@@ -1021,6 +1026,7 @@ TOOLS = [
},
{
"name": "modify_message",
"title": "Modify Message",
"description": (
"Modify message labels: mark read, archive, star, etc. Use label IDs like 'UNREAD', "
"'STARRED', 'INBOX'. remove_labels=['UNREAD'] marks as read; remove_labels=['INBOX'] "
@@ -1049,6 +1055,7 @@ TOOLS = [
},
{
"name": "send_message",
"title": "Send Message",
"description": (
"Send an email via Gmail. Supports in-thread replies via the optional in_reply_to "
"(message ID) and thread_id parameters. For a reply, pass both for correct threading "
@@ -1103,6 +1110,7 @@ TOOLS = [
},
{
"name": "get_profile",
"title": "Get Profile",
"description": "Get Gmail profile info: email address, total message/thread count, current history ID.",
"inputSchema": {
"type": "object",
@@ -1111,6 +1119,7 @@ TOOLS = [
},
{
"name": "create_label",
"title": "Create Label",
"description": "Create a new Gmail label/folder. Returns the new label ID. Fails if a label with the same name already exists.",
"inputSchema": {
"type": "object",
@@ -1135,6 +1144,7 @@ TOOLS = [
},
{
"name": "download_attachments",
"title": "Download Attachments",
"description": (
"Download all attachments from a Gmail message to a local folder. "
"Defaults to data/gmail_attachments/ (served via /data/... in the frontend). "
+30 -4
View File
@@ -42,7 +42,33 @@
"scraping",
"youtube"
],
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19"
}
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"tools": [
{
"name": "fetch_html",
"display_name": "Fetch as HTML"
},
{
"name": "fetch_markdown",
"display_name": "Fetch as Markdown"
},
{
"name": "fetch_txt",
"display_name": "Fetch as Text"
},
{
"name": "fetch_json",
"display_name": "Fetch as JSON"
},
{
"name": "fetch_readable",
"display_name": "Fetch Readable Content"
},
{
"name": "fetch_youtube_transcript",
"display_name": "Get YouTube Transcript"
}
]
}
+11 -5
View File
@@ -1,9 +1,9 @@
{
"id": "serpapi-flights",
"name": "SerpAPI Flights",
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19",
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"type": "mcp_remote",
"scope": "global",
"tags": [
@@ -43,5 +43,11 @@
},
"homepage": "https://serpapi.com/google-flights-api",
"icon_small": "icon_sm.svg",
"icon_large": "icon_lg.svg"
}
"icon_large": "icon_lg.svg",
"tools": [
{
"name": "serpapi_search_flights",
"display_name": "Search Flights"
}
]
}
+4 -4
View File
@@ -109,7 +109,7 @@
"auth": {
"type": "none"
},
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19"
}
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21"
}
+13
View File
@@ -1044,11 +1044,13 @@ _SFTP_NOTE = (
TOOLS = [
{
"name": "list_aliases",
"title": "List Aliases",
"description": "List configured SSH host aliases (never reveals keys or sudo passwords).",
"inputSchema": {"type": "object", "properties": {}},
},
{
"name": "add_alias",
"title": "Add Alias",
"description": "Register or update an SSH host alias. Login via SSH key/agent (default) or login password asked on demand via elicitation.",
"inputSchema": {
"type": "object",
@@ -1070,11 +1072,13 @@ TOOLS = [
},
{
"name": "remove_alias",
"title": "Remove Alias",
"description": "Remove a host alias and close its pooled connection.",
"inputSchema": {"type": "object", "properties": {"alias": _ALIAS}, "required": ["alias"]},
},
{
"name": "read_file",
"title": "Read File",
"description": "Read a remote file with 1-based line numbers (same format as the local read_file)." + _SFTP_NOTE,
"inputSchema": {
"type": "object",
@@ -1090,6 +1094,7 @@ TOOLS = [
},
{
"name": "list_files",
"title": "List Files",
"description": "List files/dirs under a remote path; returns a JSON array of relative paths (same as local list_files).",
"inputSchema": {
"type": "object",
@@ -1104,6 +1109,7 @@ TOOLS = [
},
{
"name": "grep_files",
"title": "Grep Files",
"description": "Search a remote path with a regex; output matches the local grep_files (uses remote grep -E).",
"inputSchema": {
"type": "object",
@@ -1122,6 +1128,7 @@ TOOLS = [
},
{
"name": "edit_file",
"title": "Edit File",
"description": "Find & replace in a remote file (atomic). `old` must match exactly once unless replace_all." + _SFTP_NOTE,
"inputSchema": {
"type": "object",
@@ -1137,6 +1144,7 @@ TOOLS = [
},
{
"name": "replace_lines",
"title": "Replace Lines",
"description": "Replace a 1-based inclusive line range in a remote file (atomic)." + _SFTP_NOTE,
"inputSchema": {
"type": "object",
@@ -1152,6 +1160,7 @@ TOOLS = [
},
{
"name": "exec",
"title": "Execute Command",
"description": "Run a command on the remote host. Set sudo=true to run via sudo (method per alias).",
"inputSchema": {
"type": "object",
@@ -1167,6 +1176,7 @@ TOOLS = [
},
{
"name": "upload",
"title": "Upload File",
"description": "Upload a local file or directory (recursive) to the remote host via SFTP." + _SFTP_NOTE,
"inputSchema": {
"type": "object",
@@ -1180,6 +1190,7 @@ TOOLS = [
},
{
"name": "download",
"title": "Download File",
"description": "Download a remote file or directory (recursive) to the local host via SFTP.",
"inputSchema": {
"type": "object",
@@ -1193,11 +1204,13 @@ TOOLS = [
},
{
"name": "sysinfo",
"title": "System Info",
"description": "Report OS, kernel, CPU count, RAM and root-disk usage, and uptime.",
"inputSchema": {"type": "object", "properties": {"alias": _ALIAS}, "required": ["alias"]},
},
{
"name": "systemd",
"title": "Manage Systemd Service",
"description": "Manage a systemd service (status/start/stop/restart/reload/enable/disable) + last 10 journal lines. Mutating actions use sudo.",
"inputSchema": {
"type": "object",
+26 -4
View File
@@ -39,7 +39,29 @@
"mcp",
"remote"
],
"version": 1,
"version_string": "1.0.0",
"version_release_date": "2026-07-19"
}
"version": 2,
"version_string": "1.0.1",
"version_release_date": "2026-07-21",
"tools": [
{
"name": "tavily_search",
"display_name": "Web Search"
},
{
"name": "tavily_extract",
"display_name": "Extract Content"
},
{
"name": "tavily_crawl",
"display_name": "Crawl Site"
},
{
"name": "tavily_map",
"display_name": "Map Site"
},
{
"name": "tavily_research",
"display_name": "Deep Research"
}
]
}
+7 -5
View File
@@ -25,7 +25,9 @@
"icon_small": "icon_sm.svg",
"icon_large": "icon_lg.svg",
"scope": "global",
"requires": ["PYTHON"],
"requires": [
"PYTHON"
],
"tags": [
"weather",
"mcp",
@@ -40,7 +42,7 @@
"weather_mcp_server.py"
]
},
"version": 3,
"version_string": "3.0.0",
"version_release_date": "2026-07-19"
}
"version": 4,
"version_string": "3.0.1",
"version_release_date": "2026-07-21"
}
+4
View File
@@ -544,6 +544,7 @@ def _weather_air_quality(args: dict[str, Any]) -> str | dict[str, Any]:
TOOLS = [
{
"name": "status",
"title": "Status",
"description": (
"Self-check that the Weather integration is operational: verifies the "
"Open-Meteo Geocoding and Forecast APIs are reachable by performing one "
@@ -555,6 +556,7 @@ TOOLS = [
},
{
"name": "get_current_weather",
"title": "Get Current Weather",
"description": (
"Get current weather conditions for any city worldwide. "
"Returns temperature, feels-like, humidity, wind (speed/direction/gusts), "
@@ -579,6 +581,7 @@ TOOLS = [
},
{
"name": "get_forecast",
"title": "Get Forecast",
"description": (
"Get multi-day weather forecast for any city worldwide. "
"Returns daily min/max temperature (and feels-like), conditions, rain probability, "
@@ -607,6 +610,7 @@ TOOLS = [
},
{
"name": "get_air_quality",
"title": "Get Air Quality",
"description": (
"Get current air quality for any city worldwide. "
"Returns European and US AQI indices, plus detailed pollutant levels: "
+4 -4
View File
@@ -44,7 +44,7 @@
"homepage": "https://github.com/WhiskeySockets/Baileys",
"icon_small": "icon_sm.png",
"icon_large": "icon_lg.png",
"version": 2,
"version_string": "2.0.2",
"version_release_date": "2026-07-19"
}
"version": 3,
"version_string": "2.0.3",
"version_release_date": "2026-07-21"
}
+7
View File
@@ -363,21 +363,25 @@ async function toolSearchContacts(args) {
const TOOLS = [
{
name: 'login_status',
title: 'Login Status',
description: 'Interactive-login status for this connector (used by the Skald login panel). Returns a JSON object {state, qr, message}: state is connecting|need_scan|ready|logged_out; qr is a data-URL PNG present only while a scan is needed. Safe to poll.',
inputSchema: { type: 'object', properties: {} },
},
{
name: 'status',
title: 'Status',
description: 'WhatsApp connection status as a short human-readable report. Call this first when another WhatsApp tool fails.',
inputSchema: { type: 'object', properties: {} },
},
{
name: 'logout',
title: 'Logout',
description: 'Log out of WhatsApp: end the session, clear the stored credentials, and generate a fresh QR code to link a (possibly different) phone. After calling, the user must scan the new QR in the Skald connector page.',
inputSchema: { type: 'object', properties: {} },
},
{
name: 'list_chats',
title: 'List Chats',
description: 'List recent WhatsApp chats (contacts and groups) with name, ID and unread count. Only chats seen since sign-in / history sync are known.',
inputSchema: {
type: 'object',
@@ -386,6 +390,7 @@ const TOOLS = [
},
{
name: 'get_messages',
title: 'Get Messages',
description: 'Get buffered messages from a chat. Identify it with EITHER chat_id (from list_chats) OR a phone number with country code for an individual contact. Only messages seen since sign-in are available (no deep history).',
inputSchema: {
type: 'object',
@@ -399,6 +404,7 @@ const TOOLS = [
},
{
name: 'send_message',
title: 'Send Message',
description: 'Send a WhatsApp text message. Identify the recipient with EITHER chat_id (from list_chats, use for groups) OR a phone number with country code for an individual contact.',
inputSchema: {
type: 'object',
@@ -412,6 +418,7 @@ const TOOLS = [
},
{
name: 'search_contacts',
title: 'Search Contacts',
description: 'Search known WhatsApp contacts by name or number. Use to find a contact ID to message.',
inputSchema: {
type: 'object',
+7 -5
View File
@@ -25,7 +25,9 @@
"icon_small": "icon_sm.svg",
"icon_large": "icon_lg.svg",
"scope": "global",
"requires": ["PYTHON"],
"requires": [
"PYTHON"
],
"tags": [
"wikipedia",
"mcp",
@@ -40,7 +42,7 @@
"wikipedia_mcp_server.py"
]
},
"version": 3,
"version_string": "3.0.0",
"version_release_date": "2026-07-19"
}
"version": 4,
"version_string": "3.0.1",
"version_release_date": "2026-07-21"
}
@@ -200,6 +200,7 @@ def _read_article(args: dict[str, Any]) -> str:
TOOLS = [
{
"name": "status",
"title": "Status",
"description": (
"Self-check that the Wikipedia integration is operational: confirms "
"the Wikipedia API is reachable by issuing a cheap siteinfo query. "
@@ -209,6 +210,7 @@ TOOLS = [
},
{
"name": "search",
"title": "Search Wikipedia",
"description": (
"Search Wikipedia articles by keyword. Returns a list of matching "
"article titles with short descriptions and URLs. Use this to find "