MCP servers
An MCP server gives an MCP client — Claude, Claude Code, Cursor, a script — a set of your nodes as tools. You choose exactly which nodes. The client gets one URL and six tools, however many nodes are behind them.
What a server is
A server is a list of nodes, kept under Settings → MCP Servers. Every node on it must have AI toolkit mode turned on: that switch, on the node, is your consent, and a node without it can't be added. Each node brings its toolkit — a Gmail node its email operations, a Slack node its messaging ones — and the client reaches all of them through the same six tools.
Running an operation runs that one node, with its own credential and settings. It does not run the flow the node sits in.
Nodes you can expose
Gmail, Email, Google Calendar, Google Drive, Google Sheets, Google Docs, Google Contacts, Google Analytics, Outlook, Outlook Calendar, OneDrive, Excel, Word, Microsoft Teams, Slack, Discord, Telegram, Social Media, MongoDB, PostgreSQL, Airtable, Notion, Jira, GitHub, Bucket, Firecrawl, Apify, Calendly, Mailchimp, Shopify, WooCommerce, ElevenLabs and RSS. Any other node type is refused when you save the server. The node's page in these docs lists the tools of its toolkit.
Creating a server
Turn on AI toolkit mode on each node
On the node's page. Only nodes with it on show up in the server's picker. While you are there, block what no client should ever run — see Blocking tools.
Settings → MCP Servers → New server
Give it a name — it is what the client will call this connection — and tick the nodes it can use. You can also start from a node: its page has an Expose as MCP tool card that adds it to an existing server, or opens a new one with the node already ticked.
Create, then copy the token if you need it
The server opens with its Connect panel. The token at the top is shown this once and can't be shown again. You only need it for clients that can't sign in — see With a token.
Connecting a client
Every server has its own URL, shown at the top of its page with a Copy URL button:
https://api.hostwebhook.com/api/mcp/<serverId>The same server accepts all of the ways below at once. Which one to use depends on where you will use it, not on the server.
With your Claude account
For claude.ai, the desktop app, the phone and Cowork — added once, it is there wherever you sign in. In Claude, go to Customize → Connectors, click Add custom connector and paste the server URL. You sign in to HostWebhook, review what the app is asking for, and approve. There is nothing to copy or keep safe.
With Claude Code
Run this, with the name and URL of your server. Your browser opens; approve there and the connection is done.
claude mcp add --scope user --transport http my-tools https://api.hostwebhook.com/api/mcp/<serverId>Keep --scope user. Without it the server is saved only for the folder you ran the command from, and Claude Code won't see it anywhere else. It stays on this machine either way.
With a token
For a script, a server with no browser, Cursor or VS Code: send the token you copied at creation in every request.
Authorization: Bearer mcp_…A client that speaks HTTP natively takes the URL and the header:
{
"mcpServers": {
"my-tools": {
"url": "https://api.hostwebhook.com/api/mcp/<serverId>",
"headers": { "Authorization": "Bearer mcp_…" }
}
}
}Claude Desktop configured by file goes through mcp-remote. The Connect panel has the snippet for Windows and for Mac / Linux, with your URL already in it; it goes in claude_desktop_config.json.
What a sign-in connection is allowed to do
When a client connects through sign-in, the approval screen says which app gets access, where the access is sent, and what it may do:
| Scope | Allows |
|---|---|
mcp:read | Listing the server's tools, and reading the last payload of each node. |
mcp:invoke | Calling tools — all six, including discover_operations and the run history. |
A sign-in is valid for the one server it was given for, never for another server of the same organization. Its access lasts an hour and the client renews it; one left unused for 30 days has to sign in again. Deleting the server cuts every sign-in at once. A token, unlike a sign-in, has no scopes: it can do everything the server allows.
The six tools
| Tool | What it does |
|---|---|
discover_operations | Searches the operations this server can run. Read-only, and it never leaves HostWebhook. |
run_read_operation | Runs one operation that only reads — listing, searching, fetching. |
run_write_operation | Runs one operation that adds without overwriting — sending, creating, posting. |
run_destructive_operation | Runs one operation that overwrites or deletes existing data. |
list_recent_runs | Lists the recent runs that started from this server's nodes or went through them, newest first. Read-only. |
show_run | Shows one run: the path it took, which step failed, how long each took. Read-only. |
Six with three nodes and six with three hundred. Clients only show a few dozen tools and drop the rest without saying so, so publishing every operation as its own tool would lose tools on any server with a handful of toolkits. Instead the client searches, then runs what it found. The individual operation names — send_email, list_files — are not tools of their own and can't be called directly.
The description of discover_operations names the integrations behind it and how many operations each has — Available here: Gmail (16), Slack (16)… — so the model knows from the start what is worth looking for.
Finding and running an operation
discover_operations takes three optional arguments: query (free text; every word has to match the operation's name, its description, its node or its integration), integration (e.g. Gmail) and limit (20 by default, 100 at most). With three results or fewer, each one comes with its full input schema, so the model can run it straight away; with more, it narrows the search first.
{
"operations": [
{
"operationId": "gmail-sales.send_email",
"integration": "Gmail",
"node": "Gmail sales",
"name": "send_email",
"kind": "write",
"description": "Send a fresh Gmail message…",
"runWith": "run_write_operation",
"inputSchema": {
"type": "object",
"properties": { "to": …, "subject": …, "body": …, "cc": …, "bcc": … },
"required": ["to", "subject", "body"]
}
}
],
"total": 1,
"truncated": false,
"detail": "full"
}The model then calls the tool named in runWith, with the operationId and the operation's own arguments:
{
"name": "run_write_operation",
"arguments": {
"operationId": "gmail-sales.send_email",
"arguments": {
"to": "ana@example.com",
"subject": "Your order",
"body": "<p>It shipped today.</p>"
}
}
}Operation ids
An operationId is the node's name, lowercased and with dashes, a dot, and the tool: gmail-sales.send_email. It says which node — which account — the call goes through, so two Gmail nodes on one server are two different sets of operations. When two nodes would get the same id, both get the last six characters of their node id appended.
discover_operations.Read, write, destructive
Each operation goes through exactly one of the three run tools, and the others refuse it. That is what lets a client trust the annotations: run_read_operation is marked read-only, so a client may run it without asking you, and nothing that writes can get through it. Sent through the wrong one, the answer names the right one:
"gmail-sales.send_email" is a write operation. Call it with run_write_operation instead.Which is which comes from what the operation does — reading, adding, or overwriting and deleting. An operation whose effect isn't known is treated as destructive.
Arguments
Arguments are checked before anything runs. A missing required argument, one the operation doesn't accept, or a value of the wrong type — an object where text goes — is refused, and the answer carries the operation's input schema so the model can retry right:
Cannot run "gmail-sales.send_email": missing required: subject. Its input schema is {…}Arguments sent flat next to operationId, or nested as a JSON string, are accepted too. An argument the operation doesn't declare is never passed on: it fails instead of being silently ignored.
Blocking tools
Two levels, both on the node:
- AI toolkit mode off — the whole node is gone: its operations stop being discoverable and runnable at once, on every server it is on. It stays on the server's list and comes back when you turn the switch on again.
- Block these tool calls — in the node's AI toolkit section, one switch per tool. A blocked tool is not offered by
discover_operations, and a client that calls it anyway — with an id it found before you blocked it — gets:
The tool "delete_email" is blocked on this node by its owner. Do not retry it; tell the user it is not allowed here.Some tools are born blocked — mostly ones that delete, cancel, refund, share or merge, plus a few that are slow or cost money per call, like Firecrawl's crawl_site and ElevenLabs' make_outbound_call. The node's switches show which; unblock them there. A block applies to every server and every AI Node that uses the node, and the node refuses the call itself as well, so there is no way around it. See MongoDB for how the switches look.
Run history from the client
list_recent_runs lists the most recent runs this server can see, newest first: the ones that started from one of its nodes or went through one of them, and the ones its own calls started. Runs of the rest of your organization don't appear, not even as a count. It returns 10 by default and 50 at most, says when there are older ones, and with sourceId lists only the runs started by one node. A run started by a node that is not on this server — one that went through its nodes on the way — comes back without its source's name or type.
show_run takes a run id from that list and shows the path the event took, which step failed and how long each took. It sees the same runs as the list: given the id of a run this server can't see, it answers No run with that id., exactly as for an id that doesn't exist. Steps of nodes that are not on this server come back as Hidden step, with no name or type and a made-up id, and the answer says how many were hidden: the client sees the shape of the run and where it broke, not what the rest of your workspace is made of.
Seeing the calls in Monitoring
Every tool call leaves a row in Monitoring → Logs, under the source MCP Server — the ones that were refused too. The message names the server and what ran: MCP “Sales tools” → send_email (412ms). Each row carries an outcome:
| Outcome | Meaning |
|---|---|
ok | It ran, or discover_operations and the run history answered. |
failed | The node ran and the provider or the node returned an error. The row has it. |
refused | Nothing ran. reason says why: unknown_operation, blocked, wrong_gate or bad_arguments — or the node itself refused the call. |
unknown_tool | The client called a tool that is not one of the six. |
not_found | show_run was given a run id that doesn't exist, or one this server can't see — the row says which, the client isn't told. |
waiting | The operation is waiting for a person to answer — see Tasks below. |
crashed | The node threw an error instead of answering, or the request broke before reaching it. The row has the message. |
Type outcome:refused, toolName:send_email or serverName:Sales in the Logs filter bar to narrow down (see Searching logs). Rows of calls that ran a node name the operation, and keep the run tool they came through in requestedTool.
A call that runs a node is also recorded as a run of its own, whose id starts with mcp:; list_recent_runs and show_run return it like any other run. And the server's page shows last used, updated on every request that gets in. A request turned away for a missing or wrong token never gets in, so it leaves no row and doesn't count as a use.
Using a server from an AI Node
An AI Node can use one of your own servers as a set of tools. In its Tools, under MCP servers, pick the server from the list: a credential named <server> (HostWebhook MCP) is created for it the first time and reused after — there is no token to copy. The agent then gets the same six tools, with the same blocks. Nodes that are on a server show In MCP · <server> on the canvas. See AI Node — Tools.
Servers your AI Nodes connect to
The other direction: an external MCP server an AI Node uses — GitHub, or a URL of your own with its token or sign-in. Those live in Settings → MCP Servers as well, under the servers you publish, and not in Settings → Credentials. Each one has its own page:
- General — its name, Edit URL, token or sign-in, tags, a folder (the same folders as your credentials) and Mark as sensitive, which hides its URL, issuer and scopes from every API response while AI Nodes keep using it.
- Security — its usage, its access log, and Rotate for when its token or sign-in may have leaked: what is stored is replaced with an unusable value, and every AI Node that uses the server fails until someone signs in again or pastes a new token.
Reconnect — signing in again — works on a server marked sensitive too. Changing the URL of a server that has a token asks for the token again, so it is never sent to a different server than the one it was given for; if the new one needs none, remove it. A server added with a custom URL and no name is named after its host, like mcp.context7.com.
Editing and deleting
- Renaming the server is safe: the URL and the token stay the same.
- Ticking and unticking nodes takes effect when you save. A node you delete leaves the servers it was on by itself.
- Deleting the server stops its URL, cuts every app connected to it, and removes it from the AI Nodes that used it. The nodes themselves are not touched. It can't be undone.
Protocol details
For anyone writing their own client, or wondering why one doesn't connect.
- Transport. JSON-RPC 2.0 over
POSTto the server URL. Answers are plain JSON, except a call that runs a node from a client that acceptstext/event-stream: that one is answered as a stream, with a progress notification at the start and at the end. The server opens no stream of its own: aGETasking for one gets405. - Versions.
2026-07-28,2025-11-25and2025-06-18.server/discoverlists them;initializeanswers the version the client asked for if it is one of these, and2025-06-18otherwise. - Resources. Each node on the server is also a read-only resource,
hw://nodes/<nodeType>/<nodeId>/last-payload: the node's most recent payload, the one the data picker shows. Reading it runs nothing. - Tasks. Gmail's
send_email_and_waitwaits for a person to approve or reject. Only clients that declare the MCP Tasks extension in the request can discover and run it; they get a task to poll withtasks/getinstead of a result, and the outcome when the person answers. - Social calendar. A server with a Social Media node, in an organization with the Social add-on, has two more tools:
list_social_postsandmanage_social_post. They act as the server's owner, in the workspace of its first Social Media node. - Errors.
401with no token or a wrong one;403when a sign-in lacks the scope the method needs;429above 60 requests a minute.