@zackbart/connecta 0.35.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +8 -4
  3. package/bin/version.mjs +1 -1
  4. package/dist/auth/downstream-oauth.js +71 -79
  5. package/dist/auth/static-oauth.js +104 -26
  6. package/dist/connectors/api-connector.d.ts +17 -0
  7. package/dist/connectors/api-connector.js +3 -1
  8. package/dist/http/client.js +1 -1
  9. package/dist/http/paging.js +1 -2
  10. package/dist/http/services.js +1 -1
  11. package/dist/http/tools.js +0 -4
  12. package/dist/operator-ui/contract.d.ts +1 -0
  13. package/dist/operator-ui/generated.js +4 -4
  14. package/dist/providers/_shared/google/kit.js +29 -139
  15. package/dist/providers/_shared/rest/kit.js +4 -404
  16. package/dist/providers/docs/tools.js +1 -2
  17. package/dist/providers/drive/api.js +1 -1
  18. package/dist/providers/forms/tools.js +1 -2
  19. package/dist/providers/gmail/tools.js +2 -2
  20. package/dist/providers/planning-center/lib/constants.d.ts +1 -1
  21. package/dist/providers/quickbooks/api.js +299 -0
  22. package/dist/providers/quickbooks/index.d.ts +13 -0
  23. package/dist/providers/quickbooks/index.js +93 -0
  24. package/dist/providers/quickbooks/lib/query.js +118 -0
  25. package/dist/providers/quickbooks/lib/writes.js +168 -0
  26. package/dist/providers/quickbooks/safety.js +222 -0
  27. package/dist/providers/quickbooks/skill.generated.js +5 -0
  28. package/dist/providers/quickbooks/tools.js +117 -0
  29. package/dist/providers/sheets/tools.js +1 -2
  30. package/dist/providers/slides/tools.js +2 -2
  31. package/dist/providers/vercel/index.js +1 -2
  32. package/dist/routes/oauth.js +3 -0
  33. package/dist/runtime/call.js +0 -4
  34. package/dist/skills.js +0 -1
  35. package/dist/types.d.ts +2 -0
  36. package/dist/ui.d.ts +1 -1
  37. package/dist/ui.js +0 -1
  38. package/dist/version.d.ts +1 -1
  39. package/dist/version.js +1 -1
  40. package/documentation/README.md +1 -0
  41. package/documentation/architecture.md +134 -301
  42. package/documentation/auth.md +47 -17
  43. package/documentation/integrating.md +1 -1
  44. package/documentation/meta-tools.md +1 -1
  45. package/documentation/operator-ui.md +16 -3
  46. package/documentation/providers.md +382 -0
  47. package/package.json +7 -8
  48. package/templates/node/package.json +1 -1
  49. package/dist/operator-ui/agents.d.ts +0 -75
  50. package/dist/operator-ui/agents.js +0 -114
  51. package/dist/operator-ui/config-summary.js +0 -566
  52. package/dist/operator-ui/connection-map.js +0 -378
  53. package/dist/operator-ui/endpoints.js +0 -212
  54. package/dist/operator-ui/fix-prompts.d.ts +0 -18
  55. package/dist/operator-ui/fix-prompts.js +0 -79
  56. package/dist/operator-ui/health.js +0 -52
  57. package/dist/operator-ui/member-page.js +0 -97
  58. package/dist/operator-ui/overview.js +0 -126
  59. package/dist/operator-ui/setup-commands.js +0 -47
  60. package/dist/operator-ui/view.d.ts +0 -378
  61. package/dist/operator-ui/view.js +0 -631
  62. package/dist/providers/_shared/rest/dispatch.js +0 -21
  63. package/dist/providers/_shared/rest/tools.js +0 -592
@@ -448,7 +448,7 @@ export default defineMcpClientConnection({
448
448
  url: "https://connecta.example.com/agent/assistant",
449
449
  description: "Use the assistant's shared CRM and ticket tools.",
450
450
  auth: {
451
- credentialOwner: "app",
451
+ principalType: "app",
452
452
  getToken: async () => ({ token: await getVercelOidcToken() }),
453
453
  },
454
454
  });
@@ -1390,8 +1390,10 @@ leaves the local grant removed. The management route returns HTTP 200 with
1390
1390
  code. Revoke the old grant in the provider's console if removal there matters.
1391
1391
  With no advertised endpoint, Disconnect makes no request. Repeating Disconnect
1392
1392
  never retries revocation, because the removed grant is no longer available.
1393
- Restart makes no revocation request. Static `api()` OAuth has no discovered
1394
- revocation endpoint and continues to remove authorization locally.
1393
+ Restart makes no revocation request. Static `api()` OAuth uses the same
1394
+ removal and revocation flow when deployment configuration supplies
1395
+ `revocationEndpoint`; without it, removal remains local. The configured
1396
+ client secret is used in memory and is never saved with the grant.
1395
1397
 
1396
1398
  ## Refresh failures
1397
1399
 
@@ -1406,11 +1408,11 @@ Copy these durable records during storage migration.
1406
1408
 
1407
1409
  Each fingerprint record names its dispatch epoch, holder, and resolution state:
1408
1410
 
