jobber-mcp
Read your Jobber Client Hub — the customer portal a service business (pest control, lawn care, HVAC, cleaning) uses to send you appointments, quotes and invoices — from a shell with the fpx CLI (@fetchproxy/cli), instead of running the jobber-mcp server. Use when you want your Jobber data without the MCP, in a script, or on a machine where the MCP isn't installed.
Rank
62
Safety
84
Downloads
1.1k
Updated
Oct 11, 2026
Version
1.0.7
Source
CLAWHUB
About
What it does, and when to use it.
Capability contract not published. No trust telemetry is available yet. 1.1K downloads reported by the source. Last updated 10/11/2026.
Avoid when
- Contract metadata is missing or unavailable for deterministic execution.
Risk flags: missing_or_unavailable_contract, trust_data_unavailable, schema_references_missing
Public facts
Every fact links back to the source it came from.
- Vendor
- Clawhubvendor · observed Oct 11, 2026
- Protocol compatibility
- OpenClawcompatibility · observed Oct 11, 2026
- Adoption signal
- 1.1K downloadsadoption · observed Oct 11, 2026
- Latest release
- 1.0.7release · observed Oct 9, 2026
- Handshake status
- UNKNOWNsecurity
Install and run
Setup complexity: low.
clawhub skill install s17cjx1a349nz5apaqp02vgz4h85728z:jobber-mcp- Install using `clawhub skill install s17cjx1a349nz5apaqp02vgz4h85728z:jobber-mcp` in an isolated environment before connecting it to live workloads.
- No published capability contract is available yet, so validate auth and request/response behavior manually.
- Review the upstream CLAWHUB listing at https://clawhub.ai/chrischall/jobber-mcp before using production credentials.
Contract: missing
curl -s "https://www.xpersona.co/api/v1/agents/clawhub-chrischall-jobber-mcp/snapshot"
Documentation
CLAWHUB
147,466 characters of source documentation, loaded on request.
Extracted files
5 files captured from the source.
SKILL.md
--- name: jobber-fpx description: >- Read your Jobber Client Hub — the customer portal a service business (pest control, lawn care, HVAC, cleaning) uses to send you appointments, quotes and invoices — from a shell with the fpx CLI (@fetchproxy/cli), instead of running the jobber-mcp server. Use when you want your Jobber data without the MCP, in a script, or on a machine where the MCP isn't installed. --- # Jobber Client Hub via fpx (no MCP) This reads the **customer** side of Jobber: the hub a business shares with you, at `clienthub.getjobber.com`. It is not the Jobber Developer API — that one serves the business running on Jobber and needs an OAuth app you cannot register as their customer. See `references/why-not-the-api.md`. `clienthub.getjobber.com` sits behind a Cloudflare managed challenge that fingerprints the **TLS client**, so plain `curl` and Node get `403 Just a moment` even with a current Chrome User-Agent and the full browser header set. `fpx` issues the request from inside your own signed-in tab, which has already cleared the challenge. There is no server-side path; the bridge is not optional here. ## One-time setup ```sh npm install -g @fetchproxy/cli # provides `fpx` fpx profile add jobber --domain getjobber.com # fetch capability only — no cookie scope needed ``` The first fetch prints a pair code to **stderr**; approve it in the ContextMint Bridge extension popup. Pairing persists — every later call reuses it. Requirements: the **ContextMint Bridge** extension (from https://github.com/nullnet-app/contextmint-bridge/releases — Chrome: load the chrome zip unpacked; Safari isn't available yet, so use Chrome for now), an open `clienthub.getjobber.com` tab signed into the hub, and the extension's **Site access** allowing `getjobber.com`. (ContextMint Bridge is the fetchproxy extension renamed, same maintainer; source at https://github.com/nullnet-app/contextmint-bridge — verify a release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`.) > Only the fetch capability is declared, deliberately. Cookies ride the tab > automatically, so no cookie scope is needed — and widening scope *after* the > first approval leaves fetches working on the old grant while the new > capability errors. Everything this skill does is covered by the grant above. ## Your hub URL is a credential Each business gives you a **different** hub, identified by a UUID: ``` https://clienthub.getjobber.com/client_hubs/<hub-uuid>/ ``` Anyone holding that URL can read the hub, so treat it like a password: keep it in an env var, never in a committed file or a shell history you share. Get it from any email that vendor sent you — the "View Details" / "View Invoice" button — or from the address bar of an open hub tab. ```sh export JOBBER_HUB='https://clienthub.getjobber.com/client_hubs/<hub-uuid>' ``` One export per business. If two vendors both use Jobber, they are two hubs with nothing in common; there is no co
_meta.json
{
"ownerId": "kn700jq4sjtf2anb0rk3ft4p7n856872",
"slug": "jobber-mcp",
"version": "1.0.7",
"publishedAt": 1791588306464
}references/recipes.md
# Recipes
Every recipe assumes the setup from `SKILL.md`:
```sh
export JOBBER_HUB='https://clienthub.getjobber.com/client_hubs/<hub-uuid>'
PARSE=references/parse-clienthub.mjs # adjust to where the skill lives
hub() { fpx get -p jobber "$JOBBER_HUB/$1" | node "$PARSE" "$1"; }
```
`hub` takes the page name, which is also the parser kind — they are the same
word on purpose, so the two can never drift apart.
## Appointments
Record shape:
```jsonc
{
"group": "Today" | "Upcoming" | "Past",
"id": "2236612358",
"date": "Jun 28, 2026",
"weekday": "Sunday",
"time": "9:00am", // null when the vendor hides times (canViewTime:false)
"arrivalWindow": null, // e.g. "8:00am - 10:00am" when the vendor sets one
"duration": null,
"location": "123 Elm St, ...",
"confirmed": true,
"url": "appointments/2236612358" // hub-relative: the hub id never appears
}
```
Everything upcoming:
```sh
hub appointments | jq '[.[] | select(.group != "Past")]'
```
The next visit, as one line:
```sh
hub appointments \
| jq -r 'map(select(.group != "Past")) | first
| if . == null then "no upcoming visits"
else "\(.weekday) \(.date)\(if .time then " at \(.time)" else "" end) — \(.location)"
end'
```
Visit history, most recent first (the hub already returns `Past` newest-first):
```sh
hub appointments | jq -r '.[] | select(.group=="Past") | "\(.date)\t\(.location)"'
```
Absolute URL for one visit:
```sh
hub appointments | jq -r --arg base "$JOBBER_HUB/" 'first | $base + .url'
```
## Invoices
Record shape:
```jsonc
{
"section": "Paid", // the list heading this card sat under
"id": "150208512",
"title": "For Services Rendered",
"number": "#15313",
"details": ["Sent Mar 23, 2026 | Due Apr 07, 2026", "$135.00 & paid in full"],
"url": "invoices/150208512" // hub-relative, like appointments
}
```
`details` is an ordered list of the card's metadata rows, kept raw rather than
parsed into fields. The rows the vendor shows vary by invoice state — an unpaid
invoice carries a balance row a paid one does not — so a fixed schema would
invent fields for some invoices and drop rows for others.
Everything not yet paid:
```sh
hub invoices | jq '[.[] | select(.section != "Paid")]'
```
One line per invoice:
```sh
hub invoices | jq -r '.[] | "\(.number)\t\(.section)\t\(.details[0] // "")"'
```
Pull the amounts out of the detail rows:
```sh
hub invoices | jq -r '.[] | . as $i
| ($i.details[] | select(test("\\$")) ) // "no amount"
| "\($i.number)\t\(.)"'
```
Sum what is outstanding — note this parses money out of display strings, so
sanity-check it before trusting it for anything that matters:
```sh
hub invoices \
| jq '[.[] | select(.section != "Paid") | .details[] | select(test("\\$"))
| capture("\\$(?<amt>[0-9,]+(\\.[0-9]{2})?)").amt | gsub(",";"") | tonumber]
| add // 0'
```
## Quotes and work requests
Same card shape as invoices — `section`, `titlreferences/why-not-the-api.md
# Why this skill does not use Jobber's documented API
Jobber publishes a clean, well-documented GraphQL API. It is the wrong surface
for a customer, and the reason is worth writing down because the API looks so
much more appetising than scraping a portal.
## The two surfaces
| | Developer API | Client Hub |
| --- | --- | --- |
| Host | `api.getjobber.com/api/graphql` | `clienthub.getjobber.com` |
| Serves | the business running on Jobber | that business's customers |
| Auth | OAuth2 against an app you register | a secret hub URL + session |
| Node-reachable | yes | **no** — Cloudflare |
The Developer API is a **seller** surface. To use it you register an app in
Jobber's Developer Center, and the OAuth grant is authorized *by a Jobber
account* — the business's. As their customer you have no such account and
nothing to authorize. There is no consumer tier, and no scope that exposes "the
invoices sent to me".
## Probes that establish it
Verified 2026-08-09. The API accepts the client identity immediately, which is
what makes it tempting:
```sh
# unauthenticated: the field is hidden, not rejected
curl -s -X POST https://api.getjobber.com/api/graphql \
-H 'Content-Type: application/json' \
-H 'X-JOBBER-GRAPHQL-VERSION: 2025-04-16' \
-d '{"query":"{ account { id name } }"}'
# -> "The field account on an object of type Query was hidden because you are
# unauthenticated" (HTTP 200)
# bogus bearer: the token is checked, so the transport is fine
curl -s -X POST https://api.getjobber.com/api/graphql \
-H 'Authorization: Bearer nope' ...
# -> {"message":"Token not recognized"} (HTTP 401)
# the OAuth token endpoint exists and validates client credentials
curl -s -X POST https://api.getjobber.com/api/oauth/token \
-d 'grant_type=authorization_code&client_id=x&client_secret=y&code=z'
# -> "The provided client id and secret do not match an existing application"
```
Everything works except the one thing that matters: the account those tokens
would reach is the vendor's, not yours.
Introspection is open unauthenticated and returns **410 queries and 629
mutations** — the full staff schema. That breadth is a trap, not an
opportunity: it is the surface Jobber's own web app uses, and every field of it
is gated on a staff session.
`clienthub.getjobber.com/api/graphql` answers introspection too, and returns
that *same* staff schema. It is not a client-facing API and not a shortcut.
## Cloudflare fingerprints the TLS client
The hub pages 403 with `<title>Just a moment...` from Node and curl, and keep
doing so when given a current Chrome User-Agent plus the full browser `Accept*`
set. What clears the challenge is being a real browser at the TLS layer, which
is why the request has to originate in the tab.
Two consequences worth stating plainly:
- **Do not add UA spoofing.** It does not work here, and code that spoofs a UA
reads as though someone verified that it did.
- **A lifted cookie will not travel.** `cf_clearance` is bound to IP, UAskill-card.md
## Description: Reads a customer's Jobber Client Hub appointments, invoices, quotes, and work requests through a signed-in browser tab and returns structured records for shell-based workflows. This skill is ready for commercial/non-commercial use. ## Publisher: [chrischall](https://clawhub.ai/user/chrischall) ### License/Terms of Use: MIT-0 ## Use Case: Customers and developers use this skill to look up their own Jobber Client Hub appointments, invoices, quotes, and work requests from a shell without running an MCP server. ### Deployment Geography for Use: Global ## Known Risks and Mitigations: Risk: A Jobber hub URL grants access to customer records if exposed. Mitigation: Treat each hub URL like a password; keep it out of committed files and shared shell history. Risk: The browser bridge receives fetch access to getjobber.com. Mitigation: Review the CLI package and browser extension source and release before installation, and grant only the fetch capability required by the skill. Risk: Account-changing actions or payments require separate safeguards. Mitigation: Use this skill only for read-only lookup; handle payments and account changes directly in the hub. ## Reference(s): - [Jobber MCP ClawHub release](https://clawhub.ai/chrischall/skills/jobber-mcp) - [Usage recipes](artifact/references/recipes.md) - [Client Hub access and API distinction](artifact/references/why-not-the-api.md) - [ContextMint Bridge source](https://github.com/nullnet-app/contextmint-bridge) - [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases) ## Skill Output: **Output Type(s):** [JSON, Shell commands, Guidance] **Output Format:** [JSON records and Markdown with shell commands] **Output Parameters:** [1D] **Other Properties Related to Output:** [Record URLs are hub-relative and omit the hub credential; prefix the user's hub URL to open a record.] ## Skill Version(s): 1.0.7 (source: ClawHub release metadata) ## Ethical Considerations: Users should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.
AionUi
Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!
activepieces
AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents
cherry-studio
AI productivity studio with smart chat, autonomous agents, and 300+ assistants.
CopilotKit
The Frontend for Agents & Generative UI. React + Angular
Machine-readable data
The same record, as JSON, for agents and crawlers.
{
"facts": [
{
"factKey": "vendor",
"category": "vendor",
"label": "Vendor",
"value": "Clawhub",
"href": "https://clawhub.ai/chrischall/skills/jobber-mcp",
"sourceUrl": "https://clawhub.ai/chrischall/skills/jobber-mcp",
"sourceType": "profile",
"confidence": "medium",
"observedAt": "2026-10-11T08:53:29.687Z",
"isPublic": true
},
{
"factKey": "protocols",
"category": "compatibility",
"label": "Protocol compatibility",
"value": "OpenClaw",
"href": "https://www.xpersona.co/api/v1/agents/clawhub-chrischall-jobber-mcp/contract",
"sourceUrl": "https://www.xpersona.co/api/v1/agents/clawhub-chrischall-jobber-mcp/contract",
"sourceType": "contract",
"confidence": "medium",
"observedAt": "2026-10-11T08:53:29.687Z",
"isPublic": true
},
{
"factKey": "traction",
"category": "adoption",
"label": "Adoption signal",
"value": "1.1K downloads",
"href": "https://clawhub.ai/chrischall/jobber-mcp",
"sourceUrl": "https://clawhub.ai/chrischall/jobber-mcp",
"sourceType": "profile",
"confidence": "medium",
"observedAt": "2026-10-11T08:53:29.687Z",
"isPublic": true
},
{
"factKey": "latest_release",
"category": "release",
"label": "Latest release",
"value": "1.0.7",
"href": "https://clawhub.ai/chrischall/jobber-mcp",
"sourceUrl": "https://clawhub.ai/chrischall/jobber-mcp",
"sourceType": "release",
"confidence": "medium",
"observedAt": "2026-10-09T23:25:06.464Z",
"isPublic": true
},
{
"factKey": "handshake_status",
"category": "security",
"label": "Handshake status",
"value": "UNKNOWN",
"href": "https://www.xpersona.co/api/v1/agents/clawhub-chrischall-jobber-mcp/trust",
"sourceUrl": "https://www.xpersona.co/api/v1/agents/clawhub-chrischall-jobber-mcp/trust",
"sourceType": "trust",
"confidence": "medium",
"observedAt": null,
"isPublic": true
}
],
"events": [
{
"eventType": "release",
"title": "Release 1.0.7",
"description": "- Output contract change: All record URLs (.url) are now relative to your hub (e.g. appointments/2236612358) instead of including the hub UUID. Prefix $JOBBER_HUB/ to open or fetch. - Updated documentation in SKILL.md and references/recipes.md to clarify new URL handling and prevent misuse. - Removed outdated skill-card.md file.",
"href": "https://clawhub.ai/chrischall/jobber-mcp",
"sourceUrl": "https://clawhub.ai/chrischall/jobber-mcp",
"sourceType": "release",
"confidence": "medium",
"observedAt": "2026-10-09T23:25:06.464Z",
"isPublic": true
}
]
}Record generated Oct 11, 2026.
