MetricsHub
MetricsHub Community Connectors 1.0.24
-
Home
- Connector Developer Guide Connector Structure 7
tools (Section)
When To Use
Use tools to give an AI assistant an operation on the monitored host that is not a metric: list the running processes with their counters, read a log, reboot a server. A tool reuses what the connector already knows (the protocol, the credentials, the queries, the parsing) without creating any monitor.
The MetricsHub Agent exposes every tool as an MCP tool named <connectorId>_<toolName> (for example WindowsProcess_listProcesses), so an assistant connected to the agent discovers it with the connector.
A tool is:
- Sources and computes, exactly like a monitor job's: the same source types, the same computes, the same
${source::...}references. - Parameters the assistant fills in, substituted with
${param::<name>}in the sources and computes. - A result: the table of one of the sources, optionally with column names.
Syntax
tools:
listProcesses:
description: Lists the running processes with their CPU time and memory, optionally filtered by name.
parameters:
matchName:
type: string
description: Regular expression matching the process name, e.g. ^java (empty for all processes)
default: ''
# Only matched against the rows: any value on one line
pattern: '.*'
sources:
processes:
type: wmi
namespace: root\CIMv2
query: SELECT ProcessId, Name, WorkingSetSize, KernelModeTime FROM Win32_Process
computes:
- type: keepOnlyMatchingLines
column: 2
regExp: ${param::matchName}
result:
source: ${source::processes}
columns: [ pid, name, workingSetBytes, kernelTime ]
Properties
| Property | Required | Default | Description |
|---|---|---|---|
tools |
No | None | Object containing the named tools of the connector. |
<toolName>.description |
Yes | None | What the tool does, as read by the assistant. Say what it returns and when to use it. |
<toolName>.parameters |
No | None | Object of named parameters (see below). |
<toolName>.destructive |
No | false |
true when the tool changes the state of the host: a reboot, a command, a write. See the Destructive Tools section below. |
<toolName>.sources |
Yes | None | Named sources with their computes, like a monitor job's sources. |
<toolName>.executionOrder |
No | Dependency order | Explicit source order, like a monitor job's. |
<toolName>.result.source |
Yes | None | Reference of the source whose table is returned, e.g. ${source::processes}. |
<toolName>.result.columns |
No | None | Names of the table columns, in order, so that the rows read as records. |
Parameters
| Property | Required | Default | Description |
|---|---|---|---|
type |
No | string |
string, integer, number or boolean. Enforced: an integer is a whole number (5, 5.0 and 5e0 are all 5), a boolean is true or false. The value is substituted as text. |
description |
No | None | What the value is for. Give an example. |
required |
No | false |
Whether the assistant must supply the value. A parameter the sources reference must be required or have a default ('' for an optional text), or the tool is refused. |
default |
No | None | The value used when the assistant does not supply one. It must satisfy the type, pattern and enum. |
pattern |
No | Default pattern for a string without enum |
A Java regular expression the whole value must match. A string declaring neither a pattern nor an enum takes the default pattern: letters, digits and _ . @ : - (see Validation and Review). |
enum |
No | None | The only values accepted, each of the parameter's type, e.g. [ TERM, KILL, HUP ]. |
The invocation arguments replace ${param::<name>} in the tool's sources and computes, exactly where a mono-instance collect replaces ${attribute::<name>}. The enum is advertised in the tool's JSON schema and the pattern in the parameter's description. Every argument is checked against type, pattern and enum before the tool runs: an invalid argument is reported to the assistant and nothing runs.
Validation and Review
An argument comes from an AI assistant, and through it from whatever the assistant read: treat it as untrusted. Inserted as is into a command line, a value such as sshd; reboot would run a command of its own, and ' OR 1=1 -- would rewrite a query. MetricsHub validates every argument before the tool runs. Where the sources insert it, and what the command does with it, is checked when the connector is reviewed.
What MetricsHub Checks
An invalid argument is reported to the assistant, and nothing runs.
- Type, enum and pattern. Every argument must satisfy the
type,enumandpatternof its parameter. - The default pattern. A
stringparameter declaring neither anenumnor apatternonly takes letters, digits and_ . @ : -, starting with a letter, a digit or_, or nothing:sshd.service,getty@tty1.service,db-01.example.com,10.0.0.1,fe80::1. Such a value cannot leave a string or a word, in a shell, a query or a URL, nor be read as an option, nor climb a path:sshd; reboot,a b,$(id),-deleteand../etcare refused. It suits most parameters: names, identifiers, addresses. An empty value, which adefault: ''gives, leaves no word where it is inserted unquoted in a command line (--filter ${param::x} filewould makefilethe filter): quote it,'${param::x}', or make the parameterrequired. - No macro, no control character. No argument may contain
%{or${, which would reveal a credential macro such as%{PASSWORD}, nor a control character other than a tab or a line break. A value that would form a macro with the text around it, such as{PASSWORD}after a%, is not inserted. - Declared references. When the agent loads the connector, every reference must name a declared parameter,
requiredor with adefault(''for an optional text), and a known escape type: the tool is refused otherwise, rather than run with the reference left in. In a tool,${attribute::<name>}is the same as${param::<name>}, the arguments being the tool's attributes.
Wider Values
A parameter that needs more characters (a path, free text, a search pattern) declares its own pattern, as narrow as possible, or an enum. Insert it with the escape of the field, inside the quotes the connector writes:
| Field | Write | Escaping |
|---|---|---|
commandLine run by a POSIX shell |
Between single quotes: '${esc(bash)::param::x}' |
' becomes '\'': nothing is expanded between single quotes |
| A PowerShell command | Between single quotes, in a command between double quotes: PowerShell.exe -Command "Get-Service '${esc(powershell)::param::x}'" |
' and the typographic quotes doubled. The command reaches PowerShell through cmd.exe, whose double quotes keep & \| < > ^ ( ) literal, but not " and %: keep these two out of the pattern |
query of a sql source |
Between single quotes: '${esc(sql)::param::x}' |
\ and ' doubled, as MySQL and MariaDB read \ as an escape. Elsewhere (PostgreSQL, SQL Server, Oracle), keep \ out of the pattern. In a LIKE pattern, % and _ stay wildcards |
query of a wmi or wbem source |
Between single or double quotes of a comparison: '${esc(wql)::param::x}' |
\, ' and " preceded with \. Not in a LIKE pattern, where WQL does not read \ as an escape |
url or path of an http source |
In the path or the query: /api/${esc(url)::param::x} |
Percent-encoded, / included, the dots of a . or .. segment too |
body of an http source |
"${esc(json)::param::x}" in JSON, ${esc(xml)::param::x} in XML character data or a quoted attribute, ${esc(url)::param::x} in a form |
\, " and the control characters for JSON; & < > " ' as entities for XML, where a quoted attribute still turns tabs and line breaks into spaces (keep them out of the pattern there); percent-encoding for a form |
keep, exclude, regExp |
A regular expression: ${param::x}, with a pattern such as .*. Text to find in a regular expression of the connector: ${esc(regex)::param::x}, outside of a [...] character class |
None for a regular expression, which is only matched against the rows. esc(regex) puts \ before ^ $ . * + ? [ ] \, so that the text matches literally |
What the Review Checks
MetricsHub does not read the commands, queries and requests of a connector. The review of every tool checks that each parameter, whatever its pattern, is only data where it lands:
- Not a command. Never the name of a command (
${param::x} --version, after;,|,&&,if,{, an assignment such asMODE=x, a redirection such as2>&1), the script of a shell (sh ${param::x}), the target of a redirection (> ${param::x}), nor a function or alias of the command line. - Not code. Never an argument of a command that runs its arguments as code or as another command:
eval,sh -c,sudo,su,ssh,env,xargs,nohup,timeout,nice,chroot,prlimit,find -exec,docker exec,awk,perl,python,sed(whose script runseand writesw),dd(whoseof=writes),tar,rsync,git,man,less… nor the value of an option naming a program (--to-command=,--rsh-command,-o ProxyCommand=). Never inside arithmetic ($((...)),let,[[ ... -eq ... ]]), a variable name (read,printf -v,export),$(...), backquotes, a here-document or a comment. - Not an option or an action. Never completing an option (
-${param::x}makes-delete), and never choosing what a service, package or container manager does: write the action (systemctl status ${param::x},docker container logs ${param::x}), or make the parameter anenum. - Not a destination. Never the scheme or the host of a URL, which would send the request and its credentials elsewhere: an
enumonly. Never afilesource path, unless itspatternkeeps it in a directory without... - Escaped where it is wider. A parameter whose
patternlets more than the default through is inserted with the escape of its field, inside the quotes the connector writes, as in the table above, unless it is a regular expression of a compute. A SQL or WQL value sits inside a quoted string, never as a column, a table or a clause. - A pattern that matches in one pass. MetricsHub matches every argument against the
patternof its parameter, without a time limit. Use character classes and single quantifiers ([A-Za-z0-9_./-]{1,255}), never a quantified group that can match the same text in several ways ((a+)+,(.*a){16}), whose matching time explodes on a crafted value, nor a repeated alternation ((x|y)*), which exhausts the stack on a long value: write[xy]*. - Destructive when it acts. Anything that changes the host is
destructive: true.
tools:
serviceLogs:
description: Returns the last lines of the journal of a systemd service. Use it when a service fails or restarts.
parameters:
service:
# The default pattern takes unit names: sshd.service, getty@tty1.service
description: The systemd unit, e.g. sshd.service
required: true
lines:
type: integer
description: How many lines to return, 1 to 9999
default: 100
# A bound: an unbounded count could return the whole journal
pattern: '[1-9][0-9]{0,3}'
priority:
description: The lowest priority to return
default: info
enum: [ emerg, alert, crit, err, warning, notice, info, debug ]
sources:
journal:
type: commandLine
commandLine: journalctl --no-pager -n ${param::lines} -p ${param::priority} -u ${param::service}
result:
source: ${source::journal}
References and Order
Sources of a tool are keyed ${source::tools.<toolName>.sources.<sourceName>}. Inside the tool, a relative reference ${source::<sourceName>} resolves to the tool's own source, and the sources run in dependency order unless executionOrder says otherwise. A tool may also reference the connector's beforeAll sources with ${source::beforeAll.<name>}: they run before the tool, as before a monitor job.
A tool creates no monitor and its tables do not reach the monitor jobs: mapping is not allowed under a tool.
How the Assistant Calls It
The agent adds two parameters to every tool: hostname, a list of configured hosts to run it on (required), and poolSize, the number of hosts run concurrently. The result lists one entry per host, holding the columns declared in result and the rows of the result source, or an error.
{
"hosts": [
{
"hostname": "win-01",
"response": {
"columns": [ "pid", "name", "workingSetBytes", "kernelTime" ],
"rows": [ [ "4212", "java.exe", "734003200", "12.5" ] ]
}
}
]
}
Destructive Tools
A tool that changes the host (power control, a command, a configuration write) must declare destructive: true. The agent prefixes its description with DESTRUCTIVE:; its own MCP server and chat advertise it only when the agent runs with the JVM flag -Dmetricshub.mcp.tool.destructive.enabled=true, while MetricsHub Central receives every tool and applies its own approval policy.
tools:
reboot:
description: Reboots the server through iLO (graceful shutdown, then power on). Use only when the user explicitly asks for a reboot.
destructive: true
parameters:
resetType:
description: GracefulRestart (default) or ForceRestart
default: GracefulRestart
enum: [ GracefulRestart, ForceRestart ]
sources:
reset:
type: http
method: post
path: /redfish/v1/Systems/1/Actions/ComputerSystem.Reset
header: "Content-Type: application/json"
body: '{"ResetType": "${param::resetType}"}'
resultContent: http_status
result:
source: ${source::reset}
columns: [ http_status ]
Recommended Pattern
- Name tools as verbs, without dots:
listProcesses,readLog,reboot. A dotted name is refused when the connector loads, since the dot separates the segments of a source reference. - Write the description for the assistant: what the tool returns, what the parameters mean, when not to use it.
- Give every parameter a
defaultorrequired: true, and an example value in its description. - Keep the default pattern for names and identifiers; use an
enumor a numeric type where you can; give a widerpatternonly where needed, with the escape of the field. - Bound the numbers that size the work or the result (a line count, a time range) with a
patternsuch as[1-9][0-9]{0,3}: the type alone accepts any integer. - Keep the result tabular: keep the commands plain, and filter, sort and select the lines with the source's
keepandexcludeand with computes (sort[1],head[2],tail[3]) rather than withgrep,sort,headortailon the host; name the columns. - Mark anything that writes as
destructive: true, even a harmless-lookingidentifyLED.
Common Mistakes
- Using
${param::...}in amapping: tools have no mapping. - Forgetting
result: the tool has nothing to return. - Leaving
destructiveunset on a tool that acts on the host. - Widening a
pattern(spaces, quotes,/) and inserting the parameter without the escape of its field, or outside the quotes the connector writes. - Passing a parameter where it is not mere data: see What the Review Checks above.
- Returning raw command output without a parsing compute: the assistant gets a single-column table of lines.
- [1] computes/sort.html
- [2] computes/head.html
- [3] computes/tail.html
