generate-tech-stack-mcp 0.2.0__py3-none-any.whl
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.
- generate_tech_stack_mcp/__init__.py +3 -0
- generate_tech_stack_mcp/analyze.py +1090 -0
- generate_tech_stack_mcp/server.py +163 -0
- generate_tech_stack_mcp-0.2.0.dist-info/METADATA +207 -0
- generate_tech_stack_mcp-0.2.0.dist-info/RECORD +9 -0
- generate_tech_stack_mcp-0.2.0.dist-info/WHEEL +5 -0
- generate_tech_stack_mcp-0.2.0.dist-info/entry_points.txt +3 -0
- generate_tech_stack_mcp-0.2.0.dist-info/licenses/LICENSE +21 -0
- generate_tech_stack_mcp-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
generate-tech-stack MCP Server
|
|
4
|
+
Universal — works with Claude Desktop, VS Code (Copilot via MCP), Cursor,
|
|
5
|
+
Zed, Windsurf, Continue, Antigravity, and any MCP-compatible host.
|
|
6
|
+
|
|
7
|
+
Install: pip install generate-tech-stack-mcp
|
|
8
|
+
Run: generate-tech-stack-mcp
|
|
9
|
+
|
|
10
|
+
Add to your MCP host config (e.g. claude_desktop_config.json):
|
|
11
|
+
{
|
|
12
|
+
"mcpServers": {
|
|
13
|
+
"generate-tech-stack": { "command": "generate-tech-stack-mcp" }
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
Then ask: /generate-tech-stack or "generate my tech stack"
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import asyncio
|
|
21
|
+
import json
|
|
22
|
+
import os
|
|
23
|
+
import sys
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
from mcp.server import Server
|
|
28
|
+
from mcp.server.stdio import stdio_server
|
|
29
|
+
import mcp.types as types
|
|
30
|
+
except ImportError:
|
|
31
|
+
print("ERROR: mcp package not found. Run: pip install mcp", file=sys.stderr)
|
|
32
|
+
sys.exit(1)
|
|
33
|
+
|
|
34
|
+
from generate_tech_stack_mcp import analyze as _analyze
|
|
35
|
+
|
|
36
|
+
server = Server("generate-tech-stack")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@server.list_tools()
|
|
40
|
+
async def handle_list_tools() -> list[types.Tool]:
|
|
41
|
+
return [
|
|
42
|
+
types.Tool(
|
|
43
|
+
name="generate_tech_stack",
|
|
44
|
+
description=(
|
|
45
|
+
"Scan a project directory and generate a TECH_STACK.html visual page. "
|
|
46
|
+
"Includes a stat row, layered architecture diagram, bar chart summary, "
|
|
47
|
+
"and colour-coded tool cards. Detects languages, frameworks, databases, "
|
|
48
|
+
"AI SDKs, testing, observability, security, and infrastructure tools."
|
|
49
|
+
),
|
|
50
|
+
inputSchema={
|
|
51
|
+
"type": "object",
|
|
52
|
+
"properties": {
|
|
53
|
+
"project_dir": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "Absolute path to the project root. Defaults to cwd.",
|
|
56
|
+
},
|
|
57
|
+
"output_file": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "Path for the output HTML. Defaults to <project_dir>/TECH_STACK.html.",
|
|
60
|
+
},
|
|
61
|
+
"open_browser": {
|
|
62
|
+
"type": "boolean",
|
|
63
|
+
"description": "Open the file in the default browser after creation.",
|
|
64
|
+
"default": True,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
"required": [],
|
|
68
|
+
},
|
|
69
|
+
),
|
|
70
|
+
types.Tool(
|
|
71
|
+
name="list_tech_stack",
|
|
72
|
+
description=(
|
|
73
|
+
"Scan a project and return the tech stack as structured JSON "
|
|
74
|
+
"(no HTML file written). Good for programmatic use."
|
|
75
|
+
),
|
|
76
|
+
inputSchema={
|
|
77
|
+
"type": "object",
|
|
78
|
+
"properties": {
|
|
79
|
+
"project_dir": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"description": "Absolute path to the project root.",
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
"required": [],
|
|
85
|
+
},
|
|
86
|
+
),
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@server.call_tool()
|
|
91
|
+
async def handle_call_tool(name: str, arguments: dict) -> list[types.TextContent]:
|
|
92
|
+
project_dir = Path(arguments.get("project_dir") or os.getcwd()).resolve()
|
|
93
|
+
|
|
94
|
+
if not project_dir.exists():
|
|
95
|
+
return [types.TextContent(type="text", text=f"ERROR: Directory not found: {project_dir}")]
|
|
96
|
+
|
|
97
|
+
if name == "list_tech_stack":
|
|
98
|
+
tools = _analyze.collect(project_dir)
|
|
99
|
+
total = sum(len(v) for v in tools.values())
|
|
100
|
+
result = {
|
|
101
|
+
"project": project_dir.name,
|
|
102
|
+
"total_tools": total,
|
|
103
|
+
"categories": {
|
|
104
|
+
cat: [{"name": t["name"], "desc": t["desc"]} for t in items]
|
|
105
|
+
for cat, items in tools.items()
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
return [types.TextContent(type="text", text=json.dumps(result, indent=2))]
|
|
109
|
+
|
|
110
|
+
if name == "generate_tech_stack":
|
|
111
|
+
output_file = Path(
|
|
112
|
+
arguments.get("output_file") or (project_dir / "TECH_STACK.html")
|
|
113
|
+
).resolve()
|
|
114
|
+
|
|
115
|
+
tools = _analyze.collect(project_dir)
|
|
116
|
+
if not tools:
|
|
117
|
+
return [types.TextContent(type="text",
|
|
118
|
+
text=f"No recognizable dependency files found in: {project_dir}")]
|
|
119
|
+
|
|
120
|
+
project_name = project_dir.name.replace("-", " ").replace("_", " ").title()
|
|
121
|
+
output_file.write_text(_analyze.render_html(tools, project_name))
|
|
122
|
+
|
|
123
|
+
total = sum(len(v) for v in tools.values())
|
|
124
|
+
lines = [
|
|
125
|
+
f"Tech stack generated: {output_file}",
|
|
126
|
+
f"Detected {total} tools across {len(tools)} categories:",
|
|
127
|
+
]
|
|
128
|
+
for cat, items in tools.items():
|
|
129
|
+
meta = _analyze.CATEGORY_META.get(cat, _analyze.CATEGORY_META["other"])
|
|
130
|
+
names = ", ".join(t["name"] for t in items)
|
|
131
|
+
lines.append(f" {meta['icon']} {meta['label']}: {names}")
|
|
132
|
+
|
|
133
|
+
if arguments.get("open_browser", True):
|
|
134
|
+
import subprocess
|
|
135
|
+
for cmd in ["xdg-open", "open", "start"]:
|
|
136
|
+
try:
|
|
137
|
+
subprocess.Popen([cmd, str(output_file)],
|
|
138
|
+
stdout=subprocess.DEVNULL,
|
|
139
|
+
stderr=subprocess.DEVNULL)
|
|
140
|
+
break
|
|
141
|
+
except FileNotFoundError:
|
|
142
|
+
continue
|
|
143
|
+
|
|
144
|
+
return [types.TextContent(type="text", text="\n".join(lines))]
|
|
145
|
+
|
|
146
|
+
return [types.TextContent(type="text", text=f"Unknown tool: {name}")]
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
async def _run():
|
|
150
|
+
async with stdio_server() as (read_stream, write_stream):
|
|
151
|
+
await server.run(
|
|
152
|
+
read_stream,
|
|
153
|
+
write_stream,
|
|
154
|
+
server.create_initialization_options(),
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def main():
|
|
159
|
+
asyncio.run(_run())
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
if __name__ == "__main__":
|
|
163
|
+
main()
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: generate-tech-stack-mcp
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Generate a visual technology-stack inventory (TECH_STACK.html) from any codebase — languages, frameworks, databases, AI SDKs, testing, and infra. CLI + MCP server, stdlib-only scanner.
|
|
5
|
+
Author: Ashutosh Kumar
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/askuma/generate-tech-stack
|
|
8
|
+
Project-URL: Repository, https://github.com/askuma/generate-tech-stack
|
|
9
|
+
Project-URL: Live Demo, https://askuma.github.io/generate-tech-stack/
|
|
10
|
+
Keywords: mcp,mcp-server,tech-stack,dependencies,inventory,static-analysis,claude
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: mcp>=1.0.0
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# generate-tech-stack
|
|
23
|
+
|
|
24
|
+
<!-- mcp-name: io.github.askuma/generate-tech-stack -->
|
|
25
|
+
|
|
26
|
+
Scan any project and generate a visual `TECH_STACK.html` page — dark-mode, auto-adapting, zero config.
|
|
27
|
+
|
|
28
|
+
Works as a **Claude Code skill**, **MCP server**, or **GitHub Copilot Extension**.
|
|
29
|
+
|
|
30
|
+
**[Live demo →](https://askuma.github.io/generate-tech-stack/)** — generated from
|
|
31
|
+
[fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template), unmodified.
|
|
32
|
+
|
|
33
|
+

|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## What it produces
|
|
38
|
+
|
|
39
|
+
Every generated page contains:
|
|
40
|
+
|
|
41
|
+
| Section | Description |
|
|
42
|
+
|---|---|
|
|
43
|
+
| **Stat row** | Total tools · Categories · AI Backends · Data Stores |
|
|
44
|
+
| **Architecture diagram** | Layered flow diagram (Consumer → API → AI/NLP → Data/Obs/Frontend) |
|
|
45
|
+
| **Bar chart** | Horizontal bars per category, colour-matched |
|
|
46
|
+
| **Tool cards** | One card per category; each tool shows a dot, name, description, and badge |
|
|
47
|
+
| **Badge legend** | Explains `pip`, `dep`, `optional`, `core`, `deploy`, `ci`, etc. |
|
|
48
|
+
| **Footer** | Project name · tool count · generation date |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Repository layout
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
~/.claude/skills/generate-tech-stack/
|
|
56
|
+
├── SKILL.md ← Claude Code skill definition
|
|
57
|
+
├── INSTALL.md ← detailed per-platform installation guide
|
|
58
|
+
├── README.md ← this file
|
|
59
|
+
├── scripts/
|
|
60
|
+
│ └── analyze.py ← core scanner + HTML renderer (no dependencies)
|
|
61
|
+
├── mcp/
|
|
62
|
+
│ ├── server.py ← MCP stdio server (pip install mcp)
|
|
63
|
+
│ └── requirements.txt
|
|
64
|
+
└── copilot/
|
|
65
|
+
├── index.js ← GitHub Copilot Extension (Express)
|
|
66
|
+
├── package.json
|
|
67
|
+
└── openai_function.json ← OpenAI / Antigravity function definition
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Usage
|
|
73
|
+
|
|
74
|
+
### pip (CLI + MCP server)
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pip install generate-tech-stack-mcp
|
|
78
|
+
|
|
79
|
+
generate-tech-stack . TECH_STACK.html # CLI: scan and write the report
|
|
80
|
+
generate-tech-stack-mcp # stdio MCP server
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
With pip installed, any MCP host config reduces to:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"mcpServers": {
|
|
88
|
+
"generate-tech-stack": { "command": "generate-tech-stack-mcp" }
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Claude Code
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
/generate-tech-stack
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Run it from any project directory. The skill calls `scripts/analyze.py` and opens the result in your browser.
|
|
100
|
+
|
|
101
|
+
### MCP (Claude Desktop, VS Code, Cursor, Zed, Windsurf, Continue)
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install mcp
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Add to your host's MCP config (replace the path with your actual home directory):
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"mcpServers": {
|
|
112
|
+
"generate-tech-stack": {
|
|
113
|
+
"command": "python3",
|
|
114
|
+
"args": ["/home/<you>/.claude/skills/generate-tech-stack/mcp/server.py"]
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Then ask: `generate my tech stack` or `/generate-tech-stack`.
|
|
121
|
+
|
|
122
|
+
**MCP tools exposed:**
|
|
123
|
+
- `generate_tech_stack` — scans a project, writes `TECH_STACK.html`, opens in browser
|
|
124
|
+
- `list_tech_stack` — returns a JSON summary, no file written
|
|
125
|
+
|
|
126
|
+
### GitHub Copilot Extension
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
cd copilot
|
|
130
|
+
npm install
|
|
131
|
+
npm start # listens on port 3000
|
|
132
|
+
ngrok http 3000 # expose for GitHub to reach
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Register a GitHub App with **Copilot Extension** enabled, set the Agent URL to `https://your-url/agent`, and install it on your account. Then in Copilot Chat:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
@generate-tech-stack /generate-tech-stack
|
|
139
|
+
@generate-tech-stack /generate-tech-stack /path/to/project
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Command line (standalone)
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
python3 ~/.claude/skills/generate-tech-stack/scripts/analyze.py /path/to/project
|
|
146
|
+
# output: /path/to/project/TECH_STACK.html
|
|
147
|
+
|
|
148
|
+
# custom output path:
|
|
149
|
+
python3 scripts/analyze.py . ~/Desktop/TECH_STACK.html
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`analyze.py` has no third-party dependencies — just Python 3.8+.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## What gets detected
|
|
157
|
+
|
|
158
|
+
| Source file | Detected tools |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `requirements.txt` / `pyproject.toml` | Python packages (web, DB, AI, testing, observability, security…) |
|
|
161
|
+
| `package.json` | Node / npm packages (frameworks, frontend, DB drivers, tooling) |
|
|
162
|
+
| `go.mod` | Go language |
|
|
163
|
+
| `Cargo.toml` | Rust language |
|
|
164
|
+
| `pom.xml` / `build.gradle` | Java / Kotlin |
|
|
165
|
+
| `Gemfile` | Ruby |
|
|
166
|
+
| `composer.json` | PHP |
|
|
167
|
+
| `**/*.py` source | Optional/dynamic SDKs via `importlib.find_spec()` patterns |
|
|
168
|
+
| `docker-compose.yml` / `.env` | PostgreSQL, Redis, MongoDB, SQLite connection strings |
|
|
169
|
+
| `Dockerfile` | Docker |
|
|
170
|
+
| `docker-compose.yml` | Docker Compose |
|
|
171
|
+
| `.github/workflows/` | GitHub Actions |
|
|
172
|
+
| `.gitlab-ci.yml` | GitLab CI |
|
|
173
|
+
| `alembic.ini` | Alembic migrations |
|
|
174
|
+
| `nginx.conf` / `Caddyfile` | Reverse proxy |
|
|
175
|
+
| `tsconfig.json` / `src/**/*.ts` | TypeScript |
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Detected categories
|
|
180
|
+
|
|
181
|
+
| Category | Colour | Examples |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| Language & Runtime | Green | Python, Go, Rust, TypeScript |
|
|
184
|
+
| Web / API Framework | Purple | FastAPI, Express, Django, Next.js |
|
|
185
|
+
| Database / Storage | Green | SQLAlchemy, Prisma, Redis, ChromaDB |
|
|
186
|
+
| AI Guardrail SDKs | Blue | GuardrailsAI, NVIDIA NeMo, Presidio, Lakera |
|
|
187
|
+
| NLP / ML | Teal | spaCy, Transformers, Sentence Transformers |
|
|
188
|
+
| Observability | Teal | Prometheus, OpenTelemetry, Sentry, Loguru |
|
|
189
|
+
| Testing | Yellow | pytest, Jest, Cypress, Playwright |
|
|
190
|
+
| Security / Auth | Rose | PyJWT, bcrypt, Authlib, Helmet |
|
|
191
|
+
| Infrastructure / Deploy | Orange | Docker, Kubernetes, Celery, Boto3 |
|
|
192
|
+
| Frontend / Dashboard | Gray | React, Vue, Tailwind, Recharts |
|
|
193
|
+
| Messaging / Comms | Blue | Kafka, RabbitMQ, Socket.io |
|
|
194
|
+
| Dev Tools | Gray | ESLint, Prettier, Vite, TypeScript |
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Design
|
|
199
|
+
|
|
200
|
+
Dark-mode only. Fonts: **IBM Plex Sans** (body) + **JetBrains Mono** (code/badges), loaded from Google Fonts. No JavaScript — pure HTML + CSS. Self-contained single file, opens in any browser offline.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## See also
|
|
205
|
+
|
|
206
|
+
- [INSTALL.md](INSTALL.md) — per-platform setup instructions
|
|
207
|
+
- [SKILL.md](SKILL.md) — Claude Code skill specification
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
generate_tech_stack_mcp/__init__.py,sha256=pzTcB3QF1p03CzooQO79pnfS2UBzps_YfudDFxJEix0,106
|
|
2
|
+
generate_tech_stack_mcp/analyze.py,sha256=3moRyfsLWuAOd5lNo77QHwX3whmq2UYK3axZaaLTEt4,50294
|
|
3
|
+
generate_tech_stack_mcp/server.py,sha256=bBBvzgASW5SKj9BQgEimliAJ8lJ6EhWp5nlT9QmfB_c,5568
|
|
4
|
+
generate_tech_stack_mcp-0.2.0.dist-info/licenses/LICENSE,sha256=k1Mx2UUhlahBiae3uzw2oGHhMN98awy7RztDPeJwIvI,1071
|
|
5
|
+
generate_tech_stack_mcp-0.2.0.dist-info/METADATA,sha256=AZcTmD5yS-F5cTx3eSjNJmL3z1F4mEniO5osYWvryg0,6846
|
|
6
|
+
generate_tech_stack_mcp-0.2.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
7
|
+
generate_tech_stack_mcp-0.2.0.dist-info/entry_points.txt,sha256=bAZhRj-mjrrYtu4pUy7CzYwgeMlkLxCe3PaBy6Hda8g,139
|
|
8
|
+
generate_tech_stack_mcp-0.2.0.dist-info/top_level.txt,sha256=s8p9Nz7Dtk9vE_UTs6vTAl3vsPBU4COqRW_XytwuHYA,24
|
|
9
|
+
generate_tech_stack_mcp-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ashutosh Kumar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
generate_tech_stack_mcp
|