@datadive-tools/mcp 0.7.0 → 0.9.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/dist/lib.d.ts ADDED
@@ -0,0 +1,184 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { z } from 'zod';
3
+ import { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
4
+
5
+ /**
6
+ * Loads and validates the server's runtime configuration from environment.
7
+ *
8
+ * Required:
9
+ * DATADIVE_API_KEY - your DataDive API key (generate at 2.datadive.tools/api-key)
10
+ *
11
+ * Optional:
12
+ * DATADIVE_API_BASE_URL - override the API base URL (defaults to https://api.datadive.tools)
13
+ * DATADIVE_AUTO_CONFIRM_WRITES - skip the confirm gate on token-spending write tools
14
+ * (create_niche_dive, create_rank_radar). Truthy =
15
+ * "1"/"true"/"yes" (case-insensitive). Defaults to false.
16
+ *
17
+ * The env-based loader always produces api-key credentials (the local stdio path).
18
+ * A remote host embedding this package builds a Config directly with bearer
19
+ * credentials (the OAuth path) — see Credentials.
20
+ */
21
+ /** OAuth scope covering the read tools. */
22
+ declare const SCOPE_READ = "datadive.read";
23
+ /** OAuth scope covering the token-spending write tools. */
24
+ declare const SCOPE_WRITE = "datadive.write";
25
+ /**
26
+ * How the HTTP client authenticates against the DataDive /v1 API.
27
+ * - "api-key": the local stdio path — sends `x-api-key` (DATADIVE_API_KEY).
28
+ * - "bearer": the remote/OAuth path — sends `Authorization: Bearer <token>`.
29
+ * The token is read at request time, so a host may mutate the
30
+ * credentials object to rotate a refreshed access token in place.
31
+ */
32
+ type Credentials = {
33
+ kind: "api-key";
34
+ apiKey: string;
35
+ } | {
36
+ kind: "bearer";
37
+ token: string;
38
+ };
39
+ interface Config {
40
+ credentials: Credentials;
41
+ baseUrl: string;
42
+ /**
43
+ * When true, the token-spending write tools proceed without requiring `confirm: true`.
44
+ * A user-controlled "don't ask me again" opt-out, set via DATADIVE_AUTO_CONFIRM_WRITES.
45
+ */
46
+ autoConfirmWrites: boolean;
47
+ /**
48
+ * OAuth scopes granted to this session. When set, tool calls are gated:
49
+ * read tools require SCOPE_READ and write tools SCOPE_WRITE (see server.ts).
50
+ * Undefined (the stdio/api-key path) means no scope gating.
51
+ */
52
+ scopes?: readonly string[];
53
+ }
54
+ declare function loadConfig(env?: NodeJS.ProcessEnv): Config;
55
+
56
+ /**
57
+ * Shared tool-definition shape consumed by the registry in src/server.ts.
58
+ *
59
+ * Each tool file exports a single `ToolDefinition` so adding tool #N+1 in v1.1
60
+ * is a one-file change (plus appending to `allTools` in tools/index.ts).
61
+ */
62
+
63
+ interface HandlerContext {
64
+ config: Config;
65
+ }
66
+ interface ToolDefinition<S extends z.ZodRawShape = z.ZodRawShape> {
67
+ /** Snake_case tool name shown to the LLM (e.g. "list_niches"). */
68
+ name: string;
69
+ /** Human-readable title (shown in some MCP UIs). */
70
+ title: string;
71
+ /**
72
+ * Tool description — the primary signal for LLM tool selection.
73
+ * Convention: lead with "Use this when..." then describe inputs and what's returned.
74
+ */
75
+ description: string;
76
+ /** Zod raw shape (object of Zod field schemas) — passed through to MCP SDK. */
77
+ inputSchema: S;
78
+ /**
79
+ * Optional MCP behavior hints (readOnlyHint, destructiveHint, etc.) so clients can
80
+ * flag token-spending write tools in their approval UI. Read tools may omit this.
81
+ */
82
+ annotations?: ToolAnnotations;
83
+ /** Returns the data payload to be JSON-stringified in the tool response. */
84
+ handler: (args: z.infer<z.ZodObject<S>>, ctx: HandlerContext) => Promise<unknown>;
85
+ }
86
+ /**
87
+ * Type-erased tool used by the registry. The MCP SDK validates `args` against
88
+ * `inputSchema` before calling `handler`, so `Record<string, unknown>` is sound
89
+ * at the call site even though each tool's handler internally expects a tighter
90
+ * inferred shape.
91
+ */
92
+ interface AnyTool {
93
+ name: string;
94
+ title: string;
95
+ description: string;
96
+ inputSchema: z.ZodRawShape;
97
+ annotations?: ToolAnnotations;
98
+ handler: (args: Record<string, unknown>, ctx: HandlerContext) => Promise<unknown>;
99
+ }
100
+
101
+ /**
102
+ * Builds the MCP server: registers each tool from the registry with the SDK.
103
+ *
104
+ * Error handling: if a tool handler throws (most commonly an ApiError from the
105
+ * HTTP client), we surface the message back through MCP as a tool-level error
106
+ * (`isError: true`). The LLM sees the message and can react — e.g. tell the
107
+ * user to regenerate their API key on a 401.
108
+ */
109
+
110
+ /**
111
+ * Returns the OAuth scope a tool call needs: SCOPE_READ for read-only tools,
112
+ * SCOPE_WRITE for the token-spending writes. Classification comes from the
113
+ * `readOnlyHint` annotation, which every tool in the registry carries.
114
+ */
115
+ declare function requiredScope(tool: Pick<AnyTool, "annotations">): string;
116
+ declare function buildServer(config: Config): McpServer;
117
+
118
+ /**
119
+ * Tool registry. The order here is the order tools appear in `tools/list`
120
+ * over the MCP transport, which biases LLM discovery — keep "discovery" tools
121
+ * (the ones that return IDs needed by other tools) at the top.
122
+ */
123
+
124
+ declare const allTools: ReadonlyArray<AnyTool>;
125
+
126
+ /**
127
+ * Error mapping for the DataDive /v1 API.
128
+ *
129
+ * The MCP server is a thin HTTP shim — when api.datadive.tools returns an error,
130
+ * we want the LLM (and ultimately the user) to see a useful, actionable message
131
+ * rather than "Request failed". `ApiError.fromHttp` turns an HTTP status + body
132
+ * into one of those messages.
133
+ *
134
+ * Source of truth for status semantics:
135
+ * datadive-backend/src/external-api/auth/api-key.guard.ts (401/402 logic)
136
+ * datadive-backend/src/external-api/external-api-v1.controller.ts (per-route docs)
137
+ */
138
+ type ApiErrorKind = "auth" | "payment" | "forbidden" | "not_found" | "bad_request" | "rate_limit" | "server" | "network" | "http";
139
+ declare class ApiError extends Error {
140
+ readonly kind: ApiErrorKind;
141
+ readonly status: number;
142
+ readonly body: unknown;
143
+ constructor(kind: ApiErrorKind, status: number, message: string, body?: unknown);
144
+ static fromHttp(status: number, body: unknown): ApiError;
145
+ }
146
+
147
+ /**
148
+ * HTTP client for the DataDive /v1 API.
149
+ *
150
+ * Responsibilities:
151
+ * 1. Attach auth from config.credentials to every request — `x-api-key` (local
152
+ * stdio path) or `Authorization: Bearer` (remote/OAuth path).
153
+ * 2. Tag the User-Agent with the package version + tool name so backend access
154
+ * logs can attribute usage per tool (no separate telemetry endpoint needed).
155
+ * 3. Map HTTP errors via `ApiError.fromHttp`.
156
+ * 4. Unwrap the `ResponseDto<T>` envelope (`{ message?, success?, data }`)
157
+ * while preserving bare `PaginationResponse<T>` bodies (which need their
158
+ * pagination metadata to reach the LLM).
159
+ *
160
+ * Envelope detection (verified against datadive-backend):
161
+ * - GET /v1/niches -> NicheList extends PaginationResponse<NicheItem> (BARE)
162
+ * - GET /v1/niches/rank-radars -> ResponseDto<ExternalRankRadarListResponseDto>
163
+ * where the inner DTO IS itself paginated.
164
+ * - All other read endpoints -> ResponseDto<T> (UNWRAP)
165
+ *
166
+ * Heuristic: if the body has `data` AND any pagination key (currentPage, lastPage,
167
+ * hasNext, hasPrev, pageSize, total), it's a PaginationResponse — return as-is.
168
+ * Otherwise if the body has `data`, it's a ResponseDto envelope — return body.data.
169
+ *
170
+ * Cite: datadive-backend/src/common/pagination/pagination.dto.ts (pagination keys)
171
+ * datadive-backend/src/common/dto/response.dto.ts (envelope shape)
172
+ */
173
+
174
+ /**
175
+ * The running package version, inlined from package.json at build time by
176
+ * tsup/esbuild (and by vite under vitest). Single source of truth — no manual
177
+ * bump here, so it can never drift from what's published to npm.
178
+ *
179
+ * Written into the User-Agent header, and compared against the backend's
180
+ * advertised latest version (see noteLatestVersion) to nudge stale installs.
181
+ */
182
+ declare const PKG_VERSION: string;
183
+
184
+ export { type AnyTool, ApiError, type Config, type Credentials, PKG_VERSION, SCOPE_READ, SCOPE_WRITE, type ToolDefinition, allTools, buildServer, loadConfig, requiredScope };