@supernova123/docker-mcp-server 0.2.0 → 0.2.2

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/README.md CHANGED
@@ -5,6 +5,8 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
6
  [![MCP](https://img.shields.io/badge/MCP-compatible-green)](https://modelcontextprotocol.io)
7
7
  [![Claude Desktop](https://img.shields.io/badge/Claude%20Desktop-compatible-purple)](https://claude.ai)
8
+ [![Glama](https://glama.ai/mcp/servers/friendlygeorge/docker-mcp-server/badges/card.svg)](https://glama.ai/mcp/servers/friendlygeorge/docker-mcp-server)
9
+ [![Glama Score](https://glama.ai/mcp/servers/friendlygeorge/docker-mcp-server/badges/score.svg)](https://glama.ai/mcp/servers/friendlygeorge/docker-mcp-server)
8
10
 
9
11
  **The Docker MCP server designed for agents that need their containers to stay running.**
10
12
 
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <coverage generated="1781300259293" clover="3.2.0">
3
+ <project timestamp="1781300259293" name="All files">
4
+ <metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0" elements="0" coveredelements="0" complexity="0" loc="0" ncloc="0" packages="0" files="0" classes="0"/>
5
+ </project>
6
+ </coverage>
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1,224 @@
1
+ body, html {
2
+ margin:0; padding: 0;
3
+ height: 100%;
4
+ }
5
+ body {
6
+ font-family: Helvetica Neue, Helvetica, Arial;
7
+ font-size: 14px;
8
+ color:#333;
9
+ }
10
+ .small { font-size: 12px; }
11
+ *, *:after, *:before {
12
+ -webkit-box-sizing:border-box;
13
+ -moz-box-sizing:border-box;
14
+ box-sizing:border-box;
15
+ }
16
+ h1 { font-size: 20px; margin: 0;}
17
+ h2 { font-size: 14px; }
18
+ pre {
19
+ font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
20
+ margin: 0;
21
+ padding: 0;
22
+ -moz-tab-size: 2;
23
+ -o-tab-size: 2;
24
+ tab-size: 2;
25
+ }
26
+ a { color:#0074D9; text-decoration:none; }
27
+ a:hover { text-decoration:underline; }
28
+ .strong { font-weight: bold; }
29
+ .space-top1 { padding: 10px 0 0 0; }
30
+ .pad2y { padding: 20px 0; }
31
+ .pad1y { padding: 10px 0; }
32
+ .pad2x { padding: 0 20px; }
33
+ .pad2 { padding: 20px; }
34
+ .pad1 { padding: 10px; }
35
+ .space-left2 { padding-left:55px; }
36
+ .space-right2 { padding-right:20px; }
37
+ .center { text-align:center; }
38
+ .clearfix { display:block; }
39
+ .clearfix:after {
40
+ content:'';
41
+ display:block;
42
+ height:0;
43
+ clear:both;
44
+ visibility:hidden;
45
+ }
46
+ .fl { float: left; }
47
+ @media only screen and (max-width:640px) {
48
+ .col3 { width:100%; max-width:100%; }
49
+ .hide-mobile { display:none!important; }
50
+ }
51
+
52
+ .quiet {
53
+ color: #7f7f7f;
54
+ color: rgba(0,0,0,0.5);
55
+ }
56
+ .quiet a { opacity: 0.7; }
57
+
58
+ .fraction {
59
+ font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
60
+ font-size: 10px;
61
+ color: #555;
62
+ background: #E8E8E8;
63
+ padding: 4px 5px;
64
+ border-radius: 3px;
65
+ vertical-align: middle;
66
+ }
67
+
68
+ div.path a:link, div.path a:visited { color: #333; }
69
+ table.coverage {
70
+ border-collapse: collapse;
71
+ margin: 10px 0 0 0;
72
+ padding: 0;
73
+ }
74
+
75
+ table.coverage td {
76
+ margin: 0;
77
+ padding: 0;
78
+ vertical-align: top;
79
+ }
80
+ table.coverage td.line-count {
81
+ text-align: right;
82
+ padding: 0 5px 0 20px;
83
+ }
84
+ table.coverage td.line-coverage {
85
+ text-align: right;
86
+ padding-right: 10px;
87
+ min-width:20px;
88
+ }
89
+
90
+ table.coverage td span.cline-any {
91
+ display: inline-block;
92
+ padding: 0 5px;
93
+ width: 100%;
94
+ }
95
+ .missing-if-branch {
96
+ display: inline-block;
97
+ margin-right: 5px;
98
+ border-radius: 3px;
99
+ position: relative;
100
+ padding: 0 4px;
101
+ background: #333;
102
+ color: yellow;
103
+ }
104
+
105
+ .skip-if-branch {
106
+ display: none;
107
+ margin-right: 10px;
108
+ position: relative;
109
+ padding: 0 4px;
110
+ background: #ccc;
111
+ color: white;
112
+ }
113
+ .missing-if-branch .typ, .skip-if-branch .typ {
114
+ color: inherit !important;
115
+ }
116
+ .coverage-summary {
117
+ border-collapse: collapse;
118
+ width: 100%;
119
+ }
120
+ .coverage-summary tr { border-bottom: 1px solid #bbb; }
121
+ .keyline-all { border: 1px solid #ddd; }
122
+ .coverage-summary td, .coverage-summary th { padding: 10px; }
123
+ .coverage-summary tbody { border: 1px solid #bbb; }
124
+ .coverage-summary td { border-right: 1px solid #bbb; }
125
+ .coverage-summary td:last-child { border-right: none; }
126
+ .coverage-summary th {
127
+ text-align: left;
128
+ font-weight: normal;
129
+ white-space: nowrap;
130
+ }
131
+ .coverage-summary th.file { border-right: none !important; }
132
+ .coverage-summary th.pct { }
133
+ .coverage-summary th.pic,
134
+ .coverage-summary th.abs,
135
+ .coverage-summary td.pct,
136
+ .coverage-summary td.abs { text-align: right; }
137
+ .coverage-summary td.file { white-space: nowrap; }
138
+ .coverage-summary td.pic { min-width: 120px !important; }
139
+ .coverage-summary tfoot td { }
140
+
141
+ .coverage-summary .sorter {
142
+ height: 10px;
143
+ width: 7px;
144
+ display: inline-block;
145
+ margin-left: 0.5em;
146
+ background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
147
+ }
148
+ .coverage-summary .sorted .sorter {
149
+ background-position: 0 -20px;
150
+ }
151
+ .coverage-summary .sorted-desc .sorter {
152
+ background-position: 0 -10px;
153
+ }
154
+ .status-line { height: 10px; }
155
+ /* yellow */
156
+ .cbranch-no { background: yellow !important; color: #111; }
157
+ /* dark red */
158
+ .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
159
+ .low .chart { border:1px solid #C21F39 }
160
+ .highlighted,
161
+ .highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
162
+ background: #C21F39 !important;
163
+ }
164
+ /* medium red */
165
+ .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
166
+ /* light red */
167
+ .low, .cline-no { background:#FCE1E5 }
168
+ /* light green */
169
+ .high, .cline-yes { background:rgb(230,245,208) }
170
+ /* medium green */
171
+ .cstat-yes { background:rgb(161,215,106) }
172
+ /* dark green */
173
+ .status-line.high, .high .cover-fill { background:rgb(77,146,33) }
174
+ .high .chart { border:1px solid rgb(77,146,33) }
175
+ /* dark yellow (gold) */
176
+ .status-line.medium, .medium .cover-fill { background: #f9cd0b; }
177
+ .medium .chart { border:1px solid #f9cd0b; }
178
+ /* light yellow */
179
+ .medium { background: #fff4c2; }
180
+
181
+ .cstat-skip { background: #ddd; color: #111; }
182
+ .fstat-skip { background: #ddd; color: #111 !important; }
183
+ .cbranch-skip { background: #ddd !important; color: #111; }
184
+
185
+ span.cline-neutral { background: #eaeaea; }
186
+
187
+ .coverage-summary td.empty {
188
+ opacity: .5;
189
+ padding-top: 4px;
190
+ padding-bottom: 4px;
191
+ line-height: 1;
192
+ color: #888;
193
+ }
194
+
195
+ .cover-fill, .cover-empty {
196
+ display:inline-block;
197
+ height: 12px;
198
+ }
199
+ .chart {
200
+ line-height: 0;
201
+ }
202
+ .cover-empty {
203
+ background: white;
204
+ }
205
+ .cover-full {
206
+ border-right: none !important;
207
+ }
208
+ pre.prettyprint {
209
+ border: none !important;
210
+ padding: 0 !important;
211
+ margin: 0 !important;
212
+ }
213
+ .com { color: #999 !important; }
214
+ .ignore-none { color: #999; font-weight: normal; }
215
+
216
+ .wrapper {
217
+ min-height: 100%;
218
+ height: auto !important;
219
+ height: 100%;
220
+ margin: 0 auto -48px;
221
+ }
222
+ .footer, .push {
223
+ height: 48px;
224
+ }
@@ -0,0 +1,87 @@
1
+ /* eslint-disable */
2
+ var jumpToCode = (function init() {
3
+ // Classes of code we would like to highlight in the file view
4
+ var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
5
+
6
+ // Elements to highlight in the file listing view
7
+ var fileListingElements = ['td.pct.low'];
8
+
9
+ // We don't want to select elements that are direct descendants of another match
10
+ var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
11
+
12
+ // Selector that finds elements on the page to which we can jump
13
+ var selector =
14
+ fileListingElements.join(', ') +
15
+ ', ' +
16
+ notSelector +
17
+ missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
18
+
19
+ // The NodeList of matching elements
20
+ var missingCoverageElements = document.querySelectorAll(selector);
21
+
22
+ var currentIndex;
23
+
24
+ function toggleClass(index) {
25
+ missingCoverageElements
26
+ .item(currentIndex)
27
+ .classList.remove('highlighted');
28
+ missingCoverageElements.item(index).classList.add('highlighted');
29
+ }
30
+
31
+ function makeCurrent(index) {
32
+ toggleClass(index);
33
+ currentIndex = index;
34
+ missingCoverageElements.item(index).scrollIntoView({
35
+ behavior: 'smooth',
36
+ block: 'center',
37
+ inline: 'center'
38
+ });
39
+ }
40
+
41
+ function goToPrevious() {
42
+ var nextIndex = 0;
43
+ if (typeof currentIndex !== 'number' || currentIndex === 0) {
44
+ nextIndex = missingCoverageElements.length - 1;
45
+ } else if (missingCoverageElements.length > 1) {
46
+ nextIndex = currentIndex - 1;
47
+ }
48
+
49
+ makeCurrent(nextIndex);
50
+ }
51
+
52
+ function goToNext() {
53
+ var nextIndex = 0;
54
+
55
+ if (
56
+ typeof currentIndex === 'number' &&
57
+ currentIndex < missingCoverageElements.length - 1
58
+ ) {
59
+ nextIndex = currentIndex + 1;
60
+ }
61
+
62
+ makeCurrent(nextIndex);
63
+ }
64
+
65
+ return function jump(event) {
66
+ if (
67
+ document.getElementById('fileSearch') === document.activeElement &&
68
+ document.activeElement != null
69
+ ) {
70
+ // if we're currently focused on the search input, we don't want to navigate
71
+ return;
72
+ }
73
+
74
+ switch (event.which) {
75
+ case 78: // n
76
+ case 74: // j
77
+ goToNext();
78
+ break;
79
+ case 66: // b
80
+ case 75: // k
81
+ case 80: // p
82
+ goToPrevious();
83
+ break;
84
+ }
85
+ };
86
+ })();
87
+ window.addEventListener('keydown', jumpToCode);
Binary file
@@ -0,0 +1,101 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for All files</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="prettify.css" />
9
+ <link rel="stylesheet" href="base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1>All files</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">Unknown% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>0/0</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">Unknown% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>0/0</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">Unknown% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>0/0</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">Unknown% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>0/0</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line medium'></div>
65
+ <div class="pad1">
66
+ <table class="coverage-summary">
67
+ <thead>
68
+ <tr>
69
+ <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
70
+ <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
71
+ <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
72
+ <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
73
+ <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
74
+ <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
75
+ <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
76
+ <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
77
+ <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
78
+ <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
79
+ </tr>
80
+ </thead>
81
+ <tbody></tbody>
82
+ </table>
83
+ </div>
84
+ <div class='push'></div><!-- for sticky footer -->
85
+ </div><!-- /wrapper -->
86
+ <div class='footer quiet pad2 space-top1 center small'>
87
+ Code coverage generated by
88
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
89
+ at 2026-06-12T21:37:39.290Z
90
+ </div>
91
+ <script src="prettify.js"></script>
92
+ <script>
93
+ window.onload = function () {
94
+ prettyPrint();
95
+ };
96
+ </script>
97
+ <script src="sorter.js"></script>
98
+ <script src="block-navigation.js"></script>
99
+ </body>
100
+ </html>
101
+
@@ -0,0 +1 @@
1
+ .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
@@ -0,0 +1,2 @@
1
+ /* eslint-disable */
2
+ window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.ignoreCase){ac=true}else{if(/[a-z]/i.test(ae.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){S=true;ac=false;break}}}var Y={b:8,t:9,n:10,v:11,f:12,r:13};function ab(ah){var ag=ah.charCodeAt(0);if(ag!==92){return ag}var af=ah.charAt(1);ag=Y[af];if(ag){return ag}else{if("0"<=af&&af<="7"){return parseInt(ah.substring(1),8)}else{if(af==="u"||af==="x"){return parseInt(ah.substring(2),16)}else{return ah.charCodeAt(1)}}}}function T(af){if(af<32){return(af<16?"\\x0":"\\x")+af.toString(16)}var ag=String.fromCharCode(af);if(ag==="\\"||ag==="-"||ag==="["||ag==="]"){ag="\\"+ag}return ag}function X(am){var aq=am.substring(1,am.length-1).match(new RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));var ak=[];var af=[];var ao=aq[0]==="^";for(var ar=ao?1:0,aj=aq.length;ar<aj;++ar){var ah=aq[ar];if(/\\[bdsw]/i.test(ah)){ak.push(ah)}else{var ag=ab(ah);var al;if(ar+2<aj&&"-"===aq[ar+1]){al=ab(aq[ar+2]);ar+=2}else{al=ag}af.push([ag,al]);if(!(al<65||ag>122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;ar<af.length;++ar){var at=af[ar];if(at[0]<=ap[1]+1){ap[1]=Math.max(ap[1],at[1])}else{ai.push(ap=at)}}var an=["["];if(ao){an.push("^")}an.push.apply(an,ak);for(var ar=0;ar<ai.length;++ar){var at=ai[ar];an.push(T(at[0]));if(at[1]>at[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){an[af]=-1}}}}for(var ak=1;ak<an.length;++ak){if(-1===an[ak]){an[ak]=++ad}}for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am;if(an[am]===undefined){aj[ak]="(?:"}}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){aj[ak]="\\"+an[am]}}}}for(var ak=0,am=0;ak<ah;++ak){if("^"===aj[ak]&&"^"!==aj[ak+1]){aj[ak]=""}}if(al.ignoreCase&&S){for(var ak=0;ak<ah;++ak){var ag=aj[ak];var ai=ag.charAt(0);if(ag.length>=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.global||ae.multiline){throw new Error(""+ae)}aa.push("(?:"+W(ae)+")")}return new RegExp(aa.join("|"),ac?"gi":"g")}function a(V){var U=/(?:^|\s)nocode(?:\s|$)/;var X=[];var T=0;var Z=[];var W=0;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=document.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Y=S&&"pre"===S.substring(0,3);function aa(ab){switch(ab.nodeType){case 1:if(U.test(ab.className)){return}for(var ae=ab.firstChild;ae;ae=ae.nextSibling){aa(ae)}var ad=ab.nodeName;if("BR"===ad||"LI"===ad){X[W]="\n";Z[W<<1]=T++;Z[(W++<<1)|1]=ab}break;case 3:case 4:var ac=ab.nodeValue;if(ac.length){if(!Y){ac=ac.replace(/[ \t\r\n]+/g," ")}else{ac=ac.replace(/\r\n?/g,"\n")}X[W]=ac;Z[W<<1]=T;T+=ac.length;Z[(W++<<1)|1]=ab}break}}aa(V);return{sourceCode:X.join("").replace(/\n$/,""),spans:Z}}function B(S,U,W,T){if(!U){return}var V={sourceCode:U,basePos:S};W(V);T.push.apply(T,V.decorations)}var v=/\S/;function o(S){var V=undefined;for(var U=S.firstChild;U;U=U.nextSibling){var T=U.nodeType;V=(T===1)?(V?S:U):(T===3)?(v.test(U.nodeValue)?S:V):V}return V===S?undefined:V}function g(U,T){var S={};var V;(function(){var ad=U.concat(T);var ah=[];var ag={};for(var ab=0,Z=ad.length;ab<Z;++ab){var Y=ad[ab];var ac=Y[3];if(ac){for(var ae=ac.length;--ae>=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae<aq;++ae){var ag=an[ae];var ap=aj[ag];var ai=void 0;var am;if(typeof ap==="string"){am=false}else{var aa=S[ag.charAt(0)];if(aa){ai=ag.match(aa[1]);ap=aa[0]}else{for(var ao=0;ao<X;++ao){aa=T[ao];ai=ag.match(aa[1]);if(ai){ap=aa[0];break}}if(!ai){ap=F}}am=ap.length>=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y<W.length;++Y){ae(W[Y])}if(ag===(ag|0)){W[0].setAttribute("value",ag)}var aa=ac.createElement("OL");aa.className="linenums";var X=Math.max(0,((ag-1))|0)||0;for(var Y=0,T=W.length;Y<T;++Y){af=W[Y];af.className="L"+((Y+X)%10);if(!af.firstChild){af.appendChild(ac.createTextNode("\xA0"))}aa.appendChild(af)}V.appendChild(aa)}function D(ac){var aj=/\bMSIE\b/.test(navigator.userAgent);var am=/\n/g;var al=ac.sourceCode;var an=al.length;var V=0;var aa=ac.spans;var T=aa.length;var ah=0;var X=ac.decorations;var Y=X.length;var Z=0;X[Y]=an;var ar,aq;for(aq=ar=0;aq<Y;){if(X[aq]!==X[aq+2]){X[ar++]=X[aq++];X[ar++]=X[aq++]}else{aq+=2}}Y=ar;for(aq=ar=0;aq<Y;){var at=X[aq];var ab=X[aq+1];var W=aq+2;while(W+2<=Y&&X[W+1]===ab){W+=2}X[ar++]=at;X[ar++]=ab;aq=W}Y=X.length=ar;var ae=null;while(ah<T){var af=aa[ah];var S=aa[ah+2]||an;var ag=X[Z];var ap=X[Z+2]||an;var W=Math.min(S,ap);var ak=aa[ah+1];var U;if(ak.nodeType!==1&&(U=al.substring(V,W))){if(aj){U=U.replace(am,"\r")}ak.nodeValue=U;var ai=ak.ownerDocument;var ao=ai.createElement("SPAN");ao.className=X[Z+1];var ad=ak.parentNode;ad.replaceChild(ao,ak);ao.appendChild(ak);if(V<S){aa[ah+1]=ak=ai.createTextNode(al.substring(W,S));ad.insertBefore(ak,ao.nextSibling)}}V=W;if(V>=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*</.test(S)?"default-markup":"default-code"}return t[T]}c(K,["default-code"]);c(g([],[[F,/^[^<?]+/],[E,/^<!\w[^>]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa<ac.length;++aa){for(var Z=0,V=ac[aa].length;Z<V;++Z){T.push(ac[aa][Z])}}ac=null;var W=Date;if(!W.now){W={now:function(){return +(new Date)}}}var X=0;var S;var ab=/\blang(?:uage)?-([\w.]+)(?!\S)/;var ae=/\bprettyprint\b/;function U(){var ag=(window.PR_SHOULD_USE_CONTINUATION?W.now()+250:Infinity);for(;X<T.length&&W.now()<ag;X++){var aj=T[X];var ai=aj.className;if(ai.indexOf("prettyprint")>=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X<T.length){setTimeout(U,250)}else{if(ad){ad()}}}U()}window.prettyPrintOne=y;window.prettyPrint=b;window.PR={createSimpleLexer:g,registerLangHandler:c,sourceDecorator:i,PR_ATTRIB_NAME:P,PR_ATTRIB_VALUE:n,PR_COMMENT:j,PR_DECLARATION:E,PR_KEYWORD:z,PR_LITERAL:G,PR_NOCODE:N,PR_PLAIN:F,PR_PUNCTUATION:L,PR_SOURCE:J,PR_STRING:C,PR_TAG:m,PR_TYPE:O}})();PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_DECLARATION,/^<!\w[^>]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^<script\b[^>]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:<!--|-->)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]);
@@ -0,0 +1,210 @@
1
+ /* eslint-disable */
2
+ var addSorting = (function() {
3
+ 'use strict';
4
+ var cols,
5
+ currentSort = {
6
+ index: 0,
7
+ desc: false
8
+ };
9
+
10
+ // returns the summary table element
11
+ function getTable() {
12
+ return document.querySelector('.coverage-summary');
13
+ }
14
+ // returns the thead element of the summary table
15
+ function getTableHeader() {
16
+ return getTable().querySelector('thead tr');
17
+ }
18
+ // returns the tbody element of the summary table
19
+ function getTableBody() {
20
+ return getTable().querySelector('tbody');
21
+ }
22
+ // returns the th element for nth column
23
+ function getNthColumn(n) {
24
+ return getTableHeader().querySelectorAll('th')[n];
25
+ }
26
+
27
+ function onFilterInput() {
28
+ const searchValue = document.getElementById('fileSearch').value;
29
+ const rows = document.getElementsByTagName('tbody')[0].children;
30
+
31
+ // Try to create a RegExp from the searchValue. If it fails (invalid regex),
32
+ // it will be treated as a plain text search
33
+ let searchRegex;
34
+ try {
35
+ searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive
36
+ } catch (error) {
37
+ searchRegex = null;
38
+ }
39
+
40
+ for (let i = 0; i < rows.length; i++) {
41
+ const row = rows[i];
42
+ let isMatch = false;
43
+
44
+ if (searchRegex) {
45
+ // If a valid regex was created, use it for matching
46
+ isMatch = searchRegex.test(row.textContent);
47
+ } else {
48
+ // Otherwise, fall back to the original plain text search
49
+ isMatch = row.textContent
50
+ .toLowerCase()
51
+ .includes(searchValue.toLowerCase());
52
+ }
53
+
54
+ row.style.display = isMatch ? '' : 'none';
55
+ }
56
+ }
57
+
58
+ // loads the search box
59
+ function addSearchBox() {
60
+ var template = document.getElementById('filterTemplate');
61
+ var templateClone = template.content.cloneNode(true);
62
+ templateClone.getElementById('fileSearch').oninput = onFilterInput;
63
+ template.parentElement.appendChild(templateClone);
64
+ }
65
+
66
+ // loads all columns
67
+ function loadColumns() {
68
+ var colNodes = getTableHeader().querySelectorAll('th'),
69
+ colNode,
70
+ cols = [],
71
+ col,
72
+ i;
73
+
74
+ for (i = 0; i < colNodes.length; i += 1) {
75
+ colNode = colNodes[i];
76
+ col = {
77
+ key: colNode.getAttribute('data-col'),
78
+ sortable: !colNode.getAttribute('data-nosort'),
79
+ type: colNode.getAttribute('data-type') || 'string'
80
+ };
81
+ cols.push(col);
82
+ if (col.sortable) {
83
+ col.defaultDescSort = col.type === 'number';
84
+ colNode.innerHTML =
85
+ colNode.innerHTML + '<span class="sorter"></span>';
86
+ }
87
+ }
88
+ return cols;
89
+ }
90
+ // attaches a data attribute to every tr element with an object
91
+ // of data values keyed by column name
92
+ function loadRowData(tableRow) {
93
+ var tableCols = tableRow.querySelectorAll('td'),
94
+ colNode,
95
+ col,
96
+ data = {},
97
+ i,
98
+ val;
99
+ for (i = 0; i < tableCols.length; i += 1) {
100
+ colNode = tableCols[i];
101
+ col = cols[i];
102
+ val = colNode.getAttribute('data-value');
103
+ if (col.type === 'number') {
104
+ val = Number(val);
105
+ }
106
+ data[col.key] = val;
107
+ }
108
+ return data;
109
+ }
110
+ // loads all row data
111
+ function loadData() {
112
+ var rows = getTableBody().querySelectorAll('tr'),
113
+ i;
114
+
115
+ for (i = 0; i < rows.length; i += 1) {
116
+ rows[i].data = loadRowData(rows[i]);
117
+ }
118
+ }
119
+ // sorts the table using the data for the ith column
120
+ function sortByIndex(index, desc) {
121
+ var key = cols[index].key,
122
+ sorter = function(a, b) {
123
+ a = a.data[key];
124
+ b = b.data[key];
125
+ return a < b ? -1 : a > b ? 1 : 0;
126
+ },
127
+ finalSorter = sorter,
128
+ tableBody = document.querySelector('.coverage-summary tbody'),
129
+ rowNodes = tableBody.querySelectorAll('tr'),
130
+ rows = [],
131
+ i;
132
+
133
+ if (desc) {
134
+ finalSorter = function(a, b) {
135
+ return -1 * sorter(a, b);
136
+ };
137
+ }
138
+
139
+ for (i = 0; i < rowNodes.length; i += 1) {
140
+ rows.push(rowNodes[i]);
141
+ tableBody.removeChild(rowNodes[i]);
142
+ }
143
+
144
+ rows.sort(finalSorter);
145
+
146
+ for (i = 0; i < rows.length; i += 1) {
147
+ tableBody.appendChild(rows[i]);
148
+ }
149
+ }
150
+ // removes sort indicators for current column being sorted
151
+ function removeSortIndicators() {
152
+ var col = getNthColumn(currentSort.index),
153
+ cls = col.className;
154
+
155
+ cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
156
+ col.className = cls;
157
+ }
158
+ // adds sort indicators for current column being sorted
159
+ function addSortIndicators() {
160
+ getNthColumn(currentSort.index).className += currentSort.desc
161
+ ? ' sorted-desc'
162
+ : ' sorted';
163
+ }
164
+ // adds event listeners for all sorter widgets
165
+ function enableUI() {
166
+ var i,
167
+ el,
168
+ ithSorter = function ithSorter(i) {
169
+ var col = cols[i];
170
+
171
+ return function() {
172
+ var desc = col.defaultDescSort;
173
+
174
+ if (currentSort.index === i) {
175
+ desc = !currentSort.desc;
176
+ }
177
+ sortByIndex(i, desc);
178
+ removeSortIndicators();
179
+ currentSort.index = i;
180
+ currentSort.desc = desc;
181
+ addSortIndicators();
182
+ };
183
+ };
184
+ for (i = 0; i < cols.length; i += 1) {
185
+ if (cols[i].sortable) {
186
+ // add the click event handler on the th so users
187
+ // dont have to click on those tiny arrows
188
+ el = getNthColumn(i).querySelector('.sorter').parentElement;
189
+ if (el.addEventListener) {
190
+ el.addEventListener('click', ithSorter(i));
191
+ } else {
192
+ el.attachEvent('onclick', ithSorter(i));
193
+ }
194
+ }
195
+ }
196
+ }
197
+ // adds sorting functionality to the UI
198
+ return function() {
199
+ if (!getTable()) {
200
+ return;
201
+ }
202
+ cols = loadColumns();
203
+ loadData();
204
+ addSearchBox();
205
+ addSortIndicators();
206
+ enableUI();
207
+ };
208
+ })();
209
+
210
+ window.addEventListener('load', addSorting);
File without changes
@@ -1,7 +1,7 @@
1
- import { FleetStatusSchema, FleetStatsSchema, WatchEventsSchema, SearchLogsSchema, CheckThresholdsSchema, MonitorDashboardSchema, } from "../types.js";
1
+ import { ContainerHealthStatusSchema, ContainerResourceUsageSchema, WatchEventsSchema, SearchLogsSchema, ResourceAlertCheckSchema, MonitorDashboardSchema, } from "../types.js";
2
2
  export function registerMonitoringTools(server, docker) {
3
3
  // 1. fleet_status — health status of all running containers
4
- server.tool("fleet_status", "Get health status of all running containers. Returns name, state, health, uptime, and restart count for each.", FleetStatusSchema.shape, async (params) => {
4
+ server.tool("container_health_status", "Check health status, uptime, and restart count for all running Docker containers. Returns JSON with container name, state, health probe status, and restart count.", ContainerHealthStatusSchema.shape, async (params) => {
5
5
  try {
6
6
  const containers = await docker.listContainers({ all: false });
7
7
  const results = await Promise.all(containers.map(async (c) => {
@@ -29,7 +29,7 @@ export function registerMonitoringTools(server, docker) {
29
29
  }
30
30
  });
31
31
  // 2. fleet_stats — resource usage for all running containers
32
- server.tool("fleet_stats", "Get resource usage (CPU%, memory%, network I/O) for all running containers. Sorted by usage.", FleetStatsSchema.shape, async (params) => {
32
+ server.tool("container_resource_usage", "Monitor CPU, memory, and network I/O across all running Docker containers. Returns sorted resource usage metrics with percentage breakdowns.", ContainerResourceUsageSchema.shape, async (params) => {
33
33
  try {
34
34
  const containers = await docker.listContainers({ all: false });
35
35
  const results = await Promise.all(containers.map(async (c) => {
@@ -73,7 +73,7 @@ export function registerMonitoringTools(server, docker) {
73
73
  }
74
74
  });
75
75
  // 3. watch_events — stream Docker events (simplified: collect events for a duration)
76
- server.tool("watch_events", "Collect Docker events (start, stop, die, restart, health_status) over a time window. Filter by container or event type.", WatchEventsSchema.shape, async (params) => {
76
+ server.tool("watch_events", "Stream Docker container events (start, stop, die, restart, health_status) over a configurable time window. Filter by specific container or event type.", WatchEventsSchema.shape, async (params) => {
77
77
  try {
78
78
  const durationMs = (params.duration || 30) * 1000;
79
79
  const filter = {};
@@ -122,7 +122,7 @@ export function registerMonitoringTools(server, docker) {
122
122
  }
123
123
  });
124
124
  // 4. search_logs — search logs across multiple containers
125
- server.tool("search_logs", "Search logs across multiple containers with regex/grep pattern. Returns matching lines with container name and timestamp.", SearchLogsSchema.shape, async (params) => {
125
+ server.tool("search_logs", "Search Docker container logs across multiple containers using regex pattern matching. Returns matching log lines with container name and timestamp.", SearchLogsSchema.shape, async (params) => {
126
126
  try {
127
127
  const targetContainers = params.containers || [];
128
128
  let containers;
@@ -168,7 +168,7 @@ export function registerMonitoringTools(server, docker) {
168
168
  }
169
169
  });
170
170
  // 5. check_thresholds — check all containers against thresholds
171
- server.tool("check_thresholds", "Check all containers against defined thresholds (CPU > X%, memory > Y%, restarts > Z). Returns violations.", CheckThresholdsSchema.shape, async (params) => {
171
+ server.tool("resource_alert_check", "Alert when Docker containers exceed resource thresholds (CPU%, memory%, restart count). Returns violations with specific metrics that triggered alerts.", ResourceAlertCheckSchema.shape, async (params) => {
172
172
  try {
173
173
  const cpuThreshold = params.cpu_percent ?? 80;
174
174
  const memThreshold = params.memory_percent ?? 80;
@@ -223,7 +223,7 @@ export function registerMonitoringTools(server, docker) {
223
223
  }
224
224
  });
225
225
  // 6. monitor_dashboard — single-call fleet summary
226
- server.tool("monitor_dashboard", "Single-call fleet summary: health status, top resource consumers, recent events, threshold violations. Designed for agent quick-assessment.", MonitorDashboardSchema.shape, async (params) => {
226
+ server.tool("monitor_dashboard", "Comprehensive Docker fleet dashboard in a single API call. Returns health status, top resource consumers, recent events, and threshold violations.", MonitorDashboardSchema.shape, async (params) => {
227
227
  try {
228
228
  const containers = await docker.listContainers({ all: false });
229
229
  // Fleet health
package/dist/types.d.ts CHANGED
@@ -306,8 +306,8 @@ export declare const ListVolumesSchema: z.ZodObject<{
306
306
  }, {
307
307
  filter?: string | undefined;
308
308
  }>;
309
- export declare const FleetStatusSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
310
- export declare const FleetStatsSchema: z.ZodObject<{
309
+ export declare const ContainerHealthStatusSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
310
+ export declare const ContainerResourceUsageSchema: z.ZodObject<{
311
311
  sort_by: z.ZodOptional<z.ZodEnum<["cpu", "memory", "network"]>>;
312
312
  }, "strip", z.ZodTypeAny, {
313
313
  sort_by?: "cpu" | "memory" | "network" | undefined;
@@ -349,7 +349,7 @@ export declare const SearchLogsSchema: z.ZodObject<{
349
349
  containers?: string[] | undefined;
350
350
  ignore_case?: boolean | undefined;
351
351
  }>;
352
- export declare const CheckThresholdsSchema: z.ZodObject<{
352
+ export declare const ResourceAlertCheckSchema: z.ZodObject<{
353
353
  cpu_percent: z.ZodOptional<z.ZodNumber>;
354
354
  memory_percent: z.ZodOptional<z.ZodNumber>;
355
355
  restart_count: z.ZodOptional<z.ZodNumber>;
package/dist/types.js CHANGED
@@ -126,8 +126,8 @@ export const ListVolumesSchema = z.object({
126
126
  filter: z.string().optional().describe("Filter by name or driver"),
127
127
  });
128
128
  // Monitoring schemas (v0.2.0)
129
- export const FleetStatusSchema = z.object({});
130
- export const FleetStatsSchema = z.object({
129
+ export const ContainerHealthStatusSchema = z.object({});
130
+ export const ContainerResourceUsageSchema = z.object({
131
131
  sort_by: z.enum(["cpu", "memory", "network"]).optional().describe("Sort results by metric (default: cpu)"),
132
132
  });
133
133
  export const WatchEventsSchema = z.object({
@@ -143,7 +143,7 @@ export const SearchLogsSchema = z.object({
143
143
  since: z.string().optional().describe("Only search logs since timestamp"),
144
144
  ignore_case: z.boolean().optional().describe("Case-insensitive search (default: false)"),
145
145
  });
146
- export const CheckThresholdsSchema = z.object({
146
+ export const ResourceAlertCheckSchema = z.object({
147
147
  cpu_percent: z.number().optional().describe("Alert if CPU usage exceeds this % (default: 80)"),
148
148
  memory_percent: z.number().optional().describe("Alert if memory usage exceeds this % (default: 80)"),
149
149
  restart_count: z.number().optional().describe("Alert if restart count exceeds this (default: 5)"),
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@supernova123/docker-mcp-server",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "mcpName": "io.github.friendlygeorge/docker-mcp-server",
5
- "description": "MCP server for Docker \u2014 container management, health checks, auto-restart, Compose lifecycle, and log streaming for Claude, Cursor, and AI agents",
5
+ "description": "MCP server for Docker container management, health checks, auto-restart, Compose lifecycle, and log streaming for Claude, Cursor, and AI agents",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
8
8
  "bin": {
@@ -18,19 +18,31 @@
18
18
  "keywords": [
19
19
  "mcp",
20
20
  "mcp-server",
21
+ "model-context-protocol",
21
22
  "docker",
22
23
  "docker-mcp",
23
24
  "container",
25
+ "containers",
24
26
  "compose",
27
+ "docker-compose",
25
28
  "health-check",
29
+ "health-monitoring",
30
+ "container-health",
26
31
  "devops",
32
+ "infrastructure",
33
+ "orchestration",
27
34
  "ai-agent",
28
- "model-context-protocol",
35
+ "ai-agents",
29
36
  "claude",
30
37
  "cursor",
31
38
  "chatgpt",
32
39
  "claude-desktop",
33
- "ai"
40
+ "monitoring",
41
+ "resource-monitoring",
42
+ "log-search",
43
+ "container-logs",
44
+ "docker-events",
45
+ "fleet-management"
34
46
  ],
35
47
  "author": "Nova",
36
48
  "license": "MIT",
@@ -53,4 +65,4 @@
53
65
  "typescript": "^5.7.0",
54
66
  "vitest": "^3.1.0"
55
67
  }
56
- }
68
+ }
@@ -1,20 +1,20 @@
1
1
  import Dockerode from "dockerode";
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import {
4
- FleetStatusSchema,
5
- FleetStatsSchema,
4
+ ContainerHealthStatusSchema,
5
+ ContainerResourceUsageSchema,
6
6
  WatchEventsSchema,
7
7
  SearchLogsSchema,
8
- CheckThresholdsSchema,
8
+ ResourceAlertCheckSchema,
9
9
  MonitorDashboardSchema,
10
10
  } from "../types.js";
11
11
 
12
12
  export function registerMonitoringTools(server: McpServer, docker: Dockerode): void {
13
13
  // 1. fleet_status — health status of all running containers
14
14
  server.tool(
15
- "fleet_status",
16
- "Get health status of all running containers. Returns name, state, health, uptime, and restart count for each.",
17
- FleetStatusSchema.shape,
15
+ "container_health_status",
16
+ "Check health status, uptime, and restart count for all running Docker containers. Returns JSON with container name, state, health probe status, and restart count.",
17
+ ContainerHealthStatusSchema.shape,
18
18
  async (params) => {
19
19
  try {
20
20
  const containers = await docker.listContainers({ all: false });
@@ -47,9 +47,9 @@ export function registerMonitoringTools(server: McpServer, docker: Dockerode): v
47
47
 
48
48
  // 2. fleet_stats — resource usage for all running containers
49
49
  server.tool(
50
- "fleet_stats",
51
- "Get resource usage (CPU%, memory%, network I/O) for all running containers. Sorted by usage.",
52
- FleetStatsSchema.shape,
50
+ "container_resource_usage",
51
+ "Monitor CPU, memory, and network I/O across all running Docker containers. Returns sorted resource usage metrics with percentage breakdowns.",
52
+ ContainerResourceUsageSchema.shape,
53
53
  async (params) => {
54
54
  try {
55
55
  const containers = await docker.listContainers({ all: false });
@@ -100,7 +100,7 @@ export function registerMonitoringTools(server: McpServer, docker: Dockerode): v
100
100
  // 3. watch_events — stream Docker events (simplified: collect events for a duration)
101
101
  server.tool(
102
102
  "watch_events",
103
- "Collect Docker events (start, stop, die, restart, health_status) over a time window. Filter by container or event type.",
103
+ "Stream Docker container events (start, stop, die, restart, health_status) over a configurable time window. Filter by specific container or event type.",
104
104
  WatchEventsSchema.shape,
105
105
  async (params) => {
106
106
  try {
@@ -156,7 +156,7 @@ export function registerMonitoringTools(server: McpServer, docker: Dockerode): v
156
156
  // 4. search_logs — search logs across multiple containers
157
157
  server.tool(
158
158
  "search_logs",
159
- "Search logs across multiple containers with regex/grep pattern. Returns matching lines with container name and timestamp.",
159
+ "Search Docker container logs across multiple containers using regex pattern matching. Returns matching log lines with container name and timestamp.",
160
160
  SearchLogsSchema.shape,
161
161
  async (params) => {
162
162
  try {
@@ -210,9 +210,9 @@ export function registerMonitoringTools(server: McpServer, docker: Dockerode): v
210
210
 
211
211
  // 5. check_thresholds — check all containers against thresholds
212
212
  server.tool(
213
- "check_thresholds",
214
- "Check all containers against defined thresholds (CPU > X%, memory > Y%, restarts > Z). Returns violations.",
215
- CheckThresholdsSchema.shape,
213
+ "resource_alert_check",
214
+ "Alert when Docker containers exceed resource thresholds (CPU%, memory%, restart count). Returns violations with specific metrics that triggered alerts.",
215
+ ResourceAlertCheckSchema.shape,
216
216
  async (params) => {
217
217
  try {
218
218
  const cpuThreshold = params.cpu_percent ?? 80;
@@ -274,7 +274,7 @@ export function registerMonitoringTools(server: McpServer, docker: Dockerode): v
274
274
  // 6. monitor_dashboard — single-call fleet summary
275
275
  server.tool(
276
276
  "monitor_dashboard",
277
- "Single-call fleet summary: health status, top resource consumers, recent events, threshold violations. Designed for agent quick-assessment.",
277
+ "Comprehensive Docker fleet dashboard in a single API call. Returns health status, top resource consumers, recent events, and threshold violations.",
278
278
  MonitorDashboardSchema.shape,
279
279
  async (params) => {
280
280
  try {
@@ -366,4 +366,4 @@ export function registerMonitoringTools(server: McpServer, docker: Dockerode): v
366
366
  }
367
367
  }
368
368
  );
369
- }
369
+ }
package/src/types.ts CHANGED
@@ -153,9 +153,9 @@ export const ListVolumesSchema = z.object({
153
153
 
154
154
 
155
155
  // Monitoring schemas (v0.2.0)
156
- export const FleetStatusSchema = z.object({});
156
+ export const ContainerHealthStatusSchema = z.object({});
157
157
 
158
- export const FleetStatsSchema = z.object({
158
+ export const ContainerResourceUsageSchema = z.object({
159
159
  sort_by: z.enum(["cpu", "memory", "network"]).optional().describe("Sort results by metric (default: cpu)"),
160
160
  });
161
161
 
@@ -174,10 +174,10 @@ export const SearchLogsSchema = z.object({
174
174
  ignore_case: z.boolean().optional().describe("Case-insensitive search (default: false)"),
175
175
  });
176
176
 
177
- export const CheckThresholdsSchema = z.object({
177
+ export const ResourceAlertCheckSchema = z.object({
178
178
  cpu_percent: z.number().optional().describe("Alert if CPU usage exceeds this % (default: 80)"),
179
179
  memory_percent: z.number().optional().describe("Alert if memory usage exceeds this % (default: 80)"),
180
180
  restart_count: z.number().optional().describe("Alert if restart count exceeds this (default: 5)"),
181
181
  });
182
182
 
183
- export const MonitorDashboardSchema = z.object({});
183
+ export const MonitorDashboardSchema = z.object({});
@@ -104,14 +104,14 @@ describe("Monitoring Tools", () => {
104
104
  registerMonitoringTools(server, docker);
105
105
  });
106
106
 
107
- describe("fleet_status", () => {
107
+ describe("container_health_status", () => {
108
108
  it("returns health status for all running containers", async () => {
109
109
  mockContainers(["abc123", "def456"], ["web", "db"]);
110
110
  mockInspect
111
111
  .mockResolvedValueOnce(mockInspectResult({ RestartCount: 2 }))
112
112
  .mockResolvedValueOnce(mockInspectResult({ RestartCount: 0, State: { Running: true, StartedAt: "2026-06-15T11:00:00Z", Health: { Status: "unhealthy" } } }));
113
113
 
114
- const result = await server.tools["fleet_status"].handler({});
114
+ const result = await server.tools["container_health_status"].handler({});
115
115
  const data = JSON.parse(result.content[0].text);
116
116
 
117
117
  expect(data).toHaveLength(2);
@@ -128,7 +128,7 @@ describe("Monitoring Tools", () => {
128
128
  State: { Running: true, StartedAt: "2026-06-15T10:00:00Z" },
129
129
  }));
130
130
 
131
- const result = await server.tools["fleet_status"].handler({});
131
+ const result = await server.tools["container_health_status"].handler({});
132
132
  const data = JSON.parse(result.content[0].text);
133
133
 
134
134
  expect(data[0].health).toBe("no-healthcheck");
@@ -136,14 +136,14 @@ describe("Monitoring Tools", () => {
136
136
 
137
137
  it("returns error on Docker failure", async () => {
138
138
  mockListContainers.mockRejectedValue(new Error("Docker daemon not running"));
139
- const result = await server.tools["fleet_status"].handler({});
139
+ const result = await server.tools["container_health_status"].handler({});
140
140
 
141
141
  expect(result.isError).toBe(true);
142
142
  expect(result.content[0].text).toContain("Docker daemon not running");
143
143
  });
144
144
  });
145
145
 
146
- describe("fleet_stats", () => {
146
+ describe("container_resource_usage", () => {
147
147
  it("returns resource usage sorted by CPU by default", async () => {
148
148
  mockContainers(["abc123", "def456"], ["low-cpu", "high-cpu"]);
149
149
  mockStats
@@ -156,7 +156,7 @@ describe("Monitoring Tools", () => {
156
156
  precpu_stats: { cpu_usage: { total_usage: 100000 }, system_cpu_usage: 9500000 },
157
157
  }));
158
158
 
159
- const result = await server.tools["fleet_stats"].handler({});
159
+ const result = await server.tools["container_resource_usage"].handler({});
160
160
  const data = JSON.parse(result.content[0].text);
161
161
 
162
162
  expect(data).toHaveLength(2);
@@ -177,7 +177,7 @@ describe("Monitoring Tools", () => {
177
177
  memory_stats: { usage: 900 * 1024 * 1024, limit: 1024 * 1024 * 1024 },
178
178
  }));
179
179
 
180
- const result = await server.tools["fleet_stats"].handler({ sort_by: "memory" });
180
+ const result = await server.tools["container_resource_usage"].handler({ sort_by: "memory" });
181
181
  const data = JSON.parse(result.content[0].text);
182
182
 
183
183
  expect(data[0].name).toBe("high-mem");
@@ -186,7 +186,7 @@ describe("Monitoring Tools", () => {
186
186
 
187
187
  it("returns error on Docker failure", async () => {
188
188
  mockListContainers.mockRejectedValue(new Error("Cannot connect"));
189
- const result = await server.tools["fleet_stats"].handler({});
189
+ const result = await server.tools["container_resource_usage"].handler({});
190
190
 
191
191
  expect(result.isError).toBe(true);
192
192
  expect(result.content[0].text).toContain("Cannot connect");
@@ -296,7 +296,7 @@ describe("Monitoring Tools", () => {
296
296
  });
297
297
  });
298
298
 
299
- describe("check_thresholds", () => {
299
+ describe("resource_alert_check", () => {
300
300
  it("returns violations when containers exceed thresholds", async () => {
301
301
  mockContainers(["abc123"], ["high-cpu"]);
302
302
  mockInspect.mockResolvedValue(mockInspectResult({ RestartCount: 10 }));
@@ -305,7 +305,7 @@ describe("Monitoring Tools", () => {
305
305
  precpu_stats: { cpu_usage: { total_usage: 1000000 }, system_cpu_usage: 9500000 },
306
306
  }));
307
307
 
308
- const result = await server.tools["check_thresholds"].handler({ cpu_percent: 80, restart_count: 5 });
308
+ const result = await server.tools["resource_alert_check"].handler({ cpu_percent: 80, restart_count: 5 });
309
309
  const data = JSON.parse(result.content[0].text);
310
310
 
311
311
  expect(data.violations).toHaveLength(1);
@@ -323,7 +323,7 @@ describe("Monitoring Tools", () => {
323
323
  precpu_stats: { cpu_usage: { total_usage: 90000 }, system_cpu_usage: 9500000 },
324
324
  }));
325
325
 
326
- const result = await server.tools["check_thresholds"].handler({});
326
+ const result = await server.tools["resource_alert_check"].handler({});
327
327
  const data = JSON.parse(result.content[0].text);
328
328
 
329
329
  expect(data.message).toContain("All containers within thresholds");
@@ -338,7 +338,7 @@ describe("Monitoring Tools", () => {
338
338
  precpu_stats: { cpu_usage: { total_usage: 90000 }, system_cpu_usage: 9500000 },
339
339
  }));
340
340
 
341
- const result = await server.tools["check_thresholds"].handler({});
341
+ const result = await server.tools["resource_alert_check"].handler({});
342
342
  const data = JSON.parse(result.content[0].text);
343
343
 
344
344
  expect(data.message).toContain("All containers within thresholds");
@@ -346,7 +346,7 @@ describe("Monitoring Tools", () => {
346
346
 
347
347
  it("returns error on Docker failure", async () => {
348
348
  mockListContainers.mockRejectedValue(new Error("Daemon down"));
349
- const result = await server.tools["check_thresholds"].handler({});
349
+ const result = await server.tools["resource_alert_check"].handler({});
350
350
 
351
351
  expect(result.isError).toBe(true);
352
352
  expect(result.content[0].text).toContain("Daemon down");
@@ -408,4 +408,4 @@ describe("Monitoring Tools", () => {
408
408
  expect(result.content[0].text).toContain("Connection refused");
409
409
  });
410
410
  });
411
- });
411
+ });