plainstamp 0.6.0 → 0.7.1
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/CHANGELOG.md +15 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.js +9 -177
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp-tools.d.ts +53 -0
- package/dist/mcp-tools.d.ts.map +1 -0
- package/dist/mcp-tools.js +196 -0
- package/dist/mcp-tools.js.map +1 -0
- package/dist/rules-loader.d.ts +25 -3
- package/dist/rules-loader.d.ts.map +1 -1
- package/dist/rules-loader.js +31 -4
- package/dist/rules-loader.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
16
16
|
|
|
17
17
|
Distribution is **npm-only**. Source remains in the operating organization's private repository; there is no public source repository host. Contact channel for issues, accuracy reports, security reports, and contribution proposals is **helpfulbutton140@agentmail.to** (see `docs/CONTRIBUTING.md`, `docs/SECURITY.md`).
|
|
18
18
|
|
|
19
|
+
## [0.7.1] — 2026-05-08
|
|
20
|
+
|
|
21
|
+
### Fixed (cross-runtime compatibility)
|
|
22
|
+
|
|
23
|
+
- New `setBundledRules(parsed)` export: allows non-Node consumers (Cloudflare Workers, Deno Deploy, browsers) to pre-load the bundled rules object explicitly, avoiding the `node:fs` + `import.meta.url` path that fails in those environments. The recommended pattern is to import the JSON directly: `import rulesJson from "plainstamp/rules/seed.json"; setBundledRules(rulesJson);`. Once the override is set, all of `disclosuresFor`, `executeMcpTool`, `getRuleById`, `listJurisdictions`, etc. work unchanged.
|
|
24
|
+
- The Node fs path is unchanged for Node consumers; this is a strictly additive fix.
|
|
25
|
+
|
|
26
|
+
## [0.7.0] — 2026-05-08
|
|
27
|
+
|
|
28
|
+
### Added (transport-independent MCP tool module)
|
|
29
|
+
|
|
30
|
+
- New module `src/mcp-tools.ts` exporting `mcpTools` (the tool descriptors) and `executeMcpTool(name, args)` (the dispatcher). Both are now public API exports from the package root. Purpose: when the Cloudflare Workers cf-worker binds an MCP Streamable HTTP transport in Phase 4 of `<autobiz>/ops/cloudflare/CLOUDFLARE_DEPLOY.md`, it imports the same tool list and dispatcher used by the existing stdio transport. No drift between transports.
|
|
31
|
+
- `mcp-server.ts` (the stdio transport) is now a thin wrapper around `mcpTools` and `executeMcpTool`. Behavior is unchanged for stdio clients.
|
|
32
|
+
- Tests still 51/51 passing. Rule count unchanged at 23.
|
|
33
|
+
|
|
19
34
|
## [0.6.0] — 2026-05-08
|
|
20
35
|
|
|
21
36
|
### Added
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { lookup, generateDisclosureText, validateDisclosure, } from "./lookup.js";
|
|
2
|
-
export { loadBundledRules, loadRulesFromPath } from "./rules-loader.js";
|
|
2
|
+
export { loadBundledRules, loadRulesFromPath, setBundledRules, } from "./rules-loader.js";
|
|
3
3
|
export { computeCoverageMatrix, renderCoverageMarkdown, renderCoverageCsv, type CoverageMatrix, type CoverageCell, } from "./coverage.js";
|
|
4
4
|
export type { DisclosureRuleT, RuleSetT, LookupQueryT, LookupResultT, ChannelT, UseCaseT, SeverityT, JurisdictionIdT, DisclosureElementT, } from "./schema.js";
|
|
5
5
|
export { Channel, UseCase, Severity, JurisdictionId, LookupQuery, DisclosureElement, DisclosureRule, RuleSet, } from "./schema.js";
|
|
6
|
+
export { mcpTools, executeMcpTool, type McpToolDescriptor, type McpToolResult, } from "./mcp-tools.js";
|
|
6
7
|
import type { LookupQueryT, LookupResultT, DisclosureRuleT } from "./schema.js";
|
|
7
8
|
/**
|
|
8
9
|
* High-level convenience: load the bundled rules and look up disclosures for
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,eAAe,EACf,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,OAAO,EACP,OAAO,EACP,QAAQ,EACR,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,QAAQ,EACR,cAAc,EACd,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAC;AAIxB,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEhF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,EAAE,CAEnE;AAED,2EAA2E;AAC3E,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAK5C;AAED,uDAAuD;AACvD,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAGnE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,MAAM;;;;;IAKtB"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { lookup, generateDisclosureText, validateDisclosure, } from "./lookup.js";
|
|
2
|
-
export { loadBundledRules, loadRulesFromPath } from "./rules-loader.js";
|
|
2
|
+
export { loadBundledRules, loadRulesFromPath, setBundledRules, } from "./rules-loader.js";
|
|
3
3
|
export { computeCoverageMatrix, renderCoverageMarkdown, renderCoverageCsv, } from "./coverage.js";
|
|
4
4
|
export { Channel, UseCase, Severity, JurisdictionId, LookupQuery, DisclosureElement, DisclosureRule, RuleSet, } from "./schema.js";
|
|
5
|
+
export { mcpTools, executeMcpTool, } from "./mcp-tools.js";
|
|
5
6
|
import { loadBundledRules } from "./rules-loader.js";
|
|
6
7
|
import { lookup as lookupFn, validateDisclosure as validateFn } from "./lookup.js";
|
|
7
8
|
/**
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,GAGlB,MAAM,eAAe,CAAC;AAYvB,OAAO,EACL,OAAO,EACP,OAAO,EACP,QAAQ,EACR,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,QAAQ,EACR,cAAc,GAGf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,kBAAkB,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AAGnF;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAmB;IAChD,OAAO,QAAQ,CAAC,gBAAgB,EAAE,EAAE,KAAK,CAAC,CAAC;AAC7C,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,iBAAiB;IAC/B,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK;QAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC;IACjC,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACxC,KAAmB,EACnB,aAAqB;IAErB,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC;IACjC,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC1C,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC;AAClE,CAAC"}
|
package/dist/mcp-server.js
CHANGED
|
@@ -2,18 +2,12 @@
|
|
|
2
2
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
-
import {
|
|
6
|
-
import { Channel, LookupQuery, UseCase } from "./schema.js";
|
|
7
|
-
import { z } from "zod";
|
|
5
|
+
import { executeMcpTool, mcpTools } from "./mcp-tools.js";
|
|
8
6
|
/**
|
|
9
|
-
* MCP server exposing the
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* - list_rules -> returns rule summaries (id, jurisdiction, severity, title)
|
|
14
|
-
* - get_rule -> returns a single rule with full citation and template
|
|
15
|
-
* - lookup_disclosure -> primary tool: applicable rules + generated text for a (jurisdiction, channel, use_case)
|
|
16
|
-
* - validate_disclosure -> heuristic check that a candidate disclosure mentions a rule's required elements
|
|
7
|
+
* MCP server (stdio transport) exposing the plainstamp lookup engine
|
|
8
|
+
* to local agent runtimes. The tool surface is defined in
|
|
9
|
+
* `mcp-tools.ts` and is shared with any future HTTP / Streamable-HTTP
|
|
10
|
+
* MCP transport binding (e.g. the Cloudflare Workers wrapper).
|
|
17
11
|
*/
|
|
18
12
|
const server = new Server({
|
|
19
13
|
name: "plainstamp",
|
|
@@ -23,176 +17,14 @@ const server = new Server({
|
|
|
23
17
|
tools: {},
|
|
24
18
|
},
|
|
25
19
|
});
|
|
26
|
-
const ValidateInput = LookupQuery.extend({
|
|
27
|
-
candidate_text: z.string().min(1),
|
|
28
|
-
});
|
|
29
20
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
30
|
-
tools:
|
|
31
|
-
{
|
|
32
|
-
name: "list_jurisdictions",
|
|
33
|
-
description: "List all jurisdiction ids supported by the bundled rules. Use this first to discover what's covered before calling lookup_disclosure.",
|
|
34
|
-
inputSchema: {
|
|
35
|
-
type: "object",
|
|
36
|
-
properties: {},
|
|
37
|
-
additionalProperties: false,
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
name: "list_rules",
|
|
42
|
-
description: "List all bundled disclosure rules as compact summaries. Useful for browsing the rule database.",
|
|
43
|
-
inputSchema: {
|
|
44
|
-
type: "object",
|
|
45
|
-
properties: {},
|
|
46
|
-
additionalProperties: false,
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: "get_rule",
|
|
51
|
-
description: "Fetch a single disclosure rule by id, with full citation, required elements, templates, and last-verified date.",
|
|
52
|
-
inputSchema: {
|
|
53
|
-
type: "object",
|
|
54
|
-
properties: {
|
|
55
|
-
rule_id: { type: "string" },
|
|
56
|
-
},
|
|
57
|
-
required: ["rule_id"],
|
|
58
|
-
additionalProperties: false,
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
name: "lookup_disclosure",
|
|
63
|
-
description: "Primary tool. Given a jurisdiction (e.g. 'us-ca' or 'eu'), a channel (e.g. 'live-chat', 'ai-generated-content'), and a use case (e.g. 'b2c-customer-support'), return every applicable disclosure rule plus a generated plain-language and formal disclosure text. Results are sorted with mandatory rules first.",
|
|
64
|
-
inputSchema: {
|
|
65
|
-
type: "object",
|
|
66
|
-
properties: {
|
|
67
|
-
jurisdiction: {
|
|
68
|
-
type: "string",
|
|
69
|
-
description: "Lowercase jurisdiction id (ISO-style). Examples: 'us', 'us-ca', 'eu'.",
|
|
70
|
-
},
|
|
71
|
-
channel: {
|
|
72
|
-
type: "string",
|
|
73
|
-
enum: Channel.options,
|
|
74
|
-
},
|
|
75
|
-
use_case: {
|
|
76
|
-
type: "string",
|
|
77
|
-
enum: UseCase.options,
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
required: ["jurisdiction", "channel", "use_case"],
|
|
81
|
-
additionalProperties: false,
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
name: "validate_disclosure",
|
|
86
|
-
description: "Heuristic substring check that a candidate disclosure text mentions the required elements of every rule that applies to the (jurisdiction, channel, use_case). Returns a per-rule pass/fail report. NOT a legal-sufficiency determination — for high-stakes disclosures, verify against the cited regulator-published text and consult counsel.",
|
|
87
|
-
inputSchema: {
|
|
88
|
-
type: "object",
|
|
89
|
-
properties: {
|
|
90
|
-
jurisdiction: { type: "string" },
|
|
91
|
-
channel: { type: "string", enum: Channel.options },
|
|
92
|
-
use_case: { type: "string", enum: UseCase.options },
|
|
93
|
-
candidate_text: { type: "string", minLength: 1 },
|
|
94
|
-
},
|
|
95
|
-
required: ["jurisdiction", "channel", "use_case", "candidate_text"],
|
|
96
|
-
additionalProperties: false,
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
],
|
|
21
|
+
tools: mcpTools,
|
|
100
22
|
}));
|
|
101
23
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
102
24
|
const { name, arguments: args } = req.params;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return {
|
|
107
|
-
content: [
|
|
108
|
-
{ type: "text", text: JSON.stringify({ jurisdictions: ids }, null, 2) },
|
|
109
|
-
],
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
case "list_rules": {
|
|
113
|
-
const rules = loadBundledRules();
|
|
114
|
-
const summaries = rules.rules.map((r) => ({
|
|
115
|
-
id: r.id,
|
|
116
|
-
jurisdiction: r.jurisdiction,
|
|
117
|
-
severity: r.severity,
|
|
118
|
-
short_title: r.short_title,
|
|
119
|
-
channels: r.channels,
|
|
120
|
-
use_cases: r.use_cases,
|
|
121
|
-
last_verified: r.last_verified,
|
|
122
|
-
}));
|
|
123
|
-
return {
|
|
124
|
-
content: [
|
|
125
|
-
{
|
|
126
|
-
type: "text",
|
|
127
|
-
text: JSON.stringify({
|
|
128
|
-
schema_version: rules.schema_version,
|
|
129
|
-
generated_at: rules.generated_at,
|
|
130
|
-
rules: summaries,
|
|
131
|
-
}, null, 2),
|
|
132
|
-
},
|
|
133
|
-
],
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
case "get_rule": {
|
|
137
|
-
const ruleId = z.object({ rule_id: z.string() }).parse(args).rule_id;
|
|
138
|
-
const rule = getRuleById(ruleId);
|
|
139
|
-
if (rule === undefined) {
|
|
140
|
-
return {
|
|
141
|
-
isError: true,
|
|
142
|
-
content: [{ type: "text", text: `unknown rule_id: ${ruleId}` }],
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
return {
|
|
146
|
-
content: [{ type: "text", text: JSON.stringify(rule, null, 2) }],
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
case "lookup_disclosure": {
|
|
150
|
-
const parsed = LookupQuery.parse(args);
|
|
151
|
-
const results = disclosuresFor(parsed);
|
|
152
|
-
return {
|
|
153
|
-
content: [
|
|
154
|
-
{
|
|
155
|
-
type: "text",
|
|
156
|
-
text: JSON.stringify({
|
|
157
|
-
query: parsed,
|
|
158
|
-
disclaimer: "Informational only. Not legal advice. Each rule cites its source; verify against the regulator-published text before relying on it.",
|
|
159
|
-
count: results.length,
|
|
160
|
-
results,
|
|
161
|
-
}, null, 2),
|
|
162
|
-
},
|
|
163
|
-
],
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
case "validate_disclosure": {
|
|
167
|
-
const parsed = ValidateInput.parse(args);
|
|
168
|
-
const reports = validateDisclosureForQuery({
|
|
169
|
-
jurisdiction: parsed.jurisdiction,
|
|
170
|
-
channel: parsed.channel,
|
|
171
|
-
use_case: parsed.use_case,
|
|
172
|
-
}, parsed.candidate_text);
|
|
173
|
-
return {
|
|
174
|
-
content: [
|
|
175
|
-
{
|
|
176
|
-
type: "text",
|
|
177
|
-
text: JSON.stringify({
|
|
178
|
-
query: {
|
|
179
|
-
jurisdiction: parsed.jurisdiction,
|
|
180
|
-
channel: parsed.channel,
|
|
181
|
-
use_case: parsed.use_case,
|
|
182
|
-
},
|
|
183
|
-
disclaimer: "Heuristic substring check. NOT a legal-sufficiency determination.",
|
|
184
|
-
reports,
|
|
185
|
-
}, null, 2),
|
|
186
|
-
},
|
|
187
|
-
],
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
default:
|
|
191
|
-
return {
|
|
192
|
-
isError: true,
|
|
193
|
-
content: [{ type: "text", text: `unknown tool: ${name}` }],
|
|
194
|
-
};
|
|
195
|
-
}
|
|
25
|
+
// The SDK's response type union includes a task-style variant and the
|
|
26
|
+
// structured-content variant; our tools always return the latter.
|
|
27
|
+
return executeMcpTool(name, args);
|
|
196
28
|
});
|
|
197
29
|
const transport = new StdioServerTransport();
|
|
198
30
|
await server.connect(transport);
|
package/dist/mcp-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;;;GAKG;AAEH,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;IACE,IAAI,EAAE,YAAY;IAClB,OAAO,EAAE,OAAO;CACjB,EACD;IACE,YAAY,EAAE;QACZ,KAAK,EAAE,EAAE;KACV;CACF,CACF,CAAC;AAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK,EAAE,QAAQ;CAChB,CAAC,CAAC,CAAC;AAEJ,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IAC5D,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;IAC7C,sEAAsE;IACtE,kEAAkE;IAClE,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,CAE/B,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport-independent MCP tool surface for plainstamp.
|
|
3
|
+
*
|
|
4
|
+
* Exposes the same tool definitions and dispatch logic to:
|
|
5
|
+
* - the stdio MCP server (`mcp-server.ts`), which talks to local
|
|
6
|
+
* agent runtimes (Claude Code, Codex, etc.); and
|
|
7
|
+
* - any HTTP / Streamable-HTTP MCP transport binding (e.g. the
|
|
8
|
+
* Cloudflare Workers wrapper at `<autobiz>/ventures/plainstamp/cf-worker/`),
|
|
9
|
+
* which will be wired in Phase 4 of `<autobiz>/ops/cloudflare/CLOUDFLARE_DEPLOY.md`.
|
|
10
|
+
*
|
|
11
|
+
* Keeping the tool list and dispatcher in one place means stdio and
|
|
12
|
+
* HTTP transports cannot drift in their tool surface.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Shape returned by an MCP tool call. Mirrors the
|
|
16
|
+
* `CallToolResult` shape from the MCP TypeScript SDK so this module
|
|
17
|
+
* stays SDK-version-agnostic.
|
|
18
|
+
*/
|
|
19
|
+
export interface McpToolResult {
|
|
20
|
+
content: Array<{
|
|
21
|
+
type: "text";
|
|
22
|
+
text: string;
|
|
23
|
+
}>;
|
|
24
|
+
isError?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* MCP tool descriptor. Matches the shape registered with
|
|
28
|
+
* `ListToolsRequestSchema` in the MCP TypeScript SDK.
|
|
29
|
+
*/
|
|
30
|
+
export interface McpToolDescriptor {
|
|
31
|
+
name: string;
|
|
32
|
+
description: string;
|
|
33
|
+
inputSchema: {
|
|
34
|
+
type: "object";
|
|
35
|
+
properties: Record<string, unknown>;
|
|
36
|
+
required?: string[];
|
|
37
|
+
additionalProperties: false;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The full list of plainstamp tool descriptors. Pass this to a
|
|
42
|
+
* `ListToolsRequestSchema` handler.
|
|
43
|
+
*/
|
|
44
|
+
export declare const mcpTools: McpToolDescriptor[];
|
|
45
|
+
/**
|
|
46
|
+
* Dispatch an MCP tool call. Returns the canonical `McpToolResult`
|
|
47
|
+
* shape regardless of which transport invoked it.
|
|
48
|
+
*
|
|
49
|
+
* Unknown tool names return `{ isError: true }` rather than throwing,
|
|
50
|
+
* matching MCP's convention.
|
|
51
|
+
*/
|
|
52
|
+
export declare function executeMcpTool(name: string, args: unknown): McpToolResult;
|
|
53
|
+
//# sourceMappingURL=mcp-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-tools.d.ts","sourceRoot":"","sources":["../src/mcp-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,oBAAoB,EAAE,KAAK,CAAC;KAC7B,CAAC;CACH;AAMD;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,iBAAiB,EA2EvC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,GACZ,aAAa,CAoHf"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport-independent MCP tool surface for plainstamp.
|
|
3
|
+
*
|
|
4
|
+
* Exposes the same tool definitions and dispatch logic to:
|
|
5
|
+
* - the stdio MCP server (`mcp-server.ts`), which talks to local
|
|
6
|
+
* agent runtimes (Claude Code, Codex, etc.); and
|
|
7
|
+
* - any HTTP / Streamable-HTTP MCP transport binding (e.g. the
|
|
8
|
+
* Cloudflare Workers wrapper at `<autobiz>/ventures/plainstamp/cf-worker/`),
|
|
9
|
+
* which will be wired in Phase 4 of `<autobiz>/ops/cloudflare/CLOUDFLARE_DEPLOY.md`.
|
|
10
|
+
*
|
|
11
|
+
* Keeping the tool list and dispatcher in one place means stdio and
|
|
12
|
+
* HTTP transports cannot drift in their tool surface.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
import { disclosuresFor, getRuleById, listJurisdictions, loadBundledRules, validateDisclosureForQuery, } from "./index.js";
|
|
16
|
+
import { Channel, LookupQuery, UseCase } from "./schema.js";
|
|
17
|
+
const ValidateInput = LookupQuery.extend({
|
|
18
|
+
candidate_text: z.string().min(1),
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* The full list of plainstamp tool descriptors. Pass this to a
|
|
22
|
+
* `ListToolsRequestSchema` handler.
|
|
23
|
+
*/
|
|
24
|
+
export const mcpTools = [
|
|
25
|
+
{
|
|
26
|
+
name: "list_jurisdictions",
|
|
27
|
+
description: "List all jurisdiction ids supported by the bundled rules. Use this first to discover what's covered before calling lookup_disclosure.",
|
|
28
|
+
inputSchema: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {},
|
|
31
|
+
additionalProperties: false,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "list_rules",
|
|
36
|
+
description: "List all bundled disclosure rules as compact summaries. Useful for browsing the rule database.",
|
|
37
|
+
inputSchema: {
|
|
38
|
+
type: "object",
|
|
39
|
+
properties: {},
|
|
40
|
+
additionalProperties: false,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "get_rule",
|
|
45
|
+
description: "Fetch a single disclosure rule by id, with full citation, required elements, templates, and last-verified date.",
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
rule_id: { type: "string" },
|
|
50
|
+
},
|
|
51
|
+
required: ["rule_id"],
|
|
52
|
+
additionalProperties: false,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "lookup_disclosure",
|
|
57
|
+
description: "Primary tool. Given a jurisdiction (e.g. 'us-ca' or 'eu'), a channel (e.g. 'live-chat', 'ai-generated-content'), and a use case (e.g. 'b2c-customer-support'), return every applicable disclosure rule plus a generated plain-language and formal disclosure text. Results are sorted with mandatory rules first.",
|
|
58
|
+
inputSchema: {
|
|
59
|
+
type: "object",
|
|
60
|
+
properties: {
|
|
61
|
+
jurisdiction: {
|
|
62
|
+
type: "string",
|
|
63
|
+
description: "Lowercase jurisdiction id (ISO-style). Examples: 'us', 'us-ca', 'eu'.",
|
|
64
|
+
},
|
|
65
|
+
channel: {
|
|
66
|
+
type: "string",
|
|
67
|
+
enum: Channel.options,
|
|
68
|
+
},
|
|
69
|
+
use_case: {
|
|
70
|
+
type: "string",
|
|
71
|
+
enum: UseCase.options,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
required: ["jurisdiction", "channel", "use_case"],
|
|
75
|
+
additionalProperties: false,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "validate_disclosure",
|
|
80
|
+
description: "Heuristic substring check that a candidate disclosure text mentions the required elements of every rule that applies to the (jurisdiction, channel, use_case). Returns a per-rule pass/fail report. NOT a legal-sufficiency determination — for high-stakes disclosures, verify against the cited regulator-published text and consult counsel.",
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: "object",
|
|
83
|
+
properties: {
|
|
84
|
+
jurisdiction: { type: "string" },
|
|
85
|
+
channel: { type: "string", enum: Channel.options },
|
|
86
|
+
use_case: { type: "string", enum: UseCase.options },
|
|
87
|
+
candidate_text: { type: "string", minLength: 1 },
|
|
88
|
+
},
|
|
89
|
+
required: ["jurisdiction", "channel", "use_case", "candidate_text"],
|
|
90
|
+
additionalProperties: false,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
/**
|
|
95
|
+
* Dispatch an MCP tool call. Returns the canonical `McpToolResult`
|
|
96
|
+
* shape regardless of which transport invoked it.
|
|
97
|
+
*
|
|
98
|
+
* Unknown tool names return `{ isError: true }` rather than throwing,
|
|
99
|
+
* matching MCP's convention.
|
|
100
|
+
*/
|
|
101
|
+
export function executeMcpTool(name, args) {
|
|
102
|
+
switch (name) {
|
|
103
|
+
case "list_jurisdictions": {
|
|
104
|
+
const ids = listJurisdictions();
|
|
105
|
+
return {
|
|
106
|
+
content: [
|
|
107
|
+
{ type: "text", text: JSON.stringify({ jurisdictions: ids }, null, 2) },
|
|
108
|
+
],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
case "list_rules": {
|
|
112
|
+
const rules = loadBundledRules();
|
|
113
|
+
const summaries = rules.rules.map((r) => ({
|
|
114
|
+
id: r.id,
|
|
115
|
+
jurisdiction: r.jurisdiction,
|
|
116
|
+
severity: r.severity,
|
|
117
|
+
short_title: r.short_title,
|
|
118
|
+
channels: r.channels,
|
|
119
|
+
use_cases: r.use_cases,
|
|
120
|
+
last_verified: r.last_verified,
|
|
121
|
+
}));
|
|
122
|
+
return {
|
|
123
|
+
content: [
|
|
124
|
+
{
|
|
125
|
+
type: "text",
|
|
126
|
+
text: JSON.stringify({
|
|
127
|
+
schema_version: rules.schema_version,
|
|
128
|
+
generated_at: rules.generated_at,
|
|
129
|
+
rules: summaries,
|
|
130
|
+
}, null, 2),
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
case "get_rule": {
|
|
136
|
+
const ruleId = z.object({ rule_id: z.string() }).parse(args).rule_id;
|
|
137
|
+
const rule = getRuleById(ruleId);
|
|
138
|
+
if (rule === undefined) {
|
|
139
|
+
return {
|
|
140
|
+
isError: true,
|
|
141
|
+
content: [{ type: "text", text: `unknown rule_id: ${ruleId}` }],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
content: [{ type: "text", text: JSON.stringify(rule, null, 2) }],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
case "lookup_disclosure": {
|
|
149
|
+
const parsed = LookupQuery.parse(args);
|
|
150
|
+
const results = disclosuresFor(parsed);
|
|
151
|
+
return {
|
|
152
|
+
content: [
|
|
153
|
+
{
|
|
154
|
+
type: "text",
|
|
155
|
+
text: JSON.stringify({
|
|
156
|
+
query: parsed,
|
|
157
|
+
disclaimer: "Informational only. Not legal advice. Each rule cites its source; verify against the regulator-published text before relying on it.",
|
|
158
|
+
count: results.length,
|
|
159
|
+
results,
|
|
160
|
+
}, null, 2),
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
case "validate_disclosure": {
|
|
166
|
+
const parsed = ValidateInput.parse(args);
|
|
167
|
+
const reports = validateDisclosureForQuery({
|
|
168
|
+
jurisdiction: parsed.jurisdiction,
|
|
169
|
+
channel: parsed.channel,
|
|
170
|
+
use_case: parsed.use_case,
|
|
171
|
+
}, parsed.candidate_text);
|
|
172
|
+
return {
|
|
173
|
+
content: [
|
|
174
|
+
{
|
|
175
|
+
type: "text",
|
|
176
|
+
text: JSON.stringify({
|
|
177
|
+
query: {
|
|
178
|
+
jurisdiction: parsed.jurisdiction,
|
|
179
|
+
channel: parsed.channel,
|
|
180
|
+
use_case: parsed.use_case,
|
|
181
|
+
},
|
|
182
|
+
disclaimer: "Heuristic substring check. NOT a legal-sufficiency determination.",
|
|
183
|
+
reports,
|
|
184
|
+
}, null, 2),
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
default:
|
|
190
|
+
return {
|
|
191
|
+
isError: true,
|
|
192
|
+
content: [{ type: "text", text: `unknown tool: ${name}` }],
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=mcp-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-tools.js","sourceRoot":"","sources":["../src/mcp-tools.ts"],"names":[],"mappings":"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"}
|
package/dist/rules-loader.d.ts
CHANGED
|
@@ -1,8 +1,30 @@
|
|
|
1
1
|
import { type RuleSetT } from "./schema.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Provide the bundled rules object explicitly. Useful in environments
|
|
4
|
+
* where `import.meta.url`-based filesystem reads are unavailable or
|
|
5
|
+
* unreliable (Cloudflare Workers, Deno Deploy, browsers): the caller
|
|
6
|
+
* imports `plainstamp/rules/seed.json` directly and hands the parsed
|
|
7
|
+
* object to this function before any other plainstamp lookup.
|
|
8
|
+
*
|
|
9
|
+
* Idempotent. Calling with `null` clears the override.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* import rulesJson from "plainstamp/rules/seed.json";
|
|
13
|
+
* import { setBundledRules, executeMcpTool } from "plainstamp";
|
|
14
|
+
* setBundledRules(rulesJson);
|
|
15
|
+
*/
|
|
16
|
+
export declare function setBundledRules(rules: unknown | null): void;
|
|
17
|
+
/**
|
|
18
|
+
* Loads and validates the bundled seed rules. If `setBundledRules()`
|
|
19
|
+
* has been called, returns that override. Otherwise reads from the
|
|
20
|
+
* package's `rules/seed.json` file via `node:fs` + `import.meta.url`.
|
|
21
|
+
*
|
|
22
|
+
* Throws on schema violation — an invalid rules file is a hard
|
|
23
|
+
* failure because the product's correctness depends on it.
|
|
24
|
+
*
|
|
25
|
+
* In non-Node environments (Workers, browsers), `import.meta.url` may
|
|
26
|
+
* not resolve to a usable path; in that case, callers MUST set the
|
|
27
|
+
* override via `setBundledRules()` before any lookup.
|
|
6
28
|
*/
|
|
7
29
|
export declare function loadBundledRules(): RuleSetT;
|
|
8
30
|
/** Loads rules from an arbitrary path. Useful for tests and for callers that maintain their own rules feed. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules-loader.d.ts","sourceRoot":"","sources":["../src/rules-loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIrD
|
|
1
|
+
{"version":3,"file":"rules-loader.d.ts","sourceRoot":"","sources":["../src/rules-loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIrD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAE3D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,IAAI,QAAQ,CAO3C;AAED,+GAA+G;AAC/G,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAIxD"}
|
package/dist/rules-loader.js
CHANGED
|
@@ -2,13 +2,40 @@ import { readFileSync } from "node:fs";
|
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { RuleSet } from "./schema.js";
|
|
5
|
-
|
|
5
|
+
let bundledRulesOverride = null;
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Provide the bundled rules object explicitly. Useful in environments
|
|
8
|
+
* where `import.meta.url`-based filesystem reads are unavailable or
|
|
9
|
+
* unreliable (Cloudflare Workers, Deno Deploy, browsers): the caller
|
|
10
|
+
* imports `plainstamp/rules/seed.json` directly and hands the parsed
|
|
11
|
+
* object to this function before any other plainstamp lookup.
|
|
12
|
+
*
|
|
13
|
+
* Idempotent. Calling with `null` clears the override.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* import rulesJson from "plainstamp/rules/seed.json";
|
|
17
|
+
* import { setBundledRules, executeMcpTool } from "plainstamp";
|
|
18
|
+
* setBundledRules(rulesJson);
|
|
19
|
+
*/
|
|
20
|
+
export function setBundledRules(rules) {
|
|
21
|
+
bundledRulesOverride = rules === null ? null : RuleSet.parse(rules);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Loads and validates the bundled seed rules. If `setBundledRules()`
|
|
25
|
+
* has been called, returns that override. Otherwise reads from the
|
|
26
|
+
* package's `rules/seed.json` file via `node:fs` + `import.meta.url`.
|
|
27
|
+
*
|
|
28
|
+
* Throws on schema violation — an invalid rules file is a hard
|
|
29
|
+
* failure because the product's correctness depends on it.
|
|
30
|
+
*
|
|
31
|
+
* In non-Node environments (Workers, browsers), `import.meta.url` may
|
|
32
|
+
* not resolve to a usable path; in that case, callers MUST set the
|
|
33
|
+
* override via `setBundledRules()` before any lookup.
|
|
10
34
|
*/
|
|
11
35
|
export function loadBundledRules() {
|
|
36
|
+
if (bundledRulesOverride !== null)
|
|
37
|
+
return bundledRulesOverride;
|
|
38
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
12
39
|
const path = join(here, "..", "rules", "seed.json");
|
|
13
40
|
const raw = readFileSync(path, "utf-8");
|
|
14
41
|
const parsed = JSON.parse(raw);
|
package/dist/rules-loader.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules-loader.js","sourceRoot":"","sources":["../src/rules-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAiB,MAAM,aAAa,CAAC;AAErD,
|
|
1
|
+
{"version":3,"file":"rules-loader.js","sourceRoot":"","sources":["../src/rules-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAiB,MAAM,aAAa,CAAC;AAErD,IAAI,oBAAoB,GAAoB,IAAI,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,KAAqB;IACnD,oBAAoB,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,oBAAoB,KAAK,IAAI;QAAE,OAAO,oBAAoB,CAAC;IAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plainstamp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "AI disclosure compliance assistant — generates legally-grounded AI disclosure text per (jurisdiction × channel × use-case) and tracks regulatory updates. Operated by an autonomous AI agent under KS Elevated Solutions LLC.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|