@decaf-ts/mcp-server 1.5.16 → 1.5.18
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/assets/code/patterns/builder.enc +0 -0
- package/dist/assets/prompts/agent/agent.enc +0 -0
- package/dist/assets/prompts/agent/init.enc +0 -0
- package/dist/assets/prompts/constitution_commands.enc +0 -0
- package/dist/assets/prompts/documentation/class.enc +0 -0
- package/dist/assets/prompts/documentation/constant.enc +0 -0
- package/dist/assets/prompts/documentation/decorator.enc +0 -0
- package/dist/assets/prompts/documentation/file.enc +0 -0
- package/dist/assets/prompts/documentation/function.enc +0 -0
- package/dist/assets/prompts/documentation/interface.enc +0 -0
- package/dist/assets/prompts/documentation/iterate.enc +0 -0
- package/dist/assets/prompts/documentation/module.enc +0 -0
- package/dist/assets/prompts/documentation/prefix.enc +0 -0
- package/dist/assets/prompts/documentation/repo.enc +0 -0
- package/dist/assets/prompts/documentation/suffix.enc +0 -0
- package/dist/assets/prompts/git_commands.enc +0 -0
- package/dist/assets/prompts/jira/operational_prompts.enc +0 -0
- package/dist/assets/prompts/jira/system_prompt.enc +0 -0
- package/dist/assets/prompts/mode_commands.enc +0 -0
- package/dist/assets/prompts/plan_commands.enc +0 -0
- package/dist/assets/prompts/repository/readme.enc +0 -0
- package/dist/assets/prompts/repository/release_notes.enc +0 -0
- package/dist/assets/prompts/repository/setup.enc +0 -0
- package/dist/assets/prompts/specification_commands.enc +0 -0
- package/dist/assets/prompts/startup_command.enc +0 -0
- package/dist/assets/prompts/task_commands.enc +0 -0
- package/dist/assets/prompts/tests/coverage.enc +0 -0
- package/dist/assets/templates/AGENTS.enc +0 -0
- package/dist/assets/templates/agents_template.enc +0 -0
- package/dist/assets/templates/constitution_template.enc +0 -0
- package/dist/assets/templates/decaf/context/logCtx.enc +0 -0
- package/dist/assets/templates/decaf/services/client_based_service.enc +0 -0
- package/dist/assets/templates/decaf/services/model_service.enc +0 -0
- package/dist/assets/templates/decaf/services/service.enc +0 -0
- package/dist/assets/templates/decaf_guidelines.enc +1 -1
- package/dist/assets/templates/instructions_template.enc +0 -0
- package/dist/assets/templates/jira_templates.enc +0 -0
- package/dist/assets/templates/plan_template.enc +0 -0
- package/dist/assets/templates/specification_template.enc +0 -0
- package/dist/assets/templates/task_template.enc +0 -0
- package/dist/mcp-server.cjs +1 -1
- package/dist/mcp-server.cjs.map +1 -1
- package/dist/mcp-server.js +1 -1
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
package/dist/mcp-server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Command as e}from"commander";import*as t from"fs";import r,{promises as s}from"fs";import{MiniLogger as i,NumericLogLevels as n,Logging as o,LoggedClass as a,toSnakeCase as c,sf as p,toPascalCase as d,LogLevel as u,LoggedEnvironment as l}from"@decaf-ts/logging";import{__decorate as m,__metadata as h}from"tslib";import{required as f,Model as y,list as g,minlength as b}from"@decaf-ts/decorator-validation";import{z as w,ZodObject as v}from"zod";import{injectable as I,inject as S}from"@decaf-ts/injectable-decorators";import{prop as k,Metadata as j}from"@decaf-ts/decoration";import*as x from"path";import A from"path";import{InternalError as T,SerializationError as E,ValidationError as O}from"@decaf-ts/db-decorators";import J from"crypto";import C from"zlib";import{fileURLToPath as _}from"url";import{inspect as N}from"node:util";import{unified as H}from"unified";import D from"remark-directive";import P from"remark-gfm";import R from"remark-parse";import{UriTemplate as $}from"@modelcontextprotocol/sdk/shared/uriTemplate.js";import{ResourceTemplate as q,McpServer as M}from"@modelcontextprotocol/sdk/server/mcp.js";import{v4 as L}from"uuid";import{StdioServerTransport as U}from"@modelcontextprotocol/sdk/server/stdio.js";import{StreamableHTTPServerTransport as F}from"@modelcontextprotocol/sdk/server/streamableHttp.js";class B extends i{constructor(e,t,r){super(e,t,r)}log(e,t,r,s){const i=this.config("level");n[i],n[e]}}const W=(e,t,...r)=>{const s=(e=>{if("string"==typeof e)return e;if(!e)return"unknown";if("function"==typeof e)return e.name||"unknown";if("object"==typeof e&&"constructor"in e){const t=e.constructor;if(t&&t.name)return t.name}return"unknown"})(e);return new B(s,t)};var K,X,Y,z,G;(e=>{e[e.NONE=0]="NONE",e[e.BASIC=1]="BASIC",e[e.ADVANCED=2]="ADVANCED",e[e.HIGH=3]="HIGH"})(K||(K={})),(e=>{e[e.NONE=0]="NONE",e[e.LOW=1]="LOW",e[e.MEDIUM=2]="MEDIUM",e[e.HIGH=3]="HIGH"})(X||(X={})),(e=>{e[e.FREE=0]="FREE",e[e.LOW=1]="LOW",e[e.MEDIUM=2]="MEDIUM",e[e.HIGH=3]="HIGH"})(Y||(Y={}));class Z extends y{get log(){return this._log||(this._log=o.for(this)),this._log}constructor(e){super(e)}logFor(e){const{sessionId:t,requestId:r,authInfo:s}=e||{};let i="string"==typeof t&&t.length>0?this.log.for(t):this.log;return s&&s.clientId&&(i=i.for(s.clientId)),r&&(i=i.for(r.toString())),i}setDescription(e){return this.description=e,this}getDescription(){return this.description}setName(e){return this.name=e,this}getName(){return this.name}setTitle(e){return this.title=e,this}}m([f(),h("design:type",String)],Z.prototype,"description",void 0),m([f(),h("design:type",String)],Z.prototype,"name",void 0),m([f(),h("design:type",String)],Z.prototype,"title",void 0);class V extends Z{constructor(e){super(e),this.reasoning=K.NONE,this.effort=X.NONE,this.cost=Y.FREE}setReasoning(e){return this.reasoning=e,this}setEffort(e){return this.effort=e,this}setCost(e){return this.cost=e,this}}function Q(e){if(!e)return;let t=e,r=t&&t._def;for(;r&&"ZodObject"!==r.typeName;){if("ZodEffects"===r.typeName&&r.schema)t=r.schema;else if("ZodOptional"===r.typeName&&r.innerType)t=r.innerType;else if("ZodDefault"===r.typeName&&r.innerType)t=r.innerType;else if("ZodNullable"===r.typeName&&r.innerType)t=r.innerType;else{if(!r.schema)return;t=r.schema}r=t&&t._def}return r&&"ZodObject"===r.typeName?r:void 0}function ee(e,t="schema"){if(Q(e))return e;if(e&&"object"==typeof e){const t=e.def&&"object"==typeof e.def?e.def:void 0,r=t&&(t.shape||"object"===t.type)&&t.shape||("object"===e.type?e.shape:void 0)||(t&&"object"===t.type?{}:void 0);if(t||"object"===e.type||r){const e={};if(r&&"object"==typeof r)for(const[t,s]of Object.entries(r))e[t]=re(s)?s:w.any();return w.object(e)}}throw Error(`Registration error: provided a non-canonical ${t}. Export a ZodObject (z.object(...)).`)}function te(e){if(!e)return;if(e&&"object"==typeof e&&!e._def)return e.def&&"object"==typeof e.def&&e.def.shape?e.def.shape:e;const t=Q(e);return t?"function"==typeof t.shape?t.shape():t.shape||void 0:void 0}function re(e){return!(!e||"object"!=typeof e||!e._def)}m([f(),h("design:type",Number)],V.prototype,"reasoning",void 0),m([f(),h("design:type",Number)],V.prototype,"effort",void 0),m([f(),h("design:type",Number)],V.prototype,"cost",void 0),(e=>{e.ASSETS="assets"})(z||(z={})),(e=>{e.PROMPT="prompts",e.DOCUMENTATION="documentation",e.CODE="code"})(G||(G={}));const se=Buffer.from("DCAF1","ascii");function ie(e){let t=A.resolve(e);for(;;){if(r.existsSync(A.join(t,"package.json")))return t;const e=A.dirname(t);if(e===t)break;t=e}}const ne=process.argv?.[1]?ie(A.dirname(A.resolve(process.argv[1]))):void 0,oe=(()=>{const e=Error().stack;if(!e)return;const t=e.split(/\r?\n/).slice(1);for(const e of t){const t=e.match(/\(?([^()]+?):\d+:\d+\)?/);if(!t)continue;let r=t[1];if(r.startsWith("file://"))try{r=_(r)}catch{continue}if(!r.includes("node:internal"))return A.dirname(r)}})(),ae=oe?ie(oe):void 0,ce=ne??ae??process.cwd();function pe(...e){return A.join(ce,...e)}function de(e){let r=e;for(;;){const e=x.join(r,"lib","assets");if(t.existsSync(e))return e;const s=x.join(r,"src","assets");if(t.existsSync(s))return s;const i=x.join(r,"assets");if(t.existsSync(i))return i;const n=x.dirname(r);if(n===r)break;r=n}}function ue(){const e=process.env.DECAF_ASSET_DIR||process.env.MCP_ASSET_DIR||process.env.ASSET_DIR||"";if(e&&t.existsSync(e))return e;const r=de(__dirname);if(r)return r;const s=process.argv?.[1];if(s){const e=de(x.dirname(s));if(e)return e}const i=[ce,process.env.INIT_CWD].filter(Boolean);for(const e of i){const t=de(e);if(t)return t}return pe("assets")}let le=class extends a{constructor(e){super(),this.basePath=e||ue()}listAssets(...e){const r=x.join(this.basePath,...e);return t.readdirSync(r)}listPrompts(){return this.listAssets(G.PROMPT)}getAsset(e,r="md",...s){const i=x.join(this.basePath,...s),n=(e,r=!1)=>{try{return r?(e=>{if(e.length<se.length+16+12+16)throw Error("Invalid prompt payload (too short)");if(!e.subarray(0,se.length).equals(se))throw Error("Invalid prompt payload (bad magic)");const t=process.env.ENCRYPTION_KEY||"";if(!t)throw Error("Missing encryption key. Set ENCRYPTION_KEY to load obfuscated assets.");let r=se.length;const s=e.subarray(r,r+16);r+=16;const i=e.subarray(r,r+12);r+=12;const n=e.subarray(r,r+16);r+=16;const o=e.subarray(r),a=((e,t)=>J.scryptSync(e,t,32))(t,s),c=J.createDecipheriv("aes-256-gcm",a,i);c.setAuthTag(n);const p=Buffer.concat([c.update(o),c.final()]);return C.gunzipSync(p)})(t.readFileSync(e)).toString("utf-8"):t.readFileSync(e,"utf-8")}catch(e){if("ENOENT"===e.code)return null;throw e}},o=n(x.join(i,`${e}.${r}`),"enc"===r);if(null!==o)return o;const a=n(x.join(i,e+".enc"),!0);if(null!==a)return a;throw Error("Asset not found: "+x.join(i,`${e}.${r}`))}getAllAssets(e,...t){return this.listAssets(e,...t).reduce((r,s)=>{const i=x.extname(s),n=x.basename(s,i),o=i.replace(/^\./,"")||void 0;return r[n]=this.getAsset(n,o??void 0,e,...t),r},{})}toPromptDef(e){const t=e=>"number"==typeof e?e:"string"==typeof e?(e=>{switch(e){case"none":return K.NONE;case"basic":return K.BASIC;case"advanced":return K.ADVANCED;case"high":return K.HIGH;case"medium":return X.MEDIUM;case"low":return Y.LOW;case"free":return Y.FREE;default:throw new T("Cannon convert unknown level "+e)}})(e.toLowerCase()):K.NONE;return e.effort=t(e.effort),e.reasoning=t(e.reasoning),e.cost=t(e.cost),e}getPrompt(e,...t){const r=this.getAsset(c(e),"json",G.PROMPT,...t);let s;try{s=JSON.parse(r)}catch(r){throw new E(`Failed to parse prompt ${e} in categories ${t}: ${r}`)}return this.toPromptDef(s)}getAllPrompts(...e){const t=this.getAllAssets(G.PROMPT,...e);return Object.entries(t).reduce((t,[r,s])=>{try{t[r]=JSON.parse(s)}catch(t){throw new E(`Failed to parse prompt ${r} in categories ${e}: ${t}`)}return t},t)}};le=m([I(),h("design:paramtypes",[String])],le);class me extends V{constructor(e){super(e)}setCb(e){return this.cb=e,this}setArgsSchema(e){return this.argsSchema=e,this}static get builder(){return new me}static patchPrompt(e,t,r,s){const i=(t=Array.isArray(t)?t:Object.keys(t)).filter(e=>!Object.prototype.hasOwnProperty.call(r,e));if(i.length)throw new O("Missing replacements for placeholders: "+i.join(", "));s&&(s.verbose("Patching prompt with placeholders: "+JSON.stringify(t)),s.debug("Values: "+JSON.stringify(r)));const n=t.reduce((e,t)=>(e[t]=r[t],e),{});return p(e,n)}patchPrompt(e,t,r,s){return me.patchPrompt(e,t,r,s||this.log.for(this.patchPrompt))}build(e,t){const r=this.log.for(this.build),s=this.hasErrors();if(s)throw new O(s.toString());try{this.argsSchema&&ee(this.argsSchema,"argsSchema");const r=te(this.argsSchema);return e.registerPrompt(this.name,{title:this.title,description:this.description,argsSchema:r},async(e,r)=>{const s=this.logFor(r);e=Object.assign({},t,e||{}),s.verbose(`Executing prompt ${this.name} with args: ${JSON.stringify(e)}`),e._meta=Object.assign(e._meta||{},{usage:{reasoning:this.reasoning,effort:this.effort,cost:this.cost}});const i=await Promise.resolve(this.cb(e,r));return s.verbose(`Prompt ${this.name} executed successfully.`),s.debug("Prompt execution meta: "+JSON.stringify(i._meta)),i})}catch(e){throw r.error("Failed to register prompt "+(this.name||this.constructor.name),e),e}}}m([S(le),h("design:type",le)],me.prototype,"assets",void 0),m([f(),h("design:type",Object)],me.prototype,"cb",void 0),m([f(),h("design:type",v)],me.prototype,"argsSchema",void 0),m([k(),h("design:type",Object)],me.prototype,"placeholders",void 0);class he extends me{setCategory(e){return this.promptCategory=e,this}addPrefix(e){return this.prefixes=this.prefixes||[],this.prefixes.push(e),this}addSuffix(e){return this.suffixes=this.suffixes||[],this.suffixes.push(e),this}constructor(e){super(e)}build(e){const t=this.assets.getPrompt(this.name,this.promptCategory);y.fromObject(this,t);const r=new Set((j.properties(he)||[]).filter(e=>!["assets","promptCategory","prefixes","suffixes"].includes(e)));["cb","argsSchema"].forEach(e=>r.add(e));const s=this.hasErrors(...Array.from(r));if(s)throw new O(s.toString());const i=(this.prefixes||[]).map(e=>this.assets.getPrompt(e,this.promptCategory)),n=(this.suffixes||[]).map(e=>this.assets.getPrompt(e,this.promptCategory)),o=[...new Set([...t.placeholders,...i.map(e=>e.placeholders||[]),...n.map(e=>e.placeholders||[])].flat())].reduce((e,t)=>(e[t]=w.string().describe("The description for "+t),e),{});return this.setArgsSchema(w.object(o)),this.setCb((e,t)=>{const r=this.logFor(t).for(he).for(this.promptCategory).for(this.name);function s(e=[]){return Array.isArray(e)?e:Object.keys(e)}const i=(this.prefixes||[]).map(e=>this.assets.getPrompt(e,this.promptCategory)),n=(this.suffixes||[]).map(e=>this.assets.getPrompt(e,this.promptCategory)),o=this.assets.getPrompt(this.name,this.promptCategory),a=[...new Set([...i.map(e=>s(e.placeholders)).flat(),...n.map(e=>s(e.placeholders)).flat(),...s(o.placeholders).flat()])];return{messages:[{role:"user",content:{type:"text",text:this.patchPrompt([...i.map(e=>e.prompt),o.prompt,...n.map(e=>e.prompt)].join("\n\n"),a,e,r)}}],_meta:{}}}),super.build(e)}setReasoning(e){throw new T("Named prompt builders don't require callback")}setEffort(e){throw new T("Named prompt builders don't require callback")}setCost(e){throw new T("Named prompt builders don't require callback")}setDescription(e){throw new T("Named prompt builders don't require callback")}setTitle(e){throw new T("Named prompt builders don't require callback")}static get builder(){return new he}}m([f(),h("design:type",String)],he.prototype,"promptCategory",void 0),m([g(String),b(1),h("design:type",Array)],he.prototype,"prefixes",void 0),m([b(1),g(String),h("design:type",Array)],he.prototype,"suffixes",void 0);const fe=me.builder.setName("example-prompt").setTitle("Example prompt").setDescription("Example prompt for testing").setArgsSchema(w.object({message:w.string().optional()})).setCb(async e=>{const t=e.message??"default";return{messages:[{role:"assistant",content:{type:"text",text:t}}],content:[],structuredContent:{message:t},result:{message:t}}}),ye=me.builder.setName("interactive-jsdoc").setTitle("Interactive JSDoc prompt").setDescription("Interactive prompt for jogging JSDoc helpers").setArgsSchema(w.object({gist:w.string().optional()})).setCb(async e=>{const t=e.gist??"interactive jsdoc response";return{messages:[{role:"assistant",content:{type:"text",text:t}}],content:[],structuredContent:{message:t},result:{message:t}}}),ge=Object.assign(ye,{name:ye.getName()});var be;function we(e,t=[],r=[]){const s=he.builder.setCategory(be.DOCS).setName(e);return["prefix",...t].forEach(e=>s.addPrefix(e)),["suffix",...r].forEach(e=>s.addSuffix(e)),s}(e=>{e.DOCS="documentation",e.CODE="code"})(be||(be={}));const ve=[we("class"),we("constant"),we("decorator"),we("function"),we("module"),we("file"),we("repo",[],["iterate"])],Ie=w.object({className:w.string().describe("the class name to turn into a builder")}),Se=[fe,ge,...ve,me.builder.setName("ts-code-dp-builder").setTitle("Typescript builder design patter prompt").setDescription("for a class, with a defined set of properties, scafold a builder design pattern").setArgsSchema(Ie).setReasoning(K.BASIC).setCb((e,t)=>(e.className=d(e.className),{messages:[{role:"user",content:{type:"text",text:`You're a senior TypeScript developer writing typescript code.You're a senior TypeScript developer writing typescript code.\nTransform the selected class into a builder design pattern implementation in Typescript.\nuse @decaf-ts validation decorators to enforce the validation of your builder.\n\n- must extend the Model Class from @decaf-ts/decorator-validation;\n- each property must be marked as protected;\n- each property must have a setter method that returns 'this' for chaining;\n- the build() method must validate the properties using hasErrors() method from Model class;\n- if validation fails, throw an error with the validation errors;\n- if validation passes, return an instance of the original class with the set properties;\n- optionally (but do so by default) add the static builder and from methods from the example;\n- if the clasee already follows the pattern but has properties without decoration or without setters, simple add them;\n\nexample:\n\noriginal class:\n\`\`\`typescript\nexport class ${e.className} {\n description!: string;\n name!: string = "default name";\n title!: string;\n age?: string;\n dateOfBirth!: Date;\n}}\n\`\`\` \n\nresulting builder pattern implementation:\n\`\`\`typescript\nexport class ${e.className}Builder extends Model {\n\n @minlength(10\n @required()\n protected description!: string;\n \n @required()\n protected name!: string = "default value;\n \n @required()\n protected title!: string;\n \n @min(18)\n protected age?: string;\n \n @date()\n protected dateOfBirth!: Date;\n\n protected constructor(arg?: ModelArg<${e.className}Builder>>) {\n super(arg);\n Model.fromModel(this, arg);\n }\n\n setDescription(value: string) {\n this.description = value;\n return this;\n }\n\n setName(value: string) {\n this.name = value;\n return this;\n }\n\n setTitle(value: string) {\n this.title = value;\n return this;\n }\n setAge(value: number) {\n this.age = value;\n return this;\n }\n setDate(value: Date) {\n this.age = value;\n return this;\n }\n \n build(...args: any[]): ${e.className}Builder | Promise<${e.className}Builder> {\n const errs = this.hasErrors();\n if (errs) throw new Error(errs.toString());\n \n return // code that builds OBJ here\n }\n \n static get builder(): ${e.className}Builder {\n return new ${e.className}Builder(); // static method to get a new builder instance\n }\n \n static from<K extends keyof ${e.className}Builder>(obj: K, ${e.className}Builder[K]): ${e.className}Builder {\n return new ${e.className}Builder(); // static method to create a builder from an object\n }\n}\n\`\`\` \n\n`}}],_meta:{}}))];class ke extends V{setAnnotations(e){return this.annotations=Object.assign(this.annotations,e),this}setCb(e){return this.cb=e,this}setInputSchema(e){return this.inputSchema=e,this}setOutputSchema(e){return this.outputSchema=e,this}constructor(e){super(e),this.annotations={readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}}static get builder(){return new ke}build(e){const t=this.hasErrors();if(t)throw Error(t.toString());try{this.inputSchema&&ee(this.inputSchema,"inputSchema"),this.outputSchema&&ee(this.outputSchema,"outputSchema");const t=te(this.inputSchema),r=te(this.outputSchema);return e.registerTool(this.name,{title:this.title,description:this.description,inputSchema:t,outputSchema:r,annotations:this.annotations,_meta:{usage:{reasoning:this.reasoning,effort:this.effort,cost:this.cost}}},async(e,t)=>{const r=this.logFor(t);r.verbose(`Executing tool ${this.name} with args: ${JSON.stringify(e)}`),t._meta=Object.assign(t._meta||{},{usage:{reasoning:this.reasoning,effort:this.effort,cost:this.cost}});const s=await Promise.resolve(this.cb(e,t));return r.verbose(`Tool ${this.name} executed successfully.`),r.debug("Tool execution meta: "+JSON.stringify(s._meta)),s})}catch(e){const t=e?.message||e+"";if("string"==typeof t&&t.includes("already registered"))return o.for(this).warn(`Tool ${this.name} already registered - skipping duplicate registration`),{name:this.name};throw o.for(this).error("Error building tool",e),e}}}m([f(),h("design:type",Object)],ke.prototype,"annotations",void 0),m([f(),h("design:type",Object)],ke.prototype,"cb",void 0),m([f(),h("design:type",Function)],ke.prototype,"inputSchema",void 0);const je=ke.builder.setName("example-tool").setTitle("Example tool").setDescription("A smoke tool used for quick testing").setInputSchema(w.object({})).setCb(async()=>({content:[{type:"text",text:"example tool ok"}],result:{status:"ok"}}));Object.assign(je,{name:je.getName()});const xe=ke.builder.setName("file-summarizer").setTitle("File summarizer").setDescription("Summaries files for quick previews").setInputSchema(w.object({filePath:w.string().optional()})).setCb(async()=>({content:[{type:"text",text:"file summary stub"}],result:{summary:"file summary stub"}}));function Ae(){try{let e=process.argv[1]?A.dirname(A.resolve(process.argv[1])):process.cwd();for(;;){const t=A.join(e,"package.json");if(r.existsSync(t))return JSON.parse(r.readFileSync(t,"utf-8"));const s=A.dirname(e);if(s===e)break;e=s}}catch{}return{}}Object.assign(xe,{name:xe.getName()});const Te=Ae().version??"0.0.0",Ee=Ae().name??"unknown";j.registerLibrary(Ee,Te);const Oe={mcpId:"decaf",name:"decaf-ts mcp server",title:"Decaf-TS MCP Server",description:"Provides precise coding assistance for the decaf-ts framework",version:Te,websiteUrl:"https://decaf-ts.github.io",repositoryUrl:"https://github.com/decaf-ts/mcp-server",license:"AGPL-3.0",workingDir:ce,assetDir:ue(),contacts:[{name:"Decaf-TS",url:"https://decaf-ts.github.io"}],tags:"server,official,decaf-ts",metadata:{},icons:[{src:"workdocs/assets/favicon.svg",mimeType:"image/svg+xml",sizes:"any"}],jira:{host:process.env.JIRA__HOST||"decaf-ts.atlassian.net",email:process.env.JIRA__EMAIL||"",apiKey:process.env.JIRA__API_KEY||process.env.JIRA__APIKEY||"",projectKey:process.env.JIRA__PROJECT_KEY||void 0,issueType:process.env.JIRA__ISSUE_TYPE||void 0,parentIssue:process.env.JIRA__PARENT_ISSUE||void 0,timeout:process.env.JIRA__TIMEOUT?parseInt(process.env.JIRA__TIMEOUT):1e3,rateLimitRetryDelayMs:process.env.JIRA__RATE_LIMIT_RETRY_DELAY_MS?parseInt(process.env.JIRA__RATE_LIMIT_RETRY_DELAY_MS):3e3},xray:{host:process.env.XRAY__HOST||process.env.XRAY__API_HOST||"https://xray.cloud.getxray.app",apiUser:process.env.XRAY__API_USER||"",apiSecret:process.env.XRAY__API_SECRET||""},level:u.error},Je=l.accumulate(Oe);function Ce(){const{host:e,email:t,apiKey:r,projectKey:s,issueType:i}=Je.jira;return{host:e?.trim(),email:t?.trim(),apiKey:r?.trim(),projectKey:s?.trim(),issueType:i?.trim(),parentIssue:Je.jira.parentIssue?.trim()}}function _e(){const e=Ce();return[{name:"JIRA__HOST",required:!0,description:"Atlassian host (e.g. decaf-ts.atlassian.net) where your Jira instance is hosted.",value:e.host},{name:"JIRA__EMAIL",required:!0,description:"Email address of the Jira account that has API access.",value:e.email},{name:"JIRA__API_KEY",required:!0,description:"API token created in your Atlassian profile (a.k.a. APIKEY alias) for authenticating requests.",sensitive:!0,value:e.apiKey},{name:"JIRA__PROJECT_KEY",required:!1,description:"Default Jira project key (e.g. DECAF) used when an issue creation request omits a project.",value:e.projectKey},{name:"JIRA__ISSUE_TYPE",required:!1,description:"Default Jira issue type (e.g. Task, Bug) used when creating issues without an explicit type.",value:e.issueType},{name:"JIRA__PARENT_ISSUE",required:!1,description:"Default parent issue key (e.g. DECAF-123) applied when a child issue is created without an explicit parent.",value:e.parentIssue}]}function Ne(e){const t=e.value?((e,t)=>{if(e)return t?"<configured>":e})(e.value,e.sensitive):"not set",r=e.required?"(required)":"(optional)";return`\u2022 ${e.name} ${r}: ${e.description} Current state: ${t}.`}o.setConfig(Je);class He extends Error{constructor(e){const t=_e(),r=(e=>{const t=_e();return`${e.length?`Missing Jira credentials: ${e.map(e=>e.name).join(", ")}.`:"Jira credentials are configured."}\n\nThis setup uses the following environment variables:\n${t.map(Ne).join("\n")}`})(e);super(r),this.name="MissingJiraEnvironmentError",this.descriptors=t,this.missing=e,"function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,He)}}const De=o.for("jira.client"),Pe=/(authorization|cookie)/i;function Re(e){if(!e)return;const t=e.baseURL??"",r=e.url??"";return t&&r?`${t.endsWith("/")?t.slice(0,-1):t}/${r.startsWith("/")?r.slice(1):r}`:r||t||void 0}function $e(e){if(void 0!==e){if("string"==typeof e)return e;try{return JSON.stringify(e,null,2)}catch(t){return N(e,{depth:null})}}}function qe(e){if(!e)return;const t={};return Object.entries(e).forEach(([e,r])=>{t[e]=Pe.test(e)&&r?"[REDACTED]":r}),t}function Me(e){let t;try{const e=require("jira.js");t=e?.Version3Client||e.default?.Version3Client||e.default||e}catch(e){throw Error("Unable to require 'jira.js' \u2014 ensure it is installed as a dependency: "+e)}const{host:r,email:s,apiKey:i}=(()=>{const e=Ce(),t=_e().filter(e=>e.required&&!e.value);if(t.length>0)throw new He(t);return{host:e.host,email:e.email,apiKey:e.apiKey}})(),n=new t({host:r.startsWith("http://")||r.startsWith("https://")?r:"https://"+r,authentication:{basic:{email:s,apiToken:i}},baseRequestConfig:{headers:{Accept:"application/json","Content-Type":"application/json"}}});return(e=>{if(!e)return;const t="__jiraLoggingAttached";e[t]||(e[t]=!0,e.interceptors.request.use(e=>{e.headers=(e=>{const t={...e||{}};return Object.keys(t).some(e=>"accept"===e.toLowerCase())||(t.Accept="application/json"),Object.keys(t).some(e=>"content-type"===e.toLowerCase())||(t["Content-Type"]="application/json"),t})(e.headers);const t=(e.method??"GET").toString().toUpperCase(),r=Re(e);return De.info("jira.request",{method:t,url:r,headers:qe(e.headers),params:e.params,data:$e(e.data)}),e},e=>(De.error("jira.request.error",{message:e.message}),Promise.reject(e))),e.interceptors.response.use(e=>{const t=(e.config?.method??"GET").toString().toUpperCase(),r=Re(e.config);return De.info("jira.response",{method:t,url:r,status:e.status,headers:qe(e.headers),data:$e(e.data)}),e},e=>{const t=e.config,r=e.response,s=(t?.method??"GET").toString().toUpperCase(),i=Re(t);return De.error("jira.response.error",{method:s,url:i,status:r?.status,headers:qe(r?.headers),data:$e(r?.data),message:e.message}),Promise.reject(e)}))})(n.instance),n}const Le=w.object({name:w.string().min(1).optional().describe("Optional template name that pre-populates additional fields"),content:w.string().min(1).describe("Markdown template content to apply when constructing the description"),placeholders:w.record(w.string()).optional().describe("Map of placeholder replacements used by the template")}).describe("Template metadata used to adjust the created description"),Ue=w.object({template:Le.optional().describe("Optional template settings for this create request")}).describe("Additional template controls available when creating an issue"),Fe=w.union([w.object({fields:w.record(w.any()).describe("Full raw field map that gets delivered to Jira")}).merge(Ue).describe("Create argument that supplies every field explicitly"),w.object({summary:w.string().min(1).describe("Title or summary of the new issue"),projectKey:w.string().min(1).describe("Project key where the issue is created"),issueType:w.string().min(1).describe("Type name for the new issue (story, task, etc.)"),description:w.string().optional().describe("Optional textual description for the issue")}).merge(Ue).describe("Create argument with minimal required identifiers plus optional description")]).describe("Union describing how to create an issue either via raw fields or shorthand properties");function Be(e,t,r){const s=((e.url??"")+"").match(/^(attachment|jira-attachment):(.+)$/i);if(!s)return null;const i=s[2],n=r.resolveAttachment?.(i);return n?{type:"block",node:{type:"mediaSingle",attrs:{layout:"center"},content:[{type:"media",attrs:{type:"file",id:n.id,collection:n.collection??"attachments"}}]}}:null}function We(e,t){if(!e)return[];if(!t.enableAtMentions&&!t.enableEmojiShortcodes)return[{type:"text",text:e}];let r=0;const s=[],i=/(^|[^A-Za-z0-9_])@([A-Za-z0-9._-]{1,64})/g,n=/:([a-z0-9_+-]{1,64}):/gi;for(;r<e.length;){const o=Xe(t.enableAtMentions?Ke(i,e,r):null,t.enableEmojiShortcodes?Ke(n,e,r):null);if(!o){s.push({type:"text",text:e.slice(r)});break}if(o.index>r&&s.push({type:"text",text:e.slice(r,o.index)}),"mention"===o.kind){const{full:e,groups:i}=o,n=i[0]??"",a=i[1]??"";n&&s.push({type:"text",text:n});const c=t.resolveMention?.(a);c?s.push({type:"mention",attrs:{id:c.id,text:c.text}}):s.push({type:"text",text:"@"+a}),r=o.index+e.length;continue}if("emoji"===o.kind){const{full:e,groups:i}=o,n=`:${i[0]}:`,a=t.resolveEmoji?.(n);s.push({type:"emoji",attrs:a?{shortName:a.shortName,text:a.text}:{shortName:n}}),r=o.index+e.length;continue}}return(e=>{const t=[];for(const r of e){const e=t[t.length-1];"text"!==r.type||"text"!==e?.type||e.marks||r.marks?t.push(r):e.text=(e.text??"")+(r.text??"")}return t})(s)}function Ke(e,t,r){e.lastIndex=r;const s=e.exec(t);if(!s)return null;const i=e.source.includes("@")?"mention":"emoji";return{index:s.index,full:s[0],groups:s.slice(1),kind:i}}function Xe(e,t){return e?t&&e.index>t.index?t:e:t}function Ye(e){const t=(e.children??[])[0];return"text"===t?.type?(t.value??"")+"":"paragraph"===t?.type?((t.children??[]).map(e=>"text"===e.type?(e.value??"")+"":"").join("")||"")+"":""}function ze(e){const t=((e??"")+"").toLowerCase().trim();return t?"info"===t||"note"===t||"success"===t||"warning"===t||"error"===t?t:"danger"===t?"error":null:null}function Ge(e){const t=((e??"")+"").toLowerCase().trim();return!t||"neutral"!==t&&"green"!==t&&"yellow"!==t&&"red"!==t&&"blue"!==t&&"purple"!==t?null:t}function Ze(e,t){const r=[];for(const s of e??[])if(s?.type)if("text"!==s.type)if("strong"!==s.type)if("emphasis"!==s.type)if("delete"!==s.type)if("inlineCode"!==s.type)if("break"!==s.type){if("link"===s.type){const e=(s.url??"")+"",i=Qe(s.children??[],e),n=Be(s,0,t);if(n){"inline"===n.type?r.push(n.node):r.push({type:"text",text:i,marks:[{type:"link",attrs:{href:e}}]});continue}if(t.enableSmartCards&&et(i,e)){r.push({type:"inlineCard",attrs:{url:e}});continue}r.push({type:"text",text:i,marks:[{type:"link",attrs:{href:e}}]});continue}if("textDirective"===s.type&&"status"===s.name){const e=Ye(s)||"Status",t=Ge(s.attributes?.color)??"neutral";r.push({type:"status",attrs:{text:e,color:t}});continue}if("textDirective"===s.type&&"emoji"===s.name){const e=tt(s);r.push(rt(e,t));continue}}else r.push({type:"hardBreak"});else r.push({type:"text",text:(s.value??"")+"",marks:[{type:"code"}]});else r.push(...Ve(Ze(s.children??[],t),{type:"strike"}));else r.push(...Ve(Ze(s.children??[],t),{type:"em"}));else r.push(...Ve(Ze(s.children??[],t),{type:"strong"}));else r.push(...We((s.value??"")+"",t));return r.filter(e=>!("text"===e.type&&""===(e.text??"")))}function Ve(e,t){return e.map(e=>{if("text"!==e.type)return e;const r=e.marks?[...e.marks,t]:[t];return{...e,marks:r}})}function Qe(e,t){const r=[];for(const t of e??[])"text"===t.type||"inlineCode"===t.type?r.push((t.value??"")+""):"emphasis"!==t.type&&"strong"!==t.type&&"delete"!==t.type||r.push(Qe(t.children??[],""));return r.join("")||t}function et(e,t){const r=(e??"").trim(),s=(t??"").trim();return r===s&&/^https?:\/\//i.test(s)}function tt(e){return(e.children??[]).map(e=>"text"===e.type?(e.value??"")+"":"").join("").trim()||""}function rt(e,t){const r=e.startsWith(":")?e:`:${e}:`,s=t.resolveEmoji?.(r);return s?{type:"emoji",attrs:{shortName:s.shortName,text:s.text}}:{type:"emoji",attrs:{shortName:r}}}function st(e){return e?"string"==typeof e?e:"text"===e.type||"inlineCode"===e.type?(e.value??"")+"":Array.isArray(e.children)?e.children.map(st).join(""):"":""}function it(e,t){if(!e?.type)return null;if((e=>"containerDirective"===e?.type&&"panel"===e?.name)(e))return((e,t)=>{const r=e.attributes??{},s=ze(r.type)??"info",i="string"==typeof r.title?r.title:void 0,n=(e.children??[]).map(e=>it(e,t)).flat().filter(Boolean);return{type:"panel",attrs:{panelType:s,...i?{panelType:s,title:i}:{panelType:s}},content:n.length?n:[{type:"paragraph",content:[]}]}})(e,t);switch(e.type){case"heading":return{type:"heading",attrs:{level:ot(e.depth??1,1,6)},content:Ze(e.children??[],t)};case"paragraph":return(e=>{const t=e.children??[];if(1!==t.length)return null;const r=t[0];if("image"!==r?.type)return null;const s=(r.url??"")+"";return s?{type:"mediaSingle",attrs:{layout:"center"},content:[{type:"media",attrs:{type:"external",url:s}}]}:null})(e)||{type:"paragraph",content:Ze(e.children??[],t)};case"blockquote":return{type:"blockquote",content:(e.children??[]).map(e=>it(e,t)).flat().filter(Boolean)};case"list":return((e,t)=>t.enableTaskLists&&(e.children??[]).some(e=>"boolean"==typeof e.checked)?((e,t)=>{const r=[];let s=0;for(const i of e.children??[]){if("boolean"!=typeof i.checked)continue;s+=1;const e=(i.children??[]).map(e=>it(e,t)).flat().filter(Boolean);r.push({type:"taskItem",attrs:{localId:"task-"+s,state:i.checked?"DONE":"TODO"},content:e.length?e:[{type:"paragraph",content:[]}]})}return{type:"taskList",content:r}})(e,t):{type:e.ordered?"orderedList":"bulletList",content:(e.children??[]).map(e=>((e,t)=>{const r=(e.children??[]).map(e=>it(e,t)).flat().filter(Boolean);return{type:"listItem",content:r.length?r:[{type:"paragraph",content:[]}]}})(e,t))})(e,t);case"code":{const r=((e,t)=>{const r=(e??"").toString().trim().toLowerCase();return r?t.enableMermaid&&"mermaid"===r?"mermaid":(e=>{const t=e.trim().toLowerCase();return{js:"javascript",javascript:"javascript",jsx:"javascript",ts:"typescript",typescript:"typescript",tsx:"typescript",py:"python",python:"python",rb:"ruby",ruby:"ruby",sh:"bash",bash:"bash",zsh:"bash",shell:"bash",yml:"yaml",yaml:"yaml",json:"json",toml:"toml",xml:"xml",html:"html",css:"css",scss:"scss",sql:"sql",go:"go",rust:"rust",java:"java",c:"c",cpp:"cpp","c++":"cpp",cs:"csharp",csharp:"csharp",php:"php",kotlin:"kotlin",swift:"swift",md:"markdown",markdown:"markdown",graphql:"graphql",gql:"graphql",dockerfile:"docker",makefile:"make",ini:"ini"}[t]??t})(r):null})(e.lang,t);return{type:"codeBlock",attrs:{language:r},content:[{type:"text",text:(e.value??"")+""}]}}case"thematicBreak":return{type:"rule"};case"table":return((e,t)=>({type:"table",content:(e.children??[]).map((e,r)=>({type:"tableRow",content:(e.children??[]).map(e=>({type:0===r?"tableHeader":"tableCell",content:[{type:"paragraph",content:Ze(e.children??[],t)}]}))}))}))(e,t);case"leafDirective":return"status"===e.name?(e=>{const t=Ge((e.attributes??{}).color)??"neutral";return{type:"paragraph",content:[{type:"status",attrs:{text:Ye(e)||"Status",color:t}}]}})(e):"panel"===e.name?((e,t)=>{const r=e.attributes??{},s=ze(r.type)??"info",i="string"==typeof r.title?r.title:void 0;return{type:"panel",attrs:{panelType:s,...i?{title:i}:{}},content:[{type:"paragraph",content:Ze([{type:"text",value:Ye(e)}],t)}]}})(e,t):nt(e,t);default:return nt(e,t)}}function nt(e,t){if("drop"===t.unknownNodeStrategy)return null;const r=st(e);return r?{type:"paragraph",content:[{type:"text",text:r}]}:null}function ot(e,t,r){const s=Number.isFinite(e)?Math.trunc(e):t;return Math.max(t,Math.min(r,s))}const at={resolveMention:void 0,resolveAttachment:void 0,resolveEmoji:void 0,enableSmartCards:!0,enableMermaid:!0,enableEmojiShortcodes:!0,enableAtMentions:!0,enableTaskLists:!0,unknownNodeStrategy:"text"};function ct(e,t={}){const r={...at,...t},s=e??"",i=H().use(R).use(D).use(P),n=i.parse(s),o=i.runSync(n);return pt(o),((e,t)=>{const r=[];for(const s of e.children??[]){const e=it(s,t);e&&(Array.isArray(e)?r.push(...e):r.push(e))}return((e,t)=>{if(!t.enableSmartCards)return e;const r=e.content.map(e=>(e=>{if("paragraph"!==e.type)return e;const t=e.content??[];if(1!==t.length)return e;const r=t[0];if("inlineCard"!==r?.type)return e;const s=r.attrs?.url;return s?[{type:"blockCard",attrs:{url:s}}]:e})(e)).flat();return{...e,content:r}})({version:1,type:"doc",content:r},t)})(o,r)}function pt(e){if(!e||!Array.isArray(e.children))return;const t=[];for(const r of e.children)"definition"!==r?.type&&("html"!==r?.type?(pt(r),t.push(r)):t.push({type:"text",value:(r.value??"")+""}));e.children=t}function dt(e){return e.flatMap(e=>"panel"===e.type?dt(e.content??[]):[ut(e)])}function ut(e){return e.content?{...e,content:dt(e.content)}:{...e}}const lt=/\{\{\s*([^\}]+)\s*\}\}/g;function mt(e){if(!e||0>=Object.keys(e).length)return[];const t=(e=>{if(null==e)return"";try{return JSON.stringify(e,null,2)}catch{return N(e,{depth:null})}})(e);return t?[{type:"text",text:t}]:[]}function ht(e={},t=[]){const r=(e=>e&&"object"==typeof e?Array.isArray(e)?{items:e}:e:"string"==typeof e?{message:e}:null==e?{}:{value:e})(e);return{content:t.length?t:mt(r),result:r,structuredContent:r}}const ft={name:"jira-issue-create",inputSchema:Fe,runTool:async(e,t)=>ht(await(async(e,t)=>{let r;const s=e=>e&&e.trim()?e.trim():void 0,i=s(Je.jira.projectKey),n=s(Je.jira.issueType),o=t&&"object"==typeof t&&!Array.isArray(t)?t:{},a=Object.prototype.hasOwnProperty.call(o,"fields")?o:{...o,projectKey:o.projectKey??i,issueType:o.issueType??n};try{r=Fe.parse(a)}catch(e){const t=Error("validation error");throw t.code="validation_error",t}let c;c=r&&"object"==typeof r&&"fields"in r&&r.fields?{...r.fields}:{summary:r.summary,project:{key:r.projectKey},issuetype:{name:r.issueType},...r.description?{description:r.description}:{}},c=((e,t)=>{if(!t||!t.content)return e;const r=(s=t.content,i=t.placeholders,s?s.replace(lt,(e,t)=>{const r=t.trim();if(!r)return"";if(i&&Object.prototype.hasOwnProperty.call(i,r)){const e=i[r];return null==e?"":e+""}return e}):"");var s,i;if(!r.trim())return e;const n=ct(r),o=(a=e.description)?"object"==typeof a&&"doc"===a.type&&Array.isArray(a.content)?a.content:"string"==typeof a?ct(a).content:[]:[];var a;return e.description={type:"doc",version:1,content:[...o,...n.content]},e})(c,r.template);const p=e?.issues?.create??e?.issues?.createIssue;if("function"!=typeof p)throw Error("Jira client missing create function");const d=await p.call(e.issues,{fields:c}),u=d&&d.data||d;return{id:u?.id??null,key:u?.key??null}})(e,t))};class yt extends Error{constructor({code:e,message:t,details:r}){super(t),Object.setPrototypeOf(this,new.target.prototype),this.name="NormalizedJiraError",this.code=e,this.details=r}}const gt=o.for("jira.errors");function bt(e){if(!e)return new yt({code:"jira_error",message:"Unknown Jira error",details:{raw:e}});const t=e?.status??e?.statusCode??e?.response?.status??e?.response?.statusCode,r="number"==typeof t?t:Number(t)||void 0,s=e?.response?.data??e?.data??e?.response?.body??e?.body,i=[];"string"==typeof e?.message&&i.push(e.message),((e,t)=>{e&&(Array.isArray(e.errorMessages)&&e.errorMessages.forEach(e=>"string"==typeof e&&t.push(e)),"string"==typeof e.errorMessage&&t.push(e.errorMessage),e.errorCollection&&Array.isArray(e.errorCollection.errors)&&e.errorCollection.errors.forEach(e=>{"string"==typeof e?t.push(e):e&&"string"==typeof e.message&&t.push(e.message)}),e?.errors&&"object"==typeof e.errors&&Object.values(e.errors).forEach(e=>{"string"==typeof e?t.push(e):"string"==typeof e?.message&&t.push(e.message)}))})(s,i);const n=r?`Jira API error (${r})`:"Jira API error",o=i.length>0?i.join(" | "):n,a=r?"jira_"+r:e?.code??"jira_error",c=e?.config,p=c?{method:c.method?c.method.toString().toUpperCase():void 0,url:c.url,headers:qe(c.headers),data:$e(c.data)}:void 0;return gt.error("jira.error",{code:a,message:o,httpStatus:r,request:p,body:$e(s)??s}),new yt({code:a,message:o,details:{httpStatus:r,body:s,request:p,raw:e}})}const wt=w.object({issueId:w.string().min(1).describe("Issue key or ID to delete"),deleteSubtasks:w.boolean().optional().default(!0).describe("Whether to delete the subtasks alongside this issue")}).describe("Arguments used to delete a Jira issue (with optional subtasks)"),vt={name:"jira-issue-delete",inputSchema:wt,runTool:async(e,t)=>{try{const r=wt.parse(t),s=e.issues??e.issue??e,i=s?.delete??s?.deleteIssue;if("function"!=typeof i)throw Error("jira client delete endpoint is not available");return await i.call(s,{issueIdOrKey:r.issueId,deleteSubtasks:r.deleteSubtasks}),ht({success:!0,message:`Issue ${r.issueId} deleted successfully`})}catch(e){throw bt(e)}}},It=w.object({projectKey:w.string().trim().min(1).optional().describe("Project key used to scope the issue search"),issueType:w.string().trim().min(1).optional().describe("Issue type name used to filter the results"),parentIssueId:w.string().trim().min(1).optional().describe("Optional parent issue key/ID to limit results to a subtree"),name:w.string().trim().min(1).optional().describe("Issue summary to match exactly"),reference:w.string().trim().min(1).optional().describe("External reference or custom identifier to filter by"),jql:w.string().trim().min(1).optional().describe("Free-form JQL query to drive the search"),startAt:w.number().int().min(0).optional().describe("Index for paging through the search results"),maxResults:w.number().int().min(1).optional().describe("Maximum number of issues to return"),fields:w.array(w.string()).optional().describe("List of issue fields to include in the response"),expand:w.string().optional().describe("Optional expansion clause for the results"),orderBy:w.string().trim().min(1).optional().describe("Field or clause used to order the returned issues")}).describe("Parameters describing how to search for Jira issues");function St(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}const kt={name:"jira-issue-list",inputSchema:It,runTool:async(e,t)=>{try{const r=It.parse(t),s=r.startAt??0,i=r.maxResults??50;let n=r.jql?.trim();if(n){if(r.orderBy){const e=r.orderBy.trim();e&&(n=/\border\s+by\b/i.test(n)?`${n}, ${e}`:`${n} ORDER BY ${e}`)}}else n=(e=>{const t=[];if(e.projectKey&&t.push(`project = "${St(e.projectKey)}"`),e.issueType&&t.push(`issuetype = "${St(e.issueType)}"`),e.parentIssueId&&t.push(`parent = "${St(e.parentIssueId)}"`),e.name&&t.push(`summary ~ "${St(e.name)}"`),e.reference){const r=St(e.reference);t.push(`(key ~ "${r}" OR summary ~ "${r}" OR text ~ "${r}")`)}if(0===t.length){const e=Error("Provide a jql query or at least one filter (project, name, reference, parent, issue type, etc.).");throw e.code="validation_error",e}let r=t.join(" AND ");if(e.orderBy){const t=e.orderBy.trim();t&&(r=/\border\s+by\b/i.test(r)?`${r}, ${t}`:`${r} ORDER BY ${t}`)}return r})(r);const o={jql:n,startAt:s,maxResults:i};r.fields&&(o.fields=r.fields),r.expand&&(o.expand=r.expand);const a=e.issueSearch,c=a&&"function"==typeof a.searchForIssuesUsingJqlEnhancedSearch?a.searchForIssuesUsingJqlEnhancedSearch:a&&"function"==typeof a.searchForIssuesUsingJql?a.searchForIssuesUsingJql:void 0;if(!c)throw Error("Jira search API is unavailable on the client");const p=await c.call(a,o),d=p?.data??p,u="object"==typeof d&&null!==d?{...d}:{};return void 0===u.startAt&&(u.startAt=s),void 0===u.maxResults&&(u.maxResults=i),ht(u)}catch(e){throw bt(e)}}},jt=w.object({issueId:w.string().min(1).describe("Jira issue key or numeric ID to read"),expand:w.string().optional().describe("Optional expand clause for nested fields or changelog"),fields:w.array(w.string()).optional().describe("Explicit list of issue fields to return"),properties:w.array(w.string()).optional().describe("Specific issue properties to include in the response")}).describe("Arguments required to read a Jira issue"),xt={name:"jira-issue-read",inputSchema:jt,runTool:async(e,t)=>{try{const r=jt.parse(t),s={issueIdOrKey:r.issueId};r.expand&&(s.expand=r.expand),r.fields&&(s.fields=r.fields),r.properties&&(s.properties=r.properties);const i=await e.issues.getIssue(s);return ht(i?.data??i)}catch(e){throw bt(e)}}},At=w.object({issueId:w.string().min(1).describe("Target issue key or ID to transition"),transitionId:w.union([w.string(),w.number()]).describe("Identifier for the transition to execute"),fields:w.record(w.any()).optional().describe("Optional field updates to apply during the transition"),update:w.record(w.array(w.object({set:w.any().optional().describe("Set operation for the transition update"),add:w.any().optional().describe("Add operation for the transition update"),remove:w.any().optional().describe("Remove operation for the transition update")}))).optional().describe("Structured update operations to send alongside the transition"),comment:w.string().optional().describe("Optional comment to attach during the transition")}).describe("Inputs needed to transition a Jira issue"),Tt={name:"jira-issue-transition",inputSchema:At,runTool:async(e,t)=>{try{const r=At.parse(t),s={id:r.transitionId};r.fields&&(s.fields=r.fields),r.update&&(s.update=r.update),r.comment&&(s.comment={body:ct(r.comment)});const i=await e.issues.transition({issueIdOrKey:r.issueId,transition:s});return ht(i?.data??i)}catch(e){throw bt(e)}}},Et=w.object({issueId:w.string().min(1).describe("Issue key or ID for which to list transitions"),expand:w.string().optional().describe("Optional expand parameter for the transition response")}).describe("Inputs used to fetch available transitions for an issue"),Ot={name:"jira-transition-list",inputSchema:Et,runTool:async(e,t)=>{try{const r=Et.parse(t),s=e.issues;if(!s||"function"!=typeof s.getTransitions)throw Error("Jira transitions API is unavailable on the client");const i={issueIdOrKey:r.issueId};r.expand&&(i.expand=r.expand);const n=await s.getTransitions(i);return ht(n?.data??n)}catch(e){throw bt(e)}}},Jt=w.object({issueId:w.string().min(1).describe("Issue key or ID to update"),fields:w.record(w.any()).optional().describe("Direct field map to apply to the issue (e.g., description, labels)"),update:w.record(w.array(w.object({set:w.any().optional().describe("Set operation alongside the update key"),add:w.any().optional().describe("Add operation alongside the update key"),remove:w.any().optional().describe("Remove operation alongside the update key"),edit:w.any().optional().describe("Edit operation alongside the update key")}))).optional().describe("Structured update operations for array/set fields"),properties:w.array(w.any()).optional().describe("Property payloads to attach to the issue"),notifyUsers:w.boolean().optional().default(!0).describe("Whether to notify watchers when the issue is updated"),issueTemplateId:w.string().optional().describe("Optional template ID to render issue descriptions"),overrideScreenSecurity:w.boolean().optional().default(!1).describe("Temporarily bypass screen security restrictions"),overrideEditableFlag:w.boolean().optional().default(!1).describe("Temporarily bypass the editable flag on the screen")}).describe("Arguments used to update existing Jira issues"),Ct=o.for("jira.rate-limit"),_t=Je.jira.rateLimitRetryDelayMs??3e3;let Nt=!1;const Ht="jira-issue-update",Dt=Jt,Pt={name:Ht,inputSchema:Dt,runTool:async(e,t)=>{try{const r=Dt.parse(t),s={issueIdOrKey:r.issueId};r.fields&&(s.fields=(e=>{const t={...e},r=t.description;var s;return(e=>{if(!e||"object"!=typeof e)return!1;const t=e;return"doc"===t.type&&1===t.version&&Array.isArray(t.content)})(r)&&(t.description=(s=r,{...s,content:dt(s.content??[])})),t})(r.fields)),r.update&&(s.update=r.update),r.properties&&(s.properties=r.properties),void 0!==r.notifyUsers&&(s.notifyUsers=r.notifyUsers),r.issueTemplateId&&(s.issueTemplateId=r.issueTemplateId),void 0!==r.overrideScreenSecurity&&(s.overrideScreenSecurity=r.overrideScreenSecurity),void 0!==r.overrideEditableFlag&&(s.overrideEditableFlag=r.overrideEditableFlag);const i=await(async(e,t)=>{try{return await t()}catch(s){if((e=>{const t=(e=>e?.status??e?.statusCode??e?.response?.status??e?.response?.statusCode??void 0)(e);if(403!==t)return!1;const r=(e=>{const t=e?.response?.data??e?.data??e?.response?.body??e,r=[];return"string"==typeof t&&r.push(t),"string"==typeof t?.message&&r.push(t.message),"string"==typeof t?.errorMessage&&r.push(t.errorMessage),Array.isArray(t?.errorMessages)&&r.push(...t.errorMessages.filter(e=>"string"==typeof e)),"string"==typeof t?.details?.message&&r.push(t.details.message),r.join(" ")||""})(e);return/rate\s?limit/i.test(r)})(s))return Nt||(Ct.warn(`Jira rate limit detected for ${e}; waiting ${_t}ms before retrying.`,{retryDelayMs:_t}),Nt=!0),_t>0&&await(r=_t,new Promise(e=>setTimeout(e,r))),t();throw s}var r})(Ht,()=>e.issues.editIssue(s));return ht(i?.data??i)}catch(e){throw bt(e)}}},Rt=w.object({issueId:w.string().min(1).describe("Issue key or ID for the assignment change"),assignee:w.union([w.string().describe("Username or account name of the new assignee"),w.object({accountId:w.string().min(1).describe("Account ID of the assignee")}),w.object({accountType:w.string().min(1).describe("Account type filter (e.g., user, app)")})]).describe("How the new assignee is specified")}).describe("Arguments required to assign a Jira issue to someone"),$t={name:"jira-assign-issue",inputSchema:Rt,runTool:async(e,t)=>{try{const r=Rt.parse(t);let s;s="string"==typeof r.assignee?{accountId:r.assignee}:r.assignee;const i=await e.issues.assignIssue({issueIdOrKey:r.issueId,assignee:s});return ht(i?.data??i)}catch(e){throw bt(e)}}},qt=w.object({issueId:w.string().min(1).describe("Issue key or ID to remove the assignee from")}).describe("Inputs required to unassign a Jira issue"),Mt={name:"jira-unassign-issue",inputSchema:qt,runTool:async(e,t)=>{try{const r=qt.parse(t),s=await e.issues.assignIssue({issueIdOrKey:r.issueId,assignee:{accountId:"-1"}});return ht(s?.data??s)}catch(e){throw bt(e)}}},Lt=w.object({issueId:w.string().min(1).describe("The Jira issue key or numeric ID receiving the comment"),body:w.string().min(1).describe("The markdown-compatible text of the comment"),visibility:w.object({type:w.enum(["role","group"]).describe("Visibility type that restricts the comment to a role or group"),value:w.string().min(1).describe("The name of the role or group granted visibility")}).optional().describe("Optional visibility override controlling who can read the comment")}).describe("Arguments for adding a comment to a Jira issue"),Ut={name:"jira-comment-add",inputSchema:Lt,runTool:async(e,t)=>{try{const r=Lt.parse(t),s=e.issueComments;if(!s||"function"!=typeof s.addComment)throw Error("Jira issueComments API is unavailable on the client");const i={issueIdOrKey:r.issueId,comment:r.body};r.visibility&&(i.visibility=r.visibility);const n=await s.addComment(i);return ht(n?.data??n)}catch(e){throw bt(e)}}},Ft=w.object({issueId:w.string().min(1).describe("Issue key or ID whose comments should be retrieved"),start:w.number().optional().default(0).describe("Zero-based index to start pagination from"),maxResults:w.number().optional().default(50).describe("Maximum number of comments to return"),orderBy:w.string().optional().describe("Field name to order the returned comments by"),expand:w.string().optional().describe("Optional expansion clause for the comment response")}).describe("Parameters for fetching comments on a Jira issue"),Bt={name:"jira-comment-list",inputSchema:Ft,runTool:async(e,t)=>{try{const r=Ft.parse(t),s=e.issueComments;if(!s||"function"!=typeof s.getComments)throw Error("Jira issueComments API is unavailable on the client");const i=await s.getComments({issueIdOrKey:r.issueId,startAt:r.start,maxResults:r.maxResults,orderBy:r.orderBy,expand:r.expand});return ht(i?.data??i)}catch(e){throw bt(e)}}},Wt=w.enum(["Blocks","Relates to","Duplicates","Is blocked by","Is related to","is tested by","tests","Is covered by","covered by","Is duplicated by","Causes","Is caused by","Clone","Required","Work on","Split","Roll up"]).describe("The named relationship (Blocks, Relates to, etc.) that describes the link type"),Kt=w.object({id:w.string().optional().describe("Numeric Jira ID used when referencing an issue"),key:w.string().optional().describe("Human-readable key of the linked issue")}).describe("An issue reference (ID or key) used when building a link payload"),Xt=w.object({type:w.enum(["role","group"]).describe("Visibility scope type attached to the comment"),value:w.string().min(1).describe("Name of the role or group granted visibility to the comment")}).describe("Optional visibility settings applied to the comment"),Yt=w.object({body:w.string().optional().describe("Markdown text to include as a linked-comment"),visibility:Xt.optional().describe("Optional ACL for the comment")}).describe("Optional comment applied at the time the link is created or updated"),zt=w.object({link:w.object({relationship:Wt,inwardIssue:Kt,outwardIssue:Kt,comment:Yt.optional()}).describe("Definition of the link that should be created between two issues")}).describe("Arguments required to create a Jira issue link");let Gt=[];function Zt(e){return(e||"").trim().toLowerCase()}async function Vt(e,t){if(!t)throw Error("Link relationship is required");0===Gt.length&&(Gt=await(async e=>{const t=e.issueLinkTypes;if(!t||"function"!=typeof t.getIssueLinkTypes)throw Error("Jira issueLinkTypes API is unavailable on the client");const r=await t.getIssueLinkTypes(),s=r?.issueLinkTypes??r?.values??r;return Array.isArray(s)?s:[]})(e));const r=Zt(t),s=Gt.find(e=>[e.name,e.inward,e.outward].some(e=>Zt(e)===r));if(!s)throw Error(`No issue link type matching '${t}' found.`);return s}function Qt(e){if(!e)throw Error("Linked issue must include an id or key");if(e.id)return{id:e.id};if(e.key)return{key:e.key};throw Error("Linked issue must include an id or key")}function er(e){if(!e)return;const t={};return e.body&&(t.body=ct(e.body)),e.visibility&&(t.visibility=e.visibility),Object.keys(t).length>0?t:void 0}const tr=zt,rr={name:"jira-link-create",inputSchema:tr,runTool:async(e,t)=>{try{const r=tr.parse(t).link,s={inwardIssue:Qt(r.inwardIssue),outwardIssue:Qt(r.outwardIssue)},i=er(r.comment);i&&(s.comment=i);const n=e.issueLinks;if(!n||"function"!=typeof n.linkIssues)throw Error("Jira issueLinks API is unavailable on the client");const o=await Vt(e,r.relationship);s.type={id:o.id};const a=await n.linkIssues(s);return ht(a?.data??a)}catch(e){throw bt(e)}}},sr=w.object({issueId:w.string().min(1).describe("Issue key or ID receiving the attachment"),file:w.string().min(1).describe("Base64 or path to the file contents to upload"),mimeType:w.string().optional().describe("Optional MIME type override for the attachment"),comment:w.string().optional().describe("Optional comment to associate with the attachment")}).describe("Inputs needed to attach a file to a Jira issue"),ir={name:"jira-attach",inputSchema:sr,runTool:async(e,t)=>{try{const r=sr.parse(t),i=A.resolve(r.file),n=await s.readFile(i),o=A.basename(i),a=new FormData;a.append("file",new Blob([n],{type:r.mimeType??"application/octet-stream"}),o);const c=e?.config??null,p=c?.host,d=c?.authentication?.basic??c?.authentication??c?.auth??null,u=d?.email,l=d?.apiToken??d?.apiKey;if(!p||!u||!l)throw Error("Jira client authentication configuration is unavailable for attachments");const m=await fetch(`${p}/rest/api/3/issue/${r.issueId}/attachments`,{method:"POST",headers:{Authorization:"Basic "+Buffer.from(`${u}:${l}`).toString("base64"),"X-Atlassian-Token":"no-check"},body:a});if(!m.ok){const e=await m.text();throw Error(`Jira attachment upload failed (${m.status}): ${e}`)}const h=await m.json();if(r.comment){const t=e.issueComments;if(!t||"function"!=typeof t.addComment)throw Error("Jira issueComments API is unavailable on the client");await t.addComment({issueIdOrKey:r.issueId,comment:ct(r.comment)})}return ht(h)}catch(e){if(e&&e.code&&"string"==typeof e.code&&["ENOENT","EACCES"].includes(e.code))throw Error("Attachment file error: "+e.message);throw bt(e)}}},nr=w.object({issueId:w.string().min(1).describe("Issue key or ID whose attachments should be listed")}).describe("Arguments used to fetch attachments for a Jira issue"),or={name:"jira-attachment-list",inputSchema:nr,runTool:async(e,t)=>{try{const r=nr.parse(t),s=e.issues;if(!s||"function"!=typeof s.getIssue)throw Error("Jira issues API is unavailable on the client");const i=await s.getIssue({issueIdOrKey:r.issueId,fields:["attachment"]}),n=i?.data??i;return ht({attachments:n?.fields?.attachment??[]})}catch(e){throw bt(e)}}},ar=w.object({issueId:w.string().min(1).describe("Issue key or ID owning the attachment"),attachmentId:w.string().min(1).describe("ID of the attachment to delete")}).describe("Arguments required to remove an attachment from Jira"),cr={name:"jira-attachment-delete",inputSchema:ar,runTool:async(e,t)=>{try{const r=ar.parse(t),s=e.issueAttachments;if(!s||"function"!=typeof s.removeAttachment)throw Error("Jira issueAttachments API is unavailable on the client");return await s.removeAttachment({id:r.attachmentId}),ht({success:!0,message:`Attachment ${t.attachmentId} deleted successfully`})}catch(e){throw bt(e)}}},pr=w.object({issueId:w.string().min(1).describe("Target issue key or ID for the worklog entry"),timeSpent:w.string().min(1).describe('Time spent text (e.g., "1h 30m")'),comment:w.string().optional().describe("Optional worklog comment in markdown"),author:w.object({accountId:w.string().min(1).describe("Account ID of the user logging the work")}).optional().describe("Optional author override for the worklog entry"),startingOn:w.string().optional().describe("Optional timestamp for when the work started (ISO)"),artifact:w.string().optional().describe("Optional identifier linking the worklog to another artifact")}).describe("Arguments required to add a worklog entry to a Jira issue"),dr={name:"jira-worklog-add",inputSchema:pr,runTool:async(e,t)=>{try{const r=pr.parse(t),s={timeSpent:r.timeSpent};r.comment&&(s.comment=r.comment),r.author&&(s.author=r.author),r.startingOn&&(s.started=r.startingOn),r.artifact&&(s.artifact=r.artifact);const i=e.issueWorklogs;if(!i||"function"!=typeof i.addWorklog)throw Error("Jira issueWorklogs API is unavailable on the client");const n=await i.addWorklog({issueIdOrKey:r.issueId,...s});return ht(n?.data??n)}catch(e){throw bt(e)}}},ur=o.for("jira.xray");class lr{constructor(){this.clientId=Je.orThrow().xray.apiUser,this.clientSecret=Je.orThrow().xray.apiSecret,this.baseUrl=Je.orThrow().xray.host||"https://eu.xray.cloud.getxray.app"}async authenticate(){if(!this.clientId||!this.clientSecret)throw Error("Xray API credentials are missing (XRAY__API_USER, XRAY__API_SECRET).");const e=await fetch(this.baseUrl+"/api/v2/authenticate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_id:this.clientId,client_secret:this.clientSecret})}),t=await e.text();return this.token=t.replace(/"/g,""),this.token}async graphql(e,t){this.token||await this.authenticate();const r={query:e,variables:t};ur.info("xray.graphql.request",{payload:$e(r)});try{const e=await fetch(this.baseUrl+"/api/v2/graphql",{method:"POST",headers:{Authorization:"Bearer "+this.token,"Content-Type":"application/json"},body:JSON.stringify(r)}),t=await e.json();if(ur.info("xray.graphql.response",{status:e.status,headers:e.headers?.get?e.headers.get("content-type"):void 0,body:$e(t)}),t.errors)throw ur.error("xray.graphql.errors",{errors:$e(t.errors)}),Error(JSON.stringify(t.errors,null,2));return t.data}catch(e){throw ur.error("xray.graphql.failure",{error:e+""}),e}}async getTest(e){return(await this.graphql('\n query GetTest($issueId: String!) {\n getTest(issueId: $issueId) {\n issueId\n jira(fields:["key"])\n steps {\n id\n action\n data\n result\n }\n }\n }\n ',{issueId:e})).getTest}async addStep(e,t){return(await this.graphql("\n mutation AddTestStep($issueId: String!, $step: CreateStepInput!) {\n addTestStep(issueId: $issueId, step: $step) {\n id\n action\n data\n result\n }\n }\n ",{issueId:e,step:t})).addTestStep}async updateStep(e,t){return(await this.graphql("\n mutation UpdateTestStep($stepId: String!, $step: UpdateStepInput!) {\n updateTestStep(stepId: $stepId, step: $step) {\n id\n action\n data\n result\n }\n }\n ",{stepId:e,step:t})).updateTestStep}async deleteStep(e){return(await this.graphql("\n mutation RemoveTestStep($stepId: String!) {\n removeTestStep(stepId: $stepId)\n }\n ",{stepId:e})).removeTestStep}async addSteps(e,t){return Promise.all(t.map(t=>this.addStep(e,t)))}async updateSteps(e){return Promise.all(e.map(e=>this.updateStep(e.stepId,e.step)))}async deleteSteps(e){return Promise.all(e.map(e=>this.deleteStep(e)))}async syncSteps(e,t){const r=(await this.getTest(e)).steps||[],s=[],i=[],n=[];for(let e=0;e<t.length;e++){const n=t[e],o=r[e];o?o.action===n.action&&o.data===n.data&&o.result===n.result||s.push({stepId:o.id,step:n}):i.push(n)}if(r.length>t.length)for(let e=t.length;e<r.length;e++)n.push(r[e].id);await this.addSteps(e,i),await this.updateSteps(s),await this.deleteSteps(n)}}let mr=null;const hr=new Map;function fr(e){const t=e?.fields,r=e?.action??t?.Action??t?.action;if(!r||"string"!=typeof r)throw Error("Xray step action is required");const s=e.data??e.fields?.Data??e.fields?.data??void 0,i=e.result??e.fields?.Result??e.fields?.result??void 0;return{action:r.toString(),data:"string"==typeof s?s:void 0,result:"string"==typeof i?i:void 0}}async function yr(e,t){if(!t)throw Error("Issue reference is required when interacting with Xray steps");if(hr.has(t))return hr.get(t);if(/^[0-9]+$/.test(t))return hr.set(t,t),t;const r=e?.issues??e?.issue;if(!r?.getIssue)throw Error("Jira client does not expose issue lookup functionality");const s=await r.getIssue({issueIdOrKey:t,fields:["id"]}),i=s?.id;if(!i)throw Error("Unable to resolve Jira issue ID for "+t);return hr.set(t,i),i}async function gr(e){if(e?.test?.step)return e.test.step;const t=await(async()=>{if(mr)return mr;const e=Je.orThrow().xray.apiUser?.trim(),t=Je.orThrow().xray.apiSecret?.trim();if(!e||!t)throw Error("Xray credentials are missing (XRAY__API_USER, XRAY__API_SECRET). Please configure them before using Xray tools.");const r=Me(),s=new lr;return mr={test:{step:{async createStep(e,t){const i=await yr(r,e),n=await s.addStep(i,fr(t));return{step:n,id:n?.id}},async updateStep(e,t,i){await yr(r,e);const n=fr(i),o=await s.updateStep(t.toString(),n);return{step:o,id:o?.id}},deleteStep:async(e,t)=>(await yr(r,e),{success:!0===await s.deleteStep(t.toString())}),async getSteps(e){const t=await yr(r,e),i=await s.getTest(t);return{steps:i?.steps??[]}}}}},mr})();if(!t?.test?.step)throw Error("Xray step API is unavailable on the client");return t.test.step}const br=w.object({issueId:w.string().min(1).describe("Xray test case key or ID that owns the step"),action:w.string().min(1).describe("Action description for the new Xray step"),data:w.string().optional().describe("Optional data or context used by this step"),result:w.string().optional().describe("Optional expected result for the step")}).describe("Inputs for adding a step to an Xray test case"),wr={name:"jira-xray-step-add",inputSchema:br,runTool:async(e,t)=>{try{const r=br.parse(t),s=await gr(e),i={action:r.action,data:r.data,result:r.result};return ht(await s.createStep(r.issueId,i))}catch(e){throw bt(e)}}},vr=w.object({issueId:w.string().min(1).describe("Xray test case key or ID that owns the step"),stepId:w.union([w.string(),w.number()]).describe("Identifier for the step that should be updated"),action:w.string().min(1).describe("New action text for the step"),data:w.string().optional().describe("Updated data/context for the step"),result:w.string().optional().describe("Updated expected result for the step")}).describe("Inputs required to modify an Xray test step"),Ir={name:"jira-xray-step-update",inputSchema:vr,runTool:async(e,t)=>{try{const r=vr.parse(t),s=await gr(e),i=r.stepId+"",n={action:r.action,data:r.data,result:r.result};return ht(await s.updateStep(r.issueId,i,n))}catch(e){throw bt(e)}}},Sr=w.object({issueId:w.string().min(1).describe("Xray test case key or ID owning the step"),stepId:w.union([w.string(),w.number()]).describe("Identifier of the step to delete")}).describe("Arguments used to remove an Xray test step"),kr={name:"jira-xray-step-delete",inputSchema:Sr,runTool:async(e,t)=>{try{const r=Sr.parse(t),s=await gr(e);return await s.deleteStep(r.issueId,r.stepId.toString()),ht({success:!0})}catch(e){throw bt(e)}}},jr=w.object({issueId:w.string().min(1).describe("Xray test case key or ID whose steps should be returned")}).describe("Inputs required to list steps on an Xray test case"),xr={name:"jira-xray-step-list",inputSchema:jr,runTool:async(e,t)=>{try{const r=jr.parse(t),s=await gr(e);return ht(await s.getSteps(r.issueId))}catch(e){throw bt(e)}}},Ar=w.object({linkId:w.string().min(1).describe("Identifier for the Jira issue link to remove")}).describe("Inputs required to delete an existing Jira issue link"),Tr={name:"jira-link-delete",inputSchema:Ar,runTool:async(e,t)=>{try{const r=Ar.parse(t),s=e.issueLinks;if(!s||"function"!=typeof s.deleteIssueLink)throw Error("Jira issueLinks API is unavailable on the client");return await s.deleteIssueLink({linkId:r.linkId}),ht({success:!0,message:`Issue link ${r.linkId} deleted successfully`})}catch(e){throw bt(e)}}},Er=w.object({linkId:w.string().min(1).describe("ID of the existing issue link to change"),relationship:Wt,comment:Yt.optional().describe("Optional comment to attach while recreating the link")}).describe("Inputs required to update (recreate) a Jira issue link"),Or={name:"jira-link-update",inputSchema:Er,runTool:async(e,t)=>{try{const r=Er.parse(t),s=e.issueLinks;if(!s||"function"!=typeof s.getIssueLink||"function"!=typeof s.deleteIssueLink||"function"!=typeof s.linkIssues)throw Error("Jira issueLinks API is unavailable on the client");const i=await s.getIssueLink({linkId:r.linkId}),n=i?.data??i;if(!n)throw Error(`Issue link ${r.linkId} not found`);const o=n.inwardIssue,a=n.outwardIssue;if(!o||!a)throw Error("Issue link payload is missing linked issues");const c=await Vt(e,r.relationship);await s.deleteIssueLink({linkId:r.linkId});const p={inwardIssue:Qt(o),outwardIssue:Qt(a),type:{id:c.id}},d=er(r.comment);return d&&(p.comment=d),await s.linkIssues(p),ht({success:!0,message:`Issue link ${r.linkId} updated to ${r.relationship}`})}catch(e){throw bt(e)}}},Jr={[ft.name]:{title:"Jira Issue Create",description:"Create a Jira issue (optionally applying a markdown template)",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[xt.name]:{title:"Jira Issue Read",description:"Read a Jira issue with expandable fields and properties",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[kt.name]:{title:"Jira Issue List",description:"Search issues by summary, reference, parent, or JQL and list the matching tickets",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[Pt.name]:{title:"Jira Issue Update",description:"Update a Jira issue using fields, update ops, and property toggles",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[vt.name]:{title:"Jira Issue Delete",description:"Delete a Jira issue and optionally remove its subtasks",annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1,openWorldHint:!0}},[Tt.name]:{title:"Jira Issue Transition",description:"Transition a Jira issue while optionally adding a comment",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[Ot.name]:{title:"Jira Transition List",description:"List available transitions for a Jira issue",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[$t.name]:{title:"Jira Issue Assign",description:"Assign a Jira issue to a user or account",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[Mt.name]:{title:"Jira Issue Unassign",description:"Unassign the current owner from a Jira issue",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[Ut.name]:{title:"Jira Comment Add",description:"Add a comment to a Jira issue with optional visibility",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[Bt.name]:{title:"Jira Comment List",description:"List comments on a Jira issue with pagination support",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[rr.name]:{title:"Jira Link Create",description:"Create an issue link relationship with optional comment",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[Or.name]:{title:"Jira Link Update",description:"Change the relationship type for an existing issue link",annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1,openWorldHint:!0}},[Tr.name]:{title:"Jira Link Delete",description:"Delete an issue link from Jira",annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1,openWorldHint:!0}},[ir.name]:{title:"Jira Attachment Add",description:"Attach a local file to a Jira issue",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[or.name]:{title:"Jira Attachment List",description:"List attachments on a Jira issue",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[cr.name]:{title:"Jira Attachment Delete",description:"Delete an attachment from a Jira issue",annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1,openWorldHint:!0}},[dr.name]:{title:"Jira Worklog Add",description:"Log time spent on a Jira issue",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[wr.name]:{title:"Jira Xray Step Add",description:"Add a step to an Xray test case",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[Ir.name]:{title:"Jira Xray Step Update",description:"Update a step on an Xray test case",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[kr.name]:{title:"Jira Xray Step Delete",description:"Delete a step from an Xray test case",annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1,openWorldHint:!0}},[xr.name]:{title:"Jira Xray Step List",description:"List steps for an Xray test case",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}}};async function Cr(e){const t=o.for(Cr);let r,s=null;try{r=Me()}catch(e){if(!(e instanceof He))return void t.warn("Skipping Jira tool registration; unable to create Jira client",{error:e});s=e,t.warn("Registering Jira tools without credentials; each tool will report configuration requirements.",{error:e})}const i=[ft,xt,kt,Pt,vt,Tt,Ot,$t,Mt,Ut,Bt,rr,Or,Tr,ir,or,cr,dr,wr,Ir,kr,xr];for(const n of i){const i=Jr[n.name];if(i)try{await e.registerTool(n.name,{title:i.title,description:i.description,inputSchema:n.inputSchema,annotations:i.annotations},async e=>{if(!r)throw s??Error("Jira client unavailable because credentials could not be loaded.");return n.runTool(r,e)}),t.info("Registered Jira tool "+n.name)}catch(e){t.error("Failed to register Jira tool "+n.name,{error:e})}}}async function _r(e){await(async e=>{e.registerTool("decaf-server-info",{title:"Decaf MCP Server Info",description:"Return server metadata, version, and registered prompt names for diagnostics.",inputSchema:{},outputSchema:void 0,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async()=>{const e=Se.map(e=>e.getName()).sort();return{content:[{type:"text",text:["Name: "+Je.name,"Title: "+Je.title,"Version: "+Je.version,"Prompts: "+(e.join(", ")||"<none>")].join("\n")}]}})})(e);const t=o.for(_r);try{await Cr(e)}catch(e){t.error("Failed to register Jira tools",e)}}class Nr extends Z{setCb(e){return this.cb=e,this}setConfig(e){return this.config=e,this}setUriOtTemplate(e){return this.uriOrTemplate=e,this}constructor(e){super(e)}static get builder(){return new Nr}build(e){const t=this.hasErrors();if(t)throw Error(t.toString());try{const t="string"==typeof this.uriOrTemplate&&this.uriOrTemplate.includes("{")?new q(new $(this.uriOrTemplate),{list:void 0}):this.uriOrTemplate,r=Object.assign(this.config,{_meta:{}}),s=async(e,t)=>{const r=this.logFor(t);r.verbose(`Requesting resource ${this.name} from ${e.toString()}`);const s=await Promise.resolve(this.cb(e,t));return r.verbose(`Resource ${this.name} retrieved successfully.`),r.debug("Resource retrieval meta: "+JSON.stringify(s._meta)),s};return e.resource(this.name,t,r,s)}catch(e){throw o.for(this).error("Error registering resource "+this.name,e),e}}}m([f(),h("design:type",String)],Nr.prototype,"uriOrTemplate",void 0),m([f(),h("design:type",Function)],Nr.prototype,"cb",void 0),m([f(),h("design:type",Object)],Nr.prototype,"config",void 0);const Hr=ue()??x.join(__dirname,"..","assets"),Dr=x.join(Hr,"templates"),Pr=x.join(Hr,"prompts"),Rr=[{name:"example.resource",title:"Example Resource",description:"A tiny example payload for verifying resource listing.",uri:"resource://example.resource",cb:async()=>({contents:[{type:"text",text:"example"}],_meta:{}})},{name:"repo.metadata",title:"Repository Metadata",description:"Static metadata for the decaf-ts repository.",uri:"resource://repo.metadata",cb:async()=>({contents:[{type:"json",text:JSON.stringify({repo:"decaf-ts",version:"1.0.0"})}],_meta:{}})},{name:"decoration.schematics",title:"Decoration Schematics",description:"Metadata describing decoration schematics that ship with the project.",uri:"resource://decoration.schematics",cb:async()=>({content:{type:"json",data:JSON.stringify({collection:"decaf",files:["metadata/Metadata.ts"]})},_meta:{}})},{name:"golden.overrides",title:"Golden Overrides",description:"Stubbed golden override payload used for testing the resource API.",uri:"resource://golden.overrides",cb:async()=>({content:{type:"text",text:"golden overrides stub"},_meta:{}})}];async function $r(e){const t=o.for($r);for(const r of Rr){const{name:s,uri:i,title:n,description:o,cb:a}=r;if(!s||!i||"function"!=typeof a){t.warn("Skipping invalid resource registration: "+(s??"<unknown>"));continue}const c={title:n??s,description:o??"",_meta:{}};try{await e.resource(s,i,c,async(e,t)=>a(e,t)),t.info(`Registered resource ${s} @ ${i}`)}catch(e){t.error("Failed to register resource "+s,e)}}}const qr=new WeakMap;class Mr extends a{get client(){const e=qr.get(this);if(!e)throw Error("Mcp server requires Mcp client");return e}constructor(){super()}async load(){const e=this.log.for(this.load);for(const t of Se)try{e.info("loading prompt "+t.getName());const r=t.build(this.client);e.verbose(`Loaded prompt ${r.title} from ${t.getName()} definition`)}catch(r){e.error("Failed to load prompt "+t.getName(),r)}try{await _r(this.client),e.verbose("Registered built-in tools")}catch(e){}try{await $r(this.client),e.verbose("Registered built-in resources")}catch(e){}try{await(async(e,r)=>{r.info("Registering agent templates as resources...");const s=t.readdirSync(Dr).filter(e=>e.endsWith(".md"));for(const i of s){const s=x.basename(i,".md"),n=x.join(Dr,i),o=Nr.builder.setName(s).setTitle("Template: "+s).setDescription("Resource template for "+s).setUriOtTemplate("file:///"+n).setConfig({mimeType:"text/markdown",description:"Template for "+s}).setCb(async e=>{const r=t.readFileSync(e.pathname,"utf8");return{contents:[{uri:e.toString(),text:r,mimeType:"text/markdown"}],_meta:{}}});try{o.build(e),r.info("Registered template: "+s)}catch(e){r.error(`Failed to register template ${s}:`,e)}}r.info("Registering agent prompts...");const i=t.readdirSync(Pr).filter(e=>e.endsWith(".md"));for(const s of i){const i=x.basename(s,".md"),n=x.join(Pr,s),o=t.readFileSync(n,"utf8"),a=me.builder.setName(i).setTitle("Prompt: "+i).setDescription("Dynamic prompt for "+i).setArgsSchema(w.object({})).setCb(async e=>({messages:[{role:"user",content:{type:"text",text:o}}],_meta:{}}));try{a.build(e),r.info("Registered prompt: "+i)}catch(e){r.error(`Failed to register prompt ${i}:`,e)}}})(this.client,e)}catch(e){}}async boot(e="stdio"){"stdio"===e&&o.setFactory(W),o.for(this.constructor.name);const t=((Array.isArray(Je.icons)?Je.icons:[Je.icons])||[]).map(e=>{const t="string"==typeof e?.src?e.src:(e?.src??"")+"",r="string"==typeof e?.mimeType?e.mimeType:(e?.mimeType??"")+"";let s=[];return Array.isArray(e?.sizes)?s=e.sizes.map(e=>e+""):"string"==typeof e?.sizes&&(s=(e.sizes+"").split(",").map(e=>e.trim())),{src:t,mimeType:r,sizes:s}}),r={name:Je.name,title:Je.title,websiteUrl:Je.websiteUrl,version:Je.version,icons:t},s=new M(r,{instructions:"You are an AI assistant designed to help users with programming tasks related to the Decaf-TS framework. \nProvide clear, concise, and accurate information.\nIf you don't know the answer, admit it rather than making up information.\nAlways prioritize the user's intent and provide helpful suggestions when appropriate.\n",capabilities:{logging:{},tools:{},prompts:{}}});switch(((e,t)=>{qr.set(e,t)})(this,s),s.onerror=e=>{this.log.error("MCP instance onerror",e)},e){case"stdio":e=new U;break;case"http":e=new F({sessionIdGenerator:()=>L(),onsessioninitialized:e=>{},onsessionclosed:e=>{},enableJsonResponse:!0,eventStore:void 0});break;default:if(!(i=e)||"object"!=typeof i||"function"!=typeof i.send&&"function"!=typeof i.close&&"function"!=typeof i.on)throw new T("Invalid transport type: "+e)}var i;try{await this.load()}catch(e){throw e}await this.client.connect(e)}}const Lr=(new e).command("start").option("--transport [String]","transport mode","stdio").description("starts decaf's mcp server").action(async e=>{const t=pe("package.json"),s=JSON.parse(r.readFileSync(t,"utf-8")),i=s.version,{transport:n}=e,o=(new B).for("mcp-server");if("stdio"!==n)throw Error("Unsupported transport mode: "+n);return o.info("Transport stdio"),o.debug(`running with options: ${JSON.stringify(e)} for ${s.name} version ${i}`),(new Mr).boot(n)});(new e).command("md-to-ast").description("pipes markdown to jira ast: `cat file.md` | npx decaf-mcp md-to-ast > ast.json").action(async e=>{const t=pe("package.json"),s=JSON.parse(r.readFileSync(t,"utf-8")),i=s.version;o.for("md-to-ast").debug(`running with options: ${JSON.stringify(e)} for ${s.name} version ${i}`);const n=ct(await(async()=>{const e=[];for await(const t of process.stdin)e.push(Buffer.from(t));return Buffer.concat(e).toString("utf8")})(),{resolveMention:e=>({id:e,text:"@"+e}),resolveAttachment:e=>({id:e,collection:"attachments"})});process.stdout.write(JSON.stringify(n,null,2)+"\n")});const Ur=(new e).name("mcp-server").command("mcp-server").description("decaf mcp server and agentic functionality");Ur.addCommand(Lr),Ur.parse(process.argv);
|
|
1
|
+
import{Command as e}from"commander";import*as t from"fs";import r,{promises as s}from"fs";import{MiniLogger as n,NumericLogLevels as i,Logging as o,LoggedClass as a,toSnakeCase as c,sf as d,toPascalCase as l,LogLevel as p,LoggedEnvironment as u}from"@decaf-ts/logging";import{__decorate as m,__metadata as h}from"tslib";import{required as y,Model as f,list as g,minlength as b}from"@decaf-ts/decorator-validation";import{z as w,ZodObject as v}from"zod";import{injectable as I,inject as j}from"@decaf-ts/injectable-decorators";import{prop as k,Metadata as S}from"@decaf-ts/decoration";import*as x from"path";import A from"path";import{InternalError as T,SerializationError as E,ValidationError as O}from"@decaf-ts/db-decorators";import J from"crypto";import C from"zlib";import{fileURLToPath as D}from"url";import{inspect as H}from"node:util";import{unified as N}from"unified";import _ from"remark-directive";import R from"remark-gfm";import $ from"remark-parse";import{UriTemplate as P}from"@modelcontextprotocol/sdk/shared/uriTemplate.js";import{ResourceTemplate as M,McpServer as L}from"@modelcontextprotocol/sdk/server/mcp.js";import{v4 as q}from"uuid";import{StdioServerTransport as F}from"@modelcontextprotocol/sdk/server/stdio.js";import{StreamableHTTPServerTransport as U}from"@modelcontextprotocol/sdk/server/streamableHttp.js";class z extends n{constructor(e,t,r){super(e,t,r)}log(e,t,r,s){const n=this.config("level");i[n],i[e]}}const B=(e,t,...r)=>{const s=(e=>{if("string"==typeof e)return e;if(!e)return"unknown";if("function"==typeof e)return e.name||"unknown";if("object"==typeof e&&"constructor"in e){const t=e.constructor;if(t&&t.name)return t.name}return"unknown"})(e);return new z(s,t)};var W,K,X,Y,G;(e=>{e[e.NONE=0]="NONE",e[e.BASIC=1]="BASIC",e[e.ADVANCED=2]="ADVANCED",e[e.HIGH=3]="HIGH"})(W||(W={})),(e=>{e[e.NONE=0]="NONE",e[e.LOW=1]="LOW",e[e.MEDIUM=2]="MEDIUM",e[e.HIGH=3]="HIGH"})(K||(K={})),(e=>{e[e.FREE=0]="FREE",e[e.LOW=1]="LOW",e[e.MEDIUM=2]="MEDIUM",e[e.HIGH=3]="HIGH"})(X||(X={}));class Z extends f{get log(){return this._log||(this._log=o.for(this)),this._log}constructor(e){super(e)}logFor(e){const{sessionId:t,requestId:r,authInfo:s}=e||{};let n="string"==typeof t&&t.length>0?this.log.for(t):this.log;return s&&s.clientId&&(n=n.for(s.clientId)),r&&(n=n.for(r.toString())),n}setDescription(e){return this.description=e,this}getDescription(){return this.description}setName(e){return this.name=e,this}getName(){return this.name}setTitle(e){return this.title=e,this}}m([y(),h("design:type",String)],Z.prototype,"description",void 0),m([y(),h("design:type",String)],Z.prototype,"name",void 0),m([y(),h("design:type",String)],Z.prototype,"title",void 0);class V extends Z{constructor(e){super(e),this.reasoning=W.NONE,this.effort=K.NONE,this.cost=X.FREE}setReasoning(e){return this.reasoning=e,this}setEffort(e){return this.effort=e,this}setCost(e){return this.cost=e,this}}function Q(e){if(!e)return;let t=e,r=t&&t._def;for(;r&&"ZodObject"!==r.typeName;){if("ZodEffects"===r.typeName&&r.schema)t=r.schema;else if("ZodOptional"===r.typeName&&r.innerType)t=r.innerType;else if("ZodDefault"===r.typeName&&r.innerType)t=r.innerType;else if("ZodNullable"===r.typeName&&r.innerType)t=r.innerType;else{if(!r.schema)return;t=r.schema}r=t&&t._def}return r&&"ZodObject"===r.typeName?r:void 0}function ee(e,t="schema"){if(Q(e))return e;if(e&&"object"==typeof e){const t=e.def&&"object"==typeof e.def?e.def:void 0,r=t&&(t.shape||"object"===t.type)&&t.shape||("object"===e.type?e.shape:void 0)||(t&&"object"===t.type?{}:void 0);if(t||"object"===e.type||r){const e={};if(r&&"object"==typeof r)for(const[t,s]of Object.entries(r))e[t]=re(s)?s:w.any();return w.object(e)}}throw Error(`Registration error: provided a non-canonical ${t}. Export a ZodObject (z.object(...)).`)}function te(e){if(!e)return;if(e&&"object"==typeof e&&!e._def)return e.def&&"object"==typeof e.def&&e.def.shape?e.def.shape:e;const t=Q(e);return t?"function"==typeof t.shape?t.shape():t.shape||void 0:void 0}function re(e){return!(!e||"object"!=typeof e||!e._def)}m([y(),h("design:type",Number)],V.prototype,"reasoning",void 0),m([y(),h("design:type",Number)],V.prototype,"effort",void 0),m([y(),h("design:type",Number)],V.prototype,"cost",void 0),(e=>{e.ASSETS="assets"})(Y||(Y={})),(e=>{e.PROMPT="prompts",e.DOCUMENTATION="documentation",e.CODE="code"})(G||(G={}));const se=Buffer.from("DCAF1","ascii");function ne(e){let t=A.resolve(e);for(;;){if(r.existsSync(A.join(t,"package.json")))return t;const e=A.dirname(t);if(e===t)break;t=e}}const ie=process.argv?.[1]?ne(A.dirname(A.resolve(process.argv[1]))):void 0,oe=(()=>{const e=Error().stack;if(!e)return;const t=e.split(/\r?\n/).slice(1);for(const e of t){const t=e.match(/\(?([^()]+?):\d+:\d+\)?/);if(!t)continue;let r=t[1];if(r.startsWith("file://"))try{r=D(r)}catch{continue}if(!r.includes("node:internal"))return A.dirname(r)}})(),ae=oe?ne(oe):void 0,ce=ie??ae??process.cwd();function de(...e){return A.join(ce,...e)}function le(e){let r=e;for(;;){const e=x.join(r,"lib","assets");if(t.existsSync(e))return e;const s=x.join(r,"src","assets");if(t.existsSync(s))return s;const n=x.join(r,"assets");if(t.existsSync(n))return n;const i=x.dirname(r);if(i===r)break;r=i}}function pe(){const e=process.env.DECAF_ASSET_DIR||process.env.MCP_ASSET_DIR||process.env.ASSET_DIR||"";if(e&&t.existsSync(e))return e;const r=le(__dirname);if(r)return r;const s=process.argv?.[1];if(s){const e=le(x.dirname(s));if(e)return e}const n=[ce,process.env.INIT_CWD].filter(Boolean);for(const e of n){const t=le(e);if(t)return t}return de("assets")}let ue=class extends a{constructor(e){super(),this.basePath=e||pe()}listAssets(...e){const r=x.join(this.basePath,...e);return t.readdirSync(r)}listPrompts(){return this.listAssets(G.PROMPT)}getAsset(e,r="md",...s){const n=x.join(this.basePath,...s),i=(e,r=!1)=>{try{return r?(e=>{if(e.length<se.length+16+12+16)throw Error("Invalid prompt payload (too short)");if(!e.subarray(0,se.length).equals(se))throw Error("Invalid prompt payload (bad magic)");const t=process.env.ENCRYPTION_KEY||"";if(!t)throw Error("Missing encryption key. Set ENCRYPTION_KEY to load obfuscated assets.");let r=se.length;const s=e.subarray(r,r+16);r+=16;const n=e.subarray(r,r+12);r+=12;const i=e.subarray(r,r+16);r+=16;const o=e.subarray(r),a=((e,t)=>J.scryptSync(e,t,32))(t,s),c=J.createDecipheriv("aes-256-gcm",a,n);c.setAuthTag(i);const d=Buffer.concat([c.update(o),c.final()]);return C.gunzipSync(d)})(t.readFileSync(e)).toString("utf-8"):t.readFileSync(e,"utf-8")}catch(e){if("ENOENT"===e.code)return null;throw e}},o=i(x.join(n,`${e}.${r}`),"enc"===r);if(null!==o)return o;const a=i(x.join(n,e+".enc"),!0);if(null!==a)return a;throw Error("Asset not found: "+x.join(n,`${e}.${r}`))}getAllAssets(e,...t){return this.listAssets(e,...t).reduce((r,s)=>{const n=x.extname(s),i=x.basename(s,n),o=n.replace(/^\./,"")||void 0;return r[i]=this.getAsset(i,o??void 0,e,...t),r},{})}toPromptDef(e){const t=e=>"number"==typeof e?e:"string"==typeof e?(e=>{switch(e){case"none":return W.NONE;case"basic":return W.BASIC;case"advanced":return W.ADVANCED;case"high":return W.HIGH;case"medium":return K.MEDIUM;case"low":return X.LOW;case"free":return X.FREE;default:throw new T("Cannon convert unknown level "+e)}})(e.toLowerCase()):W.NONE;return e.effort=t(e.effort),e.reasoning=t(e.reasoning),e.cost=t(e.cost),e}getPrompt(e,...t){const r=this.getAsset(c(e),"json",G.PROMPT,...t);let s;try{s=JSON.parse(r)}catch(r){throw new E(`Failed to parse prompt ${e} in categories ${t}: ${r}`)}return this.toPromptDef(s)}getAllPrompts(...e){const t=this.getAllAssets(G.PROMPT,...e);return Object.entries(t).reduce((t,[r,s])=>{try{t[r]=JSON.parse(s)}catch(t){throw new E(`Failed to parse prompt ${r} in categories ${e}: ${t}`)}return t},t)}};ue=m([I(),h("design:paramtypes",[String])],ue);class me extends V{constructor(e){super(e)}setCb(e){return this.cb=e,this}setArgsSchema(e){return this.argsSchema=e,this}static get builder(){return new me}static patchPrompt(e,t,r,s){const n=(t=Array.isArray(t)?t:Object.keys(t)).filter(e=>!Object.prototype.hasOwnProperty.call(r,e));if(n.length)throw new O("Missing replacements for placeholders: "+n.join(", "));s&&(s.verbose("Patching prompt with placeholders: "+JSON.stringify(t)),s.debug("Values: "+JSON.stringify(r)));const i=t.reduce((e,t)=>(e[t]=r[t],e),{});return d(e,i)}patchPrompt(e,t,r,s){return me.patchPrompt(e,t,r,s||this.log.for(this.patchPrompt))}build(e,t){const r=this.log.for(this.build),s=this.hasErrors();if(s)throw new O(s.toString());try{this.argsSchema&&ee(this.argsSchema,"argsSchema");const r=te(this.argsSchema);return e.registerPrompt(this.name,{title:this.title,description:this.description,argsSchema:r},async(e,r)=>{const s=this.logFor(r);e=Object.assign({},t,e||{}),s.verbose(`Executing prompt ${this.name} with args: ${JSON.stringify(e)}`),e._meta=Object.assign(e._meta||{},{usage:{reasoning:this.reasoning,effort:this.effort,cost:this.cost}});const n=await Promise.resolve(this.cb(e,r));return s.verbose(`Prompt ${this.name} executed successfully.`),s.debug("Prompt execution meta: "+JSON.stringify(n._meta)),n})}catch(e){throw r.error("Failed to register prompt "+(this.name||this.constructor.name),e),e}}}m([j(ue),h("design:type",ue)],me.prototype,"assets",void 0),m([y(),h("design:type",Object)],me.prototype,"cb",void 0),m([y(),h("design:type",v)],me.prototype,"argsSchema",void 0),m([k(),h("design:type",Object)],me.prototype,"placeholders",void 0);class he extends me{setCategory(e){return this.promptCategory=e,this}addPrefix(e){return this.prefixes=this.prefixes||[],this.prefixes.push(e),this}addSuffix(e){return this.suffixes=this.suffixes||[],this.suffixes.push(e),this}constructor(e){super(e)}build(e){const t=this.assets.getPrompt(this.name,this.promptCategory);f.fromObject(this,t);const r=new Set((S.properties(he)||[]).filter(e=>!["assets","promptCategory","prefixes","suffixes"].includes(e)));["cb","argsSchema"].forEach(e=>r.add(e));const s=this.hasErrors(...Array.from(r));if(s)throw new O(s.toString());const n=(this.prefixes||[]).map(e=>this.assets.getPrompt(e,this.promptCategory)),i=(this.suffixes||[]).map(e=>this.assets.getPrompt(e,this.promptCategory)),o=[...new Set([...t.placeholders,...n.map(e=>e.placeholders||[]),...i.map(e=>e.placeholders||[])].flat())].reduce((e,t)=>(e[t]=w.string().describe("The description for "+t),e),{});return this.setArgsSchema(w.object(o)),this.setCb((e,t)=>{const r=this.logFor(t).for(he).for(this.promptCategory).for(this.name);function s(e=[]){return Array.isArray(e)?e:Object.keys(e)}const n=(this.prefixes||[]).map(e=>this.assets.getPrompt(e,this.promptCategory)),i=(this.suffixes||[]).map(e=>this.assets.getPrompt(e,this.promptCategory)),o=this.assets.getPrompt(this.name,this.promptCategory),a=[...new Set([...n.map(e=>s(e.placeholders)).flat(),...i.map(e=>s(e.placeholders)).flat(),...s(o.placeholders).flat()])];return{messages:[{role:"user",content:{type:"text",text:this.patchPrompt([...n.map(e=>e.prompt),o.prompt,...i.map(e=>e.prompt)].join("\n\n"),a,e,r)}}],_meta:{}}}),super.build(e)}setReasoning(e){throw new T("Named prompt builders don't require callback")}setEffort(e){throw new T("Named prompt builders don't require callback")}setCost(e){throw new T("Named prompt builders don't require callback")}setDescription(e){throw new T("Named prompt builders don't require callback")}setTitle(e){throw new T("Named prompt builders don't require callback")}static get builder(){return new he}}m([y(),h("design:type",String)],he.prototype,"promptCategory",void 0),m([g(String),b(1),h("design:type",Array)],he.prototype,"prefixes",void 0),m([b(1),g(String),h("design:type",Array)],he.prototype,"suffixes",void 0);const ye=me.builder.setName("example-prompt").setTitle("Example prompt").setDescription("Example prompt for testing").setArgsSchema(w.object({message:w.string().optional()})).setCb(async e=>{const t=e.message??"default";return{messages:[{role:"assistant",content:{type:"text",text:t}}],content:[],structuredContent:{message:t},result:{message:t}}}),fe=me.builder.setName("interactive-jsdoc").setTitle("Interactive JSDoc prompt").setDescription("Interactive prompt for jogging JSDoc helpers").setArgsSchema(w.object({gist:w.string().optional()})).setCb(async e=>{const t=e.gist??"interactive jsdoc response";return{messages:[{role:"assistant",content:{type:"text",text:t}}],content:[],structuredContent:{message:t},result:{message:t}}}),ge=Object.assign(fe,{name:fe.getName()});var be;function we(e,t=[],r=[]){const s=he.builder.setCategory(be.DOCS).setName(e);return["prefix",...t].forEach(e=>s.addPrefix(e)),["suffix",...r].forEach(e=>s.addSuffix(e)),s}(e=>{e.DOCS="documentation",e.CODE="code"})(be||(be={}));const ve=[we("class"),we("constant"),we("decorator"),we("function"),we("module"),we("file"),we("repo",[],["iterate"])],Ie=w.object({className:w.string().describe("the class name to turn into a builder")}),je=[ye,ge,...ve,me.builder.setName("ts-code-dp-builder").setTitle("Typescript builder design patter prompt").setDescription("for a class, with a defined set of properties, scafold a builder design pattern").setArgsSchema(Ie).setReasoning(W.BASIC).setCb((e,t)=>(e.className=l(e.className),{messages:[{role:"user",content:{type:"text",text:`You're a senior TypeScript developer writing typescript code.You're a senior TypeScript developer writing typescript code.\nTransform the selected class into a builder design pattern implementation in Typescript.\nuse @decaf-ts validation decorators to enforce the validation of your builder.\n\n- must extend the Model Class from @decaf-ts/decorator-validation;\n- each property must be marked as protected;\n- each property must have a setter method that returns 'this' for chaining;\n- the build() method must validate the properties using hasErrors() method from Model class;\n- if validation fails, throw an error with the validation errors;\n- if validation passes, return an instance of the original class with the set properties;\n- optionally (but do so by default) add the static builder and from methods from the example;\n- if the clasee already follows the pattern but has properties without decoration or without setters, simple add them;\n\nexample:\n\noriginal class:\n\`\`\`typescript\nexport class ${e.className} {\n description!: string;\n name!: string = "default name";\n title!: string;\n age?: string;\n dateOfBirth!: Date;\n}}\n\`\`\` \n\nresulting builder pattern implementation:\n\`\`\`typescript\nexport class ${e.className}Builder extends Model {\n\n @minlength(10\n @required()\n protected description!: string;\n \n @required()\n protected name!: string = "default value;\n \n @required()\n protected title!: string;\n \n @min(18)\n protected age?: string;\n \n @date()\n protected dateOfBirth!: Date;\n\n protected constructor(arg?: ModelArg<${e.className}Builder>>) {\n super(arg);\n Model.fromModel(this, arg);\n }\n\n setDescription(value: string) {\n this.description = value;\n return this;\n }\n\n setName(value: string) {\n this.name = value;\n return this;\n }\n\n setTitle(value: string) {\n this.title = value;\n return this;\n }\n setAge(value: number) {\n this.age = value;\n return this;\n }\n setDate(value: Date) {\n this.age = value;\n return this;\n }\n \n build(...args: any[]): ${e.className}Builder | Promise<${e.className}Builder> {\n const errs = this.hasErrors();\n if (errs) throw new Error(errs.toString());\n \n return // code that builds OBJ here\n }\n \n static get builder(): ${e.className}Builder {\n return new ${e.className}Builder(); // static method to get a new builder instance\n }\n \n static from<K extends keyof ${e.className}Builder>(obj: K, ${e.className}Builder[K]): ${e.className}Builder {\n return new ${e.className}Builder(); // static method to create a builder from an object\n }\n}\n\`\`\` \n\n`}}],_meta:{}}))];class ke extends V{setAnnotations(e){return this.annotations=Object.assign(this.annotations,e),this}setCb(e){return this.cb=e,this}setInputSchema(e){return this.inputSchema=e,this}setOutputSchema(e){return this.outputSchema=e,this}constructor(e){super(e),this.annotations={readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}}static get builder(){return new ke}build(e){const t=this.hasErrors();if(t)throw Error(t.toString());try{this.inputSchema&&ee(this.inputSchema,"inputSchema"),this.outputSchema&&ee(this.outputSchema,"outputSchema");const t=te(this.inputSchema),r=te(this.outputSchema);return e.registerTool(this.name,{title:this.title,description:this.description,inputSchema:t,outputSchema:r,annotations:this.annotations,_meta:{usage:{reasoning:this.reasoning,effort:this.effort,cost:this.cost}}},async(e,t)=>{const r=this.logFor(t);r.verbose(`Executing tool ${this.name} with args: ${JSON.stringify(e)}`),t._meta=Object.assign(t._meta||{},{usage:{reasoning:this.reasoning,effort:this.effort,cost:this.cost}});const s=await Promise.resolve(this.cb(e,t));return r.verbose(`Tool ${this.name} executed successfully.`),r.debug("Tool execution meta: "+JSON.stringify(s._meta)),s})}catch(e){const t=e?.message||e+"";if("string"==typeof t&&t.includes("already registered"))return o.for(this).warn(`Tool ${this.name} already registered - skipping duplicate registration`),{name:this.name};throw o.for(this).error("Error building tool",e),e}}}m([y(),h("design:type",Object)],ke.prototype,"annotations",void 0),m([y(),h("design:type",Object)],ke.prototype,"cb",void 0),m([y(),h("design:type",Function)],ke.prototype,"inputSchema",void 0);const Se=ke.builder.setName("example-tool").setTitle("Example tool").setDescription("A smoke tool used for quick testing").setInputSchema(w.object({})).setCb(async()=>({content:[{type:"text",text:"example tool ok"}],result:{status:"ok"}}));Object.assign(Se,{name:Se.getName()});const xe=ke.builder.setName("file-summarizer").setTitle("File summarizer").setDescription("Summaries files for quick previews").setInputSchema(w.object({filePath:w.string().optional()})).setCb(async()=>({content:[{type:"text",text:"file summary stub"}],result:{summary:"file summary stub"}}));function Ae(){try{let e=process.argv[1]?A.dirname(A.resolve(process.argv[1])):process.cwd();for(;;){const t=A.join(e,"package.json");if(r.existsSync(t))return JSON.parse(r.readFileSync(t,"utf-8"));const s=A.dirname(e);if(s===e)break;e=s}}catch{}return{}}Object.assign(xe,{name:xe.getName()});const Te=Ae().version??"0.0.0",Ee=Ae().name??"unknown";S.registerLibrary(Ee,Te);const Oe={mcpId:"decaf",name:"decaf-ts mcp server",title:"Decaf-TS MCP Server",description:"Provides precise coding assistance for the decaf-ts framework",version:Te,websiteUrl:"https://decaf-ts.github.io",repositoryUrl:"https://github.com/decaf-ts/mcp-server",license:"AGPL-3.0",workingDir:ce,assetDir:pe(),contacts:[{name:"Decaf-TS",url:"https://decaf-ts.github.io"}],tags:"server,official,decaf-ts",metadata:{},icons:[{src:"workdocs/assets/favicon.svg",mimeType:"image/svg+xml",sizes:"any"}],jira:{host:process.env.JIRA__HOST||"decaf-ts.atlassian.net",email:process.env.JIRA__EMAIL||"",apiKey:process.env.JIRA__API_KEY||process.env.JIRA__APIKEY||"",projectKey:process.env.JIRA__PROJECT_KEY||void 0,issueType:process.env.JIRA__ISSUE_TYPE||void 0,parentIssue:process.env.JIRA__PARENT_ISSUE||void 0,timeout:process.env.JIRA__TIMEOUT?parseInt(process.env.JIRA__TIMEOUT):1e3,rateLimitRetryDelayMs:process.env.JIRA__RATE_LIMIT_RETRY_DELAY_MS?parseInt(process.env.JIRA__RATE_LIMIT_RETRY_DELAY_MS):3e3},xray:{host:process.env.XRAY__HOST||process.env.XRAY__API_HOST||"https://xray.cloud.getxray.app",apiUser:process.env.XRAY__API_USER||"",apiSecret:process.env.XRAY__API_SECRET||""},level:p.error},Je=u.accumulate(Oe);function Ce(){const{host:e,email:t,apiKey:r,projectKey:s,issueType:n}=Je.jira;return{host:e?.trim(),email:t?.trim(),apiKey:r?.trim(),projectKey:s?.trim(),issueType:n?.trim(),parentIssue:Je.jira.parentIssue?.trim()}}function De(){const e=Ce();return[{name:"JIRA__HOST",required:!0,description:"Atlassian host (e.g. decaf-ts.atlassian.net) where your Jira instance is hosted.",value:e.host},{name:"JIRA__EMAIL",required:!0,description:"Email address of the Jira account that has API access.",value:e.email},{name:"JIRA__API_KEY",required:!0,description:"API token created in your Atlassian profile (a.k.a. APIKEY alias) for authenticating requests.",sensitive:!0,value:e.apiKey},{name:"JIRA__PROJECT_KEY",required:!1,description:"Default Jira project key (e.g. DECAF) used when an issue creation request omits a project.",value:e.projectKey},{name:"JIRA__ISSUE_TYPE",required:!1,description:"Default Jira issue type (e.g. Task, Bug) used when creating issues without an explicit type.",value:e.issueType},{name:"JIRA__PARENT_ISSUE",required:!1,description:"Default parent issue key (e.g. DECAF-123) applied when a child issue is created without an explicit parent.",value:e.parentIssue}]}function He(e){const t=e.value?((e,t)=>{if(e)return t?"<configured>":e})(e.value,e.sensitive):"not set",r=e.required?"(required)":"(optional)";return`\u2022 ${e.name} ${r}: ${e.description} Current state: ${t}.`}o.setConfig(Je);class Ne extends Error{constructor(e){const t=De(),r=(e=>{const t=De();return`${e.length?`Missing Jira credentials: ${e.map(e=>e.name).join(", ")}.`:"Jira credentials are configured."}\n\nThis setup uses the following environment variables:\n${t.map(He).join("\n")}`})(e);super(r),this.name="MissingJiraEnvironmentError",this.descriptors=t,this.missing=e,"function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,Ne)}}const _e=o.for("jira.client"),Re=/(authorization|cookie)/i;function $e(e){if(!e)return;const t=e.baseURL??"",r=e.url??"";return t&&r?`${t.endsWith("/")?t.slice(0,-1):t}/${r.startsWith("/")?r.slice(1):r}`:r||t||void 0}function Pe(e){if(void 0!==e){if("string"==typeof e)return e;try{return JSON.stringify(e,null,2)}catch(t){return H(e,{depth:null})}}}function Me(e){if(!e)return;const t={};return Object.entries(e).forEach(([e,r])=>{t[e]=Re.test(e)&&r?"[REDACTED]":r}),t}function Le(e){let t;try{const e=require("jira.js");t=e?.Version3Client||e.default?.Version3Client||e.default||e}catch(e){throw Error("Unable to require 'jira.js' \u2014 ensure it is installed as a dependency: "+e)}const{host:r,email:s,apiKey:n}=(()=>{const e=Ce(),t=De().filter(e=>e.required&&!e.value);if(t.length>0)throw new Ne(t);return{host:e.host,email:e.email,apiKey:e.apiKey}})(),i=new t({host:r.startsWith("http://")||r.startsWith("https://")?r:"https://"+r,authentication:{basic:{email:s,apiToken:n}},baseRequestConfig:{headers:{Accept:"application/json","Content-Type":"application/json"}}});return(e=>{if(!e)return;const t="__jiraLoggingAttached";e[t]||(e[t]=!0,e.interceptors.request.use(e=>{e.headers=(e=>{const t={...e||{}};return Object.keys(t).some(e=>"accept"===e.toLowerCase())||(t.Accept="application/json"),Object.keys(t).some(e=>"content-type"===e.toLowerCase())||(t["Content-Type"]="application/json"),t})(e.headers);const t=(e.method??"GET").toString().toUpperCase(),r=$e(e);return _e.info("jira.request",{method:t,url:r,headers:Me(e.headers),params:e.params,data:Pe(e.data)}),e},e=>(_e.error("jira.request.error",{message:e.message}),Promise.reject(e))),e.interceptors.response.use(e=>{const t=(e.config?.method??"GET").toString().toUpperCase(),r=$e(e.config);return _e.info("jira.response",{method:t,url:r,status:e.status,headers:Me(e.headers),data:Pe(e.data)}),e},e=>{const t=e.config,r=e.response,s=(t?.method??"GET").toString().toUpperCase(),n=$e(t);return _e.error("jira.response.error",{method:s,url:n,status:r?.status,headers:Me(r?.headers),data:Pe(r?.data),message:e.message}),Promise.reject(e)}))})(i.instance),i}const qe=w.object({name:w.string().min(1).optional().describe("Optional template name that pre-populates additional fields"),content:w.string().min(1).describe("Markdown template content to apply when constructing the description"),placeholders:w.record(w.string()).optional().describe("Map of placeholder replacements used by the template")}).describe("Template metadata used to adjust the created description"),Fe=w.object({template:qe.optional().describe("Optional template settings for this create request")}).describe("Additional template controls available when creating an issue"),Ue=w.union([w.object({fields:w.record(w.any()).describe("Full raw field map that gets delivered to Jira")}).merge(Fe).describe("Create argument that supplies every field explicitly"),w.object({summary:w.string().min(1).describe("Title or summary of the new issue"),projectKey:w.string().min(1).describe("Project key where the issue is created"),issueType:w.string().min(1).describe("Type name for the new issue (story, task, etc.)"),description:w.string().optional().describe("Optional textual description for the issue")}).merge(Fe).describe("Create argument with minimal required identifiers plus optional description")]).describe("Union describing how to create an issue either via raw fields or shorthand properties");function ze(e,t,r){const s=((e.url??"")+"").match(/^(attachment|jira-attachment):(.+)$/i);if(!s)return null;const n=s[2],i=r.resolveAttachment?.(n);return i?{type:"block",node:{type:"mediaSingle",attrs:{layout:"center"},content:[{type:"media",attrs:{type:"file",id:i.id,collection:i.collection??"attachments"}}]}}:null}function Be(e,t){if(!e)return[];if(!t.enableAtMentions&&!t.enableEmojiShortcodes)return[{type:"text",text:e}];let r=0;const s=[],n=/(^|[^A-Za-z0-9_])@([A-Za-z0-9._-]{1,64})/g,i=/:([a-z0-9_+-]{1,64}):/gi;for(;r<e.length;){const o=Ke(t.enableAtMentions?We(n,e,r):null,t.enableEmojiShortcodes?We(i,e,r):null);if(!o){s.push({type:"text",text:e.slice(r)});break}if(o.index>r&&s.push({type:"text",text:e.slice(r,o.index)}),"mention"===o.kind){const{full:e,groups:n}=o,i=n[0]??"",a=n[1]??"";i&&s.push({type:"text",text:i});const c=t.resolveMention?.(a);c?s.push({type:"mention",attrs:{id:c.id,text:c.text}}):s.push({type:"text",text:"@"+a}),r=o.index+e.length;continue}if("emoji"===o.kind){const{full:e,groups:n}=o,i=`:${n[0]}:`,a=t.resolveEmoji?.(i);s.push({type:"emoji",attrs:a?{shortName:a.shortName,text:a.text}:{shortName:i}}),r=o.index+e.length;continue}}return(e=>{const t=[];for(const r of e){const e=t[t.length-1];"text"!==r.type||"text"!==e?.type||e.marks||r.marks?t.push(r):e.text=(e.text??"")+(r.text??"")}return t})(s)}function We(e,t,r){e.lastIndex=r;const s=e.exec(t);if(!s)return null;const n=e.source.includes("@")?"mention":"emoji";return{index:s.index,full:s[0],groups:s.slice(1),kind:n}}function Ke(e,t){return e?t&&e.index>t.index?t:e:t}function Xe(e){const t=(e.children??[])[0];return"text"===t?.type?(t.value??"")+"":"paragraph"===t?.type?((t.children??[]).map(e=>"text"===e.type?(e.value??"")+"":"").join("")||"")+"":""}function Ye(e){const t=((e??"")+"").toLowerCase().trim();return t?"info"===t||"note"===t||"success"===t||"warning"===t||"error"===t?t:"danger"===t?"error":null:null}function Ge(e){const t=((e??"")+"").toLowerCase().trim();return!t||"neutral"!==t&&"green"!==t&&"yellow"!==t&&"red"!==t&&"blue"!==t&&"purple"!==t?null:t}function Ze(e,t){const r=[];for(const s of e??[])if(s?.type)if("text"!==s.type)if("strong"!==s.type)if("emphasis"!==s.type)if("delete"!==s.type)if("inlineCode"!==s.type)if("break"!==s.type){if("link"===s.type){const e=(s.url??"")+"",n=Qe(s.children??[],e),i=ze(s,0,t);if(i){"inline"===i.type?r.push(i.node):r.push({type:"text",text:n,marks:[{type:"link",attrs:{href:e}}]});continue}if(t.enableSmartCards&&et(n,e)){r.push({type:"inlineCard",attrs:{url:e}});continue}r.push({type:"text",text:n,marks:[{type:"link",attrs:{href:e}}]});continue}if("textDirective"===s.type&&"status"===s.name){const e=Xe(s)||"Status",t=Ge(s.attributes?.color)??"neutral";r.push({type:"status",attrs:{text:e,color:t}});continue}if("textDirective"===s.type&&"emoji"===s.name){const e=tt(s);r.push(rt(e,t));continue}}else r.push({type:"hardBreak"});else r.push({type:"text",text:(s.value??"")+"",marks:[{type:"code"}]});else r.push(...Ve(Ze(s.children??[],t),{type:"strike"}));else r.push(...Ve(Ze(s.children??[],t),{type:"em"}));else r.push(...Ve(Ze(s.children??[],t),{type:"strong"}));else r.push(...Be((s.value??"")+"",t));return r.filter(e=>!("text"===e.type&&""===(e.text??"")))}function Ve(e,t){return e.map(e=>{if("text"!==e.type)return e;if(e.marks?.some(e=>"code"===e.type))return e;const r=e.marks?[...e.marks,t]:[t];return{...e,marks:r}})}function Qe(e,t){const r=[];for(const t of e??[])"text"===t.type||"inlineCode"===t.type?r.push((t.value??"")+""):"emphasis"!==t.type&&"strong"!==t.type&&"delete"!==t.type||r.push(Qe(t.children??[],""));return r.join("")||t}function et(e,t){const r=(e??"").trim(),s=(t??"").trim();return r===s&&/^https?:\/\//i.test(s)}function tt(e){return(e.children??[]).map(e=>"text"===e.type?(e.value??"")+"":"").join("").trim()||""}function rt(e,t){const r=e.startsWith(":")?e:`:${e}:`,s=t.resolveEmoji?.(r);return s?{type:"emoji",attrs:{shortName:s.shortName,text:s.text}}:{type:"emoji",attrs:{shortName:r}}}function st(e){return e?"string"==typeof e?e:"text"===e.type||"inlineCode"===e.type?(e.value??"")+"":Array.isArray(e.children)?e.children.map(st).join(""):"":""}function nt(e,t){if(!e?.type)return null;if((e=>"containerDirective"===e?.type&&"panel"===e?.name)(e))return((e,t)=>{const r=e.attributes??{},s=Ye(r.type)??"info",n="string"==typeof r.title?r.title:void 0,i=(e.children??[]).map(e=>nt(e,t)).flat().filter(Boolean);return{type:"panel",attrs:{panelType:s,...n?{panelType:s,title:n}:{panelType:s}},content:i.length?i:[{type:"paragraph",content:[]}]}})(e,t);switch(e.type){case"heading":return{type:"heading",attrs:{level:ot(e.depth??1,1,6)},content:Ze(e.children??[],t)};case"paragraph":return(e=>{const t=e.children??[];if(1!==t.length)return null;const r=t[0];if("image"!==r?.type)return null;const s=(r.url??"")+"";return s?{type:"mediaSingle",attrs:{layout:"center"},content:[{type:"media",attrs:{type:"external",url:s}}]}:null})(e)||{type:"paragraph",content:Ze(e.children??[],t)};case"blockquote":return{type:"blockquote",content:(e.children??[]).map(e=>nt(e,t)).flat().filter(Boolean)};case"list":return((e,t)=>t.enableTaskLists&&(e.children??[]).some(e=>"boolean"==typeof e.checked)?((e,t)=>{const r=[];let s=0;for(const n of e.children??[]){if("boolean"!=typeof n.checked)continue;s+=1;const e=(n.children??[]).map(e=>nt(e,t)).flat().filter(Boolean);r.push({type:"taskItem",attrs:{localId:"task-"+s,state:n.checked?"DONE":"TODO"},content:e.length?e:[{type:"paragraph",content:[]}]})}return{type:"taskList",content:r}})(e,t):{type:e.ordered?"orderedList":"bulletList",content:(e.children??[]).map(e=>((e,t)=>{const r=(e.children??[]).map(e=>nt(e,t)).flat().filter(Boolean);return{type:"listItem",content:r.length?r:[{type:"paragraph",content:[]}]}})(e,t))})(e,t);case"code":{const r=((e,t)=>{const r=(e??"").toString().trim().toLowerCase();return r?t.enableMermaid&&r.includes("mermaid")?"mermaid":(e=>{const t=e.trim().toLowerCase();return{js:"javascript",javascript:"javascript",jsx:"javascript",ts:"typescript",typescript:"typescript",tsx:"typescript",py:"python",python:"python",rb:"ruby",ruby:"ruby",sh:"bash",bash:"bash",zsh:"bash",shell:"bash",yml:"yaml",yaml:"yaml",json:"json",toml:"toml",xml:"xml",html:"html",css:"css",scss:"scss",sql:"sql",go:"go",rust:"rust",java:"java",c:"c",cpp:"cpp","c++":"cpp",cs:"csharp",csharp:"csharp",php:"php",kotlin:"kotlin",swift:"swift",md:"markdown",markdown:"markdown",graphql:"graphql",gql:"graphql",dockerfile:"docker",makefile:"make",ini:"ini"}[t]??t})(r):null})(e.lang,t);return{type:"codeBlock",attrs:{language:r},content:[{type:"text",text:(e.value??"")+""}]}}case"thematicBreak":return{type:"rule"};case"table":return((e,t)=>({type:"table",content:(e.children??[]).map((e,r)=>({type:"tableRow",content:(e.children??[]).map(e=>({type:0===r?"tableHeader":"tableCell",content:[{type:"paragraph",content:Ze(e.children??[],t)}]}))}))}))(e,t);case"leafDirective":return"status"===e.name?(e=>{const t=Ge((e.attributes??{}).color)??"neutral";return{type:"paragraph",content:[{type:"status",attrs:{text:Xe(e)||"Status",color:t}}]}})(e):"panel"===e.name?((e,t)=>{const r=e.attributes??{},s=Ye(r.type)??"info",n="string"==typeof r.title?r.title:void 0;return{type:"panel",attrs:{panelType:s,...n?{title:n}:{}},content:[{type:"paragraph",content:Ze([{type:"text",value:Xe(e)}],t)}]}})(e,t):it(e,t);default:return it(e,t)}}function it(e,t){if("drop"===t.unknownNodeStrategy)return null;const r=st(e);return r?{type:"paragraph",content:[{type:"text",text:r}]}:null}function ot(e,t,r){const s=Number.isFinite(e)?Math.trunc(e):t;return Math.max(t,Math.min(r,s))}const at={resolveMention:void 0,resolveAttachment:void 0,resolveEmoji:void 0,enableSmartCards:!0,enableMermaid:!0,enableEmojiShortcodes:!0,enableAtMentions:!0,enableTaskLists:!0,unknownNodeStrategy:"text"};function ct(e,t={}){const r={...at,...t},s=e??"",n=N().use($).use(_).use(R),i=n.parse(s),o=n.runSync(i);return dt(o),((e,t)=>{const r=[];for(const s of e.children??[]){const e=nt(s,t);e&&(Array.isArray(e)?r.push(...e):r.push(e))}return((e,t)=>{if(!t.enableSmartCards)return e;const r=e.content.map(e=>(e=>{if("paragraph"!==e.type)return e;const t=e.content??[];if(1!==t.length)return e;const r=t[0];if("inlineCard"!==r?.type)return e;const s=r.attrs?.url;return s?[{type:"blockCard",attrs:{url:s}}]:e})(e)).flat();return{...e,content:r}})({version:1,type:"doc",content:r},t)})(o,r)}function dt(e){if(!e||!Array.isArray(e.children))return;const t=[];for(const r of e.children)"definition"!==r?.type&&("html"!==r?.type?(dt(r),t.push(r)):t.push({type:"text",value:(r.value??"")+""}));e.children=t}function lt(e){return{...e,content:pt(e.content??[])}}function pt(e){return e.flatMap(e=>"panel"===e.type?pt(e.content??[]):[ut(e)])}function ut(e){return e.content?{...e,content:pt(e.content)}:{...e}}const mt=/\{\{\s*([^\}]+)\s*\}\}/g;function ht(e){if(!e||0>=Object.keys(e).length)return[];const t=(e=>{if(null==e)return"";try{return JSON.stringify(e,null,2)}catch{return H(e,{depth:null})}})(e);return t?[{type:"text",text:t}]:[]}function yt(e={},t=[]){const r=(e=>e&&"object"==typeof e?Array.isArray(e)?{items:e}:e:"string"==typeof e?{message:e}:null==e?{}:{value:e})(e);return{content:t.length?t:ht(r),result:r,structuredContent:r}}const ft={name:"jira-issue-create",inputSchema:Ue,runTool:async(e,t)=>yt(await(async(e,t)=>{let r;const s=e=>e&&e.trim()?e.trim():void 0,n=s(Je.jira.projectKey),i=s(Je.jira.issueType),o=t&&"object"==typeof t&&!Array.isArray(t)?t:{},a=Object.prototype.hasOwnProperty.call(o,"fields")?o:{...o,projectKey:o.projectKey??n,issueType:o.issueType??i};try{r=Ue.parse(a)}catch(e){const t=Error("validation error");throw t.code="validation_error",t}let c;c=r&&"object"==typeof r&&"fields"in r&&r.fields?{...r.fields}:{summary:r.summary,project:{key:r.projectKey},issuetype:{name:r.issueType},...r.description?{description:r.description}:{}},c=((e,t)=>{if(!t||!t.content)return e;const r=(s=t.content,n=t.placeholders,s?s.replace(mt,(e,t)=>{const r=t.trim();if(!r)return"";if(n&&Object.prototype.hasOwnProperty.call(n,r)){const e=n[r];return null==e?"":e+""}return e}):"");var s,n;if(!r.trim())return e;const i=ct(r),o=(a=e.description)?"object"==typeof a&&"doc"===a.type&&Array.isArray(a.content)?a.content:"string"==typeof a?ct(a).content:[]:[];var a;return e.description={type:"doc",version:1,content:[...o,...i.content]},e})(c,r.template);const d=e?.issues?.create??e?.issues?.createIssue;if("function"!=typeof d)throw Error("Jira client missing create function");const l=await d.call(e.issues,{fields:c}),p=l&&l.data||l;return{id:p?.id??null,key:p?.key??null}})(e,t))};class gt extends Error{constructor({code:e,message:t,details:r}){super(t),Object.setPrototypeOf(this,new.target.prototype),this.name="NormalizedJiraError",this.code=e,this.details=r}}const bt=o.for("jira.errors");function wt(e){if(!e)return new gt({code:"jira_error",message:"Unknown Jira error",details:{raw:e}});const t=e?.status??e?.statusCode??e?.response?.status??e?.response?.statusCode,r="number"==typeof t?t:Number(t)||void 0,s=e?.response?.data??e?.data??e?.response?.body??e?.body,n=e?.response?.statusText??(r?""+r:void 0),i=e?.response?.headers?Me(e.response.headers):void 0,o=[];"string"==typeof e?.message&&o.push(e.message),((e,t)=>{e&&(Array.isArray(e.errorMessages)&&e.errorMessages.forEach(e=>"string"==typeof e&&t.push(e)),"string"==typeof e.errorMessage&&t.push(e.errorMessage),e.errorCollection&&Array.isArray(e.errorCollection.errors)&&e.errorCollection.errors.forEach(e=>{"string"==typeof e?t.push(e):e&&"string"==typeof e.message&&t.push(e.message)}),e?.errors&&"object"==typeof e.errors&&Object.values(e.errors).forEach(e=>{"string"==typeof e?t.push(e):"string"==typeof e?.message&&t.push(e.message)}))})(s,o);const a=r?`Jira API error (${r})`:"Jira API error",c=o.length>0?o.join(" | "):a,d=r?"jira_"+r:e?.code??"jira_error",l=e?.config,p=l?{method:l.method?l.method.toString().toUpperCase():void 0,url:l.url,headers:Me(l.headers),data:Pe(l.data)}:void 0,u={httpStatus:r,body:s,request:p,response:i?{statusText:n,headers:i}:n?{statusText:n}:void 0,raw:e};return bt.error("jira.error",{code:d,message:c,httpStatus:r,statusText:n,responseHeaders:i,request:p,body:Pe(s)??s}),new gt({code:d,message:c,details:u})}const vt=w.object({issueId:w.string().min(1).describe("Issue key or ID to delete"),deleteSubtasks:w.boolean().optional().default(!0).describe("Whether to delete the subtasks alongside this issue")}).describe("Arguments used to delete a Jira issue (with optional subtasks)"),It={name:"jira-issue-delete",inputSchema:vt,runTool:async(e,t)=>{try{const r=vt.parse(t),s=e.issues??e.issue??e,n=s?.delete??s?.deleteIssue;if("function"!=typeof n)throw Error("jira client delete endpoint is not available");return await n.call(s,{issueIdOrKey:r.issueId,deleteSubtasks:r.deleteSubtasks}),yt({success:!0,message:`Issue ${r.issueId} deleted successfully`})}catch(e){throw wt(e)}}},jt=w.object({projectKey:w.string().trim().min(1).optional().describe("Project key used to scope the issue search"),issueType:w.string().trim().min(1).optional().describe("Issue type name used to filter the results"),parentIssueId:w.string().trim().min(1).optional().describe("Optional parent issue key/ID to limit results to a subtree"),name:w.string().trim().min(1).optional().describe("Issue summary to match exactly"),reference:w.string().trim().min(1).optional().describe("External reference or custom identifier to filter by"),jql:w.string().trim().min(1).optional().describe("Free-form JQL query to drive the search"),startAt:w.number().int().min(0).optional().describe("Index for paging through the search results"),maxResults:w.number().int().min(1).optional().describe("Maximum number of issues to return"),fields:w.array(w.string()).optional().describe("List of issue fields to include in the response"),expand:w.string().optional().describe("Optional expansion clause for the results"),orderBy:w.string().trim().min(1).optional().describe("Field or clause used to order the returned issues")}).describe("Parameters describing how to search for Jira issues");function kt(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}const St={name:"jira-issue-list",inputSchema:jt,runTool:async(e,t)=>{try{const r=jt.parse(t),s=r.startAt??0,n=r.maxResults??50;let i=r.jql?.trim();if(i){if(r.orderBy){const e=r.orderBy.trim();e&&(i=/\border\s+by\b/i.test(i)?`${i}, ${e}`:`${i} ORDER BY ${e}`)}}else i=(e=>{const t=[];if(e.projectKey&&t.push(`project = "${kt(e.projectKey)}"`),e.issueType&&t.push(`issuetype = "${kt(e.issueType)}"`),e.parentIssueId&&t.push(`parent = "${kt(e.parentIssueId)}"`),e.name&&t.push(`summary ~ "${kt(e.name)}"`),e.reference){const r=kt(e.reference);t.push(`(key ~ "${r}" OR summary ~ "${r}" OR text ~ "${r}")`)}if(0===t.length){const e=Error("Provide a jql query or at least one filter (project, name, reference, parent, issue type, etc.).");throw e.code="validation_error",e}let r=t.join(" AND ");if(e.orderBy){const t=e.orderBy.trim();t&&(r=/\border\s+by\b/i.test(r)?`${r}, ${t}`:`${r} ORDER BY ${t}`)}return r})(r);const o={jql:i,startAt:s,maxResults:n};r.fields&&(o.fields=r.fields),r.expand&&(o.expand=r.expand);const a=e.issueSearch,c=a&&"function"==typeof a.searchForIssuesUsingJqlEnhancedSearch?a.searchForIssuesUsingJqlEnhancedSearch:a&&"function"==typeof a.searchForIssuesUsingJql?a.searchForIssuesUsingJql:void 0;if(!c)throw Error("Jira search API is unavailable on the client");const d=await c.call(a,o),l=d?.data??d,p="object"==typeof l&&null!==l?{...l}:{};return void 0===p.startAt&&(p.startAt=s),void 0===p.maxResults&&(p.maxResults=n),yt(p)}catch(e){throw wt(e)}}},xt=w.object({issueId:w.string().min(1).describe("Jira issue key or numeric ID to read"),expand:w.string().optional().describe("Optional expand clause for nested fields or changelog"),fields:w.array(w.string()).optional().describe("Explicit list of issue fields to return"),properties:w.array(w.string()).optional().describe("Specific issue properties to include in the response")}).describe("Arguments required to read a Jira issue"),At={name:"jira-issue-read",inputSchema:xt,runTool:async(e,t)=>{try{const r=xt.parse(t),s={issueIdOrKey:r.issueId};r.expand&&(s.expand=r.expand),r.fields&&(s.fields=r.fields),r.properties&&(s.properties=r.properties);const n=await e.issues.getIssue(s);return yt(n?.data??n)}catch(e){throw wt(e)}}},Tt=w.object({issueId:w.string().min(1).describe("Target issue key or ID to transition"),transitionId:w.union([w.string(),w.number()]).describe("Identifier for the transition to execute"),fields:w.record(w.any()).optional().describe("Optional field updates to apply during the transition"),update:w.record(w.array(w.object({set:w.any().optional().describe("Set operation for the transition update"),add:w.any().optional().describe("Add operation for the transition update"),remove:w.any().optional().describe("Remove operation for the transition update")}))).optional().describe("Structured update operations to send alongside the transition"),comment:w.string().optional().describe("Optional comment to attach during the transition")}).describe("Inputs needed to transition a Jira issue"),Et={name:"jira-issue-transition",inputSchema:Tt,runTool:async(e,t)=>{try{const r=Tt.parse(t),s={id:r.transitionId};r.fields&&(s.fields=r.fields),r.update&&(s.update=r.update),r.comment&&(s.comment={body:ct(r.comment)});const n=await e.issues.transition({issueIdOrKey:r.issueId,transition:s});return yt(n?.data??n)}catch(e){throw wt(e)}}},Ot=w.object({issueId:w.string().min(1).describe("Issue key or ID for which to list transitions"),expand:w.string().optional().describe("Optional expand parameter for the transition response")}).describe("Inputs used to fetch available transitions for an issue"),Jt={name:"jira-transition-list",inputSchema:Ot,runTool:async(e,t)=>{try{const r=Ot.parse(t),s=e.issues;if(!s||"function"!=typeof s.getTransitions)throw Error("Jira transitions API is unavailable on the client");const n={issueIdOrKey:r.issueId};r.expand&&(n.expand=r.expand);const i=await s.getTransitions(n);return yt(i?.data??i)}catch(e){throw wt(e)}}},Ct=w.object({description:w.string().optional().describe("Markdown description that is converted to Jira ADF (use jira-md-to-adf if you need raw ADF input)")}).catchall(w.any()).describe("Field map that gets delivered to Jira (labels, components, etc.)"),Dt=w.object({issueId:w.string().min(1).describe("Issue key or ID to update"),fields:Ct.optional(),update:w.record(w.array(w.object({set:w.any().optional().describe("Set operation alongside the update key"),add:w.any().optional().describe("Add operation alongside the update key"),remove:w.any().optional().describe("Remove operation alongside the update key"),edit:w.any().optional().describe("Edit operation alongside the update key")}))).optional().describe("Structured update operations for array/set fields"),properties:w.array(w.any()).optional().describe("Property payloads to attach to the issue"),notifyUsers:w.boolean().optional().default(!0).describe("Whether to notify watchers when the issue is updated"),issueTemplateId:w.string().optional().describe("Optional template ID to render issue descriptions"),overrideScreenSecurity:w.boolean().optional().default(!1).describe("Temporarily bypass screen security restrictions"),overrideEditableFlag:w.boolean().optional().default(!1).describe("Temporarily bypass the editable flag on the screen")}).describe("Arguments used to update existing Jira issues"),Ht=w.record(w.any()).optional(),Nt=w.object({type:w.string().describe("Mark name, such as strong, emphasis, code, or link"),attrs:Ht}).describe("Inline formatting or link marks applied to text nodes"),_t=w.object({type:w.literal("text"),text:w.string().describe("Rendered string content for the text node"),marks:w.array(Nt).optional()}).describe("Plain text node that carries optional formatting marks"),Rt=w.object({type:w.literal("mention"),attrs:w.object({id:w.string().describe("Jira internal identifier for the mention"),text:w.string().describe("Human readable mention text"),userType:w.string().optional(),accessLevel:w.string().optional(),localizedAccessLevel:w.string().optional()}).describe("Metadata describing the mentioned user")}).describe("Represents a user or team mention in a block or inline context"),$t=w.object({type:w.literal("emoji"),attrs:w.object({shortName:w.string().describe("Emoji shortcode such as smiling_face"),id:w.string().optional(),text:w.string().optional()}).describe("Emoji metadata")}).describe("Emoji inline node"),Pt=w.object({type:w.literal("inlineCard"),attrs:w.object({url:w.string().url().describe("Target URL that backs the inline card")}).describe("Inline card attributes")}).describe("Inline card that represents a linked resource"),Mt=w.object({type:w.literal("status"),attrs:w.object({text:w.string().describe("Status label text"),color:w.string().describe("Color code applied by Jira"),localId:w.string().optional(),style:w.string().optional()}).describe("Status metadata published by Jira")}).describe("Status node used for Jira workflow or custom fields"),Lt=w.object({type:w.literal("date"),attrs:w.object({representation:w.string().optional(),timestamp:w.number().optional()}).describe("Date metadata, usually RFC3339 or timestamp")}).describe("Date node that embeds a Jira date reference"),qt=w.object({type:w.literal("hardBreak")}).describe("Inline hard break that forces a newline"),Ft=w.object({type:w.literal("rule")}).describe("Horizontal rule dividing sections of the document");let Ut,zt;const Bt=w.lazy(()=>w.union([_t,Rt,$t,Pt,Mt,Lt,qt])),Wt=w.lazy(()=>w.object({type:w.literal("paragraph"),content:w.array(Bt).describe("Inline nodes contained by the paragraph")})),Kt=w.lazy(()=>w.object({type:w.literal("heading"),attrs:w.object({level:w.number().int().min(1).max(6).describe("Heading level, 1-6")}).optional(),content:w.array(Bt).describe("Inline nodes composing the heading")})),Xt=w.lazy(()=>w.object({type:w.literal("listItem"),attrs:w.object({localId:w.string().optional()}).optional(),content:w.array(w.lazy(()=>Ut)).describe("Block level nodes nested inside the list item")})),Yt=w.lazy(()=>w.object({type:w.literal("bulletList"),content:w.array(Xt).describe("List items within the bullet list")})),Gt=w.lazy(()=>w.object({type:w.literal("orderedList"),attrs:w.object({order:w.number().int().min(1).optional()}).optional(),content:w.array(Xt)})),Zt=w.lazy(()=>w.object({type:w.literal("taskItem"),attrs:w.object({localId:w.string().optional(),state:w.enum(["TODO","IN_PROGRESS","DONE"]).optional()}).optional(),content:w.array(w.lazy(()=>Ut)).describe("Blocks living inside the task item")})),Vt=w.lazy(()=>w.object({type:w.literal("taskList"),content:w.array(Zt).describe("Task items inside the list")})),Qt=w.lazy(()=>w.object({type:w.literal("codeBlock"),attrs:w.object({language:w.string().optional()}).optional(),content:w.array(_t).optional()})),er=w.lazy(()=>w.object({type:w.literal("panel"),attrs:w.object({panelType:w.enum(["info","note","tip","warning","success"]).optional(),title:w.string().optional()}).optional(),content:w.array(w.lazy(()=>Ut)).describe("Panels may nest paragraphs, lists, or other blocks")})),tr=w.lazy(()=>w.object({type:w.literal("blockquote"),content:w.array(w.lazy(()=>Ut)).describe("Quoted block content")})),rr=w.lazy(()=>w.object({type:w.literal("blockCard"),attrs:w.object({url:w.string().url().describe("URL for the card")})})),sr=w.lazy(()=>w.object({type:w.literal("media"),attrs:w.object({id:w.string().describe("Media identifier in Jira storage"),type:w.string().describe("Media type, e.g., file or link"),collection:w.string().optional(),width:w.number().optional(),height:w.number().optional()}).describe("Metadata describing the embedded media")})),nr=w.lazy(()=>w.object({type:w.literal("mediaSingle"),content:w.array(sr).describe("Single media block content")})),ir=w.lazy(()=>w.object({type:w.literal("mediaGroup"),content:w.array(sr).describe("Gallery-style media grouping")})),or=w.object({type:w.literal("tableCell"),attrs:w.object({colspan:w.number().int().min(1).optional(),rowspan:w.number().int().min(1).optional()}).optional(),content:w.array(w.lazy(()=>Ut)).describe("Content inside the table cell")}).describe("A regular table cell container"),ar=w.lazy(()=>or),cr=w.lazy(()=>or.extend({type:w.literal("tableHeader")})),dr=w.lazy(()=>w.object({type:w.literal("tableRow"),content:w.array(w.union([ar,cr]))})),lr=w.lazy(()=>w.object({type:w.literal("table"),content:w.array(dr)})),pr=w.lazy(()=>w.object({type:w.literal("decisionItem"),attrs:w.object({localId:w.string().optional(),state:w.enum(["DECIDED","DECIDING"]).optional()}).optional(),content:w.array(w.lazy(()=>Ut))})),ur=w.lazy(()=>w.object({type:w.literal("decisionList"),content:w.array(pr)})),mr=w.lazy(()=>w.object({type:w.string(),attrs:w.record(w.any()).optional(),content:w.array(w.lazy(()=>zt)).optional(),marks:w.array(Nt).optional(),text:w.string().optional()}).describe("Unknown or extended Jira node"));Ut=w.lazy(()=>w.union([Wt,Kt,Yt,Gt,Xt,Vt,Zt,Qt,er,tr,rr,nr,ir,lr,dr,ar,cr,ur,pr,Ft,mr])),zt=w.lazy(()=>w.union([Ut,Bt]));const hr=w.object({type:w.literal("doc"),version:w.literal(1),content:w.array(Ut).describe("Top-level block nodes in the document")}).describe("Jira ADF document structure; run jira-md-to-adf when converting markdown"),yr=o.for("jira.rate-limit"),fr=Je.jira.rateLimitRetryDelayMs??3e3;let gr=!1;const br="jira-issue-update",wr=Dt,vr={name:br,inputSchema:wr,runTool:async(e,t)=>{try{const r=wr.parse(t),s={issueIdOrKey:r.issueId};r.fields&&(s.fields=(e=>{const t={...e},r=t.description;if("string"==typeof r){const e=lt(ct(r));t.description=hr.parse(e)}else if(r&&"object"==typeof r){const e=lt(hr.parse(r));t.description=e}return t})(r.fields)),r.update&&(s.update=r.update),r.properties&&(s.properties=r.properties),void 0!==r.notifyUsers&&(s.notifyUsers=r.notifyUsers),r.issueTemplateId&&(s.issueTemplateId=r.issueTemplateId),void 0!==r.overrideScreenSecurity&&(s.overrideScreenSecurity=r.overrideScreenSecurity),void 0!==r.overrideEditableFlag&&(s.overrideEditableFlag=r.overrideEditableFlag);const n=await(async(e,t)=>{try{return await t()}catch(s){if((e=>{const t=(e=>e?.status??e?.statusCode??e?.response?.status??e?.response?.statusCode??void 0)(e);if(403!==t)return!1;const r=(e=>{const t=e?.response?.data??e?.data??e?.response?.body??e,r=[];return"string"==typeof t&&r.push(t),"string"==typeof t?.message&&r.push(t.message),"string"==typeof t?.errorMessage&&r.push(t.errorMessage),Array.isArray(t?.errorMessages)&&r.push(...t.errorMessages.filter(e=>"string"==typeof e)),"string"==typeof t?.details?.message&&r.push(t.details.message),r.join(" ")||""})(e);return/rate\s?limit/i.test(r)})(s))return gr||(yr.warn(`Jira rate limit detected for ${e}; waiting ${fr}ms before retrying.`,{retryDelayMs:fr}),gr=!0),fr>0&&await(r=fr,new Promise(e=>setTimeout(e,r))),t();throw s}var r})(br,()=>e.issues.editIssue(s));return yt(n?.data??n)}catch(e){throw wt(e)}}},Ir=w.object({markdown:w.string().describe("Markdown source that will be converted into Jira ADF"),options:w.record(w.any()).optional().describe("Optional MarkdownToAdfOptions passed to the converter")}).describe("Convert markdown into a sanitized Jira ADF document"),jr={name:"jira-md-to-adf",inputSchema:Ir,runTool:async(e,t)=>{const r=Ir.parse(t),s=lt(ct(r.markdown,r.options));return yt(hr.parse(s))}},kr=w.object({issueId:w.string().min(1).describe("Issue key or ID for the assignment change"),assignee:w.union([w.string().describe("Username or account name of the new assignee"),w.object({accountId:w.string().min(1).describe("Account ID of the assignee")}),w.object({accountType:w.string().min(1).describe("Account type filter (e.g., user, app)")})]).describe("How the new assignee is specified")}).describe("Arguments required to assign a Jira issue to someone"),Sr={name:"jira-assign-issue",inputSchema:kr,runTool:async(e,t)=>{try{const r=kr.parse(t);let s;s="string"==typeof r.assignee?{accountId:r.assignee}:r.assignee;const n=await e.issues.assignIssue({issueIdOrKey:r.issueId,assignee:s});return yt(n?.data??n)}catch(e){throw wt(e)}}},xr=w.object({issueId:w.string().min(1).describe("Issue key or ID to remove the assignee from")}).describe("Inputs required to unassign a Jira issue"),Ar={name:"jira-unassign-issue",inputSchema:xr,runTool:async(e,t)=>{try{const r=xr.parse(t),s=await e.issues.assignIssue({issueIdOrKey:r.issueId,assignee:{accountId:"-1"}});return yt(s?.data??s)}catch(e){throw wt(e)}}},Tr=w.object({issueId:w.string().min(1).describe("The Jira issue key or numeric ID receiving the comment"),body:w.string().min(1).describe("The markdown-compatible text of the comment"),visibility:w.object({type:w.enum(["role","group"]).describe("Visibility type that restricts the comment to a role or group"),value:w.string().min(1).describe("The name of the role or group granted visibility")}).optional().describe("Optional visibility override controlling who can read the comment")}).describe("Arguments for adding a comment to a Jira issue"),Er={name:"jira-comment-add",inputSchema:Tr,runTool:async(e,t)=>{try{const r=Tr.parse(t),s=e.issueComments;if(!s||"function"!=typeof s.addComment)throw Error("Jira issueComments API is unavailable on the client");const n={issueIdOrKey:r.issueId,comment:r.body};r.visibility&&(n.visibility=r.visibility);const i=await s.addComment(n);return yt(i?.data??i)}catch(e){throw wt(e)}}},Or=w.object({issueId:w.string().min(1).describe("Issue key or ID whose comments should be retrieved"),start:w.number().optional().default(0).describe("Zero-based index to start pagination from"),maxResults:w.number().optional().default(50).describe("Maximum number of comments to return"),orderBy:w.string().optional().describe("Field name to order the returned comments by"),expand:w.string().optional().describe("Optional expansion clause for the comment response")}).describe("Parameters for fetching comments on a Jira issue"),Jr={name:"jira-comment-list",inputSchema:Or,runTool:async(e,t)=>{try{const r=Or.parse(t),s=e.issueComments;if(!s||"function"!=typeof s.getComments)throw Error("Jira issueComments API is unavailable on the client");const n=await s.getComments({issueIdOrKey:r.issueId,startAt:r.start,maxResults:r.maxResults,orderBy:r.orderBy,expand:r.expand});return yt(n?.data??n)}catch(e){throw wt(e)}}},Cr=w.enum(["Blocks","Relates to","Duplicates","Is blocked by","Is related to","is tested by","tests","Is covered by","covered by","Is duplicated by","Causes","Is caused by","Clone","Required","Work on","Split","Roll up"]).describe("The named relationship (Blocks, Relates to, etc.) that describes the link type"),Dr=w.object({id:w.string().optional().describe("Numeric Jira ID used when referencing an issue"),key:w.string().optional().describe("Human-readable key of the linked issue")}).describe("An issue reference (ID or key) used when building a link payload"),Hr=w.object({type:w.enum(["role","group"]).describe("Visibility scope type attached to the comment"),value:w.string().min(1).describe("Name of the role or group granted visibility to the comment")}).describe("Optional visibility settings applied to the comment"),Nr=w.object({body:w.string().optional().describe("Markdown text to include as a linked-comment"),visibility:Hr.optional().describe("Optional ACL for the comment")}).describe("Optional comment applied at the time the link is created or updated"),_r=w.object({link:w.object({relationship:Cr,inwardIssue:Dr,outwardIssue:Dr,comment:Nr.optional()}).describe("Definition of the link that should be created between two issues")}).describe("Arguments required to create a Jira issue link");let Rr=[];function $r(e){return(e||"").trim().toLowerCase()}async function Pr(e,t){if(!t)throw Error("Link relationship is required");0===Rr.length&&(Rr=await(async e=>{const t=e.issueLinkTypes;if(!t||"function"!=typeof t.getIssueLinkTypes)throw Error("Jira issueLinkTypes API is unavailable on the client");const r=await t.getIssueLinkTypes(),s=r?.issueLinkTypes??r?.values??r;return Array.isArray(s)?s:[]})(e));const r=$r(t),s=Rr.find(e=>[e.name,e.inward,e.outward].some(e=>$r(e)===r));if(!s)throw Error(`No issue link type matching '${t}' found.`);return s}function Mr(e){if(!e)throw Error("Linked issue must include an id or key");if(e.id)return{id:e.id};if(e.key)return{key:e.key};throw Error("Linked issue must include an id or key")}function Lr(e){if(!e)return;const t={};return e.body&&(t.body=ct(e.body)),e.visibility&&(t.visibility=e.visibility),Object.keys(t).length>0?t:void 0}const qr=_r,Fr={name:"jira-link-create",inputSchema:qr,runTool:async(e,t)=>{try{const r=qr.parse(t).link,s={inwardIssue:Mr(r.inwardIssue),outwardIssue:Mr(r.outwardIssue)},n=Lr(r.comment);n&&(s.comment=n);const i=e.issueLinks;if(!i||"function"!=typeof i.linkIssues)throw Error("Jira issueLinks API is unavailable on the client");const o=await Pr(e,r.relationship);s.type={id:o.id};const a=await i.linkIssues(s);return yt(a?.data??a)}catch(e){throw wt(e)}}},Ur=w.object({issueId:w.string().min(1).describe("Issue key or ID receiving the attachment"),file:w.string().min(1).describe("Base64 or path to the file contents to upload"),mimeType:w.string().optional().describe("Optional MIME type override for the attachment"),comment:w.string().optional().describe("Optional comment to associate with the attachment")}).describe("Inputs needed to attach a file to a Jira issue"),zr={name:"jira-attach",inputSchema:Ur,runTool:async(e,t)=>{try{const r=Ur.parse(t),n=A.resolve(r.file),i=await s.readFile(n),o=A.basename(n),a=new FormData;a.append("file",new Blob([i],{type:r.mimeType??"application/octet-stream"}),o);const c=e?.config??null,d=c?.host,l=c?.authentication?.basic??c?.authentication??c?.auth??null,p=l?.email,u=l?.apiToken??l?.apiKey;if(!d||!p||!u)throw Error("Jira client authentication configuration is unavailable for attachments");const m=await fetch(`${d}/rest/api/3/issue/${r.issueId}/attachments`,{method:"POST",headers:{Authorization:"Basic "+Buffer.from(`${p}:${u}`).toString("base64"),"X-Atlassian-Token":"no-check"},body:a});if(!m.ok){const e=await m.text();throw Error(`Jira attachment upload failed (${m.status}): ${e}`)}const h=await m.json();if(r.comment){const t=e.issueComments;if(!t||"function"!=typeof t.addComment)throw Error("Jira issueComments API is unavailable on the client");await t.addComment({issueIdOrKey:r.issueId,comment:ct(r.comment)})}return yt(h)}catch(e){if(e&&e.code&&"string"==typeof e.code&&["ENOENT","EACCES"].includes(e.code))throw Error("Attachment file error: "+e.message);throw wt(e)}}},Br=w.object({issueId:w.string().min(1).describe("Issue key or ID whose attachments should be listed")}).describe("Arguments used to fetch attachments for a Jira issue"),Wr={name:"jira-attachment-list",inputSchema:Br,runTool:async(e,t)=>{try{const r=Br.parse(t),s=e.issues;if(!s||"function"!=typeof s.getIssue)throw Error("Jira issues API is unavailable on the client");const n=await s.getIssue({issueIdOrKey:r.issueId,fields:["attachment"]}),i=n?.data??n;return yt({attachments:i?.fields?.attachment??[]})}catch(e){throw wt(e)}}},Kr=w.object({issueId:w.string().min(1).describe("Issue key or ID owning the attachment"),attachmentId:w.string().min(1).describe("ID of the attachment to delete")}).describe("Arguments required to remove an attachment from Jira"),Xr={name:"jira-attachment-delete",inputSchema:Kr,runTool:async(e,t)=>{try{const r=Kr.parse(t),s=e.issueAttachments;if(!s||"function"!=typeof s.removeAttachment)throw Error("Jira issueAttachments API is unavailable on the client");return await s.removeAttachment({id:r.attachmentId}),yt({success:!0,message:`Attachment ${t.attachmentId} deleted successfully`})}catch(e){throw wt(e)}}},Yr=w.object({issueId:w.string().min(1).describe("Target issue key or ID for the worklog entry"),timeSpent:w.string().min(1).describe('Time spent text (e.g., "1h 30m")'),comment:w.string().optional().describe("Optional worklog comment in markdown"),author:w.object({accountId:w.string().min(1).describe("Account ID of the user logging the work")}).optional().describe("Optional author override for the worklog entry"),startingOn:w.string().optional().describe("Optional timestamp for when the work started (ISO)"),artifact:w.string().optional().describe("Optional identifier linking the worklog to another artifact")}).describe("Arguments required to add a worklog entry to a Jira issue"),Gr={name:"jira-worklog-add",inputSchema:Yr,runTool:async(e,t)=>{try{const r=Yr.parse(t),s={timeSpent:r.timeSpent};r.comment&&(s.comment=r.comment),r.author&&(s.author=r.author),r.startingOn&&(s.started=r.startingOn),r.artifact&&(s.artifact=r.artifact);const n=e.issueWorklogs;if(!n||"function"!=typeof n.addWorklog)throw Error("Jira issueWorklogs API is unavailable on the client");const i=await n.addWorklog({issueIdOrKey:r.issueId,...s});return yt(i?.data??i)}catch(e){throw wt(e)}}},Zr=o.for("jira.xray");class Vr{constructor(){this.clientId=Je.orThrow().xray.apiUser,this.clientSecret=Je.orThrow().xray.apiSecret,this.baseUrl=Je.orThrow().xray.host||"https://eu.xray.cloud.getxray.app"}async authenticate(){if(!this.clientId||!this.clientSecret)throw Error("Xray API credentials are missing (XRAY__API_USER, XRAY__API_SECRET).");const e=await fetch(this.baseUrl+"/api/v2/authenticate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_id:this.clientId,client_secret:this.clientSecret})}),t=await e.text();return this.token=t.replace(/"/g,""),this.token}async graphql(e,t){this.token||await this.authenticate();const r={query:e,variables:t};Zr.info("xray.graphql.request",{payload:Pe(r)});try{const e=await fetch(this.baseUrl+"/api/v2/graphql",{method:"POST",headers:{Authorization:"Bearer "+this.token,"Content-Type":"application/json"},body:JSON.stringify(r)}),t=await e.json();if(Zr.info("xray.graphql.response",{status:e.status,headers:e.headers?.get?e.headers.get("content-type"):void 0,body:Pe(t)}),t.errors)throw Zr.error("xray.graphql.errors",{errors:Pe(t.errors)}),Error(JSON.stringify(t.errors,null,2));return t.data}catch(e){throw Zr.error("xray.graphql.failure",{error:e+""}),e}}async getTest(e){return(await this.graphql('\n query GetTest($issueId: String!) {\n getTest(issueId: $issueId) {\n issueId\n jira(fields:["key"])\n steps {\n id\n action\n data\n result\n }\n }\n }\n ',{issueId:e})).getTest}async addStep(e,t){return(await this.graphql("\n mutation AddTestStep($issueId: String!, $step: CreateStepInput!) {\n addTestStep(issueId: $issueId, step: $step) {\n id\n action\n data\n result\n }\n }\n ",{issueId:e,step:t})).addTestStep}async updateStep(e,t){return(await this.graphql("\n mutation UpdateTestStep($stepId: String!, $step: UpdateStepInput!) {\n updateTestStep(stepId: $stepId, step: $step) {\n id\n action\n data\n result\n }\n }\n ",{stepId:e,step:t})).updateTestStep}async deleteStep(e){return(await this.graphql("\n mutation RemoveTestStep($stepId: String!) {\n removeTestStep(stepId: $stepId)\n }\n ",{stepId:e})).removeTestStep}async addSteps(e,t){return Promise.all(t.map(t=>this.addStep(e,t)))}async updateSteps(e){return Promise.all(e.map(e=>this.updateStep(e.stepId,e.step)))}async deleteSteps(e){return Promise.all(e.map(e=>this.deleteStep(e)))}async syncSteps(e,t){const r=(await this.getTest(e)).steps||[],s=[],n=[],i=[];for(let e=0;e<t.length;e++){const i=t[e],o=r[e];o?o.action===i.action&&o.data===i.data&&o.result===i.result||s.push({stepId:o.id,step:i}):n.push(i)}if(r.length>t.length)for(let e=t.length;e<r.length;e++)i.push(r[e].id);await this.addSteps(e,n),await this.updateSteps(s),await this.deleteSteps(i)}}let Qr=null;const es=new Map;function ts(e){const t=e?.fields,r=e?.action??t?.Action??t?.action;if(!r||"string"!=typeof r)throw Error("Xray step action is required");const s=e.data??e.fields?.Data??e.fields?.data??void 0,n=e.result??e.fields?.Result??e.fields?.result??void 0;return{action:r.toString(),data:"string"==typeof s?s:void 0,result:"string"==typeof n?n:void 0}}async function rs(e,t){if(!t)throw Error("Issue reference is required when interacting with Xray steps");if(es.has(t))return es.get(t);if(/^[0-9]+$/.test(t))return es.set(t,t),t;const r=e?.issues??e?.issue;if(!r?.getIssue)throw Error("Jira client does not expose issue lookup functionality");const s=await r.getIssue({issueIdOrKey:t,fields:["id"]}),n=s?.id;if(!n)throw Error("Unable to resolve Jira issue ID for "+t);return es.set(t,n),n}async function ss(e){if(e?.test?.step)return e.test.step;const t=await(async()=>{if(Qr)return Qr;const e=Je.orThrow().xray.apiUser?.trim(),t=Je.orThrow().xray.apiSecret?.trim();if(!e||!t)throw Error("Xray credentials are missing (XRAY__API_USER, XRAY__API_SECRET). Please configure them before using Xray tools.");const r=Le(),s=new Vr;return Qr={test:{step:{async createStep(e,t){const n=await rs(r,e),i=await s.addStep(n,ts(t));return{step:i,id:i?.id}},async updateStep(e,t,n){await rs(r,e);const i=ts(n),o=await s.updateStep(t.toString(),i);return{step:o,id:o?.id}},deleteStep:async(e,t)=>(await rs(r,e),{success:!0===await s.deleteStep(t.toString())}),async getSteps(e){const t=await rs(r,e),n=await s.getTest(t);return{steps:n?.steps??[]}}}}},Qr})();if(!t?.test?.step)throw Error("Xray step API is unavailable on the client");return t.test.step}const ns=w.object({issueId:w.string().min(1).describe("Xray test case key or ID that owns the step"),action:w.string().min(1).describe("Action description for the new Xray step"),data:w.string().optional().describe("Optional data or context used by this step"),result:w.string().optional().describe("Optional expected result for the step")}).describe("Inputs for adding a step to an Xray test case"),is={name:"jira-xray-step-add",inputSchema:ns,runTool:async(e,t)=>{try{const r=ns.parse(t),s=await ss(e),n={action:r.action,data:r.data,result:r.result};return yt(await s.createStep(r.issueId,n))}catch(e){throw wt(e)}}},os=w.object({issueId:w.string().min(1).describe("Xray test case key or ID that owns the step"),stepId:w.union([w.string(),w.number()]).describe("Identifier for the step that should be updated"),action:w.string().min(1).describe("New action text for the step"),data:w.string().optional().describe("Updated data/context for the step"),result:w.string().optional().describe("Updated expected result for the step")}).describe("Inputs required to modify an Xray test step"),as={name:"jira-xray-step-update",inputSchema:os,runTool:async(e,t)=>{try{const r=os.parse(t),s=await ss(e),n=r.stepId+"",i={action:r.action,data:r.data,result:r.result};return yt(await s.updateStep(r.issueId,n,i))}catch(e){throw wt(e)}}},cs=w.object({issueId:w.string().min(1).describe("Xray test case key or ID owning the step"),stepId:w.union([w.string(),w.number()]).describe("Identifier of the step to delete")}).describe("Arguments used to remove an Xray test step"),ds={name:"jira-xray-step-delete",inputSchema:cs,runTool:async(e,t)=>{try{const r=cs.parse(t),s=await ss(e);return await s.deleteStep(r.issueId,r.stepId.toString()),yt({success:!0})}catch(e){throw wt(e)}}},ls=w.object({issueId:w.string().min(1).describe("Xray test case key or ID whose steps should be returned")}).describe("Inputs required to list steps on an Xray test case"),ps={name:"jira-xray-step-list",inputSchema:ls,runTool:async(e,t)=>{try{const r=ls.parse(t),s=await ss(e);return yt(await s.getSteps(r.issueId))}catch(e){throw wt(e)}}},us=w.object({linkId:w.string().min(1).describe("Identifier for the Jira issue link to remove")}).describe("Inputs required to delete an existing Jira issue link"),ms={name:"jira-link-delete",inputSchema:us,runTool:async(e,t)=>{try{const r=us.parse(t),s=e.issueLinks;if(!s||"function"!=typeof s.deleteIssueLink)throw Error("Jira issueLinks API is unavailable on the client");return await s.deleteIssueLink({linkId:r.linkId}),yt({success:!0,message:`Issue link ${r.linkId} deleted successfully`})}catch(e){throw wt(e)}}},hs=w.object({linkId:w.string().min(1).describe("ID of the existing issue link to change"),relationship:Cr,comment:Nr.optional().describe("Optional comment to attach while recreating the link")}).describe("Inputs required to update (recreate) a Jira issue link"),ys={name:"jira-link-update",inputSchema:hs,runTool:async(e,t)=>{try{const r=hs.parse(t),s=e.issueLinks;if(!s||"function"!=typeof s.getIssueLink||"function"!=typeof s.deleteIssueLink||"function"!=typeof s.linkIssues)throw Error("Jira issueLinks API is unavailable on the client");const n=await s.getIssueLink({linkId:r.linkId}),i=n?.data??n;if(!i)throw Error(`Issue link ${r.linkId} not found`);const o=i.inwardIssue,a=i.outwardIssue;if(!o||!a)throw Error("Issue link payload is missing linked issues");const c=await Pr(e,r.relationship);await s.deleteIssueLink({linkId:r.linkId});const d={inwardIssue:Mr(o),outwardIssue:Mr(a),type:{id:c.id}},l=Lr(r.comment);return l&&(d.comment=l),await s.linkIssues(d),yt({success:!0,message:`Issue link ${r.linkId} updated to ${r.relationship}`})}catch(e){throw wt(e)}}};function fs(e=[]){return e.map(gs).join("")}function gs(e){switch(e.type){case"text":return(e=>{let t=e.text||"";for(const r of e.marks||[])switch(r.type){case"strong":t=`**${t}**`;break;case"em":t=`*${t}*`;break;case"strike":t=`~~${t}~~`;break;case"code":t="`"+t+"`";break;case"link":t=`[${t}](${r.attrs.href})`}return t})(e);case"mention":return e.attrs.text||"@"+e.attrs.id;case"emoji":return e.attrs.shortName||"";case"inlineCard":return e.attrs.url;case"status":return`:status{color="${e.attrs.color}"}[${e.attrs.text}]`;case"hardBreak":return" \n"}return""}function bs(e){switch(e.type){case"heading":return"#".repeat(e.attrs?.level)+" "+fs(e.content);case"paragraph":return fs(e.content);case"blockquote":return e.content.map(bs).map(e=>"> "+e).join("\n");case"bulletList":case"orderedList":case"taskList":return(e=>{const t=[];let r=1;for(const s of e.content){let n="- ";"orderedList"===e.type&&(n=r+++". "),"taskList"===e.type&&(n="- "+("DONE"===s.attrs?.state?"[x] ":"[ ] "));const i=s.content.map(bs).join(" ");t.push(n+i)}return t.join("\n")})(e);case"table":return(e=>{const t=e.content||[];return t.length?["| "+t[0].content.map(e=>fs(e.content[0].content)).join(" | ")+" |","| "+t[0].content.map(()=>"---").join(" | ")+" |",...t.slice(1).map(e=>e.content.map(e=>fs(e.content[0].content)).join(" | ")).map(e=>"| "+e+" |")].join("\n"):""})(e);case"codeBlock":return"```"+(e.attrs?.language||"")+"\n"+e.content?.map(e=>e.text).join("")+"\n```";case"panel":return(e=>`::panel{type="${e.attrs?.panelType||"info"}"}\n${e.content.map(bs).join("\n")}\n::`)(e);case"rule":return"---";case"mediaSingle":return(e=>{const t=e.content?.[0];return t?"external"===t.attrs?.type?``:"file"===t.attrs?.type?`[attachment](attachment:${t.attrs.id})`:"":""})(e);case"blockCard":return e.attrs?.url}return""}const ws=w.object({document:hr.describe("Jira ADF document you want to translate into Markdown (use jira-md-to-adf to go the other way).")}).describe("Convert Jira ADF documents back to Markdown text for editing or review"),vs={name:"jira-adf-to-markdown",inputSchema:ws,runTool:async(e,t)=>{return yt({markdown:(r=ws.parse(t).document,(e=>{if(!e||"doc"!==e.type)return"";const t=[];for(const r of e.content||[])t.push(bs(r));return t.join("\n\n")})(r))});var r}},Is={[ft.name]:{title:"Jira Issue Create",description:"Create a Jira issue (optionally applying a markdown template)",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[At.name]:{title:"Jira Issue Read",description:"Read a Jira issue with expandable fields and properties",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[St.name]:{title:"Jira Issue List",description:"Search issues by summary, reference, parent, or JQL and list the matching tickets",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[vr.name]:{title:"Jira Issue Update",description:"Update a Jira issue using fields, update ops, and property toggles",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[jr.name]:{title:"Jira Markdown to ADF",description:"Convert Markdown into a sanitized Jira ADF document so fields.description can be supplied to jira-issue-update and other tools that expect Jira documents",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[vs.name]:{title:"Jira ADF to Markdown",description:"Translate Jira ADF documents back into Markdown text so you can edit them before sending them through tooling or LLM prompts (use jira-md-to-adf to get valid ADF inputs).",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[It.name]:{title:"Jira Issue Delete",description:"Delete a Jira issue and optionally remove its subtasks",annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1,openWorldHint:!0}},[Et.name]:{title:"Jira Issue Transition",description:"Transition a Jira issue while optionally adding a comment",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[Jt.name]:{title:"Jira Transition List",description:"List available transitions for a Jira issue",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[Sr.name]:{title:"Jira Issue Assign",description:"Assign a Jira issue to a user or account",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[Ar.name]:{title:"Jira Issue Unassign",description:"Unassign the current owner from a Jira issue",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[Er.name]:{title:"Jira Comment Add",description:"Add a comment to a Jira issue with optional visibility",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[Jr.name]:{title:"Jira Comment List",description:"List comments on a Jira issue with pagination support",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[Fr.name]:{title:"Jira Link Create",description:"Create an issue link relationship with optional comment",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[ys.name]:{title:"Jira Link Update",description:"Change the relationship type for an existing issue link",annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1,openWorldHint:!0}},[ms.name]:{title:"Jira Link Delete",description:"Delete an issue link from Jira",annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1,openWorldHint:!0}},[zr.name]:{title:"Jira Attachment Add",description:"Attach a local file to a Jira issue",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[Wr.name]:{title:"Jira Attachment List",description:"List attachments on a Jira issue",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},[Xr.name]:{title:"Jira Attachment Delete",description:"Delete an attachment from a Jira issue",annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1,openWorldHint:!0}},[Gr.name]:{title:"Jira Worklog Add",description:"Log time spent on a Jira issue",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[is.name]:{title:"Jira Xray Step Add",description:"Add a step to an Xray test case",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[as.name]:{title:"Jira Xray Step Update",description:"Update a step on an Xray test case",annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!0}},[ds.name]:{title:"Jira Xray Step Delete",description:"Delete a step from an Xray test case",annotations:{readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1,openWorldHint:!0}},[ps.name]:{title:"Jira Xray Step List",description:"List steps for an Xray test case",annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}}};async function js(e){const t=o.for(js);let r,s=null;try{r=Le()}catch(e){if(!(e instanceof Ne))return void t.warn("Skipping Jira tool registration; unable to create Jira client",{error:e});s=e,t.warn("Registering Jira tools without credentials; each tool will report configuration requirements.",{error:e})}const n=[ft,At,St,vr,jr,vs,It,Et,Jt,Sr,Ar,Er,Jr,Fr,ys,ms,zr,Wr,Xr,Gr,is,as,ds,ps];for(const i of n){const n=Is[i.name];if(n)try{await e.registerTool(i.name,{title:n.title,description:n.description,inputSchema:i.inputSchema,annotations:n.annotations},async e=>{if(!r)throw s??Error("Jira client unavailable because credentials could not be loaded.");return i.runTool(r,e)}),t.info("Registered Jira tool "+i.name)}catch(e){t.error("Failed to register Jira tool "+i.name,{error:e})}}}async function ks(e){await(async e=>{e.registerTool("decaf-server-info",{title:"Decaf MCP Server Info",description:"Return server metadata, version, and registered prompt names for diagnostics.",inputSchema:{},outputSchema:void 0,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async()=>{const e=je.map(e=>e.getName()).sort();return{content:[{type:"text",text:["Name: "+Je.name,"Title: "+Je.title,"Version: "+Je.version,"Prompts: "+(e.join(", ")||"<none>")].join("\n")}]}})})(e);const t=o.for(ks);try{await js(e)}catch(e){t.error("Failed to register Jira tools",e)}}class Ss extends Z{setCb(e){return this.cb=e,this}setConfig(e){return this.config=e,this}setUriOtTemplate(e){return this.uriOrTemplate=e,this}constructor(e){super(e)}static get builder(){return new Ss}build(e){const t=this.hasErrors();if(t)throw Error(t.toString());try{const t="string"==typeof this.uriOrTemplate&&this.uriOrTemplate.includes("{")?new M(new P(this.uriOrTemplate),{list:void 0}):this.uriOrTemplate,r=Object.assign(this.config,{_meta:{}}),s=async(e,t)=>{const r=this.logFor(t);r.verbose(`Requesting resource ${this.name} from ${e.toString()}`);const s=await Promise.resolve(this.cb(e,t));return r.verbose(`Resource ${this.name} retrieved successfully.`),r.debug("Resource retrieval meta: "+JSON.stringify(s._meta)),s};return e.resource(this.name,t,r,s)}catch(e){throw o.for(this).error("Error registering resource "+this.name,e),e}}}m([y(),h("design:type",String)],Ss.prototype,"uriOrTemplate",void 0),m([y(),h("design:type",Function)],Ss.prototype,"cb",void 0),m([y(),h("design:type",Object)],Ss.prototype,"config",void 0);const xs=pe()??x.join(__dirname,"..","assets"),As=x.join(xs,"templates"),Ts=x.join(xs,"prompts"),Es=[{name:"example.resource",title:"Example Resource",description:"A tiny example payload for verifying resource listing.",uri:"resource://example.resource",cb:async()=>({contents:[{type:"text",text:"example"}],_meta:{}})},{name:"repo.metadata",title:"Repository Metadata",description:"Static metadata for the decaf-ts repository.",uri:"resource://repo.metadata",cb:async()=>({contents:[{type:"json",text:JSON.stringify({repo:"decaf-ts",version:"1.0.0"})}],_meta:{}})},{name:"decoration.schematics",title:"Decoration Schematics",description:"Metadata describing decoration schematics that ship with the project.",uri:"resource://decoration.schematics",cb:async()=>({content:{type:"json",data:JSON.stringify({collection:"decaf",files:["metadata/Metadata.ts"]})},_meta:{}})},{name:"golden.overrides",title:"Golden Overrides",description:"Stubbed golden override payload used for testing the resource API.",uri:"resource://golden.overrides",cb:async()=>({content:{type:"text",text:"golden overrides stub"},_meta:{}})}];async function Os(e){const t=o.for(Os);for(const r of Es){const{name:s,uri:n,title:i,description:o,cb:a}=r;if(!s||!n||"function"!=typeof a){t.warn("Skipping invalid resource registration: "+(s??"<unknown>"));continue}const c={title:i??s,description:o??"",_meta:{}};try{await e.resource(s,n,c,async(e,t)=>a(e,t)),t.info(`Registered resource ${s} @ ${n}`)}catch(e){t.error("Failed to register resource "+s,e)}}}const Js=new WeakMap;class Cs extends a{get client(){const e=Js.get(this);if(!e)throw Error("Mcp server requires Mcp client");return e}constructor(){super()}async load(){const e=this.log.for(this.load);for(const t of je)try{e.info("loading prompt "+t.getName());const r=t.build(this.client);e.verbose(`Loaded prompt ${r.title} from ${t.getName()} definition`)}catch(r){e.error("Failed to load prompt "+t.getName(),r)}try{await ks(this.client),e.verbose("Registered built-in tools")}catch(e){}try{await Os(this.client),e.verbose("Registered built-in resources")}catch(e){}try{await(async(e,r)=>{r.info("Registering agent templates as resources...");const s=t.readdirSync(As).filter(e=>e.endsWith(".md"));for(const n of s){const s=x.basename(n,".md"),i=x.join(As,n),o=Ss.builder.setName(s).setTitle("Template: "+s).setDescription("Resource template for "+s).setUriOtTemplate("file:///"+i).setConfig({mimeType:"text/markdown",description:"Template for "+s}).setCb(async e=>{const r=t.readFileSync(e.pathname,"utf8");return{contents:[{uri:e.toString(),text:r,mimeType:"text/markdown"}],_meta:{}}});try{o.build(e),r.info("Registered template: "+s)}catch(e){r.error(`Failed to register template ${s}:`,e)}}r.info("Registering agent prompts...");const n=t.readdirSync(Ts).filter(e=>e.endsWith(".md"));for(const s of n){const n=x.basename(s,".md"),i=x.join(Ts,s),o=t.readFileSync(i,"utf8"),a=me.builder.setName(n).setTitle("Prompt: "+n).setDescription("Dynamic prompt for "+n).setArgsSchema(w.object({})).setCb(async e=>({messages:[{role:"user",content:{type:"text",text:o}}],_meta:{}}));try{a.build(e),r.info("Registered prompt: "+n)}catch(e){r.error(`Failed to register prompt ${n}:`,e)}}})(this.client,e)}catch(e){}}async boot(e="stdio"){"stdio"===e&&o.setFactory(B),o.for(this.constructor.name);const t=((Array.isArray(Je.icons)?Je.icons:[Je.icons])||[]).map(e=>{const t="string"==typeof e?.src?e.src:(e?.src??"")+"",r="string"==typeof e?.mimeType?e.mimeType:(e?.mimeType??"")+"";let s=[];return Array.isArray(e?.sizes)?s=e.sizes.map(e=>e+""):"string"==typeof e?.sizes&&(s=(e.sizes+"").split(",").map(e=>e.trim())),{src:t,mimeType:r,sizes:s}}),r={name:Je.name,title:Je.title,websiteUrl:Je.websiteUrl,version:Je.version,icons:t},s=new L(r,{instructions:"You are an AI assistant designed to help users with programming tasks related to the Decaf-TS framework. \nProvide clear, concise, and accurate information.\nIf you don't know the answer, admit it rather than making up information.\nAlways prioritize the user's intent and provide helpful suggestions when appropriate.\n",capabilities:{logging:{},tools:{},prompts:{}}});switch(((e,t)=>{Js.set(e,t)})(this,s),s.onerror=e=>{this.log.error("MCP instance onerror",e)},e){case"stdio":e=new F;break;case"http":e=new U({sessionIdGenerator:()=>q(),onsessioninitialized:e=>{},onsessionclosed:e=>{},enableJsonResponse:!0,eventStore:void 0});break;default:if(!(n=e)||"object"!=typeof n||"function"!=typeof n.send&&"function"!=typeof n.close&&"function"!=typeof n.on)throw new T("Invalid transport type: "+e)}var n;try{await this.load()}catch(e){throw e}await this.client.connect(e)}}const Ds=(new e).command("start").option("--transport [String]","transport mode","stdio").description("starts decaf's mcp server").action(async e=>{const t=de("package.json"),s=JSON.parse(r.readFileSync(t,"utf-8")),n=s.version,{transport:i}=e,o=(new z).for("mcp-server");if("stdio"!==i)throw Error("Unsupported transport mode: "+i);return o.info("Transport stdio"),o.debug(`running with options: ${JSON.stringify(e)} for ${s.name} version ${n}`),(new Cs).boot(i)});(new e).command("md-to-ast").description("pipes markdown to jira ast: `cat file.md` | npx decaf-mcp md-to-ast > ast.json").action(async e=>{const t=de("package.json"),s=JSON.parse(r.readFileSync(t,"utf-8")),n=s.version;o.for("md-to-ast").debug(`running with options: ${JSON.stringify(e)} for ${s.name} version ${n}`);const i=ct(await(async()=>{const e=[];for await(const t of process.stdin)e.push(Buffer.from(t));return Buffer.concat(e).toString("utf8")})(),{resolveMention:e=>({id:e,text:"@"+e}),resolveAttachment:e=>({id:e,collection:"attachments"})});process.stdout.write(JSON.stringify(i,null,2)+"\n")});const Hs=(new e).name("mcp-server").command("mcp-server").description("decaf mcp server and agentic functionality");Hs.addCommand(Ds),Hs.parse(process.argv);
|
|
2
2
|
//# sourceMappingURL=mcp-server.js.map
|