├── docs ├── .nojekyll ├── _media │ ├── favicon.png │ ├── mcp-discovery.png │ ├── mcp-discovery-logo.png │ ├── example-html-inline.jpg │ ├── mcp-discovery-xpost.png │ └── rust-mcp-stack-icon.png ├── examples │ ├── print_terminal.jpg │ ├── print_terminal_template_file.jpg │ ├── update-md-inline.md │ ├── capabilities.txt │ ├── create-md-plain.md │ ├── update-md-plain.md │ ├── json.txt │ ├── create-md.md │ └── update-md.md ├── example_template │ └── sample_txt_template.txt ├── _sidebar.md ├── _coverpage.md ├── guide │ ├── mcp-discovery-markers.md │ ├── helper-functions.md │ └── command-examples.md ├── README.md ├── index.html └── quickstart.md ├── .gitignore ├── .release-manifest.json ├── rust-toolchain.toml ├── tests ├── fixtures │ ├── template_files │ │ ├── md-template.md │ │ ├── txt-template.txt │ │ └── html-template.html │ ├── md-plain-update-inline.md │ ├── md-plain-update-file-prop.md │ ├── cmds.txt │ ├── txt-create.txt │ ├── md-plain-create.md │ ├── md-plain-update.md │ ├── everything-1.0.0.json │ ├── md-create.md │ ├── md-update.md │ └── md-plain-update-template-prop.md └── common │ └── common.rs ├── src ├── types.rs ├── handler.rs ├── error.rs ├── main.rs ├── utils.rs ├── types │ ├── capabilities.rs │ └── commands.rs ├── std_output.rs └── templates.rs ├── templates ├── common │ └── title.hbs ├── text │ ├── text_prompts.hbs │ ├── text_tools.hbs │ ├── text_resources.hbs │ ├── text_template.txt │ ├── text_resource_templates.hbs │ └── text_summary.hbs ├── markdown │ ├── md_plain_prompts.hbs │ ├── markdown_template.md │ ├── markdown_plain_template.md │ ├── md_plain_resources.hbs │ ├── summary.hbs │ ├── md_plain_tools.hbs │ ├── md_plain_resource_templates.hbs │ ├── md_prompts.hbs │ ├── md_resources.hbs │ ├── md_resource_templates.hbs │ └── md_tools.hbs └── html │ ├── html_prompts.hbs │ ├── html_summary.hbs │ ├── html_resources.hbs │ ├── html_resource_templates.hbs │ ├── html_tools.hbs │ └── html_template.html ├── .github ├── pull_request_template.md └── workflows │ ├── publish.yml │ ├── lint-pr.yml │ ├── ci.yml │ └── release-pr.yml ├── LICENSE ├── dist-workspace.toml ├── Cargo.toml ├── .release-config.json ├── CONTRIBUTING.md ├── Makefile.toml ├── CHANGELOG.md ├── README.md └── wix └── main.wxs /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.release-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "0.2.2" 3 | } -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.88.0" 3 | components = ["rustfmt", "clippy"] 4 | -------------------------------------------------------------------------------- /tests/fixtures/template_files/md-template.md: -------------------------------------------------------------------------------- 1 | {{> title-version prefix="## " }} 2 | 3 | {{> summary }} 4 | -------------------------------------------------------------------------------- /docs/_media/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-mcp-stack/mcp-discovery/HEAD/docs/_media/favicon.png -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | mod capabilities; 2 | mod commands; 3 | 4 | pub use capabilities::*; 5 | pub use commands::*; 6 | -------------------------------------------------------------------------------- /templates/common/title.hbs: -------------------------------------------------------------------------------- 1 | {{#if prefix}}{{{prefix}}}{{/if}}{{name}} {{version}}{{#if suffix}}{{{suffix}}}{{/if}} -------------------------------------------------------------------------------- /docs/_media/mcp-discovery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-mcp-stack/mcp-discovery/HEAD/docs/_media/mcp-discovery.png -------------------------------------------------------------------------------- /tests/fixtures/template_files/txt-template.txt: -------------------------------------------------------------------------------- 1 | {{> title-version prefix="## " }} 2 | 3 | Summary: 4 | {{> summary }} 5 | -------------------------------------------------------------------------------- /docs/examples/print_terminal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-mcp-stack/mcp-discovery/HEAD/docs/examples/print_terminal.jpg -------------------------------------------------------------------------------- /docs/_media/mcp-discovery-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-mcp-stack/mcp-discovery/HEAD/docs/_media/mcp-discovery-logo.png -------------------------------------------------------------------------------- /docs/_media/example-html-inline.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-mcp-stack/mcp-discovery/HEAD/docs/_media/example-html-inline.jpg -------------------------------------------------------------------------------- /docs/_media/mcp-discovery-xpost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-mcp-stack/mcp-discovery/HEAD/docs/_media/mcp-discovery-xpost.png -------------------------------------------------------------------------------- /docs/_media/rust-mcp-stack-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-mcp-stack/mcp-discovery/HEAD/docs/_media/rust-mcp-stack-icon.png -------------------------------------------------------------------------------- /docs/examples/print_terminal_template_file.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rust-mcp-stack/mcp-discovery/HEAD/docs/examples/print_terminal_template_file.jpg -------------------------------------------------------------------------------- /tests/fixtures/template_files/html-template.html: -------------------------------------------------------------------------------- 1 | 2 | {{> title-version prefix="
{{{this.param_name}}} : {{{tool_param_type
12 | this.param_type}}}| 8 | | Prompt Name | 9 |Description | 10 |
|---|---|---|
| {{plus_one @index}}. | 16 |
17 | {{{this.name}}}
18 | |
19 | {{{format_text this.description " " "['``']"}}} |
20 |
| 8 | | Prompt Name | 9 |Description | 10 |
|---|---|---|
| {{plus_one @index}}. | 16 |
17 | {{{this.name}}}
18 | |
19 | {{{format_text this.description " " "['``']"}}} |
20 |
| 8 | | Resource Name | 9 |Uri | 10 |Description | 11 |
|---|---|---|---|
| {{plus_one @index}}. | 17 |
18 | {{this.name}}
19 | |
20 | 21 | {{this.uri}} {{#if this.mimeType}}({{{this.mimeType}}}){{/if}} 22 | | 23 |{{{format_text this.description " " "['``']"}}} |
24 |
| Tools | 5 |Prompts | 6 |Resources | 7 |Logging | 8 |Completions | 9 |Experimental | 10 |
|---|---|---|---|---|---|
| {{{capability_tag "Tools" capabilities.tools (len tools)}}} | 15 |{{{capability_tag "Prompts" capabilities.prompts (len prompts)}}} | 16 |{{{capability_tag "Resources" capabilities.resources (len resources)}}} | 17 |{{{capability_tag "Logging" capabilities.logging null}}} | 18 |{{{capability_tag "Completions" capabilities.completions null}}} | 19 |{{{capability_tag "Experimental" capabilities.experimental null}}} | 20 |
| 8 | | Name | 9 |Uri Template | 10 |Description | 11 |
|---|---|---|---|
| {{plus_one @index}}. | 17 |
18 | {{this.name}}
19 | |
20 | 21 | {{this.uriTemplate}} {{#if this.mimeType}}({{{this.mimeType}}}){{/if}} 22 | | 23 |{{{format_text this.description " " "['``']"}}} |
24 |
| 8 | | Resource Name | 9 |Uri | 10 |Description | 11 |
|---|---|---|---|
| {{plus_one @index}}. | 17 |
18 | {{this.name}}
19 | |
20 | 21 | {{this.uri}} {{#if this.mimeType}}({{{this.mimeType}}}){{/if}} 22 | | 23 |{{{format_text this.description " " "['``']"}}} |
24 |
| 8 | | Name | 9 |Uri Template | 10 |Description | 11 |
|---|---|---|---|
| {{plus_one @index}}. | 17 |
18 | {{this.name}}
19 | |
20 | 21 | {{this.uriTemplate}} {{#if this.mimeType}}({{{this.mimeType}}}){{/if}} 22 | | 23 |{{{format_text this.description " " "['``']"}}} |
24 |
| 8 | | Tool Name | 9 |Description | 10 |Inputs | 11 |
|---|---|---|---|
| {{plus_one @index}}. | 17 |
18 | {{{this.name}}}
19 | |
20 | {{{format_text this.description " " "['``']"}}} |
21 |
22 |
|
29 |
| 8 | | Tool Name | 9 |Description | 10 |Inputs | 11 |
|---|---|---|---|
| {{plus_one @index}}. | 17 |
18 | {{{this.name}}}
19 | |
20 | {{{format_text this.description " " "['``']"}}} |
21 |
22 |
|
29 |
| Tools | 23 |Prompts | 24 |Resources | 25 |Logging | 26 |Completions | 27 |Experimental | 28 |
|---|---|---|---|---|---|
| 🟢 Tools (10) | 33 |🟢 Prompts (3) | 34 |🟢 Resources (10) | 35 |🟢 Logging | 36 |🟢 Completions | 37 |🔴 Experimental | 38 |
a : numberb : numberincludeImage : booleanmessageType : stringmessage : stringresourceId : numberduration : numbersteps : numbermaxTokens : numberprompt : stringa : numberb : numberincludeImage : booleanmessageType : stringmessage : stringresourceId : numberduration : numbersteps : numbermaxTokens : numberprompt : string
100 |
101 | > You can execute the mcp-discovery update command whenever you need to refresh the file with the latest MCP Server capabilities.
102 |
--------------------------------------------------------------------------------
/docs/examples/create-md-plain.md:
--------------------------------------------------------------------------------
1 | ## example-servers/everything 1.0.0
2 | | 🟢 Tools (10) | 🟢 Prompts (3) | 🟢 Resources (10) | 🟢 Logging | 🟢 Completions | 🔴 Experimental |
3 | | --- | --- | --- | --- | --- | --- |
4 |
5 | ## 🛠️ Tools (10)
6 |
7 |
8 | - **add**
9 | - Adds two numbers
10 | - **Inputs:**
11 | - a : numberb : numberincludeImage : booleanmessageType : error|success|debugmessage : stringcount : numberresourceId : numberduration : numbersteps : numbermaxTokens : numberprompt : stringlocation : stringa : numberb : numberincludeImage : booleanmessageType : error|success|debugmessage : stringcount : numberresourceId : numberduration : numbersteps : numbermaxTokens : numberprompt : stringlocation : string\` or `'` — in `` tags for HTML formatting (e.g., turning 'param' into `param`).
47 |
48 | This helper is especially useful for formatting capability descriptions in web documentation, markdown previews, or any UI where readable line breaks and inline code styling are needed.
49 |
50 | The `code_wrap_chars` parameter (last parameter of the helper function) defines pairs of characters that will wrap inline code blocks and get converted to ... in the output.
51 |
52 | You must pass a string made up of an even number of characters, where each two characters form one pair:
53 |
54 | The first character is the opening delimiter
55 | The last character is the closing delimiter
56 |
57 | | Input | Effect |
58 | | -------- | -------------------------------------- |
59 | | `"[]"` | Matches `[code]` → `code` |
60 | | `"''"` | Matches `'code'` → `code` |
61 | | `"['']"` | Matches both `[code]` and `'code'` |
62 |
63 | Example:
64 |
65 | ```hbs
66 | {{format_text "Each entry includes 'name', `type` , and 'children' for directories." "
" "'``'" }}
67 | ```
68 |
69 | Output text:
70 |
71 | ```md
72 | Each entry includes name, type , and children for directories.
73 | ```
74 |
75 | Rendered Output:
76 |
77 | Each entry includes name, type , and children for directories.
78 |
79 | ### `capability`
80 |
81 | This helper formats a capability with an optional count and a boolean indicator based on whether the capability is supported.
82 |
83 | Example:
84 |
85 | ```hbs
86 | {{capability 'Feature A' true 5}}
87 | {{capability 'Feature B' false 10}}
88 | ```
89 |
90 | Output:
91 |
92 | ```md
93 | 🟢 Feature A (5)
94 | 🔴 Feature B
95 | ```
96 |
97 | ### `capability_tag`
98 |
99 | Similar to `capability` , this helper formats a capability tag depending on whether the capability is supported, adding an optional count and formatting it with an indicator.
100 |
101 | > Note: The output of this helper contains HTML tags, so it is intended for use in markdown or HTML files.
102 |
103 | Example:
104 |
105 | ```hbs
106 | {{capability_tag 'Feature A' true 5}}
107 | {{capability_tag 'Feature B' false 0}}
108 | {{capability_tag 'Feature C' true null}}
109 | ```
110 |
111 | Output:
112 |
113 | ```md
114 | 🟢 Feature A (5)
115 | 🔴 Feature B
116 | 🟢 Feature C
117 | ```
118 |
119 | ### `capability_title`
120 |
121 | This helper will format a title with a count if present, and optionally add an underline based on the with_underline flag.
122 |
123 | Example:
124 |
125 | ```hbs
126 | {{capability_title 'Feature A' 5 true}}
127 |
128 | {{capability_title 'Feature B' 10 false}}
129 | ```
130 |
131 | Output:
132 |
133 | ```md
134 | Feature A(5)
135 | ─────────────
136 |
137 | Feature B(10)
138 | ```
139 |
140 | ### `tool_param_type`
141 |
142 | This helper converts a tool parameter type (ParamTypes) into a string. Here's how you'd use it in your template:
143 |
144 | Example:
145 |
146 | ```hbs
147 | {{#each tools.1.params}}
148 |
149 | {{tools.0.param_name}}
150 | :
151 | {{{tool_param_type this.param_type}}}
152 |
153 | {{/each}}
154 | ```
155 |
156 | Output:
157 |
158 | ```md
159 | includeImage : boolean
160 | messageType : string
161 | ```
162 |
163 | > The output may vary depending on the MCP server that is launched.
164 |
165 | ### `replace_regex`
166 |
167 | Replaces all occurrences in a string that match a given regular expression with a specified replacement string.
168 |
169 | This helper is useful for dynamic text transformations within templates, such as cleaning up labels, formatting values, or removing unwanted prefixes.
170 |
171 | Example:
172 |
173 | _Wraps words enclosed in single quotes with `` and `` tags._
174 |
175 | ```hbs
176 | {{{replace_regex
177 | (replace_regex
178 | "Each entry includes 'name', 'type' ." "'([\\w\\-\\_]+)'" '$1'
179 | )
180 | }}}
181 | ```
182 |
183 | Output:
184 |
185 | ```md
186 | Each entry includes name, type .
187 | ```
188 |
189 | ### `json`
190 |
191 | A Handlebars helper that converts an object into a JSON string. If the second parameter is 'pretty', the output will be formatted with indentation for readability.
192 |
193 | Example:
194 |
195 |
196 | _Produces a JSON string that represents the list of tools._
197 |
198 | ```hbs
199 | {{json this.tools}}
200 | ```
201 |
202 | _Produces a formatted JSON string that represents the list of tools._
203 |
204 | ```hbs
205 | {{json this.tools}}
206 | ```
207 |
208 | _Outputs the complete payload as a pretty-printed JSON string._
209 |
210 | ```hbs
211 | {{json this 'pretty'}}
212 | ```
213 |
214 | 📎 output json
215 |
--------------------------------------------------------------------------------
/docs/guide/command-examples.md:
--------------------------------------------------------------------------------
1 | # Command Examples
2 |
3 | Below is a list of sample commands showcasing various options available in the mcp-discovery CLI.
4 |
5 | _These examples use the `@modelcontextprotocol/server-everything` example server for demonstration._
6 |
7 | ## Print
8 |
9 | #### ▪️ Print MCP Server capabilities to the terminal:
10 |
11 | ```bash
12 | mcp-discovery -- npx -y @modelcontextprotocol/server-everything
13 | ```
14 |
15 | 📎 view the output
16 |
17 | ---
18 |
19 | #### ▪️ Print MCP Server capabilities to the terminal, with a custom template:
20 |
21 | ```bash
22 | mcp-discovery --template-file sample_txt_template.txt -- npx -y @modelcontextprotocol/server-everything
23 | ```
24 |
25 | 📎 view the output |
26 | 📎 sample_txt_template.txt
27 |
28 | ---
29 |
30 | #### ▪️ Print MCP Server capabilities to the terminal, with a template string:
31 |
32 | ```bash
33 | mcp-discovery --template-string "Server Name: {{name}}, Server Version: {{version}}" -- npx -y @modelcontextprotocol/server-everything
34 | ```
35 |
36 | **Output:**
37 |
38 | ```
39 | Server Name: example-servers/everything, Server Version: 1.0.0
40 | ```
41 |
42 | ---
43 |
44 | #### ▪️ Print MCP Server capabilities to the terminal as JSON:
45 |
46 | We use the `json` helper function in a template string. It accepts an object and optional second parameter with value of 'pretty' for a formatted output:
47 |
48 |
49 | - Print the Full MCP Server Capabilities to the Terminal in JSON Format:
50 | ```bash
51 | mcp-discovery --template-string "{{{json this}}}" -- npx -y @modelcontextprotocol/server-everything
52 | ```
53 | 📎 printed json
54 |
55 | - Print MCP Server tools to the Terminal in pretty-formatted JSON :
56 | ```bash
57 | mcp-discovery --template-string "{{{json this.tools}}}" -- npx -y @modelcontextprotocol/server-everything
58 | ```
59 |
60 |
61 |
62 | ---
63 |
64 | ## Create
65 |
66 | #### Create a Markdown file (\*.md) describing MCP Server capabilities:
67 |
68 | ```bash
69 | mcp-discovery create -f create-md.md -- npx -y @modelcontextprotocol/server-everything
70 | ```
71 |
72 | 📎 view generated file
73 |
74 | ---
75 |
76 | #### Create a Markdown file (\*.md) using `md-plain` template:
77 |
78 | `md-plain` generates plain markdown using text lists rather than tables.
79 |
80 | ```bash
81 | mcp-discovery create -f create-md-plain.md --template md-plain -- npx -y @modelcontextprotocol/server-everything
82 | ```
83 |
84 | 📎 view generated file
85 |
86 | ---
87 |
88 | #### Create a HTML file (\*.html) describing MCP Server capabilities:
89 |
90 | ```bash
91 | mcp-discovery create -f server-info.html -- npx -y @modelcontextprotocol/server-everything
92 | ```
93 |
94 | 📎 view generated file
95 |
96 | #### Create a TEXT file (\*.txt) describing MCP Server capabilities:
97 |
98 | ```bash
99 | mcp-discovery create -f capabilities.txt -- npx -y @modelcontextprotocol/server-everything
100 | ```
101 |
102 | 📎 view generated file
103 |
104 |
105 | ## Update
106 |
107 | To update files, you need to annotate a [render block](./guide/mcp-discovery-markers.md) within the target file where the MCP server capabilities should be inserted.
108 | Refer to the ["Update Regions with Markers"](./guide/mcp-discovery-markers.md) page for details on how to define render blocks and optional inline template sections.
109 |
110 | #### Update a Markdown file with MCP Server capabilities:
111 |
112 | ```bash
113 | mcp-discovery update -f update-md.md -- npx -y @modelcontextprotocol/server-everything
114 | ```
115 |
116 | Below is a typical md file containing a render block marked with `` and ``.
117 | MCP Discovery will overwrite the content between these markers with the latest generated output.
118 |
119 | ```md
120 | # Server Info and Capabilities
121 |
122 |
123 |
124 | ```
125 |
126 | 📎 view updated file
127 |
128 | ---
129 |
130 | #### Update a Markdown file using `md-plain` template:
131 |
132 | We can either pass the --template md-plain argument to the CLI or specify md-plain as a property on the line.
133 |
134 | ```bash
135 | mcp-discovery update -f update-md-plain.md -- npx -y @modelcontextprotocol/server-everything
136 | ```
137 |
138 | Below is a md file containing a render block with `template` property set to `md-plain`:
139 |
140 | ```md
141 | # Server Info and Capabilities
142 |
143 |
144 |
145 | ```
146 |
147 | 📎 view updated file
148 |
149 | ---
150 |
151 | #### Update a Markdown file with an inline template:
152 |
153 | Inline templates should appear between a render block. Refer to the ["Update Regions with Markers"](./guide/mcp-discovery-markers.md) page for details on how to define render blocks and optional inline template sections.
154 |
155 | ```bash
156 | mcp-discovery update -f update-md-inline.md -- npx -y @modelcontextprotocol/server-everything
157 | ```
158 |
159 | Below is an md file with a `render block` and an `inline template`. The `inline template` will be used and preserved when the `mcp-discovery` CLI updates the file.
160 |
161 | ```md
162 | # Server Info and Capabilities
163 |
164 |
165 |
174 |
175 |
176 | ---
177 |
178 | A Footer
179 | ```
180 |
181 | 📎 view updated file
182 |
--------------------------------------------------------------------------------
/docs/examples/json.txt:
--------------------------------------------------------------------------------
1 | {
2 | "capabilities": {
3 | "experimental": false,
4 | "logging": true,
5 | "prompts": true,
6 | "resources": true,
7 | "tools": true
8 | },
9 | "name": "example-servers/everything",
10 | "prompts": [
11 | {
12 | "description": "A prompt without arguments",
13 | "name": "simple_prompt"
14 | },
15 | {
16 | "arguments": [
17 | {
18 | "description": "Temperature setting",
19 | "name": "temperature",
20 | "required": true
21 | },
22 | {
23 | "description": "Output style",
24 | "name": "style",
25 | "required": false
26 | }
27 | ],
28 | "description": "A prompt with arguments",
29 | "name": "complex_prompt"
30 | },
31 | {
32 | "arguments": [
33 | {
34 | "description": "Resource ID to include (1-100)",
35 | "name": "resourceId",
36 | "required": true
37 | }
38 | ],
39 | "description": "A prompt that includes an embedded resource reference",
40 | "name": "resource_prompt"
41 | }
42 | ],
43 | "resource_templates": [
44 | {
45 | "description": "A static resource with a numeric ID",
46 | "name": "Static Resource",
47 | "uriTemplate": "test://static/resource/{id}"
48 | }
49 | ],
50 | "resources": [
51 | {
52 | "mimeType": "text/plain",
53 | "name": "Resource 1",
54 | "uri": "test://static/resource/1"
55 | },
56 | {
57 | "mimeType": "application/octet-stream",
58 | "name": "Resource 2",
59 | "uri": "test://static/resource/2"
60 | },
61 | {
62 | "mimeType": "text/plain",
63 | "name": "Resource 3",
64 | "uri": "test://static/resource/3"
65 | },
66 | {
67 | "mimeType": "application/octet-stream",
68 | "name": "Resource 4",
69 | "uri": "test://static/resource/4"
70 | },
71 | {
72 | "mimeType": "text/plain",
73 | "name": "Resource 5",
74 | "uri": "test://static/resource/5"
75 | },
76 | {
77 | "mimeType": "application/octet-stream",
78 | "name": "Resource 6",
79 | "uri": "test://static/resource/6"
80 | },
81 | {
82 | "mimeType": "text/plain",
83 | "name": "Resource 7",
84 | "uri": "test://static/resource/7"
85 | },
86 | {
87 | "mimeType": "application/octet-stream",
88 | "name": "Resource 8",
89 | "uri": "test://static/resource/8"
90 | },
91 | {
92 | "mimeType": "text/plain",
93 | "name": "Resource 9",
94 | "uri": "test://static/resource/9"
95 | },
96 | {
97 | "mimeType": "application/octet-stream",
98 | "name": "Resource 10",
99 | "uri": "test://static/resource/10"
100 | }
101 | ],
102 | "tools": [
103 | {
104 | "description": "Adds two numbers",
105 | "name": "add",
106 | "params": [
107 | {
108 | "param_description": "First number",
109 | "param_name": "a",
110 | "param_type": {
111 | "Primitive": "number"
112 | },
113 | "required": true
114 | },
115 | {
116 | "param_description": "Second number",
117 | "param_name": "b",
118 | "param_type": {
119 | "Primitive": "number"
120 | },
121 | "required": true
122 | }
123 | ]
124 | },
125 | {
126 | "description": "Demonstrates how annotations can be used to provide metadata about content",
127 | "name": "annotatedMessage",
128 | "params": [
129 | {
130 | "param_description": "Whether to include an example image",
131 | "param_name": "includeImage",
132 | "param_type": {
133 | "Primitive": "boolean"
134 | },
135 | "required": true
136 | },
137 | {
138 | "param_description": "Type of message to demonstrate different annotation patterns",
139 | "param_name": "messageType",
140 | "param_type": {
141 | "Primitive": "string"
142 | },
143 | "required": true
144 | }
145 | ]
146 | },
147 | {
148 | "description": "Echoes back the input",
149 | "name": "echo",
150 | "params": [
151 | {
152 | "param_description": "Message to echo",
153 | "param_name": "message",
154 | "param_type": {
155 | "Primitive": "string"
156 | },
157 | "required": true
158 | }
159 | ]
160 | },
161 | {
162 | "description": "Returns a resource reference that can be used by MCP clients",
163 | "name": "getResourceReference",
164 | "params": [
165 | {
166 | "param_description": "ID of the resource to reference (1-100)",
167 | "param_name": "resourceId",
168 | "param_type": {
169 | "Primitive": "number"
170 | },
171 | "required": true
172 | }
173 | ]
174 | },
175 | {
176 | "description": "Returns the MCP_TINY_IMAGE",
177 | "name": "getTinyImage",
178 | "params": []
179 | },
180 | {
181 | "description": "Demonstrates a long running operation with progress updates",
182 | "name": "longRunningOperation",
183 | "params": [
184 | {
185 | "param_description": "Duration of the operation in seconds",
186 | "param_name": "duration",
187 | "param_type": {
188 | "Primitive": "number"
189 | },
190 | "required": true
191 | },
192 | {
193 | "param_description": "Number of steps in the operation",
194 | "param_name": "steps",
195 | "param_type": {
196 | "Primitive": "number"
197 | },
198 | "required": true
199 | }
200 | ]
201 | },
202 | {
203 | "description": "Prints all environment variables, helpful for debugging MCP server configuration",
204 | "name": "printEnv",
205 | "params": []
206 | },
207 | {
208 | "description": "Samples from an LLM using MCP's sampling feature",
209 | "name": "sampleLLM",
210 | "params": [
211 | {
212 | "param_description": "Maximum number of tokens to generate",
213 | "param_name": "maxTokens",
214 | "param_type": {
215 | "Primitive": "number"
216 | },
217 | "required": true
218 | },
219 | {
220 | "param_description": "The prompt to send to the LLM",
221 | "param_name": "prompt",
222 | "param_type": {
223 | "Primitive": "string"
224 | },
225 | "required": true
226 | }
227 | ]
228 | }
229 | ],
230 | "version": "1.0.0"
231 | }
232 |
--------------------------------------------------------------------------------
/src/std_output.rs:
--------------------------------------------------------------------------------
1 | use colored::Colorize;
2 | use std::io::{self, Write};
3 | use unicode_width::UnicodeWidthStr;
4 |
5 | use crate::{McpServerInfo, utils::boolean_indicator};
6 |
7 | const SUMMARY_HEADER_SIZE: usize = 50;
8 |
9 | /// Function to print a list of items to the given writer `w`.
10 | /// Each item is printed with an index, key and value.
11 | pub fn print_list(mut w: W, list_items: Vec<(String, String)>) -> io::Result<()> {
12 | for (index, (key, val)) in list_items.iter().enumerate() {
13 | writeln!(
14 | w,
15 | "{}. {}: {}",
16 | (index + 1).to_string().bold().cyan(),
17 | key.bold().cyan(),
18 | val
19 | )?;
20 | }
21 | Ok(())
22 | }
23 |
24 | /// Function to print a header table with a title and table size to the writer `w`.
25 | /// The header includes a top border, the title in the center, and a bottom border.
26 | pub fn print_header(mut w: W, title: &str, table_size: usize) -> io::Result<()> {
27 | writeln!(w, "{}", table_top(table_size))?;
28 | writeln!(w, "{}", table_content(table_size, title))?;
29 | writeln!(w, "{}", table_bottom(table_size))?;
30 | Ok(())
31 | }
32 |
33 | /// Generates the top border for the table based on the given width (`width`).
34 | /// Uses a character `─` for the border.
35 | pub fn table_top(width: usize) -> String {
36 | format!("┌{:─ String {
41 | format!("└{:─ String {
47 | let title_length = strip_ansi_escapes::strip_str(content).width();
48 | let l_pad = (((width) as f32 / 2.0) - (title_length as f32 / 2.0)).floor() as usize;
49 | let r_pad = width - l_pad - title_length;
50 | format!("│{}{}{}│", " ".repeat(l_pad), content, " ".repeat(r_pad))
51 | }
52 |
53 | /// Function to print a formatted summary of the server information.
54 | pub fn print_summary(mut w: W, server_info: &McpServerInfo) -> io::Result {
55 | let server_name = format!("{} {}", server_info.name, server_info.version);
56 | let title_length = server_name.width(); // Use display width for accuracy
57 | let table_size = SUMMARY_HEADER_SIZE.max(title_length + 4); // 2 padding on each side
58 |
59 | writeln!(w, "{}", table_top(table_size))?;
60 | writeln!(
61 | w,
62 | "{}",
63 | table_content(table_size, &server_name.bold().cyan().to_string())
64 | )?;
65 | writeln!(w, "{}", table_content(table_size, ""))?;
66 |
67 | let caps = &server_info.capabilities;
68 | let lines = [
69 | format!(
70 | "{} Tools {} Prompts {} Resources {} Logging",
71 | boolean_indicator(caps.tools),
72 | boolean_indicator(caps.prompts),
73 | boolean_indicator(caps.resources),
74 | boolean_indicator(caps.logging),
75 | ),
76 | format!(
77 | "{} Completions {} Experimental",
78 | boolean_indicator(caps.completions),
79 | boolean_indicator(caps.experimental)
80 | ),
81 | ];
82 |
83 | let adjust = lines[0].width().saturating_sub(lines[1].width());
84 | writeln!(w, "{}", table_content(table_size, &lines[0]))?;
85 | writeln!(
86 | w,
87 | "{}",
88 | table_content(table_size, &format!("{}{}", &lines[1], " ".repeat(adjust)))
89 | )?;
90 |
91 | writeln!(w, "{}", table_bottom(table_size))?;
92 | Ok(table_size)
93 | }
94 |
95 | #[cfg(test)]
96 | mod tests {
97 | use crate::McpCapabilities;
98 |
99 | use super::*;
100 |
101 | #[test]
102 | fn test_table_top_bottom() {
103 | assert_eq!(table_top(5), "┌─────┐");
104 | assert_eq!(table_bottom(5), "└─────┘");
105 | }
106 |
107 | #[test]
108 | fn test_table_content_centering() {
109 | let result = table_content(10, "Hi");
110 | assert!(result.starts_with("│"));
111 | assert!(result.ends_with("│"));
112 | assert_eq!(strip_ansi_escapes::strip_str(&result).width(), 12); // includes borders
113 | assert!(result.contains("Hi"));
114 | }
115 |
116 | #[test]
117 | fn test_print_list() {
118 | let items = vec![
119 | ("Item1".to_string(), "Value1".to_string()),
120 | ("Item2".to_string(), "Value2".to_string()),
121 | ];
122 |
123 | let mut buffer = Vec::new();
124 | print_list(&mut buffer, items).unwrap();
125 |
126 | let output = String::from_utf8(buffer).unwrap();
127 | let output = strip_ansi_escapes::strip_str(output);
128 |
129 | assert!(output.contains("1. Item1: Value1"));
130 | assert!(output.contains("2. Item2: Value2"));
131 | }
132 |
133 | #[test]
134 | fn test_print_header_structure() {
135 | let mut buffer = Vec::new();
136 | print_header(&mut buffer, "My Header", 20).unwrap();
137 |
138 | // Create the String first
139 | let output = String::from_utf8(buffer).unwrap();
140 |
141 | // Now borrow the String with `lines()`
142 | let lines: Vec<&str> = output.lines().collect();
143 |
144 | assert_eq!(lines.len(), 3);
145 | assert!(lines[0].starts_with("┌") && lines[0].ends_with("┐"));
146 | assert!(lines[2].starts_with("└") && lines[2].ends_with("┘"));
147 | assert!(lines[1].contains("My Header"));
148 | }
149 |
150 | #[test]
151 | fn test_print_summary_layout() {
152 | let info = McpServerInfo {
153 | name: "MyApp".to_string(),
154 | version: "0.9".to_string(),
155 | capabilities: McpCapabilities {
156 | tools: true,
157 | prompts: false,
158 | resources: false,
159 | logging: true,
160 | experimental: false,
161 | completions: true,
162 | },
163 | tools: None,
164 | prompts: None,
165 | resources: None,
166 | resource_templates: None,
167 | };
168 |
169 | let mut buffer = Vec::new();
170 | let size = print_summary(&mut buffer, &info).unwrap();
171 |
172 | let output = String::from_utf8(buffer).unwrap();
173 | assert!(output.contains("MyApp 0.9"));
174 | assert!(size >= 44);
175 | }
176 |
177 | #[test]
178 | fn test_print_to_stdout() {
179 | let items = vec![
180 | ("Tool1".to_string(), "Enabled".to_string()),
181 | ("Tool2".to_string(), "Disabled".to_string()),
182 | ];
183 |
184 | // Print directly to stdout
185 | print_list(io::stdout(), items).unwrap();
186 | }
187 |
188 | #[test]
189 | fn test_print_summary_to_stdout() {
190 | let info = McpServerInfo {
191 | name: "SampleServer".to_string(),
192 | version: "1.1".to_string(),
193 | capabilities: McpCapabilities {
194 | tools: true,
195 | prompts: true,
196 | resources: true,
197 | logging: false,
198 | experimental: false,
199 | completions: true,
200 | },
201 | tools: None,
202 | prompts: None,
203 | resources: None,
204 | resource_templates: None,
205 | };
206 |
207 | // Print directly to stdout
208 | print_summary(io::stdout(), &info).unwrap();
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/tests/fixtures/everything-1.0.0.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example-servers/everything",
3 | "version": "1.0.0",
4 | "capabilities": {
5 | "tools": true,
6 | "prompts": true,
7 | "resources": true,
8 | "logging": true,
9 | "experimental": false
10 | },
11 | "tools": [
12 | {
13 | "name": "add",
14 | "description": "Adds two numbers",
15 | "params": [
16 | {
17 | "param_name": "a",
18 | "param_type": {
19 | "Primitive": "number"
20 | },
21 | "param_description": "First number",
22 | "required": true
23 | },
24 | {
25 | "param_name": "b",
26 | "param_type": {
27 | "Primitive": "number"
28 | },
29 | "param_description": "Second number",
30 | "required": true
31 | }
32 | ]
33 | },
34 | {
35 | "name": "annotatedMessage",
36 | "description": "Demonstrates how annotations can be used to provide metadata about content",
37 | "params": [
38 | {
39 | "param_name": "includeImage",
40 | "param_type": {
41 | "Primitive": "boolean"
42 | },
43 | "param_description": "Whether to include an example image",
44 | "required": true
45 | },
46 | {
47 | "param_name": "messageType",
48 | "param_type": {
49 | "Primitive": "string"
50 | },
51 | "param_description": "Type of message to demonstrate different annotation patterns",
52 | "required": true
53 | }
54 | ]
55 | },
56 | {
57 | "name": "echo",
58 | "description": "Echoes back the input",
59 | "params": [
60 | {
61 | "param_name": "message",
62 | "param_type": {
63 | "Primitive": "string"
64 | },
65 | "param_description": "Message to echo",
66 | "required": true
67 | }
68 | ]
69 | },
70 | {
71 | "name": "getResourceReference",
72 | "description": "Returns a resource reference that can be used by MCP clients",
73 | "params": [
74 | {
75 | "param_name": "resourceId",
76 | "param_type": {
77 | "Primitive": "number"
78 | },
79 | "param_description": "ID of the resource to reference (1-100)",
80 | "required": true
81 | }
82 | ]
83 | },
84 | {
85 | "name": "getTinyImage",
86 | "description": "Returns the MCP_TINY_IMAGE",
87 | "params": []
88 | },
89 | {
90 | "name": "longRunningOperation",
91 | "description": "Demonstrates a long running operation with progress updates",
92 | "params": [
93 | {
94 | "param_name": "duration",
95 | "param_type": {
96 | "Primitive": "number"
97 | },
98 | "param_description": "Duration of the operation in seconds",
99 | "required": true
100 | },
101 | {
102 | "param_name": "steps",
103 | "param_type": {
104 | "Primitive": "number"
105 | },
106 | "param_description": "Number of steps in the operation",
107 | "required": true
108 | }
109 | ]
110 | },
111 | {
112 | "name": "printEnv",
113 | "description": "Prints all environment variables, helpful for debugging MCP server configuration",
114 | "params": []
115 | },
116 | {
117 | "name": "sampleLLM",
118 | "description": "Samples from an LLM using MCP's sampling feature",
119 | "params": [
120 | {
121 | "param_name": "maxTokens",
122 | "param_type": {
123 | "Primitive": "number"
124 | },
125 | "param_description": "Maximum number of tokens to generate",
126 | "required": true
127 | },
128 | {
129 | "param_name": "prompt",
130 | "param_type": {
131 | "Primitive": "string"
132 | },
133 | "param_description": "The prompt to send to the LLM",
134 | "required": true
135 | }
136 | ]
137 | }
138 | ],
139 | "prompts": [
140 | {
141 | "description": "A prompt without arguments",
142 | "name": "simple_prompt"
143 | },
144 | {
145 | "arguments": [
146 | {
147 | "description": "Temperature setting",
148 | "name": "temperature",
149 | "required": true
150 | },
151 | {
152 | "description": "Output style",
153 | "name": "style",
154 | "required": false
155 | }
156 | ],
157 | "description": "A prompt with arguments",
158 | "name": "complex_prompt"
159 | },
160 | {
161 | "arguments": [
162 | {
163 | "description": "Resource ID to include (1-100)",
164 | "name": "resourceId",
165 | "required": true
166 | }
167 | ],
168 | "description": "A prompt that includes an embedded resource reference",
169 | "name": "resource_prompt"
170 | }
171 | ],
172 | "resources": [
173 | {
174 | "mimeType": "text/plain",
175 | "name": "Resource 1",
176 | "uri": "test://static/resource/1"
177 | },
178 | {
179 | "mimeType": "application/octet-stream",
180 | "name": "Resource 2",
181 | "uri": "test://static/resource/2"
182 | },
183 | {
184 | "mimeType": "text/plain",
185 | "name": "Resource 3",
186 | "uri": "test://static/resource/3"
187 | },
188 | {
189 | "mimeType": "application/octet-stream",
190 | "name": "Resource 4",
191 | "uri": "test://static/resource/4"
192 | },
193 | {
194 | "mimeType": "text/plain",
195 | "name": "Resource 5",
196 | "uri": "test://static/resource/5"
197 | },
198 | {
199 | "mimeType": "application/octet-stream",
200 | "name": "Resource 6",
201 | "uri": "test://static/resource/6"
202 | },
203 | {
204 | "mimeType": "text/plain",
205 | "name": "Resource 7",
206 | "uri": "test://static/resource/7"
207 | },
208 | {
209 | "mimeType": "application/octet-stream",
210 | "name": "Resource 8",
211 | "uri": "test://static/resource/8"
212 | },
213 | {
214 | "mimeType": "text/plain",
215 | "name": "Resource 9",
216 | "uri": "test://static/resource/9"
217 | },
218 | {
219 | "mimeType": "application/octet-stream",
220 | "name": "Resource 10",
221 | "uri": "test://static/resource/10"
222 | }
223 | ],
224 | "resource_templates": [
225 | {
226 | "description": "A static resource with a numeric ID",
227 | "name": "Static Resource",
228 | "uriTemplate": "test://static/resource/{id}"
229 | }
230 | ]
231 | }
--------------------------------------------------------------------------------
/docs/quickstart.md:
--------------------------------------------------------------------------------
1 | # Quick Start
2 |
3 | ## Install
4 |
5 |
6 |
7 | #### **Shell script**
8 |
9 |
10 |
11 | ```sh
12 | curl --proto '=https' --tlsv1.2 -LsSf https://github.com/rust-mcp-stack/mcp-discovery/releases/download/v0.2.2/mcp-discovery-installer.sh | sh
13 | ```
14 |
15 | #### **PowerShell script**
16 |
17 | ```sh
18 | powershell -ExecutionPolicy Bypass -c "irm https://github.com/rust-mcp-stack/mcp-discovery/releases/download/v0.2.2/mcp-discovery-installer.ps1 | iex"
19 | ```
20 |
21 |
22 |
23 | #### **Homebrew**
24 |
25 | ```sh
26 | brew install rust-mcp-stack/tap/mcp-discovery
27 | ```
28 |
29 | #### **Cargo**
30 |
31 | ```sh
32 | cargo install mcp-discovery --locked
33 | ```
34 |
35 | #### **NPM**
36 |
37 | ```sh
38 | npm i -g @rustmcp/mcp-discovery@latest
39 | ```
40 |
41 | #### **Download Binaries**
42 |
43 |
44 |
45 |
46 | File
47 | Platform
48 | Checksum
49 |
50 |
51 |
52 |
53 |
54 |
55 | mcp-discovery-aarch64-apple-darwin.tar.gz
56 |
57 |
58 | Apple Silicon macOS
59 |
60 |
61 | checksum
62 |
63 |
64 |
65 |
66 |
67 |
68 | mcp-discovery-x86_64-apple-darwin.tar.gz
69 |
70 |
71 | Intel macOS
72 |
73 |
74 | checksum
75 |
76 |
77 |
78 |
79 |
80 |
81 | mcp-discovery-x86_64-pc-windows-msvc.zip
82 |
83 |
84 | x64 Windows (zip)
85 |
86 |
87 | checksum
88 |
89 |
90 |
91 |
92 |
93 |
94 | mcp-discovery-x86_64-pc-windows-msvc.msi
95 |
96 |
97 | x64 Windows (msi)
98 |
99 |
100 | checksum
101 |
102 |
103 |
104 |
105 |
106 |
107 | mcp-discovery-aarch64-unknown-linux-gnu.tar.gz
108 |
109 |
110 | ARM64 Linux
111 |
112 |
113 | checksum
114 |
115 |
116 |
117 |
118 |
119 |
120 | mcp-discovery-x86_64-unknown-linux-gnu.tar.gz
121 |
122 |
123 | x64 Linux
124 |
125 |
126 | checksum
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | ### Usage
136 |
137 | ```sh
138 | Usage: mcp-discovery [OPTIONS] -- ...
139 | mcp-discovery
140 |
141 | Commands:
142 | print Displays MCP server capability details in the terminal
143 | create Creates a file with MCP server capability details
144 | update Updates a file by adding MCP server capability information between specified markers
145 | help Print this message or the help of the given subcommand(s)
146 |
147 | Arguments:
148 | ... Command and arguments to launch the MCP server
149 |
150 | Options:
151 | -t, --template
152 | Select an output template from the built-in options [possible values: md, md-plain, html, txt]
153 | -p, --template-file
154 | Path to a custom template file written in the Handlebars format
155 | -s, --template-string
156 | Template content provided as a string
157 | -h, --help
158 | Print help
159 | -V, --version
160 | Print version
161 | ```
162 |
163 | ### Example
164 |
165 | Print MCP Server capabilities to the terminal:
166 |
167 | ```sh
168 | mcp-discovery -- npx -y @modelcontextprotocol/server-everything
169 | ```
170 |
171 | ## Subcommands
172 |
173 | - **`print`**: Displays MCP Server capabilities in the terminal.
174 | - **`create`**: Creates a new file with MCP Server capability details.
175 | - **`update`**: Updates an existing file by inserting MCP Server capabilities between specified
176 | markers.
177 |
178 | 👉 Note: If no subcommand is provided, the `print` subcommand will be used by default.
179 |
180 | ### Options ⚙️
181 |
182 | - `-f, --filename `: Used with `create` and `update` commands to specify the output file to generate or modify.
183 | - `-t, --template `: Choose a built-in output template. Options: `md`, `md-plain`, `html`, `txt`.
184 | - `-p, --template-file `: Path to a custom Handlebars template file.
185 | - `-s, --template-string `: Inline Handlebars template provided as a string.
186 | - `-h, --help`: Display help information.
187 | - `-V, --version`: Display the version of `mcp-discovery`.
188 |
189 | 👉 Note: If no template is provided, `mcp-discovery` will automatically select the most suitable built-in template based on the file extension.
190 |
191 | ## Built-in Templates 🧬
192 |
193 | The CLI supports the following built-in output templates:
194 |
195 | - **`md`**: Formatted Markdown that presents MCP Server capabilities in a table format.
196 | - **`md-plain`**: Minimalist Markdown for straightforward output, using plain text instead of tables.
197 | - **`html`**: Structured HTML with basic styling.
198 | - **`txt`**: Plain text for raw, unformatted output.
199 |
200 | ## Custom Templates 🧩
201 |
202 | You can provide custom Handlebars templates in different ways:
203 |
204 | 1. Use the `--template-file` flag to provide a custom template file.
205 | 2. Use the `--template-string` flag to provide a raw Handlebars template directly as a string.
206 | 3. To use an inline template, define it in a file for the `update` command only — this will not function with print or create.
207 |
208 | > Inline templates must be enclosed within designated marker annotations.
209 |
210 | ?> 💡 See [Example Commands](guide/command-examples.md) for CLI usage examples across different configurations and scenarios.
211 |
--------------------------------------------------------------------------------
/src/templates.rs:
--------------------------------------------------------------------------------
1 | use crate::{
2 | McpServerInfo,
3 | error::DiscoveryResult,
4 | render_template,
5 | types::Template,
6 | utils::{find_template_file, line_ending},
7 | };
8 | use std::{
9 | borrow::Cow,
10 | path::{Path, PathBuf},
11 | };
12 |
13 | // Static string constants for built-in template files
14 | const TEMPLATE_MARKDOWN: &str = include_str!("../templates/markdown/markdown_template.md");
15 | const TEMPLATE_HTML: &str = include_str!("../templates/html/html_template.html");
16 | const TEMPLATE_MARKDOWN_PLAIN: &str =
17 | include_str!("../templates/markdown/markdown_plain_template.md");
18 | const TEMPLATE_TEXT: &str = include_str!("../templates/text/text_template.txt");
19 |
20 | pub const TITLE_VERSION: &str = include_str!("../templates/common/title.hbs");
21 | pub const MD_SUMMARY: &str = include_str!("../templates/markdown/summary.hbs");
22 |
23 | // md partials
24 | pub const MD_TOOLS: &str = include_str!("../templates/markdown/md_tools.hbs");
25 | pub const MD_PROMPTS: &str = include_str!("../templates/markdown/md_prompts.hbs");
26 | pub const MD_RESOURCES: &str = include_str!("../templates/markdown/md_resources.hbs");
27 | pub const MD_RESOURCE_TEMPLATES: &str =
28 | include_str!("../templates/markdown/md_resource_templates.hbs");
29 |
30 | // md-plain partials
31 | pub const MD_PLAIN_TOOLS: &str = include_str!("../templates/markdown/md_plain_tools.hbs");
32 | pub const MD_PLAIN_PROMPTS: &str = include_str!("../templates/markdown/md_plain_prompts.hbs");
33 | pub const MD_PLAIN_RESOURCES: &str = include_str!("../templates/markdown/md_plain_resources.hbs");
34 | pub const MD_PLAIN_RESOURCE_TEMPLATES: &str =
35 | include_str!("../templates/markdown/md_plain_resource_templates.hbs");
36 |
37 | // html partials
38 | pub const HTML_SUMMARY: &str = include_str!("../templates/html/html_summary.hbs");
39 | pub const HTML_TOOLS: &str = include_str!("../templates/html/html_tools.hbs");
40 | pub const HTML_PROMPTS: &str = include_str!("../templates/html/html_prompts.hbs");
41 | pub const HTML_RESOURCES: &str = include_str!("../templates/html/html_resources.hbs");
42 | pub const HTML_RESOURCE_TEMPLATES: &str =
43 | include_str!("../templates/html/html_resource_templates.hbs");
44 |
45 | // text partials
46 | pub const TEXT_SUMMARY: &str = include_str!("../templates/text/text_summary.hbs");
47 | pub const TEXT_TOOLS: &str = include_str!("../templates/text/text_tools.hbs");
48 | pub const TEXT_PROMPTS: &str = include_str!("../templates/text/text_prompts.hbs");
49 | pub const TEXT_RESOURCES: &str = include_str!("../templates/text/text_resources.hbs");
50 | pub const TEXT_RESOURCE_TEMPLATES: &str =
51 | include_str!("../templates/text/text_resource_templates.hbs");
52 |
53 | pub static PARTIALS: [(&str, &str); 21] = [
54 | ("title-version", TITLE_VERSION),
55 | ("summary", MD_SUMMARY),
56 | ("md-tools", MD_TOOLS),
57 | ("md-prompts", MD_PROMPTS),
58 | ("md-resources", MD_RESOURCES),
59 | ("md-resource-templates", MD_RESOURCE_TEMPLATES),
60 | ("md-plain-tools", MD_PLAIN_TOOLS),
61 | ("md-plain-prompts", MD_PLAIN_PROMPTS),
62 | ("md-plain-resources", MD_PLAIN_RESOURCES),
63 | ("md-plain-resource-templates", MD_PLAIN_RESOURCE_TEMPLATES),
64 | ("html-summary", HTML_SUMMARY),
65 | ("html-tools", HTML_TOOLS),
66 | ("html-prompts", HTML_PROMPTS),
67 | ("html-resources", HTML_RESOURCES),
68 | ("html-resource-templates", HTML_RESOURCE_TEMPLATES),
69 | ("txt-summary", TEXT_SUMMARY),
70 | ("txt-tools", TEXT_TOOLS),
71 | ("txt-prompts", TEXT_PROMPTS),
72 | ("txt-resources", TEXT_RESOURCES),
73 | ("txt-resource-templates", TEXT_RESOURCE_TEMPLATES),
74 | ("txt-summary", TEXT_SUMMARY),
75 | ];
76 |
77 | /// Struct to hold information about inline templates
78 | /// Used for templates embedded within other content with specific markers
79 | #[derive(Debug)]
80 | pub struct InlineTemplateInfo {
81 | pub template: String,
82 | pub marker_start: String,
83 | pub marker_end: String,
84 | }
85 |
86 | /// Enum representing different types of output templates
87 | /// Used to specify the type of template to render
88 | #[derive(Debug)]
89 | pub enum OutputTemplate {
90 | /// Markdown template (generates tables)
91 | Md,
92 | /// HTML template
93 | Html,
94 | /// Plain text template
95 | Txt,
96 | /// MD Plain template
97 | MdPlain,
98 | /// Custom template from file
99 | CustomTemplate(PathBuf),
100 | /// Template from string
101 | TemplateString(String),
102 | /// Inline template with markers
103 | InlineTemplate(InlineTemplateInfo),
104 | // Print to the terminal
105 | None,
106 | }
107 |
108 | impl OutputTemplate {
109 | /// Creates an OutputTemplate from a file path
110 | /// Resolves the template file path relative to a base file if provided
111 | /// Returns a DiscoveryResult containing the CustomTemplate variant
112 | pub fn from_file(template_file: &Path, base_file: Option<&PathBuf>) -> DiscoveryResult {
113 | let actual_template_file = find_template_file(template_file, base_file)?;
114 | Ok(OutputTemplate::CustomTemplate(actual_template_file))
115 | }
116 |
117 | /// Returns the content of the template as a Cow string
118 | pub fn content(&self) -> Cow<'_, str> {
119 | match &self {
120 | // Return borrowed references to static templates
121 | Self::Md => Cow::Borrowed(TEMPLATE_MARKDOWN),
122 | Self::MdPlain => Cow::Borrowed(TEMPLATE_MARKDOWN_PLAIN),
123 | Self::Html => Cow::Borrowed(TEMPLATE_HTML),
124 | Self::Txt => Cow::Borrowed(TEMPLATE_TEXT),
125 | // Read custom template from file, return error message instead of the template if reading fails
126 | Self::CustomTemplate(path_buf) => {
127 | let content = std::fs::read_to_string(path_buf).unwrap_or(format!(
128 | ">> ERROR LOADING TEMPLATE FILE : '{}' <<",
129 | path_buf.to_string_lossy()
130 | ));
131 | Cow::Owned(content)
132 | }
133 | Self::TemplateString(template_str) => Cow::Owned(template_str.to_owned()),
134 | OutputTemplate::InlineTemplate(inline_template_info) => {
135 | Cow::Owned(inline_template_info.template.to_owned())
136 | }
137 | Self::None => Cow::Owned("".into()),
138 | }
139 | }
140 |
141 | /// Generates formatted inline template, including markers and proper line endings
142 | /// Used for InlineTemplate variant to format the output with start/end markers
143 | fn inline_template(&self, inline_template_info: &InlineTemplateInfo) -> String {
144 | let line_ending = line_ending(&inline_template_info.template, None);
145 | format!(
146 | "{}{}{}{}{}{}",
147 | inline_template_info.marker_start,
148 | line_ending,
149 | inline_template_info.template,
150 | line_ending,
151 | inline_template_info.marker_end,
152 | line_ending,
153 | )
154 | }
155 |
156 | /// Renders the template with provided server information
157 | /// Returns the rendered output as a `DiscoveryResult`
158 | pub fn render_template(&self, server_info: &McpServerInfo) -> DiscoveryResult {
159 | let rendered = render_template(self, server_info)?;
160 | match self {
161 | OutputTemplate::InlineTemplate(inline_template_info) => Ok(format!(
162 | "{}{}",
163 | self.inline_template(inline_template_info),
164 | rendered
165 | )),
166 | _ => Ok(rendered),
167 | }
168 | }
169 | }
170 |
171 | impl From<&Template> for OutputTemplate {
172 | fn from(value: &Template) -> Self {
173 | match value {
174 | Template::Md => OutputTemplate::Md,
175 | Template::Html => OutputTemplate::Html,
176 | Template::Txt => OutputTemplate::Txt,
177 | Template::MdPlain => OutputTemplate::MdPlain,
178 | }
179 | }
180 | }
181 |
182 | impl From for OutputTemplate {
183 | fn from(value: Template) -> Self {
184 | match value {
185 | Template::Md => OutputTemplate::Md,
186 | Template::Html => OutputTemplate::Html,
187 | Template::Txt => OutputTemplate::Txt,
188 | Template::MdPlain => OutputTemplate::MdPlain,
189 | }
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/tests/fixtures/md-create.md:
--------------------------------------------------------------------------------
1 | ## example-servers/everything 1.0.0
2 | | 🟢 Tools (8) | 🟢 Prompts (3) | 🟢 Resources (10) | 🟢 Logging | 🔴 Experimental |
3 | | --- | --- | --- | --- | --- |
4 | ## 🛠️ Tools (8)
5 |
6 |
7 |
8 |
9 |
10 | Tool Name
11 | Description
12 | Inputs
13 |
14 |
15 |
16 |
17 | 1.
18 |
19 | add
20 |
21 | Adds two numbers
22 |
23 |
24 | -
a : number
25 | -
b : number
26 |
27 |
28 |
29 |
30 | 2.
31 |
32 | annotatedMessage
33 |
34 | Demonstrates how annotations can be used to provide metadata about content
35 |
36 |
37 | -
includeImage : boolean
38 | -
messageType : string
39 |
40 |
41 |
42 |
43 | 3.
44 |
45 | echo
46 |
47 | Echoes back the input
48 |
49 |
50 | -
message : string
51 |
52 |
53 |
54 |
55 | 4.
56 |
57 | getResourceReference
58 |
59 | Returns a resource reference that can be used by MCP clients
60 |
61 |
62 | -
resourceId : number
63 |
64 |
65 |
66 |
67 | 5.
68 |
69 | getTinyImage
70 |
71 | Returns the MCP_TINY_IMAGE
72 |
73 |
74 |
75 |
76 |
77 |
78 | 6.
79 |
80 | longRunningOperation
81 |
82 | Demonstrates a long running operation with progress updates
83 |
84 |
85 | -
duration : number
86 | -
steps : number
87 |
88 |
89 |
90 |
91 | 7.
92 |
93 | printEnv
94 |
95 | Prints all environment variables, helpful for debugging MCP server configuration
96 |
97 |
98 |
99 |
100 |
101 |
102 | 8.
103 |
104 | sampleLLM
105 |
106 | Samples from an LLM using MCP's sampling feature
107 |
108 |
109 | -
maxTokens : number
110 | -
prompt : string
111 |
112 |
113 |
114 |
115 |
116 |
117 | ## 📝 Prompts (3)
118 |
119 |
120 |
121 |
122 |
123 | Prompt Name
124 | Description
125 |
126 |
127 |
128 |
129 | 1.
130 |
131 | simple_prompt
132 |
133 | A prompt without arguments
134 |
135 |
136 | 2.
137 |
138 | complex_prompt
139 |
140 | A prompt with arguments
141 |
142 |
143 | 3.
144 |
145 | resource_prompt
146 |
147 | A prompt that includes an embedded resource reference
148 |
149 |
150 |
151 |
152 | ## 📄 Resources (10)
153 |
154 |
155 |
156 |
157 |
158 | Resource Name
159 | Uri
160 | Description
161 |
162 |
163 |
164 |
165 | 1.
166 |
167 | Resource 1
168 |
169 |
170 | test://static/resource/1 (text/plain)
171 |
172 |
173 |
174 |
175 | 2.
176 |
177 | Resource 2
178 |
179 |
180 | test://static/resource/2 (application/octet-stream)
181 |
182 |
183 |
184 |
185 | 3.
186 |
187 | Resource 3
188 |
189 |
190 | test://static/resource/3 (text/plain)
191 |
192 |
193 |
194 |
195 | 4.
196 |
197 | Resource 4
198 |
199 |
200 | test://static/resource/4 (application/octet-stream)
201 |
202 |
203 |
204 |
205 | 5.
206 |
207 | Resource 5
208 |
209 |
210 | test://static/resource/5 (text/plain)
211 |
212 |
213 |
214 |
215 | 6.
216 |
217 | Resource 6
218 |
219 |
220 | test://static/resource/6 (application/octet-stream)
221 |
222 |
223 |
224 |
225 | 7.
226 |
227 | Resource 7
228 |
229 |
230 | test://static/resource/7 (text/plain)
231 |
232 |
233 |
234 |
235 | 8.
236 |
237 | Resource 8
238 |
239 |
240 | test://static/resource/8 (application/octet-stream)
241 |
242 |
243 |
244 |
245 | 9.
246 |
247 | Resource 9
248 |
249 |
250 | test://static/resource/9 (text/plain)
251 |
252 |
253 |
254 |
255 | 10.
256 |
257 | Resource 10
258 |
259 |
260 | test://static/resource/10 (application/octet-stream)
261 |
262 |
263 |
264 |
265 |
266 |
267 | ## 🧩 Resource Templates (1)
268 |
269 |
270 |
271 |
272 |
273 | Name
274 | Uri Template
275 | Description
276 |
277 |
278 |
279 |
280 | 1.
281 |
282 | Static Resource
283 |
284 |
285 | test://static/resource/{id}
286 |
287 | A static resource with a numeric ID
288 |
289 |
290 |
291 |
292 | ◾ generated by [mcp-discovery](https://github.com/rust-mcp-stack/mcp-discovery)
293 |
--------------------------------------------------------------------------------
/tests/fixtures/md-update.md:
--------------------------------------------------------------------------------
1 |
2 | ## example-servers/everything 1.0.0
3 | | 🟢 Tools (8) | 🟢 Prompts (3) | 🟢 Resources (10) | 🟢 Logging | 🔴 Experimental |
4 | | --- | --- | --- | --- | --- |
5 | ## 🛠️ Tools (8)
6 |
7 |
8 |
9 |
10 |
11 | Tool Name
12 | Description
13 | Inputs
14 |
15 |
16 |
17 |
18 | 1.
19 |
20 | add
21 |
22 | Adds two numbers
23 |
24 |
25 | -
a : number
26 | -
b : number
27 |
28 |
29 |
30 |
31 | 2.
32 |
33 | annotatedMessage
34 |
35 | Demonstrates how annotations can be used to provide metadata about content
36 |
37 |
38 | -
includeImage : boolean
39 | -
messageType : string
40 |
41 |
42 |
43 |
44 | 3.
45 |
46 | echo
47 |
48 | Echoes back the input
49 |
50 |
51 | -
message : string
52 |
53 |
54 |
55 |
56 | 4.
57 |
58 | getResourceReference
59 |
60 | Returns a resource reference that can be used by MCP clients
61 |
62 |
63 | -
resourceId : number
64 |
65 |
66 |
67 |
68 | 5.
69 |
70 | getTinyImage
71 |
72 | Returns the MCP_TINY_IMAGE
73 |
74 |
75 |
76 |
77 |
78 |
79 | 6.
80 |
81 | longRunningOperation
82 |
83 | Demonstrates a long running operation with progress updates
84 |
85 |
86 | -
duration : number
87 | -
steps : number
88 |
89 |
90 |
91 |
92 | 7.
93 |
94 | printEnv
95 |
96 | Prints all environment variables, helpful for debugging MCP server configuration
97 |
98 |
99 |
100 |
101 |
102 |
103 | 8.
104 |
105 | sampleLLM
106 |
107 | Samples from an LLM using MCP's sampling feature
108 |
109 |
110 | -
maxTokens : number
111 | -
prompt : string
112 |
113 |
114 |
115 |
116 |
117 |
118 | ## 📝 Prompts (3)
119 |
120 |
121 |
122 |
123 |
124 | Prompt Name
125 | Description
126 |
127 |
128 |
129 |
130 | 1.
131 |
132 | simple_prompt
133 |
134 | A prompt without arguments
135 |
136 |
137 | 2.
138 |
139 | complex_prompt
140 |
141 | A prompt with arguments
142 |
143 |
144 | 3.
145 |
146 | resource_prompt
147 |
148 | A prompt that includes an embedded resource reference
149 |
150 |
151 |
152 |
153 | ## 📄 Resources (10)
154 |
155 |
156 |
157 |
158 |
159 | Resource Name
160 | Uri
161 | Description
162 |
163 |
164 |
165 |
166 | 1.
167 |
168 | Resource 1
169 |
170 |
171 | test://static/resource/1 (text/plain)
172 |
173 |
174 |
175 |
176 | 2.
177 |
178 | Resource 2
179 |
180 |
181 | test://static/resource/2 (application/octet-stream)
182 |
183 |
184 |
185 |
186 | 3.
187 |
188 | Resource 3
189 |
190 |
191 | test://static/resource/3 (text/plain)
192 |
193 |
194 |
195 |
196 | 4.
197 |
198 | Resource 4
199 |
200 |
201 | test://static/resource/4 (application/octet-stream)
202 |
203 |
204 |
205 |
206 | 5.
207 |
208 | Resource 5
209 |
210 |
211 | test://static/resource/5 (text/plain)
212 |
213 |
214 |
215 |
216 | 6.
217 |
218 | Resource 6
219 |
220 |
221 | test://static/resource/6 (application/octet-stream)
222 |
223 |
224 |
225 |
226 | 7.
227 |
228 | Resource 7
229 |
230 |
231 | test://static/resource/7 (text/plain)
232 |
233 |
234 |
235 |
236 | 8.
237 |
238 | Resource 8
239 |
240 |
241 | test://static/resource/8 (application/octet-stream)
242 |
243 |
244 |
245 |
246 | 9.
247 |
248 | Resource 9
249 |
250 |
251 | test://static/resource/9 (text/plain)
252 |
253 |
254 |
255 |
256 | 10.
257 |
258 | Resource 10
259 |
260 |
261 | test://static/resource/10 (application/octet-stream)
262 |
263 |
264 |
265 |
266 |
267 |
268 | ## 🧩 Resource Templates (1)
269 |
270 |
271 |
272 |
273 |
274 | Name
275 | Uri Template
276 | Description
277 |
278 |
279 |
280 |
281 | 1.
282 |
283 | Static Resource
284 |
285 |
286 | test://static/resource/{id}
287 |
288 | A static resource with a numeric ID
289 |
290 |
291 |
292 |
293 | ◾ generated by [mcp-discovery](https://github.com/rust-mcp-stack/mcp-discovery)
294 |
295 |
--------------------------------------------------------------------------------
/tests/fixtures/md-plain-update-template-prop.md:
--------------------------------------------------------------------------------
1 |
2 | ## example-servers/everything 1.0.0
3 | | 🟢 Tools (8) | 🟢 Prompts (3) | 🟢 Resources (10) | 🟢 Logging | 🔴 Experimental |
4 | | --- | --- | --- | --- | --- |
5 | ## 🛠️ Tools (8)
6 |
7 |
8 |
9 |
10 |
11 | Tool Name
12 | Description
13 | Inputs
14 |
15 |
16 |
17 |
18 | 1.
19 |
20 | add
21 |
22 | Adds two numbers
23 |
24 |
25 | -
a : number
26 | -
b : number
27 |
28 |
29 |
30 |
31 | 2.
32 |
33 | annotatedMessage
34 |
35 | Demonstrates how annotations can be used to provide metadata about content
36 |
37 |
38 | -
includeImage : boolean
39 | -
messageType : string
40 |
41 |
42 |
43 |
44 | 3.
45 |
46 | echo
47 |
48 | Echoes back the input
49 |
50 |
51 | -
message : string
52 |
53 |
54 |
55 |
56 | 4.
57 |
58 | getResourceReference
59 |
60 | Returns a resource reference that can be used by MCP clients
61 |
62 |
63 | -
resourceId : number
64 |
65 |
66 |
67 |
68 | 5.
69 |
70 | getTinyImage
71 |
72 | Returns the MCP_TINY_IMAGE
73 |
74 |
75 |
76 |
77 |
78 |
79 | 6.
80 |
81 | longRunningOperation
82 |
83 | Demonstrates a long running operation with progress updates
84 |
85 |
86 | -
duration : number
87 | -
steps : number
88 |
89 |
90 |
91 |
92 | 7.
93 |
94 | printEnv
95 |
96 | Prints all environment variables, helpful for debugging MCP server configuration
97 |
98 |
99 |
100 |
101 |
102 |
103 | 8.
104 |
105 | sampleLLM
106 |
107 | Samples from an LLM using MCP's sampling feature
108 |
109 |
110 | -
maxTokens : number
111 | -
prompt : string
112 |
113 |
114 |
115 |
116 |
117 |
118 | ## 📝 Prompts (3)
119 |
120 |
121 |
122 |
123 |
124 | Prompt Name
125 | Description
126 |
127 |
128 |
129 |
130 | 1.
131 |
132 | simple_prompt
133 |
134 | A prompt without arguments
135 |
136 |
137 | 2.
138 |
139 | complex_prompt
140 |
141 | A prompt with arguments
142 |
143 |
144 | 3.
145 |
146 | resource_prompt
147 |
148 | A prompt that includes an embedded resource reference
149 |
150 |
151 |
152 |
153 | ## 📄 Resources (10)
154 |
155 |
156 |
157 |
158 |
159 | Resource Name
160 | Uri
161 | Description
162 |
163 |
164 |
165 |
166 | 1.
167 |
168 | Resource 1
169 |
170 |
171 | test://static/resource/1 (text/plain)
172 |
173 |
174 |
175 |
176 | 2.
177 |
178 | Resource 2
179 |
180 |
181 | test://static/resource/2 (application/octet-stream)
182 |
183 |
184 |
185 |
186 | 3.
187 |
188 | Resource 3
189 |
190 |
191 | test://static/resource/3 (text/plain)
192 |
193 |
194 |
195 |
196 | 4.
197 |
198 | Resource 4
199 |
200 |
201 | test://static/resource/4 (application/octet-stream)
202 |
203 |
204 |
205 |
206 | 5.
207 |
208 | Resource 5
209 |
210 |
211 | test://static/resource/5 (text/plain)
212 |
213 |
214 |
215 |
216 | 6.
217 |
218 | Resource 6
219 |
220 |
221 | test://static/resource/6 (application/octet-stream)
222 |
223 |
224 |
225 |
226 | 7.
227 |
228 | Resource 7
229 |
230 |
231 | test://static/resource/7 (text/plain)
232 |
233 |
234 |
235 |
236 | 8.
237 |
238 | Resource 8
239 |
240 |
241 | test://static/resource/8 (application/octet-stream)
242 |
243 |
244 |
245 |
246 | 9.
247 |
248 | Resource 9
249 |
250 |
251 | test://static/resource/9 (text/plain)
252 |
253 |
254 |
255 |
256 | 10.
257 |
258 | Resource 10
259 |
260 |
261 | test://static/resource/10 (application/octet-stream)
262 |
263 |
264 |
265 |
266 |
267 |
268 | ## 🧩 Resource Templates (1)
269 |
270 |
271 |
272 |
273 |
274 | Name
275 | Uri Template
276 | Description
277 |
278 |
279 |
280 |
281 | 1.
282 |
283 | Static Resource
284 |
285 |
286 | test://static/resource/{id}
287 |
288 | A static resource with a numeric ID
289 |
290 |
291 |
292 |
293 | ◾ generated by [mcp-discovery](https://github.com/rust-mcp-stack/mcp-discovery)
294 |
295 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # MCP Discovery
6 |
7 | A command-line tool written in Rust for discovering and documenting MCP Server capabilities.
8 |
9 | It supports outputting the results in the terminal or saving them to files in [Markdown](https://github.com/rust-mcp-stack/mcp-discovery/blob/main/docs/examples/update-md.md#server-info-and-capabilities), [HTML](https://rust-mcp-stack.github.io/mcp-discovery/examples/server-info.html), [plain text](https://rust-mcp-stack.github.io/mcp-discovery/examples/capabilities.txt), JSON, or a custom template defined by you.
10 |
11 |
12 | Check the [project documentation](https://rust-mcp-stack.github.io/mcp-discovery) for instructions and [command examples](https://rust-mcp-stack.github.io/mcp-discovery/#/guide/command-examples).
13 |
14 | ## Features 💡
15 |
16 | - **Display MCP Details**: Output MCP Server information, including tools, resources, and capabilities, directly to the terminal.
17 | - **Generate Files**: Create files in Markdown (`.md`), HTML (`.html`), or plain text (`.txt`) formats with MCP Server details and capabilities.
18 | - **Update Files**: Modify existing Markdown, HTML, or text files by adding MCP Server capabilities within specified markers, enabling MCP Server developers to automatically maintain up-to-date documentation and repository README files.
19 | - **Flexible Output Customization**: Choose from built-in templates (`md`, `md-plain`, `html`, `txt`) or supply custom Handlebars templates for personalized output.
20 | - **MCP Discovery GitHub Action**: Integrate the mcp-discovery CLI as a GitHub Action to automate and maintain up-to-date MCP Server documentation in your development workflow.
21 |
22 |
23 |
This open-source project leverages the [rust-mcp-sdk](https://github.com/rust-mcp-stack/rust-mcp-sdk) for seamless interaction with MCP Servers.
24 |
25 | 🌐 Check out the **rust-mcp-filesystem** [capabilities](https://rust-mcp-stack.github.io/rust-mcp-filesystem/#/capabilities) page for a sample output.
26 |
27 | ## Installation ⬇️
28 |
29 | ### Running as CLI
30 |
31 | Check the [project documentation](https://rust-mcp-stack.github.io/mcp-discovery) for instructions on installing the tool on different platforms.
32 |
33 | ### GitHub Action
34 |
35 | The easiest way to automate and maintain up-to-date MCP Server documentation , is to use mcp-discovery as a GitHub action.
36 | Please see [rust-mcp-stack/mcp-discovery-action](https://github.com/rust-mcp-stack/mcp-discovery-action) for installation and configuration instructions.
37 |
38 | ## Subcommands
39 |
40 | - **`print`**: Displays MCP Server capabilities in the terminal.
41 | - **`create`**: Creates a new file with MCP Server capability details.
42 | - **`update`**: Updates an existing file by inserting MCP Server capabilities between specified
43 | markers.
44 |
45 | 👉 Note: If no subcommand is provided, the `print` subcommand will be used by default.
46 |
47 | ### Options ⚙️
48 |
49 | - `-f, --filename `: Used with `create` and `update` commands to specify the output file to generate or modify.
50 | - `-t, --template `: Choose a built-in output template. Options: `md`, `md-plain`, `html`, `txt`.
51 | - `-p, --template-file `: Path to a custom Handlebars template file.
52 | - `-s, --template-string `: Inline Handlebars template provided as a string.
53 | - `-h, --help`: Display help information.
54 | - `-V, --version`: Display the version of `mcp-discovery`.
55 |
56 | 👉 Note: If no template is provided, `mcp-discovery` will automatically select the most suitable built-in template based on the file extension.
57 |
58 | ## Built-in Templates 🧬
59 |
60 | The CLI supports the following built-in output templates:
61 |
62 | - **`md`**: Formatted Markdown that presents MCP Server capabilities in a table format.
63 | - **`md-plain`**: Minimalist Markdown for straightforward output, using plain text instead of tables.
64 | - **`html`**: Structured HTML with basic styling.
65 | - **`txt`**: Plain text for raw, unformatted output.
66 |
67 | ## Custom Templates 🧩
68 |
69 | You can provide custom Handlebars templates in different ways:
70 |
71 | 1. Use the `--template-file` flag to provide a custom template file.
72 | 2. Use the `--template-string` flag to provide a raw Handlebars template directly as a string.
73 | 3. To use an inline template, define it in a file for the `update` command only — this will not function with print or create.
74 |
75 | > Inline templates must be enclosed within designated marker annotations.
76 |
77 | ### Examples
78 |
79 | ##### Print MCP Server capabilities to the terminal:
80 |
81 | ```bash
82 | mcp-discovery -- npx -y @modelcontextprotocol/server-everything
83 | ```
84 |
85 | #### Create a HTML file with MCP Server capabilities:
86 |
87 | ```bash
88 | mcp-discovery create -f capabilities.html -- npx -y @modelcontextprotocol/server-everything
89 | ```
90 |
91 | 📄 Click here to view generated html file
92 |
93 | #### Create a MD file with MCP Server capabilities:
94 |
95 | ```bash
96 | mcp-discovery create -f capabilities.md -- npx -y @modelcontextprotocol/server-everything
97 | ```
98 |
99 | #### Use a custom Handlebars template:
100 |
101 | ```bash
102 | mcp-discovery create -f capabilities.md --template-file=custom_template.hbs -- npx -y @modelcontextprotocol/server-everything
103 | ```
104 |
105 | 💡 See the [Command Examples](https://rust-mcp-stack.github.io/mcp-discovery/#/guide/command-examples) section in the project documentation for additional CLI usage examples.
106 |
107 | ## Defining Update Regions with Markers
108 |
109 | When using the `update` subcommand, `mcp-discovery` places capabilities between designated markers in the target file, which vary by file format and are typically comment lines.
110 | The update command simplifies the process for developers and maintainers to keep documentation current effortlessly.
111 | Run the mcp-discovery update command anytime to refresh the file with the latest MCP Server capabilities.
112 |
113 | ### Marker Annotations
114 |
115 | - **Render Block Start** : **`mcp-discovery-render`**
116 | - **Render Block End** : **`mcp-discovery-render-end`**
117 |
118 | **👉** The mcp-discovery-render marker supports template and template-file properties as well. Check the examples below for details.
119 |
120 | You can optionally include an inline template identifier within the render block, enclosed by:
121 |
122 | - **Template Block Start**: **`mcp-discovery-template`**
123 | - **Template Block End**: **`mcp-discovery-template-end`**
124 |
125 | If a template annotation is detected within a render block, `mcp-discovery` will use it to render the output. This allows for customized templates without depending on built-in or external template files. Check the examples below for details:
126 |
127 | ### Sample Markdown file annotated with render block:
128 |
129 | ```md
130 | # Server Info and Capabilities
131 |
132 |
133 |
134 | Server Capabilities will be placed here...
135 |
136 |
137 | ```
138 |
139 | ### Sample Markdown file, annotated with render block and template name:
140 |
141 | ```md
142 | # Server Info and Capabilities
143 |
144 |
145 |
146 | Server Capabilities will be placed here...
147 |
148 |
149 | ```
150 |
151 | ### Sample Markdown file, annotated with render block and custom template file:
152 |
153 | ```md
154 | # Server Info and Capabilities
155 |
156 |
157 |
158 | Server Capabilities will be placed here...
159 |
160 |
161 | ```
162 |
163 | ### Sample HTML file with annotations :
164 |
165 | ```html
166 |
167 |
168 |
169 | My MCP Server
170 |
171 |
172 | MCP Server Details
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | ```
181 |
182 | ### Sample HTML file with inline template :
183 |
184 | ```html
185 | MCP Server Details
186 |
187 |
188 |
197 |
198 |
199 | ```
200 |
201 | Below is a screenshot showing the resulting HTML after the mcp-discovery update command is executed:
202 |
203 |
204 |
205 | > You can execute the mcp-discovery update command whenever you need to refresh the file with the latest MCP Server capabilities.
206 |
207 | ## Contributing
208 |
209 | We welcome everyone who wishes to contribute! Please refer to the [contributing](CONTRIBUTING.md) guidelines for more details.
210 |
211 | All contributions, including issues and pull requests, must follow
212 | Rust's Code of Conduct.
213 |
214 | Unless explicitly stated otherwise, any contribution you submit for inclusion in mcp-discovery is provided under the terms of the MIT License, without any additional conditions or restrictions.
215 |
216 | ## License
217 |
218 | This project is licensed under the MIT License. see the [LICENSE](LICENSE) file for details.
219 |
--------------------------------------------------------------------------------
/docs/examples/create-md.md:
--------------------------------------------------------------------------------
1 | ## example-servers/everything 1.0.0
2 | | 🟢 Tools (10) | 🟢 Prompts (3) | 🟢 Resources (10) | 🟢 Logging | 🟢 Completions | 🔴 Experimental |
3 | | --- | --- | --- | --- | --- | --- |
4 |
5 | ## 🛠️ Tools (10)
6 |
7 |
8 |
9 |
10 |
11 | Tool Name
12 | Description
13 | Inputs
14 |
15 |
16 |
17 |
18 | 1.
19 |
20 | add
21 |
22 | Adds two numbers
23 |
24 |
25 | -
a : number
26 | -
b : number
27 |
28 |
29 |
30 |
31 | 2.
32 |
33 | annotatedMessage
34 |
35 | Demonstrates how annotations can be used to provide metadata about content
36 |
37 |
38 | -
includeImage : boolean
39 | -
messageType : error|success|debug
40 |
41 |
42 |
43 |
44 | 3.
45 |
46 | echo
47 |
48 | Echoes back the input
49 |
50 |
51 | -
message : string
52 |
53 |
54 |
55 |
56 | 4.
57 |
58 | getResourceLinks
59 |
60 | Returns multiple resource links that reference different types of resources
61 |
62 |
63 | -
count : number
64 |
65 |
66 |
67 |
68 | 5.
69 |
70 | getResourceReference
71 |
72 | Returns a resource reference that can be used by MCP clients
73 |
74 |
75 | -
resourceId : number
76 |
77 |
78 |
79 |
80 | 6.
81 |
82 | getTinyImage
83 |
84 | Returns the MCP_TINY_IMAGE
85 |
86 |
87 |
88 |
89 |
90 |
91 | 7.
92 |
93 | longRunningOperation
94 |
95 | Demonstrates a long running operation with progress updates
96 |
97 |
98 | -
duration : number
99 | -
steps : number
100 |
101 |
102 |
103 |
104 | 8.
105 |
106 | printEnv
107 |
108 | Prints all environment variables, helpful for debugging MCP server configuration
109 |
110 |
111 |
112 |
113 |
114 |
115 | 9.
116 |
117 | sampleLLM
118 |
119 | Samples from an LLM using MCP's sampling feature
120 |
121 |
122 | -
maxTokens : number
123 | -
prompt : string
124 |
125 |
126 |
127 |
128 | 10.
129 |
130 | structuredContent
131 |
132 | Returns structured content along with an output schema for client data validation
133 |
134 |
135 | -
location : string
136 |
137 |
138 |
139 |
140 |
141 |
142 | ## 📝 Prompts (3)
143 |
144 |
145 |
146 |
147 |
148 | Prompt Name
149 | Description
150 |
151 |
152 |
153 |
154 | 1.
155 |
156 | simple_prompt
157 |
158 | A prompt without arguments
159 |
160 |
161 | 2.
162 |
163 | complex_prompt
164 |
165 | A prompt with arguments
166 |
167 |
168 | 3.
169 |
170 | resource_prompt
171 |
172 | A prompt that includes an embedded resource reference
173 |
174 |
175 |
176 |
177 | ## 📄 Resources (10)
178 |
179 |
180 |
181 |
182 |
183 | Resource Name
184 | Uri
185 | Description
186 |
187 |
188 |
189 |
190 | 1.
191 |
192 | Resource 1
193 |
194 |
195 | test://static/resource/1 (text/plain)
196 |
197 |
198 |
199 |
200 | 2.
201 |
202 | Resource 2
203 |
204 |
205 | test://static/resource/2 (application/octet-stream)
206 |
207 |
208 |
209 |
210 | 3.
211 |
212 | Resource 3
213 |
214 |
215 | test://static/resource/3 (text/plain)
216 |
217 |
218 |
219 |
220 | 4.
221 |
222 | Resource 4
223 |
224 |
225 | test://static/resource/4 (application/octet-stream)
226 |
227 |
228 |
229 |
230 | 5.
231 |
232 | Resource 5
233 |
234 |
235 | test://static/resource/5 (text/plain)
236 |
237 |
238 |
239 |
240 | 6.
241 |
242 | Resource 6
243 |
244 |
245 | test://static/resource/6 (application/octet-stream)
246 |
247 |
248 |
249 |
250 | 7.
251 |
252 | Resource 7
253 |
254 |
255 | test://static/resource/7 (text/plain)
256 |
257 |
258 |
259 |
260 | 8.
261 |
262 | Resource 8
263 |
264 |
265 | test://static/resource/8 (application/octet-stream)
266 |
267 |
268 |
269 |
270 | 9.
271 |
272 | Resource 9
273 |
274 |
275 | test://static/resource/9 (text/plain)
276 |
277 |
278 |
279 |
280 | 10.
281 |
282 | Resource 10
283 |
284 |
285 | test://static/resource/10 (application/octet-stream)
286 |
287 |
288 |
289 |
290 |
291 |
292 | ## 🧩 Resource Templates (1)
293 |
294 |
295 |
296 |
297 |
298 | Name
299 | Uri Template
300 | Description
301 |
302 |
303 |
304 |
305 | 1.
306 |
307 | Static Resource
308 |
309 |
310 | test://static/resource/{id}
311 |
312 | A static resource with a numeric ID
313 |
314 |
315 |
316 |
317 | ◾ generated by [mcp-discovery](https://github.com/rust-mcp-stack/mcp-discovery)
318 |
--------------------------------------------------------------------------------
/docs/examples/update-md.md:
--------------------------------------------------------------------------------
1 | # Server Info and Capabilities
2 |
3 |
4 | ## example-servers/everything 1.0.0
5 | | 🟢 Tools (10) | 🟢 Prompts (3) | 🟢 Resources (10) | 🟢 Logging | 🟢 Completions | 🔴 Experimental |
6 | | --- | --- | --- | --- | --- | --- |
7 |
8 | ## 🛠️ Tools (10)
9 |
10 |
11 |
12 |
13 |
14 | Tool Name
15 | Description
16 | Inputs
17 |
18 |
19 |
20 |
21 | 1.
22 |
23 | add
24 |
25 | Adds two numbers
26 |
27 |
28 | -
a : number
29 | -
b : number
30 |
31 |
32 |
33 |
34 | 2.
35 |
36 | annotatedMessage
37 |
38 | Demonstrates how annotations can be used to provide metadata about content
39 |
40 |
41 | -
includeImage : boolean
42 | -
messageType : error|success|debug
43 |
44 |
45 |
46 |
47 | 3.
48 |
49 | echo
50 |
51 | Echoes back the input
52 |
53 |
54 | -
message : string
55 |
56 |
57 |
58 |
59 | 4.
60 |
61 | getResourceLinks
62 |
63 | Returns multiple resource links that reference different types of resources
64 |
65 |
66 | -
count : number
67 |
68 |
69 |
70 |
71 | 5.
72 |
73 | getResourceReference
74 |
75 | Returns a resource reference that can be used by MCP clients
76 |
77 |
78 | -
resourceId : number
79 |
80 |
81 |
82 |
83 | 6.
84 |
85 | getTinyImage
86 |
87 | Returns the MCP_TINY_IMAGE
88 |
89 |
90 |
91 |
92 |
93 |
94 | 7.
95 |
96 | longRunningOperation
97 |
98 | Demonstrates a long running operation with progress updates
99 |
100 |
101 | -
duration : number
102 | -
steps : number
103 |
104 |
105 |
106 |
107 | 8.
108 |
109 | printEnv
110 |
111 | Prints all environment variables, helpful for debugging MCP server configuration
112 |
113 |
114 |
115 |
116 |
117 |
118 | 9.
119 |
120 | sampleLLM
121 |
122 | Samples from an LLM using MCP's sampling feature
123 |
124 |
125 | -
maxTokens : number
126 | -
prompt : string
127 |
128 |
129 |
130 |
131 | 10.
132 |
133 | structuredContent
134 |
135 | Returns structured content along with an output schema for client data validation
136 |
137 |
138 | -
location : string
139 |
140 |
141 |
142 |
143 |
144 |
145 | ## 📝 Prompts (3)
146 |
147 |
148 |
149 |
150 |
151 | Prompt Name
152 | Description
153 |
154 |
155 |
156 |
157 | 1.
158 |
159 | simple_prompt
160 |
161 | A prompt without arguments
162 |
163 |
164 | 2.
165 |
166 | complex_prompt
167 |
168 | A prompt with arguments
169 |
170 |
171 | 3.
172 |
173 | resource_prompt
174 |
175 | A prompt that includes an embedded resource reference
176 |
177 |
178 |
179 |
180 | ## 📄 Resources (10)
181 |
182 |
183 |
184 |
185 |
186 | Resource Name
187 | Uri
188 | Description
189 |
190 |
191 |
192 |
193 | 1.
194 |
195 | Resource 1
196 |
197 |
198 | test://static/resource/1 (text/plain)
199 |
200 |
201 |
202 |
203 | 2.
204 |
205 | Resource 2
206 |
207 |
208 | test://static/resource/2 (application/octet-stream)
209 |
210 |
211 |
212 |
213 | 3.
214 |
215 | Resource 3
216 |
217 |
218 | test://static/resource/3 (text/plain)
219 |
220 |
221 |
222 |
223 | 4.
224 |
225 | Resource 4
226 |
227 |
228 | test://static/resource/4 (application/octet-stream)
229 |
230 |
231 |
232 |
233 | 5.
234 |
235 | Resource 5
236 |
237 |
238 | test://static/resource/5 (text/plain)
239 |
240 |
241 |
242 |
243 | 6.
244 |
245 | Resource 6
246 |
247 |
248 | test://static/resource/6 (application/octet-stream)
249 |
250 |
251 |
252 |
253 | 7.
254 |
255 | Resource 7
256 |
257 |
258 | test://static/resource/7 (text/plain)
259 |
260 |
261 |
262 |
263 | 8.
264 |
265 | Resource 8
266 |
267 |
268 | test://static/resource/8 (application/octet-stream)
269 |
270 |
271 |
272 |
273 | 9.
274 |
275 | Resource 9
276 |
277 |
278 | test://static/resource/9 (text/plain)
279 |
280 |
281 |
282 |
283 | 10.
284 |
285 | Resource 10
286 |
287 |
288 | test://static/resource/10 (application/octet-stream)
289 |
290 |
291 |
292 |
293 |
294 |
295 | ## 🧩 Resource Templates (1)
296 |
297 |
298 |
299 |
300 |
301 | Name
302 | Uri Template
303 | Description
304 |
305 |
306 |
307 |
308 | 1.
309 |
310 | Static Resource
311 |
312 |
313 | test://static/resource/{id}
314 |
315 | A static resource with a numeric ID
316 |
317 |
318 |
319 |
320 | ◾ generated by [mcp-discovery](https://github.com/rust-mcp-stack/mcp-discovery)
321 |
--------------------------------------------------------------------------------
/wix/main.wxs:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
46 |
47 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
69 |
70 |
80 |
81 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
106 |
111 |
112 |
113 |
114 |
122 |
123 |
124 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
145 |
146 |
150 |
151 |
152 |
153 |
154 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
191 | 1
192 | 1
193 |
194 |
195 |
196 |
197 |
202 |
203 |
204 |
205 |
213 |
214 |
215 |
216 |
224 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------