fg-tracker-mcp 0.4.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/CHANGELOG.md +15 -0
- package/README.md +83 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +51 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +103 -0
- package/dist/client.js +166 -0
- package/dist/client.js.map +1 -0
- package/dist/database.d.ts +15 -0
- package/dist/database.js +119 -0
- package/dist/database.js.map +1 -0
- package/dist/docs.d.ts +13 -0
- package/dist/docs.js +127 -0
- package/dist/docs.js.map +1 -0
- package/dist/format.d.ts +27 -0
- package/dist/format.js +103 -0
- package/dist/format.js.map +1 -0
- package/dist/guide.d.ts +19 -0
- package/dist/guide.js +490 -0
- package/dist/guide.js.map +1 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.js +418 -0
- package/dist/server.js.map +1 -0
- package/package.json +71 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog — fg-tracker-mcp
|
|
2
|
+
|
|
3
|
+
## 0.4.0 — 2026-09-15
|
|
4
|
+
|
|
5
|
+
- **Renomeado de `stread-track-mcp` — nomes antigos continuam funcionando e serão removidos na 1.0.** Veja "Migração de stread-track-mcp" no README.
|
|
6
|
+
- Bin `fg-tracker-mcp`; `stread-track-mcp` continua como alias obsoleto (avisa no stderr).
|
|
7
|
+
- Variáveis `FG_TRACKER_URL`, `FG_TRACKER_TOKEN`, `FG_TRACKER_API_KEY` e `FG_TRACKER_TIMEOUT_MS`, lidas antes dos nomes legados `STREAD_TRACK_*` (fallback).
|
|
8
|
+
- Nome do servidor MCP: `fg-tracker` (versão `0.4.0`). Tools `track_*` e o prompt `instrument-project` não mudaram.
|
|
9
|
+
- Resource `fg-tracker://docs/quickstart`; a URI `stread-track://docs/quickstart` continua registrada.
|
|
10
|
+
- A chave de projeto vai no header `x-fg-tracker-key`. Guias e quickstart passam a instalar `fg-tracker-sdk@^0.4.0` com `FG_TRACKER_KEY`/`FG_TRACKER_URL`.
|
|
11
|
+
- `package.json`: repositório `FORTGROUND/fg-tracker`, `publishConfig.access: public`, `prepack` limpa e recompila `dist/`.
|
|
12
|
+
|
|
13
|
+
## 0.3.0
|
|
14
|
+
|
|
15
|
+
- Versão interna do monorepo (a última publicada no npm como `stread-track-mcp` foi a 0.2.0).
|
package/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# fg-tracker-mcp
|
|
2
|
+
|
|
3
|
+
Servidor [MCP](https://modelcontextprotocol.io) (stdio) do FG Tracker para agentes de código (Claude Code, Cursor, Windsurf, Claude Desktop): projetos, métricas, traces, issues com commits suspeitos, releases, monitores, provedores externos, logs e guia de instrumentação. Documentação completa: `docs/mcp.md` no repositório.
|
|
4
|
+
|
|
5
|
+
## Instalação
|
|
6
|
+
|
|
7
|
+
Claude Code:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
claude mcp add fg-tracker \
|
|
11
|
+
-e FG_TRACKER_URL=http://localhost:4050 \
|
|
12
|
+
-e FG_TRACKER_TOKEN=<token-de-sessao> \
|
|
13
|
+
-- npx -y fg-tracker-mcp
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Cursor / Windsurf / Claude Desktop (JSON):
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"mcpServers": {
|
|
21
|
+
"fg-tracker": {
|
|
22
|
+
"command": "npx",
|
|
23
|
+
"args": ["-y", "fg-tracker-mcp"],
|
|
24
|
+
"env": {
|
|
25
|
+
"FG_TRACKER_URL": "http://localhost:4050",
|
|
26
|
+
"FG_TRACKER_TOKEN": "<token-de-sessao>"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Em produção, `FG_TRACKER_URL` é a URL da API mostrada no painel em **Conectar**. O domínio `https://tracker-api.fortground.com.br` será o endereço definitivo; até ele entrar no ar, use a URL atual do painel.
|
|
34
|
+
|
|
35
|
+
## Variáveis de ambiente
|
|
36
|
+
|
|
37
|
+
| variável | default | uso |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `FG_TRACKER_URL` | `http://localhost:4050` | URL base da API |
|
|
40
|
+
| `FG_TRACKER_TOKEN` | — | token de sessão (`Authorization: Bearer`) — projetos, métricas, traces, issues, logs |
|
|
41
|
+
| `FG_TRACKER_API_KEY` | — | chave de projeto (`x-fg-tracker-key`) — opcional, só ingestão |
|
|
42
|
+
| `FG_TRACKER_TIMEOUT_MS` | `15000` | timeout das chamadas HTTP |
|
|
43
|
+
|
|
44
|
+
Os nomes antigos `STREAD_TRACK_*` continuam lidos quando o nome novo está ausente.
|
|
45
|
+
|
|
46
|
+
## Tools, prompt e resource
|
|
47
|
+
|
|
48
|
+
Tools `track_*` (nomes inalterados), prompt `instrument-project` e resource `fg-tracker://docs/quickstart`.
|
|
49
|
+
|
|
50
|
+
## Migração de stread-track-mcp
|
|
51
|
+
|
|
52
|
+
O pacote foi renomeado de `stread-track-mcp` (última versão no npm: 0.2.0) para `fg-tracker-mcp` (0.4.0). Nomes antigos continuam funcionando e serão removidos na 1.0.
|
|
53
|
+
|
|
54
|
+
| antigo | novo | compatibilidade |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| pacote `stread-track-mcp` | `fg-tracker-mcp` | as versões antigas seguem no npm |
|
|
57
|
+
| bin `stread-track-mcp` | `fg-tracker-mcp` | o bin antigo é alias obsoleto (mesmo arquivo, aviso no stderr) |
|
|
58
|
+
| `STREAD_TRACK_URL`, `STREAD_TRACK_TOKEN`, `STREAD_TRACK_API_KEY`, `STREAD_TRACK_TIMEOUT_MS` | `FG_TRACKER_URL`, `FG_TRACKER_TOKEN`, `FG_TRACKER_API_KEY`, `FG_TRACKER_TIMEOUT_MS` | o novo tem precedência; o antigo é fallback |
|
|
59
|
+
| nome do servidor MCP `stread-track` | `fg-tracker` | renomeie a entrada na config do cliente quando quiser |
|
|
60
|
+
| resource `stread-track://docs/quickstart` | `fg-tracker://docs/quickstart` | a URI antiga continua registrada (mesmo conteúdo) |
|
|
61
|
+
| header `x-stread-track-key` | `x-fg-tracker-key` | a API aceita os dois |
|
|
62
|
+
| tools `track_*`, prompt `instrument-project` | inalterados | — |
|
|
63
|
+
|
|
64
|
+
Na config do cliente: troque `"stread-track": { "command": "npx", "args": ["-y", "stread-track-mcp"] }` por `"fg-tracker": { "command": "npx", "args": ["-y", "fg-tracker-mcp"] }` e renomeie as variáveis de `env`.
|
|
65
|
+
|
|
66
|
+
## Database detection (0.2.0)
|
|
67
|
+
|
|
68
|
+
`track_detect_databases { projectPath, serviceName }` inspects local Node project
|
|
69
|
+
manifests and imports without opening .env/credential files, following symlinks,
|
|
70
|
+
executing project scripts or reading dependencies. It returns candidate engines,
|
|
71
|
+
driver adapters, source references and an implementation guide. Multiple databases
|
|
72
|
+
are reported separately; a dependency alone is not proof of production use.
|
|
73
|
+
|
|
74
|
+
The coding agent must verify client creation sites, apply the appropriate SDK
|
|
75
|
+
adapter, preserve transactions/pool settings, and validate real `db.query` spans
|
|
76
|
+
under an HTTP request with `track_get_trace`. Detect before requesting
|
|
77
|
+
`track_instrumentation_guide { framework, databaseDriver, projectId }`.
|
|
78
|
+
|
|
79
|
+
Native adapters: pg and Postgres.js (including Drizzle). Generic adapters cover
|
|
80
|
+
synchronous, Promise and error-first callback operations; explicit completion
|
|
81
|
+
wrappers cover other engines, ORM operations and cursor/stream consumption.
|
|
82
|
+
Unknown drivers are not silently treated as pg. SQL is normalized and values are
|
|
83
|
+
not exported. No double instrumentation at both ORM and driver layers.
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Entrada do binário `fg-tracker-mcp` (alias obsoleto: `stread-track-mcp`): sobe o servidor MCP em stdio.
|
|
4
|
+
* Env: FG_TRACKER_URL (default http://localhost:4050), FG_TRACKER_TOKEN, FG_TRACKER_API_KEY,
|
|
5
|
+
* FG_TRACKER_TIMEOUT_MS — os nomes legados STREAD_TRACK_* continuam valendo como fallback.
|
|
6
|
+
*/
|
|
7
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
8
|
+
import { configFromEnv, TrackClient } from './client.js';
|
|
9
|
+
import { createServer, SERVER_NAME, SERVER_VERSION } from './server.js';
|
|
10
|
+
const argv = process.argv.slice(2);
|
|
11
|
+
if (argv.includes('--help') || argv.includes('-h')) {
|
|
12
|
+
process.stdout.write([
|
|
13
|
+
`${SERVER_NAME}-mcp ${SERVER_VERSION} — servidor MCP (stdio) do FG Tracker`,
|
|
14
|
+
'',
|
|
15
|
+
'Uso: fg-tracker-mcp (sem argumentos; fala MCP JSON-RPC via stdin/stdout)',
|
|
16
|
+
' fg-tracker-mcp --version',
|
|
17
|
+
'',
|
|
18
|
+
'Variáveis de ambiente:',
|
|
19
|
+
' FG_TRACKER_URL URL da API (default http://localhost:4050)',
|
|
20
|
+
' FG_TRACKER_TOKEN token de sessão (Authorization: Bearer) — projetos, métricas, logs',
|
|
21
|
+
' FG_TRACKER_API_KEY chave de projeto (x-fg-tracker-key) — opcional, só ingestão',
|
|
22
|
+
' FG_TRACKER_TIMEOUT_MS timeout das chamadas HTTP (default 15000)',
|
|
23
|
+
' (os nomes antigos STREAD_TRACK_* ainda são lidos como fallback; serão removidos na 1.0)',
|
|
24
|
+
'',
|
|
25
|
+
'Instalação no Claude Code:',
|
|
26
|
+
' claude mcp add fg-tracker -e FG_TRACKER_URL=http://localhost:4050 -e FG_TRACKER_TOKEN=... -- npx -y fg-tracker-mcp',
|
|
27
|
+
'',
|
|
28
|
+
].join('\n'));
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
if (argv.includes('--version') || argv.includes('-v')) {
|
|
32
|
+
process.stdout.write(`${SERVER_VERSION}\n`);
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
const config = configFromEnv();
|
|
36
|
+
const client = new TrackClient(config);
|
|
37
|
+
const server = createServer({ client });
|
|
38
|
+
// stdout é o canal JSON-RPC: qualquer diagnóstico vai para stderr.
|
|
39
|
+
const invoked = process.argv[1]?.split(/[\\/]/).pop() ?? '';
|
|
40
|
+
if (invoked.startsWith('stread-track-')) {
|
|
41
|
+
console.error(`[fg-tracker-mcp] "${invoked}" está obsoleto: use "fg-tracker-mcp" (o alias será removido na 1.0).`);
|
|
42
|
+
}
|
|
43
|
+
console.error(`[fg-tracker-mcp] API ${config.baseUrl} · token ${config.token ? 'ok' : 'ausente'} · apiKey ${config.apiKey ? 'ok' : 'ausente'}`);
|
|
44
|
+
const transport = new StdioServerTransport();
|
|
45
|
+
await server.connect(transport);
|
|
46
|
+
const shutdown = () => {
|
|
47
|
+
void server.close().finally(() => process.exit(0));
|
|
48
|
+
};
|
|
49
|
+
process.on('SIGINT', shutdown);
|
|
50
|
+
process.on('SIGTERM', shutdown);
|
|
51
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;GAIG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAExE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB;QACE,GAAG,WAAW,QAAQ,cAAc,uCAAuC;QAC3E,EAAE;QACF,uFAAuF;QACvF,+BAA+B;QAC/B,EAAE;QACF,wBAAwB;QACxB,qEAAqE;QACrE,6FAA6F;QAC7F,sFAAsF;QACtF,oEAAoE;QACpE,2FAA2F;QAC3F,EAAE;QACF,4BAA4B;QAC5B,sHAAsH;QACtH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AACD,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,cAAc,IAAI,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;AAC/B,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;AACvC,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAExC,mEAAmE;AACnE,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;AAC5D,IAAI,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;IACxC,OAAO,CAAC,KAAK,CAAC,qBAAqB,OAAO,uEAAuE,CAAC,CAAC;AACrH,CAAC;AACD,OAAO,CAAC,KAAK,CAAC,wBAAwB,MAAM,CAAC,OAAO,YAAY,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,aAAa,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;AAEhJ,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAEhC,MAAM,QAAQ,GAAG,GAAS,EAAE;IAC1B,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC,CAAC;AACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cliente HTTP mínimo para a API do FG Tracker (docs/CONTRATO.md §4, §8, §11).
|
|
3
|
+
* Lê `FG_TRACKER_URL`, `FG_TRACKER_TOKEN` (Bearer de sessão), `FG_TRACKER_API_KEY`
|
|
4
|
+
* (chave de projeto, header `x-fg-tracker-key`) e `FG_TRACKER_TIMEOUT_MS` — com
|
|
5
|
+
* fallback para os nomes legados `STREAD_TRACK_*` (`stread-track-mcp` ≤ 0.3).
|
|
6
|
+
*/
|
|
7
|
+
/** API local do monorepo. O endereço definitivo da API será `https://tracker-api.fortground.com.br`. */
|
|
8
|
+
export declare const DEFAULT_URL = "http://localhost:4050";
|
|
9
|
+
/** Header da chave de projeto (a API aceita também o legado `x-stread-track-key`). */
|
|
10
|
+
export declare const API_KEY_HEADER = "x-fg-tracker-key";
|
|
11
|
+
/**
|
|
12
|
+
* Lê `FG_TRACKER_<name>` e, se ausente/vazia, o legado `STREAD_TRACK_<name>`
|
|
13
|
+
* (obsoleto, removido na 1.0).
|
|
14
|
+
*/
|
|
15
|
+
export declare function readEnv(name: string, env?: NodeJS.ProcessEnv): string | undefined;
|
|
16
|
+
export interface TrackClientConfig {
|
|
17
|
+
baseUrl: string;
|
|
18
|
+
token?: string;
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
timeoutMs?: number;
|
|
21
|
+
}
|
|
22
|
+
export type QueryValue = string | number | boolean | undefined | null;
|
|
23
|
+
export declare class TrackApiError extends Error {
|
|
24
|
+
readonly status: number | undefined;
|
|
25
|
+
readonly path: string;
|
|
26
|
+
readonly hint?: string | undefined;
|
|
27
|
+
constructor(message: string, status: number | undefined, path: string, hint?: string | undefined);
|
|
28
|
+
/** Mensagem amigável pronta para devolver ao agente. */
|
|
29
|
+
describe(): string;
|
|
30
|
+
}
|
|
31
|
+
export declare function configFromEnv(env?: NodeJS.ProcessEnv): TrackClientConfig;
|
|
32
|
+
export declare class TrackClient {
|
|
33
|
+
readonly config: TrackClientConfig;
|
|
34
|
+
constructor(config: TrackClientConfig);
|
|
35
|
+
get baseUrl(): string;
|
|
36
|
+
get hasToken(): boolean;
|
|
37
|
+
get hasApiKey(): boolean;
|
|
38
|
+
/** Headers de autenticação: Bearer (sessão) e/ou chave de projeto. */
|
|
39
|
+
private authHeaders;
|
|
40
|
+
request<T = unknown>(method: 'GET' | 'POST' | 'PATCH' | 'DELETE', path: string, options?: {
|
|
41
|
+
query?: Record<string, QueryValue>;
|
|
42
|
+
body?: unknown;
|
|
43
|
+
headers?: Record<string, string>;
|
|
44
|
+
}): Promise<T>;
|
|
45
|
+
get<T = unknown>(path: string, query?: Record<string, QueryValue>): Promise<T>;
|
|
46
|
+
post<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
47
|
+
patch<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
48
|
+
}
|
|
49
|
+
export type RangeKey = '15m' | '1h' | '6h' | '24h' | '7d' | '30d';
|
|
50
|
+
export declare const RANGE_KEYS: readonly RangeKey[];
|
|
51
|
+
export declare const RANGE_SECONDS: Record<RangeKey, number>;
|
|
52
|
+
export interface Project {
|
|
53
|
+
id: string;
|
|
54
|
+
name: string;
|
|
55
|
+
slug: string;
|
|
56
|
+
apiKey: string;
|
|
57
|
+
slowThresholdMs: number;
|
|
58
|
+
loopThreshold: number;
|
|
59
|
+
apdexTargetMs: number;
|
|
60
|
+
createdAt: string;
|
|
61
|
+
stats?: {
|
|
62
|
+
requests24h: number;
|
|
63
|
+
errorRate24h: number;
|
|
64
|
+
p95Ms24h: number;
|
|
65
|
+
openIssues: number;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export interface HealthResponse {
|
|
69
|
+
status: string;
|
|
70
|
+
database: 'up' | 'down';
|
|
71
|
+
uptimeSeconds: number;
|
|
72
|
+
version: string;
|
|
73
|
+
}
|
|
74
|
+
export interface TracesResponse {
|
|
75
|
+
items: Array<{
|
|
76
|
+
traceId: string;
|
|
77
|
+
name: string;
|
|
78
|
+
method: string | null;
|
|
79
|
+
statusCode: number | null;
|
|
80
|
+
startedAt: string;
|
|
81
|
+
durationMs: number;
|
|
82
|
+
spanCount: number;
|
|
83
|
+
dbQueries: number;
|
|
84
|
+
hasIssue: boolean;
|
|
85
|
+
}>;
|
|
86
|
+
nextCursor: string | null;
|
|
87
|
+
}
|
|
88
|
+
export interface LogsResponse {
|
|
89
|
+
items: Array<{
|
|
90
|
+
id?: number | string;
|
|
91
|
+
ts: string;
|
|
92
|
+
level: number | string;
|
|
93
|
+
service: string;
|
|
94
|
+
message: string;
|
|
95
|
+
context?: Record<string, unknown> | null;
|
|
96
|
+
traceId?: string | null;
|
|
97
|
+
spanId?: string | null;
|
|
98
|
+
requestId?: string | null;
|
|
99
|
+
env?: string | null;
|
|
100
|
+
host?: string | null;
|
|
101
|
+
}>;
|
|
102
|
+
nextCursor: string | null;
|
|
103
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cliente HTTP mínimo para a API do FG Tracker (docs/CONTRATO.md §4, §8, §11).
|
|
3
|
+
* Lê `FG_TRACKER_URL`, `FG_TRACKER_TOKEN` (Bearer de sessão), `FG_TRACKER_API_KEY`
|
|
4
|
+
* (chave de projeto, header `x-fg-tracker-key`) e `FG_TRACKER_TIMEOUT_MS` — com
|
|
5
|
+
* fallback para os nomes legados `STREAD_TRACK_*` (`stread-track-mcp` ≤ 0.3).
|
|
6
|
+
*/
|
|
7
|
+
/** API local do monorepo. O endereço definitivo da API será `https://tracker-api.fortground.com.br`. */
|
|
8
|
+
export const DEFAULT_URL = 'http://localhost:4050';
|
|
9
|
+
/** Header da chave de projeto (a API aceita também o legado `x-stread-track-key`). */
|
|
10
|
+
export const API_KEY_HEADER = 'x-fg-tracker-key';
|
|
11
|
+
/**
|
|
12
|
+
* Lê `FG_TRACKER_<name>` e, se ausente/vazia, o legado `STREAD_TRACK_<name>`
|
|
13
|
+
* (obsoleto, removido na 1.0).
|
|
14
|
+
*/
|
|
15
|
+
export function readEnv(name, env = process.env) {
|
|
16
|
+
return env[`FG_TRACKER_${name}`]?.trim() || env[`STREAD_TRACK_${name}`]?.trim() || undefined;
|
|
17
|
+
}
|
|
18
|
+
export class TrackApiError extends Error {
|
|
19
|
+
status;
|
|
20
|
+
path;
|
|
21
|
+
hint;
|
|
22
|
+
constructor(message, status, path, hint) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.status = status;
|
|
25
|
+
this.path = path;
|
|
26
|
+
this.hint = hint;
|
|
27
|
+
this.name = 'TrackApiError';
|
|
28
|
+
}
|
|
29
|
+
/** Mensagem amigável pronta para devolver ao agente. */
|
|
30
|
+
describe() {
|
|
31
|
+
return this.hint ? `${this.message}\n\nDica: ${this.hint}` : this.message;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function configFromEnv(env = process.env) {
|
|
35
|
+
const baseUrl = (readEnv('URL', env) || DEFAULT_URL).replace(/\/+$/, '');
|
|
36
|
+
const token = readEnv('TOKEN', env);
|
|
37
|
+
const apiKey = readEnv('API_KEY', env);
|
|
38
|
+
const timeoutRaw = Number(readEnv('TIMEOUT_MS', env));
|
|
39
|
+
const timeoutMs = Number.isFinite(timeoutRaw) && timeoutRaw > 0 ? timeoutRaw : 15_000;
|
|
40
|
+
return { baseUrl, token, apiKey, timeoutMs };
|
|
41
|
+
}
|
|
42
|
+
function buildQuery(query) {
|
|
43
|
+
if (!query)
|
|
44
|
+
return '';
|
|
45
|
+
const params = new URLSearchParams();
|
|
46
|
+
for (const [key, value] of Object.entries(query)) {
|
|
47
|
+
if (value === undefined || value === null || value === '')
|
|
48
|
+
continue;
|
|
49
|
+
params.set(key, String(value));
|
|
50
|
+
}
|
|
51
|
+
const s = params.toString();
|
|
52
|
+
return s ? `?${s}` : '';
|
|
53
|
+
}
|
|
54
|
+
function isConnectionError(err) {
|
|
55
|
+
const cause = err?.cause;
|
|
56
|
+
const code = cause?.code ?? err?.code;
|
|
57
|
+
if (code && /ECONNREFUSED|ENOTFOUND|ECONNRESET|EAI_AGAIN|UND_ERR_CONNECT_TIMEOUT|EHOSTUNREACH/.test(code))
|
|
58
|
+
return true;
|
|
59
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
60
|
+
return /fetch failed|ECONNREFUSED|network/i.test(msg);
|
|
61
|
+
}
|
|
62
|
+
function extractMessage(body, fallback) {
|
|
63
|
+
if (body && typeof body === 'object') {
|
|
64
|
+
const m = body.message;
|
|
65
|
+
if (typeof m === 'string')
|
|
66
|
+
return m;
|
|
67
|
+
if (Array.isArray(m))
|
|
68
|
+
return m.map(String).join('; ');
|
|
69
|
+
}
|
|
70
|
+
if (typeof body === 'string' && body.trim())
|
|
71
|
+
return body.slice(0, 300);
|
|
72
|
+
return fallback;
|
|
73
|
+
}
|
|
74
|
+
export class TrackClient {
|
|
75
|
+
config;
|
|
76
|
+
constructor(config) {
|
|
77
|
+
this.config = config;
|
|
78
|
+
}
|
|
79
|
+
get baseUrl() {
|
|
80
|
+
return this.config.baseUrl;
|
|
81
|
+
}
|
|
82
|
+
get hasToken() {
|
|
83
|
+
return Boolean(this.config.token);
|
|
84
|
+
}
|
|
85
|
+
get hasApiKey() {
|
|
86
|
+
return Boolean(this.config.apiKey);
|
|
87
|
+
}
|
|
88
|
+
/** Headers de autenticação: Bearer (sessão) e/ou chave de projeto. */
|
|
89
|
+
authHeaders(extra) {
|
|
90
|
+
const headers = { accept: 'application/json', ...extra };
|
|
91
|
+
if (this.config.token)
|
|
92
|
+
headers.authorization = `Bearer ${this.config.token}`;
|
|
93
|
+
if (this.config.apiKey)
|
|
94
|
+
headers[API_KEY_HEADER] = this.config.apiKey;
|
|
95
|
+
return headers;
|
|
96
|
+
}
|
|
97
|
+
async request(method, path, options = {}) {
|
|
98
|
+
const url = `${this.config.baseUrl}${path}${buildQuery(options.query)}`;
|
|
99
|
+
const headers = this.authHeaders(options.headers);
|
|
100
|
+
let init = { method, headers, signal: AbortSignal.timeout(this.config.timeoutMs ?? 15_000) };
|
|
101
|
+
if (options.body !== undefined) {
|
|
102
|
+
headers['content-type'] = 'application/json';
|
|
103
|
+
init = { ...init, body: JSON.stringify(options.body) };
|
|
104
|
+
}
|
|
105
|
+
let res;
|
|
106
|
+
try {
|
|
107
|
+
res = await fetch(url, init);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
if (isConnectionError(err)) {
|
|
111
|
+
throw new TrackApiError(`API do FG Tracker não está no ar em ${this.config.baseUrl} (conexão recusada).`, undefined, path, 'suba a API com `pnpm dev:api` no monorepo do FG Tracker ou ajuste FG_TRACKER_URL.');
|
|
112
|
+
}
|
|
113
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
114
|
+
if (/abort|timeout/i.test(msg)) {
|
|
115
|
+
throw new TrackApiError(`Tempo esgotado ao chamar ${method} ${path} em ${this.config.baseUrl}.`, undefined, path);
|
|
116
|
+
}
|
|
117
|
+
throw new TrackApiError(`Falha ao chamar ${method} ${path}: ${msg}`, undefined, path);
|
|
118
|
+
}
|
|
119
|
+
const text = await res.text();
|
|
120
|
+
let body = null;
|
|
121
|
+
if (text) {
|
|
122
|
+
try {
|
|
123
|
+
body = JSON.parse(text);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
body = text;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (res.ok)
|
|
130
|
+
return body;
|
|
131
|
+
const message = extractMessage(body, `${res.status} ${res.statusText}`);
|
|
132
|
+
switch (res.status) {
|
|
133
|
+
case 401:
|
|
134
|
+
throw new TrackApiError(`Não autenticado (401) em ${method} ${path}: ${message}`, 401, path, this.config.token
|
|
135
|
+
? 'o FG_TRACKER_TOKEN expirou ou é inválido — faça login de novo (POST /v1/auth/login) e defina FG_TRACKER_TOKEN com o novo token.'
|
|
136
|
+
: 'defina FG_TRACKER_TOKEN com um token de sessão do FG Tracker (POST /v1/auth/login → `token`). Para ingestão use FG_TRACKER_API_KEY.');
|
|
137
|
+
case 403:
|
|
138
|
+
throw new TrackApiError(`Sem permissão (403) em ${method} ${path}: ${message}`, 403, path, 'o usuário do FG_TRACKER_TOKEN não é membro deste projeto. Peça a um owner/admin para convidá-lo em /members.');
|
|
139
|
+
case 404:
|
|
140
|
+
throw new TrackApiError(`Não encontrado (404) em ${method} ${path}: ${message}`, 404, path);
|
|
141
|
+
case 400:
|
|
142
|
+
throw new TrackApiError(`Requisição inválida (400) em ${method} ${path}: ${message}`, 400, path);
|
|
143
|
+
default:
|
|
144
|
+
throw new TrackApiError(`Erro ${res.status} em ${method} ${path}: ${message}`, res.status, path);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
get(path, query) {
|
|
148
|
+
return this.request('GET', path, { query });
|
|
149
|
+
}
|
|
150
|
+
post(path, body) {
|
|
151
|
+
return this.request('POST', path, { body });
|
|
152
|
+
}
|
|
153
|
+
patch(path, body) {
|
|
154
|
+
return this.request('PATCH', path, { body });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
export const RANGE_KEYS = ['15m', '1h', '6h', '24h', '7d', '30d'];
|
|
158
|
+
export const RANGE_SECONDS = {
|
|
159
|
+
'15m': 15 * 60,
|
|
160
|
+
'1h': 60 * 60,
|
|
161
|
+
'6h': 6 * 60 * 60,
|
|
162
|
+
'24h': 24 * 60 * 60,
|
|
163
|
+
'7d': 7 * 24 * 60 * 60,
|
|
164
|
+
'30d': 30 * 24 * 60 * 60,
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface DatabaseDetection {
|
|
2
|
+
package: string;
|
|
3
|
+
system: string;
|
|
4
|
+
adapter: string;
|
|
5
|
+
manifests: string[];
|
|
6
|
+
imports: string[];
|
|
7
|
+
}
|
|
8
|
+
/** Local bounded inspection: never read .env, credentials, lockfile contents or execute project code. */
|
|
9
|
+
export declare function detectDatabases(projectPath: string): Promise<{
|
|
10
|
+
projectPath: string;
|
|
11
|
+
databases: DatabaseDetection[];
|
|
12
|
+
truncated: boolean;
|
|
13
|
+
instructions: string;
|
|
14
|
+
}>;
|
|
15
|
+
export declare function databaseGuide(driver: string, serviceName: string): string;
|
package/dist/database.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { readdir, readFile, realpath } from 'node:fs/promises';
|
|
2
|
+
import { join, relative, extname } from 'node:path';
|
|
3
|
+
const DRIVERS = {
|
|
4
|
+
postgres: { system: 'postgresql', adapter: 'instrumentPostgres' },
|
|
5
|
+
pg: { system: 'postgresql', adapter: 'instrumentPg' },
|
|
6
|
+
'@neondatabase/serverless': { system: 'postgresql', adapter: 'generic' },
|
|
7
|
+
mysql2: { system: 'mysql', adapter: 'instrumentDatabase' },
|
|
8
|
+
mysql: { system: 'mysql', adapter: 'instrumentDatabase' },
|
|
9
|
+
mariadb: { system: 'mariadb', adapter: 'instrumentDatabase' },
|
|
10
|
+
'better-sqlite3': { system: 'sqlite', adapter: 'generic-sync' },
|
|
11
|
+
sqlite3: { system: 'sqlite', adapter: 'generic' },
|
|
12
|
+
'@libsql/client': { system: 'libsql', adapter: 'instrumentDatabase' },
|
|
13
|
+
mongodb: { system: 'mongodb', adapter: 'generic' },
|
|
14
|
+
mongoose: { system: 'mongodb', adapter: 'generic' },
|
|
15
|
+
'@prisma/client': { system: 'prisma-provider', adapter: 'generic' },
|
|
16
|
+
ioredis: { system: 'redis', adapter: 'generic' },
|
|
17
|
+
redis: { system: 'redis', adapter: 'generic' },
|
|
18
|
+
mssql: { system: 'mssql', adapter: 'generic' },
|
|
19
|
+
tedious: { system: 'mssql', adapter: 'generic' },
|
|
20
|
+
oracledb: { system: 'oracle', adapter: 'instrumentDatabase' },
|
|
21
|
+
'@aws-sdk/client-dynamodb': { system: 'dynamodb', adapter: 'generic' },
|
|
22
|
+
'@clickhouse/client': { system: 'clickhouse', adapter: 'generic' },
|
|
23
|
+
'cassandra-driver': { system: 'cassandra', adapter: 'instrumentDatabase' },
|
|
24
|
+
couchbase: { system: 'couchbase', adapter: 'generic' },
|
|
25
|
+
'snowflake-sdk': { system: 'snowflake', adapter: 'generic' },
|
|
26
|
+
'@elastic/elasticsearch': { system: 'elasticsearch', adapter: 'generic' },
|
|
27
|
+
};
|
|
28
|
+
const SKIP = new Set(['node_modules', 'dist', 'build', 'out', 'coverage', 'vendor', 'infra', 'test-results']);
|
|
29
|
+
/** Local bounded inspection: never read .env, credentials, lockfile contents or execute project code. */
|
|
30
|
+
export async function detectDatabases(projectPath) {
|
|
31
|
+
const root = await realpath(projectPath);
|
|
32
|
+
const candidates = new Map();
|
|
33
|
+
const files = [];
|
|
34
|
+
let visited = 0;
|
|
35
|
+
let truncated = false;
|
|
36
|
+
async function walk(directory, depth) {
|
|
37
|
+
if (depth > 8) {
|
|
38
|
+
truncated = true;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
for (const entry of (await readdir(directory, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
42
|
+
if (++visited > 10000) {
|
|
43
|
+
truncated = true;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (entry.isSymbolicLink() || entry.name.startsWith('.') || SKIP.has(entry.name))
|
|
47
|
+
continue;
|
|
48
|
+
const path = join(directory, entry.name);
|
|
49
|
+
if (entry.isDirectory())
|
|
50
|
+
await walk(path, depth + 1);
|
|
51
|
+
else if (entry.name === 'package.json' || ['.ts', '.tsx', '.js', '.mjs', '.cjs'].includes(extname(path)))
|
|
52
|
+
files.push(path);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
await walk(root, 0);
|
|
56
|
+
const contents = [];
|
|
57
|
+
for (const path of files) {
|
|
58
|
+
const source = await readFile(path, 'utf8');
|
|
59
|
+
if (source.length > 512_000) {
|
|
60
|
+
truncated = true;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const name = relative(root, path);
|
|
64
|
+
if (name.endsWith('package.json')) {
|
|
65
|
+
let manifest;
|
|
66
|
+
try {
|
|
67
|
+
manifest = JSON.parse(source);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
for (const dependency of Object.keys({ ...manifest.dependencies, ...manifest.optionalDependencies })) {
|
|
73
|
+
const match = DRIVERS[dependency];
|
|
74
|
+
if (!match)
|
|
75
|
+
continue;
|
|
76
|
+
const current = candidates.get(dependency) ?? { package: dependency, ...match, manifests: [], imports: [] };
|
|
77
|
+
current.manifests.push(name);
|
|
78
|
+
candidates.set(dependency, current);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (!/\.(test|spec)\./.test(name))
|
|
82
|
+
contents.push([name, source]);
|
|
83
|
+
}
|
|
84
|
+
for (const [name, source] of contents) {
|
|
85
|
+
for (const [dependency, match] of Object.entries(DRIVERS)) {
|
|
86
|
+
const escaped = dependency.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
87
|
+
const pattern = new RegExp(`(?:from\\s*|require\\s*\\(\\s*|import\\s*\\(\\s*)['"]${escaped}(?:/[^'"]*)?['"]`, 'g');
|
|
88
|
+
let found;
|
|
89
|
+
while ((found = pattern.exec(source))) {
|
|
90
|
+
const current = candidates.get(dependency) ?? { package: dependency, ...match, manifests: [], imports: [] };
|
|
91
|
+
current.imports.push(`${name}:${source.slice(0, found.index).split('\n').length}`);
|
|
92
|
+
candidates.set(dependency, current);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { projectPath: root, databases: [...candidates.values()], truncated,
|
|
97
|
+
instructions: 'Inspect the reported initialization sites; dependencies are candidates, imports are evidence, not proof of an active production database. Instrument every active client exactly once, at one layer (driver OR ORM). For unknown drivers use traceDatabase/traceDatabaseSync around actual completed operations. Never infer the engine from DATABASE_URL or read secrets. Do not claim automatic support for an unknown cursor/callback lifecycle.' };
|
|
98
|
+
}
|
|
99
|
+
export function databaseGuide(driver, serviceName) {
|
|
100
|
+
const known = DRIVERS[driver];
|
|
101
|
+
const system = known?.system ?? 'custom';
|
|
102
|
+
let snippet;
|
|
103
|
+
if (driver === 'postgres')
|
|
104
|
+
snippet = `const raw = postgres(process.env.DATABASE_URL!);\nconst sql = tracker.instrumentPostgres(raw);\nconst db = drizzle(sql); // Drizzle queries, transactions and savepoints use this client`;
|
|
105
|
+
else if (driver === 'pg')
|
|
106
|
+
snippet = `const pool = tracker.instrumentPg(new Pool({ connectionString: process.env.DATABASE_URL }));\n// Also instrument clients acquired with pool.connect() when queries use those directly.`;
|
|
107
|
+
else if (known?.adapter === 'instrumentDatabase')
|
|
108
|
+
snippet = `const db = tracker.instrumentDatabase(rawClient, {\n system: '${system}', methods: ['query', 'execute'],\n statement: (_method, args) => typeof args[0] === 'string' ? args[0] : undefined,\n callbacks: true, // only for drivers with a final error-first callback\n});\n// Instrument separately acquired transaction connections too. For cursors, wrap consumption instead.`;
|
|
109
|
+
else if (driver === '@prisma/client')
|
|
110
|
+
snippet = `const db = prisma.$extends({ query: { $allModels: {\n async $allOperations({ model, operation, args, query }) {\n return tracker.traceDatabase({ system: 'prisma', operation: model + '.' + operation }, () => query(args));\n }\n} } });\n// Cover raw queries separately. Do NOT export args; this captures ORM operation timing, not underlying SQL.`;
|
|
111
|
+
else if (driver === 'mongodb' || driver === 'mongoose')
|
|
112
|
+
snippet = `const result = await tracker.traceDatabase(\n { system: 'mongodb', operation: 'tracks.find' },\n () => collection.find(filter).toArray(), // include cursor consumption, never serialize filter/documents\n);`;
|
|
113
|
+
else if (known?.adapter === 'generic-sync')
|
|
114
|
+
snippet = `const result = tracker.traceDatabaseSync(\n { system: '${system}', operation: 'query', statement: 'select * from tracks where id = ?' },\n () => statement.get(id),\n);`;
|
|
115
|
+
else
|
|
116
|
+
snippet = `const result = await tracker.traceDatabase(\n { system: '${system}', operation: 'repository.operation' },\n () => clientOperation(), // await the real operation; consume cursor/stream here if applicable\n);\n// For callback drivers: await a Promise settled by the operation's final callback.\n// For sync drivers: traceDatabaseSync preserves a synchronous result and throws.`;
|
|
117
|
+
return `# Database instrumentation: ${driver}\n\nInstall fg-tracker-sdk@^0.4.0 (formerly stread-track-sdk). Reuse the request tracker (${serviceName}); do not create a second tracker for the database.\n\n\`\`\`ts\n${snippet}\n\`\`\`\n\nUse the existing connection settings, pool sizes and transaction boundaries. Generic adapters support any engine when the operation completion is supplied explicitly; they do not auto-understand every driver. Bind values, result rows, documents, connection strings and credentials must never be exported. SQL spans use normalized statements; non-SQL operations use static names. Do not instrument both ORM and driver for the same operation.\n\nImplement these changes at the actual client/repository initialization sites, not merely in an unused example file. Run a real request, use track_get_trace and verify db.query spans share its traceId and have parentSpanId. Verify rollback, errors and parallel requests. Logs-only frontends must not create a tracker. Confirm completion only after the runtime exports the linked query spans.\n`;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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"}
|
package/dist/docs.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conteúdo estático: resource `fg-tracker://docs/quickstart` e o prompt
|
|
3
|
+
* `instrument-project`.
|
|
4
|
+
*/
|
|
5
|
+
export declare const QUICKSTART_URI = "fg-tracker://docs/quickstart";
|
|
6
|
+
/** @deprecated URI do `stread-track-mcp` ≤ 0.3; ainda registrada como alias, removida na 1.0. */
|
|
7
|
+
export declare const LEGACY_QUICKSTART_URI = "stread-track://docs/quickstart";
|
|
8
|
+
export declare function quickstartMarkdown(endpoint: string): string;
|
|
9
|
+
export interface InstrumentPromptArgs {
|
|
10
|
+
projectName?: string;
|
|
11
|
+
framework?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function instrumentProjectPrompt(args: InstrumentPromptArgs, endpoint: string): string;
|