@cyanheads/wikidata-mcp-server 0.1.1
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/CLAUDE.md +401 -0
- package/Dockerfile +98 -0
- package/LICENSE +201 -0
- package/README.md +293 -0
- package/changelog/0.1.x/0.1.0.md +20 -0
- package/changelog/0.1.x/0.1.1.md +20 -0
- package/changelog/template.md +119 -0
- package/dist/config/server-config.d.ts +11 -0
- package/dist/config/server-config.d.ts.map +1 -0
- package/dist/config/server-config.js +31 -0
- package/dist/config/server-config.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/resources/definitions/entity.resource.d.ts +11 -0
- package/dist/mcp-server/resources/definitions/entity.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/entity.resource.js +127 -0
- package/dist/mcp-server/resources/definitions/entity.resource.js.map +1 -0
- package/dist/mcp-server/tools/definitions/get-entity.tool.d.ts +38 -0
- package/dist/mcp-server/tools/definitions/get-entity.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/get-entity.tool.js +215 -0
- package/dist/mcp-server/tools/definitions/get-entity.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/get-labels.tool.d.ts +24 -0
- package/dist/mcp-server/tools/definitions/get-labels.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/get-labels.tool.js +93 -0
- package/dist/mcp-server/tools/definitions/get-labels.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/get-sitelinks.tool.d.ts +31 -0
- package/dist/mcp-server/tools/definitions/get-sitelinks.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/get-sitelinks.tool.js +128 -0
- package/dist/mcp-server/tools/definitions/get-sitelinks.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/get-statements.tool.d.ts +29 -0
- package/dist/mcp-server/tools/definitions/get-statements.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/get-statements.tool.js +185 -0
- package/dist/mcp-server/tools/definitions/get-statements.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/resolve-external-id.tool.d.ts +30 -0
- package/dist/mcp-server/tools/definitions/resolve-external-id.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/resolve-external-id.tool.js +193 -0
- package/dist/mcp-server/tools/definitions/resolve-external-id.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts +36 -0
- package/dist/mcp-server/tools/definitions/search-entities.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/search-entities.tool.js +129 -0
- package/dist/mcp-server/tools/definitions/search-entities.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/sparql-query.tool.d.ts +34 -0
- package/dist/mcp-server/tools/definitions/sparql-query.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/sparql-query.tool.js +151 -0
- package/dist/mcp-server/tools/definitions/sparql-query.tool.js.map +1 -0
- package/dist/services/wikidata/types.d.ts +164 -0
- package/dist/services/wikidata/types.d.ts.map +1 -0
- package/dist/services/wikidata/types.js +6 -0
- package/dist/services/wikidata/types.js.map +1 -0
- package/dist/services/wikidata/wikidata-rest-service.d.ts +48 -0
- package/dist/services/wikidata/wikidata-rest-service.d.ts.map +1 -0
- package/dist/services/wikidata/wikidata-rest-service.js +293 -0
- package/dist/services/wikidata/wikidata-rest-service.js.map +1 -0
- package/dist/services/wikidata/wikidata-sparql-service.d.ts +23 -0
- package/dist/services/wikidata/wikidata-sparql-service.d.ts.map +1 -0
- package/dist/services/wikidata/wikidata-sparql-service.js +163 -0
- package/dist/services/wikidata/wikidata-sparql-service.js.map +1 -0
- package/package.json +82 -0
- package/server.json +141 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Server-specific configuration for wikidata-mcp-server.
|
|
3
|
+
* @module config/server-config
|
|
4
|
+
*/
|
|
5
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { parseEnvConfig } from '@cyanheads/mcp-ts-core/config';
|
|
7
|
+
const ServerConfigSchema = z.object({
|
|
8
|
+
userAgent: z
|
|
9
|
+
.string()
|
|
10
|
+
.default('wikidata-mcp-server/0.1 (https://github.com/cyanheads/wikidata-mcp-server)')
|
|
11
|
+
.describe('User-Agent string for Wikimedia requests. Wikimedia policy requires a descriptive User-Agent.'),
|
|
12
|
+
sparqlTimeoutMs: z.coerce
|
|
13
|
+
.number()
|
|
14
|
+
.default(55_000)
|
|
15
|
+
.describe('Max time to wait for a SPARQL response in milliseconds. Default: 55000 (just under the 60s hard server limit).'),
|
|
16
|
+
restTimeoutMs: z.coerce
|
|
17
|
+
.number()
|
|
18
|
+
.default(10_000)
|
|
19
|
+
.describe('Max time to wait for REST API responses in milliseconds. Default: 10000.'),
|
|
20
|
+
});
|
|
21
|
+
let _config;
|
|
22
|
+
/** Returns the lazy-parsed server configuration. */
|
|
23
|
+
export function getServerConfig() {
|
|
24
|
+
_config ??= parseEnvConfig(ServerConfigSchema, {
|
|
25
|
+
userAgent: 'WIKIDATA_USER_AGENT',
|
|
26
|
+
sparqlTimeoutMs: 'WIKIDATA_SPARQL_TIMEOUT_MS',
|
|
27
|
+
restTimeoutMs: 'WIKIDATA_REST_TIMEOUT_MS',
|
|
28
|
+
});
|
|
29
|
+
return _config;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=server-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,OAAO,CAAC,4EAA4E,CAAC;SACrF,QAAQ,CACP,+FAA+F,CAChG;IACH,eAAe,EAAE,CAAC,CAAC,MAAM;SACtB,MAAM,EAAE;SACR,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CACP,gHAAgH,CACjH;IACH,aAAa,EAAE,CAAC,CAAC,MAAM;SACpB,MAAM,EAAE;SACR,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,0EAA0E,CAAC;CACxF,CAAC,CAAC;AAEH,IAAI,OAAuD,CAAC;AAE5D,oDAAoD;AACpD,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,SAAS,EAAE,qBAAqB;QAChC,eAAe,EAAE,4BAA4B;QAC7C,aAAa,EAAE,0BAA0B;KAC1C,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview wikidata-mcp-server MCP server entry point.
|
|
4
|
+
* @module index
|
|
5
|
+
*/
|
|
6
|
+
import { createApp } from '@cyanheads/mcp-ts-core';
|
|
7
|
+
import { wikidataEntityResource } from './mcp-server/resources/definitions/entity.resource.js';
|
|
8
|
+
import { wikidataGetEntity } from './mcp-server/tools/definitions/get-entity.tool.js';
|
|
9
|
+
import { wikidataGetLabels } from './mcp-server/tools/definitions/get-labels.tool.js';
|
|
10
|
+
import { wikidataGetSitelinks } from './mcp-server/tools/definitions/get-sitelinks.tool.js';
|
|
11
|
+
import { wikidataGetStatements } from './mcp-server/tools/definitions/get-statements.tool.js';
|
|
12
|
+
import { wikidataResolveExternalId } from './mcp-server/tools/definitions/resolve-external-id.tool.js';
|
|
13
|
+
import { wikidataSearchEntities } from './mcp-server/tools/definitions/search-entities.tool.js';
|
|
14
|
+
import { wikidataSparqlQuery } from './mcp-server/tools/definitions/sparql-query.tool.js';
|
|
15
|
+
import { initWikidataRestService } from './services/wikidata/wikidata-rest-service.js';
|
|
16
|
+
import { initWikidataSparqlService } from './services/wikidata/wikidata-sparql-service.js';
|
|
17
|
+
await createApp({
|
|
18
|
+
tools: [
|
|
19
|
+
wikidataSearchEntities,
|
|
20
|
+
wikidataGetEntity,
|
|
21
|
+
wikidataGetLabels,
|
|
22
|
+
wikidataGetStatements,
|
|
23
|
+
wikidataGetSitelinks,
|
|
24
|
+
wikidataSparqlQuery,
|
|
25
|
+
wikidataResolveExternalId,
|
|
26
|
+
],
|
|
27
|
+
resources: [wikidataEntityResource],
|
|
28
|
+
prompts: [],
|
|
29
|
+
setup(core) {
|
|
30
|
+
initWikidataRestService(core.config, core.storage);
|
|
31
|
+
initWikidataSparqlService(core.config, core.storage);
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uDAAuD,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AACtF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AACtF,OAAO,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,uDAAuD,CAAC;AAC9F,OAAO,EAAE,yBAAyB,EAAE,MAAM,4DAA4D,CAAC;AACvG,OAAO,EAAE,sBAAsB,EAAE,MAAM,wDAAwD,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qDAAqD,CAAC;AAC1F,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAE,yBAAyB,EAAE,MAAM,gDAAgD,CAAC;AAE3F,MAAM,SAAS,CAAC;IACd,KAAK,EAAE;QACL,sBAAsB;QACtB,iBAAiB;QACjB,iBAAiB;QACjB,qBAAqB;QACrB,oBAAoB;QACpB,mBAAmB;QACnB,yBAAyB;KAC1B;IACD,SAAS,EAAE,CAAC,sBAAsB,CAAC;IACnC,OAAO,EAAE,EAAE;IACX,KAAK,CAAC,IAAI;QACR,uBAAuB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,yBAAyB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Wikidata entity resource — compact entity summary by QID or PID.
|
|
3
|
+
* @module mcp-server/resources/definitions/entity.resource
|
|
4
|
+
*/
|
|
5
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
export declare const wikidataEntityResource: import("@cyanheads/mcp-ts-core").ResourceDefinition<z.ZodObject<{
|
|
7
|
+
id: z.ZodString;
|
|
8
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
9
|
+
content: z.ZodString;
|
|
10
|
+
}, z.core.$strip>, undefined>;
|
|
11
|
+
//# sourceMappingURL=entity.resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/entity.resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AASrD,eAAO,MAAM,sBAAsB;;;;6BAsIjC,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Wikidata entity resource — compact entity summary by QID or PID.
|
|
3
|
+
* @module mcp-server/resources/definitions/entity.resource
|
|
4
|
+
*/
|
|
5
|
+
import { resource, z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { invalidParams, notFound } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
import { getWikidataRestService, isPId, isQId, normalizeId, } from '../../../services/wikidata/wikidata-rest-service.js';
|
|
8
|
+
export const wikidataEntityResource = resource('wikidata://entity/{id}', {
|
|
9
|
+
name: 'wikidata-entity',
|
|
10
|
+
description: 'Wikidata entity by QID or PID — labels (all languages), English description, ' +
|
|
11
|
+
'and a summary of key properties (instance-of P31, image P18, enwiki sitelink). ' +
|
|
12
|
+
'Formatted as compact markdown. For full entity data, use the wikidata_get_entity tool.',
|
|
13
|
+
mimeType: 'text/markdown',
|
|
14
|
+
params: z.object({
|
|
15
|
+
id: z.string().describe('Q-ID (e.g., "Q76") or P-ID (e.g., "P31") of the entity.'),
|
|
16
|
+
}),
|
|
17
|
+
output: z.object({
|
|
18
|
+
content: z.string().describe('Compact markdown summary of the entity.'),
|
|
19
|
+
}),
|
|
20
|
+
async handler(params, ctx) {
|
|
21
|
+
const id = normalizeId(params.id);
|
|
22
|
+
if (!isQId(id) && !isPId(id)) {
|
|
23
|
+
throw invalidParams(`"${params.id}" is not a valid Wikidata ID. Expected Q+digits (e.g., Q76) or P+digits (e.g., P31).`, { id: params.id });
|
|
24
|
+
}
|
|
25
|
+
const svc = getWikidataRestService();
|
|
26
|
+
ctx.log.info('Fetching entity resource', { id });
|
|
27
|
+
let entity;
|
|
28
|
+
try {
|
|
29
|
+
entity = await svc.fetchEntity(id, ctx);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
const e = err;
|
|
33
|
+
if (e?.data?.status === 404) {
|
|
34
|
+
throw notFound(`No Wikidata entity found for ID "${id}".`, { id }, { cause: err });
|
|
35
|
+
}
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
38
|
+
const lines = [];
|
|
39
|
+
// Header: ID + English label
|
|
40
|
+
const enLabel = entity.labels?.en?.value;
|
|
41
|
+
lines.push(`# ${enLabel ? `${enLabel} (${id})` : id}`);
|
|
42
|
+
// English description
|
|
43
|
+
const enDesc = entity.descriptions?.en?.value;
|
|
44
|
+
if (enDesc)
|
|
45
|
+
lines.push(`*${enDesc}*`);
|
|
46
|
+
lines.push('');
|
|
47
|
+
// Type/data_type
|
|
48
|
+
if (entity.type === 'property' && entity.data_type) {
|
|
49
|
+
lines.push(`**Type:** Property | **Data type:** ${entity.data_type}`);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
lines.push(`**Type:** ${entity.type}`);
|
|
53
|
+
}
|
|
54
|
+
// Instance of (P31)
|
|
55
|
+
const instanceOf = entity.statements?.P31;
|
|
56
|
+
if (instanceOf?.length) {
|
|
57
|
+
const values = instanceOf
|
|
58
|
+
.slice(0, 3)
|
|
59
|
+
.map((stmt) => {
|
|
60
|
+
const content = stmt.value?.content;
|
|
61
|
+
return content?.id ?? '?';
|
|
62
|
+
})
|
|
63
|
+
.join(', ');
|
|
64
|
+
lines.push(`**Instance of:** ${values} *(resolve with wikidata_get_labels)*`);
|
|
65
|
+
}
|
|
66
|
+
// Wikipedia link (enwiki sitelink)
|
|
67
|
+
const enwiki = entity.sitelinks?.enwiki;
|
|
68
|
+
if (enwiki?.url) {
|
|
69
|
+
lines.push(`**Wikipedia:** [${enwiki.title}](${enwiki.url})`);
|
|
70
|
+
}
|
|
71
|
+
else if (enwiki?.title) {
|
|
72
|
+
lines.push(`**Wikipedia:** ${enwiki.title}`);
|
|
73
|
+
}
|
|
74
|
+
// Image (P18)
|
|
75
|
+
const images = entity.statements?.P18;
|
|
76
|
+
if (images?.length) {
|
|
77
|
+
const firstImage = images[0];
|
|
78
|
+
const imgContent = firstImage?.value?.content;
|
|
79
|
+
if (typeof imgContent === 'string' && imgContent) {
|
|
80
|
+
lines.push(`**Image:** ${imgContent}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Labels summary
|
|
84
|
+
const labelCount = entity.labels ? Object.keys(entity.labels).length : 0;
|
|
85
|
+
if (labelCount > 0) {
|
|
86
|
+
lines.push('');
|
|
87
|
+
lines.push(`**Labels available:** ${labelCount} languages`);
|
|
88
|
+
const sample = Object.entries(entity.labels ?? {})
|
|
89
|
+
.slice(0, 5)
|
|
90
|
+
.map(([lang, lb]) => `${lang}: ${lb.value}`)
|
|
91
|
+
.join(' | ');
|
|
92
|
+
if (sample)
|
|
93
|
+
lines.push(sample);
|
|
94
|
+
}
|
|
95
|
+
// Statement count
|
|
96
|
+
const propCount = entity.statements ? Object.keys(entity.statements).length : 0;
|
|
97
|
+
if (propCount > 0) {
|
|
98
|
+
lines.push(`**Statements:** ${propCount} properties`);
|
|
99
|
+
}
|
|
100
|
+
lines.push('');
|
|
101
|
+
lines.push(`**Wikidata URL:** https://www.wikidata.org/wiki/${id}`);
|
|
102
|
+
return { content: lines.join('\n') };
|
|
103
|
+
},
|
|
104
|
+
list: () => ({
|
|
105
|
+
resources: [
|
|
106
|
+
{
|
|
107
|
+
uri: 'wikidata://entity/Q76',
|
|
108
|
+
name: 'Barack Obama (Q76)',
|
|
109
|
+
description: 'Example: Wikidata entity for Barack Obama',
|
|
110
|
+
mimeType: 'text/markdown',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
uri: 'wikidata://entity/Q42',
|
|
114
|
+
name: 'Douglas Adams (Q42)',
|
|
115
|
+
description: 'Example: Wikidata entity for Douglas Adams',
|
|
116
|
+
mimeType: 'text/markdown',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
uri: 'wikidata://entity/P31',
|
|
120
|
+
name: 'instance of (P31)',
|
|
121
|
+
description: 'Example: Wikidata property "instance of"',
|
|
122
|
+
mimeType: 'text/markdown',
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
}),
|
|
126
|
+
});
|
|
127
|
+
//# sourceMappingURL=entity.resource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/entity.resource.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Fetch a Wikidata entity by QID or PID with field selection.
|
|
3
|
+
* @module mcp-server/tools/definitions/get-entity.tool
|
|
4
|
+
*/
|
|
5
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
export declare const wikidataGetEntity: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
|
|
8
|
+
id: z.ZodString;
|
|
9
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
10
|
+
labels: "labels";
|
|
11
|
+
descriptions: "descriptions";
|
|
12
|
+
aliases: "aliases";
|
|
13
|
+
statements: "statements";
|
|
14
|
+
sitelinks: "sitelinks";
|
|
15
|
+
}>>>;
|
|
16
|
+
languages: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
17
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
18
|
+
id: z.ZodString;
|
|
19
|
+
type: z.ZodString;
|
|
20
|
+
data_type: z.ZodOptional<z.ZodString>;
|
|
21
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
22
|
+
descriptions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
23
|
+
aliases: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
|
|
24
|
+
statements: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodObject<{}, z.core.$loose>>>>;
|
|
25
|
+
sitelinks: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{}, z.core.$loose>>>;
|
|
26
|
+
fieldsReturned: z.ZodArray<z.ZodString>;
|
|
27
|
+
}, z.core.$strip>, readonly [{
|
|
28
|
+
readonly reason: "entity_not_found";
|
|
29
|
+
readonly code: JsonRpcErrorCode.NotFound;
|
|
30
|
+
readonly when: "No entity exists at this ID — the REST API returned resource-not-found.";
|
|
31
|
+
readonly recovery: "Verify the ID with wikidata_search_entities or check the Wikidata URL directly.";
|
|
32
|
+
}, {
|
|
33
|
+
readonly reason: "invalid_id";
|
|
34
|
+
readonly code: JsonRpcErrorCode.InvalidParams;
|
|
35
|
+
readonly when: "ID format is not recognized as a Q-ID or P-ID.";
|
|
36
|
+
readonly recovery: "Supply a valid Q-ID (Q followed by digits, e.g. Q76) or P-ID (P followed by digits, e.g. P31).";
|
|
37
|
+
}]>;
|
|
38
|
+
//# sourceMappingURL=get-entity.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-entity.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-entity.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAUjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmQ5B,CAAC"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Fetch a Wikidata entity by QID or PID with field selection.
|
|
3
|
+
* @module mcp-server/tools/definitions/get-entity.tool
|
|
4
|
+
*/
|
|
5
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
import { getWikidataRestService, isPId, isQId, normalizeId, } from '../../../services/wikidata/wikidata-rest-service.js';
|
|
8
|
+
const FIELD_ENUM = z.enum(['labels', 'descriptions', 'aliases', 'statements', 'sitelinks']);
|
|
9
|
+
export const wikidataGetEntity = tool('wikidata_get_entity', {
|
|
10
|
+
title: 'Get Wikidata Entity',
|
|
11
|
+
description: 'Fetch a Wikidata entity (item or property) by QID or PID. ' +
|
|
12
|
+
'The REST API always returns the full entity payload (300KB+ for major items like Q76 Barack Obama). ' +
|
|
13
|
+
'Use the fields parameter to trim what is returned to the caller — the network cost is fixed, ' +
|
|
14
|
+
'but the context budget benefit is real. Omit fields to get all data. ' +
|
|
15
|
+
'Q-IDs (e.g. Q76) fetch items; P-IDs (e.g. P31) fetch properties from the correct endpoint automatically. ' +
|
|
16
|
+
'Use wikidata_get_statements for deep claim traversal with label resolution.',
|
|
17
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
18
|
+
input: z.object({
|
|
19
|
+
id: z
|
|
20
|
+
.string()
|
|
21
|
+
.min(1)
|
|
22
|
+
.describe('Q-ID (e.g., "Q76") or P-ID (e.g., "P31"). Case-insensitive — normalized to uppercase.'),
|
|
23
|
+
fields: z
|
|
24
|
+
.array(FIELD_ENUM)
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('Fields to include in the response. Options: "labels", "descriptions", "aliases", "statements", "sitelinks". ' +
|
|
27
|
+
'Omit for all fields. Filtering is client-side — the full entity is always fetched from the API.'),
|
|
28
|
+
languages: z
|
|
29
|
+
.array(z.string())
|
|
30
|
+
.optional()
|
|
31
|
+
.describe('Language codes to include in labels, descriptions, and aliases (e.g., ["en", "de"]). ' +
|
|
32
|
+
'Omit to return all available languages.'),
|
|
33
|
+
}),
|
|
34
|
+
output: z.object({
|
|
35
|
+
id: z.string().describe('Normalized entity ID (e.g., "Q76" or "P31").'),
|
|
36
|
+
type: z.string().describe('Entity type: "item" or "property".'),
|
|
37
|
+
data_type: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe('Property data type (e.g., "wikibase-item", "external-id"). Present on properties only.'),
|
|
41
|
+
labels: z
|
|
42
|
+
.record(z.string(), z.string())
|
|
43
|
+
.optional()
|
|
44
|
+
.describe('Map of language code to label string (e.g., {"en": "Barack Obama", "de": "Barack Obama"}).'),
|
|
45
|
+
descriptions: z
|
|
46
|
+
.record(z.string(), z.string())
|
|
47
|
+
.optional()
|
|
48
|
+
.describe('Map of language code to description string (e.g., {"en": "44th President of the United States"}).'),
|
|
49
|
+
aliases: z
|
|
50
|
+
.record(z.string(), z.array(z.string()))
|
|
51
|
+
.optional()
|
|
52
|
+
.describe('Map of language code to list of alias strings (e.g., {"en": ["Barack H. Obama", "President Obama"]}).'),
|
|
53
|
+
statements: z
|
|
54
|
+
.record(z.string(), z.array(z.object({}).passthrough()))
|
|
55
|
+
.optional()
|
|
56
|
+
.describe('Map of property ID to array of raw statement objects. Use wikidata_get_statements for resolved claims with label resolution.'),
|
|
57
|
+
// Sitelink values are from a dynamic external API — passthrough preserves all nested fields
|
|
58
|
+
// (title, url, badges) in structuredContent without aspirational per-field typing.
|
|
59
|
+
sitelinks: z
|
|
60
|
+
.record(z.string(), z.object({}).passthrough())
|
|
61
|
+
.optional()
|
|
62
|
+
.describe('Map of site code (e.g., "enwiki") to sitelink metadata with title, url, and badges fields.'),
|
|
63
|
+
fieldsReturned: z.array(z.string()).describe('Which fields are included in this response.'),
|
|
64
|
+
}),
|
|
65
|
+
errors: [
|
|
66
|
+
{
|
|
67
|
+
reason: 'entity_not_found',
|
|
68
|
+
code: JsonRpcErrorCode.NotFound,
|
|
69
|
+
when: 'No entity exists at this ID — the REST API returned resource-not-found.',
|
|
70
|
+
recovery: 'Verify the ID with wikidata_search_entities or check the Wikidata URL directly.',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
reason: 'invalid_id',
|
|
74
|
+
code: JsonRpcErrorCode.InvalidParams,
|
|
75
|
+
when: 'ID format is not recognized as a Q-ID or P-ID.',
|
|
76
|
+
recovery: 'Supply a valid Q-ID (Q followed by digits, e.g. Q76) or P-ID (P followed by digits, e.g. P31).',
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
async handler(input, ctx) {
|
|
80
|
+
const id = normalizeId(input.id);
|
|
81
|
+
if (!isQId(id) && !isPId(id)) {
|
|
82
|
+
throw ctx.fail('invalid_id', `"${input.id}" is not a valid Wikidata ID. Expected Q+digits (item) or P+digits (property).`, { ...ctx.recoveryFor('invalid_id') });
|
|
83
|
+
}
|
|
84
|
+
const svc = getWikidataRestService();
|
|
85
|
+
ctx.log.info('Fetching Wikidata entity', {
|
|
86
|
+
id,
|
|
87
|
+
fields: input.fields,
|
|
88
|
+
languages: input.languages,
|
|
89
|
+
});
|
|
90
|
+
let entity;
|
|
91
|
+
try {
|
|
92
|
+
entity = await svc.fetchEntity(id, ctx);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
if (err?.data?.status === 404) {
|
|
96
|
+
throw ctx.fail('entity_not_found', `No entity found for ID "${id}".`, {
|
|
97
|
+
...ctx.recoveryFor('entity_not_found'),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
throw err;
|
|
101
|
+
}
|
|
102
|
+
// Determine which fields to include
|
|
103
|
+
const requestedFields = new Set(input.fields ?? ['labels', 'descriptions', 'aliases', 'statements', 'sitelinks']);
|
|
104
|
+
// Helper to filter language-keyed maps
|
|
105
|
+
const filterLangs = (map) => {
|
|
106
|
+
if (!map)
|
|
107
|
+
return;
|
|
108
|
+
if (!input.languages?.length)
|
|
109
|
+
return map;
|
|
110
|
+
const langSet = new Set(input.languages);
|
|
111
|
+
const filtered = Object.fromEntries(Object.entries(map).filter(([lang]) => langSet.has(lang)));
|
|
112
|
+
return Object.keys(filtered).length ? filtered : undefined;
|
|
113
|
+
};
|
|
114
|
+
// Flatten label/description maps from { language, value } → string
|
|
115
|
+
const flattenLabelMap = (map) => {
|
|
116
|
+
if (!map)
|
|
117
|
+
return;
|
|
118
|
+
return Object.fromEntries(Object.entries(map).map(([lang, entry]) => [lang, entry.value]));
|
|
119
|
+
};
|
|
120
|
+
const flattenAliasMap = (map) => {
|
|
121
|
+
if (!map)
|
|
122
|
+
return;
|
|
123
|
+
return Object.fromEntries(Object.entries(map).map(([lang, entries]) => [lang, entries.map((e) => e.value)]));
|
|
124
|
+
};
|
|
125
|
+
const result = {
|
|
126
|
+
id: entity.id,
|
|
127
|
+
type: entity.type,
|
|
128
|
+
fieldsReturned: [...requestedFields],
|
|
129
|
+
};
|
|
130
|
+
if (entity.data_type)
|
|
131
|
+
result.data_type = entity.data_type;
|
|
132
|
+
if (requestedFields.has('labels')) {
|
|
133
|
+
const labels = flattenLabelMap(filterLangs(entity.labels));
|
|
134
|
+
if (labels)
|
|
135
|
+
result.labels = labels;
|
|
136
|
+
}
|
|
137
|
+
if (requestedFields.has('descriptions')) {
|
|
138
|
+
const descriptions = flattenLabelMap(filterLangs(entity.descriptions));
|
|
139
|
+
if (descriptions)
|
|
140
|
+
result.descriptions = descriptions;
|
|
141
|
+
}
|
|
142
|
+
if (requestedFields.has('aliases')) {
|
|
143
|
+
const aliases = flattenAliasMap(filterLangs(entity.aliases));
|
|
144
|
+
if (aliases)
|
|
145
|
+
result.aliases = aliases;
|
|
146
|
+
}
|
|
147
|
+
if (requestedFields.has('statements') && entity.statements) {
|
|
148
|
+
result.statements = entity.statements;
|
|
149
|
+
}
|
|
150
|
+
if (requestedFields.has('sitelinks') && entity.sitelinks) {
|
|
151
|
+
result.sitelinks = Object.fromEntries(Object.entries(entity.sitelinks).map(([site, sl]) => [
|
|
152
|
+
site,
|
|
153
|
+
{
|
|
154
|
+
title: sl.title,
|
|
155
|
+
...(sl.url ? { url: sl.url } : {}),
|
|
156
|
+
...(sl.badges?.length ? { badges: sl.badges } : {}),
|
|
157
|
+
},
|
|
158
|
+
]));
|
|
159
|
+
}
|
|
160
|
+
// The output schema defines the full shape — result satisfies it at runtime
|
|
161
|
+
// even though the TypeScript type is widened to Record<string, unknown>.
|
|
162
|
+
return result;
|
|
163
|
+
},
|
|
164
|
+
format: (result) => {
|
|
165
|
+
const lines = [`## ${result.id} (${result.type})`];
|
|
166
|
+
if (result.data_type)
|
|
167
|
+
lines.push(`**Data type:** ${result.data_type}`);
|
|
168
|
+
lines.push(`**Fields returned:** ${result.fieldsReturned.join(', ')}`);
|
|
169
|
+
if (result.labels) {
|
|
170
|
+
const enLabel = result.labels.en;
|
|
171
|
+
const allLabels = Object.entries(result.labels)
|
|
172
|
+
.slice(0, 5)
|
|
173
|
+
.map(([lang, val]) => `${lang}: ${val}`)
|
|
174
|
+
.join(', ');
|
|
175
|
+
lines.push(`**Label:** ${enLabel ?? Object.values(result.labels)[0] ?? '(none)'}`);
|
|
176
|
+
if (Object.keys(result.labels).length > 1) {
|
|
177
|
+
lines.push(`**Labels (sample):** ${allLabels}${Object.keys(result.labels).length > 5 ? ` … (${Object.keys(result.labels).length} total)` : ''}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (result.descriptions) {
|
|
181
|
+
const enDesc = result.descriptions.en;
|
|
182
|
+
if (enDesc) {
|
|
183
|
+
lines.push(`**Description:** ${enDesc}`);
|
|
184
|
+
}
|
|
185
|
+
const otherDescs = Object.entries(result.descriptions)
|
|
186
|
+
.filter(([lang]) => lang !== 'en')
|
|
187
|
+
.slice(0, 3)
|
|
188
|
+
.map(([lang, val]) => `${lang}: ${val}`);
|
|
189
|
+
if (otherDescs.length)
|
|
190
|
+
lines.push(`**Descriptions (sample):** ${otherDescs.join(' | ')}`);
|
|
191
|
+
}
|
|
192
|
+
if (result.aliases) {
|
|
193
|
+
const allAliasEntries = Object.entries(result.aliases).slice(0, 3);
|
|
194
|
+
for (const [lang, aliases] of allAliasEntries) {
|
|
195
|
+
if (aliases.length) {
|
|
196
|
+
lines.push(`**Aliases (${lang}):** ${aliases.slice(0, 5).join(', ')}${aliases.length > 5 ? ` … (${aliases.length} total)` : ''}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (result.statements) {
|
|
201
|
+
const propCount = Object.keys(result.statements).length;
|
|
202
|
+
const claimCount = Object.values(result.statements).reduce((acc, stmts) => acc + stmts.length, 0);
|
|
203
|
+
lines.push(`**Statements:** ${propCount} properties, ${claimCount} total claims`);
|
|
204
|
+
}
|
|
205
|
+
if (result.sitelinks) {
|
|
206
|
+
const sitelinkCount = Object.keys(result.sitelinks).length;
|
|
207
|
+
const enwiki = result.sitelinks.enwiki;
|
|
208
|
+
lines.push(`**Sitelinks:** ${sitelinkCount} total`);
|
|
209
|
+
if (enwiki)
|
|
210
|
+
lines.push(`**Wikipedia (en):** ${enwiki.url ?? enwiki.title}`);
|
|
211
|
+
}
|
|
212
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
//# sourceMappingURL=get-entity.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-entity.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-entity.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Batch-resolve QIDs/PIDs to human-readable labels and descriptions.
|
|
3
|
+
* @module mcp-server/tools/definitions/get-labels.tool
|
|
4
|
+
*/
|
|
5
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
export declare const wikidataGetLabels: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
|
|
8
|
+
ids: z.ZodArray<z.ZodString>;
|
|
9
|
+
languages: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
10
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
11
|
+
entities: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
12
|
+
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
13
|
+
descriptions: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
14
|
+
}, z.core.$strip>>;
|
|
15
|
+
found: z.ZodNumber;
|
|
16
|
+
notFound: z.ZodArray<z.ZodString>;
|
|
17
|
+
languages: z.ZodArray<z.ZodString>;
|
|
18
|
+
}, z.core.$strip>, readonly [{
|
|
19
|
+
readonly reason: "invalid_ids";
|
|
20
|
+
readonly code: JsonRpcErrorCode.InvalidParams;
|
|
21
|
+
readonly when: "One or more IDs in the array are not valid Q-IDs or P-IDs.";
|
|
22
|
+
readonly recovery: "All IDs must match Q+digits or P+digits format (e.g., Q76, P31). Use wikidata_search_entities to find valid IDs.";
|
|
23
|
+
}]>;
|
|
24
|
+
//# sourceMappingURL=get-labels.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-labels.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-labels.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;GA8G5B,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Batch-resolve QIDs/PIDs to human-readable labels and descriptions.
|
|
3
|
+
* @module mcp-server/tools/definitions/get-labels.tool
|
|
4
|
+
*/
|
|
5
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
import { getWikidataRestService, normalizeId } from '../../../services/wikidata/wikidata-rest-service.js';
|
|
8
|
+
export const wikidataGetLabels = tool('wikidata_get_labels', {
|
|
9
|
+
title: 'Get Wikidata Labels',
|
|
10
|
+
description: 'Resolve one or more QIDs or PIDs to their human-readable labels and descriptions. ' +
|
|
11
|
+
'Lightweight — returns no claim data. Supports up to 50 IDs per call (batched automatically). ' +
|
|
12
|
+
'Designed for the common agent pattern: receive QIDs from a SPARQL query, then humanize them. ' +
|
|
13
|
+
'Uses the MediaWiki wbgetentities API for efficient batch resolution.',
|
|
14
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
15
|
+
input: z.object({
|
|
16
|
+
ids: z
|
|
17
|
+
.array(z.string().min(1))
|
|
18
|
+
.min(1)
|
|
19
|
+
.max(50)
|
|
20
|
+
.describe('Q-IDs (e.g., "Q76") or P-IDs (e.g., "P31") to resolve. 1–50 IDs per call.'),
|
|
21
|
+
languages: z
|
|
22
|
+
.array(z.string().min(1))
|
|
23
|
+
.min(1)
|
|
24
|
+
.default(['en'])
|
|
25
|
+
.describe('BCP 47 language codes for returned labels and descriptions (e.g., ["en", "de", "fr"]).'),
|
|
26
|
+
}),
|
|
27
|
+
output: z.object({
|
|
28
|
+
entities: z
|
|
29
|
+
.record(z.string(), z.object({
|
|
30
|
+
labels: z
|
|
31
|
+
.record(z.string(), z.string())
|
|
32
|
+
.describe('Map of language code to label string. Keys match the requested languages that have data.'),
|
|
33
|
+
descriptions: z
|
|
34
|
+
.record(z.string(), z.string())
|
|
35
|
+
.describe('Map of language code to description string. Keys match the requested languages that have data.'),
|
|
36
|
+
}))
|
|
37
|
+
.describe('Map of entity ID to labels and descriptions. IDs that were not found are absent.'),
|
|
38
|
+
found: z.number().describe('Count of IDs that returned data.'),
|
|
39
|
+
notFound: z
|
|
40
|
+
.array(z.string())
|
|
41
|
+
.describe('IDs from the request that did not return data (not found or invalid).'),
|
|
42
|
+
languages: z.array(z.string()).describe('The language codes that were requested.'),
|
|
43
|
+
}),
|
|
44
|
+
errors: [
|
|
45
|
+
{
|
|
46
|
+
reason: 'invalid_ids',
|
|
47
|
+
code: JsonRpcErrorCode.InvalidParams,
|
|
48
|
+
when: 'One or more IDs in the array are not valid Q-IDs or P-IDs.',
|
|
49
|
+
recovery: 'All IDs must match Q+digits or P+digits format (e.g., Q76, P31). Use wikidata_search_entities to find valid IDs.',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
async handler(input, ctx) {
|
|
53
|
+
// Validate all IDs
|
|
54
|
+
const normalized = input.ids.map(normalizeId);
|
|
55
|
+
const invalid = normalized.filter((id) => !/^[QP]\d+$/.test(id));
|
|
56
|
+
if (invalid.length > 0) {
|
|
57
|
+
throw ctx.fail('invalid_ids', `Invalid Wikidata IDs: ${invalid.join(', ')}. IDs must be Q+digits or P+digits.`, { invalid, ...ctx.recoveryFor('invalid_ids') });
|
|
58
|
+
}
|
|
59
|
+
const svc = getWikidataRestService();
|
|
60
|
+
ctx.log.info('Resolving labels', { count: normalized.length, languages: input.languages });
|
|
61
|
+
const labelData = await svc.fetchLabels(normalized, input.languages, ctx);
|
|
62
|
+
const notFound = normalized.filter((id) => !labelData[id]);
|
|
63
|
+
return {
|
|
64
|
+
entities: labelData,
|
|
65
|
+
found: Object.keys(labelData).length,
|
|
66
|
+
notFound,
|
|
67
|
+
languages: input.languages,
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
format: (result) => {
|
|
71
|
+
const lines = [
|
|
72
|
+
`**Languages:** ${result.languages.join(', ')} | **Found:** ${result.found}`,
|
|
73
|
+
];
|
|
74
|
+
if (result.notFound.length > 0) {
|
|
75
|
+
lines.push(`**Not found:** ${result.notFound.join(', ')}`);
|
|
76
|
+
}
|
|
77
|
+
lines.push('');
|
|
78
|
+
for (const [id, data] of Object.entries(result.entities)) {
|
|
79
|
+
const enLabel = data.labels.en ?? Object.values(data.labels)[0] ?? id;
|
|
80
|
+
const enDesc = data.descriptions.en ?? Object.values(data.descriptions)[0] ?? '';
|
|
81
|
+
lines.push(`**${id}:** ${enLabel}${enDesc ? ` — ${enDesc}` : ''}`);
|
|
82
|
+
// Show additional language labels if requested
|
|
83
|
+
const otherLangs = Object.entries(data.labels)
|
|
84
|
+
.filter(([lang]) => lang !== 'en')
|
|
85
|
+
.map(([lang, lbl]) => `${lang}: ${lbl}`)
|
|
86
|
+
.slice(0, 3);
|
|
87
|
+
if (otherLangs.length)
|
|
88
|
+
lines.push(` ${otherLangs.join(' | ')}`);
|
|
89
|
+
}
|
|
90
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=get-labels.tool.js.map
|