@mcp-com-ai/plugin-capability-graph 0.0.0-stage → 1.2.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.
- package/LICENSE +92 -0
- package/README.md +443 -2
- package/dist/canonical.d.ts +9 -0
- package/dist/classifier.d.ts +11 -0
- package/dist/commands.d.ts +9 -0
- package/dist/compiler.d.ts +9 -0
- package/dist/evaluation.d.ts +24 -0
- package/dist/execution-digests.d.ts +7 -0
- package/dist/execution-envelope.d.ts +19 -0
- package/dist/execution-preflight.d.ts +38 -0
- package/dist/executor.d.ts +21 -0
- package/dist/extensions.d.ts +100 -0
- package/dist/fact-audit.d.ts +34 -0
- package/dist/fact-closure.d.ts +41 -0
- package/dist/graphml.d.ts +2 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +315 -0
- package/dist/json-schema.d.ts +6 -0
- package/dist/openapi-document.d.ts +9 -0
- package/dist/planner.d.ts +14 -0
- package/dist/planning-gates.d.ts +10 -0
- package/dist/response-outcomes.d.ts +6 -0
- package/dist/runtime.d.ts +15 -0
- package/dist/runtime.js +5 -0
- package/dist/triggers.d.ts +15 -0
- package/dist/visualization-api.d.ts +3 -0
- package/dist/visualization-api.js +163 -0
- package/dist/visualization-assets.d.ts +2 -0
- package/dist/visualization-flow-cards.d.ts +26 -0
- package/dist/visualization-renderer.d.ts +2 -0
- package/dist/visualization-shared.d.ts +7 -0
- package/dist/visualization-types.d.ts +343 -0
- package/dist/visualization.d.ts +3 -0
- package/package.json +66 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
La Rebelion Labs Community License (LRL-CL)
|
|
2
|
+
Version 1.0
|
|
3
|
+
Copyright (c) 2026 La Rebelion Labs
|
|
4
|
+
|
|
5
|
+
By accessing, downloading, using, or modifying this software, you agree to the terms of this License.
|
|
6
|
+
|
|
7
|
+
1. Definitions
|
|
8
|
+
|
|
9
|
+
"Software" means the source code, binaries, assets, documentation, configuration, workflows, examples, templates, and related materials distributed under this License.
|
|
10
|
+
|
|
11
|
+
"Licensor" means La Rebelion Labs and its contributors.
|
|
12
|
+
|
|
13
|
+
"User" means an individual or organization accessing or using the Software.
|
|
14
|
+
|
|
15
|
+
"Community Member" means a user with authorized access through La Rebelion Labs memberships, subscriptions, partnerships, or approved distribution channels.
|
|
16
|
+
|
|
17
|
+
2. Grant of Rights
|
|
18
|
+
|
|
19
|
+
Subject to the terms and restrictions of this License, Community Members are granted a limited, non-exclusive, non-transferable, revocable license to:
|
|
20
|
+
|
|
21
|
+
- Access and use the Software
|
|
22
|
+
- Modify the Software for internal or personal purposes
|
|
23
|
+
- Self-host the Software
|
|
24
|
+
- Learn from and experiment with the Software
|
|
25
|
+
- Build internal solutions using the Software
|
|
26
|
+
|
|
27
|
+
3. Restrictions
|
|
28
|
+
|
|
29
|
+
You may NOT, without prior written permission from the Licensor:
|
|
30
|
+
|
|
31
|
+
- Redistribute the Software
|
|
32
|
+
- Share the source code publicly or privately outside authorized Community Members
|
|
33
|
+
- Publish the Software to public repositories
|
|
34
|
+
- Sell, sublicense, rent, lease, or commercially distribute the Software
|
|
35
|
+
- Offer the Software as a hosted or managed service
|
|
36
|
+
- Create competing commercial products or services based substantially on the Software
|
|
37
|
+
- Remove or alter copyright notices, branding, or license text
|
|
38
|
+
- Circumvent access restrictions, licensing systems, or membership protections
|
|
39
|
+
|
|
40
|
+
4. Contributions
|
|
41
|
+
|
|
42
|
+
Unless otherwise agreed in writing, any contributions submitted to the Licensor may be used, modified, redistributed, or relicensed by the Licensor without obligation or compensation.
|
|
43
|
+
|
|
44
|
+
5. Ownership
|
|
45
|
+
|
|
46
|
+
The Software is licensed, not sold.
|
|
47
|
+
|
|
48
|
+
All intellectual property rights, title, and ownership remain exclusively with the Licensor.
|
|
49
|
+
|
|
50
|
+
6. Termination
|
|
51
|
+
|
|
52
|
+
This License terminates automatically if you violate any term of this License.
|
|
53
|
+
|
|
54
|
+
Upon termination, you must immediately stop using and distributing the Software and delete all copies in your possession.
|
|
55
|
+
|
|
56
|
+
7. No Warranty
|
|
57
|
+
|
|
58
|
+
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AVAILABILITY, OR PERFORMANCE.
|
|
59
|
+
|
|
60
|
+
8. No Liability
|
|
61
|
+
|
|
62
|
+
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSOR SHALL NOT BE LIABLE FOR ANY CLAIMS, DAMAGES, LOSSES, OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT, OR OTHERWISE, ARISING FROM OR RELATED TO THE SOFTWARE OR ITS USE.
|
|
63
|
+
|
|
64
|
+
9. Governing Terms
|
|
65
|
+
|
|
66
|
+
This License constitutes the complete agreement between the User and the Licensor regarding the Software.
|
|
67
|
+
|
|
68
|
+
The Licensor reserves the right to publish updated versions of this License for future releases of the Software.
|
|
69
|
+
|
|
70
|
+
Using the Software after receiving updated versions constitutes acceptance of the updated terms.
|
|
71
|
+
|
|
72
|
+
10. Contact
|
|
73
|
+
|
|
74
|
+
Licensing inquiries:
|
|
75
|
+
https://rebelion.la
|
|
76
|
+
|
|
77
|
+
Commercial licensing and enterprise partnerships:
|
|
78
|
+
https://mcp.com.ai
|
|
79
|
+
https://clawster.my
|
|
80
|
+
|
|
81
|
+
11. Production and Commercial Use Limitations
|
|
82
|
+
|
|
83
|
+
Use of the Software in production environments requires a commercial license if ANY of the following conditions apply:
|
|
84
|
+
|
|
85
|
+
- The organization has more than 25 employees
|
|
86
|
+
- The Software manages more than 10 active agents, runtimes, or orchestrated workloads
|
|
87
|
+
- The Software processes more than 100,000 monthly requests, executions, or workflows
|
|
88
|
+
- The organization generates more than $1,000,000 USD in annual revenue
|
|
89
|
+
- The Software is used as part of a commercial hosted or managed service
|
|
90
|
+
|
|
91
|
+
For commercial licensing inquiries:
|
|
92
|
+
https://rebelion.la/contact
|
package/README.md
CHANGED
|
@@ -1,3 +1,444 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@mcp-com-ai/plugin-capability-graph`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Public OSS compiler and CLI plugin for HAPI capability graphs.
|
|
4
|
+
|
|
5
|
+
The plugin exposes the OpenAPI compiler as a library, deterministic MCP tool
|
|
6
|
+
discovery, and offline graph commands. Runtime graph mode is opt-in and leaves
|
|
7
|
+
existing eager and deferred-search behavior unchanged when disabled.
|
|
8
|
+
|
|
9
|
+
The package has no Enterprise classifier or hosted AI dependencies.
|
|
10
|
+
|
|
11
|
+
## Compiler API
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import {
|
|
15
|
+
compileCapabilityGraph,
|
|
16
|
+
serializeCapabilityGraph,
|
|
17
|
+
} from "@mcp-com-ai/plugin-capability-graph";
|
|
18
|
+
|
|
19
|
+
const graph = await compileCapabilityGraph(openApiDocument, {
|
|
20
|
+
source: {
|
|
21
|
+
identifier: "crm-api",
|
|
22
|
+
canonicalUri: "https://api.example.com/openapi.json",
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const canonicalJson = serializeCapabilityGraph(graph);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`compileCapabilityGraph` accepts one OpenAPI 3.x object and returns a deeply
|
|
30
|
+
frozen `CapabilityGraphV1`. Invalid supported `x-hapi-*` extensions reject with
|
|
31
|
+
`CapabilityGraphCompilationError`, whose `diagnostics` identify the operation,
|
|
32
|
+
JSON pointer, and validation error.
|
|
33
|
+
|
|
34
|
+
Supported optional operation extensions:
|
|
35
|
+
|
|
36
|
+
- `x-hapi-capability`
|
|
37
|
+
- `x-hapi-intent`
|
|
38
|
+
- `x-hapi-effects`
|
|
39
|
+
- `x-hapi-prerequisites`
|
|
40
|
+
- `x-hapi-planning`
|
|
41
|
+
|
|
42
|
+
A response object may also declare `x-hapi-outcome`, described under
|
|
43
|
+
[Response outcomes](#response-outcomes). Webhook and callback operations may
|
|
44
|
+
declare `x-hapi-event` (see [Event triggers](#event-triggers)), and the
|
|
45
|
+
document root may declare `x-hapi-client-facts` (see
|
|
46
|
+
[Client facts](#client-facts)).
|
|
47
|
+
|
|
48
|
+
Example:
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
paths:
|
|
52
|
+
/orders/{orderId}/cancel:
|
|
53
|
+
post:
|
|
54
|
+
operationId: cancelOrder
|
|
55
|
+
x-hapi-capability: [orders/management, customer-support/orders]
|
|
56
|
+
x-hapi-intent:
|
|
57
|
+
use-when: [The customer asks to cancel an open order]
|
|
58
|
+
avoid-when: [The order has already shipped]
|
|
59
|
+
x-hapi-effects:
|
|
60
|
+
mode: write
|
|
61
|
+
side-effecting: true
|
|
62
|
+
destructive: true
|
|
63
|
+
requires-confirmation: true
|
|
64
|
+
x-hapi-prerequisites: [The order exists and is still cancellable]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Missing semantics are inferred deterministically and retain provenance. Schema
|
|
68
|
+
summaries preserve `$ref` values instead of expanding them, so recursive models
|
|
69
|
+
remain bounded. Equivalent path, tag, object-property, and `oneOf` ordering
|
|
70
|
+
produces the same operation identities and graph fingerprint.
|
|
71
|
+
|
|
72
|
+
## Runtime discovery
|
|
73
|
+
|
|
74
|
+
Enable deterministic graph-backed tool discovery for a native server:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
hapi serve --specs ./openapi.yaml --mcp --capability-graph
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The flag implies `--deferred-tool-search`. Cloudflare deployments expose the
|
|
81
|
+
same behavior through `hapi cloudflare deploy --capability-graph`, which sets
|
|
82
|
+
`HAPI_CAPABILITY_GRAPH=true`. The graph is compiled once during runtime
|
|
83
|
+
initialization, and malformed explicit `x-hapi-*` metadata fails startup.
|
|
84
|
+
|
|
85
|
+
## Offline commands
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
hapi graph compile ./openapi.yaml > graph.json
|
|
89
|
+
hapi graph compile --specs https://api.example.com/openapi.yaml --out graph.json
|
|
90
|
+
hapi graph inspect graph.json
|
|
91
|
+
hapi graph inspect ./openapi.yaml --format graphml > graph.graphml
|
|
92
|
+
hapi graph visualize graph.json --out capability-graph.html
|
|
93
|
+
hapi graph visualize ./openapi.yaml > capability-graph.html
|
|
94
|
+
hapi graph visualize graph.json --out plan.html \
|
|
95
|
+
--initial-fact patient.identity.verified \
|
|
96
|
+
--initial-fact slot.selected \
|
|
97
|
+
--goal-fact appointment.booked
|
|
98
|
+
hapi graph search graph.json "close the deal" --limit 5
|
|
99
|
+
hapi graph eval graph.json ./evaluation.json
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
All source-taking graph commands accept either a positional source or
|
|
103
|
+
`--specs <path-or-http(s)-url>`. Remote loads use bounded size, timeout, and
|
|
104
|
+
redirect handling. Supplying both selectors is rejected. `--url` is not
|
|
105
|
+
accepted because these commands compile and inspect documents without calling
|
|
106
|
+
an upstream API. Direct Arazzo documents remain owned by `hapi arazzo` and
|
|
107
|
+
`hapi serve --specs`; the graph compiler input is one OpenAPI document or a
|
|
108
|
+
canonical graph.
|
|
109
|
+
|
|
110
|
+
`compile` emits canonical, round-trippable JSON by default. `inspect` provides
|
|
111
|
+
a concise human summary or deterministic GraphML. `visualize` accepts canonical
|
|
112
|
+
JSON or compiles one OpenAPI document and emits byte-stable, self-contained
|
|
113
|
+
HTML. `search` uses the runtime deterministic classifier. `eval` exits non-zero
|
|
114
|
+
when any fixture expectation fails.
|
|
115
|
+
|
|
116
|
+
Canonical JSON is the lossless visualization input; GraphML is export-only and
|
|
117
|
+
cannot be read back by `visualize`. The HTML viewer is single-graph, local, and
|
|
118
|
+
read-only. It has no remote assets, network requests, cookies, browser storage,
|
|
119
|
+
service worker, API invocation, or execution control. The topology and local
|
|
120
|
+
text/filter results are inspection aids and do not imply authorization or
|
|
121
|
+
execution eligibility. Planning transitions, when present, appear in a
|
|
122
|
+
separate view. The Business State Flow deduplicates canonical predicate/value
|
|
123
|
+
facts and connects every prerequisite to its operation or workflow before
|
|
124
|
+
showing produced and removed facts. Facts are conditions; the planner's state
|
|
125
|
+
is the complete set of facts currently true, so this view is intentionally not
|
|
126
|
+
presented as a formal UML state machine. Compiler-generated
|
|
127
|
+
`operation.*.completed` facts are hidden by default and remain available with
|
|
128
|
+
the technical-fact toggle.
|
|
129
|
+
|
|
130
|
+
Supplying at least one `--goal-fact` embeds an exact Plan Trace produced by the
|
|
131
|
+
same deterministic planner and inputs as `graph simulate`. The trace shows the
|
|
132
|
+
initial state and every before/after fact set for planned, complete,
|
|
133
|
+
clarification-required, and unplannable outcomes. An unplannable result still
|
|
134
|
+
produces a successful HTML artifact; the outcome is displayed in the file.
|
|
135
|
+
Planning-only options without a goal are rejected. No planner or principal
|
|
136
|
+
data is embedded in the browser.
|
|
137
|
+
|
|
138
|
+
The same trace also drives a **Flow cards** view. It shows a start card with
|
|
139
|
+
the goal and known facts, one card per planner step in planner order, and an
|
|
140
|
+
outcome card. A step with an unsatisfied gate says "Wait for confirmation"
|
|
141
|
+
(or the gate kind) in text. Steps that do not depend on each other through
|
|
142
|
+
declared facts share a row. That is not a promise of parallel execution, and
|
|
143
|
+
every card keeps its planner step number. Open the artifact on this view with
|
|
144
|
+
`--initial-view flow-cards`:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
hapi graph visualize graph.json --out trip-flow.html \
|
|
148
|
+
--initial-fact traveller.identity.verified \
|
|
149
|
+
--goal-fact trip.booked \
|
|
150
|
+
--initial-view flow-cards
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Each operation card lists its required inputs: required parameters and
|
|
154
|
+
required body property names, never credentials. It says "Needs input" when no
|
|
155
|
+
earlier step in the plan has a planning-eligible OpenAPI Link to that
|
|
156
|
+
operation. Otherwise it names the link and step that may supply them. Compiled
|
|
157
|
+
graphs do not keep Link parameter mappings, so the card never claims which
|
|
158
|
+
input a link fills. These markers are advisory and do not change the plan,
|
|
159
|
+
its gates, or its outcome.
|
|
160
|
+
|
|
161
|
+
### Fact audit
|
|
162
|
+
|
|
163
|
+
`hapi graph audit` checks that every planning fact can be established and
|
|
164
|
+
every outcome can be reached:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
hapi graph audit graph.json --client-verified-fact traveller.identity.verified
|
|
168
|
+
hapi graph audit ./openapi.yaml --no-reachability --output json
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
It reports:
|
|
172
|
+
|
|
173
|
+
- **Orphan requirements.** A business fact some transition requires, that no
|
|
174
|
+
transition produces, and that is not declared with `--client-verified-fact`.
|
|
175
|
+
- **Client-verified facts.** Facts established outside the API, such as
|
|
176
|
+
verified identity, declared in the contract with `x-hapi-client-facts` or
|
|
177
|
+
passed with `--client-verified-fact`. Each shows its origin.
|
|
178
|
+
- **Outcomes.** Business facts produced and never required. These are the
|
|
179
|
+
candidate goals.
|
|
180
|
+
- **Response and event facts.** Facts produced by a declared response
|
|
181
|
+
outcome or signalled by a declared webhook or callback. They are not orphans,
|
|
182
|
+
and they are never planned.
|
|
183
|
+
- **Discovery-only operations.** Operations that no planning transition
|
|
184
|
+
targets.
|
|
185
|
+
- **Reachability.** Each outcome, or each `--goal-fact`, is planned from the
|
|
186
|
+
client-verified facts with every operation eligible and every
|
|
187
|
+
non-authorization gate treated as satisfied. This is a topology check. It
|
|
188
|
+
does not grant authorization or confirmation.
|
|
189
|
+
|
|
190
|
+
Compiler-generated `operation.*.completed` facts are excluded. The command
|
|
191
|
+
exits 0 when clean, 1 when an orphan or unreachable outcome is found, and 2
|
|
192
|
+
for usage, input, or compilation errors, so it can gate CI. `graph visualize`
|
|
193
|
+
accepts the same `--client-verified-fact` option and shows the static findings
|
|
194
|
+
as gap cards in the Flow cards view, without running the reachability sweep.
|
|
195
|
+
|
|
196
|
+
Generated HTML contains allowlisted graph summaries, authorization scheme
|
|
197
|
+
names/scopes, diagnostics, provenance, and planning facts. Handle it with the
|
|
198
|
+
same sensitivity as its source graph. The renderer limits input to 16 MiB,
|
|
199
|
+
5,000 nodes, 20,000 edges, 10,000 planning transitions, 10,000 unique planning
|
|
200
|
+
facts, 50,000 state relations, 1,000 trace steps, 2,000 diagnostics, and 32 MiB
|
|
201
|
+
of generated HTML. Unsupported versions, malformed references, or exceeded
|
|
202
|
+
limits fail before stdout or the atomically written `--out` file is committed.
|
|
203
|
+
|
|
204
|
+
The pure browser-safe API is available separately:
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
import {
|
|
208
|
+
projectCapabilityGraphVisualization,
|
|
209
|
+
renderCapabilityGraphVisualizationHtml,
|
|
210
|
+
} from "@mcp-com-ai/plugin-capability-graph/visualization";
|
|
211
|
+
|
|
212
|
+
const document = projectCapabilityGraphVisualization(graph);
|
|
213
|
+
const html = await renderCapabilityGraphVisualizationHtml(document);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## OSS and Enterprise boundary
|
|
217
|
+
|
|
218
|
+
This package owns graph compilation, inspection, exports, and deterministic
|
|
219
|
+
classification. It never loads a licensed classifier or AI SDK.
|
|
220
|
+
|
|
221
|
+
Probabilistic transition authoring is intentionally separate. A future
|
|
222
|
+
licensed `capability-graph-transition-assistant` may use Jev to score candidate
|
|
223
|
+
relationships, but suggestions cannot affect this viewer, the graph
|
|
224
|
+
fingerprint, or planning until a user accepts them into `x-hapi-planning` or
|
|
225
|
+
Arazzo and recompiles the contract.
|
|
226
|
+
|
|
227
|
+
The TypeSafe/Jev classifier is implemented in the separate private
|
|
228
|
+
`@mcp-com-ai/enterprise-plugin-capability-classifier` package. It registers an
|
|
229
|
+
alternate classifier through Core's versioned provider seam after checking the
|
|
230
|
+
`core.enterprise` or `capability.graph.ai` entitlement. Native managed
|
|
231
|
+
extensions and a private static Worker profile provide the licensed code; the
|
|
232
|
+
public npm package, standalone binary, Docker image, and Worker remain
|
|
233
|
+
deterministic-only.
|
|
234
|
+
|
|
235
|
+
Operators with the private extension explicitly opt in with both graph mode
|
|
236
|
+
and `--capability-classifier typesafe`. Omission remains deterministic.
|
|
237
|
+
|
|
238
|
+
## AOT planning contracts
|
|
239
|
+
|
|
240
|
+
The package compiles and plans over the closed `x-hapi-planning` v1 shape:
|
|
241
|
+
|
|
242
|
+
```yaml
|
|
243
|
+
x-hapi-planning:
|
|
244
|
+
requires:
|
|
245
|
+
- predicate: order.open
|
|
246
|
+
produces:
|
|
247
|
+
- predicate: order.approved
|
|
248
|
+
removes:
|
|
249
|
+
- predicate: order.open
|
|
250
|
+
cost: 1
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
`produces` is required and non-empty. Predicates are lowercase canonical names,
|
|
254
|
+
fact values must be JSON-safe, and cost must be finite and nonnegative. This
|
|
255
|
+
metadata, fully mapped OpenAPI Links, and supported validated Arazzo workflows
|
|
256
|
+
are the only transition sources. Missing planning metadata is never invented.
|
|
257
|
+
|
|
258
|
+
Simulate offline:
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
hapi graph simulate ./openapi.yaml \
|
|
262
|
+
--initial-fact order.open \
|
|
263
|
+
--goal-fact order.approved \
|
|
264
|
+
--satisfied-gate mutation-confirmation \
|
|
265
|
+
--output json
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
The planner uses finite nonnegative costs and bounded Dijkstra search. Defaults
|
|
269
|
+
are depth 12, 2,000 states, 1,000 frontier entries, and 100 expansions per
|
|
270
|
+
state; every bound has a CLI override. Outcomes are `planned`,
|
|
271
|
+
`clarification-required`, `complete`, or `unplannable`. Authorization removes
|
|
272
|
+
ineligible operations before search. Policy, risk, and confirmation gates are
|
|
273
|
+
reported explicitly and never hidden in path cost.
|
|
274
|
+
|
|
275
|
+
### Response outcomes
|
|
276
|
+
|
|
277
|
+
A non-success response can declare the facts it produces or removes:
|
|
278
|
+
|
|
279
|
+
```yaml
|
|
280
|
+
responses:
|
|
281
|
+
"409":
|
|
282
|
+
description: Hotel is unavailable
|
|
283
|
+
x-hapi-outcome:
|
|
284
|
+
produces: [{ predicate: hotel.unavailable }]
|
|
285
|
+
removes: [{ predicate: hotel.selected }]
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
`produces` and `removes` use the `x-hapi-planning` fact rules, and at least
|
|
289
|
+
one must be non-empty. The status key may be a code, an `NXX` range, or
|
|
290
|
+
`default`, but never a `2xx` status, because `x-hapi-planning` already models
|
|
291
|
+
success. The operation must have `x-hapi-planning`; otherwise the outcome is
|
|
292
|
+
ignored with an `outcome-without-planning` warning.
|
|
293
|
+
|
|
294
|
+
Outcomes are alternatives the client cannot choose, so the planner never plans
|
|
295
|
+
through one. They appear on each plan step as `outcomes`, including in the
|
|
296
|
+
bounded `capability_plan` result. A failed guarded execution step reports the
|
|
297
|
+
matching outcome as `declaredOutcome`, matching the exact status, then the
|
|
298
|
+
range, then `default`. The facts are reported and never applied to execution
|
|
299
|
+
state: the client verifies the response and re-plans. Flow cards show outcomes
|
|
300
|
+
as "Otherwise" lines, and `hapi graph audit` lists their facts as response
|
|
301
|
+
facts rather than orphans. Documents without outcomes keep their fingerprint.
|
|
302
|
+
|
|
303
|
+
### Event triggers
|
|
304
|
+
|
|
305
|
+
The compiler records OpenAPI 3.1 `webhooks` and operation `callbacks` as
|
|
306
|
+
descriptive `triggers` on the graph. A trigger's id is
|
|
307
|
+
`webhook:<name>:<method>` or `callback:<operationId>:<name>:<method>`. A
|
|
308
|
+
webhook or callback operation can declare the facts its event signals:
|
|
309
|
+
|
|
310
|
+
```yaml
|
|
311
|
+
webhooks:
|
|
312
|
+
orderPaid:
|
|
313
|
+
post:
|
|
314
|
+
summary: The payment provider confirmed payment
|
|
315
|
+
x-hapi-event:
|
|
316
|
+
produces: [{ predicate: order.paid }]
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
`produces` must be a non-empty canonical fact array. `x-hapi-event` on an
|
|
320
|
+
ordinary `paths` operation is ignored with an `event-on-path-operation`
|
|
321
|
+
warning, and an unresolvable webhook or callback reference is skipped with an
|
|
322
|
+
`unresolved-trigger` warning.
|
|
323
|
+
|
|
324
|
+
Triggers are descriptive only. HAPI never subscribes to, receives, or plans
|
|
325
|
+
through an event. A client that receives and verifies the event passes the
|
|
326
|
+
fact as verified initial state. Flow cards name a trigger on the start card
|
|
327
|
+
when it signals one of the plan's initial facts, and `hapi graph audit` lists
|
|
328
|
+
event-signalled facts as event facts instead of orphans. Documents without
|
|
329
|
+
webhooks or callbacks keep their fingerprint. Arazzo AsyncAPI steps are not
|
|
330
|
+
supported yet.
|
|
331
|
+
|
|
332
|
+
### Client facts
|
|
333
|
+
|
|
334
|
+
A document can declare the facts a client establishes outside the API:
|
|
335
|
+
|
|
336
|
+
```yaml
|
|
337
|
+
x-hapi-client-facts:
|
|
338
|
+
- predicate: traveller.identity.verified
|
|
339
|
+
description: The client verified the traveller's identity.
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Entries use the planning fact rules plus an optional non-empty `description`.
|
|
343
|
+
A declared fact that no transition requires compiles with an
|
|
344
|
+
`unused-client-fact` warning. The graph keeps them as `clientFacts`.
|
|
345
|
+
|
|
346
|
+
`hapi graph audit` and `graph visualize` treat declared facts like
|
|
347
|
+
`--client-verified-fact` values and report each fact's origin as `contract`,
|
|
348
|
+
`option`, or both. `capability_context` marks matching requirement cards with
|
|
349
|
+
`clientEstablished: true` so an MCP client knows it must verify them. The
|
|
350
|
+
declaration never makes a fact true: `capability_plan` still accepts only facts
|
|
351
|
+
the client verified.
|
|
352
|
+
|
|
353
|
+
Expose MCP planning only with the second explicit opt-in:
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
hapi serve --specs ./openapi.yaml --mcp \
|
|
357
|
+
--capability-graph --capability-planning
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
For Workers, deploy with both `--capability-graph --capability-planning`, or set
|
|
361
|
+
`HAPI_CAPABILITY_GRAPH=true` and `HAPI_CAPABILITY_PLANNING=true`. The
|
|
362
|
+
`capability_plan` tool accepts bounded initial/goal facts, satisfied gate codes,
|
|
363
|
+
and bounds. It returns an allowlisted result with transition identities, costs,
|
|
364
|
+
gates, provenance, digests, and diagnostics.
|
|
365
|
+
|
|
366
|
+
The same explicit planning opt-in also exposes `capability_context`. Call it
|
|
367
|
+
with a natural-language request before planning to receive bounded,
|
|
368
|
+
authorization-filtered candidate tools, declared goal facts, fact
|
|
369
|
+
relationships, gates, and transition provenance. Its facts are guidance, not
|
|
370
|
+
asserted state: select a goal, supply only verified facts to
|
|
371
|
+
`capability_plan`, collect any clarification, then re-plan after a safe tool
|
|
372
|
+
result or human choice. Context neither calls an API nor stores state, asks a
|
|
373
|
+
user, executes a plan, or grants authority. Compiler-owned
|
|
374
|
+
`operation.*.completed` facts are hidden unless explicitly requested.
|
|
375
|
+
|
|
376
|
+
### Development tracing
|
|
377
|
+
|
|
378
|
+
For a local demonstration, add `--dev --capability-trace` to graph-enabled
|
|
379
|
+
serve. HAPI emits bounded `[HCG_TRACE]` records for discovery, context,
|
|
380
|
+
planning, graph-backed operation calls, and guarded execution. The records
|
|
381
|
+
show declared transition relationships, observed direct calls, and validated
|
|
382
|
+
guarded progression distinctly; they never log query text, fact values,
|
|
383
|
+
arguments, responses, credentials, or patient data. Trace mode is opt-in and
|
|
384
|
+
rejected outside explicit development mode.
|
|
385
|
+
|
|
386
|
+
Planning never invokes an API, the OpenAPI operation invoker, or the Arazzo
|
|
387
|
+
executor. It does not return credentials, HTTP requests/responses, raw graph
|
|
388
|
+
records, or runtime context.
|
|
389
|
+
|
|
390
|
+
## Guarded execution
|
|
391
|
+
|
|
392
|
+
Guarded execution is public OSS and requires all three explicit options:
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
hapi serve --specs ./openapi.yaml --mcp \
|
|
396
|
+
--capability-graph --capability-planning \
|
|
397
|
+
--runtime-authority guarded
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Workers use `HAPI_CAPABILITY_GRAPH=true`, `HAPI_CAPABILITY_PLANNING=true`, and
|
|
401
|
+
`HAPI_RUNTIME_AUTHORITY=guarded`. The default `decision` authority continues to
|
|
402
|
+
offer discovery and optional planning but never registers `capability_execute`.
|
|
403
|
+
|
|
404
|
+
The executor accepts only an exact canonical plan. It recomputes the plan and
|
|
405
|
+
binds confirmations to the graph fingerprint, plan digest, server principal,
|
|
406
|
+
and argument-digested mutation set. Confirmation receipts must be issued by a
|
|
407
|
+
trusted provider registered through Core's versioned verifier seam; this plugin
|
|
408
|
+
does not expose a confirmation-issuing tool.
|
|
409
|
+
|
|
410
|
+
Register a trusted verifier during startup before accepting mutation plans:
|
|
411
|
+
|
|
412
|
+
```ts
|
|
413
|
+
import { registerCapabilityExecutionConfirmationVerifier } from "@mcp-com-ai/core/capability-execution";
|
|
414
|
+
|
|
415
|
+
registerCapabilityExecutionConfirmationVerifier({
|
|
416
|
+
version: "1",
|
|
417
|
+
id: "deployment-confirmation-service",
|
|
418
|
+
verify: (receipt, binding, signal) =>
|
|
419
|
+
confirmationService.verify(receipt, binding, signal),
|
|
420
|
+
});
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
Before every attempt the runtime rechecks confirmation, authorization, policy,
|
|
424
|
+
current facts, arguments/body variant, and retained schemas. OpenAPI operations
|
|
425
|
+
run through the existing invoker; supported Arazzo workflows run as one atomic
|
|
426
|
+
outer step under both workflow and guarded limits. Automatic retries apply only
|
|
427
|
+
to read-only or explicitly idempotent operations and normalized transient
|
|
428
|
+
failures. Results are `completed`, `partial`, `rejected`, `failed`, or
|
|
429
|
+
`cancelled`; ambiguous upstream timeouts/network failures are recorded as
|
|
430
|
+
`indeterminate` steps and stop the sequence.
|
|
431
|
+
|
|
432
|
+
Deployment limits may reduce, but never exceed, the compiled ceilings: 50 plan
|
|
433
|
+
steps, five minutes total, 60 seconds per step, 100 total attempts, three
|
|
434
|
+
retries per eligible step, 10 MiB per response, 100 result records, and 500
|
|
435
|
+
event records. Public defaults are deliberately lower (12 steps, 60 seconds
|
|
436
|
+
total, 15 seconds per step, 16 attempts, one retry, 1 MiB responses, 50 result
|
|
437
|
+
records, and 100 events).
|
|
438
|
+
|
|
439
|
+
MCP summaries and structured events are allowlisted: raw arguments, bodies,
|
|
440
|
+
headers/cookies, URL credentials/query values, principal claims, confirmation
|
|
441
|
+
proofs, fact values, and stacks are excluded. The runtime does not compensate,
|
|
442
|
+
resume, persist state, or guarantee exactly-once execution. Receipts are
|
|
443
|
+
short-lived and context-bound, but durable single-use replay enforcement belongs
|
|
444
|
+
to the confirmation provider or a future persistent receipt store.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CapabilityGraphJsonValue, CapabilityGraphV1 } from "@mcp-com-ai/core";
|
|
2
|
+
export declare function canonicalizeJson(value: unknown, options?: {
|
|
3
|
+
schema?: boolean;
|
|
4
|
+
}): CapabilityGraphJsonValue;
|
|
5
|
+
export declare function canonicalStringify(value: unknown): string;
|
|
6
|
+
export declare function canonicalSchemaStringify(value: unknown): string;
|
|
7
|
+
export declare function sha256(value: string): Promise<string>;
|
|
8
|
+
export declare function hashCanonicalSchema(value: unknown): Promise<string>;
|
|
9
|
+
export declare function serializeCapabilityGraph(graph: CapabilityGraphV1): string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CapabilityGraphClassifierProvider, CapabilityGraphClassifierRequest, CapabilityGraphClassifierResult, CapabilityGraphOperationNode } from '@mcp-com-ai/core';
|
|
2
|
+
export interface CapabilityGraphPrincipalContext {
|
|
3
|
+
readonly scopes?: readonly string[];
|
|
4
|
+
readonly schemes?: Readonly<Record<string, readonly string[]>>;
|
|
5
|
+
readonly authorizedOperationIds?: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
export declare class DeterministicCapabilityGraphClassifier implements CapabilityGraphClassifierProvider {
|
|
8
|
+
readonly id = "deterministic-v1";
|
|
9
|
+
classify(request: CapabilityGraphClassifierRequest): Promise<CapabilityGraphClassifierResult>;
|
|
10
|
+
}
|
|
11
|
+
export declare function isOperationAuthorized(operation: CapabilityGraphOperationNode, principal: unknown): boolean;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type CliCommand } from "@mcp-com-ai/plugin-sdk";
|
|
2
|
+
export declare const graphCompileCommand: CliCommand;
|
|
3
|
+
export declare const graphInspectCommand: CliCommand;
|
|
4
|
+
export declare const graphVisualizeCommand: CliCommand;
|
|
5
|
+
export declare const graphSearchCommand: CliCommand;
|
|
6
|
+
export declare const graphEvalCommand: CliCommand;
|
|
7
|
+
export declare const graphSimulateCommand: CliCommand;
|
|
8
|
+
export declare const graphAuditCommand: CliCommand;
|
|
9
|
+
export declare const graphRootCommand: CliCommand;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CapabilityGraphDiagnostic, CapabilityGraphSource, CapabilityGraphV1 } from "@mcp-com-ai/core";
|
|
2
|
+
export interface CompileCapabilityGraphOptions {
|
|
3
|
+
readonly source?: Partial<CapabilityGraphSource>;
|
|
4
|
+
}
|
|
5
|
+
export declare class CapabilityGraphCompilationError extends Error {
|
|
6
|
+
readonly diagnostics: readonly CapabilityGraphDiagnostic[];
|
|
7
|
+
constructor(diagnostics: readonly CapabilityGraphDiagnostic[]);
|
|
8
|
+
}
|
|
9
|
+
export declare function compileCapabilityGraph(input: unknown, options?: CompileCapabilityGraphOptions): Promise<CapabilityGraphV1>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { CapabilityGraphClassifierProvider, CapabilityGraphClassifierResult, CapabilityGraphV1 } from '@mcp-com-ai/core';
|
|
2
|
+
export type CapabilityGraphEvaluationStatus = 'matched' | 'ambiguous' | 'clarification-required' | 'no-match';
|
|
3
|
+
export interface CapabilityGraphEvaluationCase {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly query: string;
|
|
6
|
+
readonly expectedOperationIds?: readonly string[];
|
|
7
|
+
readonly excludedOperationIds?: readonly string[];
|
|
8
|
+
readonly expectedStatus?: CapabilityGraphEvaluationStatus;
|
|
9
|
+
readonly principalScopes?: readonly string[];
|
|
10
|
+
}
|
|
11
|
+
export interface CapabilityGraphEvaluationFixture {
|
|
12
|
+
readonly schemaVersion: '1';
|
|
13
|
+
readonly cases: readonly CapabilityGraphEvaluationCase[];
|
|
14
|
+
}
|
|
15
|
+
export interface CapabilityGraphEvaluationResult {
|
|
16
|
+
readonly id: string;
|
|
17
|
+
readonly passed: boolean;
|
|
18
|
+
readonly status: CapabilityGraphEvaluationStatus;
|
|
19
|
+
readonly operationIds: readonly string[];
|
|
20
|
+
readonly diagnostics: CapabilityGraphClassifierResult['diagnostics'];
|
|
21
|
+
readonly failures: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
export declare function evaluateCapabilityGraph(graph: CapabilityGraphV1, fixture: CapabilityGraphEvaluationFixture, classifier: CapabilityGraphClassifierProvider): Promise<readonly CapabilityGraphEvaluationResult[]>;
|
|
24
|
+
export declare function classifyEvaluationStatus(graph: CapabilityGraphV1, query: string, result: CapabilityGraphClassifierResult): CapabilityGraphEvaluationStatus;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CapabilityExecutionConfirmationBindingV1, CapabilityExecutionMutationV1, CapabilityExecutionRequestV1, CapabilityGraphJsonValue, CapabilityGraphPlanningStepV1, CapabilityGraphV1 } from "@mcp-com-ai/core";
|
|
2
|
+
export declare function capabilityExecutionPrincipalDigest(principal: unknown): Promise<string>;
|
|
3
|
+
export declare function capabilityExecutionArgumentDigest(args: Readonly<Record<string, CapabilityGraphJsonValue>>): Promise<string>;
|
|
4
|
+
export declare function capabilityExecutionMutationSet(graph: CapabilityGraphV1, steps: readonly CapabilityGraphPlanningStepV1[], stepArguments: CapabilityExecutionRequestV1["stepArguments"]): Promise<readonly CapabilityExecutionMutationV1[]>;
|
|
5
|
+
export declare function capabilityExecutionMutationSetDigest(mutations: readonly CapabilityExecutionMutationV1[]): Promise<string>;
|
|
6
|
+
export declare function capabilityExecutionConfirmationBinding(request: CapabilityExecutionRequestV1, graph: CapabilityGraphV1): Promise<CapabilityExecutionConfirmationBindingV1>;
|
|
7
|
+
export declare function capabilityExecutionEnvelopeDigest(request: CapabilityExecutionRequestV1): Promise<string>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CapabilityExecutionConfirmationBindingV1, CapabilityExecutionDiagnosticV1, CapabilityExecutionMutationV1, CapabilityExecutionRequestV1, CapabilityGraphPlannerV1, CapabilityGraphPlanningTransitionV1, CapabilityGraphV1 } from "@mcp-com-ai/core";
|
|
2
|
+
export interface CapabilityExecutionConfirmationPolicy {
|
|
3
|
+
readonly now?: () => number;
|
|
4
|
+
readonly maxReceiptLifetimeMs?: number;
|
|
5
|
+
readonly clockSkewMs?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ValidatedCapabilityExecutionEnvelope {
|
|
8
|
+
readonly ok: boolean;
|
|
9
|
+
readonly executionDigest?: string;
|
|
10
|
+
readonly binding?: CapabilityExecutionConfirmationBindingV1;
|
|
11
|
+
readonly mutations: readonly CapabilityExecutionMutationV1[];
|
|
12
|
+
readonly transitions: readonly CapabilityGraphPlanningTransitionV1[];
|
|
13
|
+
readonly diagnostics: readonly CapabilityExecutionDiagnosticV1[];
|
|
14
|
+
}
|
|
15
|
+
export declare function validateCapabilityExecutionEnvelope(graph: CapabilityGraphV1, request: CapabilityExecutionRequestV1, options?: {
|
|
16
|
+
readonly planner?: CapabilityGraphPlannerV1;
|
|
17
|
+
readonly confirmation?: CapabilityExecutionConfirmationPolicy;
|
|
18
|
+
}): Promise<ValidatedCapabilityExecutionEnvelope>;
|
|
19
|
+
export declare function validateCapabilityExecutionConfirmations(request: CapabilityExecutionRequestV1, mutations: readonly CapabilityExecutionMutationV1[], binding: CapabilityExecutionConfirmationBindingV1, policy?: CapabilityExecutionConfirmationPolicy): Promise<readonly CapabilityExecutionDiagnosticV1[]>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { CapabilityExecutionDiagnosticV1, CapabilityExecutionRequestV1, CapabilityExecutionTargetDescriptorV1, CapabilityGraphOperationNode, CapabilityGraphPlanningTransitionV1, CapabilityGraphV1, PlanningFactV1 } from "@mcp-com-ai/core";
|
|
2
|
+
import { type CapabilityExecutionConfirmationPolicy, type ValidatedCapabilityExecutionEnvelope } from "./execution-envelope";
|
|
3
|
+
export interface CapabilityExecutionPreflightDependencies {
|
|
4
|
+
readonly descriptors: ReadonlyMap<string, CapabilityExecutionTargetDescriptorV1>;
|
|
5
|
+
readonly now?: () => number;
|
|
6
|
+
readonly deadlineEpochMs?: number;
|
|
7
|
+
readonly confirmation?: CapabilityExecutionConfirmationPolicy;
|
|
8
|
+
readonly authorize?: (context: {
|
|
9
|
+
readonly transition: CapabilityGraphPlanningTransitionV1;
|
|
10
|
+
readonly operation?: CapabilityGraphOperationNode;
|
|
11
|
+
readonly principal: unknown;
|
|
12
|
+
}) => Promise<boolean> | boolean;
|
|
13
|
+
readonly evaluatePolicy?: (context: {
|
|
14
|
+
readonly transition: CapabilityGraphPlanningTransitionV1;
|
|
15
|
+
readonly principal: unknown;
|
|
16
|
+
readonly currentFacts: readonly PlanningFactV1[];
|
|
17
|
+
}) => Promise<boolean> | boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface CapabilityExecutionPreflightResult {
|
|
20
|
+
readonly ok: boolean;
|
|
21
|
+
readonly envelope: ValidatedCapabilityExecutionEnvelope;
|
|
22
|
+
readonly transition?: CapabilityGraphPlanningTransitionV1;
|
|
23
|
+
readonly descriptor?: CapabilityExecutionTargetDescriptorV1;
|
|
24
|
+
readonly diagnostics: readonly CapabilityExecutionDiagnosticV1[];
|
|
25
|
+
}
|
|
26
|
+
export interface CapabilityExecutionInvocationResult {
|
|
27
|
+
readonly status?: number;
|
|
28
|
+
readonly mediaType?: string;
|
|
29
|
+
readonly body?: unknown;
|
|
30
|
+
}
|
|
31
|
+
export interface CapabilityExecutionStateResult {
|
|
32
|
+
readonly ok: boolean;
|
|
33
|
+
readonly facts: readonly PlanningFactV1[];
|
|
34
|
+
readonly stateDigest?: string;
|
|
35
|
+
readonly diagnostics: readonly CapabilityExecutionDiagnosticV1[];
|
|
36
|
+
}
|
|
37
|
+
export declare function preflightCapabilityExecutionStep(graph: CapabilityGraphV1, request: CapabilityExecutionRequestV1, stepIndex: number, currentFacts: readonly PlanningFactV1[], dependencies: CapabilityExecutionPreflightDependencies): Promise<CapabilityExecutionPreflightResult>;
|
|
38
|
+
export declare function validateCapabilityExecutionResult(preflight: CapabilityExecutionPreflightResult, currentFacts: readonly PlanningFactV1[], result: CapabilityExecutionInvocationResult): Promise<CapabilityExecutionStateResult>;
|