internetdata-mcp 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/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/schema.gen.d.ts +11 -0
- package/dist/schema.gen.js +272 -0
- package/dist/schema.gen.js.map +1 -0
- package/dist/stdio.d.ts +2 -0
- package/dist/stdio.js +29 -0
- package/dist/stdio.js.map +1 -0
- package/dist/tools.d.ts +21 -0
- package/dist/tools.js +232 -0
- package/dist/tools.js.map +1 -0
- package/package.json +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mslm Dev
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# [<img src="https://s3.internetdata.io/internetdata-public/brand/mark.svg" alt="InternetData" height="28"/>](https://internetdata.io/) InternetData MCP Server
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/internetdata-mcp)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
The official [Model Context Protocol](https://modelcontextprotocol.io) server for the [InternetData](https://internetdata.io) API.
|
|
7
|
+
|
|
8
|
+
InternetData publishes IP databases: VPN and proxy address space, hosting and CDN ranges, provider catalogs, bogons and more, as gzipped CSV and as MMDB. This server gives an AI agent four read-only tools over them - which databases your organization is licensed for, what is inside one, the digests to verify a copy you already hold, and your recent download history.
|
|
9
|
+
|
|
10
|
+
## Getting Started
|
|
11
|
+
|
|
12
|
+
You need an API key carrying the `db.download` scope. Databases are licensed by contract rather than bought self-serve, so a key arrives with the licence; see the [API documentation](https://docs.internetdata.io/api) or write to [dev@internetdata.io](mailto:dev@internetdata.io).
|
|
13
|
+
|
|
14
|
+
Add this to your MCP client's config:
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"mcpServers": {
|
|
19
|
+
"internetdata": {
|
|
20
|
+
"command": "npx",
|
|
21
|
+
"args": ["-y", "internetdata-mcp"],
|
|
22
|
+
"env": { "INTERNETDATA_API_KEY": "your-key" }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Then ask it something like *"which IP databases are we licensed for, and how big is the latest VPN build?"*.
|
|
29
|
+
|
|
30
|
+
Requires Node.js 22 or newer. `INTERNETDATA_BASE_URL` overrides the endpoint if you need to point somewhere else.
|
|
31
|
+
|
|
32
|
+
## Tools
|
|
33
|
+
|
|
34
|
+
| Tool | What it answers |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `list_databases` | The databases your organization is licensed for, with the licence type and term. |
|
|
37
|
+
| `database_metadata` | A database's columns, sample rows, row count, build date and file sizes. |
|
|
38
|
+
| `database_checksum` | The published digests for one database file. |
|
|
39
|
+
| `list_downloads` | Your organization's recent download attempts, refusals included. |
|
|
40
|
+
|
|
41
|
+
Every tool is read-only.
|
|
42
|
+
|
|
43
|
+
## Two spellings of a database id
|
|
44
|
+
|
|
45
|
+
`list_databases` answers a `base` id and a `versions` array:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"base": "vpn_ip",
|
|
50
|
+
"standing": "licensed",
|
|
51
|
+
"versions": [{ "id": "vpn_ip_v1", "version": 1, "formats": ["csvgz", "mmdb"] }]
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The `base` is what a **licence** names. `versions[].id` is what a **download** names, and it is the one `database_metadata` and `database_checksum` accept. The tools say so in their own descriptions, so an agent generally gets this right on its own; it is worth knowing when you read a transcript where one was refused.
|
|
56
|
+
|
|
57
|
+
## There is no download tool, deliberately
|
|
58
|
+
|
|
59
|
+
The published builds run to several GB, which is not something an agent should pull into a conversation. `database_metadata` is how you find out what a transfer would cost, and the [client libraries](https://github.com/internetdata) or the API are how you actually move the bytes.
|
|
60
|
+
|
|
61
|
+
## Reading the download history
|
|
62
|
+
|
|
63
|
+
`list_downloads` is a bounded window - at most 200 attempts, newest first - and it lists refusals alongside successes, because a denial and its `http_status` are what answer *"it stopped working"*. A database missing from the answer means it is not in that window, never that it was never fetched.
|
|
64
|
+
|
|
65
|
+
## Other Libraries
|
|
66
|
+
|
|
67
|
+
There are official InternetData client libraries available for many languages including PHP, Python, Go, Java, Ruby, and many popular frameworks such as Django, Rails, and Laravel. See our GitHub at https://github.com/internetdata for more.
|
|
68
|
+
|
|
69
|
+
## About InternetData
|
|
70
|
+
|
|
71
|
+
IP intelligence databases: VPN, proxy, hosting, CDN and relay address space, provider catalogs and network metadata, published as CSV and MMDB.
|
|
72
|
+
|
|
73
|
+
[<img src="https://s3.internetdata.io/internetdata-public/brand/mark.svg" alt="InternetData" width="96"/>](https://internetdata.io/)
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
This project is licensed under the [MIT License](LICENSE).
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const SPEC_VERSION = "2026.09.09";
|
|
2
|
+
export interface ObjectSchema {
|
|
3
|
+
type: 'object';
|
|
4
|
+
properties?: Record<string, object>;
|
|
5
|
+
required?: string[];
|
|
6
|
+
[k: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
export declare const DATABASE_SCHEMA: ObjectSchema;
|
|
9
|
+
export declare const DATABASE_METADATA_SCHEMA: ObjectSchema;
|
|
10
|
+
export declare const DB_CHECKSUMS_SCHEMA: ObjectSchema;
|
|
11
|
+
export declare const DOWNLOAD_SCHEMA: ObjectSchema;
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
// Code generated by scripts/gen-schema.mjs from spec/openapi.json. DO NOT EDIT.
|
|
2
|
+
export const SPEC_VERSION = '2026.09.09';
|
|
3
|
+
export const DATABASE_SCHEMA = {
|
|
4
|
+
"type": "object",
|
|
5
|
+
"description": "One database FAMILY, with your organization's licence beside it. A\nlicence covers the family, while a download names a specific version,\nso the ids passed to `download` and `checksum` come from `versions`.\n",
|
|
6
|
+
"required": [
|
|
7
|
+
"base",
|
|
8
|
+
"name",
|
|
9
|
+
"summary",
|
|
10
|
+
"standing",
|
|
11
|
+
"license_type",
|
|
12
|
+
"starts",
|
|
13
|
+
"expires",
|
|
14
|
+
"renews_at",
|
|
15
|
+
"notice_due_at",
|
|
16
|
+
"versions"
|
|
17
|
+
],
|
|
18
|
+
"properties": {
|
|
19
|
+
"base": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "The family, e.g. `vpn_ip`. What a licence is held against."
|
|
22
|
+
},
|
|
23
|
+
"name": {
|
|
24
|
+
"type": "string"
|
|
25
|
+
},
|
|
26
|
+
"summary": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "One line on what the newest version contains."
|
|
29
|
+
},
|
|
30
|
+
"standing": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"enum": [
|
|
33
|
+
"licensed",
|
|
34
|
+
"expired",
|
|
35
|
+
"unlicensed"
|
|
36
|
+
],
|
|
37
|
+
"description": "`licensed` is a live grant, `expired` one whose term has ended, and\n`unlicensed` a database published but never bought.\n"
|
|
38
|
+
},
|
|
39
|
+
"license_type": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"nullable": true,
|
|
42
|
+
"enum": [
|
|
43
|
+
"evaluation",
|
|
44
|
+
"standard",
|
|
45
|
+
"redistribute",
|
|
46
|
+
null
|
|
47
|
+
],
|
|
48
|
+
"description": "What your licence permits you to do with the data. Null when there\nis no licence.\n"
|
|
49
|
+
},
|
|
50
|
+
"starts": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"format": "date-time",
|
|
53
|
+
"nullable": true
|
|
54
|
+
},
|
|
55
|
+
"expires": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"format": "date-time",
|
|
58
|
+
"nullable": true,
|
|
59
|
+
"description": "A hard stop. Null when the licence has no end date, which is the normal case for a rolling agreement, and when there is no licence. A rolling licence reports its turnover date in renews_at instead."
|
|
60
|
+
},
|
|
61
|
+
"renews_at": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"format": "date-time",
|
|
64
|
+
"nullable": true,
|
|
65
|
+
"description": "When a rolling licence next renews. Null when the licence has no defined term, when expires sets a hard stop instead, and when there is no licence."
|
|
66
|
+
},
|
|
67
|
+
"notice_due_at": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"format": "date-time",
|
|
70
|
+
"nullable": true,
|
|
71
|
+
"description": "The last day notice of non-renewal can be given for the term ending at renews_at. Null whenever renews_at is, and when the agreement records no notice period."
|
|
72
|
+
},
|
|
73
|
+
"versions": {
|
|
74
|
+
"type": "array",
|
|
75
|
+
"description": "Every published version of this family, oldest first. Old versions\nare frozen rather than migrated, so both stay downloadable.\n",
|
|
76
|
+
"items": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"required": [
|
|
79
|
+
"id",
|
|
80
|
+
"version",
|
|
81
|
+
"summary",
|
|
82
|
+
"formats"
|
|
83
|
+
],
|
|
84
|
+
"properties": {
|
|
85
|
+
"id": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"description": "The versioned id. Pass this to `download`, `checksum` and `metadata`."
|
|
88
|
+
},
|
|
89
|
+
"version": {
|
|
90
|
+
"type": "integer"
|
|
91
|
+
},
|
|
92
|
+
"summary": {
|
|
93
|
+
"type": "string"
|
|
94
|
+
},
|
|
95
|
+
"formats": {
|
|
96
|
+
"type": "array",
|
|
97
|
+
"description": "The formats this version is BUILT in. Asking for another is a 400,\nnot a gap - the `_provider` catalogs are keyed by provider id, so no\nMMDB exists for them.\n",
|
|
98
|
+
"items": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"enum": [
|
|
101
|
+
"csvgz",
|
|
102
|
+
"mmdb"
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
export const DATABASE_METADATA_SCHEMA = {
|
|
112
|
+
"type": "object",
|
|
113
|
+
"description": "The build document written by the exporter, served through unchanged.",
|
|
114
|
+
"required": [
|
|
115
|
+
"id",
|
|
116
|
+
"updated",
|
|
117
|
+
"entries",
|
|
118
|
+
"schema",
|
|
119
|
+
"size"
|
|
120
|
+
],
|
|
121
|
+
"properties": {
|
|
122
|
+
"id": {
|
|
123
|
+
"type": "string"
|
|
124
|
+
},
|
|
125
|
+
"update_freq": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"description": "How often a new build is published."
|
|
128
|
+
},
|
|
129
|
+
"updated": {
|
|
130
|
+
"type": "string",
|
|
131
|
+
"format": "date",
|
|
132
|
+
"description": "ISO-8601 date (YYYY-MM-DD) the published build was generated on."
|
|
133
|
+
},
|
|
134
|
+
"entries": {
|
|
135
|
+
"type": "integer",
|
|
136
|
+
"format": "int64",
|
|
137
|
+
"description": "Row count in the current build."
|
|
138
|
+
},
|
|
139
|
+
"schema": {
|
|
140
|
+
"type": "object",
|
|
141
|
+
"description": "Columns, keyed by format.",
|
|
142
|
+
"additionalProperties": {
|
|
143
|
+
"type": "array",
|
|
144
|
+
"items": {
|
|
145
|
+
"type": "object",
|
|
146
|
+
"required": [
|
|
147
|
+
"name",
|
|
148
|
+
"type"
|
|
149
|
+
],
|
|
150
|
+
"properties": {
|
|
151
|
+
"name": {
|
|
152
|
+
"type": "string"
|
|
153
|
+
},
|
|
154
|
+
"type": {
|
|
155
|
+
"type": "string"
|
|
156
|
+
},
|
|
157
|
+
"description": {
|
|
158
|
+
"type": "string"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
"sample": {
|
|
165
|
+
"type": "object",
|
|
166
|
+
"description": "A few real rows, keyed by format.",
|
|
167
|
+
"additionalProperties": {
|
|
168
|
+
"type": "array",
|
|
169
|
+
"items": {
|
|
170
|
+
"type": "object"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"size": {
|
|
175
|
+
"type": "object",
|
|
176
|
+
"description": "Bytes per format.",
|
|
177
|
+
"additionalProperties": {
|
|
178
|
+
"type": "integer",
|
|
179
|
+
"format": "int64"
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
export const DB_CHECKSUMS_SCHEMA = {
|
|
185
|
+
"type": "object",
|
|
186
|
+
"required": [
|
|
187
|
+
"md5",
|
|
188
|
+
"sha1",
|
|
189
|
+
"sha256",
|
|
190
|
+
"sha512"
|
|
191
|
+
],
|
|
192
|
+
"properties": {
|
|
193
|
+
"md5": {
|
|
194
|
+
"type": "string",
|
|
195
|
+
"description": "Hex-encoded MD5 digest."
|
|
196
|
+
},
|
|
197
|
+
"sha1": {
|
|
198
|
+
"type": "string",
|
|
199
|
+
"description": "Hex-encoded SHA-1 digest."
|
|
200
|
+
},
|
|
201
|
+
"sha256": {
|
|
202
|
+
"type": "string",
|
|
203
|
+
"description": "Hex-encoded SHA-256 digest."
|
|
204
|
+
},
|
|
205
|
+
"sha512": {
|
|
206
|
+
"type": "string",
|
|
207
|
+
"description": "Hex-encoded SHA-512 digest."
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
export const DOWNLOAD_SCHEMA = {
|
|
212
|
+
"type": "object",
|
|
213
|
+
"description": "One download ATTEMPT, refusals included.",
|
|
214
|
+
"required": [
|
|
215
|
+
"dataset_id",
|
|
216
|
+
"format",
|
|
217
|
+
"outcome",
|
|
218
|
+
"bytes",
|
|
219
|
+
"http_status",
|
|
220
|
+
"apikey_id",
|
|
221
|
+
"client_ip",
|
|
222
|
+
"user_agent",
|
|
223
|
+
"created"
|
|
224
|
+
],
|
|
225
|
+
"properties": {
|
|
226
|
+
"dataset_id": {
|
|
227
|
+
"type": "string"
|
|
228
|
+
},
|
|
229
|
+
"format": {
|
|
230
|
+
"type": "string"
|
|
231
|
+
},
|
|
232
|
+
"outcome": {
|
|
233
|
+
"type": "string",
|
|
234
|
+
"enum": [
|
|
235
|
+
"ok",
|
|
236
|
+
"unauthorized",
|
|
237
|
+
"denied",
|
|
238
|
+
"expired",
|
|
239
|
+
"unknown",
|
|
240
|
+
"unavailable"
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
"bytes": {
|
|
244
|
+
"type": "integer",
|
|
245
|
+
"format": "int64",
|
|
246
|
+
"nullable": true,
|
|
247
|
+
"description": "Object size at redirect time, NOT bytes delivered: the transfer is a\npresigned redirect straight to object storage, so we never observe\nhow much of it was taken.\n"
|
|
248
|
+
},
|
|
249
|
+
"http_status": {
|
|
250
|
+
"type": "integer",
|
|
251
|
+
"nullable": true
|
|
252
|
+
},
|
|
253
|
+
"apikey_id": {
|
|
254
|
+
"type": "string",
|
|
255
|
+
"nullable": true,
|
|
256
|
+
"description": "The key that made the request. Null when it could not be resolved."
|
|
257
|
+
},
|
|
258
|
+
"client_ip": {
|
|
259
|
+
"type": "string",
|
|
260
|
+
"nullable": true
|
|
261
|
+
},
|
|
262
|
+
"user_agent": {
|
|
263
|
+
"type": "string",
|
|
264
|
+
"nullable": true
|
|
265
|
+
},
|
|
266
|
+
"created": {
|
|
267
|
+
"type": "string",
|
|
268
|
+
"format": "date-time"
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
//# sourceMappingURL=schema.gen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.gen.js","sourceRoot":"","sources":["../src/schema.gen.ts"],"names":[],"mappings":"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"}
|
package/dist/stdio.d.ts
ADDED
package/dist/stdio.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The stdio entry point: the process an MCP client spawns.
|
|
3
|
+
//
|
|
4
|
+
// This is the one file that reads the environment. The MCP specification tells
|
|
5
|
+
// stdio servers to take credentials that way rather than through the protocol's
|
|
6
|
+
// OAuth profile, and everything below it takes its configuration as arguments.
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
9
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
10
|
+
import { InternetData } from '@internetdata/internetdata';
|
|
11
|
+
import { createTools, registerTools } from './tools.js';
|
|
12
|
+
const version = createRequire(import.meta.url)('../package.json').version;
|
|
13
|
+
async function main() {
|
|
14
|
+
const apiKey = process.env['INTERNETDATA_API_KEY'];
|
|
15
|
+
const client = new InternetData({
|
|
16
|
+
...(apiKey === undefined || apiKey === '' ? {} : { apiKey: apiKey }),
|
|
17
|
+
...(process.env['INTERNETDATA_BASE_URL'] === undefined
|
|
18
|
+
? {} : { baseUrl: process.env['INTERNETDATA_BASE_URL'] }),
|
|
19
|
+
});
|
|
20
|
+
const server = new Server({ name: 'internetdata', version: version }, { capabilities: { tools: {} } });
|
|
21
|
+
registerTools(server, createTools({ client: client }));
|
|
22
|
+
await server.connect(new StdioServerTransport());
|
|
23
|
+
}
|
|
24
|
+
main().catch((err) => {
|
|
25
|
+
// stdout carries the protocol, so a diagnostic can only go to stderr.
|
|
26
|
+
console.error(err);
|
|
27
|
+
process.exitCode = 1;
|
|
28
|
+
});
|
|
29
|
+
//# sourceMappingURL=stdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":";AAEA,2DAA2D;AAC3D,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAExD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,OAAiB,CAAC;AAEpF,KAAK,UAAU,IAAI;IACf,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC;QAC5B,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QACpE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,KAAK,SAAS;YAClD,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,EAAE,CAAC;KAChE,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,MAAM,CACrB,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,EAC1C,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAClC,CAAC;IACF,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAEvD,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC1B,sEAAsE;IACtE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACzB,CAAC,CAAC,CAAC"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import type { CallToolResult, Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import type { InternetData } from '@internetdata/internetdata';
|
|
4
|
+
/** The most history rows one `list_downloads` call may ask for. The API clamps to the same. */
|
|
5
|
+
export declare const DOWNLOADS_LIMIT = 200;
|
|
6
|
+
export interface ToolContext {
|
|
7
|
+
client: InternetData;
|
|
8
|
+
}
|
|
9
|
+
export interface ToolDef {
|
|
10
|
+
tool: Tool;
|
|
11
|
+
handler: (args: Record<string, unknown>) => Promise<CallToolResult>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The tool manifest, and the single place either transport gets it from.
|
|
15
|
+
*
|
|
16
|
+
* Descriptions are read by a model rather than a developer, so they say what
|
|
17
|
+
* the tool answers and what it costs, not how it is implemented.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createTools(ctx: ToolContext): ToolDef[];
|
|
20
|
+
/** Mounts a manifest on a server. Both transports use this and nothing else. */
|
|
21
|
+
export declare function registerTools(server: Server, defs: ToolDef[]): void;
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { DATASET_FORMATS } from '@internetdata/internetdata';
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import { DATABASE_METADATA_SCHEMA, DATABASE_SCHEMA, DB_CHECKSUMS_SCHEMA, DOWNLOAD_SCHEMA, } from './schema.gen.js';
|
|
5
|
+
/** The most history rows one `list_downloads` call may ask for. The API clamps to the same. */
|
|
6
|
+
export const DOWNLOADS_LIMIT = 200;
|
|
7
|
+
// The formats come from the SDK's own exported vocabulary rather than a literal
|
|
8
|
+
// here. It is typed by the union generated from the spec, so a format this
|
|
9
|
+
// package spells wrong does not compile, and one the API adds arrives with a
|
|
10
|
+
// version bump instead of a silent divergence. The tuple cast is about z.enum
|
|
11
|
+
// wanting a non-empty tuple, not a claim about the wire.
|
|
12
|
+
const FORMATS = z.enum([...DATASET_FORMATS]);
|
|
13
|
+
// Both spellings of a dataset id, stated wherever one is taken. `list_databases`
|
|
14
|
+
// answers a `base` id (what a licence names) and a `versions[].id`; everything
|
|
15
|
+
// else accepts only the versioned one. A model that has just read
|
|
16
|
+
// `base: "bogon_ip"` will otherwise pass it and get a refusal that reads like a
|
|
17
|
+
// bad dataset rather than a wrong spelling.
|
|
18
|
+
const VERSIONED_ID = 'A VERSIONED database id, from `versions[].id` in `list_databases` - '
|
|
19
|
+
+ '`bogon_ip_v1`, not `bogon_ip`. The unversioned base id is a licence reference and is '
|
|
20
|
+
+ 'not accepted here.';
|
|
21
|
+
/**
|
|
22
|
+
* The tool manifest, and the single place either transport gets it from.
|
|
23
|
+
*
|
|
24
|
+
* Descriptions are read by a model rather than a developer, so they say what
|
|
25
|
+
* the tool answers and what it costs, not how it is implemented.
|
|
26
|
+
*/
|
|
27
|
+
export function createTools(ctx) {
|
|
28
|
+
const defs = [
|
|
29
|
+
{
|
|
30
|
+
tool: {
|
|
31
|
+
name: 'list_databases',
|
|
32
|
+
title: 'List databases',
|
|
33
|
+
description: 'The IP database catalog as this API key\'s organization may see it, '
|
|
34
|
+
+ 'one entry per database FAMILY, with `standing` saying where their licence '
|
|
35
|
+
+ 'stands: `licensed` if the family is theirs today, `expired` if the term has '
|
|
36
|
+
+ 'ended, `unlicensed` if it is published but has never been bought. Each entry '
|
|
37
|
+
+ 'has a `base` id, which is what a licence names, and a `versions` array whose '
|
|
38
|
+
+ '`id` is what the other tools take - pass `versions[].id` (`bogon_ip_v1`), '
|
|
39
|
+
+ 'never the `base` (`bogon_ip`). Ask again rather than holding on to this: it '
|
|
40
|
+
+ 'is answered per key and is not the same for everyone.',
|
|
41
|
+
inputSchema: { type: 'object', additionalProperties: false },
|
|
42
|
+
outputSchema: objectSchema({
|
|
43
|
+
databases: { type: 'array', items: DATABASE_SCHEMA },
|
|
44
|
+
}, ['databases']),
|
|
45
|
+
annotations: {
|
|
46
|
+
readOnlyHint: true,
|
|
47
|
+
idempotentHint: true,
|
|
48
|
+
openWorldHint: true,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
handler: async () => {
|
|
52
|
+
return ok({ databases: await ctx.client.database.list() });
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
tool: {
|
|
57
|
+
name: 'database_metadata',
|
|
58
|
+
title: 'Describe a database',
|
|
59
|
+
description: 'What is inside one database before you fetch it: the columns in each '
|
|
60
|
+
+ 'published format with their types, a few sample rows, the row count, the '
|
|
61
|
+
+ 'build date and the file sizes. Use this to answer questions about what a '
|
|
62
|
+
+ 'database contains without downloading it - the files reach several GB - and '
|
|
63
|
+
+ 'to budget a transfer before starting one.',
|
|
64
|
+
inputSchema: jsonSchema(z.object({
|
|
65
|
+
dataset_id: z.string().describe(VERSIONED_ID),
|
|
66
|
+
})),
|
|
67
|
+
outputSchema: DATABASE_METADATA_SCHEMA,
|
|
68
|
+
annotations: {
|
|
69
|
+
readOnlyHint: true,
|
|
70
|
+
idempotentHint: true,
|
|
71
|
+
openWorldHint: true,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
handler: async (args) => {
|
|
75
|
+
const { dataset_id } = z.object({ dataset_id: z.string() }).parse(args);
|
|
76
|
+
return ok(await ctx.client.database.metadata(dataset_id));
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
tool: {
|
|
81
|
+
name: 'database_checksum',
|
|
82
|
+
title: 'Get a database\'s checksums',
|
|
83
|
+
description: 'The published digests for one database file, for verifying a copy '
|
|
84
|
+
+ 'you already hold or deciding whether a build has changed since you last '
|
|
85
|
+
+ 'fetched it.',
|
|
86
|
+
inputSchema: jsonSchema(z.object({
|
|
87
|
+
dataset_id: z.string().describe(VERSIONED_ID),
|
|
88
|
+
format: FORMATS.describe('Which published file to digest.'),
|
|
89
|
+
})),
|
|
90
|
+
outputSchema: objectSchema({ checksums: DB_CHECKSUMS_SCHEMA }, ['checksums']),
|
|
91
|
+
annotations: {
|
|
92
|
+
readOnlyHint: true,
|
|
93
|
+
idempotentHint: true,
|
|
94
|
+
openWorldHint: true,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
handler: async (args) => {
|
|
98
|
+
const parsed = z.object({
|
|
99
|
+
dataset_id: z.string(),
|
|
100
|
+
format: FORMATS,
|
|
101
|
+
}).parse(args);
|
|
102
|
+
const checksums = await ctx.client.database.checksums(parsed.dataset_id, parsed.format);
|
|
103
|
+
return ok({ checksums: checksums });
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
tool: {
|
|
108
|
+
name: 'list_downloads',
|
|
109
|
+
title: 'List recent download attempts',
|
|
110
|
+
description: 'This organization\'s own recent download attempts, newest first, '
|
|
111
|
+
+ 'REFUSALS INCLUDED - a denial carries the `outcome` and `http_status` that '
|
|
112
|
+
+ 'answer "it stopped working", which nothing else here can. Use it to explain '
|
|
113
|
+
+ 'a failing fetch, to confirm a transfer ran, or to check whether a request '
|
|
114
|
+
+ 'was theirs. This is a bounded WINDOW of at most '
|
|
115
|
+
+ `${DOWNLOADS_LIMIT} rows, so a database missing from the answer means it is `
|
|
116
|
+
+ 'not in this window - never that it was never downloaded.',
|
|
117
|
+
inputSchema: jsonSchema(z.object({
|
|
118
|
+
limit: z.number().int().min(1).max(DOWNLOADS_LIMIT).optional().describe(`How many attempts to return, newest first. At most ${DOWNLOADS_LIMIT}; `
|
|
119
|
+
+ 'the API defaults to 50.'),
|
|
120
|
+
})),
|
|
121
|
+
outputSchema: objectSchema({
|
|
122
|
+
downloads: { type: 'array', items: DOWNLOAD_SCHEMA },
|
|
123
|
+
}, ['downloads']),
|
|
124
|
+
annotations: {
|
|
125
|
+
readOnlyHint: true,
|
|
126
|
+
idempotentHint: false,
|
|
127
|
+
openWorldHint: true,
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
handler: async (args) => {
|
|
131
|
+
const { limit } = z.object({
|
|
132
|
+
limit: z.number().int().min(1).max(DOWNLOADS_LIMIT).optional(),
|
|
133
|
+
}).parse(args);
|
|
134
|
+
const downloads = await ctx.client.database.downloads(limit === undefined ? {} : { limit: limit });
|
|
135
|
+
return ok({ downloads: downloads });
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
// A handler NEVER throws: an upstream 404 or a rejected argument is a result
|
|
140
|
+
// the model can read and correct itself from, while a JSON-RPC protocol error
|
|
141
|
+
// is not. Wrapping here rather than in `registerTools` keeps that true for
|
|
142
|
+
// any consumer of a ToolDef, including a transport that mounts its own.
|
|
143
|
+
return defs.map((d) => ({ tool: d.tool, handler: guard(d.handler) }));
|
|
144
|
+
}
|
|
145
|
+
/** Mounts a manifest on a server. Both transports use this and nothing else. */
|
|
146
|
+
export function registerTools(server, defs) {
|
|
147
|
+
const byName = new Map(defs.map((d) => [d.tool.name, d]));
|
|
148
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
149
|
+
return { tools: defs.map((d) => d.tool) };
|
|
150
|
+
});
|
|
151
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
152
|
+
const def = byName.get(req.params.name);
|
|
153
|
+
if (def === undefined) {
|
|
154
|
+
throw new Error(`Unknown tool: ${req.params.name}`);
|
|
155
|
+
}
|
|
156
|
+
return await def.handler(req.params.arguments ?? {});
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function guard(handler) {
|
|
160
|
+
return async (args) => {
|
|
161
|
+
try {
|
|
162
|
+
return await handler(args);
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
return toolError(err);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* The serialized structured content IS the text block, rather than a prose
|
|
171
|
+
* summary beside it. Writing it once puts the same answer in front of a client
|
|
172
|
+
* that reads `structuredContent` and one that only renders `content`.
|
|
173
|
+
*/
|
|
174
|
+
function ok(structured) {
|
|
175
|
+
return {
|
|
176
|
+
content: [{ type: 'text', text: JSON.stringify(structured, null, 2) }],
|
|
177
|
+
structuredContent: structured,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* An error carries no `structuredContent`, deliberately.
|
|
182
|
+
*
|
|
183
|
+
* A tool that declares an `outputSchema` has every structured result validated
|
|
184
|
+
* against it by the client, and an error is not shaped like a success - so
|
|
185
|
+
* attaching one turns a readable failure into a protocol error the model cannot
|
|
186
|
+
* act on. The text block is what it reads instead.
|
|
187
|
+
*/
|
|
188
|
+
function toolError(err) {
|
|
189
|
+
const known = asClientError(err);
|
|
190
|
+
const detail = known !== undefined
|
|
191
|
+
? { kind: known.kind, message: known.message, retryable: known.retryable === true }
|
|
192
|
+
: { kind: 'internal', message: err instanceof Error ? err.message : String(err) };
|
|
193
|
+
return {
|
|
194
|
+
content: [{ type: 'text', text: JSON.stringify({ error: detail }, null, 2) }],
|
|
195
|
+
isError: true,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Recognises an `InternetDataError` by SHAPE, not by `instanceof`.
|
|
200
|
+
*
|
|
201
|
+
* This package and whatever mounts it can each end up with their own copy of
|
|
202
|
+
* the `@internetdata/internetdata` module - the hosted service depends on both -
|
|
203
|
+
* and two copies of one class are two identities, so `instanceof` silently
|
|
204
|
+
* returns false and every upstream failure degrades to a generic `internal`. A
|
|
205
|
+
* caller then sees "internal" for what was really `forbidden`, and loses the
|
|
206
|
+
* `retryable` flag that decides whether trying again is worth anything.
|
|
207
|
+
*/
|
|
208
|
+
function asClientError(err) {
|
|
209
|
+
if (err === null || typeof err !== 'object') {
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
const e = err;
|
|
213
|
+
if (e.name !== 'InternetDataError' || typeof e.kind !== 'string') {
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
return e;
|
|
217
|
+
}
|
|
218
|
+
// One zod declaration yields both the published schema and the runtime parse, so
|
|
219
|
+
// a cap advertised to a client is the same cap the handler enforces.
|
|
220
|
+
function jsonSchema(schema) {
|
|
221
|
+
const out = z.toJSONSchema(schema, { io: 'input' });
|
|
222
|
+
delete out['$schema'];
|
|
223
|
+
return { ...out, type: 'object' };
|
|
224
|
+
}
|
|
225
|
+
function objectSchema(properties, required) {
|
|
226
|
+
return {
|
|
227
|
+
type: 'object',
|
|
228
|
+
properties: properties,
|
|
229
|
+
required: required,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "internetdata-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official MCP server for the InternetData API. Lets an LLM agent browse the IP databases an organization is licensed for, inspect what is inside one, and verify a copy it already holds.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://internetdata.io",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/internetdata/mcp.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/internetdata/mcp/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"model-context-protocol",
|
|
18
|
+
"ip-database",
|
|
19
|
+
"ip-intelligence",
|
|
20
|
+
"ip-data",
|
|
21
|
+
"mmdb",
|
|
22
|
+
"maxmind-db",
|
|
23
|
+
"dataset",
|
|
24
|
+
"llm",
|
|
25
|
+
"agent"
|
|
26
|
+
],
|
|
27
|
+
"main": "./dist/index.js",
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"bin": {
|
|
30
|
+
"internetdata-mcp": "./dist/stdio.js"
|
|
31
|
+
},
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./tools": {
|
|
38
|
+
"types": "./dist/tools.d.ts",
|
|
39
|
+
"default": "./dist/tools.js"
|
|
40
|
+
},
|
|
41
|
+
"./package.json": "./package.json"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"README.md",
|
|
46
|
+
"LICENSE"
|
|
47
|
+
],
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=22"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@internetdata/internetdata": "^1.2.1",
|
|
53
|
+
"@modelcontextprotocol/sdk": "^1.20.2",
|
|
54
|
+
"zod": "^4.1.12"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@types/node": "^26.2.0",
|
|
58
|
+
"ajv": "^8.20.0",
|
|
59
|
+
"ajv-formats": "^3.0.1",
|
|
60
|
+
"typescript": "^5.9.3"
|
|
61
|
+
},
|
|
62
|
+
"scripts": {
|
|
63
|
+
"generate": "node scripts/gen-schema.mjs",
|
|
64
|
+
"build": "rm -rf dist && pnpm run generate && tsc",
|
|
65
|
+
"test": "pnpm run build && node --test test/*.test.mjs"
|
|
66
|
+
}
|
|
67
|
+
}
|