@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/README.md +23 -8
- package/dist/index.js +153 -62
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +184 -0
- package/dist/lib.js +909 -0
- package/dist/lib.js.map +1 -0
- package/package.json +11 -3
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 };
|