@devflow-tools/devflow 0.8.10 → 0.9.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.
Files changed (33) hide show
  1. package/README.md +34 -21
  2. package/dist/hooks/post-tool-use.js +2 -0
  3. package/dist/hooks/pre-tool-use.js +2 -2
  4. package/dist/hooks/stop.js +2 -0
  5. package/package.json +14 -14
  6. package/plugin-registry.json +40 -24
  7. package/dist/cli.js +0 -46
  8. package/dist/fallback.html +0 -106
  9. package/dist/mcp-server.js +0 -2
  10. package/dist/plugin/hooks.json +0 -40
  11. package/dist/plugin/skills/devflow/SKILL.md +0 -20
  12. package/dist/plugin/skills/devflow:animation/SKILL.md +0 -39
  13. package/dist/plugin/skills/devflow:context/SKILL.md +0 -44
  14. package/dist/plugin/skills/devflow:css/SKILL.md +0 -39
  15. package/dist/plugin/skills/devflow:docker/SKILL.md +0 -62
  16. package/dist/plugin/skills/devflow:doctor/SKILL.md +0 -17
  17. package/dist/plugin/skills/devflow:electron/SKILL.md +0 -62
  18. package/dist/plugin/skills/devflow:git/SKILL.md +0 -43
  19. package/dist/plugin/skills/devflow:graph/SKILL.md +0 -37
  20. package/dist/plugin/skills/devflow:graphql/SKILL.md +0 -63
  21. package/dist/plugin/skills/devflow:knowledge/SKILL.md +0 -37
  22. package/dist/plugin/skills/devflow:memory/SKILL.md +0 -36
  23. package/dist/plugin/skills/devflow:nest/SKILL.md +0 -63
  24. package/dist/plugin/skills/devflow:nextjs/SKILL.md +0 -60
  25. package/dist/plugin/skills/devflow:performance/SKILL.md +0 -62
  26. package/dist/plugin/skills/devflow:react/SKILL.md +0 -80
  27. package/dist/plugin/skills/devflow:start/SKILL.md +0 -54
  28. package/dist/plugin/skills/devflow:tailwind/SKILL.md +0 -58
  29. package/dist/plugin/skills/devflow:taro/SKILL.md +0 -61
  30. package/dist/plugin/skills/devflow:ui-layout/SKILL.md +0 -39
  31. package/dist/plugin/skills/devflow:vue/SKILL.md +0 -69
  32. package/dist/plugin/skills/devflow:workflow/SKILL.md +0 -37
  33. package/dist/server.js +0 -10
