@bighub/bighub-mcp 0.1.4 → 0.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/README.md CHANGED
@@ -1,144 +1,156 @@
1
- # @bighub/bighub-mcp
2
-
3
- > MCP server for governing AI agent actions with the BIGHUB control plane.
4
-
5
- Use BIGHUB governance from any [Model Context Protocol](https://modelcontextprotocol.io) client. This server exposes MCP tools that validate, bound, and govern AI agent execution by calling the BIGHUB API — actions, rules, approvals, kill switch, events, API keys, webhooks, auth, and Future Memory.
6
-
7
- ```text
8
- MCP Client (Claude, Cursor, etc.)
9
-
10
- @bighub/bighub-mcp (stdio)
11
-
12
- BIGHUB Control Plane API (api.bighub.io)
13
-
14
- execute / block / require approval
15
- ```
16
-
17
- ---
18
-
19
- ## Install
20
-
21
- ```bash
22
- npm install @bighub/bighub-mcp
23
- ```
24
-
25
- Requires Node.js 18+.
26
-
27
- ---
28
-
29
- ## Quickstart
30
-
31
- 1. Set your API key:
32
-
33
- ```bash
34
- export BIGHUB_API_KEY=your_api_key
35
- ```
36
-
37
- 2. Run the server in stdio mode:
38
-
39
- ```bash
40
- npx @bighub/bighub-mcp
41
- ```
42
-
43
- The server exposes MCP tools over stdio. Connect it to any MCP-compatible client (Claude Desktop, Cursor, etc.) by adding it to your MCP configuration:
44
-
45
- ```json
46
- {
47
- "mcpServers": {
48
- "bighub": {
49
- "command": "npx",
50
- "args": ["@bighub/bighub-mcp"],
51
- "env": {
52
- "BIGHUB_API_KEY": "your_api_key"
53
- }
54
- }
55
- }
56
- }
57
- ```
58
-
59
- ---
60
-
61
- ## What BIGHUB does
62
-
63
- BIGHUB is the execution control plane for AI agents in production. It sits between agent reasoning and real-world execution, validating every action against enforceable policies before it reaches production systems.
64
-
65
- | Without BIGHUB | With BIGHUB |
66
- |---|---|
67
- | Agent acts directly in production | Every action validated before execution |
68
- | Guardrails are suggestions | Policies are enforced at runtime |
69
- | Logging shows what happened | Decisions are blocked *before* they happen |
70
- | Autonomy grows, exposure grows | Bounded autonomy, controlled risk |
71
-
72
- ---
73
-
74
- ## Environment variables
75
-
76
- | Variable | Required | Default | Description |
77
- |----------|----------|---------|-------------|
78
- | `BIGHUB_API_KEY` | Yes* | — | API key authentication (`X-API-Key` header) |
79
- | `BIGHUB_BEARER_TOKEN` | No | — | Alternative auth (`Authorization: Bearer`) |
80
- | `BIGHUB_BASE_URL` | No | `https://api.bighub.io` | API base URL |
81
- | `BIGHUB_TIMEOUT_MS` | No | `15000` | HTTP request timeout in milliseconds |
82
- | `BIGHUB_MAX_RETRIES` | No | `2` | Retry count on transient failures (429/5xx) |
83
- | `BIGHUB_ALLOW_INSECURE_HTTP` | No | — | Allow HTTP for localhost/private host testing |
84
-
85
- *One of `BIGHUB_API_KEY` or `BIGHUB_BEARER_TOKEN` is required.
86
-
87
- ---
88
-
89
- ## Tool coverage
90
-
91
- 35+ MCP tools mapping one-to-one to BIGHUB API endpoints:
92
-
93
- | Domain | Tools | Description |
94
- |--------|-------|-------------|
95
- | **Actions** | submit, submit_v2, dry_run, status, verify, stats, dashboard_summary | Validate and govern agent actions before execution. |
96
- | **Future Memory** | ingest, context, refresh_aggregates, recommendations | Ingest execution events, query learned context, surface policy recommendations. |
97
- | **Rules** | create, list, get, update, delete, pause, resume, validate, dry_run, versions, domains, apply_patch, purge_idempotency | Define and manage execution policies. |
98
- | **Approvals** | list, resolve | Human-in-the-loop approval workflows. |
99
- | **Kill switch** | status, activate, deactivate | Emergency stop for all agent execution. |
100
- | **Events** | list, stats | Audit trail for governed decisions. |
101
- | **API keys** | create, list, delete, rotate, validate, scopes | Manage authentication credentials. |
102
- | **Webhooks** | create, list, get, update, delete, deliveries, test, list_events, verify_signature, replay | Export governed events to external systems. |
103
- | **Auth** | signup, login, refresh, logout | Account and session management. |
104
- | **Fallback** | `bighub_http_request` | Generic tool for any BIGHUB endpoint not yet wrapped. |
105
-
106
- ---
107
-
108
- ## Reliability
109
-
110
- - Retries with exponential backoff and jitter for transient errors (429, 5xx, network)
111
- - Configurable timeout per request
112
- - Structured error metadata preserved from API responses
113
- - HTTPS enforced by default (override for local testing only)
114
-
115
- ---
116
-
117
- ## Local development
118
-
119
- ```bash
120
- git clone https://github.com/bighub-io/bighub.git
121
- cd bighub/servers/mcp
122
- npm install
123
- npm run test # run tests with vitest
124
- npm run check # typecheck with tsc --noEmit
125
- npm run build # compile to dist/
126
- npm run start # run compiled server
127
- npm run dev # run with tsx (auto-reload)
128
- ```
129
-
130
- ---
131
-
132
- ## Links
133
-
134
- - [bighub.io](https://bighub.io)
135
- - [GitHub — bighub-io/bighub](https://github.com/bighub-io/bighub)
136
- - [npm @bighub/bighub-mcp](https://www.npmjs.com/package/@bighub/bighub-mcp)
137
- - [PyPI — bighub (Python SDK)](https://pypi.org/project/bighub/)
138
- - [PyPI — bighub-openai](https://pypi.org/project/bighub-openai/)
139
-
140
- ---
141
-
142
- ## License
143
-
144
- MIT
1
+ # @bighub/bighub-mcp
2
+
3
+ > MCP server for decision learning on agent actions.
4
+
5
+ Use BIGHUB from any [Model Context Protocol](https://modelcontextprotocol.io) client to evaluate agent actions, report real outcomes, retrieve similar past cases, and improve future decisions over time.
6
+
7
+ ```text
8
+ MCP client
9
+
10
+ @bighub/bighub-mcp
11
+
12
+ BIGHUB API
13
+
14
+ evaluate -> execute -> report outcome -> learn
15
+ ```
16
+
17
+ ---
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ npm install @bighub/bighub-mcp
23
+ ```
24
+
25
+ Requires Node.js 18+.
26
+
27
+ ---
28
+
29
+ ## Quickstart
30
+
31
+ Set your API key:
32
+
33
+ ```bash
34
+ export BIGHUB_API_KEY=your_api_key
35
+ ```
36
+
37
+ Run the server in stdio mode:
38
+
39
+ ```bash
40
+ npx @bighub/bighub-mcp
41
+ ```
42
+
43
+ Add it to your MCP client configuration:
44
+
45
+ ```json
46
+ {
47
+ "mcpServers": {
48
+ "bighub": {
49
+ "command": "npx",
50
+ "args": ["@bighub/bighub-mcp"],
51
+ "env": {
52
+ "BIGHUB_API_KEY": "your_api_key"
53
+ }
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ Works with MCP-compatible clients such as Claude Desktop and Cursor.
60
+
61
+ ---
62
+
63
+ ## Core MCP Tools
64
+
65
+ Most teams start with the first three tools (the core loop):
66
+
67
+ | Tool | Purpose |
68
+ |---|---|
69
+ | `bighub_actions_submit` | Submit an action for evaluation before execution |
70
+ | `bighub_outcomes_report` | Report what actually happened |
71
+ | `bighub_precedents_query` | Retrieve similar past cases |
72
+ | `bighub_calibration_report` | Compare prediction vs reality |
73
+ | `bighub_insights_advise` | Retrieve learned guidance for the next action |
74
+
75
+ `bighub_actions_submit_v2` is available as an advanced action submission endpoint.
76
+
77
+ ---
78
+
79
+ ## Typical MCP Loop
80
+
81
+ 1. Evaluate the action
82
+ 2. Execute it in your runtime
83
+ 3. Report the real outcome
84
+ 4. Retrieve similar past cases
85
+ 5. Compare prediction vs reality
86
+ 6. Use learned guidance on the next action
87
+
88
+ Typical tool flow:
89
+
90
+ ```text
91
+ bighub_actions_submit
92
+ -> agent runtime executes action
93
+ -> bighub_outcomes_report
94
+ -> bighub_precedents_query
95
+ -> bighub_calibration_report
96
+ -> bighub_insights_advise
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Environment Variables
102
+
103
+ | Variable | Required | Default | Description |
104
+ |---|---|---|---|
105
+ | `BIGHUB_API_KEY` | Yes* | - | API key auth |
106
+ | `BIGHUB_BEARER_TOKEN` | No | - | Alternative bearer auth |
107
+ | `BIGHUB_BASE_URL` | No | `https://api.bighub.io` | API base URL |
108
+ | `BIGHUB_TIMEOUT_MS` | No | `15000` | Request timeout |
109
+ | `BIGHUB_MAX_RETRIES` | No | `2` | Retries on transient failures |
110
+ | `BIGHUB_ALLOW_INSECURE_HTTP` | No | - | Allow HTTP for local/private testing |
111
+
112
+ \* One of `BIGHUB_API_KEY` or `BIGHUB_BEARER_TOKEN` is required.
113
+
114
+ Some management tools (for example API key and webhook administration) require user JWT auth and should be used with `BIGHUB_BEARER_TOKEN`.
115
+
116
+ ---
117
+
118
+ ## Free BETA
119
+
120
+ Current Free BETA limits:
121
+
122
+ - 3 agents
123
+ - 2,500 actions / month
124
+ - 30 days history
125
+ - 1 environment
126
+
127
+ ---
128
+
129
+ ## Local Development
130
+
131
+ ```bash
132
+ git clone https://github.com/bighub-io/bighub.git
133
+ cd bighub/servers/mcp
134
+ npm install
135
+ npm run test
136
+ npm run check
137
+ npm run build
138
+ npm run start
139
+ npm run dev
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Links
145
+
146
+ - [bighub.io](https://bighub.io)
147
+ - [GitHub - bighub-io/bighub](https://github.com/bighub-io/bighub)
148
+ - [npm - @bighub/bighub-mcp](https://www.npmjs.com/package/@bighub/bighub-mcp)
149
+ - [PyPI - bighub (Python SDK)](https://pypi.org/project/bighub/)
150
+ - [PyPI - bighub-openai](https://pypi.org/project/bighub-openai/)
151
+
152
+ ---
153
+
154
+ ## License
155
+
156
+ MIT
package/dist/index.js CHANGED
@@ -25,11 +25,11 @@ async function main() {
25
25
  bearerToken,
26
26
  timeoutMs: parseNumberEnv("BIGHUB_TIMEOUT_MS", 15000),
27
27
  maxRetries: parseNumberEnv("BIGHUB_MAX_RETRIES", 2),
28
- userAgent: "bighub-mcp/0.1.0",
28
+ userAgent: "bighub-mcp/0.2.0",
29
29
  });
30
30
  const server = new McpServer({
31
31
  name: "bighub-mcp",
32
- version: "0.1.0",
32
+ version: "0.2.0",
33
33
  });
34
34
  registerBighubTools(server, client);
35
35
  const transport = new StdioServerTransport();
@@ -37,7 +37,7 @@ export function registerBighubTools(server, client) {
37
37
  idempotencyKey: idempotency_key,
38
38
  })));
39
39
  server.registerTool("bighub_actions_submit", {
40
- description: "Validate an action via /actions/submit.",
40
+ description: "Evaluate an action via /actions/submit.",
41
41
  outputSchema: AnyOutputSchema,
42
42
  inputSchema: {
43
43
  action: z.string(),
@@ -45,17 +45,18 @@ export function registerBighubTools(server, client) {
45
45
  value: z.number().optional(),
46
46
  target: z.string().optional(),
47
47
  domain: z.string().optional(),
48
+ context: JsonObjectSchema.optional(),
48
49
  metadata: JsonObjectSchema.optional(),
49
50
  idempotency_key: z.string().optional(),
50
51
  },
51
- }, async ({ action, actor, value, target, domain, metadata, idempotency_key }) => toResult(await client.request({
52
+ }, async ({ action, actor, value, target, domain, context, metadata, idempotency_key }) => toResult(await client.request({
52
53
  method: "POST",
53
54
  path: "/actions/submit",
54
- body: cleanObject({ action, actor, value, target, domain, metadata }),
55
+ body: cleanObject({ action, actor, value, target, domain, context: context ?? metadata }),
55
56
  idempotencyKey: idempotency_key,
56
57
  })));
57
58
  server.registerTool("bighub_actions_submit_v2", {
58
- description: "Validate an action with pro decision intelligence via /actions/submit/v2.",
59
+ description: "Evaluate an action via /actions/submit/v2 (advanced mode).",
59
60
  outputSchema: AnyOutputSchema,
60
61
  inputSchema: {
61
62
  payload: JsonObjectSchema,
@@ -68,7 +69,7 @@ export function registerBighubTools(server, client) {
68
69
  idempotencyKey: idempotency_key,
69
70
  })));
70
71
  server.registerTool("bighub_actions_dry_run", {
71
- description: "Run a non-persistent action validation via /actions/submit/dry-run.",
72
+ description: "Dry-run action evaluation (non-persistent) via /actions/submit/dry-run.",
72
73
  inputSchema: {
73
74
  payload: JsonObjectSchema,
74
75
  idempotency_key: z.string().optional(),
@@ -80,7 +81,7 @@ export function registerBighubTools(server, client) {
80
81
  idempotencyKey: idempotency_key,
81
82
  })));
82
83
  server.registerTool("bighub_actions_verify_validation", {
83
- description: "Verify a previous validation by validation_id.",
84
+ description: "Verify a previous evaluation by validation_id.",
84
85
  inputSchema: { validation_id: z.string() },
85
86
  }, async ({ validation_id }) => toResult(await client.request({
86
87
  method: "GET",
@@ -99,7 +100,7 @@ export function registerBighubTools(server, client) {
99
100
  inputSchema: {},
100
101
  }, async () => toResult(await client.request({ method: "GET", path: "/actions/status" })));
101
102
  server.registerTool("bighub_actions_memory_ingest", {
102
- description: "Ingest governed execution events into Future Memory.",
103
+ description: "Ingest scored execution events into decision memory.",
103
104
  inputSchema: {
104
105
  events: z.array(JsonObjectSchema),
105
106
  source: z.string().default("adapter"),
@@ -127,7 +128,7 @@ export function registerBighubTools(server, client) {
127
128
  }),
128
129
  })));
129
130
  server.registerTool("bighub_actions_memory_context", {
130
- description: "Read Future Memory context window and rates.",
131
+ description: "Read decision memory context window and rates.",
131
132
  inputSchema: {
132
133
  window_hours: z.number().int().default(24),
133
134
  tool: z.string().optional(),
@@ -142,7 +143,7 @@ export function registerBighubTools(server, client) {
142
143
  query: cleanObject({ window_hours, tool, domain, actor, source, limit_recent }),
143
144
  })));
144
145
  server.registerTool("bighub_actions_memory_refresh_aggregates", {
145
- description: "Refresh Future Memory aggregates.",
146
+ description: "Refresh decision memory aggregates.",
146
147
  inputSchema: {
147
148
  concurrent: z.boolean().default(false),
148
149
  window_hours: z.number().int().default(24),
@@ -153,7 +154,7 @@ export function registerBighubTools(server, client) {
153
154
  query: { concurrent, window_hours },
154
155
  })));
155
156
  server.registerTool("bighub_actions_memory_recommendations", {
156
- description: "Compute Future Memory policy recommendations.",
157
+ description: "Compute decision memory recommendations.",
157
158
  outputSchema: AnyOutputSchema,
158
159
  inputSchema: {
159
160
  window_hours: z.number().int().default(24),
@@ -176,7 +177,7 @@ export function registerBighubTools(server, client) {
176
177
  body: cleanObject(args),
177
178
  })));
178
179
  server.registerTool("bighub_rules_create", {
179
- description: "Create a governance rule.",
180
+ description: "Create a boundary rule.",
180
181
  outputSchema: AnyOutputSchema,
181
182
  inputSchema: {
182
183
  payload: JsonObjectSchema,
@@ -189,7 +190,7 @@ export function registerBighubTools(server, client) {
189
190
  idempotencyKey: idempotency_key,
190
191
  })));
191
192
  server.registerTool("bighub_rules_list", {
192
- description: "List governance rules.",
193
+ description: "List boundary rules.",
193
194
  outputSchema: AnyOutputSchema,
194
195
  inputSchema: {
195
196
  status: z.string().optional(),
@@ -233,7 +234,7 @@ export function registerBighubTools(server, client) {
233
234
  idempotencyKey: idempotency_key,
234
235
  })));
235
236
  server.registerTool("bighub_rules_pause", {
236
- description: "Pause rule enforcement for a rule_id.",
237
+ description: "Pause a rule by rule_id.",
237
238
  inputSchema: {
238
239
  rule_id: z.string(),
239
240
  idempotency_key: z.string().optional(),
@@ -352,13 +353,16 @@ export function registerBighubTools(server, client) {
352
353
  outputSchema: AnyOutputSchema,
353
354
  inputSchema: {
354
355
  request_id: z.string(),
355
- resolution: z.enum(["approved", "rejected"]),
356
+ resolution: z.enum(["approved", "denied", "rejected"]),
356
357
  comment: z.string().optional(),
357
358
  },
358
359
  }, async ({ request_id, resolution, comment }) => toResult(await client.request({
359
360
  method: "POST",
360
361
  path: `/approvals/${request_id}/resolve`,
361
- body: cleanObject({ resolution, comment }),
362
+ body: cleanObject({
363
+ resolution: resolution === "rejected" ? "denied" : resolution,
364
+ comment,
365
+ }),
362
366
  })));
363
367
  server.registerTool("bighub_kill_switch_status", {
364
368
  description: "Read kill switch status.",
@@ -539,10 +543,609 @@ export function registerBighubTools(server, client) {
539
543
  }, async ({ payload }) => toResult(await client.request({ method: "POST", path: "/auth/login", body: payload })));
540
544
  server.registerTool("bighub_auth_refresh", {
541
545
  description: "Rotate auth tokens with refresh token.",
542
- inputSchema: { refresh_token: z.string() },
546
+ inputSchema: { refresh_token: z.string().optional() },
543
547
  }, async ({ refresh_token }) => toResult(await client.request({ method: "POST", path: "/auth/refresh", body: { refresh_token } })));
544
548
  server.registerTool("bighub_auth_logout", {
545
549
  description: "Invalidate a refresh token.",
546
- inputSchema: { refresh_token: z.string() },
550
+ inputSchema: { refresh_token: z.string().optional() },
547
551
  }, async ({ refresh_token }) => toResult(await client.request({ method: "POST", path: "/auth/logout", body: { refresh_token } })));
552
+ // ---------------------------------------------------------------------------
553
+ // Cases — Decision case lifecycle
554
+ // ---------------------------------------------------------------------------
555
+ server.registerTool("bighub_cases_create", {
556
+ description: "Create a decision case.",
557
+ outputSchema: AnyOutputSchema,
558
+ inputSchema: {
559
+ domain: z.string(),
560
+ action: JsonObjectSchema,
561
+ context: JsonObjectSchema.optional(),
562
+ simulation: JsonObjectSchema.optional(),
563
+ verdict: JsonObjectSchema.optional(),
564
+ goal_summary: z.string().optional(),
565
+ trigger_source: z.string().optional(),
566
+ actor_type: z.string().default("AI_AGENT"),
567
+ actor_id: z.string().optional(),
568
+ agent_model: z.string().optional(),
569
+ refs: JsonObjectSchema.optional(),
570
+ tags: z.array(z.string()).optional(),
571
+ },
572
+ }, async ({ domain, action, context, simulation, verdict, goal_summary, trigger_source, actor_type, actor_id, agent_model, refs, tags }) => toResult(await client.request({
573
+ method: "POST",
574
+ path: "/cases",
575
+ body: cleanObject({ domain, action, context, simulation, verdict, goal_summary, trigger_source, actor_type, actor_id, agent_model, refs, tags }),
576
+ })));
577
+ server.registerTool("bighub_cases_get", {
578
+ description: "Get a decision case by ID.",
579
+ outputSchema: AnyOutputSchema,
580
+ inputSchema: { case_id: z.string() },
581
+ }, async ({ case_id }) => toResult(await client.request({ method: "GET", path: `/cases/${case_id}` })));
582
+ server.registerTool("bighub_cases_list", {
583
+ description: "List decision cases with filters.",
584
+ outputSchema: AnyOutputSchema,
585
+ inputSchema: {
586
+ domain: z.string().optional(),
587
+ tool: z.string().optional(),
588
+ action: z.string().optional(),
589
+ verdict: z.string().optional(),
590
+ outcome_status: z.string().optional(),
591
+ has_outcome: z.boolean().optional(),
592
+ min_risk_score: z.number().optional(),
593
+ max_risk_score: z.number().optional(),
594
+ limit: z.number().int().default(50),
595
+ offset: z.number().int().default(0),
596
+ },
597
+ }, async ({ domain, tool, action, verdict, outcome_status, has_outcome, min_risk_score, max_risk_score, limit, offset }) => toResult(await client.request({
598
+ method: "GET",
599
+ path: "/cases",
600
+ query: cleanObject({ domain, tool, action, verdict, outcome_status, has_outcome, min_risk_score, max_risk_score, limit, offset }),
601
+ })));
602
+ server.registerTool("bighub_cases_report_outcome", {
603
+ description: "Report a real-world outcome for a decision case.",
604
+ outputSchema: AnyOutputSchema,
605
+ inputSchema: {
606
+ case_id: z.string(),
607
+ status: z.string(),
608
+ description: z.string().optional(),
609
+ details: JsonObjectSchema.optional(),
610
+ actual_impact: JsonObjectSchema.optional(),
611
+ correction_needed: z.boolean().default(false),
612
+ rollback_performed: z.boolean().default(false),
613
+ revenue_impact: z.number().optional(),
614
+ },
615
+ }, async ({ case_id, status, description, details, actual_impact, correction_needed, rollback_performed, revenue_impact }) => toResult(await client.request({
616
+ method: "POST",
617
+ path: `/cases/${case_id}/outcome`,
618
+ body: cleanObject({ status, description, details, actual_impact, correction_needed, rollback_performed, revenue_impact }),
619
+ })));
620
+ server.registerTool("bighub_cases_precedents", {
621
+ description: "Get precedent intelligence for a proposed action.",
622
+ outputSchema: AnyOutputSchema,
623
+ inputSchema: {
624
+ domain: z.string(),
625
+ action: z.string(),
626
+ tool: z.string().optional(),
627
+ actor_type: z.string().default("AI_AGENT"),
628
+ risk_score: z.number().optional(),
629
+ axes: JsonObjectSchema.optional(),
630
+ },
631
+ }, async ({ domain, action, tool, actor_type, risk_score, axes }) => toResult(await client.request({
632
+ method: "POST",
633
+ path: "/cases/precedents",
634
+ body: cleanObject({ domain, action, tool, actor_type, risk_score, axes }),
635
+ })));
636
+ server.registerTool("bighub_cases_calibration", {
637
+ description: "Get calibration metrics (prediction vs reality) for cases.",
638
+ outputSchema: AnyOutputSchema,
639
+ inputSchema: {
640
+ domain: z.string().optional(),
641
+ },
642
+ }, async ({ domain }) => toResult(await client.request({
643
+ method: "GET",
644
+ path: "/cases/calibration",
645
+ query: cleanObject({ domain }),
646
+ })));
647
+ // ---------------------------------------------------------------------------
648
+ // Outcomes — Report and analyze what actually happened after execution
649
+ // ---------------------------------------------------------------------------
650
+ server.registerTool("bighub_outcomes_report", {
651
+ description: "Report a real-world outcome linked to a decision.",
652
+ outputSchema: AnyOutputSchema,
653
+ inputSchema: {
654
+ status: z.string(),
655
+ request_id: z.string().optional(),
656
+ case_id: z.string().optional(),
657
+ validation_id: z.string().optional(),
658
+ description: z.string().optional(),
659
+ details: JsonObjectSchema.optional(),
660
+ actual_impact: JsonObjectSchema.optional(),
661
+ correction_needed: z.boolean().default(false),
662
+ rollback_performed: z.boolean().default(false),
663
+ revenue_impact: z.number().optional(),
664
+ observed_at: z.string().optional(),
665
+ reported_by: z.string().optional(),
666
+ tags: z.array(z.string()).optional(),
667
+ },
668
+ }, async ({ status, request_id, case_id, validation_id, description, details, actual_impact, correction_needed, rollback_performed, revenue_impact, observed_at, reported_by, tags }) => toResult(await client.request({
669
+ method: "POST",
670
+ path: "/outcomes/report",
671
+ body: cleanObject({ status, request_id, case_id, validation_id, description, details, actual_impact, correction_needed, rollback_performed, revenue_impact, observed_at, reported_by, tags }),
672
+ })));
673
+ server.registerTool("bighub_outcomes_report_batch", {
674
+ description: "Batch report outcomes (max 100).",
675
+ outputSchema: AnyOutputSchema,
676
+ inputSchema: {
677
+ outcomes: z.array(JsonObjectSchema),
678
+ },
679
+ }, async ({ outcomes }) => toResult(await client.request({
680
+ method: "POST",
681
+ path: "/outcomes/report/batch",
682
+ body: { outcomes },
683
+ })));
684
+ server.registerTool("bighub_outcomes_get", {
685
+ description: "Get outcome by request_id.",
686
+ outputSchema: AnyOutputSchema,
687
+ inputSchema: { request_id: z.string() },
688
+ }, async ({ request_id }) => toResult(await client.request({ method: "GET", path: `/outcomes/${request_id}` })));
689
+ server.registerTool("bighub_outcomes_timeline", {
690
+ description: "Get full outcome timeline for a request.",
691
+ outputSchema: AnyOutputSchema,
692
+ inputSchema: { request_id: z.string() },
693
+ }, async ({ request_id }) => toResult(await client.request({ method: "GET", path: `/outcomes/${request_id}/timeline` })));
694
+ server.registerTool("bighub_outcomes_pending", {
695
+ description: "List decisions still awaiting outcome reports.",
696
+ outputSchema: AnyOutputSchema,
697
+ inputSchema: {
698
+ min_age_hours: z.number().int().optional(),
699
+ limit: z.number().int().default(50),
700
+ },
701
+ }, async ({ min_age_hours, limit }) => toResult(await client.request({
702
+ method: "GET",
703
+ path: "/outcomes/pending/list",
704
+ query: cleanObject({ min_age_hours, limit }),
705
+ })));
706
+ server.registerTool("bighub_outcomes_analytics", {
707
+ description: "Outcome analytics summary.",
708
+ outputSchema: AnyOutputSchema,
709
+ inputSchema: {
710
+ domain: z.string().optional(),
711
+ since: z.string().optional(),
712
+ until: z.string().optional(),
713
+ },
714
+ }, async ({ domain, since, until }) => toResult(await client.request({
715
+ method: "GET",
716
+ path: "/outcomes/analytics/summary",
717
+ query: cleanObject({ domain, since, until }),
718
+ })));
719
+ server.registerTool("bighub_outcomes_taxonomy", {
720
+ description: "Supported outcome status taxonomy.",
721
+ inputSchema: {},
722
+ }, async () => toResult(await client.request({ method: "GET", path: "/outcomes/taxonomy" })));
723
+ // ---------------------------------------------------------------------------
724
+ // Precedents — Case-based reasoning from past decisions
725
+ // ---------------------------------------------------------------------------
726
+ server.registerTool("bighub_precedents_query", {
727
+ description: "Query similar past decision cases.",
728
+ outputSchema: AnyOutputSchema,
729
+ inputSchema: {
730
+ domain: z.string(),
731
+ action: z.string(),
732
+ tool: z.string().optional(),
733
+ actor_type: z.string().default("AI_AGENT"),
734
+ axes: JsonObjectSchema.optional(),
735
+ risk_score: z.number().optional(),
736
+ intent: z.string().optional(),
737
+ min_similarity: z.number().optional(),
738
+ max_results: z.number().int().optional(),
739
+ require_outcome: z.boolean().optional(),
740
+ },
741
+ }, async ({ domain, action, tool, actor_type, axes, risk_score, intent, min_similarity, max_results, require_outcome }) => toResult(await client.request({
742
+ method: "POST",
743
+ path: "/precedents/query",
744
+ body: cleanObject({ domain, action, tool, actor_type, axes, risk_score, intent, min_similarity, max_results, require_outcome }),
745
+ })));
746
+ server.registerTool("bighub_precedents_signals", {
747
+ description: "Get aggregated precedent signals for an action.",
748
+ outputSchema: AnyOutputSchema,
749
+ inputSchema: {
750
+ domain: z.string(),
751
+ action: z.string(),
752
+ tool: z.string().optional(),
753
+ actor_type: z.string().default("AI_AGENT"),
754
+ axes: JsonObjectSchema.optional(),
755
+ risk_score: z.number().optional(),
756
+ },
757
+ }, async ({ domain, action, tool, actor_type, axes, risk_score }) => toResult(await client.request({
758
+ method: "POST",
759
+ path: "/precedents/signals",
760
+ body: cleanObject({ domain, action, tool, actor_type, axes, risk_score }),
761
+ })));
762
+ server.registerTool("bighub_precedents_stats", {
763
+ description: "Get precedent engine statistics.",
764
+ inputSchema: {},
765
+ }, async () => toResult(await client.request({ method: "GET", path: "/precedents/stats" })));
766
+ // ---------------------------------------------------------------------------
767
+ // Calibration — Prediction vs reality
768
+ // ---------------------------------------------------------------------------
769
+ server.registerTool("bighub_calibration_report", {
770
+ description: "Calibration report: how well do predicted risk scores match real outcomes.",
771
+ outputSchema: AnyOutputSchema,
772
+ inputSchema: {
773
+ domain: z.string().optional(),
774
+ tool: z.string().optional(),
775
+ risk_band: z.string().optional(),
776
+ },
777
+ }, async ({ domain, tool, risk_band }) => toResult(await client.request({
778
+ method: "GET",
779
+ path: "/calibration/report",
780
+ query: cleanObject({ domain, tool, risk_band }),
781
+ })));
782
+ server.registerTool("bighub_calibration_reliability", {
783
+ description: "Calibration reliability diagram data.",
784
+ outputSchema: AnyOutputSchema,
785
+ inputSchema: {
786
+ domain: z.string().optional(),
787
+ tool: z.string().optional(),
788
+ },
789
+ }, async ({ domain, tool }) => toResult(await client.request({
790
+ method: "GET",
791
+ path: "/calibration/reliability",
792
+ query: cleanObject({ domain, tool }),
793
+ })));
794
+ server.registerTool("bighub_calibration_drift", {
795
+ description: "Detect calibration drift over time.",
796
+ outputSchema: AnyOutputSchema,
797
+ inputSchema: {
798
+ window_days: z.number().int().optional(),
799
+ domain: z.string().optional(),
800
+ },
801
+ }, async ({ window_days, domain }) => toResult(await client.request({
802
+ method: "GET",
803
+ path: "/calibration/drift",
804
+ query: cleanObject({ window_days, domain }),
805
+ })));
806
+ server.registerTool("bighub_calibration_breakdown", {
807
+ description: "Calibration breakdown by dimension.",
808
+ outputSchema: AnyOutputSchema,
809
+ inputSchema: {
810
+ by: z.string().default("domain"),
811
+ },
812
+ }, async ({ by }) => toResult(await client.request({
813
+ method: "GET",
814
+ path: "/calibration/breakdown",
815
+ query: { by },
816
+ })));
817
+ server.registerTool("bighub_calibration_feedback", {
818
+ description: "Calibration feedback and improvement suggestions.",
819
+ outputSchema: AnyOutputSchema,
820
+ inputSchema: {
821
+ domain: z.string().optional(),
822
+ },
823
+ }, async ({ domain }) => toResult(await client.request({
824
+ method: "GET",
825
+ path: "/calibration/feedback",
826
+ query: cleanObject({ domain }),
827
+ })));
828
+ server.registerTool("bighub_calibration_observe", {
829
+ description: "Submit a calibration observation (predicted risk vs real outcome).",
830
+ outputSchema: AnyOutputSchema,
831
+ inputSchema: {
832
+ case_id: z.string(),
833
+ predicted_risk: z.number(),
834
+ outcome_status: z.string(),
835
+ domain: z.string().optional(),
836
+ tool: z.string().optional(),
837
+ action: z.string().optional(),
838
+ actor_type: z.string().optional(),
839
+ verdict: z.string().optional(),
840
+ },
841
+ }, async ({ case_id, predicted_risk, outcome_status, domain, tool, action, actor_type, verdict }) => toResult(await client.request({
842
+ method: "POST",
843
+ path: "/calibration/observe",
844
+ body: cleanObject({ case_id, predicted_risk, outcome_status, domain, tool, action, actor_type, verdict }),
845
+ })));
846
+ // ---------------------------------------------------------------------------
847
+ // Retrieval — Multi-signal decision retrieval engine
848
+ // ---------------------------------------------------------------------------
849
+ server.registerTool("bighub_retrieval_query", {
850
+ description: "Multi-signal decision retrieval: find relevant past cases for an upcoming action.",
851
+ outputSchema: AnyOutputSchema,
852
+ inputSchema: {
853
+ domain: z.string(),
854
+ action: z.string(),
855
+ tool: z.string().optional(),
856
+ actor_type: z.string().default("AI_AGENT"),
857
+ axes: JsonObjectSchema.optional(),
858
+ risk_score: z.number().optional(),
859
+ strategy: z.string().default("balanced"),
860
+ strategy_name: z.string().optional(),
861
+ },
862
+ }, async ({ domain, action, tool, actor_type, axes, risk_score, strategy, strategy_name }) => toResult(await client.request({
863
+ method: "POST",
864
+ path: "/retrieval/query",
865
+ body: cleanObject({
866
+ domain,
867
+ action,
868
+ tool,
869
+ actor_type,
870
+ axes,
871
+ risk_score,
872
+ strategy: strategy_name ?? strategy,
873
+ strategy_name: strategy_name ?? strategy,
874
+ }),
875
+ })));
876
+ server.registerTool("bighub_retrieval_query_explained", {
877
+ description: "Retrieval query with full scoring explanation.",
878
+ outputSchema: AnyOutputSchema,
879
+ inputSchema: {
880
+ domain: z.string(),
881
+ action: z.string(),
882
+ tool: z.string().optional(),
883
+ actor_type: z.string().default("AI_AGENT"),
884
+ axes: JsonObjectSchema.optional(),
885
+ risk_score: z.number().optional(),
886
+ strategy: z.string().default("balanced"),
887
+ strategy_name: z.string().optional(),
888
+ },
889
+ }, async ({ domain, action, tool, actor_type, axes, risk_score, strategy, strategy_name }) => toResult(await client.request({
890
+ method: "POST",
891
+ path: "/retrieval/query/explained",
892
+ body: cleanObject({
893
+ domain,
894
+ action,
895
+ tool,
896
+ actor_type,
897
+ axes,
898
+ risk_score,
899
+ strategy: strategy_name ?? strategy,
900
+ strategy_name: strategy_name ?? strategy,
901
+ }),
902
+ })));
903
+ server.registerTool("bighub_retrieval_strategies", {
904
+ description: "List available retrieval strategies.",
905
+ inputSchema: {},
906
+ }, async () => toResult(await client.request({ method: "GET", path: "/retrieval/strategies" })));
907
+ server.registerTool("bighub_retrieval_strategy", {
908
+ description: "Get details of a retrieval strategy by name.",
909
+ outputSchema: AnyOutputSchema,
910
+ inputSchema: { name: z.string() },
911
+ }, async ({ name }) => toResult(await client.request({ method: "GET", path: `/retrieval/strategy/${name}` })));
912
+ server.registerTool("bighub_retrieval_index_case", {
913
+ description: "Index a decision case into the retrieval engine.",
914
+ outputSchema: AnyOutputSchema,
915
+ inputSchema: {
916
+ case_id: z.string(),
917
+ org_id: z.string(),
918
+ tool: z.string(),
919
+ action: z.string(),
920
+ domain: z.string(),
921
+ actor_type: z.string().default("AI_AGENT"),
922
+ risk_score: z.number().default(0.0),
923
+ verdict: z.string().default("ALLOWED"),
924
+ axes: JsonObjectSchema.optional(),
925
+ },
926
+ }, async ({ case_id, org_id, tool, action, domain, actor_type, risk_score, verdict, axes }) => toResult(await client.request({
927
+ method: "POST",
928
+ path: "/retrieval/index",
929
+ body: cleanObject({ case_id, org_id, tool, action, domain, actor_type, risk_score, verdict, axes }),
930
+ })));
931
+ server.registerTool("bighub_retrieval_stats", {
932
+ description: "Get retrieval engine statistics.",
933
+ inputSchema: {},
934
+ }, async () => toResult(await client.request({ method: "GET", path: "/retrieval/stats" })));
935
+ // ---------------------------------------------------------------------------
936
+ // Features — Decision feature layer
937
+ // ---------------------------------------------------------------------------
938
+ server.registerTool("bighub_features_compute", {
939
+ description: "Compute decision features for a case.",
940
+ outputSchema: AnyOutputSchema,
941
+ inputSchema: {
942
+ case_id: z.string(),
943
+ org_id: z.string(),
944
+ case_data: JsonObjectSchema,
945
+ precedent_data: JsonObjectSchema.optional(),
946
+ advisory_data: JsonObjectSchema.optional(),
947
+ },
948
+ }, async ({ case_id, org_id, case_data, precedent_data, advisory_data }) => toResult(await client.request({
949
+ method: "POST",
950
+ path: "/features/compute",
951
+ body: cleanObject({ case_id, org_id, case_data, precedent_data, advisory_data }),
952
+ })));
953
+ server.registerTool("bighub_features_snapshot", {
954
+ description: "Create a versioned feature snapshot for a case.",
955
+ outputSchema: AnyOutputSchema,
956
+ inputSchema: {
957
+ case_id: z.string(),
958
+ tag: z.string().optional(),
959
+ },
960
+ }, async ({ case_id, tag }) => toResult(await client.request({
961
+ method: "POST",
962
+ path: "/features/snapshot",
963
+ body: cleanObject({ case_id, tag }),
964
+ })));
965
+ server.registerTool("bighub_features_get_snapshot", {
966
+ description: "Get a feature snapshot by ID.",
967
+ outputSchema: AnyOutputSchema,
968
+ inputSchema: { snapshot_id: z.string() },
969
+ }, async ({ snapshot_id }) => toResult(await client.request({ method: "GET", path: `/features/snapshot/${snapshot_id}` })));
970
+ server.registerTool("bighub_features_list_snapshots", {
971
+ description: "List feature snapshots.",
972
+ outputSchema: AnyOutputSchema,
973
+ inputSchema: {
974
+ tag: z.string().optional(),
975
+ case_id: z.string().optional(),
976
+ },
977
+ }, async ({ tag, case_id }) => toResult(await client.request({
978
+ method: "GET",
979
+ path: "/features/snapshots",
980
+ query: cleanObject({ tag, case_id }),
981
+ })));
982
+ server.registerTool("bighub_features_explain", {
983
+ description: "Explain computed features for a case.",
984
+ outputSchema: AnyOutputSchema,
985
+ inputSchema: {
986
+ case_id: z.string(),
987
+ feature_key: z.string().optional(),
988
+ },
989
+ }, async ({ case_id, feature_key }) => toResult(await client.request({
990
+ method: "GET",
991
+ path: feature_key ? `/features/explain/${case_id}/${feature_key}` : `/features/explain/${case_id}`,
992
+ })));
993
+ server.registerTool("bighub_features_export", {
994
+ description: "Export all features for a case.",
995
+ outputSchema: AnyOutputSchema,
996
+ inputSchema: { case_id: z.string() },
997
+ }, async ({ case_id }) => toResult(await client.request({ method: "GET", path: `/features/export/${case_id}` })));
998
+ server.registerTool("bighub_features_schema", {
999
+ description: "Get the feature schema (all defined features and types).",
1000
+ inputSchema: {},
1001
+ }, async () => toResult(await client.request({ method: "GET", path: "/features/schema" })));
1002
+ server.registerTool("bighub_features_stats", {
1003
+ description: "Get feature layer statistics.",
1004
+ inputSchema: {},
1005
+ }, async () => toResult(await client.request({ method: "GET", path: "/features/stats" })));
1006
+ // ---------------------------------------------------------------------------
1007
+ // Insights — Patterns, advisories, and action profiles
1008
+ // ---------------------------------------------------------------------------
1009
+ server.registerTool("bighub_insights_advise", {
1010
+ description: "Get decision advisory for a proposed action based on learned patterns.",
1011
+ outputSchema: AnyOutputSchema,
1012
+ inputSchema: {
1013
+ tool: z.string(),
1014
+ action: z.string(),
1015
+ domain: z.string(),
1016
+ actor_type: z.string().default("AI_AGENT"),
1017
+ risk_band: z.string().optional(),
1018
+ },
1019
+ }, async ({ tool, action, domain, actor_type, risk_band }) => toResult(await client.request({
1020
+ method: "POST",
1021
+ path: "/insights/advise",
1022
+ body: cleanObject({ tool, action, domain, actor_type, risk_band }),
1023
+ })));
1024
+ server.registerTool("bighub_insights_patterns", {
1025
+ description: "List detected decision patterns.",
1026
+ outputSchema: AnyOutputSchema,
1027
+ inputSchema: {
1028
+ pattern_type: z.string().optional(),
1029
+ domain: z.string().optional(),
1030
+ tool: z.string().optional(),
1031
+ min_severity: z.string().optional(),
1032
+ },
1033
+ }, async ({ pattern_type, domain, tool, min_severity }) => toResult(await client.request({
1034
+ method: "GET",
1035
+ path: "/insights/patterns",
1036
+ query: cleanObject({ pattern_type, domain, tool, min_severity }),
1037
+ })));
1038
+ server.registerTool("bighub_insights_learn", {
1039
+ description: "Trigger pattern learning from accumulated cases.",
1040
+ inputSchema: {},
1041
+ }, async () => toResult(await client.request({ method: "GET", path: "/insights/patterns/learn" })));
1042
+ server.registerTool("bighub_insights_profile", {
1043
+ description: "Get action quality profile for a tool/action/domain.",
1044
+ outputSchema: AnyOutputSchema,
1045
+ inputSchema: {
1046
+ tool: z.string().optional(),
1047
+ action: z.string().optional(),
1048
+ domain: z.string().optional(),
1049
+ },
1050
+ }, async ({ tool, action, domain }) => toResult(await client.request({
1051
+ method: "GET",
1052
+ path: "/insights/profile",
1053
+ query: cleanObject({ tool, action, domain }),
1054
+ })));
1055
+ // ---------------------------------------------------------------------------
1056
+ // Simulations — Chronos simulation vault
1057
+ // ---------------------------------------------------------------------------
1058
+ server.registerTool("bighub_simulations_list", {
1059
+ description: "List persisted simulation snapshots.",
1060
+ outputSchema: AnyOutputSchema,
1061
+ inputSchema: {
1062
+ domain: z.string().optional(),
1063
+ tool: z.string().optional(),
1064
+ with_outcome: z.boolean().optional(),
1065
+ limit: z.number().int().default(50),
1066
+ },
1067
+ }, async ({ domain, tool, with_outcome, limit }) => toResult(await client.request({
1068
+ method: "GET",
1069
+ path: "/simulations",
1070
+ query: cleanObject({ domain, tool, with_outcome, limit }),
1071
+ })));
1072
+ server.registerTool("bighub_simulations_get", {
1073
+ description: "Get a simulation snapshot by ID.",
1074
+ outputSchema: AnyOutputSchema,
1075
+ inputSchema: { snapshot_id: z.string() },
1076
+ }, async ({ snapshot_id }) => toResult(await client.request({ method: "GET", path: `/simulations/${snapshot_id}` })));
1077
+ server.registerTool("bighub_simulations_by_request", {
1078
+ description: "Get simulation snapshot for a given request_id.",
1079
+ outputSchema: AnyOutputSchema,
1080
+ inputSchema: { request_id: z.string() },
1081
+ }, async ({ request_id }) => toResult(await client.request({ method: "GET", path: `/simulations/by-request/${request_id}` })));
1082
+ server.registerTool("bighub_simulations_compare", {
1083
+ description: "Compare simulation prediction vs real outcome for a request.",
1084
+ outputSchema: AnyOutputSchema,
1085
+ inputSchema: { request_id: z.string() },
1086
+ }, async ({ request_id }) => toResult(await client.request({ method: "GET", path: `/simulations/by-request/${request_id}/compare` })));
1087
+ server.registerTool("bighub_simulations_accuracy", {
1088
+ description: "Simulation accuracy metrics.",
1089
+ outputSchema: AnyOutputSchema,
1090
+ inputSchema: {
1091
+ domain: z.string().optional(),
1092
+ tool: z.string().optional(),
1093
+ },
1094
+ }, async ({ domain, tool }) => toResult(await client.request({
1095
+ method: "GET",
1096
+ path: "/simulations/accuracy",
1097
+ query: cleanObject({ domain, tool }),
1098
+ })));
1099
+ server.registerTool("bighub_simulations_stats", {
1100
+ description: "Get simulation vault statistics.",
1101
+ inputSchema: {},
1102
+ }, async () => toResult(await client.request({ method: "GET", path: "/simulations/stats" })));
1103
+ // ---------------------------------------------------------------------------
1104
+ // Learning — Outcome-to-learning pipeline management
1105
+ // ---------------------------------------------------------------------------
1106
+ server.registerTool("bighub_learning_strategy", {
1107
+ description: "Get current learning strategy version and configuration.",
1108
+ inputSchema: {},
1109
+ }, async () => toResult(await client.request({ method: "GET", path: "/ops/learning/strategy" })));
1110
+ server.registerTool("bighub_learning_runs", {
1111
+ description: "List recent learning pipeline runs.",
1112
+ outputSchema: AnyOutputSchema,
1113
+ inputSchema: {
1114
+ limit: z.number().int().default(50),
1115
+ },
1116
+ }, async ({ limit }) => toResult(await client.request({
1117
+ method: "GET",
1118
+ path: "/ops/learning/runs",
1119
+ query: { limit },
1120
+ })));
1121
+ server.registerTool("bighub_learning_recompute", {
1122
+ description: "Trigger recomputation of learning artifacts for a scope.",
1123
+ outputSchema: AnyOutputSchema,
1124
+ inputSchema: {
1125
+ domain: z.string().default(""),
1126
+ action_family: z.string().default(""),
1127
+ force: z.boolean().default(false),
1128
+ limit: z.number().int().default(5000),
1129
+ async_mode: z.boolean().default(true),
1130
+ },
1131
+ }, async ({ domain, action_family, force, limit, async_mode }) => toResult(await client.request({
1132
+ method: "POST",
1133
+ path: "/ops/learning/recompute",
1134
+ body: { domain, action_family, force, limit, async_mode },
1135
+ })));
1136
+ server.registerTool("bighub_learning_backfill", {
1137
+ description: "Backfill learning artifacts from historical outcomes.",
1138
+ outputSchema: AnyOutputSchema,
1139
+ inputSchema: {
1140
+ domain: z.string().default(""),
1141
+ action_family: z.string().default(""),
1142
+ force: z.boolean().default(false),
1143
+ limit: z.number().int().default(5000),
1144
+ async_mode: z.boolean().default(true),
1145
+ },
1146
+ }, async ({ domain, action_family, force, limit, async_mode }) => toResult(await client.request({
1147
+ method: "POST",
1148
+ path: "/ops/learning/backfill",
1149
+ body: { domain, action_family, force, limit, async_mode },
1150
+ })));
548
1151
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@bighub/bighub-mcp",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "mcpName": "io.bighub/mcp",
5
- "description": "MCP server for governing AI agent actions with the BIGHUB control plane.",
5
+ "description": "MCP server for decision learning for AI agent actions with BIGHUB.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
8
8
  "bin": {
@@ -35,9 +35,8 @@
35
35
  "bighub",
36
36
  "mcp",
37
37
  "model-context-protocol",
38
- "governance",
39
- "ai-agents",
40
- "execution-control"
38
+ "decision-learning",
39
+ "ai-agents"
41
40
  ],
42
41
  "license": "MIT",
43
42
  "engines": {