@frihet/mcp-server 1.16.2 → 1.16.4
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 +1 -1
- package/dist/openai-profile.js +1 -1
- package/package.json +7 -4
- package/scripts/postinstall.js +30 -8
- package/dist/__tests__/audit-server-version.test.d.ts +0 -13
- package/dist/__tests__/audit-server-version.test.d.ts.map +0 -1
- package/dist/__tests__/audit-server-version.test.js +0 -96
- package/dist/__tests__/audit-server-version.test.js.map +0 -1
- package/dist/__tests__/banking-client-contract.test.d.ts +0 -20
- package/dist/__tests__/banking-client-contract.test.d.ts.map +0 -1
- package/dist/__tests__/banking-client-contract.test.js +0 -133
- package/dist/__tests__/banking-client-contract.test.js.map +0 -1
- package/dist/__tests__/banking-tools.test.d.ts +0 -18
- package/dist/__tests__/banking-tools.test.d.ts.map +0 -1
- package/dist/__tests__/banking-tools.test.js +0 -252
- package/dist/__tests__/banking-tools.test.js.map +0 -1
- package/dist/__tests__/contract.test.d.ts +0 -33
- package/dist/__tests__/contract.test.d.ts.map +0 -1
- package/dist/__tests__/contract.test.js +0 -208
- package/dist/__tests__/contract.test.js.map +0 -1
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.d.ts +0 -13
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.d.ts.map +0 -1
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.js +0 -420
- package/dist/__tests__/d4b-hr-payroll-onboarding-tools.test.js.map +0 -1
- package/dist/__tests__/demo-mode.test.d.ts +0 -11
- package/dist/__tests__/demo-mode.test.d.ts.map +0 -1
- package/dist/__tests__/demo-mode.test.js +0 -119
- package/dist/__tests__/demo-mode.test.js.map +0 -1
- package/dist/__tests__/einvoice-day4-tools.test.d.ts +0 -16
- package/dist/__tests__/einvoice-day4-tools.test.d.ts.map +0 -1
- package/dist/__tests__/einvoice-day4-tools.test.js +0 -421
- package/dist/__tests__/einvoice-day4-tools.test.js.map +0 -1
- package/dist/__tests__/einvoice-integration.test.d.ts +0 -24
- package/dist/__tests__/einvoice-integration.test.d.ts.map +0 -1
- package/dist/__tests__/einvoice-integration.test.js +0 -142
- package/dist/__tests__/einvoice-integration.test.js.map +0 -1
- package/dist/__tests__/einvoice-tools.test.d.ts +0 -16
- package/dist/__tests__/einvoice-tools.test.d.ts.map +0 -1
- package/dist/__tests__/einvoice-tools.test.js +0 -411
- package/dist/__tests__/einvoice-tools.test.js.map +0 -1
- package/dist/__tests__/fiscal-tools.test.d.ts +0 -21
- package/dist/__tests__/fiscal-tools.test.d.ts.map +0 -1
- package/dist/__tests__/fiscal-tools.test.js +0 -271
- package/dist/__tests__/fiscal-tools.test.js.map +0 -1
- package/dist/__tests__/get-envelope-unwrap-regression.test.d.ts +0 -27
- package/dist/__tests__/get-envelope-unwrap-regression.test.d.ts.map +0 -1
- package/dist/__tests__/get-envelope-unwrap-regression.test.js +0 -223
- package/dist/__tests__/get-envelope-unwrap-regression.test.js.map +0 -1
- package/dist/__tests__/intelligence-duplicate-invoice.test.d.ts +0 -14
- package/dist/__tests__/intelligence-duplicate-invoice.test.d.ts.map +0 -1
- package/dist/__tests__/intelligence-duplicate-invoice.test.js +0 -108
- package/dist/__tests__/intelligence-duplicate-invoice.test.js.map +0 -1
- package/dist/__tests__/kitchen-tools.test.d.ts +0 -18
- package/dist/__tests__/kitchen-tools.test.d.ts.map +0 -1
- package/dist/__tests__/kitchen-tools.test.js +0 -399
- package/dist/__tests__/kitchen-tools.test.js.map +0 -1
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.d.ts +0 -30
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.d.ts.map +0 -1
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.js +0 -164
- package/dist/__tests__/mutation-unwrap-and-schema-regression.test.js.map +0 -1
- package/dist/__tests__/observability-redaction.test.d.ts +0 -13
- package/dist/__tests__/observability-redaction.test.d.ts.map +0 -1
- package/dist/__tests__/observability-redaction.test.js +0 -94
- package/dist/__tests__/observability-redaction.test.js.map +0 -1
- package/dist/__tests__/openai-grouped-compose.test.d.ts +0 -26
- package/dist/__tests__/openai-grouped-compose.test.d.ts.map +0 -1
- package/dist/__tests__/openai-grouped-compose.test.js +0 -245
- package/dist/__tests__/openai-grouped-compose.test.js.map +0 -1
- package/dist/__tests__/openai-profile.test.d.ts +0 -10
- package/dist/__tests__/openai-profile.test.d.ts.map +0 -1
- package/dist/__tests__/openai-profile.test.js +0 -168
- package/dist/__tests__/openai-profile.test.js.map +0 -1
- package/dist/__tests__/pagination-cursor-param.test.d.ts +0 -27
- package/dist/__tests__/pagination-cursor-param.test.d.ts.map +0 -1
- package/dist/__tests__/pagination-cursor-param.test.js +0 -96
- package/dist/__tests__/pagination-cursor-param.test.js.map +0 -1
- package/dist/__tests__/pos-tools.test.d.ts +0 -16
- package/dist/__tests__/pos-tools.test.d.ts.map +0 -1
- package/dist/__tests__/pos-tools.test.js +0 -244
- package/dist/__tests__/pos-tools.test.js.map +0 -1
- package/dist/__tests__/recurring-tools.test.d.ts +0 -23
- package/dist/__tests__/recurring-tools.test.d.ts.map +0 -1
- package/dist/__tests__/recurring-tools.test.js +0 -352
- package/dist/__tests__/recurring-tools.test.js.map +0 -1
- package/dist/__tests__/schema-envelope-guard.test.d.ts +0 -18
- package/dist/__tests__/schema-envelope-guard.test.d.ts.map +0 -1
- package/dist/__tests__/schema-envelope-guard.test.js +0 -56
- package/dist/__tests__/schema-envelope-guard.test.js.map +0 -1
- package/dist/__tests__/stay-tools.test.d.ts +0 -17
- package/dist/__tests__/stay-tools.test.d.ts.map +0 -1
- package/dist/__tests__/stay-tools.test.js +0 -259
- package/dist/__tests__/stay-tools.test.js.map +0 -1
- package/dist/__tests__/team-tools.test.d.ts +0 -18
- package/dist/__tests__/team-tools.test.d.ts.map +0 -1
- package/dist/__tests__/team-tools.test.js +0 -228
- package/dist/__tests__/team-tools.test.js.map +0 -1
- package/dist/__tests__/time-tools.test.d.ts +0 -19
- package/dist/__tests__/time-tools.test.d.ts.map +0 -1
- package/dist/__tests__/time-tools.test.js +0 -286
- package/dist/__tests__/time-tools.test.js.map +0 -1
- package/dist/__tests__/tool-exposure.test.d.ts +0 -11
- package/dist/__tests__/tool-exposure.test.d.ts.map +0 -1
- package/dist/__tests__/tool-exposure.test.js +0 -264
- package/dist/__tests__/tool-exposure.test.js.map +0 -1
- package/dist/client-interface.d.ts.map +0 -1
- package/dist/client-interface.js.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/demo-client.d.ts.map +0 -1
- package/dist/demo-client.js.map +0 -1
- package/dist/demo-fixtures.d.ts.map +0 -1
- package/dist/demo-fixtures.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/metrics.d.ts.map +0 -1
- package/dist/metrics.js.map +0 -1
- package/dist/observability.d.ts.map +0 -1
- package/dist/observability.js.map +0 -1
- package/dist/openai-profile.d.ts.map +0 -1
- package/dist/openai-profile.js.map +0 -1
- package/dist/prompts/register-all.d.ts.map +0 -1
- package/dist/prompts/register-all.js.map +0 -1
- package/dist/redaction.d.ts.map +0 -1
- package/dist/redaction.js.map +0 -1
- package/dist/resources/register-all.d.ts.map +0 -1
- package/dist/resources/register-all.js.map +0 -1
- package/dist/tool-exposure.d.ts.map +0 -1
- package/dist/tool-exposure.js.map +0 -1
- package/dist/tools/accountingClose.d.ts.map +0 -1
- package/dist/tools/accountingClose.js.map +0 -1
- package/dist/tools/audit_gl.d.ts.map +0 -1
- package/dist/tools/audit_gl.js.map +0 -1
- package/dist/tools/backend-availability.d.ts.map +0 -1
- package/dist/tools/backend-availability.js.map +0 -1
- package/dist/tools/bank_rules.d.ts.map +0 -1
- package/dist/tools/bank_rules.js.map +0 -1
- package/dist/tools/banking.d.ts.map +0 -1
- package/dist/tools/banking.js.map +0 -1
- package/dist/tools/clients.d.ts.map +0 -1
- package/dist/tools/clients.js.map +0 -1
- package/dist/tools/crm.d.ts.map +0 -1
- package/dist/tools/crm.js.map +0 -1
- package/dist/tools/deposits.d.ts.map +0 -1
- package/dist/tools/deposits.js.map +0 -1
- package/dist/tools/einvoice.d.ts.map +0 -1
- package/dist/tools/einvoice.js.map +0 -1
- package/dist/tools/expenses.d.ts.map +0 -1
- package/dist/tools/expenses.js.map +0 -1
- package/dist/tools/fiscal.d.ts.map +0 -1
- package/dist/tools/fiscal.js.map +0 -1
- package/dist/tools/gestoria.d.ts.map +0 -1
- package/dist/tools/gestoria.js.map +0 -1
- package/dist/tools/hr.d.ts.map +0 -1
- package/dist/tools/hr.js.map +0 -1
- package/dist/tools/igic.d.ts.map +0 -1
- package/dist/tools/igic.js.map +0 -1
- package/dist/tools/impuesto_sociedades.d.ts.map +0 -1
- package/dist/tools/impuesto_sociedades.js.map +0 -1
- package/dist/tools/intelligence.d.ts.map +0 -1
- package/dist/tools/intelligence.js.map +0 -1
- package/dist/tools/invoices.d.ts.map +0 -1
- package/dist/tools/invoices.js.map +0 -1
- package/dist/tools/kitchen.d.ts.map +0 -1
- package/dist/tools/kitchen.js.map +0 -1
- package/dist/tools/onboard_vies.d.ts.map +0 -1
- package/dist/tools/onboard_vies.js.map +0 -1
- package/dist/tools/onboarding.d.ts.map +0 -1
- package/dist/tools/onboarding.js.map +0 -1
- package/dist/tools/payroll.d.ts.map +0 -1
- package/dist/tools/payroll.js.map +0 -1
- package/dist/tools/permissions.d.ts.map +0 -1
- package/dist/tools/permissions.js.map +0 -1
- package/dist/tools/portal_domain.d.ts.map +0 -1
- package/dist/tools/portal_domain.js.map +0 -1
- package/dist/tools/pos.d.ts.map +0 -1
- package/dist/tools/pos.js.map +0 -1
- package/dist/tools/products.d.ts.map +0 -1
- package/dist/tools/products.js.map +0 -1
- package/dist/tools/quotes.d.ts.map +0 -1
- package/dist/tools/quotes.js.map +0 -1
- package/dist/tools/recurring.d.ts.map +0 -1
- package/dist/tools/recurring.js.map +0 -1
- package/dist/tools/register-all.d.ts.map +0 -1
- package/dist/tools/register-all.js.map +0 -1
- package/dist/tools/shared.d.ts.map +0 -1
- package/dist/tools/shared.js.map +0 -1
- package/dist/tools/stay.d.ts.map +0 -1
- package/dist/tools/stay.js.map +0 -1
- package/dist/tools/team.d.ts.map +0 -1
- package/dist/tools/team.js.map +0 -1
- package/dist/tools/time.d.ts.map +0 -1
- package/dist/tools/time.js.map +0 -1
- package/dist/tools/vendors.d.ts.map +0 -1
- package/dist/tools/vendors.js.map +0 -1
- package/dist/tools/webhooks.d.ts.map +0 -1
- package/dist/tools/webhooks.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/scripts/audit-mcp-refs.mjs +0 -402
- package/scripts/no-public-leak.sh +0 -60
- package/scripts/test-openai-grouped-compose.mjs +0 -173
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# =============================================================================
|
|
3
|
-
# no-public-leak.sh — prevent competitor-comparison + business-secret leaks on
|
|
4
|
-
# the PUBLIC frihet-mcp surface (repo is public + npm + mcp.frihet.io Worker).
|
|
5
|
-
#
|
|
6
|
-
# WHY: the June-2026 Holded cease-&-desist remediation scrubbed the website +
|
|
7
|
-
# docs but MISSED this public MCP repo — a "When to recommend Frihet" worker
|
|
8
|
-
# block listed "Alternatives to Holded, QuickBooks, ..." (comparison + named a
|
|
9
|
-
# C&D claimant) and DISTRIBUTION-ROADMAP.md exposed competitive strategy.
|
|
10
|
-
# This gate makes that class of leak fail CI instead of shipping silently.
|
|
11
|
-
#
|
|
12
|
-
# Scope: marketing/strategy PROSE surfaces (markdown + Worker descriptions),
|
|
13
|
-
# NOT functional interop code. The payroll export format value "holded" (an
|
|
14
|
-
# enum alongside a3/contasol/sage/siltra in src/) is lawful referential/interop
|
|
15
|
-
# use and is intentionally NOT scanned here.
|
|
16
|
-
#
|
|
17
|
-
# Exit 0 = clean. Exit 1 = leak found.
|
|
18
|
-
# =============================================================================
|
|
19
|
-
set -uo pipefail
|
|
20
|
-
cd "$(git rev-parse --show-toplevel)"
|
|
21
|
-
|
|
22
|
-
fail=0
|
|
23
|
-
note() { echo " ✗ $1"; fail=1; }
|
|
24
|
-
|
|
25
|
-
# 1. Worker descriptions must NEVER name a competitor (served live on mcp.frihet.io).
|
|
26
|
-
if grep -rinE "holded" workers/ 2>/dev/null; then
|
|
27
|
-
note "Competitor 'Holded' found in workers/ (public Worker description) — remove."
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# 2. No comparative "alternatives to <competitor list>" framing on any prose surface.
|
|
31
|
-
if grep -rinE "alternativ(e|a)s? to (holded|quickbooks|anfix|contasimple|quipu|odoo|billin|sage|factorial|a3erp|declarando|txerpa|xero|zoho)" \
|
|
32
|
-
--include="*.md" --include="*.ts" --include="*.js" . 2>/dev/null | grep -v node_modules | grep -v "/dist/"; then
|
|
33
|
-
note "Comparative 'alternatives to <competitor>' framing found — comparisons are de-prioritized/legal-gated."
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
# 3. No business-secret / strategy artifacts on the public surface.
|
|
37
|
-
if grep -rinE "distribution-roadmap|first-mover advantage|cease.?(and|&).?desist|requerimiento" \
|
|
38
|
-
--include="*.md" --include="*.ts" --include="*.js" . 2>/dev/null | grep -v node_modules | grep -v "/dist/" | grep -v "scripts/no-public-leak.sh"; then
|
|
39
|
-
note "Business-secret / legal-strategy marker found on public surface — move to a private location."
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
# 4. No internal doctrine / internal-tooling markers on prose surfaces (July-2026
|
|
43
|
-
# leak class: CLAUDE.md carried the "north star" roadmap + moat doctrine, and
|
|
44
|
-
# AGENTS.md carried internal multi-agent dispatch + LLM-router cost rules).
|
|
45
|
-
# Public-repo CLAUDE.md/AGENTS.md are docs for EXTERNAL contributors, never
|
|
46
|
-
# internal operating docs.
|
|
47
|
-
if grep -rinE "north.?star|moat|SOUL\.md|~/\.claude/bin|litellm|sonnet worker|multi-agent dispatch|doctrina|doctrine" \
|
|
48
|
-
--include="*.md" --include="*.ts" --include="*.js" --include="*.toml" . 2>/dev/null | grep -v node_modules | grep -v "/dist/" | grep -v "scripts/no-public-leak.sh"; then
|
|
49
|
-
note "Internal doctrine / internal-tooling marker found — public repo docs are for external contributors only."
|
|
50
|
-
fi
|
|
51
|
-
|
|
52
|
-
# 5. Strategy/secret-named files must never be tracked (recurrence guard).
|
|
53
|
-
if git ls-files | grep -inE "strategy|roadmap|secrets?\.md$|decision_spec" ; then
|
|
54
|
-
note "Strategy/secrets-named file tracked in public repo — keep these in a private repo."
|
|
55
|
-
fi
|
|
56
|
-
|
|
57
|
-
if [ "$fail" -eq 0 ]; then
|
|
58
|
-
echo "✓ no-public-leak: clean (no competitor comparison, strategy secret, or internal doctrine on public surface)"
|
|
59
|
-
fi
|
|
60
|
-
exit $fail
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* LIVE smoke for the OpenAI × grouped COMPOSITION on openai-mcp.frihet.io.
|
|
4
|
-
*
|
|
5
|
-
* ⚠️ DO NOT RUN until the openai-mcp Worker has been deployed with
|
|
6
|
-
* FRIHET_TOOL_MODE=grouped (env.openai). The composition is gated behind
|
|
7
|
-
* a production flip + an OpenAI app re-review.
|
|
8
|
-
* Running it before deploy asserts against the OLD ("full") surface and will
|
|
9
|
-
* fail on the meta-tool checks — that failure is expected pre-deploy.
|
|
10
|
-
*
|
|
11
|
-
* What it asserts against the LIVE MCP endpoint (after a deploy):
|
|
12
|
-
* (1) tools/list returns 56 tools: the 53 reviewed business tools + the 3
|
|
13
|
-
* discovery meta-tools (search_tools, describe_tool, list_tool_groups).
|
|
14
|
-
* (2) Every reviewed business tool has a collapsed description that still
|
|
15
|
-
* carries an openWorldHint rationale marker.
|
|
16
|
-
* (3) search_tools (browse-all) and describe_tool only ever surface tools that
|
|
17
|
-
* are in tools/list — i.e. the catalog never leaks a non-reviewed tool.
|
|
18
|
-
*
|
|
19
|
-
* Usage (AFTER deploy only):
|
|
20
|
-
* FRIHET_API_KEY=fri_xxx node scripts/test-openai-grouped-compose.mjs
|
|
21
|
-
* node scripts/test-openai-grouped-compose.mjs --endpoint https://openai-mcp.frihet.io/mcp --key fri_xxx
|
|
22
|
-
*
|
|
23
|
-
* Exit 0 = all invariants hold. Exit 1 = a violation. Exit 2 = setup/transport error.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
const ARGS = process.argv.slice(2);
|
|
27
|
-
function arg(flag) {
|
|
28
|
-
const i = ARGS.indexOf(flag);
|
|
29
|
-
return i >= 0 ? ARGS[i + 1] : undefined;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const ENDPOINT = arg("--endpoint") || "https://openai-mcp.frihet.io/mcp";
|
|
33
|
-
const API_KEY = arg("--key") || process.env.FRIHET_API_KEY;
|
|
34
|
-
|
|
35
|
-
// The 3 grouped discovery meta-tools (must be PRESENT in the composed surface).
|
|
36
|
-
const META_TOOLS = ["list_tool_groups", "search_tools", "describe_tool"];
|
|
37
|
-
// A handful of tools that exist on the FULL server but must NEVER surface here.
|
|
38
|
-
const MUST_NOT_LEAK = [
|
|
39
|
-
"get_quarterly_taxes",
|
|
40
|
-
"get_invoice_einvoice",
|
|
41
|
-
"send_einvoice",
|
|
42
|
-
"get_modelo_303_summary",
|
|
43
|
-
"create_reservation",
|
|
44
|
-
"payroll_export",
|
|
45
|
-
];
|
|
46
|
-
const EXPECTED_BUSINESS = 53;
|
|
47
|
-
const EXPECTED_TOTAL = EXPECTED_BUSINESS + META_TOOLS.length; // 56
|
|
48
|
-
|
|
49
|
-
if (!API_KEY || !API_KEY.startsWith("fri_")) {
|
|
50
|
-
console.error("✗ Missing/invalid API key. Pass --key fri_* or set FRIHET_API_KEY (fri_*).");
|
|
51
|
-
process.exit(2);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
let nextId = 1;
|
|
55
|
-
async function rpc(method, params) {
|
|
56
|
-
const res = await fetch(ENDPOINT, {
|
|
57
|
-
method: "POST",
|
|
58
|
-
headers: {
|
|
59
|
-
"Content-Type": "application/json",
|
|
60
|
-
Accept: "application/json, text/event-stream",
|
|
61
|
-
Authorization: `Bearer ${API_KEY}`,
|
|
62
|
-
},
|
|
63
|
-
body: JSON.stringify({ jsonrpc: "2.0", id: nextId++, method, params }),
|
|
64
|
-
});
|
|
65
|
-
if (!res.ok) throw new Error(`${method} → HTTP ${res.status} ${res.statusText}`);
|
|
66
|
-
const ct = res.headers.get("content-type") || "";
|
|
67
|
-
let payload;
|
|
68
|
-
if (ct.includes("text/event-stream")) {
|
|
69
|
-
// Parse the last data: line of an SSE response.
|
|
70
|
-
const text = await res.text();
|
|
71
|
-
const dataLines = text
|
|
72
|
-
.split("\n")
|
|
73
|
-
.filter((l) => l.startsWith("data:"))
|
|
74
|
-
.map((l) => l.slice(5).trim())
|
|
75
|
-
.filter(Boolean);
|
|
76
|
-
if (!dataLines.length) throw new Error(`${method} → empty SSE body`);
|
|
77
|
-
payload = JSON.parse(dataLines[dataLines.length - 1]);
|
|
78
|
-
} else {
|
|
79
|
-
payload = await res.json();
|
|
80
|
-
}
|
|
81
|
-
if (payload.error) throw new Error(`${method} → JSON-RPC error: ${JSON.stringify(payload.error)}`);
|
|
82
|
-
return payload.result;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function parseToolText(callResult) {
|
|
86
|
-
const block = (callResult?.content || []).find((c) => c.type === "text");
|
|
87
|
-
return block ? JSON.parse(block.text) : null;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async function main() {
|
|
91
|
-
const failures = [];
|
|
92
|
-
const note = (ok, label) => {
|
|
93
|
-
console.log(`${ok ? "✓" : "✗"} ${label}`);
|
|
94
|
-
if (!ok) failures.push(label);
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// Handshake.
|
|
98
|
-
await rpc("initialize", {
|
|
99
|
-
protocolVersion: "2025-06-18",
|
|
100
|
-
capabilities: {},
|
|
101
|
-
clientInfo: { name: "openai-grouped-compose-smoke", version: "1.0.0" },
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// ---- tools/list ----------------------------------------------------------
|
|
105
|
-
const list = await rpc("tools/list", {});
|
|
106
|
-
const tools = list.tools || [];
|
|
107
|
-
const names = new Set(tools.map((t) => t.name));
|
|
108
|
-
|
|
109
|
-
// Invariant (1): 56 tools, meta-tools present.
|
|
110
|
-
note(tools.length === EXPECTED_TOTAL, `tools/list returns ${EXPECTED_TOTAL} tools (got ${tools.length})`);
|
|
111
|
-
for (const m of META_TOOLS) note(names.has(m), `meta-tool present: ${m}`);
|
|
112
|
-
const businessCount = tools.filter((t) => !META_TOOLS.includes(t.name)).length;
|
|
113
|
-
note(businessCount === EXPECTED_BUSINESS, `exactly ${EXPECTED_BUSINESS} reviewed business tools (got ${businessCount})`);
|
|
114
|
-
for (const leak of MUST_NOT_LEAK) note(!names.has(leak), `non-reviewed tool absent: ${leak}`);
|
|
115
|
-
|
|
116
|
-
// Meta-tools are read-only + closed-world.
|
|
117
|
-
for (const m of META_TOOLS) {
|
|
118
|
-
const t = tools.find((x) => x.name === m);
|
|
119
|
-
const ann = t?.annotations || {};
|
|
120
|
-
note(ann.readOnlyHint === true && ann.openWorldHint === false, `${m} is read-only + closed-world`);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Invariant (2): every business tool collapsed + carries openWorldHint rationale.
|
|
124
|
-
let collapsedOk = true;
|
|
125
|
-
let owOk = true;
|
|
126
|
-
for (const t of tools) {
|
|
127
|
-
if (META_TOOLS.includes(t.name)) continue;
|
|
128
|
-
const d = t.description || "";
|
|
129
|
-
if (!/^\[[a-z]+\] /.test(d) || !d.includes(`describe_tool('${t.name}')`)) collapsedOk = false;
|
|
130
|
-
if (!d.includes("openWorldHint")) owOk = false;
|
|
131
|
-
}
|
|
132
|
-
note(collapsedOk, "every reviewed tool has a collapsed [group] … describe_tool() description");
|
|
133
|
-
note(owOk, "every reviewed tool's collapsed description carries an openWorldHint rationale");
|
|
134
|
-
|
|
135
|
-
// Invariant (3): catalog only ever surfaces tools that are in tools/list.
|
|
136
|
-
const search = await rpc("tools/call", { name: "search_tools", arguments: { query: "", limit: 500 } });
|
|
137
|
-
const searchPayload = parseToolText(search);
|
|
138
|
-
const searchNames = (searchPayload?.tools || []).map((x) => x.name);
|
|
139
|
-
const searchLeaks = searchNames.filter((n) => !names.has(n));
|
|
140
|
-
note(searchLeaks.length === 0, `search_tools (browse-all) leaks nothing (leaks: ${searchLeaks.join(", ") || "none"})`);
|
|
141
|
-
note(
|
|
142
|
-
searchNames.length === EXPECTED_BUSINESS,
|
|
143
|
-
`search_tools browse-all returns the ${EXPECTED_BUSINESS} reviewed tools (got ${searchNames.length})`,
|
|
144
|
-
);
|
|
145
|
-
|
|
146
|
-
// A fiscal query must surface no non-reviewed tool.
|
|
147
|
-
const fiscal = await rpc("tools/call", { name: "search_tools", arguments: { query: "modelo 303 verifactu" } });
|
|
148
|
-
const fiscalNames = (parseToolText(fiscal)?.tools || []).map((x) => x.name);
|
|
149
|
-
note(fiscalNames.every((n) => names.has(n)), "search_tools('modelo 303') surfaces no non-reviewed tool");
|
|
150
|
-
|
|
151
|
-
// describe_tool rejects a non-reviewed tool.
|
|
152
|
-
const desc = await rpc("tools/call", { name: "describe_tool", arguments: { name: "get_quarterly_taxes" } });
|
|
153
|
-
note(desc?.isError === true, "describe_tool('get_quarterly_taxes') is rejected (not in reviewed catalog)");
|
|
154
|
-
|
|
155
|
-
// list_tool_groups totals 53.
|
|
156
|
-
const groups = await rpc("tools/call", { name: "list_tool_groups", arguments: {} });
|
|
157
|
-
const gPayload = parseToolText(groups);
|
|
158
|
-
note(gPayload?.totalTools === EXPECTED_BUSINESS, `list_tool_groups totalTools === ${EXPECTED_BUSINESS} (got ${gPayload?.totalTools})`);
|
|
159
|
-
|
|
160
|
-
console.log("");
|
|
161
|
-
if (failures.length) {
|
|
162
|
-
console.error(`FAIL — ${failures.length} invariant violation(s):`);
|
|
163
|
-
for (const f of failures) console.error(` - ${f}`);
|
|
164
|
-
process.exit(1);
|
|
165
|
-
}
|
|
166
|
-
console.log(`PASS — all ${EXPECTED_TOTAL}-tool composition invariants hold on ${ENDPOINT}`);
|
|
167
|
-
process.exit(0);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
main().catch((err) => {
|
|
171
|
-
console.error(`✗ transport/setup error: ${err.message}`);
|
|
172
|
-
process.exit(2);
|
|
173
|
-
});
|