@dataville/dataville-mcp 0.1.0 → 0.1.2
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 +9 -1
- package/dist/client.js +32 -1
- package/dist/index.js +3 -3
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -43,5 +43,13 @@ npm run build
|
|
|
43
43
|
## Development
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
npm run dev
|
|
46
|
+
npm run dev # tsx watch
|
|
47
|
+
npm test # node test runner
|
|
48
|
+
npm run build # tsc
|
|
47
49
|
```
|
|
50
|
+
|
|
51
|
+
## Releasing
|
|
52
|
+
|
|
53
|
+
Publishes run from CI via npm trusted publishing (OIDC) — no tokens are stored.
|
|
54
|
+
To cut a release: bump the version, update `CHANGELOG.md`, then publish a GitHub
|
|
55
|
+
Release for the new tag. The `Publish` workflow builds, tests, and publishes to npm.
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const DEFAULT_BASE_URL = "https://api.dataville.com";
|
|
2
|
+
// Keep in sync with package.json version (enforced by a test).
|
|
3
|
+
export const VERSION = "0.1.2";
|
|
4
|
+
const USER_AGENT = `dataville-mcp/${VERSION}`;
|
|
2
5
|
export class DatavilleApiError extends Error {
|
|
3
6
|
status;
|
|
4
7
|
constructor(status, message) {
|
|
@@ -7,6 +10,21 @@ export class DatavilleApiError extends Error {
|
|
|
7
10
|
this.name = "DatavilleApiError";
|
|
8
11
|
}
|
|
9
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Raised when the API accepted the request but did not recognise our API key.
|
|
15
|
+
*
|
|
16
|
+
* Dataville's auth middleware never rejects outright — an unrecognised key
|
|
17
|
+
* falls through to anonymous access, which still returns data but under the
|
|
18
|
+
* much lower anonymous rate limit and without attributing usage to the
|
|
19
|
+
* account. Left unchecked that failure is invisible inside an MCP client, so
|
|
20
|
+
* we surface it explicitly instead of returning results that look fine.
|
|
21
|
+
*/
|
|
22
|
+
export class DatavilleAuthError extends Error {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "DatavilleAuthError";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
10
28
|
function getConfig() {
|
|
11
29
|
const apiKey = process.env.DATAVILLE_API_KEY;
|
|
12
30
|
if (!apiKey) {
|
|
@@ -24,7 +42,10 @@ export async function searchDataSource(source, keywords, params) {
|
|
|
24
42
|
}
|
|
25
43
|
}
|
|
26
44
|
const response = await fetch(url, {
|
|
27
|
-
headers: {
|
|
45
|
+
headers: {
|
|
46
|
+
Authorization: `Bearer ${apiKey}`,
|
|
47
|
+
"User-Agent": USER_AGENT,
|
|
48
|
+
},
|
|
28
49
|
});
|
|
29
50
|
const body = await response.json().catch(() => undefined);
|
|
30
51
|
if (!response.ok) {
|
|
@@ -32,5 +53,15 @@ export async function searchDataSource(source, keywords, params) {
|
|
|
32
53
|
`Dataville API request failed with status ${response.status}`;
|
|
33
54
|
throw new DatavilleApiError(response.status, message);
|
|
34
55
|
}
|
|
56
|
+
// We always send an API key, so an "anonymous" account state means the key
|
|
57
|
+
// was not accepted. Fail loudly rather than silently serving anonymous-tier
|
|
58
|
+
// results that are neither attributed nor billed to the user's account.
|
|
59
|
+
if (body &&
|
|
60
|
+
typeof body === "object" &&
|
|
61
|
+
body.account_state === "anonymous") {
|
|
62
|
+
throw new DatavilleAuthError("Your DATAVILLE_API_KEY was not recognised, so this request fell back to anonymous access " +
|
|
63
|
+
"(much lower rate limits, and usage is not attributed to your account). " +
|
|
64
|
+
"Check the key in your MCP client config, or generate a new one at https://app.dataville.com/api-keys.");
|
|
65
|
+
}
|
|
35
66
|
return body;
|
|
36
67
|
}
|
package/dist/index.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
import { searchDataSource,
|
|
5
|
+
import { searchDataSource, VERSION } from "./client.js";
|
|
6
6
|
import { DATAVILLE_SOURCES } from "./sources.js";
|
|
7
7
|
const server = new McpServer({
|
|
8
8
|
name: "dataville-mcp-server",
|
|
9
|
-
version:
|
|
9
|
+
version: VERSION,
|
|
10
10
|
});
|
|
11
11
|
server.registerTool("list_dataville_sources", {
|
|
12
12
|
title: "List Dataville data sources",
|
|
@@ -32,7 +32,7 @@ server.registerTool("search_dataville", {
|
|
|
32
32
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
33
33
|
}
|
|
34
34
|
catch (error) {
|
|
35
|
-
const message = error instanceof
|
|
35
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
36
36
|
return { content: [{ type: "text", text: message }], isError: true };
|
|
37
37
|
}
|
|
38
38
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dataville/dataville-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "MCP server exposing Dataville's data source API as tools for MCP clients",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,12 +12,17 @@
|
|
|
12
12
|
"bin": {
|
|
13
13
|
"dataville-mcp": "dist/index.js"
|
|
14
14
|
},
|
|
15
|
-
"files": [
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
16
20
|
"scripts": {
|
|
17
21
|
"build": "tsc",
|
|
18
22
|
"prepublishOnly": "npm run build",
|
|
19
23
|
"dev": "tsx watch src/index.ts",
|
|
20
|
-
"start": "node dist/index.js"
|
|
24
|
+
"start": "node dist/index.js",
|
|
25
|
+
"test": "tsx --test src/__tests__/*.test.ts"
|
|
21
26
|
},
|
|
22
27
|
"dependencies": {
|
|
23
28
|
"@modelcontextprotocol/sdk": "^1.12.0",
|