@zt-playground/mcp-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +190 -0
- package/dist/auth.d.ts +6 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +44 -0
- package/dist/auth.js.map +1 -0
- package/dist/context-store.d.ts +42 -0
- package/dist/context-store.d.ts.map +1 -0
- package/dist/context-store.js +119 -0
- package/dist/context-store.js.map +1 -0
- package/dist/http-client.d.ts +17 -0
- package/dist/http-client.d.ts.map +1 -0
- package/dist/http-client.js +113 -0
- package/dist/http-client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/issue.d.ts +3 -0
- package/dist/resources/issue.d.ts.map +1 -0
- package/dist/resources/issue.js +59 -0
- package/dist/resources/issue.js.map +1 -0
- package/dist/resources/project.d.ts +3 -0
- package/dist/resources/project.d.ts.map +1 -0
- package/dist/resources/project.js +51 -0
- package/dist/resources/project.js.map +1 -0
- package/dist/tools/analytics.d.ts +3 -0
- package/dist/tools/analytics.d.ts.map +1 -0
- package/dist/tools/analytics.js +53 -0
- package/dist/tools/analytics.js.map +1 -0
- package/dist/tools/attachments.d.ts +3 -0
- package/dist/tools/attachments.d.ts.map +1 -0
- package/dist/tools/attachments.js +30 -0
- package/dist/tools/attachments.js.map +1 -0
- package/dist/tools/auth.d.ts +3 -0
- package/dist/tools/auth.d.ts.map +1 -0
- package/dist/tools/auth.js +68 -0
- package/dist/tools/auth.js.map +1 -0
- package/dist/tools/bugs.d.ts +3 -0
- package/dist/tools/bugs.d.ts.map +1 -0
- package/dist/tools/bugs.js +78 -0
- package/dist/tools/bugs.js.map +1 -0
- package/dist/tools/comments.d.ts +3 -0
- package/dist/tools/comments.d.ts.map +1 -0
- package/dist/tools/comments.js +28 -0
- package/dist/tools/comments.js.map +1 -0
- package/dist/tools/context.d.ts +3 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +106 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/database.d.ts +3 -0
- package/dist/tools/database.d.ts.map +1 -0
- package/dist/tools/database.js +154 -0
- package/dist/tools/database.js.map +1 -0
- package/dist/tools/epics.d.ts +3 -0
- package/dist/tools/epics.d.ts.map +1 -0
- package/dist/tools/epics.js +78 -0
- package/dist/tools/epics.js.map +1 -0
- package/dist/tools/issues.d.ts +3 -0
- package/dist/tools/issues.d.ts.map +1 -0
- package/dist/tools/issues.js +137 -0
- package/dist/tools/issues.js.map +1 -0
- package/dist/tools/labels.d.ts +3 -0
- package/dist/tools/labels.d.ts.map +1 -0
- package/dist/tools/labels.js +39 -0
- package/dist/tools/labels.js.map +1 -0
- package/dist/tools/monitor.d.ts +3 -0
- package/dist/tools/monitor.d.ts.map +1 -0
- package/dist/tools/monitor.js +115 -0
- package/dist/tools/monitor.js.map +1 -0
- package/dist/tools/projects.d.ts +3 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +39 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/relations.d.ts +3 -0
- package/dist/tools/relations.d.ts.map +1 -0
- package/dist/tools/relations.js +51 -0
- package/dist/tools/relations.js.map +1 -0
- package/dist/tools/repository.d.ts +3 -0
- package/dist/tools/repository.d.ts.map +1 -0
- package/dist/tools/repository.js +176 -0
- package/dist/tools/repository.js.map +1 -0
- package/dist/tools/ssh.d.ts +3 -0
- package/dist/tools/ssh.d.ts.map +1 -0
- package/dist/tools/ssh.js +141 -0
- package/dist/tools/ssh.js.map +1 -0
- package/dist/utils.d.ts +15 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +31 -0
- package/dist/utils.js.map +1 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# ZT Playground - MCP Server
|
|
2
|
+
|
|
3
|
+
Servidor MCP (Model Context Protocol) para gerenciamento de projetos, issues, bugs, analytics e monitoramento do ZT Playground.
|
|
4
|
+
|
|
5
|
+
## Ferramentas disponíveis
|
|
6
|
+
|
|
7
|
+
- **Projetos** - listar projetos, plataformas, saúde do projeto
|
|
8
|
+
- **Issues** - criar, buscar, atualizar issues (tasks, bugs, stories)
|
|
9
|
+
- **Epics** - criar épicos com sub-tasks automáticas
|
|
10
|
+
- **Bugs** - reportar bugs com contexto enriquecido (steps to reproduce, expected/actual behavior)
|
|
11
|
+
- **Comentários** - adicionar comentários em issues
|
|
12
|
+
- **Anexos** - anexar arquivos/imagens em issues
|
|
13
|
+
- **Labels** - gerenciar labels em issues
|
|
14
|
+
- **Analytics** - relatórios por repositório e análise por área
|
|
15
|
+
- **Monitor** - overview de erros, listagem, detalhes, eventos, performance
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Setup para usar com Claude Code
|
|
20
|
+
|
|
21
|
+
### Pre-requisitos
|
|
22
|
+
|
|
23
|
+
- [Node.js](https://nodejs.org/) v18+
|
|
24
|
+
- Acesso ao banco de dados PostgreSQL do ZT Playground
|
|
25
|
+
- Uma API Key válida do ZT Playground
|
|
26
|
+
|
|
27
|
+
### Passo 1 - Clonar o repositório
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
git clone git@github.com:v0up3r/zt-mcp-server.git
|
|
31
|
+
cd zt-mcp-server
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Passo 2 - Instalar dependências
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Passo 3 - Gerar o Prisma Client
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx prisma generate
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Passo 4 - Build do projeto
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run build
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Passo 5 - Configurar o MCP no Claude Code
|
|
53
|
+
|
|
54
|
+
Abra o arquivo de configuração do Claude Code. Existem duas opções:
|
|
55
|
+
|
|
56
|
+
**Opção A - Configuração global** (funciona em qualquer projeto):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Abre o arquivo de configuração global
|
|
60
|
+
nano ~/.claude/settings.json
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Opção B - Configuração por projeto** (apenas no projeto específico):
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Na raiz do seu projeto, crie/edite o arquivo
|
|
67
|
+
nano .mcp.json
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Passo 6 - Adicionar a configuração do MCP
|
|
71
|
+
|
|
72
|
+
Cole a seguinte configuração (ajuste os caminhos e variáveis):
|
|
73
|
+
|
|
74
|
+
**Para `~/.claude/settings.json`** (configuração global):
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"mcpServers": {
|
|
79
|
+
"zt-playground": {
|
|
80
|
+
"command": "node",
|
|
81
|
+
"args": ["/CAMINHO/COMPLETO/PARA/zt-mcp-server/dist/index.js"],
|
|
82
|
+
"env": {
|
|
83
|
+
"DATABASE_URL": "postgresql://USUARIO:SENHA@HOST:PORTA/BANCO",
|
|
84
|
+
"ZT_API_KEY": "SUA_API_KEY_AQUI"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Para `.mcp.json`** (configuração por projeto):
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"mcpServers": {
|
|
96
|
+
"zt-playground": {
|
|
97
|
+
"command": "node",
|
|
98
|
+
"args": ["/CAMINHO/COMPLETO/PARA/zt-mcp-server/dist/index.js"],
|
|
99
|
+
"env": {
|
|
100
|
+
"DATABASE_URL": "postgresql://USUARIO:SENHA@HOST:PORTA/BANCO",
|
|
101
|
+
"ZT_API_KEY": "SUA_API_KEY_AQUI"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
> **Importante:** Substitua:
|
|
109
|
+
> - `/CAMINHO/COMPLETO/PARA/zt-mcp-server/` pelo caminho real onde você clonou o repositório
|
|
110
|
+
> - `DATABASE_URL` pela connection string do banco PostgreSQL
|
|
111
|
+
> - `ZT_API_KEY` pela sua API key pessoal
|
|
112
|
+
|
|
113
|
+
### Passo 7 - Reiniciar o Claude Code
|
|
114
|
+
|
|
115
|
+
Feche e abra o Claude Code novamente (ou use `/mcp` para verificar o status do servidor).
|
|
116
|
+
|
|
117
|
+
### Passo 8 - Verificar se está funcionando
|
|
118
|
+
|
|
119
|
+
No Claude Code, digite:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
/mcp
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Você deve ver o servidor `zt-playground` listado e ativo. Agora pode usar comandos como:
|
|
126
|
+
|
|
127
|
+
- "Liste os projetos do ZT Playground"
|
|
128
|
+
- "Crie uma task no projeto X"
|
|
129
|
+
- "Mostre os bugs abertos"
|
|
130
|
+
- "Qual a saúde do projeto X?"
|
|
131
|
+
- "Mostre os erros do monitor"
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Setup para usar com OpenAI Codex
|
|
136
|
+
|
|
137
|
+
### Passos 1 a 4
|
|
138
|
+
|
|
139
|
+
Mesmos passos do Claude Code (clonar, instalar, gerar prisma, build).
|
|
140
|
+
|
|
141
|
+
### Passo 5 - Configurar o MCP no Codex
|
|
142
|
+
|
|
143
|
+
**Opção A - Via CLI:**
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
codex mcp add zt-playground \
|
|
147
|
+
--env DATABASE_URL=postgresql://USUARIO:SENHA@HOST:PORTA/BANCO \
|
|
148
|
+
--env ZT_API_KEY=SUA_API_KEY_AQUI \
|
|
149
|
+
-- node /CAMINHO/COMPLETO/PARA/zt-mcp-server/dist/index.js
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Opção B - Editando o arquivo de configuração:**
|
|
153
|
+
|
|
154
|
+
Edite `~/.codex/config.toml` (global) ou `.codex/config.toml` (por projeto):
|
|
155
|
+
|
|
156
|
+
```toml
|
|
157
|
+
[mcp_servers.zt-playground]
|
|
158
|
+
command = "node"
|
|
159
|
+
args = ["/CAMINHO/COMPLETO/PARA/zt-mcp-server/dist/index.js"]
|
|
160
|
+
|
|
161
|
+
[mcp_servers.zt-playground.env]
|
|
162
|
+
DATABASE_URL = "postgresql://USUARIO:SENHA@HOST:PORTA/BANCO"
|
|
163
|
+
ZT_API_KEY = "SUA_API_KEY_AQUI"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Passo 6 - Verificar
|
|
167
|
+
|
|
168
|
+
Reinicie o Codex e as ferramentas do ZT Playground estarão disponíveis.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Variáveis de ambiente
|
|
173
|
+
|
|
174
|
+
| Variável | Descrição | Obrigatório |
|
|
175
|
+
| -------------- | ------------------------------------------ | ----------- |
|
|
176
|
+
| `DATABASE_URL` | Connection string do PostgreSQL | Sim |
|
|
177
|
+
| `ZT_API_KEY` | API Key para autenticação no ZT Playground | Sim |
|
|
178
|
+
|
|
179
|
+
## Desenvolvimento
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Rodar em modo desenvolvimento
|
|
183
|
+
npm run dev
|
|
184
|
+
|
|
185
|
+
# Build
|
|
186
|
+
npm run build
|
|
187
|
+
|
|
188
|
+
# Gerar Prisma Client
|
|
189
|
+
npm run prisma:generate
|
|
190
|
+
```
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function validateAuth(): Promise<void>;
|
|
2
|
+
export declare function getUserId(): string;
|
|
3
|
+
export declare function getUserName(): string | null;
|
|
4
|
+
export declare function requireAuth(): void;
|
|
5
|
+
export declare function setCachedUser(userId: string, userName: string): void;
|
|
6
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAKA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBlD;AAED,wBAAgB,SAAS,IAAI,MAAM,CAUlC;AAED,wBAAgB,WAAW,IAAI,MAAM,GAAG,IAAI,CAE3C;AAED,wBAAgB,WAAW,IAAI,IAAI,CAIlC;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAGpE"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { api, isAuthenticated, loadAuth } from './http-client.js';
|
|
2
|
+
let cachedUserId = null;
|
|
3
|
+
let cachedUserName = null;
|
|
4
|
+
export async function validateAuth() {
|
|
5
|
+
if (!isAuthenticated()) {
|
|
6
|
+
// Don't abort — tools that need auth will return an error
|
|
7
|
+
console.error('No API key configured. Use the auth_setup tool to authenticate.');
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
const user = await api.get('/auth/me');
|
|
12
|
+
cachedUserId = user.id;
|
|
13
|
+
cachedUserName = user.name;
|
|
14
|
+
console.error(`Authenticated as ${user.name} (${user.email})`);
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
console.error(`API key validation failed: ${err.message}`);
|
|
18
|
+
// Don't abort — let the user fix it via auth_setup
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function getUserId() {
|
|
22
|
+
if (!cachedUserId) {
|
|
23
|
+
const auth = loadAuth();
|
|
24
|
+
if (auth?.userId) {
|
|
25
|
+
cachedUserId = auth.userId;
|
|
26
|
+
return cachedUserId;
|
|
27
|
+
}
|
|
28
|
+
throw new Error('Not authenticated. Use the auth_setup tool to configure your API key.');
|
|
29
|
+
}
|
|
30
|
+
return cachedUserId;
|
|
31
|
+
}
|
|
32
|
+
export function getUserName() {
|
|
33
|
+
return cachedUserName;
|
|
34
|
+
}
|
|
35
|
+
export function requireAuth() {
|
|
36
|
+
if (!isAuthenticated()) {
|
|
37
|
+
throw new Error('Not authenticated. Use the auth_setup tool to configure your API key.');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function setCachedUser(userId, userName) {
|
|
41
|
+
cachedUserId = userId;
|
|
42
|
+
cachedUserName = userName;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAElE,IAAI,YAAY,GAAkB,IAAI,CAAC;AACvC,IAAI,cAAc,GAAkB,IAAI,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACvB,0DAA0D;QAC1D,OAAO,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACjF,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,GAAG,CAA8C,UAAU,CAAC,CAAC;QACpF,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC;QACvB,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,oBAAoB,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACjE,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,8BAA8B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3D,mDAAmD;IACrD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;YACjB,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC;YAC3B,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC3F,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC3F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,QAAgB;IAC5D,YAAY,GAAG,MAAM,CAAC;IACtB,cAAc,GAAG,QAAQ,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface RepoConfig {
|
|
2
|
+
name: string;
|
|
3
|
+
path: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface DatabaseConfig {
|
|
7
|
+
name: string;
|
|
8
|
+
connectionString: string;
|
|
9
|
+
readOnly: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface SshConfig {
|
|
12
|
+
name: string;
|
|
13
|
+
host: string;
|
|
14
|
+
user: string;
|
|
15
|
+
keyPath?: string;
|
|
16
|
+
password?: string;
|
|
17
|
+
port: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ProjectContext {
|
|
20
|
+
projectId: string;
|
|
21
|
+
projectName: string;
|
|
22
|
+
repos: RepoConfig[];
|
|
23
|
+
databases: DatabaseConfig[];
|
|
24
|
+
ssh: SshConfig[];
|
|
25
|
+
}
|
|
26
|
+
export declare function saveContext(ctx: ProjectContext): void;
|
|
27
|
+
export declare function loadContext(name: string): ProjectContext | null;
|
|
28
|
+
export declare function listContexts(): Array<{
|
|
29
|
+
name: string;
|
|
30
|
+
projectId: string;
|
|
31
|
+
repos: number;
|
|
32
|
+
databases: number;
|
|
33
|
+
ssh: number;
|
|
34
|
+
}>;
|
|
35
|
+
export declare function removeContext(name: string): boolean;
|
|
36
|
+
export declare function setActiveContext(name: string): ProjectContext;
|
|
37
|
+
export declare function getActiveContext(): ProjectContext | null;
|
|
38
|
+
export declare function getActiveContextOrThrow(): ProjectContext;
|
|
39
|
+
export declare function resolveRepo(name?: string): RepoConfig;
|
|
40
|
+
export declare function resolveDatabase(name?: string): DatabaseConfig;
|
|
41
|
+
export declare function resolveSsh(name?: string): SshConfig;
|
|
42
|
+
//# sourceMappingURL=context-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-store.d.ts","sourceRoot":"","sources":["../src/context-store.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,GAAG,EAAE,SAAS,EAAE,CAAC;CAClB;AAuBD,wBAAgB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAKrD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAI/D;AAED,wBAAgB,YAAY,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAaxH;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASnD;AAOD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAM7D;AAED,wBAAgB,gBAAgB,IAAI,cAAc,GAAG,IAAI,CAExD;AAED,wBAAgB,uBAAuB,IAAI,cAAc,CAKxD;AAID,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAUrD;AAED,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAU7D;AAED,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAUnD"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync, readdirSync, unlinkSync, chmodSync, existsSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
// --- Paths ---
|
|
5
|
+
const CONTEXTS_DIR = join(homedir(), '.zt-playground', 'contexts');
|
|
6
|
+
function ensureDir() {
|
|
7
|
+
mkdirSync(CONTEXTS_DIR, { recursive: true });
|
|
8
|
+
}
|
|
9
|
+
function toKebab(name) {
|
|
10
|
+
return name
|
|
11
|
+
.toLowerCase()
|
|
12
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
13
|
+
.replace(/^-|-$/g, '');
|
|
14
|
+
}
|
|
15
|
+
function contextPath(name) {
|
|
16
|
+
return join(CONTEXTS_DIR, `${toKebab(name)}.json`);
|
|
17
|
+
}
|
|
18
|
+
// --- Storage ---
|
|
19
|
+
export function saveContext(ctx) {
|
|
20
|
+
ensureDir();
|
|
21
|
+
const path = contextPath(ctx.projectName);
|
|
22
|
+
writeFileSync(path, JSON.stringify(ctx, null, 2), 'utf-8');
|
|
23
|
+
chmodSync(path, 0o600);
|
|
24
|
+
}
|
|
25
|
+
export function loadContext(name) {
|
|
26
|
+
const path = contextPath(name);
|
|
27
|
+
if (!existsSync(path))
|
|
28
|
+
return null;
|
|
29
|
+
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
30
|
+
}
|
|
31
|
+
export function listContexts() {
|
|
32
|
+
ensureDir();
|
|
33
|
+
const files = readdirSync(CONTEXTS_DIR).filter((f) => f.endsWith('.json'));
|
|
34
|
+
return files.map((f) => {
|
|
35
|
+
const ctx = JSON.parse(readFileSync(join(CONTEXTS_DIR, f), 'utf-8'));
|
|
36
|
+
return {
|
|
37
|
+
name: ctx.projectName,
|
|
38
|
+
projectId: ctx.projectId,
|
|
39
|
+
repos: ctx.repos.length,
|
|
40
|
+
databases: ctx.databases.length,
|
|
41
|
+
ssh: ctx.ssh.length,
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export function removeContext(name) {
|
|
46
|
+
const path = contextPath(name);
|
|
47
|
+
if (!existsSync(path))
|
|
48
|
+
return false;
|
|
49
|
+
unlinkSync(path);
|
|
50
|
+
if (activeContextName && toKebab(activeContextName) === toKebab(name)) {
|
|
51
|
+
activeContextName = null;
|
|
52
|
+
activeContext = null;
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
// --- Active context (in-memory) ---
|
|
57
|
+
let activeContext = null;
|
|
58
|
+
let activeContextName = null;
|
|
59
|
+
export function setActiveContext(name) {
|
|
60
|
+
const ctx = loadContext(name);
|
|
61
|
+
if (!ctx)
|
|
62
|
+
throw new Error(`Context not found: ${name}`);
|
|
63
|
+
activeContext = ctx;
|
|
64
|
+
activeContextName = name;
|
|
65
|
+
return ctx;
|
|
66
|
+
}
|
|
67
|
+
export function getActiveContext() {
|
|
68
|
+
return activeContext;
|
|
69
|
+
}
|
|
70
|
+
export function getActiveContextOrThrow() {
|
|
71
|
+
if (!activeContext) {
|
|
72
|
+
throw new Error('No active context. Use context_set_active or context_setup first.');
|
|
73
|
+
}
|
|
74
|
+
return activeContext;
|
|
75
|
+
}
|
|
76
|
+
// --- Resolvers (auto-select if only one, error if ambiguous) ---
|
|
77
|
+
export function resolveRepo(name) {
|
|
78
|
+
const ctx = getActiveContextOrThrow();
|
|
79
|
+
if (ctx.repos.length === 0)
|
|
80
|
+
throw new Error('No repos configured in active context.');
|
|
81
|
+
if (name) {
|
|
82
|
+
const repo = ctx.repos.find((r) => r.name === name);
|
|
83
|
+
if (!repo)
|
|
84
|
+
throw new Error(`Repo "${name}" not found. Available: ${ctx.repos.map((r) => r.name).join(', ')}`);
|
|
85
|
+
return repo;
|
|
86
|
+
}
|
|
87
|
+
if (ctx.repos.length === 1)
|
|
88
|
+
return ctx.repos[0];
|
|
89
|
+
throw new Error(`Multiple repos available. Specify repoName: ${ctx.repos.map((r) => r.name).join(', ')}`);
|
|
90
|
+
}
|
|
91
|
+
export function resolveDatabase(name) {
|
|
92
|
+
const ctx = getActiveContextOrThrow();
|
|
93
|
+
if (ctx.databases.length === 0)
|
|
94
|
+
throw new Error('No databases configured in active context.');
|
|
95
|
+
if (name) {
|
|
96
|
+
const db = ctx.databases.find((d) => d.name === name);
|
|
97
|
+
if (!db)
|
|
98
|
+
throw new Error(`Database "${name}" not found. Available: ${ctx.databases.map((d) => d.name).join(', ')}`);
|
|
99
|
+
return db;
|
|
100
|
+
}
|
|
101
|
+
if (ctx.databases.length === 1)
|
|
102
|
+
return ctx.databases[0];
|
|
103
|
+
throw new Error(`Multiple databases available. Specify dbName: ${ctx.databases.map((d) => d.name).join(', ')}`);
|
|
104
|
+
}
|
|
105
|
+
export function resolveSsh(name) {
|
|
106
|
+
const ctx = getActiveContextOrThrow();
|
|
107
|
+
if (ctx.ssh.length === 0)
|
|
108
|
+
throw new Error('No SSH servers configured in active context.');
|
|
109
|
+
if (name) {
|
|
110
|
+
const ssh = ctx.ssh.find((s) => s.name === name);
|
|
111
|
+
if (!ssh)
|
|
112
|
+
throw new Error(`SSH "${name}" not found. Available: ${ctx.ssh.map((s) => s.name).join(', ')}`);
|
|
113
|
+
return ssh;
|
|
114
|
+
}
|
|
115
|
+
if (ctx.ssh.length === 1)
|
|
116
|
+
return ctx.ssh[0];
|
|
117
|
+
throw new Error(`Multiple SSH servers available. Specify serverName: ${ctx.ssh.map((s) => s.name).join(', ')}`);
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=context-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-store.js","sourceRoot":"","sources":["../src/context-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface AuthData {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
apiUrl: string;
|
|
4
|
+
userId?: string;
|
|
5
|
+
userName?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function loadAuth(): AuthData | null;
|
|
8
|
+
export declare function saveAuth(apiKey: string, apiUrl?: string, userId?: string, userName?: string): void;
|
|
9
|
+
export declare function isAuthenticated(): boolean;
|
|
10
|
+
export declare const api: {
|
|
11
|
+
get<T>(path: string, params?: Record<string, string | number | undefined>): Promise<T>;
|
|
12
|
+
post<T>(path: string, body?: unknown): Promise<T>;
|
|
13
|
+
patch<T>(path: string, body?: unknown): Promise<T>;
|
|
14
|
+
delete<T>(path: string): Promise<T>;
|
|
15
|
+
};
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=http-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"AAQA,UAAU,QAAQ;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,QAAQ,IAAI,QAAQ,GAAG,IAAI,CAqB1C;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAkBlG;AAED,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AA0DD,eAAO,MAAM,GAAG;QACV,CAAC,QAAQ,MAAM,WAAW,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;SAGjF,CAAC,QAAQ,MAAM,SAAS,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;UAG3C,CAAC,QAAQ,MAAM,SAAS,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;WAG3C,CAAC,QAAQ,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAGpC,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
const AUTH_DIR = join(homedir(), '.zt-playground');
|
|
5
|
+
const AUTH_FILE = join(AUTH_DIR, 'auth.json');
|
|
6
|
+
const DEFAULT_API_URL = 'https://zt-playground-api.vercel.app';
|
|
7
|
+
export function loadAuth() {
|
|
8
|
+
// Priority 1: env vars
|
|
9
|
+
const envKey = process.env.ZT_API_KEY;
|
|
10
|
+
if (envKey) {
|
|
11
|
+
return {
|
|
12
|
+
apiKey: envKey,
|
|
13
|
+
apiUrl: process.env.ZT_API_URL || DEFAULT_API_URL,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
// Priority 2: auth file
|
|
17
|
+
try {
|
|
18
|
+
if (existsSync(AUTH_FILE)) {
|
|
19
|
+
const data = JSON.parse(readFileSync(AUTH_FILE, 'utf-8'));
|
|
20
|
+
if (data.apiKey)
|
|
21
|
+
return data;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// Ignore parse errors
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
export function saveAuth(apiKey, apiUrl, userId, userName) {
|
|
30
|
+
if (!existsSync(AUTH_DIR)) {
|
|
31
|
+
mkdirSync(AUTH_DIR, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
const data = {
|
|
34
|
+
apiKey,
|
|
35
|
+
apiUrl: apiUrl || process.env.ZT_API_URL || DEFAULT_API_URL,
|
|
36
|
+
userId,
|
|
37
|
+
userName,
|
|
38
|
+
};
|
|
39
|
+
writeFileSync(AUTH_FILE, JSON.stringify(data, null, 2), 'utf-8');
|
|
40
|
+
try {
|
|
41
|
+
chmodSync(AUTH_FILE, 0o600);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Windows may not support chmod
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function isAuthenticated() {
|
|
48
|
+
return loadAuth() !== null;
|
|
49
|
+
}
|
|
50
|
+
function getBaseUrl() {
|
|
51
|
+
const auth = loadAuth();
|
|
52
|
+
return auth?.apiUrl || process.env.ZT_API_URL || DEFAULT_API_URL;
|
|
53
|
+
}
|
|
54
|
+
function getApiKey() {
|
|
55
|
+
const auth = loadAuth();
|
|
56
|
+
return auth?.apiKey || null;
|
|
57
|
+
}
|
|
58
|
+
async function request(method, path, body, params) {
|
|
59
|
+
const apiKey = getApiKey();
|
|
60
|
+
if (!apiKey) {
|
|
61
|
+
throw new Error('Not authenticated. Use the auth_setup tool to configure your API key.');
|
|
62
|
+
}
|
|
63
|
+
let url = `${getBaseUrl()}${path}`;
|
|
64
|
+
// Append query params
|
|
65
|
+
if (params) {
|
|
66
|
+
const searchParams = new URLSearchParams();
|
|
67
|
+
for (const [key, value] of Object.entries(params)) {
|
|
68
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
69
|
+
searchParams.set(key, String(value));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const qs = searchParams.toString();
|
|
73
|
+
if (qs)
|
|
74
|
+
url += `?${qs}`;
|
|
75
|
+
}
|
|
76
|
+
const headers = {
|
|
77
|
+
'X-ZT-API-Key': apiKey,
|
|
78
|
+
'Content-Type': 'application/json',
|
|
79
|
+
};
|
|
80
|
+
const res = await fetch(url, {
|
|
81
|
+
method,
|
|
82
|
+
headers,
|
|
83
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
84
|
+
});
|
|
85
|
+
if (!res.ok) {
|
|
86
|
+
const text = await res.text().catch(() => '');
|
|
87
|
+
throw new Error(`API ${method} ${path} returned ${res.status}: ${text}`);
|
|
88
|
+
}
|
|
89
|
+
const text = await res.text();
|
|
90
|
+
if (!text)
|
|
91
|
+
return undefined;
|
|
92
|
+
try {
|
|
93
|
+
return JSON.parse(text);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return text;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export const api = {
|
|
100
|
+
get(path, params) {
|
|
101
|
+
return request('GET', path, undefined, params);
|
|
102
|
+
},
|
|
103
|
+
post(path, body) {
|
|
104
|
+
return request('POST', path, body);
|
|
105
|
+
},
|
|
106
|
+
patch(path, body) {
|
|
107
|
+
return request('PATCH', path, body);
|
|
108
|
+
},
|
|
109
|
+
delete(path) {
|
|
110
|
+
return request('DELETE', path);
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=http-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { validateAuth } from './auth.js';
|
|
5
|
+
import { registerAuthTools } from './tools/auth.js';
|
|
6
|
+
import { registerProjectTools } from './tools/projects.js';
|
|
7
|
+
import { registerIssueTools } from './tools/issues.js';
|
|
8
|
+
import { registerEpicTools } from './tools/epics.js';
|
|
9
|
+
import { registerBugTools } from './tools/bugs.js';
|
|
10
|
+
import { registerCommentTools } from './tools/comments.js';
|
|
11
|
+
import { registerAttachmentTools } from './tools/attachments.js';
|
|
12
|
+
import { registerLabelTools } from './tools/labels.js';
|
|
13
|
+
import { registerAnalyticsTools } from './tools/analytics.js';
|
|
14
|
+
import { registerMonitorTools } from './tools/monitor.js';
|
|
15
|
+
import { registerRelationTools } from './tools/relations.js';
|
|
16
|
+
import { registerContextTools } from './tools/context.js';
|
|
17
|
+
import { registerRepositoryTools } from './tools/repository.js';
|
|
18
|
+
import { registerDatabaseTools } from './tools/database.js';
|
|
19
|
+
import { registerSshTools } from './tools/ssh.js';
|
|
20
|
+
import { registerProjectResources } from './resources/project.js';
|
|
21
|
+
import { registerIssueResources } from './resources/issue.js';
|
|
22
|
+
async function main() {
|
|
23
|
+
// Validate auth (non-blocking — won't abort if no key)
|
|
24
|
+
await validateAuth();
|
|
25
|
+
const server = new McpServer({
|
|
26
|
+
name: 'zt-playground',
|
|
27
|
+
version: '1.0.0',
|
|
28
|
+
});
|
|
29
|
+
// Auth setup tool (always available)
|
|
30
|
+
registerAuthTools(server);
|
|
31
|
+
// Register all ZT tools
|
|
32
|
+
registerProjectTools(server);
|
|
33
|
+
registerIssueTools(server);
|
|
34
|
+
registerEpicTools(server);
|
|
35
|
+
registerBugTools(server);
|
|
36
|
+
registerCommentTools(server);
|
|
37
|
+
registerAttachmentTools(server);
|
|
38
|
+
registerLabelTools(server);
|
|
39
|
+
registerAnalyticsTools(server);
|
|
40
|
+
registerMonitorTools(server);
|
|
41
|
+
registerRelationTools(server);
|
|
42
|
+
// Register context & environment tools
|
|
43
|
+
registerContextTools(server);
|
|
44
|
+
registerRepositoryTools(server);
|
|
45
|
+
registerDatabaseTools(server);
|
|
46
|
+
registerSshTools(server);
|
|
47
|
+
// Register resources
|
|
48
|
+
registerProjectResources(server);
|
|
49
|
+
registerIssueResources(server);
|
|
50
|
+
// Connect via stdio
|
|
51
|
+
const transport = new StdioServerTransport();
|
|
52
|
+
await server.connect(transport);
|
|
53
|
+
console.error('ZT Playground MCP Server running on stdio');
|
|
54
|
+
}
|
|
55
|
+
main().catch((err) => {
|
|
56
|
+
console.error('Fatal error:', err);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,KAAK,UAAU,IAAI;IACjB,uDAAuD;IACvD,MAAM,YAAY,EAAE,CAAC;IAErB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,qCAAqC;IACrC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE1B,wBAAwB;IACxB,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAE9B,uCAAuC;IACvC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAEzB,qBAAqB;IACrB,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAE/B,oBAAoB;IACpB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;AAC7D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../../src/resources/issue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAGtF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,QAiEvD"}
|