New:Socket for Asana Is Now Available.Learn more
Get Started

@toolstop/export-control

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@toolstop/export-control - npm Package Compare versions

Comparing version
0.1.0
to
0.2.0
+31
-0
dist/lib.mjs

@@ -112,2 +112,30 @@ // Licence-requirement lookup against the Commerce Country Chart.

/**
* An entry with no controls in the data is a question this server cannot
* answer, and it must never come back as `licenseRequired: false`.
*
* Two different things produce one: an entry whose licence requirements are
* written as prose rather than as a country-chart table (0A983 reads "a license
* is required for ALL destinations", which is the opposite of no licence), and
* an entry that is a pointer to the ITAR and carries no EAR requirement at all
* (0A002). Both are real, controlled items. Neither can be answered from an
* empty control list, and `false` computed from an empty array is not a finding
* about the regulation, it is the absence of one.
*/
function indeterminateResult(eccn, entry) {
return {
status: "indeterminate",
eccn,
title: entry.t,
reasons: (entry.r ?? []).map((r) => ({ code: r, name: REASON_CODES[r] ?? null })),
message:
`${eccn} carries no country-chart control in the ${SOURCE_EDITION} data, so the chart cannot ` +
"answer for it. Do not read this as no licence required: entries in this state include items " +
"requiring a licence to all destinations, and items that are subject to the ITAR rather than " +
"the EAR. Read the entry directly in 15 CFR part 774, Supplement No. 1, and check the title " +
"returned here, which often states the requirement.",
notCovered: NOT_COVERED,
};
}
/** Every caveat that a chart answer does not cover. Attached to every result. */

@@ -172,2 +200,4 @@ const NOT_COVERED = [

if (!entry.c.length) return indeterminateResult(eccn, entry);
const marks = new Set(row.c);

@@ -204,2 +234,3 @@ const triggered = [];

if (!e) return { status: "unknown_eccn", eccn, message: `${eccn} is not in the ${SOURCE_EDITION} Commerce Control List.` };
if (!e.c.length) return { ...indeterminateResult(eccn, e), chartDetermined: false, sourceEdition: SOURCE_EDITION };
return {

@@ -206,0 +237,0 @@ status: "ok",

+31
-6

@@ -15,2 +15,3 @@ // The single source of truth for this server. Both transports import this and

"embargoed",
"indeterminate",
"invalid_eccn",

@@ -28,4 +29,6 @@ "unknown_eccn",

"Outcome of the lookup. Only `ok` carries an answer. `embargoed` means the " +
"chart does not govern the destination. `ambiguous_country` means the name " +
"matched more than one row and you must ask which was meant.",
"chart does not govern the destination. `indeterminate` means the entry has " +
"no country-chart control in this data and the chart cannot answer for it, " +
"which is not the same as no licence being required. `ambiguous_country` " +
"means the name matched more than one row and you must ask which was meant.",
};

@@ -35,3 +38,3 @@

name: "export-control",
version: "0.1.0",
version: "0.2.0",
instructions:

@@ -62,2 +65,9 @@ "Answers one question: does the Commerce Country Chart require an export " +

"you should put that choice to a human rather than picking.\n\n" +
"Some entries write their licence requirement as prose rather than as a " +
"chart column, and some are pointers to the ITAR carrying no EAR " +
"requirement at all. Those return `indeterminate` rather than an answer, " +
"because a chart verdict computed from an entry with no chart controls " +
"would read as `licenseRequired: false` for items that in fact require a " +
"licence to every destination. Treat `indeterminate` as unanswered and go " +
"to the regulation.\n\n" +
"A result of `licenseRequired: false` means only that the country chart " +

@@ -87,4 +97,6 @@ "does not require one for that ECCN. It is not permission to export. The " +

"about the Entity List, embargoes, end-use controls, or whether the " +
"ECCN is the right one. This tool cannot classify an item into an " +
"ECCN and will not try.",
"ECCN is the right one. Entries whose requirement is not written as a " +
"chart column return `indeterminate` instead of a verdict, and that is " +
"an unanswered question rather than a negative answer. This tool cannot " +
"classify an item into an ECCN and will not try.",
annotations: { readOnlyHint: true, openWorldHint: false },

@@ -140,2 +152,4 @@ inputSchema: {

},
title: { type: "string", description: "The Control List entry heading, on an indeterminate result." },
message: { type: "string", description: "Why no verdict was returned, when status is not `ok`." },
},

@@ -150,2 +164,8 @@ required: ["status"],

{
// The requirement is "a license is required for ALL destinations",
// written as prose. An empty control list must not become `false`.
args: { eccn: "0A983", country: "France" },
expect: { status: "indeterminate", eccn: "0A983" },
},
{
args: { eccn: "3A001", country: "Canada" },

@@ -180,3 +200,4 @@ expect: { status: "ok", licenseRequired: false },

"decided by the country chart at all, and those return " +
"`chartDetermined: false` with the requirement text instead. Knowing an " +
"`chartDetermined: false` with the requirement text instead, or " +
"`indeterminate` when the entry carries no chart control at all. Knowing an " +
"entry's reasons for control does not tell you whether a licence is " +

@@ -226,2 +247,6 @@ "required for a destination; pass the ECCN to check_export_license for " +

},
{
args: { eccn: "0A002" }, // present, but a pointer to the ITAR
expect: { status: "indeterminate", chartDetermined: false },
},
],

@@ -228,0 +253,0 @@ handler: ({ eccn }) => lookupEccn(eccn),

+1
-1
{
"name": "@toolstop/export-control",
"version": "0.1.0",
"version": "0.2.0",
"mcpName": "dev.toolstop/export-control",

@@ -5,0 +5,0 @@ "description": "MCP server that answers whether the US Commerce Country Chart requires an export licence for a given ECCN to a given destination, from the published CFR tables.",