1409
- | State | Send gate |
1410
- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1411
- | `outstanding` | Dispatched without a definitive outcome yet. Refuse the fingerprint in every epoch. |
1412
- | `ambiguous` | The sent request's outcome is unknowable. Refuse the fingerprint in every epoch, including when re-consent returns it again. |
1413
- | `resolved` | The tokens were committed or a definitive failure was recorded. Refuse another send in the same epoch. A later epoch may send once only when its code exchange completed after the resolution was recorded. |
1411
+ | State | Send gate |
1412
+ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1413
+ | `outstanding` | Dispatched without a definitive outcome yet. Refuse the fingerprint in every epoch. |
1414
+ | `ambiguous` | The sent request's outcome is unknowable. Refuse the fingerprint in every epoch, including when re-consent returns it again. |
1415
+ | `resolved` | The tokens were committed or a definitive failure was recorded. A completed lease whose token digest matches the current grant may start the next generation in the same epoch. A later epoch needs a code exchange that observed this exact resolved record. |
1414
1416
 
1415
1417
  Resolution writes use CAS against the exact outstanding record and record a
1416
1418
  `resolvedAt` timestamp with a resolved outcome. When accepting a code response,
@@ -1423,6 +1425,14 @@ outstanding dispatch. An earlier consent cannot become eligible merely because
1423
1425
  the pending refresh later resolves. Competing epochs cannot both replace the
1424
1426
  same record, and a late answer cannot turn an ambiguous record into resolved.
1425
1427
 
1428
+ For vendors that return unchanged refresh-token bytes, a successful token
1429
+ commit and its matching completed lease authorize the next refresh generation
1430
+ in that epoch. It must replace the exact resolved fingerprint by CAS before
1431
+ sending. Outstanding, ambiguous and failed attempts never authorize reuse;
1432
+ concurrent callers with an older access token adopt the committed result.
1433
+ An unsent successor retains the prior successful proof during cleanup, so a
1434
+ transient storage failure before dispatch can be retried without losing the grant.
1435
+
1426
1436
  An ambiguous token stays blocked even if re-consent returns identical bytes.
1427
1437
  Recovery requires re-consent that yields a different refresh token, or
1428
1438
  revocation at the provider. Restart never deletes spent records or moves old
@@ -2400,6 +2410,13 @@ need `consumeAuthError` to accept error callbacks, sharing `finishAuth`'s atomic
2400
2410
  consent claim. Reissue
2401
2411
  pending consent links after upgrading; callbacks without a saved initiating user cannot complete.
2402
2412
 
2413
+ Custom connectors may implement `verifyCallbackParameters(params, ctx)` for
2414
+ provider-specific callback assertions. The route calls it after successful
2415
+ state verification and before issuer validation, handoff consumption, error
2416
+ handling, or code exchange. Returning false or throwing produces the generic
2417
+ invalid-callback refusal. Apply the same assertions inside `finishAuth` when
2418
+ supporting direct programmatic completion.
2419
+
2403
2420
  `compareAndSet` atomically claims link nonces, callback handoffs, and consents, with one concurrent winner,
2404
2421
  so each completes once.
