product-spec-mcp 0.3.20 → 0.3.21
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/dist/index.cjs +101 -17
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7,7 +7,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
9
|
var __commonJS = (cb, mod) => function __require() {
|
|
10
|
-
|
|
10
|
+
try {
|
|
11
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw mod = 0, e;
|
|
14
|
+
}
|
|
11
15
|
};
|
|
12
16
|
var __export = (target, all) => {
|
|
13
17
|
for (var name in all)
|
|
@@ -6936,7 +6940,6 @@ function $constructor(name, initializer3, params) {
|
|
|
6936
6940
|
Object.defineProperty(_, "name", { value: name });
|
|
6937
6941
|
return _;
|
|
6938
6942
|
}
|
|
6939
|
-
var $brand = Symbol("zod_brand");
|
|
6940
6943
|
var $ZodAsyncError = class extends Error {
|
|
6941
6944
|
constructor() {
|
|
6942
6945
|
super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
|
|
@@ -9440,8 +9443,6 @@ function en_default() {
|
|
|
9440
9443
|
}
|
|
9441
9444
|
|
|
9442
9445
|
// node_modules/zod/v4/core/registries.js
|
|
9443
|
-
var $output = Symbol("ZodOutput");
|
|
9444
|
-
var $input = Symbol("ZodInput");
|
|
9445
9446
|
var $ZodRegistry = class {
|
|
9446
9447
|
constructor() {
|
|
9447
9448
|
this._map = /* @__PURE__ */ new Map();
|
|
@@ -16838,7 +16839,7 @@ ZodNaN.create = (params) => {
|
|
|
16838
16839
|
...processCreateParams(params)
|
|
16839
16840
|
});
|
|
16840
16841
|
};
|
|
16841
|
-
var BRAND = Symbol("zod_brand");
|
|
16842
|
+
var BRAND = /* @__PURE__ */ Symbol("zod_brand");
|
|
16842
16843
|
var ZodBranded = class extends ZodType2 {
|
|
16843
16844
|
_parse(input) {
|
|
16844
16845
|
const { ctx } = this._processInputParams(input);
|
|
@@ -17247,7 +17248,7 @@ function isTerminal(status) {
|
|
|
17247
17248
|
}
|
|
17248
17249
|
|
|
17249
17250
|
// node_modules/zod-to-json-schema/dist/esm/Options.js
|
|
17250
|
-
var ignoreOverride = Symbol("Let zodToJsonSchema decide on which parser to use");
|
|
17251
|
+
var ignoreOverride = /* @__PURE__ */ Symbol("Let zodToJsonSchema decide on which parser to use");
|
|
17251
17252
|
var defaultOptions = {
|
|
17252
17253
|
name: void 0,
|
|
17253
17254
|
$refStrategy: "root",
|
|
@@ -20223,7 +20224,7 @@ var Server = class extends Protocol {
|
|
|
20223
20224
|
};
|
|
20224
20225
|
|
|
20225
20226
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/completable.js
|
|
20226
|
-
var COMPLETABLE_SYMBOL = Symbol.for("mcp.completable");
|
|
20227
|
+
var COMPLETABLE_SYMBOL = /* @__PURE__ */ Symbol.for("mcp.completable");
|
|
20227
20228
|
function isCompletable(schema) {
|
|
20228
20229
|
return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema;
|
|
20229
20230
|
}
|
|
@@ -23537,6 +23538,79 @@ var SpecCompileOutputSchema = external_exports.object({
|
|
|
23537
23538
|
})
|
|
23538
23539
|
});
|
|
23539
23540
|
|
|
23541
|
+
// src/core/localToolSignals.ts
|
|
23542
|
+
function buildLocalToolSignalProfile(text) {
|
|
23543
|
+
const recordObject = extractRecordObject(text);
|
|
23544
|
+
const fieldLabels = buildFieldLabels(text, recordObject);
|
|
23545
|
+
const featureHints = buildFeatureHints(text, recordObject);
|
|
23546
|
+
const acceptanceItems = buildAcceptanceItems(text, recordObject, fieldLabels);
|
|
23547
|
+
return {
|
|
23548
|
+
recordObject,
|
|
23549
|
+
fieldExample: fieldLabels.join("\u3001"),
|
|
23550
|
+
featureHints,
|
|
23551
|
+
acceptanceItems
|
|
23552
|
+
};
|
|
23553
|
+
}
|
|
23554
|
+
function extractRecordObject(text) {
|
|
23555
|
+
if (/药品|药箱|药/.test(text)) return "\u836F\u54C1";
|
|
23556
|
+
const patterns = [
|
|
23557
|
+
/(?:做一个|做个|开发一个|创建一个|想做一个|想做个)([^,。,.;;]{1,16}?)(?:管理工具|提醒工具|记录工具|清单|小工具|页面|网页|HTML)/i,
|
|
23558
|
+
/记录(?:家里有哪些)?([^,。,.;;、和]{1,12})/
|
|
23559
|
+
];
|
|
23560
|
+
for (const pattern of patterns) {
|
|
23561
|
+
const match = text.match(pattern);
|
|
23562
|
+
const value = cleanObjectLabel(match?.[1]);
|
|
23563
|
+
if (value) return value;
|
|
23564
|
+
}
|
|
23565
|
+
return "\u8BB0\u5F55";
|
|
23566
|
+
}
|
|
23567
|
+
function cleanObjectLabel(value) {
|
|
23568
|
+
if (!value) return "";
|
|
23569
|
+
return value.replace(/^(家庭|个人|家里|我的|一个|一款)/, "").replace(/(管理|提醒|记录|清单|工具|页面|网页|HTML)$/i, "").trim();
|
|
23570
|
+
}
|
|
23571
|
+
function buildFieldLabels(text, recordObject) {
|
|
23572
|
+
const labels = [`${recordObject}\u540D`];
|
|
23573
|
+
addIf(labels, "\u6570\u91CF/\u5E93\u5B58", /数量|库存|余量|剩余|补货/.test(text));
|
|
23574
|
+
addIf(labels, "\u6709\u6548\u671F/\u5230\u671F\u65E5", /有效期|过期|临期|到期|截止|保质期|续费|提醒/.test(text));
|
|
23575
|
+
addIf(labels, "\u5206\u7C7B", /分类|类别|标签|类型/.test(text));
|
|
23576
|
+
addIf(labels, "\u5B58\u653E\u4F4D\u7F6E", /位置|存放|放在|地点|地址/.test(text));
|
|
23577
|
+
addIf(labels, "\u72B6\u6001", /状态|进度|已完成|未完成|正常|异常/.test(text));
|
|
23578
|
+
addIf(labels, "\u91D1\u989D/\u4EF7\u683C", /金额|价格|费用|预算|保费/.test(text));
|
|
23579
|
+
addIf(labels, "\u94FE\u63A5", /链接|网址|URL/i.test(text));
|
|
23580
|
+
labels.push("\u5907\u6CE8");
|
|
23581
|
+
return Array.from(new Set(labels));
|
|
23582
|
+
}
|
|
23583
|
+
function buildFeatureHints(text, recordObject) {
|
|
23584
|
+
const hints = [];
|
|
23585
|
+
if (/记录|管理|保存|清单|列表/.test(text)) hints.push(`${recordObject}\u8BB0\u5F55\u7BA1\u7406`);
|
|
23586
|
+
if (/新增|添加|编辑|删除|增删改查|CRUD/i.test(text)) hints.push("\u65B0\u589E/\u7F16\u8F91/\u5220\u9664");
|
|
23587
|
+
if (/搜索|筛选|分类|标签|查询/.test(text)) hints.push("\u641C\u7D22/\u7B5B\u9009/\u5206\u7C7B");
|
|
23588
|
+
if (/提醒|到期|过期|临期|快过期|截止|倒计时|保质期|续费/.test(text)) hints.push("\u5230\u671F/\u8FC7\u671F\u63D0\u9192");
|
|
23589
|
+
if (/数量|库存|余量|剩余|补货/.test(text)) hints.push("\u6570\u91CF/\u5E93\u5B58\u7BA1\u7406");
|
|
23590
|
+
if (/高级|好看|美观|视觉|界面|页面|UI|ui|响应式/.test(text)) hints.push("\u9AD8\u7EA7\u754C\u9762\u4E0E\u54CD\u5E94\u5F0F\u5E03\u5C40");
|
|
23591
|
+
return Array.from(new Set(hints));
|
|
23592
|
+
}
|
|
23593
|
+
function buildAcceptanceItems(text, recordObject, fieldLabels) {
|
|
23594
|
+
const items = [];
|
|
23595
|
+
if (/记录|管理|保存|清单|列表/.test(text)) {
|
|
23596
|
+
items.push(`${recordObject}\u8BB0\u5F55\u80FD\u4FDD\u5B58${fieldLabels.join("\u3001")}`);
|
|
23597
|
+
}
|
|
23598
|
+
if (/提醒|到期|过期|临期|快过期|截止|保质期|续费/.test(text)) {
|
|
23599
|
+
items.push("\u63D0\u9192\u5217\u8868\u80FD\u6309\u65E5\u671F\u6392\u5E8F\uFF0C\u5DF2\u8FC7\u671F\u3001\u5373\u5C06\u5230\u671F\u548C\u6B63\u5E38\u72B6\u6001\u6E05\u6670");
|
|
23600
|
+
items.push("\u7F16\u8F91\u6216\u5220\u9664\u8BB0\u5F55\u540E\uFF0C\u63D0\u9192\u5217\u8868\u540C\u6B65\u66F4\u65B0");
|
|
23601
|
+
}
|
|
23602
|
+
if (/数量|库存|余量|剩余|补货/.test(text)) {
|
|
23603
|
+
items.push("\u6570\u91CF\u6216\u5E93\u5B58\u53D8\u5316\u540E\uFF0C\u5217\u8868\u3001\u8BE6\u60C5\u548C\u63D0\u9192\u72B6\u6001\u540C\u6B65\u66F4\u65B0");
|
|
23604
|
+
}
|
|
23605
|
+
if (/高级|好看|美观|视觉|界面|页面|UI|ui|响应式/.test(text)) {
|
|
23606
|
+
items.push("\u9875\u9762\u89C6\u89C9\u98CE\u683C\u4E00\u81F4\uFF0C\u684C\u9762\u7AEF\u548C\u79FB\u52A8\u7AEF\u90FD\u4E0D\u80FD\u51FA\u73B0\u6587\u5B57\u6EA2\u51FA\u6216\u63A7\u4EF6\u91CD\u53E0");
|
|
23607
|
+
}
|
|
23608
|
+
return items;
|
|
23609
|
+
}
|
|
23610
|
+
function addIf(items, label, condition) {
|
|
23611
|
+
if (condition) items.push(label);
|
|
23612
|
+
}
|
|
23613
|
+
|
|
23540
23614
|
// src/core/promptBuilder.ts
|
|
23541
23615
|
function buildSpec(rawIdea, context, readiness) {
|
|
23542
23616
|
const assumptions = [];
|
|
@@ -23582,7 +23656,8 @@ function buildSpec(rawIdea, context, readiness) {
|
|
|
23582
23656
|
assumptions.push("\u76EE\u6807\u7528\u6237\uFF1A\u9ED8\u8BA4\u4E3A\u4E2A\u4EBA\u7528\u6237");
|
|
23583
23657
|
}
|
|
23584
23658
|
const platform = normalizedContext.platform || extractPlatform(rawIdea) || "web";
|
|
23585
|
-
const
|
|
23659
|
+
const extractedFeatures = personalLocalTool ? buildLocalFirstExtractedFeatures(rawIdea) : extractFeatures(rawIdea);
|
|
23660
|
+
const coreFeatures = hasStructuredAnswers ? buildGenericCoreFeatures(normalizedContext, extractedFeatures) : toArray(normalizedContext.core_features, extractedFeatures);
|
|
23586
23661
|
const isGenericFeatures = coreFeatures.length === 1 && coreFeatures[0] === "\u6838\u5FC3\u529F\u80FD";
|
|
23587
23662
|
if (isGenericFeatures) {
|
|
23588
23663
|
assumptions.push("\u6838\u5FC3\u529F\u80FD\uFF1A\u672A\u8BC6\u522B\u5230\u5177\u4F53\u529F\u80FD\uFF0C\u9700\u8981\u7528\u6237\u8865\u5145");
|
|
@@ -24745,6 +24820,12 @@ function extractFeatures(text) {
|
|
|
24745
24820
|
}
|
|
24746
24821
|
return features.length > 0 ? features : ["\u6838\u5FC3\u529F\u80FD"];
|
|
24747
24822
|
}
|
|
24823
|
+
function buildLocalFirstExtractedFeatures(text) {
|
|
24824
|
+
const genericFeatures = extractFeatures(text).filter((feature) => feature !== "\u6838\u5FC3\u529F\u80FD");
|
|
24825
|
+
const signalProfile = buildLocalToolSignalProfile(text);
|
|
24826
|
+
const features = [...genericFeatures, ...signalProfile.featureHints];
|
|
24827
|
+
return features.length > 0 ? Array.from(new Set(features)) : ["\u6838\u5FC3\u529F\u80FD"];
|
|
24828
|
+
}
|
|
24748
24829
|
function isNegatedKeyword(text, keyword) {
|
|
24749
24830
|
const escaped = keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
24750
24831
|
return new RegExp(`(\u4E0D\u63A5|\u4E0D\u505A|\u4E0D\u7528|\u65E0\u9700|\u4E0D\u9700\u8981|\u6682\u4E0D|\u5148\u4E0D|\u4E0D\u8981|\u6CA1\u6709).{0,8}${escaped}`, "i").test(text);
|
|
@@ -26649,7 +26730,7 @@ function buildLocalFirstAcceptanceCategories(technicalProfile, productType, feat
|
|
|
26649
26730
|
}
|
|
26650
26731
|
function buildGenericToolAcceptanceItems(productType, features) {
|
|
26651
26732
|
const text = buildFeatureText(productType, features);
|
|
26652
|
-
const items = [];
|
|
26733
|
+
const items = [...buildLocalToolSignalProfile(text).acceptanceItems];
|
|
26653
26734
|
if (/地图|景点|酒店|美食|点位|坐标|路线/.test(text)) {
|
|
26654
26735
|
items.push("\u5730\u56FE provider\u3001\u5750\u6807\u6765\u6E90\u548C API Key \u4F7F\u7528\u65B9\u5F0F\u5DF2\u660E\u786E\uFF1BKey \u4E0D\u5E94\u786C\u7F16\u7801\u5230\u516C\u5F00\u4ED3\u5E93");
|
|
26655
26736
|
items.push("\u7528\u6237\u4FDD\u5B58\u7684\u7F8E\u98DF\u3001\u9152\u5E97\u3001\u666F\u70B9\u80FD\u6309\u7C7B\u578B\u7B5B\u9009\u5E76\u6B63\u786E\u663E\u793A\u5728\u5730\u56FE\u6216\u5217\u8868\u4E2D");
|
|
@@ -27222,7 +27303,7 @@ function buildProductQuickQuestions(message, knownContext) {
|
|
|
27222
27303
|
const domain = classifyProductDomain(contextText, knownContext || {}).domain;
|
|
27223
27304
|
const technicalProfile = buildTechnicalProfile(message, knownContext || {});
|
|
27224
27305
|
if (domain === "generic" && isLocalFirstProfile(technicalProfile)) {
|
|
27225
|
-
return withQuestionExamples(buildLocalFirstQuickQuestions(technicalProfile));
|
|
27306
|
+
return withQuestionExamples(buildLocalFirstQuickQuestions(technicalProfile, message));
|
|
27226
27307
|
}
|
|
27227
27308
|
if (domain === "crm") {
|
|
27228
27309
|
return withQuestionExamples(buildCrmQuickQuestions());
|
|
@@ -27466,13 +27547,16 @@ function buildProductQuickQuestions(message, knownContext) {
|
|
|
27466
27547
|
}
|
|
27467
27548
|
]);
|
|
27468
27549
|
}
|
|
27469
|
-
function buildLocalFirstQuickQuestions(technicalProfile) {
|
|
27550
|
+
function buildLocalFirstQuickQuestions(technicalProfile, message = "") {
|
|
27470
27551
|
const storageDefault = technicalProfile.shape === "static_json_data_page" ? "static_json" : technicalProfile.shape === "local_json_import_export" ? "local_file" : "local_storage";
|
|
27552
|
+
const signalProfile = buildLocalToolSignalProfile(message);
|
|
27553
|
+
const recordObject = signalProfile.recordObject;
|
|
27554
|
+
const fieldExample = signalProfile.fieldExample;
|
|
27471
27555
|
const questions = [
|
|
27472
27556
|
{
|
|
27473
27557
|
id: "record_object",
|
|
27474
|
-
question:
|
|
27475
|
-
example: "\u6BD4\u5982\u98DF\u6750\u3001\u836F\u54C1\u3001\u6E38\u620F\u3001\u88C5\u5907\u3001\u4FDD\u5355\uFF0C\u6216\u666F\u70B9\u3001\u9152\u5E97\u3001\u7F8E\u98DF\u3002"
|
|
27558
|
+
question: `\u4F60\u60F3\u8BB0\u5F55\u6216\u5C55\u793A\u4EC0\u4E48\u4E1C\u897F\uFF1F`,
|
|
27559
|
+
example: recordObject === "\u8BB0\u5F55" ? "\u6BD4\u5982\u98DF\u6750\u3001\u836F\u54C1\u3001\u6E38\u620F\u3001\u88C5\u5907\u3001\u4FDD\u5355\uFF0C\u6216\u666F\u70B9\u3001\u9152\u5E97\u3001\u7F8E\u98DF\u3002" : `\u6BD4\u5982\u5148\u56F4\u7ED5\u201C${recordObject}\u201D\u505A\u4E2A\u4EBA\u8BB0\u5F55/\u6E05\u5355\u3002`,
|
|
27476
27560
|
whyImportant: "\u5148\u786E\u8BA4\u6838\u5FC3\u5BF9\u8C61\uFF0C\u907F\u514D\u88AB\u6269\u6210\u540E\u53F0\u7CFB\u7EDF\u3002",
|
|
27477
27561
|
priority: "P0",
|
|
27478
27562
|
defaultValue: "personal_records",
|
|
@@ -27485,8 +27569,8 @@ function buildLocalFirstQuickQuestions(technicalProfile) {
|
|
|
27485
27569
|
},
|
|
27486
27570
|
{
|
|
27487
27571
|
id: "record_items",
|
|
27488
|
-
question:
|
|
27489
|
-
example:
|
|
27572
|
+
question: `\u6BCF\u6761${recordObject === "\u8BB0\u5F55" ? "\u8BB0\u5F55" : recordObject}\u8BB0\u5F55\u8981\u4FDD\u5B58\u54EA\u4E9B\u4FE1\u606F\uFF1F`,
|
|
27573
|
+
example: `\u6BD4\u5982${fieldExample}\u3002`,
|
|
27490
27574
|
whyImportant: "\u51B3\u5B9A\u9875\u9762\u8868\u5355\u3001\u5217\u8868\u5217\u540D\u548C\u672C\u5730 JSON \u6570\u636E\u7ED3\u6784\u3002",
|
|
27491
27575
|
priority: "P0",
|
|
27492
27576
|
defaultValue: "name_date_status_note",
|
|
@@ -27514,7 +27598,7 @@ function buildLocalFirstQuickQuestions(technicalProfile) {
|
|
|
27514
27598
|
{
|
|
27515
27599
|
id: "operations",
|
|
27516
27600
|
question: "\u9700\u8981\u54EA\u4E9B\u64CD\u4F5C\uFF1F",
|
|
27517
|
-
example: "\u6BD4\u5982\u65B0\u589E\u3001\u7F16\u8F91\u3001\u5220\u9664\u3001\u641C\u7D22\u3001\u7B5B\u9009\u3001\u5206\u7C7B\u3002",
|
|
27601
|
+
example: signalProfile.featureHints.length > 0 ? `\u6BD4\u5982${signalProfile.featureHints.join("\u3001")}\u3002` : "\u6BD4\u5982\u65B0\u589E\u3001\u7F16\u8F91\u3001\u5220\u9664\u3001\u641C\u7D22\u3001\u7B5B\u9009\u3001\u5206\u7C7B\u3002",
|
|
27518
27602
|
whyImportant: "\u51B3\u5B9A\u7B2C\u4E00\u7248\u529F\u80FD\u8303\u56F4\u548C\u9A8C\u6536\u6807\u51C6\u3002",
|
|
27519
27603
|
priority: "P0",
|
|
27520
27604
|
defaultValue: "crud_search_filter",
|
|
@@ -28302,7 +28386,7 @@ function registerProductSpecAssist(server) {
|
|
|
28302
28386
|
function createServer() {
|
|
28303
28387
|
const server = new McpServer({
|
|
28304
28388
|
name: "product-spec-mcp",
|
|
28305
|
-
version: "0.3.
|
|
28389
|
+
version: "0.3.21"
|
|
28306
28390
|
});
|
|
28307
28391
|
registerSpecInterrogate(server);
|
|
28308
28392
|
registerSpecCompile(server);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "product-spec-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.21",
|
|
4
4
|
"description": "MCP Server for product specification - requirement interrogation, architecture decision, UI translation, debug guidance, and acceptance generation",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/index.cjs",
|