skillhook
NPM · @METERAPP/SKILLHOOK
Turn this machine into a webhook endpoint that runs Agent Skills with Claude Code or Codex.
Available components
Last scanned (20 hours ago)
Scores higher than 52% of npm servers
Category Workflow Automation
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security100
- No malware found by supply-chain analysis.Pass
- No known CVEs affecting this package version or its production dependencies.Pass
- No install/post-install scripts declared.Pass
- 0 of 4 dependencies flagged as unhealthy. View diagnostics → Pass
Provenance & Transparency100
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Cryptographically verified build provenance (signed, bound to MeterApp/skillhook). View diagnostics → Pass
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 0 days ago).Pass
- Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability62
- AI-judged instruction clarity (good).Pass
- Context-footprint check failed: tool/resource definitions use about 4877 tokens (~118/item across 41 items; 41 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management0
- Stability not yet verified: not enough scan history yet (needs a 30-day window).Unverified
Tool Coverage77
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 30% of tool parameters carry a description.Partial
Tool Safety75
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- 0 of 3 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "send_test_webhook" implies "send" and declares no destructiveHint at all, which the MCP spec reads as destructive by default. See how to fix → Fail
- An AI judge read all 42 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Unverified: 1 category
A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 4 Nov 26 +15
- Malware scan: unverified → pass ▲ security
- 3 Nov 26 61
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 4 Nov 2026 · Analysed npm/@meterapp/skillhook@0.14.7
Provenance Verified
A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.
| Result | Verified |
|---|---|
| Ecosystem | npm |
| Reason | Verified |
| Discovered via | Registry attestation endpoint |
| Source repo | MeterApp/skillhook |
| Certificate issuer | https://token.actions.githubusercontent.com |
| Certificate SAN | https://github.com/MeterApp/skillhook/.github/workflows/publish.yml@refs/tags/v0.14.7 |
| Rekor log index | 3671227137 |
| Predicate type | SLSA build provenance https://slsa.dev/provenance/v1 |
| Subject digest | sha512:0d8638c00cc3d26054dc69924fc801e3c5815b904280b6482f13484ab336b971f99eef13b3fe31f8c7a8eaa91dda7643c550738a8619b34279a126da6 |
Background: How many MCP packages publish verified provenance →
Dependencies 4 packages
| Packages resolved | 4 |
|---|---|
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
add_example Add example skill ~48
Copies a bundled example into <home>/skills (optionally under another name) and generates its secret when skillhook manages it.
| Name | Type | Req | Description |
|---|---|---|---|
| as | string | – | – |
| name | string | yes | – |
No output schema declared.
No examples provided.
answer_job Answer a job ~231
A person's answer to a job that is waiting: delivered live to the agent's pending job_ask_human call when the job is still running (`delivered: live`); otherwise recorded and, unless resume is `never`, a new job with trigger `resume` continues the agent's session with it (`claude --resume` / `codex exec resume`; `delivered: resumed`, `resume_job_id`). Use list_jobs with waiting: true to find such jobs; pass `option` when the person picked one of the question's options, `options` for the picks of a multiple-choice question (the answer then lists them one per line), `by` to say who answered.
| Name | Type | Req | Description |
|---|---|---|---|
| answer | string | – | The answer; may be left out when option or options say it all |
| by | string | – | – |
| id | string | yes | – |
| option | string | – | – |
| options | array | – | – |
| resume | string | – | – |
| wait_seconds | integer | – | how long to wait for the resume job (default 120; 0 returns at once) |
No output schema declared.
No examples provided.
cancel_job Cancel job ~27
Cancels a queued or running job on the running server.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | – |
No output schema declared.
No examples provided.
check_update Check for updates ~79
Ask the npm registry for the newest skillhook (what `skillhook update` does). With `install: true` and a newer version, upgrade with the package manager that installed skillhook and restart the background service when it has no jobs in progress; a busy service keeps running the old version until `restart_server`.
| Name | Type | Req | Description |
|---|---|---|---|
| install | boolean | – | – |
No output schema declared.
No examples provided.
cloud_disconnect Disconnect from Skillhook Cloud ~76
Stops the link to Skillhook Cloud: sets cloud.enabled to false, revokes and removes the machine token and key, deletes the local spool, and tells a running server (which stops syncing within seconds). Nothing leaves the machine afterwards. keep_token keeps the token in .env for a later reconnect.
| Name | Type | Req | Description |
|---|---|---|---|
| keep_token | boolean | – | – |
No output schema declared.
No examples provided.
cloud_report_issue Report an issue to Skillhook ~306
Sends a problem report to the Skillhook team through Skillhook Cloud, from this paired machine (what `skillhook cloud report` does). Use it only when the person asked to report something, and tell them what goes out (dry_run: true returns exactly that without sending): the title and body (write them from what the person said), optional kind, severity, contact_email and the job id, delivery id or skill it is about, and unless diagnostics is false the machine's facts: skillhook, Node and OS versions, cloud mode, the link's state, whether each runner is ready and the failing or warning health checks, all scrubbed of every .env value. Never payloads, logs, prompts or job output. Returns the issue number and URL and whether a confirmation email went out. Fails on a machine that is not paired (`skillhook cloud connect`) or under SKILLHOOK_NO_CLOUD.
| Name | Type | Req | Description |
|---|---|---|---|
| body | string | – | – |
| contact_email | string | – | where the Skillhook team answers |
| delivery_id | string | – | – |
| diagnostics | boolean | – | attach the machine's facts (default true) |
| dry_run | boolean | – | return the report that would be sent, send nothing |
| job_id | string | – | this machine's job id the report is about |
| kind | string | – | default bug |
| severity | string | – | default normal |
| skill | string | – | – |
| title | string | yes | – |
No output schema declared.
No examples provided.
cloud_status Skillhook Cloud status ~172
Whether this machine is paired with Skillhook Cloud (the opt-in dashboard for every machine's webhooks, jobs and health), its URL, machine id and mode (observe: the cloud can look; control: it can also run skills and change the configuration), whether the token is present (never the token itself), the running server's link state (connected, degraded, disconnected with the reason, last sync, events waiting) and whether an organisation API key is kept here for the fleet (api_key; the skillhook-cloud MCP server and `skillhook cloud overview` use it). Pairing is not a tool on purpose: the person runs `skillhook cloud connect --code <code from their dashboard>` in a terminal, so a code from an untrusted source can never hand this machine to someone else's account.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
create_skill Create skill ~329
Creates <home>/skills/<name>/SKILL.md. Writes the instructions (markdown body) and the skillhook frontmatter (runner, model, auth, filters). For bearer/basic/hmac auth a secret is generated and returned once; for provider-signed auth (github, sentry, granola, stripe, slack, linear, svix, standard-webhooks) call set_secret with the provider's signing secret afterwards.
| Name | Type | Req | Description |
|---|---|---|---|
| auth_type | string | – | default bearer |
| cwd | string | – | working directory for the agent, e.g. ~/dev/my-repo |
| description | string | yes | what the skill does and when it runs (1-1024 chars) |
| effort | string | – | low|medium|high|xhigh|max |
| env | array | – | env var names from .env to expose to the agent |
| instructions | string | yes | markdown body: what the agent should do with the payload. Use {{payload}} / {{payload.some.path}} placeholders or let skillhook append the event automatically. |
| model | string | – | e.g. opus, sonnet, haiku, claude-opus-5, gpt-5-codex |
| name | string | yes | lowercase letters, digits and hyphens |
| overwrite | boolean | – | – |
| runner | string | – | – |
| secret_env | string | – | env var holding the secret; default SKILLHOOK_SECRET_<NAME> |
| timeout_seconds | integer | – | – |
| when | array | – | filters, e.g. [{"path":"action","equals":"created"}] |
No output schema declared.
No examples provided.
doctor Doctor ~31
Checks Node, config, secrets, skills, Claude/Codex login, Tailscale exposure, server and service.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
expose Expose via Tailscale ~62
mode=funnel: public HTTPS URL (internet). mode=serve: tailnet-only URL. mode=off: disable. mode=status: current exposure. The URL is permanent (your Tailscale node name) and survives reboots.
| Name | Type | Req | Description |
|---|---|---|---|
| mode | string | yes | – |
No output schema declared.
No examples provided.
generate_secret Generate secret ~47
Generates a random secret for a skill (or "admin") and returns it once. Existing secrets are kept unless force=true.
| Name | Type | Req | Description |
|---|---|---|---|
| force | boolean | – | – |
| name | string | yes | – |
No output schema declared.
No examples provided.
get_config Get config ~57
The effective skillhook.json (defaults applied), which keys the running server applies live (`hot_keys`) and which need a restart (`restart_keys`: host, port), and what is pending a restart. From the running server when there is one.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
get_delivery Get delivery ~58
One delivery record; `include_body` adds the request body when the log kept it (rejected and filtered deliveries) or the payload of the job an accepted delivery created.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | – |
| include_body | boolean | – | – |
No output schema declared.
No examples provided.
get_health Health report ~128
Everything doctor checks plus, with deep (default), every MCP server Claude Code and Codex know (connected, needs authentication, failed), installed plugins, `codex doctor`, disk space and each skill's last run, grouped (system, skillhook, runners, tools, skills, exposure). Through the running server's cached report when there is one (`refresh` probes again); otherwise probed now.
| Name | Type | Req | Description |
|---|---|---|---|
| deep | boolean | – | – |
| network | boolean | – | ask the npm registry and probe the public URL (default false through the server, true locally) |
| refresh | boolean | – | – |
No output schema declared.
No examples provided.
get_job Get job ~59
Job record plus optional artifacts (result, response, prompt, stdout, stderr, payload, event) and, when the agent reported any, its progress timeline, pending question and answer.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | – |
| include | array | – | – |
No output schema declared.
No examples provided.
get_runners Runner readiness ~82
Is each runner (claude, codex, shell) installed and logged in, or given an API key: what every job checks before it starts (a `fallback:` runner takes over, or the job fails fast with failure.kind auth). Through the running server's cached answer when there is one (`refresh` probes again).
| Name | Type | Req | Description |
|---|---|---|---|
| refresh | boolean | – | – |
No output schema declared.
No examples provided.
get_skill Get skill ~33
Returns a skill's summary and the full SKILL.md content.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | skill name (directory name) |
No output schema declared.
No examples provided.
get_stats Stats ~105
Numbers over the jobs and deliveries on this machine: jobs by status, outcome, trigger, runner and failure kind, success and completion rates, duration and queue-wait percentiles, cost and tokens, deliveries by outcome and HTTP status, and the same per skill. `since` takes 24h, 7d, 2w or an ISO-8601 instant.
| Name | Type | Req | Description |
|---|---|---|---|
| since | string | – | – |
| skill | string | – | – |
| until | string | – | – |
No output schema declared.
No examples provided.
get_webhook_urls Webhook URLs ~37
Webhook URL per skill, using the public URL (Tailscale/config) when one exists.
| Name | Type | Req | Description |
|---|---|---|---|
| skill | string | – | – |
No output schema declared.
No examples provided.
link_project Link project ~151
Registers a repository's skillhook.yaml (dir, or the YAML file itself) in skillhook.json so its hooks are served at /hooks/<name>; the running server picks them up without a restart. With init=true a starter skillhook.yaml is written first when none exists (a `run: git pull --ff-only` hook for merged GitHub pull requests). Secrets skillhook manages (bearer/basic/hmac) are generated and returned once; provider-signed hooks need set_secret afterwards.
| Name | Type | Req | Description |
|---|---|---|---|
| dir | string | yes | repository directory (or path to its skillhook.yaml) |
| init | boolean | – | write a starter skillhook.yaml when the directory has none |
| no_secret | boolean | – | – |
No output schema declared.
No examples provided.
list_accounts Accounts ~221
The Claude Code and Codex accounts (named logins) skills run as: for each its state (ready, needs_login, expired, limited, missing_secret, disabled), who it is logged in as, its plan, its usage windows (5h, weekly, per model; with `usage: true` asked from each account's CLI now), its last use, its jobs of the last 24 hours, the skills that use it, and `attention`: what needs a person, each with the command that fixes it. With `mcp: true` (slow: every server connects) also `mcp`: the MCP servers, claude.ai / ChatGPT connectors and plugins each account's runs get, whether each connected, needs authentication or failed, and attention items for them. Logging in is done by a person in a terminal (`skillhook accounts login <name>`), never by a tool.
| Name | Type | Req | Description |
|---|---|---|---|
| account | string | – | – |
| mcp | boolean | – | – |
| refresh | boolean | – | – |
| usage | boolean | – | – |
No output schema declared.
No examples provided.
list_deliveries List deliveries ~120
Every request to /hooks/<skill> the server received, newest first, with its outcome: accepted (a job was created), duplicate, in_flight, skipped (a when filter), rejected (401, 404, 413, 503, …), challenge, error. Use it to see why a webhook did not run. `after` pages further back.
| Name | Type | Req | Description |
|---|---|---|---|
| after | string | – | – |
| limit | integer | – | – |
| outcome | string | – | – |
| since | string | – | – |
| skill | string | – | – |
No output schema declared.
No examples provided.
list_examples List example skills ~35
Bundled example skills (hello, granola-meeting-actions, sentry-triage, …) that add_example can copy.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
list_jobs List jobs ~187
Recent jobs, newest first. `status` is how the process ended, `outcome` whether the task was done. `waiting: true` lists only the jobs waiting for a person (an unanswered question, or outcome needs_human not yet resumed): answer them with answer_job. `after` (the `next_after` of the previous call) pages further back; `since` is an ISO-8601 instant.
| Name | Type | Req | Description |
|---|---|---|---|
| after | string | – | – |
| failure | string | – | only jobs that failed this way: auth, usage_limit, rate_limit, budget, max_turns, not_found, timeout, crash, unknown |
| limit | integer | – | – |
| outcome | string | – | – |
| since | string | – | – |
| skill | string | – | – |
| status | string | – | – |
| trigger | string | – | – |
| waiting | boolean | – | – |
No output schema declared.
No examples provided.
list_projects List linked projects ~61
Repositories whose skillhook.yaml is served by this machine: directory, file, and each hook with its runner, kind (run/skill/prompt), auth, cwd and webhook URL. This is the version-controlled answer to 'which skill runs from which webhook'.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
list_schedules List schedules ~79
Every skill or hook with a `schedule:`: cron, time zone, catch_up and overlap policy, whether it is enabled and also has a webhook, the next due time, and the last slot, job and status (live from the running server when there is one). A hook with `webhook: false` runs only on its schedule.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
list_secrets List secret names ~24
Names of secrets in <home>/.env (values are never returned).
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
list_skills List skills ~31
Lists every skill with runner, model, auth type, whether its secret is configured, and its webhook URL.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
replay_delivery Replay delivery ~178
Runs a recorded delivery again through the skill as it is now, as a new job with trigger `replay`: the original payload, headers and query, no signature check, `when` filters applied unless skip_filters, identical in-flight work is reused when deduplication is enabled on the running server. A delivery that was rejected needs `force` (its body was never verified). Uses the running server when there is one, otherwise runs in-process.
| Name | Type | Req | Description |
|---|---|---|---|
| effort | string | – | – |
| force | boolean | – | replay a delivery that was rejected or errored |
| id | string | yes | – |
| model | string | – | – |
| runner | string | – | – |
| skip_filters | boolean | – | run even when the skill's `when` conditions do not match the original request |
| wait_seconds | integer | – | default 120 |
No output schema declared.
No examples provided.
replay_job Replay job ~126
Runs the request an earlier job received again, as a new job with trigger `replay` and `replay_of` pointing at the original (same payload, headers and query; `when` filters applied unless skip_filters; runner/model/effort may be overridden).
| Name | Type | Req | Description |
|---|---|---|---|
| effort | string | – | – |
| id | string | yes | – |
| model | string | – | – |
| runner | string | – | – |
| skip_filters | boolean | – | run even when the skill's `when` conditions do not match the original request |
| wait_seconds | integer | – | default 120 |
No output schema declared.
No examples provided.
restart_server Restart server ~121
Ask the running server to restart: it pauses dispatch while keeping intake and cloud sync available, lets running jobs finish for up to wait_seconds (default 30), then exits only if idle. On timeout it resumes dispatch without terminating jobs; `force: true` terminates them. Launchd / systemd starts it again after an exit. Only works for a server run as the service (409 otherwise); use it after update_config changed host or port, or after an update was installed.
| Name | Type | Req | Description |
|---|---|---|---|
| force | boolean | – | – |
| wait_seconds | integer | – | – |
No output schema declared.
No examples provided.
run_skill Run skill ~167
Runs a skill with a payload through the same prompt, runner and job pipeline as a webhook, skipping HTTP auth, the skill's when filters and de-duplication. Uses the running server when there is one (job visible in its queue), otherwise runs in-process. Set wait_seconds to block for the result; otherwise poll get_job. Use send_test_webhook to exercise auth and filters too.
| Name | Type | Req | Description |
|---|---|---|---|
| effort | string | – | – |
| headers | object | – | extra request headers to simulate, e.g. {"x-github-event":"issues"} |
| model | string | – | – |
| name | string | yes | – |
| payload | – | – | JSON payload the skill receives (object, array, string…) |
| runner | string | – | – |
| wait_seconds | integer | – | default 120 |
No output schema declared.
No examples provided.
send_test_webhook Send signed test webhook ~94
Signs a payload the way the skill's auth expects and POSTs it to /hooks/<name>, proving the HTTP path (auth, filters, queue) works. Defaults to the local server; set public=true to go through the public URL.
| Name | Type | Req | Description |
|---|---|---|---|
| base_url | string | – | – |
| name | string | yes | – |
| payload | – | – | – |
| public | boolean | – | – |
| wait_seconds | integer | – | – |
No output schema declared.
No examples provided.
service Background service ~47
install: run the server at login (launchd/systemd) and keep it alive. status/restart/uninstall/logs.
| Name | Type | Req | Description |
|---|---|---|---|
| action | string | yes | – |
| lines | integer | – | – |
No output schema declared.
No examples provided.
set_secret Set secret ~92
Stores a secret in <home>/.env (mode 600). `name` is an ENV_VAR_NAME, a skill name (its secret_env) or "admin". Use it for provider signing secrets (Granola whsec_…, Sentry client secret, GitHub webhook secret) and for API keys a skill needs via `env:`.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | – |
| value | string | yes | – |
No output schema declared.
No examples provided.
skillhook_status skillhook status ~29
Overview: home directory, server state, public URL, skills and recent jobs. Call this first.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
test_skill Test a SKILL.md that is not installed ~198
Runs the complete text of a SKILL.md (frontmatter included) with a payload, exactly like run_skill, without installing it: the file is kept in the job directory (jobs/<id>/skill/<name>/SKILL.md) and the job has trigger `test`. Use it to try a draft before create_skill, or to see how a change would behave. Through the running server when there is one, otherwise in-process.
| Name | Type | Req | Description |
|---|---|---|---|
| cwd | string | – | working directory for the run (default: the skill's `cwd`, else the copy's own directory inside the job) |
| effort | string | – | – |
| headers | object | – | – |
| model | string | – | – |
| payload | – | – | – |
| runner | string | – | – |
| skill_md | string | yes | the whole SKILL.md text, frontmatter included; `name` must be a valid skill name |
| wait_seconds | integer | – | default 120 |
No output schema declared.
No examples provided.
unlink_project Unlink project ~40
Stops serving a repository's hooks (they answer 404 at once). The repository and its skillhook.yaml are not touched.
| Name | Type | Req | Description |
|---|---|---|---|
| dir | string | yes | – |
No output schema declared.
No examples provided.
update_config Update config ~104
Change skillhook.json: `set` maps dotted keys to values ({"concurrency": 3, "defaults.model": "sonnet"}), `unset` lists dotted keys to remove. One validated write; an invalid result changes nothing. The running server re-reads the file at once and says which keys it applied live and which (host, port) wait for a restart (`restart_server`).
| Name | Type | Req | Description |
|---|---|---|---|
| set | object | – | – |
| unset | array | – | – |
No output schema declared.
No examples provided.
update_skill_file Update SKILL.md ~48
Replaces a skill's SKILL.md with new content after validating the frontmatter.
| Name | Type | Req | Description |
|---|---|---|---|
| content | string | yes | complete SKILL.md text including frontmatter |
| name | string | yes | – |
No output schema declared.
No examples provided.
validate_skills Validate skills ~32
Parses every SKILL.md (or one) and reports errors and missing secrets.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | – | – |
No output schema declared.
No examples provided.
How do I install the skillhook MCP server?
skillhook runs locally as an npm package, launched with npx -y @meterapp/skillhook. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
npm · @meterapp/skillhook
claude mcp add dev-skillhook-skillhook -- npx -y @meterapp/skillhook
What is the skillhook MCP server?
skillhook is an MCP server listed in the public MCP registry as dev.skillhook/skillhook. Turn this machine into a webhook endpoint that runs Agent Skills with Claude Code or Codex. This page covers its npm package (@meterapp/skillhook).
Is the skillhook MCP server safe to use?
skillhook scores 76 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 4 November 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the skillhook MCP server expose?
skillhook exposes 41 tools: skillhook_status, list_skills, get_skill, create_skill, update_skill_file, and 36 more. Their descriptions and schemas cost roughly 4,152 tokens of context every time the server is loaded.
Is the skillhook MCP server still maintained?
skillhook is still listed as active in the MCP registry. We last reached this channel on 4 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the skillhook MCP server under?
skillhook declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.