@@ -1,106 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>DevFlow</title>
7
- <style>
8
- * { margin: 0; padding: 0; box-sizing: border-box; }
9
- body {
10
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
11
- background: #0a0a0a;
12
- color: #fafafa;
13
- display: flex;
14
- align-items: center;
15
- justify-content: center;
16
- min-height: 100vh;
17
- }
18
- .container {
19
- text-align: center;
20
- padding: 2rem;
21
- }
22
- .logo {
23
- font-size: 3rem;
24
- font-weight: 700;
25
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
26
- -webkit-background-clip: text;
27
- -webkit-text-fill-color: transparent;
28
- margin-bottom: 1rem;
29
- }
30
- .status {
31
- color: #a1a1aa;
32
- font-size: 1.1rem;
33
- margin-bottom: 2rem;
34
- }
35
- .spinner {
36
- width: 40px;
37
- height: 40px;
38
- border: 3px solid #27272a;
39
- border-top-color: #667eea;
40
- border-radius: 50%;
41
- animation: spin 0.8s linear infinite;
42
- margin: 0 auto 1.5rem;
43
- }
44
- @keyframes spin {
45
- to { transform: rotate(360deg); }
46
- }
47
- .info {
48
- color: #52525b;
49
- font-size: 0.85rem;
50
- margin-top: 2rem;
51
- }
52
- .server-ok {
53
- color: #22c55e;
54
- }
55
- .server-wait {
56
- color: #eab308;
57
- }
58
- </style>
59
- </head>
60
- <body>
61
- <div class="container">
62
- <div class="logo">DevFlow</div>
63
- <div class="spinner" id="spinner"></div>
64
- <div class="status" id="status">Preparing dashboard...</div>
65
- <div class="info" id="info">Checking server status...</div>
66
- </div>
67
- <script>
68
- let attempts = 0;
69
- const maxAttempts = 60;
70
-
71
- async function checkStatus() {
72
- attempts++;
73
- const statusEl = document.getElementById('status');
74
- const infoEl = document.getElementById('info');
75
- const spinnerEl = document.getElementById('spinner');
76
-
77
- try {
78
- const res = await fetch('/api/projects/active', {
79
- headers: { 'x-api-key': 'dev-key-000000' }
80
- });
81
-
82
- if (res.ok) {
83
- infoEl.textContent = 'Server is running. Dashboard will appear when download completes.';
84
- infoEl.className = 'info server-ok';
85
- } else {
86
- infoEl.textContent = 'Waiting for server...';
87
- infoEl.className = 'info server-wait';
88
- }
89
- } catch {
90
- infoEl.textContent = 'Waiting for server...';
91
- infoEl.className = 'info server-wait';
92
- }
93
-
94
- if (attempts < maxAttempts) {
95
- setTimeout(checkStatus, 3000);
96
- } else {
97
- statusEl.textContent = 'Dashboard download is taking longer than expected';
98
- spinnerEl.style.display = 'none';
99
- infoEl.textContent = 'The server is running. You can use the API at /api. The dashboard will appear when ready.';
100
- }
101
- }
102
-
103
- checkStatus();
104
- </script>
105
- </body>
106
- </html>
@@ -1,2 +0,0 @@
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 pe=Object.defineProperty;var h=(t,e)=>()=>(t&&(e=t(t=0)),e);var F=(t,e)=>{for(var o in e)pe(t,o,{get:e[o],enumerable:true});};var L={};F(L,{createPluginHandlers:()=>fe,createToolHandlers:()=>me,getCoreTools:()=>j,getPluginTools:()=>C});function j(){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 me(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=(d,m)=>!d||d.length<=m?{value:d??"",truncated:false}:{value:d.slice(0,m),truncated:true},r=o(e.prompt,500),n=o(e.response,500),s=o(e.stdout,1e3),a=o(e.stderr,500),i=r.truncated||n.truncated||s.truncated||a.truncated,u={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:a.value,mcpToolName:e.mcpToolName,errorMessage:e.errorMessage,errorStack:e.errorStack,memoryKey:e.memoryKey,userMessage:e.userMessage},metadata:{source:"manual"},...i&&{metadata:{truncated:true,source:"manual"}}};return await t.telemetry.recordEvent(u),{acknowledged:true,eventId:u.id}}}}function C(t){let e=[];for(let o of t){let r=o.meta.name;for(let s of o.tools??[])e.push({name:s.name,description:s.description,inputSchema:s.inputSchema});let n=new Set(e.map(s=>s.name));for(let s of o.workflow?.templates??[]){let a=s.triggers?.find(u=>u.type==="mcp");if(!a?.tool)continue;let i=`${r}_${a.tool}`;n.has(i)||e.push({name:i,description:s.description,inputSchema:{type:"object",properties:s.steps.filter(u=>u.inputSchema).reduce((u,d)=>({...u,...d.inputSchema??{}}),{}),required:[]}});}}return e}function fe(t,e){let o={};for(let r of e){let n=r.meta.name;for(let s of r.tools??[])s.handler&&(o[s.name]=s.handler);for(let s of r.workflow?.templates??[]){let a=s.triggers?.find(u=>u.type==="mcp");if(!a?.tool)continue;let i=`${n}_${a.tool}`;o[i]||(o[i]=async u=>{let d=await t.workflow.run(s.name,u),m="";try{let l={id:d.runId??`run:${Date.now()}`,source:"mcp",tool:i,workflow:s.name,input:u,status:"running",startedAt:Date.now(),finishedAt:null,steps:[],metadata:{}};m=t.workflow.renderPlan(l,s);}catch{}return {...d,plan:m,_devflow_unique:{dag_orchestrated:true,step_tracked:true,plugin_name:n,template_name:s.name}}});}}return o}var M=h(()=>{});var T,A=h(()=>{T=[{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 J(t){let e=await t.ruleGetAll();return [...T,...e]}function ge(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=W.get(r);if((!s||n>s.resetAt)&&(s={count:0,resetAt:n+6e4},W.set(r,s)),s.count++,s.count>o.maxCallsPerMinute)return t.action}return "allow"}function K(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=ge(r,e);if(n!=="allow")return {decision:n,rule:r}}return {decision:"allow"}}var W,U=h(()=>{A();W=new Map;});function x(t){let e=JSON.stringify(t,Object.keys(t).sort());return createHash("sha256").update(e).digest("hex")}async function q(t,e,o,r,n,s){let a=await t.auditGetSecret(),i=await t.auditGetAll(),u=i.length>0?i[i.length-1].signature:createHash("sha256").update("genesis").digest("hex"),d=Date.now(),m=i.length+1,l=`${m}|${d}|${e}|${o}|${r}|${n??""}|${s}|${u}`,f=createHmac("sha256",a).update(l).digest("hex");await t.auditAppend({seq:m,ts:d,tool:e,argsHash:o,decision:r,ruleId:n,sessionId:s,prevHash:u,signature:f});}async function G(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}`,a=createHmac("sha256",e).update(s).digest("hex");if(n.signature!==a)return {valid:false,brokenAt:n.seq};r=n.signature;}return {valid:true,brokenAt:null}}async function V(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}`,a=createHmac("sha256",e).update(s).digest("hex");await t.sqlExecute("UPDATE devflow_audit_chain SET prev_hash = ?, signature = ? WHERE seq = ?",[r,a,n.seq]),r=a;}}var O=h(()=>{});function S(t,e,o){let r=Date.now(),n=r+we,s=createHash("sha256").update(JSON.stringify(e)).digest("hex"),a=`${t}|${r}|${n}|${s}`,i=createHmac("sha256",o).update(a).digest("hex");return {tool:t,ts:r,exp:n,queryHash:s,hmac:i}}function X(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}`,a=createHmac("sha256",r).update(s).digest("hex");return t.hmac===a}function Y(t){return Date.now()>t.exp}var we,H=h(()=>{we=3e4;});var Z={};F(Z,{CONSTITUTIONAL_RULES:()=>T,enforce:()=>ye,hashArgs:()=>x,isReceiptExpired:()=>Y,issueReceipt:()=>S,parseJwtPayload:()=>Q,rebuildAuditChain:()=>V,verifyAuditChain:()=>G,verifyReceipt:()=>X});function Q(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 ye(t,e,o){if(!e._devflow_token){let l=process.env.DEVFLOW_SESSION_TOKEN;if(l){let f=Q(l);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 l=Math.floor(Date.now()/1e3);if(n.tokenPayload.exp&&l>n.tokenPayload.exp){let f=x(e);return await q(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 J(o),{decision:a,rule:i}=K(s,n),u=x(e);if(await q(o,t,u,a,i?.id??null,r),a==="deny"&&i)return {result:{allowed:false,rule:i,message:i.message}};if(a==="warn"&&i){let l=await o.auditGetSecret(),f=S(t,e,l);return {result:{allowed:true,warning:i.message,rule:i},receipt:f}}let d=await o.auditGetSecret(),m=S(t,e,d);return {result:{allowed:true},receipt:m}}var ee=h(()=>{U();O();H();O();H();A();});M();async function se(t){Ee(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(),a=await loadPlugins(),i=Array.from(a.values()),u=j(),d=C(i),m=[...u,...d];e.setRequestHandler(ListToolsRequestSchema,async()=>({tools:m}));let l=null;e.setRequestHandler(CallToolRequestSchema,async ie=>{let{name:c,arguments:ce}=ie.params,w=ce??{},E=Date.now();try{let p;if(s){p=await Ce(n,c,w),ne(t.projectRoot,c);let y=Date.now()-E,g=c.split("_")[0];try{await n.recordTelemetryEvent({toolName:c,args:w,durationMs:y,success:!0,pluginName:g,metadata:{projectRoot:t.projectRoot}});}catch(_){console.error("[devflow-mcp] Failed to record telemetry:",_);}try{await n.recordMemoryEvent({id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:`session:${t.projectRoot.split("/").pop()??"default"}`,tool:c,command:R(c)||c,exitCode:0,durationMs:y});}catch(_){console.error("[devflow-mcp] Failed to record memory event:",_);}}else {if(!l){let[{createEngines:b}]=await Promise.all([import('@devflow-tools/context-engine')]);l=await b(t.projectRoot);for(let P of i)for(let k of P.workflow?.templates??[])l.workflow.register(k);console.error(`[devflow-mcp] Warning: DevFlow server not reachable at ${o}`),console.error("[devflow-mcp] Running in local mode.");}let{enforce:y}=await Promise.resolve().then(()=>(ee(),Z)),g=await y(c,w,l.data);if(!g.result.allowed)return {content:[{type:"text",text:JSON.stringify({_devflow:{v:1,tool:c,ts:Date.now(),marker:"devflow-mcp-v1"},error:g.result.message,rule:g.result.rule?.id})}],isError:!0};let{createToolHandlers:_,createPluginHandlers:le}=await Promise.resolve().then(()=>(M(),L)),ue=_(l),de=le(l,i),N={...ue,...de}[c];if(!N)throw new Error(`Unknown tool: ${c}`);p=await N(w),ne(t.projectRoot,c);let D=Date.now()-E;try{await l.data.recordToolCall(c,w,D);let b=c.startsWith("devflow_")||c.includes("_"),P=c.split("_")[0],k=ae.has(P);await l.telemetry.recordToolCall({eventId:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,executionId:`exec:${t.projectRoot.split("/").pop()??"default"}:${Date.now()}`,timestamp:Date.now(),toolName:c,toolType:b||k?"mcp":"direct",isMcpTool:b||k,mcpToolName:k?c:void 0,mcpEnforced:!0,mcpFallback:!1,input:w,output:De(p),tokensUsed:0,duration:D,blocked:!1});}catch{}try{await l.memory.recordEvent({id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:`session:${t.projectRoot.split("/").pop()??"default"}`,tool:c,command:R(c)||c,exitCode:0,stderr:void 0,durationMs:D,createdAt:Date.now()}),l.memory.processSessionEvents().catch(()=>{});}catch{}g.receipt&&(p={...p,_receipt:g.receipt}),g.result.warning&&(p={...p,_warning:g.result.warning});}let v=Pe(c,p);return {content:[{type:"text",text:JSON.stringify(v,null,2)}]}}catch(p){let v=Date.now()-E;if(s){try{await n.recordTelemetryEvent({toolName:c,args:w,durationMs:v,success:!1,error:p.message,pluginName:c.split("_")[0],metadata:{projectRoot:t.projectRoot}});}catch(y){console.error("[devflow-mcp] Failed to record error telemetry:",y);}try{await n.recordMemoryEvent({id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:`session:${t.projectRoot.split("/").pop()??"default"}`,tool:c,command:R(c)||c,exitCode:1,stderr:p.message,durationMs:v});}catch(y){console.error("[devflow-mcp] Failed to record error memory event:",y);}}else if(l){try{await l.data.recordToolCall(c,w,v,p.message);}catch{}try{await l.memory.recordEvent({id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:`session:${t.projectRoot.split("/").pop()??"default"}`,tool:c,command:R(c)||c,exitCode:1,stderr:p.message,durationMs:v,createdAt:Date.now()});}catch{}}return {content:[{type:"text",text:`Error: ${p.message}`}],isError:true}}});let f=new StdioServerTransport;await e.connect(f);}function Ee(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"),a=createHmac("sha256","devflow-local-mcp-secret-v1").update(`${e}.${n}`).digest("base64url");process.env.DEVFLOW_SESSION_TOKEN=`${e}.${n}.${a}`,console.error("[devflow-mcp] Auto-generated session token (no env token provided).");}var ae=new Set(["react","vue","nest","nextjs","graphql","docker","tailwind","taro","electron","performance"]);function R(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 ae.has(o)?`devflow:${o}`:""}function ne(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 a={};if(existsSync(s))try{a=JSON.parse(readFileSync(s,"utf-8"));}catch{}a.lastMcpCall=Date.now(),a.bypassCount=0;let i=R(e);i&&(a.activeCommand=i),writeFileSync(s,JSON.stringify(a));}catch{}}function De(t){if(t&&typeof t=="object"&&!Array.isArray(t)){let{_devflow:e,_receipt:o,_warning:r,...n}=t;return Object.keys(n).length>0?n:t}return t}function Pe(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 a=s.triggers?.find(i=>i.type==="mcp");if(a?.tool){let i=`${n}_${a.tool}`;t.set(i,s.name);}}}return t}async function Ce(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 Me(){let t=process.env.DEVFLOW_PROJECT_ROOT||process.cwd();await se({mode:"stdio",projectRoot:t});}Me().catch(t=>{console.error("MCP Server error:",t),process.exit(1);});
@@ -1,40 +0,0 @@
1
- {
2
- "hooks": {
3
- "SessionStart": [
4
- {
5
- "matcher": "",
6
- "hooks": [
7
- {
8
- "type": "command",
9
- "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start\"",
10
- "async": false
11
- }
12
- ]
13
- }
14
- ],
15
- "PreToolUse": [
16
- {
17
- "matcher": "*",
18
- "hooks": [
19
- {
20
- "type": "command",
21
- "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/pre-tool-use\"",
22
- "async": false
23
- }
24
- ]
25
- }
26
- ],
27
- "PostToolUse": [
28
- {
29
- "matcher": "*",
30
- "hooks": [
31
- {
32
- "type": "command",
33
- "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use\"",
34
- "async": false
35
- }
36
- ]
37
- }
38
- ]
39
- }
40
- }
@@ -1,20 +0,0 @@
1
- ---
2
- name: devflow
3
- description: DevFlow — 项目开发智能平台。代码检索、图谱、记忆、工作流一站式工具集。
4
- required_mcp_tools: []
5
- ---
6
-
7
- # DevFlow
8
-
9
- 你已接入 DevFlow 开发智能平台。收到 /devflow: 前缀命令时,只做一件事:调用对应的 MCP 工具。
10
-
11
- | 命令 | 只调用这个工具 |
12
- |------|-------------|
13
- | /devflow:context | get_project_context |
14
- | /devflow:graph | get_dependency_graph |
15
- | /devflow:memory | get_memory |
16
- | /devflow:knowledge | get_knowledge |
17
- | /devflow:workflow | run_workflow |
18
- | /devflow:doctor | get_project_context |
19
-
20
- 领域插件(/devflow:react, /devflow:vue, /devflow:nextjs, /devflow:nest, /devflow:tailwind, /devflow:docker, /devflow:electron, /devflow:graphql, /devflow:git, /devflow:performance, /devflow:animation, /devflow:css, /devflow:taro, /devflow:ui-layout)— 每个都有对应的 MCP 工具。
@@ -1,39 +0,0 @@
1
- ---
2
- name: devflow:animation
3
- description: Animation 动画专家 — CSS 动画、Framer Motion、GSAP、Lottie、性能优化
4
- required_mcp_tools: []
5
- ---
6
-
7
- # ✨ ANIMATION
8
-
9
- 你是一个动画专家。精通 CSS Animation、Framer Motion、GSAP。动画必须 60fps 且支持 prefers-reduced-motion。
10
-
11
- ## 适用场景
12
-
13
- **动画审计:性能检查 → 可访问性 → 实现质量**
14
-
15
- **新建动画:需求分析 → 选型建议 → 实现 → 性能验证**
16
-
17
- **动画 GPU 迁移:扫描 → 替换为 GPU 属性 → 验证**
18
-
19
- ## 核心规则
20
-
21
- - 动画属性只使用 transform 和 opacity(GPU 加速)
22
- - 过渡动画 200-300ms,入场 300-500ms
23
- - 使用 ease-out 入场、ease-in 退场
24
- - 尊重 prefers-reduced-motion,提供减弱方案
25
- - 避免同时动画过多元素(批量编排使用 staggerChildren)
26
- - 使用 AnimatePresence 处理 React 组件退出动画
27
- - Lottie 动画控制文件大小 < 50KB
28
-
29
- ## 当前版本
30
-
31
- - animation-docs: 2024 — https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animations
32
-
33
- ## 工作流
34
-
35
- | 场景 | 触发方式 |
36
- |------|----------|
37
- | 动画审计:性能检查 → 可访问性 → 实现质量 | 调用 MCP 工具 `animation_audit:animation` |
38
- | 新建动画:需求分析 → 选型建议 → 实现 → 性能验证 | 调用 MCP 工具 `animation_new:animation` |
39
- | 动画 GPU 迁移:扫描 → 替换为 GPU 属性 → 验证 | 调用 MCP 工具 `animation_migrate:gpu-animation` |
@@ -1,44 +0,0 @@
1
- ---
2
- name: devflow:context
3
- description: 检索项目上下文 — 自然语言查询相关代码、符号、依赖关系
4
- required_mcp_tools:
5
- - get_project_context
6
- - search_symbol
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","registeredAt":'"$(date +%s)000"'}' > ~/.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
-
27
-
28
- # /devflow:context
29
-
30
- ## 执行
31
-
32
- 1. 如果用户的查询包含中文,先将其中的中文关键词翻译为英文代码术语(空格分隔)
33
- 2. 调用 `get_project_context` MCP 工具:
34
-
35
- ```
36
- query = 用户的原始查询内容(包含中文)
37
- expandedTerms = 你翻译的英文关键词(如 "code review audit module")
38
- mode = "fast" (首次调用;如需更深入结果,再改用 "deep")
39
- ```
40
-
41
- 示例:
42
- - 用户查询 "代码审核模块的流程" → expandedTerms = "code review audit module workflow pipeline process"
43
- - 用户查询 "用户登录认证逻辑" → expandedTerms = "user login authentication auth logic service handler"
44
- - 用户查询 "数据库缓存策略" → expandedTerms = "database db cache memo redis storage strategy"
@@ -1,39 +0,0 @@
1
- ---
2
- name: devflow:css
3
- description: CSS 专家 — 布局调试、响应式审查、BEM 规范、性能优化
4
- required_mcp_tools: []
5
- ---
6
-
7
- # 🎨 CSS
8
-
9
- 你是一个 CSS 专家。使用现代布局方案(Flexbox/Grid),遵循 BEM 命名,移动优先响应式设计。遇到问题先查 MDN 文档。
10
-
11
- ## 适用场景
12
-
13
- **布局调试:检查元素定位 → 弹性/网格属性 → 修复**
14
-
15
- **响应式审查:断点检查 → 媒体查询 → 流体方案**
16
-
17
- **BEM 命名审查:扫描类名 → 规范检查 → 修复建议**
18
-
19
- ## 核心规则
20
-
21
- - 使用 BEM 命名规范
22
- - 优先使用 Flexbox 和 Grid 布局
23
- - 移动优先响应式设计
24
- - 使用 CSS 变量管理主题
25
- - 避免 !important 和深层嵌套
26
- - 使用 rem/em 做相对单位
27
- - 不确定属性行为时先查 MDN 文档确认
28
-
29
- ## 当前版本
30
-
31
- - mdn-css: 2024 — https://developer.mozilla.org/en-US/docs/Web/CSS
32
-
33
- ## 工作流
34
-
35
- | 场景 | 触发方式 |
36
- |------|----------|
37
- | 布局调试:检查元素定位 → 弹性/网格属性 → 修复 | 调用 MCP 工具 `css_debug:layout` |
38
- | 响应式审查:断点检查 → 媒体查询 → 流体方案 | 调用 MCP 工具 `css_audit:responsive` |
39
- | BEM 命名审查:扫描类名 → 规范检查 → 修复建议 | 调用 MCP 工具 `css_review:bem` |
@@ -1,62 +0,0 @@
1
- ---
2
- name: devflow:docker
3
- description: Docker 专家 — 镜像优化、Compose 编排、安全扫描、多阶段构建
4
- required_mcp_tools:
5
- - docker_dockerize_project
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","registeredAt":'"$(date +%s)000"'}' > ~/.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
-
25
-
26
- # 🐳 DOCKER
27
-
28
- 你是一个 Docker 专家。使用多阶段构建优化镜像,遵循安全和性能最佳实践。遇到问题先查官方文档。
29
-
30
- ## 适用场景
31
-
32
- **项目 Docker 化:分析项目 → 多阶段 Dockerfile → Compose → 构建验证**
33
-
34
- **镜像优化:体积分析 → 层优化 → 多阶段重构**
35
-
36
- **安全扫描:漏洞检测 → 配置审查 → 修复建议**
37
-
38
- **多服务 Compose 编排:依赖分析 → 网络设计 → 环境管理**
39
-
40
- ## 核心规则
41
-
42
- - 使用多阶段构建减小镜像体积
43
- - 基础镜像固定版本标签(不使用 latest)
44
- - 利用层缓存优化构建顺序
45
- - 使用非 root 用户运行应用
46
- - 使用 .dockerignore 排除无用文件
47
- - 添加 HEALTHCHECK 监控容器健康状态
48
- - 不在镜像层中写入敏感信息
49
- - 修复安全问题时先查 Docker 官方文档确认方案
50
-
51
- ## 当前版本
52
-
53
- - docker-docs: 26.0.0 — https://docs.docker.com/reference/
54
-
55
- ## 工作流
56
-
57
- | 场景 | 触发方式 |
58
- |------|----------|
59
- | 项目 Docker 化:分析项目 → 多阶段 Dockerfile → Compose → 构建验证 | 调用 MCP 工具 `docker_dockerize_project` |
60
- | 镜像优化:体积分析 → 层优化 → 多阶段重构 | 调用 MCP 工具 `docker_optimize:image` |
61
- | 安全扫描:漏洞检测 → 配置审查 → 修复建议 | 调用 MCP 工具 `docker_scan:security` |
62
- | 多服务 Compose 编排:依赖分析 → 网络设计 → 环境管理 | 调用 MCP 工具 `docker_setup:compose` |
@@ -1,17 +0,0 @@
1
- ---
2
- name: devflow:doctor
3
- description: 项目健康检查 — 索引状态、引擎就绪、插件列表
4
- required_mcp_tools: []
5
- ---
6
-
7
- # 项目健康检查
8
-
9
- 快速了解 DevFlow 在当前项目中的运行状态。任务开始前用一次即可。
10
-
11
- ## 检查项
12
-
13
- - 文件索引是否最新
14
- - Context/Graph/Memory/Knowledge/Workflow 引擎是否就绪
15
- - 已安装哪些领域插件
16
- - 是否有已知配置问题
17
- **MCP Gateway 策略**: 调用前会校验 Session Token 和调用合法性。无有效收据的情况下直接使用原生工具(grep/Glob/WebSearch)将被 PreToolUse Hook 拦截。收据有效期 30 秒,过期后需重新通过 MCP 工具获取。
@@ -1,62 +0,0 @@
1
- ---
2
- name: devflow:electron
3
- description: Electron 专家 — IPC 通信、窗口管理、原生模块、自动更新、安全配置
4
- required_mcp_tools:
5
- - electron_diagnose_bug
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","registeredAt":'"$(date +%s)000"'}' > ~/.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
-
25
-
26
- # ⚛️ ELECTRON
27
-
28
- 你是一个 Electron 专家。使用 contextBridge + IPC 安全通信模式。严格遵循 Electron 安全最佳实践。
29
-
30
- ## 适用场景
31
-
32
- **新建 IPC 通道:定义 API → Preload 暴露 → 主进程处理**
33
-
34
- **安全审计:配置检查 → IPC 暴露面 → CSP → 第三方依赖**
35
-
36
- **自动更新配置:electron-updater → 发布渠道 → 更新 UI**
37
-
38
- **Electron Bug 诊断:进程分类 → IPC 追踪 → 原生调试**
39
-
40
- ## 核心规则
41
-
42
- - 使用 contextBridge + ipcRenderer/ipcMain 通信
43
- - 必须启用 contextIsolation,禁用 nodeIntegration
44
- - 主进程负责系统操作,渲染进程只做 UI
45
- - Preload 脚本只暴露最小必要的安全 API
46
- - 使用 electron-updater 实现自动更新
47
- - 启用 sandbox 和 CSP 安全策略
48
- - 避免使用 remote 模块(已废弃)
49
- - 构建使用 electron-builder 并配置代码签名
50
-
51
- ## 当前版本
52
-
53
- - electron-docs: 30.0.0 — https://www.electronjs.org/docs/latest/
54
-
55
- ## 工作流
56
-
57
- | 场景 | 触发方式 |
58
- |------|----------|
59
- | 新建 IPC 通道:定义 API → Preload 暴露 → 主进程处理 | 调用 MCP 工具 `electron_new:ipc` |
60
- | 安全审计:配置检查 → IPC 暴露面 → CSP → 第三方依赖 | 调用 MCP 工具 `electron_audit:security` |
61
- | 自动更新配置:electron-updater → 发布渠道 → 更新 UI | 调用 MCP 工具 `electron_setup:auto-update` |
62
- | Electron Bug 诊断:进程分类 → IPC 追踪 → 原生调试 | 调用 MCP 工具 `electron_diagnose_bug` |
@@ -1,43 +0,0 @@
1
- ---
2
- name: devflow:git
3
- description: Git 专家 — 提交规范、分支审查、Changelog 生成、冲突解决
4
- required_mcp_tools: []
5
- ---
6
-
7
- # 🔀 GIT
8
-
9
- 你是一个 Git 工作流专家。遵循 Conventional Commits 规范和 GitFlow 分支策略。
10
-
11
- ## 适用场景
12
-
13
- **规范化提交:** 代码改完了要提交 → 检查分支命名,分析变更内容,生成 Conventional Commits 格式的提交信息。
14
-
15
- **发布流程:** 从提交历史确定版本号,生成 Changelog,创建 Tag 并推送。
16
-
17
- **分支清理:** 分支太多太乱 → 列出所有分支,检查命名规范、合并状态、过期分支,生成清理建议。
18
-
19
- **冲突解决:** merge/rebase 冲突 → 检测所有冲突文件和类型,分析冲突来源(两边最后修改者),建议解决策略。
20
-
21
- ## 核心规则
22
-
23
- - 提交信息使用 Conventional Commits 格式:type(scope): description
24
- - 功能分支从 develop 拉出,完成后合并回 develop
25
- - 提交信息主题行不超过 50 字符
26
- - 每个提交是逻辑上独立的变更
27
- - 公共分支禁止 force push 和 rebase
28
- - PR 必须关联 Issue
29
- - 解决冲突前先理解两边变更的意图
30
-
31
- ## 当前版本
32
-
33
- - conventional-commits: 1.0.0 — https://www.conventionalcommits.org/en/v1.0.0/
34
- - git-scm-docs: 2.45.0 — https://git-scm.com/docs
35
-
36
- ## 工作流
37
-
38
- | 场景 | 触发方式 |
39
- |------|----------|
40
- | 规范化提交: | 调用 MCP 工具 `git_commit` |
41
- | 发布流程: | 调用 MCP 工具 `git_release` |
42
- | 分支清理: | 调用 MCP 工具 `git_audit:branches` |
43
- | 冲突解决: | 调用 MCP 工具 `git_resolve:conflicts` |
@@ -1,37 +0,0 @@
1
- ---
2
- name: devflow:graph
3
- description: 查看项目模块图谱 — 架构分层、文件分组、依赖可视化
4
- required_mcp_tools:
5
- - get_dependency_graph
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","registeredAt":'"$(date +%s)000"'}' > ~/.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
-
25
-
26
- # /devflow:graph
27
-
28
- ## 执行
29
-
30
- 调用 `get_dependency_graph` MCP 工具:
31
-
32
- ```
33
- target = "all" (默认,拉取完整图谱)
34
- depth = 2 (默认,可调整 1-5)
35
- ```
36
-
37
- DevFlow 的依赖图谱是预索引的结构化数据(节点类型、边的方向、架构分层),原生工具无法提供同等质量的架构分析。
@@ -1,63 +0,0 @@
1
- ---
2
- name: devflow:graphql
3
- description: GraphQL 专家 — Schema 设计、N+1 检测、Resolver 优化、安全审计
4
- required_mcp_tools:
5
- - graphql_new_graphql_type
6
- - graphql_diagnose_bug
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","registeredAt":'"$(date +%s)000"'}' > ~/.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
-
27
-
28
- # ◈ GRAPHQL
29
-
30
- 你是一个 GraphQL 专家。使用 Schema-First 设计,Apollo Server 实现。遇到问题先查文档,不凭空猜测。
31
-
32
- ## 适用场景
33
-
34
- **新建 GraphQL Type + Resolver + DataLoader**
35
-
36
- **N+1 检测与修复:扫描 Resolver → 识别批量模式 → 加 DataLoader**
37
-
38
- **Schema 设计审查:类型设计 → 分页模式 → 安全风险评估**
39
-
40
- **GraphQL Bug 诊断:查询分析 → Resolver 链追踪 → 修复**
41
-
42
- ## 核心规则
43
-
44
- - 使用 Schema-First 设计(SDL)定义类型和操作
45
- - Resolver 保持简洁,业务逻辑在 Service 层
46
- - 使用 DataLoader 解决 N+1 查询问题
47
- - Mutation 命名使用动词(create/update/delete)
48
- - 使用 Connection 模式实现分页
49
- - 限制查询深度和复杂度防止滥用
50
- - 遇到不确定的 Schema 设计时先查 GraphQL 官方规范
51
-
52
- ## 当前版本
53
-
54
- - graphql-docs: 2024 — https://graphql.org/learn/
55
-
56
- ## 工作流
57
-
58
- | 场景 | 触发方式 |
59
- |------|----------|
60
- | 新建 GraphQL Type + Resolver + DataLoader | 调用 MCP 工具 `graphql_new_graphql_type` |
61
- | N+1 检测与修复:扫描 Resolver → 识别批量模式 → 加 DataLoader | 调用 MCP 工具 `graphql_fix:n+1` |
62
- | Schema 设计审查:类型设计 → 分页模式 → 安全风险评估 | 调用 MCP 工具 `graphql_review:schema` |
63
- | GraphQL Bug 诊断:查询分析 → Resolver 链追踪 → 修复 | 调用 MCP 工具 `graphql_diagnose_bug` |
@@ -1,37 +0,0 @@
1
- ---
2
- name: devflow:knowledge
3
- description: 搜索技术文档知识库 — React、Vue、Nest、TypeScript 等官方文档
4
- required_mcp_tools:
5
- - get_knowledge
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","registeredAt":'"$(date +%s)000"'}' > ~/.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
-
25
-
26
- # /devflow:knowledge
27
-
28
- ## 执行
29
-
30
- 调用 `get_knowledge` MCP 工具:
31
-
32
- ```
33
- query = 用户的查询内容
34
- scope = "all" (默认;可选 react/vue/nest)
35
- ```
36
-
37
- DevFlow 知识库预索引了 React、Vue、NestJS、TypeScript 官方文档(带版本标签和代码示例),比 WebSearch/WebFetch 更快更准。