@devflow-tools/devflow 0.7.5 → 0.8.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/dist/hooks/pre-tool-use.js +2 -2
- package/dist/mcp-server.js +1 -1
- package/dist/plugin/.claude-plugin/plugin.json +19 -19
- package/dist/plugin/skills/devflow:context/SKILL.md +19 -0
- package/dist/plugin/skills/devflow:docker/SKILL.md +18 -0
- package/dist/plugin/skills/devflow:electron/SKILL.md +18 -0
- package/dist/plugin/skills/devflow:graph/SKILL.md +18 -0
- package/dist/plugin/skills/devflow:graphql/SKILL.md +19 -0
- package/dist/plugin/skills/devflow:knowledge/SKILL.md +18 -0
- package/dist/plugin/skills/devflow:memory/SKILL.md +18 -0
- package/dist/plugin/skills/devflow:nest/SKILL.md +19 -0
- package/dist/plugin/skills/devflow:nextjs/SKILL.md +19 -0
- package/dist/plugin/skills/devflow:performance/SKILL.md +18 -0
- package/dist/plugin/skills/devflow:react/SKILL.md +23 -0
- package/dist/plugin/skills/devflow:tailwind/SKILL.md +18 -0
- package/dist/plugin/skills/devflow:taro/SKILL.md +18 -0
- package/dist/plugin/skills/devflow:vue/SKILL.md +20 -0
- package/dist/plugin/skills/devflow:workflow/SKILL.md +18 -0
- package/package.json +12 -12
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {existsSync,readFileSync,mkdirSync,writeFileSync,unlinkSync,readdirSync}from'fs';import {join}from'path';import {homedir}from'os';var
|
|
2
|
-
export{
|
|
1
|
+
import {existsSync,readFileSync,mkdirSync,writeFileSync,unlinkSync,readdirSync}from'fs';import {join}from'path';import {homedir}from'os';var f=1e4,O=300*1e3,p=class{constructor(t){this.retryScheduled=false;this.apiUrl=t?.apiUrl??process.env.DEVFLOW_API_URL??"http://localhost:13337",this.apiKey=t?.apiKey??process.env.DEVFLOW_API_KEY??"dev-key-000000",this.cacheDir=t?.cacheDir??join(homedir(),".devflow","telemetry-cache");}async sendEvent(t){let e=this.truncateInput(t.input),r={...t,input:e};try{let n=await fetch(`${this.apiUrl}/api/telemetry/tool-call`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.apiKey},body:JSON.stringify(r)});if(!n.ok)throw new Error(`Server responded ${n.status}`)}catch{this.cacheEvent({type:"tool_call",payload:r});}}async sendExecutionStart(t,e,r){let n={executionId:t,skillName:e,startedAt:r};try{let i=await fetch(`${this.apiUrl}/api/telemetry/skill-execution/start`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.apiKey},body:JSON.stringify(n)});if(!i.ok)throw new Error(`Server responded ${i.status}`)}catch{this.cacheEvent({type:"execution_start",payload:n});}}async flushCache(){if(!existsSync(this.cacheDir))return;let t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json"));for(let e of t)try{let r=join(this.cacheDir,e),n=readFileSync(r,"utf8"),i=JSON.parse(n),a=i.type==="execution_start"?"/api/telemetry/skill-execution/start":"/api/telemetry/tool-call";(await fetch(`${this.apiUrl}${a}`,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":this.apiKey},body:JSON.stringify(i.payload)})).ok&&unlinkSync(r);}catch{}}cacheEvent(t){try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let e=join(this.cacheDir,`${Date.now()}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(e,JSON.stringify(t,null,2)),this.scheduleRetry();}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache().catch(()=>{});},O).unref());}truncateInput(t){let e=JSON.stringify(t);return e.length<=f?t:{_truncated:true,_original_size:e.length,_preview:e.substring(0,f)+"..."}}};function F(){return process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow")}var d=class{constructor(t){this.stateDir=F();}detect(){let t=join(this.stateDir,"current-skill.json");if(!existsSync(t))return null;try{let e=readFileSync(t,"utf8");return JSON.parse(e)}catch{return null}}startExecution(t,e){existsSync(this.stateDir)||mkdirSync(this.stateDir,{recursive:true});let r=this.getCurrentExecutionId();if(r)return r;let n=`exec_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return writeFileSync(join(this.stateDir,"current-execution-id"),n),writeFileSync(join(this.stateDir,"current-skill.json"),JSON.stringify({name:t,required_mcp_tools:e?.required_mcp_tools??[]})),n}getCurrentExecutionId(){let t=join(this.stateDir,"current-execution-id");if(!existsSync(t))return null;try{return readFileSync(t,"utf8").trim()}catch{return null}}endExecution(){let t=join(this.stateDir,"current-skill.json"),e=join(this.stateDir,"current-execution-id");try{existsSync(t)&&unlinkSync(t);}catch{}try{existsSync(e)&&unlinkSync(e);}catch{}}};async function M(o){try{if(!o||o.trim()==="")return {decision:"allow"};let t=JSON.parse(o),e=new d,r=e.detect(),n=t.tool_name.startsWith("mcp__devflow__"),i=n?t.tool_name.replace("mcp__devflow__",""):void 0,a=r?.required_mcp_tools??[],l=a.length>0,h=l&&!n,u;h?u={decision:"block",reason:`Skill "${r?.name||"unknown"}" requires MCP tools. Use one of: ${a.join(", ")}`}:u={decision:"allow"};let v=e.getCurrentExecutionId()??`exec_orphan_${Date.now()}`,S=new p,w={eventId:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`,executionId:v,timestamp:Date.now(),toolName:t.tool_name,toolType:n?"mcp":t.tool_name==="Agent"?"subagent":"direct",isMcpTool:n,mcpToolName:i,mcpEnforced:n&&l,mcpFallback:!n&&!l,input:t.tool_input,tokensUsed:0,duration:0,blocked:h,blockReason:h?u.reason:void 0};return S.sendEvent(w).catch(()=>{}),u}catch{return {decision:"allow"}}}if(process.argv[1]?.endsWith("pre-tool-use")||process.argv[1]?.endsWith("pre-tool-use.js")){let o="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{o+=t;}),process.stdin.on("end",async()=>{let t=await M(o);console.log(JSON.stringify(t));}),process.stdin.on("error",()=>{console.log(JSON.stringify({decision:"allow"})),process.exit(0);}),setTimeout(()=>{console.log(JSON.stringify({decision:"allow"})),process.exit(0);},4e3).unref();}
|
|
2
|
+
export{M as handlePreToolUse};
|
package/dist/mcp-server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {createHmac,createHash}from'crypto';import {Server}from'@modelcontextprotocol/sdk/server/index.js';import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';import {ListToolsRequestSchema,CallToolRequestSchema}from'@modelcontextprotocol/sdk/types.js';import {DevFlowApiClient,loadPlugins}from'@devflow-tools/sdk';import {join}from'path';import {existsSync,mkdirSync,readFileSync,writeFileSync}from'fs';var ue=Object.defineProperty;var y=(t,e)=>()=>(t&&(e=t(t=0)),e);var O=(t,e)=>{for(var o in e)ue(t,o,{get:e[o],enumerable:true});};var I={};O(I,{createPluginHandlers:()=>pe,createToolHandlers:()=>de,getCoreTools:()=>T,getPluginTools:()=>P});function T(){return [{name:"get_project_context",description:"\u83B7\u53D6\u4E0E\u7F16\u7801\u4EFB\u52A1\u6700\u76F8\u5173\u7684\u6700\u5C0F\u4E0A\u4E0B\u6587",inputSchema:{type:"object",properties:{query:{type:"string",description:"\u81EA\u7136\u8BED\u8A00\u67E5\u8BE2"},mode:{type:"string",enum:["fast","deep"],default:"fast"},expandedTerms:{type:"string",description:"Agent \u9884\u7FFB\u8BD1\u7684\u82F1\u6587\u5173\u952E\u8BCD\uFF08\u7A7A\u683C\u5206\u9694\uFF09\uFF0C\u7528\u4E8E\u63D0\u5347\u4E2D\u6587\u67E5\u8BE2\u7684\u641C\u7D22\u6548\u679C"}},required:["query"]}},{name:"search_symbol",description:"\u6309\u7B26\u53F7\u540D\u641C\u7D22\u4EE3\u7801\u2014\u2014\u8BED\u4E49\u7EA7\u4EE3\u7801\u7ED3\u6784\u641C\u7D22",inputSchema:{type:"object",properties:{symbol:{type:"string",description:"\u7B26\u53F7\u540D\u79F0"}},required:["symbol"]}},{name:"get_dependency_graph",description:"\u83B7\u53D6\u6587\u4EF6/\u7EC4\u4EF6\u7684\u4F9D\u8D56\u5173\u7CFB",inputSchema:{type:"object",properties:{target:{type:"string",default:"all"},depth:{type:"number",default:2}}}},{name:"run_workflow",description:"\u6267\u884C\u6807\u51C6\u5316\u5F00\u53D1\u5DE5\u4F5C\u6D41",inputSchema:{type:"object",properties:{type:{type:"string",enum:["bugfix","feature","review"]},input:{type:"string"}},required:["type"]}},{name:"get_memory",description:"\u83B7\u53D6\u9879\u76EE\u8BB0\u5FC6\uFF1A\u6280\u672F\u6808\u3001\u7EA6\u5B9A\u3001\u504F\u597D\u3001\u5386\u53F2\u51B3\u7B56",inputSchema:{type:"object",properties:{}}},{name:"get_knowledge",description:"\u67E5\u8BE2\u6280\u672F\u6587\u6863\u77E5\u8BC6\u5E93",inputSchema:{type:"object",properties:{query:{type:"string"},scope:{type:"string",enum:["react","vue","nest","all"],default:"all"}},required:["query"]}},{name:"devflow_report_event",description:"Report fine-grained events within workflow steps (LLM calls, tool usage, file read/write etc.). Optional, for more granular observability.",inputSchema:{type:"object",properties:{runId:{type:"string"},stepId:{type:"string"},kind:{type:"string",enum:["llm_call","tool_use","memory_read","memory_write","file_read","file_write","bash_command","mcp_tool_call","error","user_input"]},duration:{type:"number"},model:{type:"string"},prompt:{type:"string"},response:{type:"string"},inputTokens:{type:"number"},outputTokens:{type:"number"},toolName:{type:"string"},toolInput:{type:"string"},toolOutput:{type:"string"},filePath:{type:"string"},command:{type:"string"},exitCode:{type:"number"},stdout:{type:"string"},stderr:{type:"string"},mcpToolName:{type:"string"},errorMessage:{type:"string"},errorStack:{type:"string"},memoryKey:{type:"string"},userMessage:{type:"string"}},required:["runId","stepId","kind"]}}]}function de(t){return {get_project_context:async({query:e,mode:o,expandedTerms:r})=>{let n=await t.context.buildTaskContext(e,{mode:o??"fast"});return {taskType:n.taskType,requiredFiles:n.requiredFiles,optionalFiles:n.optionalFiles,keySymbols:n.keySymbols,graphSummary:n.graphSummary,riskHints:n.riskHints,nextActions:n.nextActions,reasoning:n.reasoning,confidence:n.confidence,tokenCount:n.tokenCount,_devflow_unique:{search_method:"bm25_semantic",task_oriented:true,risk_aware:true,memory_injected:true,knowledge_injected:true,token_estimated:true,required_vs_optional:true}}},search_symbol:async({symbol:e})=>({...await t.indexer.findSymbol(e),_devflow_unique:{index_backed:true,kind_annotated:true}}),get_dependency_graph:async({target:e,depth:o})=>{let r=e??"all",n=o??2;return {...r==="all"?t.graph.export():t.graph.getSubGraph(r,n),_devflow_unique:{layer_annotated:true,architecture_grouped:true,query_depth:n}}},run_workflow:async({type:e,input:o})=>({...await t.workflow.run(e,{input:o}),_devflow_unique:{dag_orchestrated:true,step_tracked:true,workflow_type:e}}),get_memory:async()=>({...await t.memory.getAll(),_devflow_unique:{memory_version:1,structured_storage:true,project_context_included:true}}),get_knowledge:async({query:e,scope:o})=>({...await t.knowledge.search(e,{sources:o==="all"?void 0:[o]}),_devflow_unique:{source_versioned:true,code_examples_included:true,search_scope:o}}),devflow_report_event:async e=>{let o=(u,p)=>!u||u.length<=p?{value:u??"",truncated:false}:{value:u.slice(0,p),truncated:true},r=o(e.prompt,500),n=o(e.response,500),s=o(e.stdout,1e3),i=o(e.stderr,500),a=r.truncated||n.truncated||s.truncated||i.truncated,l={id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,runId:e.runId,stepId:e.stepId,kind:e.kind,timestamp:Date.now(),duration:e.duration,data:{model:e.model,prompt:r.value,response:n.value,inputTokens:e.inputTokens,outputTokens:e.outputTokens,toolName:e.toolName,toolInput:e.toolInput,toolOutput:e.toolOutput,filePath:e.filePath,command:e.command,exitCode:e.exitCode,stdout:s.value,stderr:i.value,mcpToolName:e.mcpToolName,errorMessage:e.errorMessage,errorStack:e.errorStack,memoryKey:e.memoryKey,userMessage:e.userMessage},metadata:{source:"manual"},...a&&{metadata:{truncated:true,source:"manual"}}};return await t.telemetry.recordEvent(l),{acknowledged:true,eventId:l.id}}}}function P(t){let e=[];for(let o of t){let r=o.meta.name;for(let n of o.workflow?.templates??[]){let s=n.triggers?.find(i=>i.type==="mcp");s?.tool&&e.push({name:`${r}_${s.tool}`,description:n.description,inputSchema:{type:"object",properties:n.steps.filter(i=>i.inputSchema).reduce((i,a)=>({...i,...a.inputSchema??{}}),{}),required:[]}});}}return e}function pe(t,e){let o={};for(let r of e){let n=r.meta.name;for(let s of r.workflow?.templates??[]){let i=s.triggers?.find(l=>l.type==="mcp");if(!i?.tool)continue;let a=`${n}_${i.tool}`;o[a]=async l=>{let u=await t.workflow.run(s.name,l),p="";try{let c={id:u.runId??`run:${Date.now()}`,source:"mcp",tool:a,workflow:s.name,input:l,status:"running",startedAt:Date.now(),finishedAt:null,steps:[],metadata:{}};p=t.workflow.renderPlan(c,s);}catch{}return {...u,plan:p,_devflow_unique:{dag_orchestrated:true,step_tracked:true,plugin_name:n,template_name:s.name}}};}}return o}var E=y(()=>{});var x,$=y(()=>{x=[{id:"C001",name:"\u5FC5\u987B\u643A\u5E26 Session Token",level:"constitutional",condition:{requireFields:["_devflow_token"]},action:"deny",message:"\u7F3A\u5C11 Session Token\u3002\u8BF7\u901A\u8FC7 /devflow: \u547D\u4EE4\u542F\u52A8\u4F1A\u8BDD\uFF0C\u6216\u8FD0\u884C devflow session token \u83B7\u53D6\u4EE4\u724C\u3002"},{id:"C002",name:"Token \u5DF2\u8FC7\u671F",level:"constitutional",condition:{},action:"deny",message:"Session Token \u5DF2\u8FC7\u671F\uFF08\u8D85\u8FC7 1 \u5C0F\u65F6\uFF09\u3002\u8BF7\u91CD\u65B0\u8FD0\u884C devflow session token \u83B7\u53D6\u65B0\u4EE4\u724C\u3002"},{id:"C003",name:"\u901F\u7387\u9650\u5236",level:"constitutional",condition:{maxCallsPerMinute:60},action:"warn",message:"\u8C03\u7528\u9891\u7387\u8FC7\u9AD8\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}];});async function H(t){let e=await t.ruleGetAll();return [...x,...e]}function me(t,e){let o=t.condition;if(o.tools&&!o.tools.includes("*")&&!o.tools.includes(e.toolName))return "allow";if(o.requireFields){for(let r of o.requireFields)if(!(r in e.args))return t.action}if(o.forbidPatterns){for(let r of o.forbidPatterns)for(let n of Object.values(e.args))if(typeof n=="string"&&new RegExp(r).test(n))return t.action}if(o.paramPatterns)for(let[r,n]of Object.entries(o.paramPatterns)){let s=String(e.args[r]??"");if(new RegExp(n).test(s))return t.action}if(o.maxCallsPerMinute){let r=`${e.toolName}:${e.sessionId??"anon"}`,n=Date.now(),s=M.get(r);if((!s||n>s.resetAt)&&(s={count:0,resetAt:n+6e4},M.set(r,s)),s.count++,s.count>o.maxCallsPerMinute)return t.action}return "allow"}function N(t,e){let o=[...t].sort((r,n)=>{let s={constitutional:0,project:1,session:2};return s[r.level]-s[n.level]});for(let r of o){let n=me(r,e);if(n!=="allow")return {decision:n,rule:r}}return {decision:"allow"}}var M,F=y(()=>{$();M=new Map;});function _(t){let e=JSON.stringify(t,Object.keys(t).sort());return createHash("sha256").update(e).digest("hex")}async function D(t,e,o,r,n,s){let i=await t.auditGetSecret(),a=await t.auditGetAll(),l=a.length>0?a[a.length-1].signature:createHash("sha256").update("genesis").digest("hex"),u=Date.now(),p=a.length+1,c=`${p}|${u}|${e}|${o}|${r}|${n??""}|${s}|${l}`,f=createHmac("sha256",i).update(c).digest("hex");await t.auditAppend({seq:p,ts:u,tool:e,argsHash:o,decision:r,ruleId:n,sessionId:s,prevHash:l,signature:f});}async function L(t){let e=await t.auditGetSecret(),o=await t.auditGetAll(),r=createHash("sha256").update("genesis").digest("hex");for(let n of o){if(n.prevHash!==r)return {valid:false,brokenAt:n.seq};let s=`${n.seq}|${n.ts}|${n.tool}|${n.argsHash}|${n.decision}|${n.ruleId??""}|${n.sessionId}|${r}`,i=createHmac("sha256",e).update(s).digest("hex");if(n.signature!==i)return {valid:false,brokenAt:n.seq};r=n.signature;}return {valid:true,brokenAt:null}}async function J(t){let e=await t.auditGetSecret(),o=await t.auditGetAll(),r=createHash("sha256").update("genesis").digest("hex");for(let n of o){let s=`${n.seq}|${n.ts}|${n.tool}|${n.argsHash}|${n.decision}|${n.ruleId??""}|${n.sessionId}|${r}`,i=createHmac("sha256",e).update(s).digest("hex");await t.sqlExecute("UPDATE devflow_audit_chain SET prev_hash = ?, signature = ? WHERE seq = ?",[r,i,n.seq]),r=i;}}var C=y(()=>{});function h(t,e,o){let r=Date.now(),n=r+fe,s=createHash("sha256").update(JSON.stringify(e)).digest("hex"),i=`${t}|${r}|${n}|${s}`,a=createHmac("sha256",o).update(i).digest("hex");return {tool:t,ts:r,exp:n,queryHash:s,hmac:a}}function G(t,e,o,r){if(Date.now()>t.exp)return false;let n=createHash("sha256").update(JSON.stringify(o)).digest("hex");if(t.queryHash!==n)return false;let s=`${e}|${t.ts}|${t.exp}|${n}`,i=createHmac("sha256",r).update(s).digest("hex");return t.hmac===i}function U(t){return Date.now()>t.exp}var fe,q=y(()=>{fe=3e4;});var B={};O(B,{CONSTITUTIONAL_RULES:()=>x,enforce:()=>ge,hashArgs:()=>_,isReceiptExpired:()=>U,issueReceipt:()=>h,parseJwtPayload:()=>V,rebuildAuditChain:()=>J,verifyAuditChain:()=>L,verifyReceipt:()=>G});function V(t){try{let e=t.split(".");if(e.length!==3)return null;let o=e[1],r=Buffer.from(o,"base64url").toString("utf-8");return JSON.parse(r)}catch{return null}}async function ge(t,e,o){if(!e._devflow_token){let c=process.env.DEVFLOW_SESSION_TOKEN;if(c){let f=V(c);f&&(e={...e,_devflow_token:f});}}let r=e._devflow_token?.sub??"anon",n={toolName:t,args:e,sessionId:r,tokenPayload:e._devflow_token};if(n.tokenPayload){let c=Math.floor(Date.now()/1e3);if(n.tokenPayload.exp&&c>n.tokenPayload.exp){let f=_(e);return await D(o,t,f,"deny","C002",r),{result:{allowed:false,message:"Session Token \u5DF2\u8FC7\u671F\uFF08\u8D85\u8FC7 1 \u5C0F\u65F6\uFF09\u3002\u8BF7\u91CD\u65B0\u8FD0\u884C devflow session token \u83B7\u53D6\u65B0\u4EE4\u724C\u3002"}}}}let s=await H(o),{decision:i,rule:a}=N(s,n),l=_(e);if(await D(o,t,l,i,a?.id??null,r),i==="deny"&&a)return {result:{allowed:false,rule:a,message:a.message}};if(i==="warn"&&a){let c=await o.auditGetSecret(),f=h(t,e,c);return {result:{allowed:true,warning:a.message,rule:a},receipt:f}}let u=await o.auditGetSecret(),p=h(t,e,u);return {result:{allowed:true},receipt:p}}var z=y(()=>{F();C();q();C();q();$();});E();async function ee(t){Te(t.projectRoot);let e=new Server({name:"devflow-mcp",version:"0.1.0"},{capabilities:{tools:{}}}),o=process.env.DEVFLOW_SERVER_URL??"http://127.0.0.1:13337",r=process.env.DEVFLOW_API_KEY??"dev-key-000000",n=new DevFlowApiClient({baseUrl:o,projectRoot:t.projectRoot,apiKey:r}),s=await n.ping(),i=await loadPlugins(),a=Array.from(i.values()),l=T(),u=P(a),p=[...l,...u];e.setRequestHandler(ListToolsRequestSchema,async()=>({tools:p}));let c=null;e.setRequestHandler(CallToolRequestSchema,async te=>{let{name:d,arguments:ne}=te.params,w=ne??{},b=Date.now();try{let m;if(s){m=await De(n,d,w),Q(t.projectRoot,d);let v=Date.now()-b,g=d.split("_")[0];try{await n.recordTelemetryEvent({toolName:d,args:w,durationMs:v,success:!0,pluginName:g,metadata:{projectRoot:t.projectRoot}});}catch(R){console.error("[devflow-mcp] Failed to record telemetry:",R);}}else {if(!c){let[{createEngines:ae}]=await Promise.all([import('@devflow-tools/context-engine')]);c=await ae(t.projectRoot);for(let ce of a)for(let le of ce.workflow?.templates??[])c.workflow.register(le);console.error(`[devflow-mcp] Warning: DevFlow server not reachable at ${o}`),console.error("[devflow-mcp] Running in local mode.");}let{enforce:v}=await Promise.resolve().then(()=>(z(),B)),g=await v(d,w,c.data);if(!g.result.allowed)return {content:[{type:"text",text:JSON.stringify({_devflow:{v:1,tool:d,ts:Date.now(),marker:"devflow-mcp-v1"},error:g.result.message,rule:g.result.rule?.id})}],isError:!0};let{createToolHandlers:R,createPluginHandlers:oe}=await Promise.resolve().then(()=>(E(),I)),re=R(c),se=oe(c,a),A={...re,...se}[d];if(!A)throw new Error(`Unknown tool: ${d}`);m=await A(w),Q(t.projectRoot,d);let ie=Date.now()-b;try{await c.data.recordToolCall(d,w,ie);}catch{}g.receipt&&(m={...m,_receipt:g.receipt}),g.result.warning&&(m={...m,_warning:g.result.warning});}let k=$e(d,m);return {content:[{type:"text",text:JSON.stringify(k,null,2)}]}}catch(m){let k=Date.now()-b;if(s)try{await n.recordTelemetryEvent({toolName:d,args:w,durationMs:k,success:!1,error:m.message,pluginName:d.split("_")[0],metadata:{projectRoot:t.projectRoot}});}catch(v){console.error("[devflow-mcp] Failed to record error telemetry:",v);}else if(c)try{await c.data.recordToolCall(d,w,k,m.message);}catch{}return {content:[{type:"text",text:`Error: ${m.message}`}],isError:true}}});let f=new StdioServerTransport;await e.connect(f);}function Te(t){if(process.env.DEVFLOW_SESSION_TOKEN)return;let e=Buffer.from(JSON.stringify({alg:"HS256",typ:"JWT"})).toString("base64url"),o=Math.floor(Date.now()/1e3),r={sub:`devflow-mcp-${Date.now().toString(36)}`,project:t.split("/").pop()??"unknown",iat:o,exp:o+86400,scope:["context","knowledge","memory","workflow","graph"]},n=Buffer.from(JSON.stringify(r)).toString("base64url"),i=createHmac("sha256","devflow-local-mcp-secret-v1").update(`${e}.${n}`).digest("base64url");process.env.DEVFLOW_SESSION_TOKEN=`${e}.${n}.${i}`,console.error("[devflow-mcp] Auto-generated session token (no env token provided).");}var Pe=new Set(["react","vue","nest","nextjs","graphql","docker","tailwind","taro","electron","performance"]);function Ee(t){let e={get_project_context:"context",search_symbol:"context",get_dependency_graph:"graph",get_knowledge:"knowledge",get_memory:"memory",run_workflow:"workflow"};if(e[t])return `devflow:${e[t]}`;let o=t.split("_")[0];return Pe.has(o)?`devflow:${o}`:""}function Q(t,e){try{let o=process.env.TMPDIR||"/tmp",r=join(o,".devflow-receipts"),n=createHash("sha256").update(t).digest("hex").slice(0,16),s=join(r,`${n}.json`);existsSync(r)||mkdirSync(r,{recursive:!0});let i={};if(existsSync(s))try{i=JSON.parse(readFileSync(s,"utf-8"));}catch{}i.lastMcpCall=Date.now(),i.bypassCount=0;let a=Ee(e);a&&(i.activeCommand=a),writeFileSync(s,JSON.stringify(i));}catch{}}function $e(t,e){let o={_devflow:{v:1,tool:t,ts:Date.now(),marker:"devflow-mcp-v1"}};return e&&typeof e=="object"&&!Array.isArray(e)?{...e,...o}:{result:e,...o}}async function je(){let t=new Map,e=await loadPlugins(),o=Array.from(e.values());for(let r of o){let n=r.meta.name;for(let s of r.workflow?.templates??[]){let i=s.triggers?.find(a=>a.type==="mcp");if(i?.tool){let a=`${n}_${i.tool}`;t.set(a,s.name);}}}return t}async function De(t,e,o){switch(e){case "get_project_context":return t.buildContext(o.query,o.mode??"fast");case "search_symbol":return t.searchSymbol(o.symbol);case "get_dependency_graph":return t.getGraph(o.target??"all",o.depth??2);case "run_workflow":return t.runWorkflow(o.type,o.input);case "get_memory":return t.getMemory();case "get_knowledge":return t.searchKnowledge(o.query,o.scope??"all");case "devflow_report_event":return t.recordEvent(o);default:{let n=(await je()).get(e)??e;return t.runWorkflow(n,o)}}}async function Ce(){let t=process.env.DEVFLOW_PROJECT_ROOT||process.cwd();await ee({mode:"stdio",projectRoot:t});}Ce().catch(t=>{console.error("MCP Server error:",t),process.exit(1);});
|
|
2
|
+
import {createHmac,createHash}from'crypto';import {Server}from'@modelcontextprotocol/sdk/server/index.js';import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';import {ListToolsRequestSchema,CallToolRequestSchema}from'@modelcontextprotocol/sdk/types.js';import {DevFlowApiClient,loadPlugins}from'@devflow-tools/sdk';import {join}from'path';import {existsSync,mkdirSync,readFileSync,writeFileSync}from'fs';var ue=Object.defineProperty;var y=(t,e)=>()=>(t&&(e=t(t=0)),e);var O=(t,e)=>{for(var n in e)ue(t,n,{get:e[n],enumerable:true});};var I={};O(I,{createPluginHandlers:()=>pe,createToolHandlers:()=>de,getCoreTools:()=>T,getPluginTools:()=>P});function T(){return [{name:"get_project_context",description:"\u83B7\u53D6\u4E0E\u7F16\u7801\u4EFB\u52A1\u6700\u76F8\u5173\u7684\u6700\u5C0F\u4E0A\u4E0B\u6587",inputSchema:{type:"object",properties:{query:{type:"string",description:"\u81EA\u7136\u8BED\u8A00\u67E5\u8BE2"},mode:{type:"string",enum:["fast","deep"],default:"fast"},expandedTerms:{type:"string",description:"Agent \u9884\u7FFB\u8BD1\u7684\u82F1\u6587\u5173\u952E\u8BCD\uFF08\u7A7A\u683C\u5206\u9694\uFF09\uFF0C\u7528\u4E8E\u63D0\u5347\u4E2D\u6587\u67E5\u8BE2\u7684\u641C\u7D22\u6548\u679C"}},required:["query"]}},{name:"search_symbol",description:"\u6309\u7B26\u53F7\u540D\u641C\u7D22\u4EE3\u7801\u2014\u2014\u8BED\u4E49\u7EA7\u4EE3\u7801\u7ED3\u6784\u641C\u7D22",inputSchema:{type:"object",properties:{symbol:{type:"string",description:"\u7B26\u53F7\u540D\u79F0"}},required:["symbol"]}},{name:"get_dependency_graph",description:"\u83B7\u53D6\u6587\u4EF6/\u7EC4\u4EF6\u7684\u4F9D\u8D56\u5173\u7CFB",inputSchema:{type:"object",properties:{target:{type:"string",default:"all"},depth:{type:"number",default:2}}}},{name:"run_workflow",description:"\u6267\u884C\u6807\u51C6\u5316\u5F00\u53D1\u5DE5\u4F5C\u6D41",inputSchema:{type:"object",properties:{type:{type:"string",enum:["bugfix","feature","review"]},input:{type:"string"}},required:["type"]}},{name:"get_memory",description:"\u83B7\u53D6\u9879\u76EE\u8BB0\u5FC6\uFF1A\u6280\u672F\u6808\u3001\u7EA6\u5B9A\u3001\u504F\u597D\u3001\u5386\u53F2\u51B3\u7B56",inputSchema:{type:"object",properties:{}}},{name:"get_knowledge",description:"\u67E5\u8BE2\u6280\u672F\u6587\u6863\u77E5\u8BC6\u5E93",inputSchema:{type:"object",properties:{query:{type:"string"},scope:{type:"string",enum:["react","vue","nest","all"],default:"all"}},required:["query"]}},{name:"devflow_report_event",description:"Report fine-grained events within workflow steps (LLM calls, tool usage, file read/write etc.). Optional, for more granular observability.",inputSchema:{type:"object",properties:{runId:{type:"string"},stepId:{type:"string"},kind:{type:"string",enum:["llm_call","tool_use","memory_read","memory_write","file_read","file_write","bash_command","mcp_tool_call","error","user_input"]},duration:{type:"number"},model:{type:"string"},prompt:{type:"string"},response:{type:"string"},inputTokens:{type:"number"},outputTokens:{type:"number"},toolName:{type:"string"},toolInput:{type:"string"},toolOutput:{type:"string"},filePath:{type:"string"},command:{type:"string"},exitCode:{type:"number"},stdout:{type:"string"},stderr:{type:"string"},mcpToolName:{type:"string"},errorMessage:{type:"string"},errorStack:{type:"string"},memoryKey:{type:"string"},userMessage:{type:"string"}},required:["runId","stepId","kind"]}}]}function de(t){return {get_project_context:async({query:e,mode:n,expandedTerms:r})=>{let o=await t.context.buildTaskContext(e,{mode:n??"fast"});return {taskType:o.taskType,requiredFiles:o.requiredFiles,optionalFiles:o.optionalFiles,keySymbols:o.keySymbols,graphSummary:o.graphSummary,riskHints:o.riskHints,nextActions:o.nextActions,reasoning:o.reasoning,confidence:o.confidence,tokenCount:o.tokenCount,_devflow_unique:{search_method:"bm25_semantic",task_oriented:true,risk_aware:true,memory_injected:true,knowledge_injected:true,token_estimated:true,required_vs_optional:true}}},search_symbol:async({symbol:e})=>({...await t.indexer.findSymbol(e),_devflow_unique:{index_backed:true,kind_annotated:true}}),get_dependency_graph:async({target:e,depth:n})=>{let r=e??"all",o=n??2;return {...r==="all"?t.graph.export():t.graph.getSubGraph(r,o),_devflow_unique:{layer_annotated:true,architecture_grouped:true,query_depth:o}}},run_workflow:async({type:e,input:n})=>({...await t.workflow.run(e,{input:n}),_devflow_unique:{dag_orchestrated:true,step_tracked:true,workflow_type:e}}),get_memory:async()=>({...await t.memory.getAll(),_devflow_unique:{memory_version:1,structured_storage:true,project_context_included:true}}),get_knowledge:async({query:e,scope:n})=>({...await t.knowledge.search(e,{sources:n==="all"?void 0:[n]}),_devflow_unique:{source_versioned:true,code_examples_included:true,search_scope:n}}),devflow_report_event:async e=>{let n=(u,p)=>!u||u.length<=p?{value:u??"",truncated:false}:{value:u.slice(0,p),truncated:true},r=n(e.prompt,500),o=n(e.response,500),s=n(e.stdout,1e3),i=n(e.stderr,500),a=r.truncated||o.truncated||s.truncated||i.truncated,c={id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,runId:e.runId,stepId:e.stepId,kind:e.kind,timestamp:Date.now(),duration:e.duration,data:{model:e.model,prompt:r.value,response:o.value,inputTokens:e.inputTokens,outputTokens:e.outputTokens,toolName:e.toolName,toolInput:e.toolInput,toolOutput:e.toolOutput,filePath:e.filePath,command:e.command,exitCode:e.exitCode,stdout:s.value,stderr:i.value,mcpToolName:e.mcpToolName,errorMessage:e.errorMessage,errorStack:e.errorStack,memoryKey:e.memoryKey,userMessage:e.userMessage},metadata:{source:"manual"},...a&&{metadata:{truncated:true,source:"manual"}}};return await t.telemetry.recordEvent(c),{acknowledged:true,eventId:c.id}}}}function P(t){let e=[];for(let n of t){let r=n.meta.name;for(let s of n.tools??[])e.push({name:s.name,description:s.description,inputSchema:s.inputSchema});let o=new Set(e.map(s=>s.name));for(let s of n.workflow?.templates??[]){let i=s.triggers?.find(c=>c.type==="mcp");if(!i?.tool)continue;let a=`${r}_${i.tool}`;o.has(a)||e.push({name:a,description:s.description,inputSchema:{type:"object",properties:s.steps.filter(c=>c.inputSchema).reduce((c,u)=>({...c,...u.inputSchema??{}}),{}),required:[]}});}}return e}function pe(t,e){let n={};for(let r of e){let o=r.meta.name;for(let s of r.tools??[])s.handler&&(n[s.name]=s.handler);for(let s of r.workflow?.templates??[]){let i=s.triggers?.find(c=>c.type==="mcp");if(!i?.tool)continue;let a=`${o}_${i.tool}`;n[a]||(n[a]=async c=>{let u=await t.workflow.run(s.name,c),p="";try{let l={id:u.runId??`run:${Date.now()}`,source:"mcp",tool:a,workflow:s.name,input:c,status:"running",startedAt:Date.now(),finishedAt:null,steps:[],metadata:{}};p=t.workflow.renderPlan(l,s);}catch{}return {...u,plan:p,_devflow_unique:{dag_orchestrated:true,step_tracked:true,plugin_name:o,template_name:s.name}}});}}return n}var E=y(()=>{});var x,$=y(()=>{x=[{id:"C001",name:"\u5FC5\u987B\u643A\u5E26 Session Token",level:"constitutional",condition:{requireFields:["_devflow_token"]},action:"deny",message:"\u7F3A\u5C11 Session Token\u3002\u8BF7\u901A\u8FC7 /devflow: \u547D\u4EE4\u542F\u52A8\u4F1A\u8BDD\uFF0C\u6216\u8FD0\u884C devflow session token \u83B7\u53D6\u4EE4\u724C\u3002"},{id:"C002",name:"Token \u5DF2\u8FC7\u671F",level:"constitutional",condition:{},action:"deny",message:"Session Token \u5DF2\u8FC7\u671F\uFF08\u8D85\u8FC7 1 \u5C0F\u65F6\uFF09\u3002\u8BF7\u91CD\u65B0\u8FD0\u884C devflow session token \u83B7\u53D6\u65B0\u4EE4\u724C\u3002"},{id:"C003",name:"\u901F\u7387\u9650\u5236",level:"constitutional",condition:{maxCallsPerMinute:60},action:"warn",message:"\u8C03\u7528\u9891\u7387\u8FC7\u9AD8\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}];});async function H(t){let e=await t.ruleGetAll();return [...x,...e]}function me(t,e){let n=t.condition;if(n.tools&&!n.tools.includes("*")&&!n.tools.includes(e.toolName))return "allow";if(n.requireFields){for(let r of n.requireFields)if(!(r in e.args))return t.action}if(n.forbidPatterns){for(let r of n.forbidPatterns)for(let o of Object.values(e.args))if(typeof o=="string"&&new RegExp(r).test(o))return t.action}if(n.paramPatterns)for(let[r,o]of Object.entries(n.paramPatterns)){let s=String(e.args[r]??"");if(new RegExp(o).test(s))return t.action}if(n.maxCallsPerMinute){let r=`${e.toolName}:${e.sessionId??"anon"}`,o=Date.now(),s=M.get(r);if((!s||o>s.resetAt)&&(s={count:0,resetAt:o+6e4},M.set(r,s)),s.count++,s.count>n.maxCallsPerMinute)return t.action}return "allow"}function N(t,e){let n=[...t].sort((r,o)=>{let s={constitutional:0,project:1,session:2};return s[r.level]-s[o.level]});for(let r of n){let o=me(r,e);if(o!=="allow")return {decision:o,rule:r}}return {decision:"allow"}}var M,F=y(()=>{$();M=new Map;});function v(t){let e=JSON.stringify(t,Object.keys(t).sort());return createHash("sha256").update(e).digest("hex")}async function j(t,e,n,r,o,s){let i=await t.auditGetSecret(),a=await t.auditGetAll(),c=a.length>0?a[a.length-1].signature:createHash("sha256").update("genesis").digest("hex"),u=Date.now(),p=a.length+1,l=`${p}|${u}|${e}|${n}|${r}|${o??""}|${s}|${c}`,f=createHmac("sha256",i).update(l).digest("hex");await t.auditAppend({seq:p,ts:u,tool:e,argsHash:n,decision:r,ruleId:o,sessionId:s,prevHash:c,signature:f});}async function L(t){let e=await t.auditGetSecret(),n=await t.auditGetAll(),r=createHash("sha256").update("genesis").digest("hex");for(let o of n){if(o.prevHash!==r)return {valid:false,brokenAt:o.seq};let s=`${o.seq}|${o.ts}|${o.tool}|${o.argsHash}|${o.decision}|${o.ruleId??""}|${o.sessionId}|${r}`,i=createHmac("sha256",e).update(s).digest("hex");if(o.signature!==i)return {valid:false,brokenAt:o.seq};r=o.signature;}return {valid:true,brokenAt:null}}async function J(t){let e=await t.auditGetSecret(),n=await t.auditGetAll(),r=createHash("sha256").update("genesis").digest("hex");for(let o of n){let s=`${o.seq}|${o.ts}|${o.tool}|${o.argsHash}|${o.decision}|${o.ruleId??""}|${o.sessionId}|${r}`,i=createHmac("sha256",e).update(s).digest("hex");await t.sqlExecute("UPDATE devflow_audit_chain SET prev_hash = ?, signature = ? WHERE seq = ?",[r,i,o.seq]),r=i;}}var C=y(()=>{});function _(t,e,n){let r=Date.now(),o=r+fe,s=createHash("sha256").update(JSON.stringify(e)).digest("hex"),i=`${t}|${r}|${o}|${s}`,a=createHmac("sha256",n).update(i).digest("hex");return {tool:t,ts:r,exp:o,queryHash:s,hmac:a}}function G(t,e,n,r){if(Date.now()>t.exp)return false;let o=createHash("sha256").update(JSON.stringify(n)).digest("hex");if(t.queryHash!==o)return false;let s=`${e}|${t.ts}|${t.exp}|${o}`,i=createHmac("sha256",r).update(s).digest("hex");return t.hmac===i}function U(t){return Date.now()>t.exp}var fe,q=y(()=>{fe=3e4;});var B={};O(B,{CONSTITUTIONAL_RULES:()=>x,enforce:()=>ge,hashArgs:()=>v,isReceiptExpired:()=>U,issueReceipt:()=>_,parseJwtPayload:()=>V,rebuildAuditChain:()=>J,verifyAuditChain:()=>L,verifyReceipt:()=>G});function V(t){try{let e=t.split(".");if(e.length!==3)return null;let n=e[1],r=Buffer.from(n,"base64url").toString("utf-8");return JSON.parse(r)}catch{return null}}async function ge(t,e,n){if(!e._devflow_token){let l=process.env.DEVFLOW_SESSION_TOKEN;if(l){let f=V(l);f&&(e={...e,_devflow_token:f});}}let r=e._devflow_token?.sub??"anon",o={toolName:t,args:e,sessionId:r,tokenPayload:e._devflow_token};if(o.tokenPayload){let l=Math.floor(Date.now()/1e3);if(o.tokenPayload.exp&&l>o.tokenPayload.exp){let f=v(e);return await j(n,t,f,"deny","C002",r),{result:{allowed:false,message:"Session Token \u5DF2\u8FC7\u671F\uFF08\u8D85\u8FC7 1 \u5C0F\u65F6\uFF09\u3002\u8BF7\u91CD\u65B0\u8FD0\u884C devflow session token \u83B7\u53D6\u65B0\u4EE4\u724C\u3002"}}}}let s=await H(n),{decision:i,rule:a}=N(s,o),c=v(e);if(await j(n,t,c,i,a?.id??null,r),i==="deny"&&a)return {result:{allowed:false,rule:a,message:a.message}};if(i==="warn"&&a){let l=await n.auditGetSecret(),f=_(t,e,l);return {result:{allowed:true,warning:a.message,rule:a},receipt:f}}let u=await n.auditGetSecret(),p=_(t,e,u);return {result:{allowed:true},receipt:p}}var z=y(()=>{F();C();q();C();q();$();});E();async function ee(t){Te(t.projectRoot);let e=new Server({name:"devflow-mcp",version:"0.1.0"},{capabilities:{tools:{}}}),n=process.env.DEVFLOW_SERVER_URL??"http://127.0.0.1:13337",r=process.env.DEVFLOW_API_KEY??"dev-key-000000",o=new DevFlowApiClient({baseUrl:n,projectRoot:t.projectRoot,apiKey:r}),s=await o.ping(),i=await loadPlugins(),a=Array.from(i.values()),c=T(),u=P(a),p=[...c,...u];e.setRequestHandler(ListToolsRequestSchema,async()=>({tools:p}));let l=null;e.setRequestHandler(CallToolRequestSchema,async te=>{let{name:d,arguments:ne}=te.params,w=ne??{},b=Date.now();try{let m;if(s){m=await je(o,d,w),Q(t.projectRoot,d);let h=Date.now()-b,g=d.split("_")[0];try{await o.recordTelemetryEvent({toolName:d,args:w,durationMs:h,success:!0,pluginName:g,metadata:{projectRoot:t.projectRoot}});}catch(R){console.error("[devflow-mcp] Failed to record telemetry:",R);}}else {if(!l){let[{createEngines:ae}]=await Promise.all([import('@devflow-tools/context-engine')]);l=await ae(t.projectRoot);for(let ce of a)for(let le of ce.workflow?.templates??[])l.workflow.register(le);console.error(`[devflow-mcp] Warning: DevFlow server not reachable at ${n}`),console.error("[devflow-mcp] Running in local mode.");}let{enforce:h}=await Promise.resolve().then(()=>(z(),B)),g=await h(d,w,l.data);if(!g.result.allowed)return {content:[{type:"text",text:JSON.stringify({_devflow:{v:1,tool:d,ts:Date.now(),marker:"devflow-mcp-v1"},error:g.result.message,rule:g.result.rule?.id})}],isError:!0};let{createToolHandlers:R,createPluginHandlers:oe}=await Promise.resolve().then(()=>(E(),I)),re=R(l),se=oe(l,a),A={...re,...se}[d];if(!A)throw new Error(`Unknown tool: ${d}`);m=await A(w),Q(t.projectRoot,d);let ie=Date.now()-b;try{await l.data.recordToolCall(d,w,ie);}catch{}g.receipt&&(m={...m,_receipt:g.receipt}),g.result.warning&&(m={...m,_warning:g.result.warning});}let k=$e(d,m);return {content:[{type:"text",text:JSON.stringify(k,null,2)}]}}catch(m){let k=Date.now()-b;if(s)try{await o.recordTelemetryEvent({toolName:d,args:w,durationMs:k,success:!1,error:m.message,pluginName:d.split("_")[0],metadata:{projectRoot:t.projectRoot}});}catch(h){console.error("[devflow-mcp] Failed to record error telemetry:",h);}else if(l)try{await l.data.recordToolCall(d,w,k,m.message);}catch{}return {content:[{type:"text",text:`Error: ${m.message}`}],isError:true}}});let f=new StdioServerTransport;await e.connect(f);}function Te(t){if(process.env.DEVFLOW_SESSION_TOKEN)return;let e=Buffer.from(JSON.stringify({alg:"HS256",typ:"JWT"})).toString("base64url"),n=Math.floor(Date.now()/1e3),r={sub:`devflow-mcp-${Date.now().toString(36)}`,project:t.split("/").pop()??"unknown",iat:n,exp:n+86400,scope:["context","knowledge","memory","workflow","graph"]},o=Buffer.from(JSON.stringify(r)).toString("base64url"),i=createHmac("sha256","devflow-local-mcp-secret-v1").update(`${e}.${o}`).digest("base64url");process.env.DEVFLOW_SESSION_TOKEN=`${e}.${o}.${i}`,console.error("[devflow-mcp] Auto-generated session token (no env token provided).");}var Pe=new Set(["react","vue","nest","nextjs","graphql","docker","tailwind","taro","electron","performance"]);function Ee(t){let e={get_project_context:"context",search_symbol:"context",get_dependency_graph:"graph",get_knowledge:"knowledge",get_memory:"memory",run_workflow:"workflow"};if(e[t])return `devflow:${e[t]}`;let n=t.split("_")[0];return Pe.has(n)?`devflow:${n}`:""}function Q(t,e){try{let n=process.env.TMPDIR||"/tmp",r=join(n,".devflow-receipts"),o=createHash("sha256").update(t).digest("hex").slice(0,16),s=join(r,`${o}.json`);existsSync(r)||mkdirSync(r,{recursive:!0});let i={};if(existsSync(s))try{i=JSON.parse(readFileSync(s,"utf-8"));}catch{}i.lastMcpCall=Date.now(),i.bypassCount=0;let a=Ee(e);a&&(i.activeCommand=a),writeFileSync(s,JSON.stringify(i));}catch{}}function $e(t,e){let n={_devflow:{v:1,tool:t,ts:Date.now(),marker:"devflow-mcp-v1"}};return e&&typeof e=="object"&&!Array.isArray(e)?{...e,...n}:{result:e,...n}}async function De(){let t=new Map,e=await loadPlugins(),n=Array.from(e.values());for(let r of n){let o=r.meta.name;for(let s of r.workflow?.templates??[]){let i=s.triggers?.find(a=>a.type==="mcp");if(i?.tool){let a=`${o}_${i.tool}`;t.set(a,s.name);}}}return t}async function je(t,e,n){switch(e){case "get_project_context":return t.buildContext(n.query,n.mode??"fast");case "search_symbol":return t.searchSymbol(n.symbol);case "get_dependency_graph":return t.getGraph(n.target??"all",n.depth??2);case "run_workflow":return t.runWorkflow(n.type,n.input);case "get_memory":return t.getMemory();case "get_knowledge":return t.searchKnowledge(n.query,n.scope??"all");case "devflow_report_event":return t.recordEvent(n);default:{let o=(await De()).get(e)??e;return t.runWorkflow(o,n)}}}async function Ce(){let t=process.env.DEVFLOW_PROJECT_ROOT||process.cwd();await ee({mode:"stdio",projectRoot:t});}Ce().catch(t=>{console.error("MCP Server error:",t),process.exit(1);});
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
2
|
+
"name": "@devflow-tools/claude-code-plugin",
|
|
3
|
+
"description": "DevFlow — Developer Intelligence Platform: project context, code graph, knowledge base, memory engine, and workflow automation with 14 domain plugins",
|
|
4
|
+
"version": "0.7.6",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "DevFlow"
|
|
7
|
+
},
|
|
8
|
+
"homepage": "https://github.com/shilongfeicool/dev-flow",
|
|
9
|
+
"repository": "https://github.com/shilongfeicool/dev-flow",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"devflow",
|
|
13
|
+
"context",
|
|
14
|
+
"knowledge-base",
|
|
15
|
+
"code-graph",
|
|
16
|
+
"memory",
|
|
17
|
+
"workflow",
|
|
18
|
+
"development"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -5,6 +5,25 @@ required_mcp_tools:
|
|
|
5
5
|
- get_project_context
|
|
6
6
|
- search_symbol
|
|
7
7
|
---
|
|
8
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
9
|
+
|
|
10
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:context","required_mcp_tools":["get_project_context","search_symbol"],"description":"devflow:context skill"}' > ~/.devflow/current-skill.json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
17
|
+
- `mcp__devflow__get_project_context`
|
|
18
|
+
- `mcp__devflow__search_symbol`
|
|
19
|
+
|
|
20
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
21
|
+
|
|
22
|
+
When the skill execution is complete, clean up:
|
|
23
|
+
```bash
|
|
24
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
25
|
+
```
|
|
26
|
+
|
|
8
27
|
|
|
9
28
|
# /devflow:context
|
|
10
29
|
|
|
@@ -4,6 +4,24 @@ description: Docker 专家 — 镜像优化、Compose 编排、安全扫描、
|
|
|
4
4
|
required_mcp_tools:
|
|
5
5
|
- docker_dockerize_project
|
|
6
6
|
---
|
|
7
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
8
|
+
|
|
9
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:docker","required_mcp_tools":["docker_dockerize_project"],"description":"devflow:docker skill"}' > ~/.devflow/current-skill.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
16
|
+
- `mcp__devflow__docker_dockerize_project`
|
|
17
|
+
|
|
18
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
19
|
+
|
|
20
|
+
When the skill execution is complete, clean up:
|
|
21
|
+
```bash
|
|
22
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
23
|
+
```
|
|
24
|
+
|
|
7
25
|
|
|
8
26
|
# 🐳 DOCKER
|
|
9
27
|
|
|
@@ -4,6 +4,24 @@ description: Electron 专家 — IPC 通信、窗口管理、原生模块、自
|
|
|
4
4
|
required_mcp_tools:
|
|
5
5
|
- electron_diagnose_bug
|
|
6
6
|
---
|
|
7
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
8
|
+
|
|
9
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:electron","required_mcp_tools":["electron_diagnose_bug"],"description":"devflow:electron skill"}' > ~/.devflow/current-skill.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
16
|
+
- `mcp__devflow__electron_diagnose_bug`
|
|
17
|
+
|
|
18
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
19
|
+
|
|
20
|
+
When the skill execution is complete, clean up:
|
|
21
|
+
```bash
|
|
22
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
23
|
+
```
|
|
24
|
+
|
|
7
25
|
|
|
8
26
|
# ⚛️ ELECTRON
|
|
9
27
|
|
|
@@ -4,6 +4,24 @@ description: 查看项目模块图谱 — 架构分层、文件分组、依赖
|
|
|
4
4
|
required_mcp_tools:
|
|
5
5
|
- get_dependency_graph
|
|
6
6
|
---
|
|
7
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
8
|
+
|
|
9
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:graph","required_mcp_tools":["get_dependency_graph"],"description":"devflow:graph skill"}' > ~/.devflow/current-skill.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
16
|
+
- `mcp__devflow__get_dependency_graph`
|
|
17
|
+
|
|
18
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
19
|
+
|
|
20
|
+
When the skill execution is complete, clean up:
|
|
21
|
+
```bash
|
|
22
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
23
|
+
```
|
|
24
|
+
|
|
7
25
|
|
|
8
26
|
# /devflow:graph
|
|
9
27
|
|
|
@@ -5,6 +5,25 @@ required_mcp_tools:
|
|
|
5
5
|
- graphql_new_graphql_type
|
|
6
6
|
- graphql_diagnose_bug
|
|
7
7
|
---
|
|
8
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
9
|
+
|
|
10
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:graphql","required_mcp_tools":["graphql_new_graphql_type","graphql_diagnose_bug"],"description":"devflow:graphql skill"}' > ~/.devflow/current-skill.json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
17
|
+
- `mcp__devflow__graphql_new_graphql_type`
|
|
18
|
+
- `mcp__devflow__graphql_diagnose_bug`
|
|
19
|
+
|
|
20
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
21
|
+
|
|
22
|
+
When the skill execution is complete, clean up:
|
|
23
|
+
```bash
|
|
24
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
25
|
+
```
|
|
26
|
+
|
|
8
27
|
|
|
9
28
|
# ◈ GRAPHQL
|
|
10
29
|
|
|
@@ -4,6 +4,24 @@ description: 搜索技术文档知识库 — React、Vue、Nest、TypeScript 等
|
|
|
4
4
|
required_mcp_tools:
|
|
5
5
|
- get_knowledge
|
|
6
6
|
---
|
|
7
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
8
|
+
|
|
9
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:knowledge","required_mcp_tools":["get_knowledge"],"description":"devflow:knowledge skill"}' > ~/.devflow/current-skill.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
16
|
+
- `mcp__devflow__get_knowledge`
|
|
17
|
+
|
|
18
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
19
|
+
|
|
20
|
+
When the skill execution is complete, clean up:
|
|
21
|
+
```bash
|
|
22
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
23
|
+
```
|
|
24
|
+
|
|
7
25
|
|
|
8
26
|
# /devflow:knowledge
|
|
9
27
|
|
|
@@ -4,6 +4,24 @@ description: 项目记忆 — 技术栈、编码约定、历史决策、用户
|
|
|
4
4
|
required_mcp_tools:
|
|
5
5
|
- get_memory
|
|
6
6
|
---
|
|
7
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
8
|
+
|
|
9
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:memory","required_mcp_tools":["get_memory"],"description":"devflow:memory skill"}' > ~/.devflow/current-skill.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
16
|
+
- `mcp__devflow__get_memory`
|
|
17
|
+
|
|
18
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
19
|
+
|
|
20
|
+
When the skill execution is complete, clean up:
|
|
21
|
+
```bash
|
|
22
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
23
|
+
```
|
|
24
|
+
|
|
7
25
|
|
|
8
26
|
# /devflow:memory
|
|
9
27
|
|
|
@@ -5,6 +5,25 @@ required_mcp_tools:
|
|
|
5
5
|
- nest_new_module
|
|
6
6
|
- nest_diagnose_bug
|
|
7
7
|
---
|
|
8
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
9
|
+
|
|
10
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:nest","required_mcp_tools":["nest_new_module","nest_diagnose_bug"],"description":"devflow:nest skill"}' > ~/.devflow/current-skill.json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
17
|
+
- `mcp__devflow__nest_new_module`
|
|
18
|
+
- `mcp__devflow__nest_diagnose_bug`
|
|
19
|
+
|
|
20
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
21
|
+
|
|
22
|
+
When the skill execution is complete, clean up:
|
|
23
|
+
```bash
|
|
24
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
25
|
+
```
|
|
26
|
+
|
|
8
27
|
|
|
9
28
|
# 🐱 NEST
|
|
10
29
|
|
|
@@ -5,6 +5,25 @@ required_mcp_tools:
|
|
|
5
5
|
- nextjs_new_page
|
|
6
6
|
- nextjs_diagnose_bug
|
|
7
7
|
---
|
|
8
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
9
|
+
|
|
10
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:nextjs","required_mcp_tools":["nextjs_new_page","nextjs_diagnose_bug"],"description":"devflow:nextjs skill"}' > ~/.devflow/current-skill.json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
17
|
+
- `mcp__devflow__nextjs_new_page`
|
|
18
|
+
- `mcp__devflow__nextjs_diagnose_bug`
|
|
19
|
+
|
|
20
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
21
|
+
|
|
22
|
+
When the skill execution is complete, clean up:
|
|
23
|
+
```bash
|
|
24
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
25
|
+
```
|
|
26
|
+
|
|
8
27
|
|
|
9
28
|
# ▲ NEXTJS
|
|
10
29
|
|
|
@@ -4,6 +4,24 @@ description: Web 性能专家 — Core Web Vitals、Bundle 优化、加载策略
|
|
|
4
4
|
required_mcp_tools:
|
|
5
5
|
- performance_audit_performance
|
|
6
6
|
---
|
|
7
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
8
|
+
|
|
9
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:performance","required_mcp_tools":["performance_audit_performance"],"description":"devflow:performance skill"}' > ~/.devflow/current-skill.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
16
|
+
- `mcp__devflow__performance_audit_performance`
|
|
17
|
+
|
|
18
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
19
|
+
|
|
20
|
+
When the skill execution is complete, clean up:
|
|
21
|
+
```bash
|
|
22
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
23
|
+
```
|
|
24
|
+
|
|
7
25
|
|
|
8
26
|
# ⚡ PERFORMANCE
|
|
9
27
|
|
|
@@ -9,6 +9,29 @@ required_mcp_tools:
|
|
|
9
9
|
- react_refactor_component
|
|
10
10
|
- react_new_component
|
|
11
11
|
---
|
|
12
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
13
|
+
|
|
14
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:react","required_mcp_tools":["react_diagnose_bug","react_new_feature","react_audit_performance","react_review_hooks","react_refactor_component","react_new_component"],"description":"devflow:react skill"}' > ~/.devflow/current-skill.json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
21
|
+
- `mcp__devflow__react_diagnose_bug`
|
|
22
|
+
- `mcp__devflow__react_new_feature`
|
|
23
|
+
- `mcp__devflow__react_audit_performance`
|
|
24
|
+
- `mcp__devflow__react_review_hooks`
|
|
25
|
+
- `mcp__devflow__react_refactor_component`
|
|
26
|
+
- `mcp__devflow__react_new_component`
|
|
27
|
+
|
|
28
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
29
|
+
|
|
30
|
+
When the skill execution is complete, clean up:
|
|
31
|
+
```bash
|
|
32
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
33
|
+
```
|
|
34
|
+
|
|
12
35
|
|
|
13
36
|
# ⚛️ REACT
|
|
14
37
|
|
|
@@ -4,6 +4,24 @@ description: Tailwind 专家 — 响应式设计、主题定制、Purge 检查
|
|
|
4
4
|
required_mcp_tools:
|
|
5
5
|
- tailwind_new_component
|
|
6
6
|
---
|
|
7
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
8
|
+
|
|
9
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:tailwind","required_mcp_tools":["tailwind_new_component"],"description":"devflow:tailwind skill"}' > ~/.devflow/current-skill.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
16
|
+
- `mcp__devflow__tailwind_new_component`
|
|
17
|
+
|
|
18
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
19
|
+
|
|
20
|
+
When the skill execution is complete, clean up:
|
|
21
|
+
```bash
|
|
22
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
23
|
+
```
|
|
24
|
+
|
|
7
25
|
|
|
8
26
|
# 🌊 TAILWIND
|
|
9
27
|
|
|
@@ -4,6 +4,24 @@ description: Taro 跨端专家 — 多端适配、小程序调试、性能优化
|
|
|
4
4
|
required_mcp_tools:
|
|
5
5
|
- taro_new_page
|
|
6
6
|
---
|
|
7
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
8
|
+
|
|
9
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:taro","required_mcp_tools":["taro_new_page"],"description":"devflow:taro skill"}' > ~/.devflow/current-skill.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
16
|
+
- `mcp__devflow__taro_new_page`
|
|
17
|
+
|
|
18
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
19
|
+
|
|
20
|
+
When the skill execution is complete, clean up:
|
|
21
|
+
```bash
|
|
22
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
23
|
+
```
|
|
24
|
+
|
|
7
25
|
|
|
8
26
|
# 🛠️ TARO
|
|
9
27
|
|
|
@@ -6,6 +6,26 @@ required_mcp_tools:
|
|
|
6
6
|
- vue_new_component
|
|
7
7
|
- vue_debug_reactivity
|
|
8
8
|
---
|
|
9
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
10
|
+
|
|
11
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:vue","required_mcp_tools":["vue_diagnose_bug","vue_new_component","vue_debug_reactivity"],"description":"devflow:vue skill"}' > ~/.devflow/current-skill.json
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
18
|
+
- `mcp__devflow__vue_diagnose_bug`
|
|
19
|
+
- `mcp__devflow__vue_new_component`
|
|
20
|
+
- `mcp__devflow__vue_debug_reactivity`
|
|
21
|
+
|
|
22
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
23
|
+
|
|
24
|
+
When the skill execution is complete, clean up:
|
|
25
|
+
```bash
|
|
26
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
27
|
+
```
|
|
28
|
+
|
|
9
29
|
|
|
10
30
|
# 💚 VUE
|
|
11
31
|
|
|
@@ -4,6 +4,24 @@ description: 执行标准化开发工作流 — Bug 修复、功能开发、代
|
|
|
4
4
|
required_mcp_tools:
|
|
5
5
|
- run_workflow
|
|
6
6
|
---
|
|
7
|
+
## MANDATORY FIRST STEP - Skill Registration
|
|
8
|
+
|
|
9
|
+
> **IMPORTANT: Before ANY other action, execute the registration command below. This is NON-NEGOTIABLE.**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
mkdir -p ~/.devflow && echo '{"name":"devflow:workflow","required_mcp_tools":["run_workflow"],"description":"devflow:workflow skill"}' > ~/.devflow/current-skill.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
After registration, you **MUST** use ONLY these MCP tools for all work in this skill:
|
|
16
|
+
- `mcp__devflow__run_workflow`
|
|
17
|
+
|
|
18
|
+
**Never use direct tools** (Read, Write, Edit, Bash, Grep, etc.) for tasks that can be handled by the MCP tools above.
|
|
19
|
+
|
|
20
|
+
When the skill execution is complete, clean up:
|
|
21
|
+
```bash
|
|
22
|
+
rm -f ~/.devflow/current-skill.json ~/.devflow/current-execution-id
|
|
23
|
+
```
|
|
24
|
+
|
|
7
25
|
|
|
8
26
|
# /devflow:workflow
|
|
9
27
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devflow-tools/devflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "DevFlow - Developer Intelligence Platform (Distribution Package)",
|
|
6
6
|
"bin": {
|
|
@@ -15,16 +15,16 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@colbymchenry/codegraph": "^1.1.1",
|
|
18
|
-
"@devflow-tools/adapters": "^0.
|
|
19
|
-
"@devflow-tools/benchmark": "^0.
|
|
20
|
-
"@devflow-tools/context-engine": "^0.
|
|
21
|
-
"@devflow-tools/database": "^0.
|
|
22
|
-
"@devflow-tools/knowledge-engine": "^0.
|
|
23
|
-
"@devflow-tools/mcp-server": "^0.
|
|
24
|
-
"@devflow-tools/memory-engine": "^0.
|
|
25
|
-
"@devflow-tools/sdk": "^0.
|
|
26
|
-
"@devflow-tools/telemetry": "^0.
|
|
27
|
-
"@devflow-tools/workflow-engine": "^0.
|
|
18
|
+
"@devflow-tools/adapters": "^0.8.0",
|
|
19
|
+
"@devflow-tools/benchmark": "^0.8.0",
|
|
20
|
+
"@devflow-tools/context-engine": "^0.8.0",
|
|
21
|
+
"@devflow-tools/database": "^0.8.0",
|
|
22
|
+
"@devflow-tools/knowledge-engine": "^0.8.0",
|
|
23
|
+
"@devflow-tools/mcp-server": "^0.8.0",
|
|
24
|
+
"@devflow-tools/memory-engine": "^0.8.0",
|
|
25
|
+
"@devflow-tools/sdk": "^0.8.0",
|
|
26
|
+
"@devflow-tools/telemetry": "^0.8.0",
|
|
27
|
+
"@devflow-tools/workflow-engine": "^0.8.0",
|
|
28
28
|
"@inquirer/prompts": "^7.10.1",
|
|
29
29
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
30
30
|
"@nestjs/common": "^10.4.0",
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"plugin-registry.json",
|
|
52
52
|
"scripts/postinstall.js"
|
|
53
53
|
],
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "5c9a804d3c2e6e6822b516fde67d5b789dbdb5b3"
|
|
55
55
|
}
|