2405
2422
  [Meta-tools](./meta-tools.md#authorization-recovery) describes recovery.
@@ -2506,15 +2523,28 @@ api("church", {
2506
2523
  No discovery or registration occurs; all URLs are configuration, so the
2507
2524
  [advertised-URL rule](#urls-a-downstream-advertises) does not apply.
2508
2525
 
2509
- | Option or binding | Contract |
2510
- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2511
- | Endpoints | Checked at construction: HTTPS, HTTP only on loopback, no credentials or fragment. |
2512
- | `pkce` | S256 by default; `false` omits challenge and verifier. |
2513
- | `authorizationParams` | Adds provider parameters; cannot restate the grant's own. |
2514
- | `tokenRequestHeaders` | Adds code-exchange and every refresh's headers; cannot set `Authorization`, `Content-Type`, `Content-Length`, `Cookie`, or `Host`. |
2515
- | `tokenEndpointAuthMethod` | Defaults to `client_secret_basic` with a secret, `none` without; mismatched pairings refuse construction. |
2516
- | Issuer/resource | No advertised issuer means no required RFC 9207 `iss` or sent RFC 8707 `resource`. The grant binds to the token endpoint; after it changes, old tokens are never sent and the next consent replaces them. |
2517
- | Client | One deployment-config identity, never written or sealed to storage; no owner vault slot. Store leaks contain no client secret; Disconnect deletes none and Restart carries none. Read from environment or Worker secrets; empty strings refuse construction without quoting values. |
2526
+ | Option or binding | Contract |
2527
+ | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
2528
+ | Endpoints | Checked at construction: HTTPS, HTTP only on loopback, no credentials or fragment. |
2529
+ | `pkce` | S256 by default; `false` omits challenge and verifier. |
2530
+ | `authorizationParams` | Adds provider parameters; cannot restate the grant's own. |
2531
+ | `expectedCallbackParameters` | Optional `Readonly<Record<string, string>>` of fixed provider response values. Each configured parameter must occur exactly once with its exact decoded value, after pending-state verification and before issuer validation, flow claims, code exchange, or grant persistence. Missing, duplicate, or mismatched values refuse without exchanging a code or returning parameter values. Omission preserves existing behavior. |
2532
+ | `revocationEndpoint` | Optional trusted HTTPS revocation URL (loopback HTTP allowed), without credentials, query or fragment. Disconnect removes the local grant before one bounded attempt using the configured client. Failure reports `oauth_revocation_failed`; a repeated Disconnect never retries. |
2533
+ | `revocationRequestFormat` | `"form"` by default; `"json"` sends JSON without `token_type_hint`. Requires `revocationEndpoint` when set. |
2534
+ | `tokenRequestHeaders` | Adds code-exchange and every refresh's headers; cannot set `Authorization`, `Content-Type`, `Content-Length`, `Cookie`, or `Host`. |
2535
+ | `tokenEndpointAuthMethod` | Defaults to `client_secret_basic` with a secret, `none` without; mismatched pairings refuse construction. |
2536
+ | Issuer/resource | No advertised issuer means no required RFC 9207 `iss` or sent RFC 8707 `resource`. The grant binds to the token endpoint; after it changes, old tokens are never sent and the next consent replaces them. |
2537
+ | Client | One deployment-config identity, never written or sealed to storage; no owner vault slot. Store leaks contain no client secret; Disconnect deletes none and Restart carries none. Read from environment or Worker secrets; empty strings refuse construction without quoting values. |
2538
+
2539
+ For a connector bound to a fixed company, set
2540
+ `expectedCallbackParameters: { realmId: "company_alice" }`. This checks all
2541
+ callbacks, including errors, and direct `finishAuth` calls. Names must be
2542
+ nonempty ASCII letters, digits, dots, underscores, or hyphens; values must be
2543
+ nonempty strings. The protocol fields `code`, `state`, `iss`, `error`,
2544
+ `error_description`, and `error_uri` are reserved. Malformed expectations throw
2545
+ at construction without quoting values. Unconfigured provider parameters are
2546
+ ignored. Expectations are deployment configuration, never grant metadata or
2547
+ dynamic company selection; they do not inspect or rebind an existing grant.
2518
2548
 
2519
2549
  Handlers never see the grant. `ctx.oauth.fetch(url, init)` sends the calling
2520
2550
  owner's access token as `Authorization: Bearer` with these rules:
@@ -328,7 +328,7 @@ check shared behavior. Provider-specific tests remain beside each provider.
328
328
 
329
329
  Use [`@zackbart/connecta-eve`](https://github.com/zackbart/connecta/blob/main/packages/connecta-eve/README.md)
330
330
  in the Eve app for an app-owned connection and endpoint instructions refreshed
331
- at turn start. It requires Node 24 and Eve 0.83.x, and installs separately from
331
+ once per turn. It requires Node 24 and Eve 0.84.x, and installs separately from
332
332
  Connecta. Follow its README for the two agent files, token environment variables,
333
333
  optional write approval and Vercel OIDC token source. Configure the server's
334
334
  [agent and pool membership](./auth.md#issue-rotate-or-revoke-an-agent-token)
@@ -1292,7 +1292,7 @@ window, a native `tools/list` carries a 300-second private cache hint, against
1292
1292
  an hour on meta endpoints. This hint does not guarantee that a host refreshes
1293
1293
  its cached annotations; the stale-approval race is accepted on writable pools.
1294
1294
 
1295
- **Listing.** `tools/list` is one page with no cursor (Eve 0.83 reads only the
1295
+ **Listing.** `tools/list` is one page with no cursor (Eve 0.84 reads only the
1296
1296
  first page). A pool listing more than 1,000 tools fails `tools/list` with a
1297
1297
  JSON-RPC error asking the operator to narrow the pool; nothing is silently
1298
1298
  dropped. A connector whose catalog cannot load is left out of that listing
@@ -519,8 +519,9 @@ says the snapshot is for maintainers. It requires the UI module and the
519
519
  existing doctor authentication environment variables; it runs no diagnostic
520
520
  program, follows no redirects, and prints no raw HTTP failure body.
521
521
 
522
- The operator shell uses React, TanStack Router/Query/Table, Radix, cmdk and
523
- Tailwind v4. Hanken Grotesk, JetBrains Mono, CSS, JavaScript and dependency notices are hashed assets
522
+ The operator shell uses React, TanStack Router, Radix and cmdk. Esbuild bundles
523
+ the authored CSS with an explicit browser reset; it generates no utility classes.
524
+ Hanken Grotesk, JetBrains Mono, CSS, JavaScript and dependency notices are hashed assets
524
525
  under `/ui/assets/*`, served identically with immutable cache headers on Node
525
526
  and Workers. HTML contains only mount points and escaped inert configuration;
526
527
  it remains uncached. Ahead of the stylesheet, every operator page (sign-in
@@ -537,7 +538,11 @@ private browsing: a read finds nothing stored and a write keeps nothing, so a
537
538
  bearer token is not remembered there. `generated.ts` is ignored and generated before build and
538
539
  test; `check:operator-ui` detects stale assets and shared page styles. The UI
539
540
  stays behind `./ui`, outside the root import graph. The identity-fenced store
540
- owns authenticated reads and existing mutations. An Access-only shell selects
541
+ owns authenticated reads and existing mutations, with explicit identity and
542
+ read-cycle AbortControllers, revision fences, and no query cache or automatic
543
+ mutation replay. Browser-only view models ship inside the hashed bundle, with
544
+ no duplicate standalone server modules. The shared contract owns the unchanged
545
+ `OperatorPage` union exported from `@zackbart/connecta/ui`. An Access-only shell selects
541
546
  Access even when the HTML request has no trusted context; only authenticated
542
547
  API responses establish the session. A gated Access session offers Retry.
543
548
  Focus, visibility, and timer-driven recovery share one admission-read schedule
@@ -661,3 +666,11 @@ serve the authenticated shell and data. The browser lives in
661
666
  and [browser flows](https://github.com/zackbart/connecta/blob/main/test/browser/operator-ui.spec.ts)
662
667
  defend filtering and behavior. Use [Operator UI tests](./operator-tests.md)
663
668
  for the browser state matrix and Linux snapshot procedure.
669
+
670
+ The browser flows also hold configuration and connector reads open across a
671
+ bearer identity switch, observe cancellation of the old HTTP response, and
672
+ require only the replacement viewer's data after navigation. A held OAuth poll
673
+ must abort on navigation without sending its start again; the Access recovery
674
+ flow checks explicit Retry and browser-history navigation without a document
675
+ reload. The packed deployment journey compiles every `OperatorPage` through
676
+ the public `@zackbart/connecta/ui` alias after declaration pruning.
@@ -7,6 +7,258 @@ roster](./integrating.md#add-or-remove-a-connector) covers the general
7
7
  procedure and the providers not listed here. Agent guidance for each
8
8
  provider ships with its connection's usage guide, not here.
9
9
 
10
+ ## API sources and tool inventory
11
+
12
+ Maintained providers pair reviewed API contracts and indexes with Connecta's
13
+ adapters and tools. Sources include upstream OpenAPI,
14
+ Google Discovery conversions, reviewed HTML/documentation conversions and
15
+ hand-authored endpoint contracts. Tithe.ly and Overflow use endpoint checks
16
+ without vendored OpenAPI documents. `remoteMcp()` discovers live server tools
17
+ instead.
18
+
19
+ QuickBooks Online uses a restricted hand-authored Accounting API contract with
20
+ manual vendor review; its read hatch cannot execute arbitrary query SQL.
21
+
22
+ These generated reference catalogs separate named workflows from API tools
23
+ and reads from writes. API search/details inspect indexed contracts, including
24
+ refused operations. Raw read/write calls accept only reviewed operations within
25
+ configured scope and safety rules. Gmail has no generic write tool.
26
+
27
+ Addresses use your connector ID: Stripe configured as `billing` exposes
28
+ `billing.stripe_api_read`. Configuration, credentials and read-only policy affect
29
+ availability. Planning Center labels identify required products. Use live
30
+ discovery for your deployment's catalog.
31
+
32
+ <!-- provider-inventory:start -->
33
+
34
+ <details>
35
+ <summary>Breeze ChMS (15 tools)</summary>
36
+
37
+ [Setup](#breeze-chms). **API source:** [Reviewed HTML/documentation conversion](https://app.breezechms.com/api).
38
+
39
+ - **Named reads:** `get_account_summary`, `get_person`, `list_attendance`, `list_contributions`, `list_events`, `list_funds`, `list_people`, `list_profile_fields`, `list_tags`.
40
+ - **Named writes:** `add_person`, `update_person`.
41
+ - **API reads:** `breeze_api_details`, `breeze_api_read`, `breeze_api_search`.
42
+ - **API writes:** `breeze_api_write`.
43
+
44
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/breeze).
45
+
46
+ </details>
47
+
48
+ <details>
49
+ <summary>Church Community Builder (20 tools)</summary>
50
+
51
+ [Setup](#church-community-builder). **API source:** [Upstream OpenAPI](https://docs.pushpay.io/chms-v2/openapi/chms-api-specs.json?download=1).
52
+
53
+ - **Named reads:** `get_event_attendance`, `get_event`, `get_family`, `get_giving_metrics`, `get_group`, `get_individual`, `get_me`, `list_event_attendees`, `list_events`, `list_families`, `list_group_members`, `list_groups`, `list_individual_groups`, `list_individual_notes`, `list_individuals`, `search_records`.
54
+ - **Named writes:** None.
55
+ - **API reads:** `ccb_api_details`, `ccb_api_read`, `ccb_api_search`.
56
+ - **API writes:** `ccb_api_write`.
57
+
58
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/ccb).
59
+
60
+ </details>
61
+
62
+ <details>
63
+ <summary>Cloudflare (9 tools)</summary>
64
+
65
+ [Setup](#cloudflare). **API source:** [Upstream OpenAPI](https://raw.githubusercontent.com/cloudflare/api-schemas/main/openapi.json). [Supplemental reviewed contract](https://developers.cloudflare.com/analytics/graphql-api/).
66
+
67
+ - **Named reads:** `graphql_query`, `list_accounts`, `list_zones`, `verify_credential`.
68
+ - **Named writes:** None.
69
+ - **API reads:** `cloudflare_api_details`, `cloudflare_api_read`, `cloudflare_api_search`.
70
+ - **API writes:** `cloudflare_api_upload`, `cloudflare_api_write`.
71
+
72
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/cloudflare).
73
+
74
+ </details>
75
+
76
+ <details>
77
+ <summary>Google Docs (10 tools)</summary>
78
+
79
+ [Setup](#google-docs). **API source:** [Google Discovery conversion](https://docs.googleapis.com/$discovery/rest?version=v1).
80
+
81
+ - **Named reads:** `get_document`.
82
+ - **Named writes:** `append_text`, `batch_update_document`, `create_document`, `insert_text`, `replace_all_text`.
83
+ - **API reads:** `docs_api_details`, `docs_api_read`, `docs_api_search`.
84
+ - **API writes:** `docs_api_write`.
85
+
86
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/docs).
87
+
88
+ </details>
89
+
90
+ <details>
91
+ <summary>Google Drive (21 tools)</summary>
92
+
93
+ [Setup](#google-drive). **API source:** [Google Discovery conversion](https://developers.google.com/workspace/drive/api/reference/rest/v3).
94
+
95
+ - **Named reads:** `get_file_content`, `get_file`, `list_folder_items`, `list_permissions`, `list_shared_drives`, `search_files`.
96
+ - **Named writes:** `copy_file`, `create_file`, `create_folder`, `delete_permission`, `move_file`, `restore_file`, `share_file`, `trash_file`, `update_file_content`, `update_file`, `update_permission`.
97
+ - **API reads:** `drive_api_details`, `drive_api_read`, `drive_api_search`.
98
+ - **API writes:** `drive_api_write`.
99
+
100
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/drive).
101
+
102
+ </details>
103
+
104
+ <details>
105
+ <summary>Google Forms (10 tools)</summary>
106
+
107
+ [Setup](#google-forms). **API source:** [Google Discovery conversion](https://developers.google.com/workspace/forms/api/reference/rest).
108
+
109
+ - **Named reads:** `get_form`, `get_response`, `list_responses`.
110
+ - **Named writes:** `batch_update_form`, `create_form`, `update_form_info`.
111
+ - **API reads:** `forms_api_details`, `forms_api_read`, `forms_api_search`.
112
+ - **API writes:** `forms_api_write`.
113
+
114
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/forms).
115
+
116
+ </details>
117
+
118
+ <details>
119
+ <summary>GitHub (7 tools)</summary>
120
+
121
+ [Setup](#github). **API source:** [Upstream OpenAPI](https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json).
122
+
123
+ - **Named reads:** `list_scopes`, `search_scoped`.
124
+ - **Named writes:** `merge_pull_request`.
125
+ - **API reads:** `github_api_details`, `github_api_read`, `github_api_search`.
126
+ - **API writes:** `github_api_write`.
127
+
128
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/github).
129
+
130
+ </details>
131
+
132
+ <details>
133
+ <summary>Gmail (12 tools)</summary>
134
+
135
+ [Setup](#gmail). **API source:** [Google Discovery conversion](https://developers.google.com/workspace/gmail/api/reference/rest).
136
+
137
+ - **Named reads:** `get_attachment`, `get_draft`, `get_message`, `get_thread`, `list_drafts`, `list_labels`, `search_threads`.
138
+ - **Named writes:** `create_draft`, `update_draft`.
139
+ - **API reads:** `gmail_api_details`, `gmail_api_read`, `gmail_api_search`.
140
+ - **API writes:** None.
141
+
142
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/gmail).
143
+
144
+ </details>
145
+
146
+ <details>
147
+ <summary>Overflow (17 tools)</summary>
148
+
149
+ [Setup](#overflow). **API source:** Hand-authored endpoint contracts; [upstream endpoint checks](https://server.stage.overflow.co/api/docs/openapi.json). No vendored OpenAPI document.
150
+
151
+ - **Named reads:** `get_contribution`, `get_deposit_summary`, `get_deposit`, `get_donor`, `list_campaigns`, `list_chargebacks`, `list_contributions`, `list_deposits`, `list_donors`, `list_locations`, `list_payment_methods`, `list_refunds`, `list_subscriptions`.
152
+ - **Named writes:** None.
153
+ - **API reads:** `overflow_api_details`, `overflow_api_read`, `overflow_api_search`.
154
+ - **API writes:** `overflow_api_write`.
155
+
156
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/overflow).
157
+
158
+ </details>
159
+
160
+ <details>
161
+ <summary>Planning Center (27 tools)</summary>
162
+
163
+ [Setup](#planning-center). **API source:** Composed upstream OpenAPI contracts: [/people/v2](https://developer.planning.center/docs/#/people/2026-06-04), [/services/v2](https://developer.planning.center/docs/#/services/2018-11-01), [/groups/v2](https://developer.planning.center/docs/#/groups/2023-07-10), [/check-ins/v2](https://developer.planning.center/docs/#/check-ins/2025-05-28), [/calendar/v2](https://developer.planning.center/docs/#/calendar/2026-06-22), [/registrations/v2](https://developer.planning.center/docs/#/registrations/2025-05-01), [/giving/v2](https://developer.planning.center/docs/#/giving/2019-10-18), [/publishing/v2](https://developer.planning.center/docs/#/publishing/2024-03-25), [/webhooks/v2](https://developer.planning.center/docs/#/webhooks/2022-10-20), [/api/v2](https://developer.planning.center/docs/#/api/2026-09-24).
164
+
165
+ - **Named reads:** `get_me`, `get_person`, `get_plan` (services enabled), `list_donations` (giving enabled), `list_funds` (giving enabled), `list_group_memberships` (groups enabled), `list_groups` (groups enabled), `list_person_field_data`, `list_person_notes`, `list_person_schedules` (services enabled), `list_plans` (services enabled), `list_service_types` (services enabled), `list_teams` (services enabled), `list_workflow_cards`, `list_workflows`, `search_people`.
166
+ - **Named writes:** `add_group_member` (groups enabled), `add_person_note`, `add_workflow_card`, `apply_workflow_card_action`, `create_person`, `schedule_plan_person` (services enabled), `update_person`.
167
+ - **API reads:** `pco_api_details`, `pco_api_read`, `pco_api_search`.
168
+ - **API writes:** `pco_api_write`.
169
+
170
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/planning-center).
171
+
172
+ </details>
173
+
174
+ <details>
175
+ <summary>QuickBooks Online (10 tools)</summary>
176
+
177
+ [Setup](#quickbooks-online). **API source:** Hand-authored endpoint contracts. No vendored OpenAPI document.
178
+
179
+ - **Named reads:** `get_company_info`, `get_record`, `get_report`, `search_records`.
180
+ - **Named writes:** `create_customer`, `create_invoice`, `update_customer`.
181
+ - **API reads:** `quickbooks_api_details`, `quickbooks_api_read`, `quickbooks_api_search`.
182
+ - **API writes:** None.
183
+
184
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/quickbooks).
185
+
186
+ </details>
187
+
188
+ <details>
189
+ <summary>Google Sheets (13 tools)</summary>
190
+
191
+ [Setup](#google-sheets). **API source:** [Google Discovery conversion](https://developers.google.com/workspace/sheets/api/reference/rest).
192
+
193
+ - **Named reads:** `get_spreadsheet`, `get_values`.
194
+ - **Named writes:** `add_sheet`, `append_values`, `batch_update_spreadsheet`, `batch_update_values`, `clear_values`, `create_spreadsheet`, `update_values`.
195
+ - **API reads:** `sheets_api_details`, `sheets_api_read`, `sheets_api_search`.
196
+ - **API writes:** `sheets_api_write`.
197
+
198
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/sheets).
199
+
200
+ </details>
201
+
202
+ <details>
203
+ <summary>Google Slides (19 tools)</summary>
204
+
205
+ [Setup](#google-slides). **API source:** [Google Discovery conversion](https://developers.google.com/workspace/slides/api/reference/rest).
206
+
207
+ - **Named reads:** `get_page`, `get_presentation`, `get_slide_thumbnail`, `list_comments`, `list_layouts`.
208
+ - **Named writes:** `batch_update_presentation`, `create_comment_reply`, `create_comment`, `create_presentation`, `create_slide`, `delete_comment_reply`, `delete_comment`, `replace_all_text`, `update_comment_post`, `update_comment_thread`.
209
+ - **API reads:** `slides_api_details`, `slides_api_read`, `slides_api_search`.
210
+ - **API writes:** `slides_api_write`.
211
+
212
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/slides).
213
+
214
+ </details>
215
+
216
+ <details>
217
+ <summary>Stripe (6 tools)</summary>
218
+
219
+ [Setup](#stripe). **API source:** [Upstream OpenAPI](https://raw.githubusercontent.com/stripe/openapi/master/latest/openapi.spec3.json).
220
+
221
+ - **Named reads:** `get_balance_summary`, `get_stripe_account_info`.
222
+ - **Named writes:** None.
223
+ - **API reads:** `stripe_api_details`, `stripe_api_read`, `stripe_api_search`.
224
+ - **API writes:** `stripe_api_write`.
225
+
226
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/stripe).
227
+
228
+ </details>
229
+
230
+ <details>
231
+ <summary>Tithe.ly (11 tools)</summary>
232
+
233
+ [Setup](#tithely). **API source:** Hand-authored endpoint contracts; [upstream endpoint checks](https://docs.tithe.ly/reference/). No vendored OpenAPI document.
234
+
235
+ - **Named reads:** `get_charge`, `get_recurring_charge`, `list_accounts`, `list_charges`, `list_organizations`, `list_payment_methods`, `list_recurring_charges`.
236
+ - **Named writes:** None.
237
+ - **API reads:** `tithely_api_details`, `tithely_api_read`, `tithely_api_search`.
238
+ - **API writes:** `tithely_api_write`.
239
+
240
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/tithely).
241
+
242
+ </details>
243
+
244
+ <details>
245
+ <summary>Vercel (11 tools)</summary>
246
+
247
+ [Setup](#vercel). **API source:** [Upstream OpenAPI](https://openapi.vercel.sh/).
248
+
249
+ - **Named reads:** `get_deployment_build_logs`, `get_runtime_logs`, `list_project_env_vars`, `list_teams`.
250
+ - **Named writes:** `update_project_env_var`, `upsert_project_env_var`.
251
+ - **API reads:** `vercel_api_details`, `vercel_api_read`, `vercel_api_search`.
252
+ - **API writes:** `vercel_api_upload`, `vercel_api_write`.
253
+
254
+ **Contributor evidence (optional):** [contracts, adapters and review](https://github.com/zackbart/connecta/tree/main/src/providers/vercel).
255
+
256
+ </details>
257
+
258
+ <!-- provider-inventory:end -->
259
+
260
+ ## API operation discovery and boundaries
261
+
10
262
  Standard API operation search accepts resource nouns, actions and conversational
11
263
  phrasing. A leading create/add/update/edit/make/set/apply/change/rename/send/delete/remove/cancel/stop
12
264
  with an object prefers reviewed writes and keeps later read words as nouns, as in
@@ -963,3 +1215,133 @@ body and `result.page` carries continuation. Resource keys, decryption JWTs and
963
1215
  private download destinations remain withheld on named and hatch responses.
964
1216
  A 404 does not prove absence. Auxiliary lookup failures send no move; an actual
965
1217
  write failure can have an unknown outcome and requires a read before repetition.
1218
+
1219
+ ## QuickBooks Online
1220
+
1221
+ Available from 0.36.0. Use the deployment's own Intuit app and configure one
1222
+ fixed QuickBooks Online company per connector. Multiple companies need separate
1223
+ connector IDs and separate consent; tool arguments cannot select another
1224
+ company or environment.
1225
+
1226
+ ```ts
1227
+ import { quickbooks } from "@zackbart/connecta/providers/quickbooks";
1228
+
1229
+ const accounting = quickbooks("accounting", {
1230
+ purpose: "Company accounting reports and invoice reconciliation",
1231
+ realmId: process.env.QUICKBOOKS_REALM_ID!,
1232
+ environment: "sandbox",
1233
+ clientId: process.env.QUICKBOOKS_CLIENT_ID!,
1234
+ clientSecret: process.env.QUICKBOOKS_CLIENT_SECRET!,
1235
+ });
1236
+ ```
1237
+
1238
+ Create an Intuit QuickBooks Online app, enable the Accounting API and obtain
1239
+ the client ID and secret for the selected environment. Sandbox and production
1240
+ credentials are separate. Register
1241
+ `<publicUrl>/oauth/callback/accounting` as an exact redirect URI. Set the
1242
+ numeric company/realm ID in deployment configuration, then connect through
1243
+ the operator UI or `authorize_connector`. After valid OAuth state, the callback
1244
+ must contain exactly one `realmId` equal to the configured value before any
1245
+ code exchange. Selecting another company fails authorization. Store app
1246
+ credentials in deployment secrets; token import and endpoint overrides are
1247
+ not supported.
1248
+
1249
+ OAuth defaults to one shared grant; `authScope: "personal"` instead gives each
1250
+ owner a grant for the same fixed company. The requested
1251
+ `com.intuit.quickbooks.accounting` scope permits both reads and writes at Intuit.
1252
+ This provider defaults to `readOnly: true`. Set `readOnly: false` explicitly in
1253
+ deployment code to enable the three bounded named writes below. Connector,
1254
+ endpoint and pool read-only policy still refuses writes before validation or
1255
+ dispatch. It reuses sealed grants, coordinated refresh,
1256
+ rotation and revocation. Access tokens last one hour; refresh authorization
1257
+ requires use within 100 days and expires absolutely after five years. Reconnect
1258
+ when Intuit requires consent again. Do not assume refresh extends the absolute
1259
+ window or infer expiry from provider-specific fields.
1260
+
1261
+ `get_company_info`, `search_records`, `get_record` and `get_report` are the
1262
+ named reads. The reviewed record families are customers, vendors, accounts,
1263
+ items, invoices, bills, received accounting payments and bill payments.
1264
+ `search_records` accepts at most eight structured AND filters and returns up to
1265
+ 100 rows per page (25 by default; configurable with `defaultPageSize`). Its
1266
+ signed continuation binds the original arguments, company, environment,
1267
+ connector and credential owner. Continue with unchanged arguments and cursor.
1268
+ Search is not a snapshot; concurrent accounting changes can alter later pages.
1269
+
1270
+ Reports are allowlisted to ProfitAndLoss, BalanceSheet, CashFlow,
1271
+ AgedReceivables and AgedPayables. P&L and Cash Flow accept `start_date`; all
1272
+ accept `end_date` (translated to `report_date` with `aging_method: "Report_Date"`
1273
+ for AR/AP aging). P&L and Balance Sheet accept `accounting_method` (`Cash` or
1274
+ `Accrual`). No verified currency override is exposed; inspect the returned
1275
+ Header.Currency and never combine unlike currencies. Unsupported combinations fail before
1276
+ dispatch. Report Header, Columns and nested Rows retain section identity,
1277
+ column metadata and empty amount strings. Check the returned period, basis
1278
+ and currency; an empty amount is never converted to zero. Responses use the
1279
+ modernized report service in effect since August 31, 2026. Requests explicitly
1280
+ use the supported minor-version floor 75.
1281
+
1282
+ `quickbooks_api_search` and `quickbooks_api_details` inspect reviewed
1283
+ operations. `quickbooks_api_read` reaches only indexed record/company/report
1284
+ GETs inside this company's configured host and path. `/query` is refused;
1285
+ use the named structured search. Unreviewed entities, arbitrary SQL, URL,
1286
+ realm, scope and token overrides and arbitrary writes are unavailable. Desktop,
1287
+ Payments and Payroll APIs are outside this provider.
1288
+
1289
+ With `readOnly: false`, `create_customer` accepts only DisplayName and optional
1290
+ CompanyName. `update_customer` requires caller-observed Id and SyncToken and
1291
+ uses `sparse: true` for those naming fields; a stale version fails without a
1292
+ version fetch or overwrite. DisplayName must be unique across customers,
1293
+ vendors and employees.
1294
+
1295
+ `create_invoice` creates a real accounting transaction, never a draft, only
1296
+ for a verified US company and a customer using USD. The reviewed autosend
1297
+ contract is US-specific; the initial money contract uses two-decimal USD
1298
+ units. It requires an observed active customer, currency USD, an explicit positive
1299
+ exchange rate, transaction/due dates, DocNumber and 1–20 active Service-item
1300
+ lines. Amounts are positive decimal-unit strings with exactly two fractional
1301
+ digits, at most 999999999.99 per line. Every line explicitly supplies one unit
1302
+ and its price. Preflight reads verify the fixed company Country is US, then
1303
+ recheck the customer currency and item type and activity; they are not an atomic snapshot. No default prices, dates or rates,
1304
+ and no implicit customer/item creation, are used. QuickBooks computes taxes and
1305
+ totals, and locale/company rules may reject the narrow request. Inspect the
1306
+ returned CurrencyRef, ExchangeRate and totals.
1307
+ Each request after the first charges the same call-admission budget before
1308
+ dispatch. Returned references, dates, rate and service prices must match the
1309
+ admitted intent; contradictions produce an unknown, non-retryable outcome.
1310
+
1311
+ Creation fixes EmailStatus to `NotSet` and IPN/online/card/ACH/PayPal/Affirm
1312
+ payment flags to false, accepts no email fields, and never calls a send endpoint.
1313
+ Intuit's documented autosend path requires company opt-in, enabled online
1314
+ payments and `NeedToSend` with BillEmail; the fixed creation body withholds
1315
+ those request conditions. Invoice updates remain unavailable because retaining
1316
+ an existing send-ready state is not established safe, and resetting that state
1317
+ would change existing payment settings. Deletes, voids, delivery, payment
1318
+ execution, batch and other accounting writes remain unavailable. The API hatch
1319
+ refuses POSTs even when named writes are enabled.
1320
+
1321
+ Each write requires `requestId`, a stable identifier for the exact intent,
1322
+ unique across all requests/tools for this company: 1–50 ASCII letters, digits,
1323
+ underscores or hyphens, beginning with a letter or digit. It is sent as Intuit's
1324
+ `requestid` query parameter with minorversion 75. The vendor recognizes repeated
1325
+ content and ID; no retention duration is established. This never permits
1326
+ Connecta to replay automatically: every dispatched write has one attempt,
1327
+ including 401, timeout, server failure and malformed success.
1328
+
1329
+ Reconcile an unknown create through reads before another intent: customer
1330
+ DisplayName (including inactive matches when relevant), or invoice DocNumber
1331
+ plus CustomerRef and currency, dates, lines and computed amounts. DocNumber may
1332
+ repeat and is not proof by itself. Do not blindly create again with a new ID;
1333
+ report ambiguity. Reconcile unknown updates by the known record Id and version.
1334
+ The requestId supplies no lookup endpoint or permanent retention guarantee.
1335
+
1336
+ All named and hatch responses apply the same closed privacy projection before
1337
+ `fields` narrows it. Public Id and SyncToken versions, accounting references,
1338
+ amounts and minimal display names remain; contact emails/phones/addresses,
1339
+ bank/card/tax identifiers, private notes, credentials and private URLs are
1340
+ withheld. No `sensitiveFields` or `raw` option widens these results. Reduce
1341
+ financial records to task-relevant aggregates before returning them to a user.
1342
+ `maxResultBytes`, `callAdmission` and the standard provider title/instructions
1343
+ options remain available. No default admission budget is declared: account for
1344
+ other integrations sharing the app when configuring one. Intuit documents
1345
+ 500 requests per minute per company and 10 per second per company/app in both
1346
+ environments; after HTTP 429, wait at least 60 seconds. Local admission is per
1347
+ runtime and cannot coordinate other deployments' spending.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zackbart/connecta",
3
- "version": "0.35.0",
3
+ "version": "0.36.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "One MCP to rule them all — a single MCP endpoint aggregating many downstream connectors behind a code-first surface of six meta-tools.",
@@ -115,6 +115,10 @@
115
115
  "types": "./dist/providers/planning-center/index.d.ts",
116
116
  "import": "./dist/providers/planning-center/index.js"
117
117
  },
118
+ "./providers/quickbooks": {
119
+ "types": "./dist/providers/quickbooks/index.d.ts",
120
+ "import": "./dist/providers/quickbooks/index.js"
121
+ },
118
122
  "./providers/sheets": {
119
123
  "types": "./dist/providers/sheets/index.d.ts",
120
124
  "import": "./dist/providers/sheets/index.js"
@@ -167,8 +171,6 @@
167
171
  "test:browser:install": "playwright install chromium",
168
172
  "test:browser": "playwright test",
169
173
  "test:browser:snapshots": "node scripts/update-operator-snapshots.mjs",
170
- "goldens:update": "node scripts/update-goldens.mjs",
171
- "pregoldens:update": "node scripts/generate-version.mjs && pnpm run build:operator-ui",
172
174
  "pretest:browser:snapshots": "pnpm run build:operator-ui",
173
175
  "test:node": "vitest run --config vitest.config.node.ts",
174
176
  "test:workers": "vitest run --project workers",
@@ -185,6 +187,8 @@
185
187
  "eval:selftest": "tsx eval/selftest.ts",
186
188
  "eval:agent": "tsx eval/run-agent.ts",
187
189
  "eval:smoke": "tsx eval/run-smoke.ts",
190
+ "eval:outcomes": "tsx eval/run-outcomes.ts",
191
+ "preeval:outcomes": "node scripts/generate-version.mjs && pnpm run build:operator-ui",
188
192
  "eval:perf": "tsx eval/run-perf.ts",
189
193
  "eval:report": "tsx eval/report.ts",
190
194
  "check:static": "node --test scripts/check-provider-exemptions.test.mjs && pnpm run format:check && pnpm run check:providers-generated && pnpm run check:docs && pnpm run check:changes && pnpm run check:operator-ui && pnpm run check:clerk-sdk && pnpm run check:lint && pnpm run check:unused && pnpm run typecheck",
@@ -252,11 +256,7 @@
252
256
  "@fontsource-variable/jetbrains-mono": "^5.3.0",
253
257
  "@playwright/test": "^1.62.0",
254
258
  "@radix-ui/react-dialog": "^1.2.0",
255
- "@radix-ui/react-slot": "^1.4.0",
256
259
  "@radix-ui/react-tabs": "^1.1.22",
257
- "@tailwindcss/node": "^4.3.3",
258
- "@tailwindcss/oxide": "^4.3.3",
259
- "@tanstack/react-query": "^5.104.1",
260
260
  "@tanstack/react-router": "^1.170.41",
261
261
  "@types/node": "^22.0.0",
262
262
  "@types/react": "^19.3.0",
@@ -270,7 +270,6 @@
270
270
  "quickjs-emscripten": "^0.32.0",
271
271
  "react": "^19.3.0",
272
272
  "react-dom": "^19.3.0",
273
- "tailwindcss": "^4.3.3",
274
273
  "tsx": "^4.23.1",
275
274
  "typescript": "^5.9.3",
276
275
  "undici": "6.29.1",
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "@clerk/backend": "^3.12.0",
21
- "@zackbart/connecta": "0.35.0",
21
+ "@zackbart/connecta": "0.36.0",
22
22
  "quickjs-emscripten": "0.32.0",
23
23
  "undici": "6.29.1"
24
24
  },