@cyanheads/orcid-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.
Files changed (64) hide show
  1. package/CLAUDE.md +405 -0
  2. package/Dockerfile +98 -0
  3. package/README.md +321 -0
  4. package/changelog/0.1.x/0.1.0.md +20 -0
  5. package/changelog/0.1.x/0.1.1.md +13 -0
  6. package/changelog/template.md +119 -0
  7. package/dist/config/server-config.d.ts +12 -0
  8. package/dist/config/server-config.d.ts.map +1 -0
  9. package/dist/config/server-config.js +22 -0
  10. package/dist/config/server-config.js.map +1 -0
  11. package/dist/index.d.ts +8 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +35 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/mcp-server/resources/definitions/researcher-profile.resource.d.ts +24 -0
  16. package/dist/mcp-server/resources/definitions/researcher-profile.resource.d.ts.map +1 -0
  17. package/dist/mcp-server/resources/definitions/researcher-profile.resource.js +62 -0
  18. package/dist/mcp-server/resources/definitions/researcher-profile.resource.js.map +1 -0
  19. package/dist/mcp-server/resources/definitions/researcher-works.resource.d.ts +24 -0
  20. package/dist/mcp-server/resources/definitions/researcher-works.resource.d.ts.map +1 -0
  21. package/dist/mcp-server/resources/definitions/researcher-works.resource.js +60 -0
  22. package/dist/mcp-server/resources/definitions/researcher-works.resource.js.map +1 -0
  23. package/dist/mcp-server/tools/definitions/get-affiliations.tool.d.ts +47 -0
  24. package/dist/mcp-server/tools/definitions/get-affiliations.tool.d.ts.map +1 -0
  25. package/dist/mcp-server/tools/definitions/get-affiliations.tool.js +170 -0
  26. package/dist/mcp-server/tools/definitions/get-affiliations.tool.js.map +1 -0
  27. package/dist/mcp-server/tools/definitions/get-funding.tool.d.ts +36 -0
  28. package/dist/mcp-server/tools/definitions/get-funding.tool.d.ts.map +1 -0
  29. package/dist/mcp-server/tools/definitions/get-funding.tool.js +140 -0
  30. package/dist/mcp-server/tools/definitions/get-funding.tool.js.map +1 -0
  31. package/dist/mcp-server/tools/definitions/get-peer-reviews.tool.d.ts +35 -0
  32. package/dist/mcp-server/tools/definitions/get-peer-reviews.tool.d.ts.map +1 -0
  33. package/dist/mcp-server/tools/definitions/get-peer-reviews.tool.js +146 -0
  34. package/dist/mcp-server/tools/definitions/get-peer-reviews.tool.js.map +1 -0
  35. package/dist/mcp-server/tools/definitions/get-profile.tool.d.ts +39 -0
  36. package/dist/mcp-server/tools/definitions/get-profile.tool.d.ts.map +1 -0
  37. package/dist/mcp-server/tools/definitions/get-profile.tool.js +146 -0
  38. package/dist/mcp-server/tools/definitions/get-profile.tool.js.map +1 -0
  39. package/dist/mcp-server/tools/definitions/get-works.tool.d.ts +35 -0
  40. package/dist/mcp-server/tools/definitions/get-works.tool.d.ts.map +1 -0
  41. package/dist/mcp-server/tools/definitions/get-works.tool.js +127 -0
  42. package/dist/mcp-server/tools/definitions/get-works.tool.js.map +1 -0
  43. package/dist/mcp-server/tools/definitions/resolve-researcher.tool.d.ts +46 -0
  44. package/dist/mcp-server/tools/definitions/resolve-researcher.tool.d.ts.map +1 -0
  45. package/dist/mcp-server/tools/definitions/resolve-researcher.tool.js +250 -0
  46. package/dist/mcp-server/tools/definitions/resolve-researcher.tool.js.map +1 -0
  47. package/dist/mcp-server/tools/definitions/search-researchers.tool.d.ts +40 -0
  48. package/dist/mcp-server/tools/definitions/search-researchers.tool.d.ts.map +1 -0
  49. package/dist/mcp-server/tools/definitions/search-researchers.tool.js +192 -0
  50. package/dist/mcp-server/tools/definitions/search-researchers.tool.js.map +1 -0
  51. package/dist/services/orcid/normalizers.d.ts +32 -0
  52. package/dist/services/orcid/normalizers.d.ts.map +1 -0
  53. package/dist/services/orcid/normalizers.js +256 -0
  54. package/dist/services/orcid/normalizers.js.map +1 -0
  55. package/dist/services/orcid/orcid-service.d.ts +65 -0
  56. package/dist/services/orcid/orcid-service.d.ts.map +1 -0
  57. package/dist/services/orcid/orcid-service.js +140 -0
  58. package/dist/services/orcid/orcid-service.js.map +1 -0
  59. package/dist/services/orcid/types.d.ts +335 -0
  60. package/dist/services/orcid/types.d.ts.map +1 -0
  61. package/dist/services/orcid/types.js +6 -0
  62. package/dist/services/orcid/types.js.map +1 -0
  63. package/package.json +79 -0
  64. package/server.json +99 -0
@@ -0,0 +1,256 @@
1
+ /**
2
+ * @fileoverview Normalization functions that convert raw ORCID API shapes to
3
+ * typed domain objects. Preserves absence as unknown rather than inventing defaults.
4
+ * @module services/orcid/normalizers
5
+ */
6
+ // ---------------------------------------------------------------------------
7
+ // Helpers
8
+ // ---------------------------------------------------------------------------
9
+ function normalizeDate(d) {
10
+ if (!d?.year?.value)
11
+ return;
12
+ const y = d.year.value;
13
+ const m = d.month?.value?.padStart(2, '0');
14
+ const day = d.day?.value?.padStart(2, '0');
15
+ if (m && day)
16
+ return `${y}-${m}-${day}`;
17
+ if (m)
18
+ return `${y}-${m}`;
19
+ return y;
20
+ }
21
+ function normalizeOrg(raw) {
22
+ if (!raw)
23
+ return;
24
+ const dis = raw['disambiguated-organization'];
25
+ const result = {};
26
+ if (raw.name)
27
+ result.name = raw.name;
28
+ if (raw.address?.city)
29
+ result.city = raw.address.city;
30
+ if (raw.address?.country)
31
+ result.country = raw.address.country;
32
+ if (dis?.['disambiguated-organization-identifier']) {
33
+ result.disambiguatedId = dis['disambiguated-organization-identifier'];
34
+ }
35
+ if (dis?.['disambiguation-source']) {
36
+ result.disambiguationSource = dis['disambiguation-source'];
37
+ }
38
+ return Object.keys(result).length > 0 ? result : undefined;
39
+ }
40
+ function normalizeExternalId(raw) {
41
+ if (!raw['external-id-type'] || !raw['external-id-value'])
42
+ return;
43
+ return {
44
+ type: raw['external-id-type'],
45
+ value: raw['external-id-value'],
46
+ ...(raw['external-id-url']?.value && { url: raw['external-id-url'].value }),
47
+ ...(raw['external-id-relationship'] && { relationship: raw['external-id-relationship'] }),
48
+ };
49
+ }
50
+ function normalizeExternalIds(raw) {
51
+ if (!raw?.length)
52
+ return [];
53
+ return raw.map(normalizeExternalId).filter((id) => id !== undefined);
54
+ }
55
+ function normalizeSummary(raw, type) {
56
+ const org = normalizeOrg(raw.organization);
57
+ const aff = { type };
58
+ if (org)
59
+ aff.organization = org;
60
+ if (raw['department-name'])
61
+ aff.department = raw['department-name'];
62
+ if (raw['role-title'])
63
+ aff.role = raw['role-title'];
64
+ const start = normalizeDate(raw['start-date']);
65
+ if (start)
66
+ aff.startDate = start;
67
+ const end = normalizeDate(raw['end-date']);
68
+ if (end)
69
+ aff.endDate = end;
70
+ if (raw.url?.value)
71
+ aff.url = raw.url.value;
72
+ return aff;
73
+ }
74
+ function extractSummariesFromGroup(group, type) {
75
+ if (!group)
76
+ return [];
77
+ const summaries = group['affiliation-summary'] ?? group.summaries ?? [];
78
+ return summaries.map((s) => normalizeSummary(s, type));
79
+ }
80
+ function extractGroupSummaries(groups, type) {
81
+ return (groups ?? []).flatMap((g) => extractSummariesFromGroup(g, type));
82
+ }
83
+ export function normalizePerson(raw) {
84
+ const name = raw.name;
85
+ const result = {
86
+ keywords: [],
87
+ researcherUrls: [],
88
+ externalIdentifiers: [],
89
+ emails: [],
90
+ countries: [],
91
+ };
92
+ const givenNames = name?.['given-names']?.value;
93
+ if (givenNames)
94
+ result.givenNames = givenNames;
95
+ const familyName = name?.['family-name']?.value;
96
+ if (familyName)
97
+ result.familyName = familyName;
98
+ const creditName = name?.['credit-name']?.value;
99
+ if (creditName)
100
+ result.creditName = creditName;
101
+ const biography = raw.biography?.content?.trim() || undefined;
102
+ if (biography)
103
+ result.biography = biography;
104
+ result.keywords = raw.keywords?.keyword?.map((k) => k.content ?? '').filter(Boolean) ?? [];
105
+ result.researcherUrls =
106
+ raw['researcher-urls']?.['researcher-url']?.flatMap((u) => {
107
+ const url = u.url?.value;
108
+ if (!url)
109
+ return [];
110
+ const entry = { url };
111
+ if (u['url-name'])
112
+ entry.name = u['url-name'];
113
+ return [entry];
114
+ }) ?? [];
115
+ result.externalIdentifiers = normalizeExternalIds(raw['external-identifiers']?.['external-identifier']);
116
+ result.emails =
117
+ raw.emails?.email?.flatMap((e) => {
118
+ if (!e.email)
119
+ return [];
120
+ const entry = { email: e.email };
121
+ if (typeof e.primary === 'boolean')
122
+ entry.primary = e.primary;
123
+ return [entry];
124
+ }) ?? [];
125
+ result.countries =
126
+ raw.addresses?.address?.flatMap((a) => {
127
+ const c = a.country?.value;
128
+ return c ? [c] : [];
129
+ }) ?? [];
130
+ return result;
131
+ }
132
+ function normalizeWorkSummary(raw) {
133
+ const externalIds = normalizeExternalIds(raw['external-ids']?.['external-id']);
134
+ const work = { externalIds };
135
+ const title = raw.title?.title?.value;
136
+ if (title)
137
+ work.title = title;
138
+ if (raw['work-type'])
139
+ work.workType = raw['work-type'];
140
+ const pubDate = normalizeDate(raw['publication-date']);
141
+ if (pubDate)
142
+ work.publicationDate = pubDate;
143
+ if (raw['journal-title']?.value)
144
+ work.journalTitle = raw['journal-title'].value;
145
+ if (raw.url?.value)
146
+ work.url = raw.url.value;
147
+ return work;
148
+ }
149
+ export function normalizeWorks(raw) {
150
+ return (raw.group ?? []).flatMap((g) => {
151
+ // Return the first (preferred) work summary per group
152
+ const preferred = g['work-summary']?.[0];
153
+ if (!preferred)
154
+ return [];
155
+ return [normalizeWorkSummary(preferred)];
156
+ });
157
+ }
158
+ const ALL_AFFILIATION_TYPES = [
159
+ 'employment',
160
+ 'education',
161
+ 'invited-positions',
162
+ 'distinctions',
163
+ 'memberships',
164
+ 'qualifications',
165
+ 'services',
166
+ ];
167
+ const AFFILIATION_TYPE_KEYS = {
168
+ employment: 'employments',
169
+ education: 'educations',
170
+ 'invited-positions': 'invited-positions',
171
+ distinctions: 'distinctions',
172
+ memberships: 'memberships',
173
+ qualifications: 'qualifications',
174
+ services: 'services',
175
+ };
176
+ export function normalizeActivities(raw, types) {
177
+ const resolvedTypes = types.includes('all')
178
+ ? ALL_AFFILIATION_TYPES
179
+ : types;
180
+ return resolvedTypes.flatMap((type) => {
181
+ const key = AFFILIATION_TYPE_KEYS[type];
182
+ const section = raw[key];
183
+ return extractGroupSummaries(section?.['affiliation-group'], type);
184
+ });
185
+ }
186
+ function normalizeFundingSummary(raw) {
187
+ const funder = normalizeOrg(raw.organization);
188
+ const grantNumbers = normalizeExternalIds(raw['external-ids']?.['external-id'])
189
+ .filter((id) => id.type === 'grant_number')
190
+ .map((id) => id.value);
191
+ const record = { grantNumbers };
192
+ if (raw.title?.title?.value)
193
+ record.title = raw.title.title.value;
194
+ if (raw.type)
195
+ record.type = raw.type;
196
+ if (funder)
197
+ record.funder = funder;
198
+ const startDate = normalizeDate(raw['start-date']);
199
+ if (startDate)
200
+ record.startDate = startDate;
201
+ const endDate = normalizeDate(raw['end-date']);
202
+ if (endDate)
203
+ record.endDate = endDate;
204
+ if (raw.url?.value)
205
+ record.url = raw.url.value;
206
+ return record;
207
+ }
208
+ export function normalizeFundings(raw) {
209
+ return (raw.group ?? []).flatMap((g) => (g['funding-summary'] ?? []).map((s) => normalizeFundingSummary(s)));
210
+ }
211
+ export function normalizePeerReviews(raw) {
212
+ return (raw.group ?? []).flatMap((g) => {
213
+ // Extract ISSN from group-level external IDs
214
+ const issn = g['external-ids']?.['external-id']?.find((id) => id['external-id-type'] === 'issn')?.['external-id-value'];
215
+ return (g['peer-review-group'] ?? []).flatMap((prg) => (prg['peer-review-summary'] ?? []).map((s) => {
216
+ const org = normalizeOrg(s['convening-organization']);
217
+ const review = {};
218
+ if (s['reviewer-role'])
219
+ review.reviewerRole = s['reviewer-role'];
220
+ if (s['review-type'])
221
+ review.reviewType = s['review-type'];
222
+ const completionDate = normalizeDate(s['completion-date']);
223
+ if (completionDate)
224
+ review.completionDate = completionDate;
225
+ if (org)
226
+ review.conveningOrganization = org;
227
+ if (s['review-url']?.value)
228
+ review.reviewUrl = s['review-url'].value;
229
+ if (issn)
230
+ review.groupIssn = issn;
231
+ return review;
232
+ }));
233
+ });
234
+ }
235
+ export function normalizeExpandedSearch(raw) {
236
+ const results = (raw['expanded-result'] ?? []).flatMap((r) => {
237
+ const orcidId = r['orcid-id'];
238
+ if (!orcidId)
239
+ return [];
240
+ const result = {
241
+ orcidId,
242
+ otherNames: r['other-name'] ?? [],
243
+ emails: r.email ?? [],
244
+ institutionNames: r['institution-name'] ?? [],
245
+ };
246
+ if (r['given-names'])
247
+ result.givenNames = r['given-names'];
248
+ if (r['family-names'])
249
+ result.familyNames = r['family-names'];
250
+ if (r['credit-name'])
251
+ result.creditName = r['credit-name'];
252
+ return [result];
253
+ });
254
+ return { results, numFound: raw['num-found'] ?? 0 };
255
+ }
256
+ //# sourceMappingURL=normalizers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizers.js","sourceRoot":"","sources":["../../../src/services/orcid/normalizers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @fileoverview ORCID Public API v3.0 service. Provides search and record-section
3
+ * fetchers with retry, backoff, and JSON normalization. Uses init/accessor pattern.
4
+ * @module services/orcid/orcid-service
5
+ */
6
+ import type { Context } from '@cyanheads/mcp-ts-core';
7
+ import type { AppConfig } from '@cyanheads/mcp-ts-core/config';
8
+ import type { StorageService } from '@cyanheads/mcp-ts-core/storage';
9
+ import type { NormalizedPerson } from './normalizers.js';
10
+ import type { Affiliation, ExpandedSearchResponse, FundingRecord, PeerReview, Work } from './types.js';
11
+ /** Strip https://orcid.org/ prefix to get the bare 0000-XXXX-XXXX-XXXX form. */
12
+ export declare function normalizeOrcidId(id: string): string;
13
+ /** The accepted affiliation types as a union for type-safety. */
14
+ export type AffiliationType = 'employment' | 'education' | 'invited-positions' | 'distinctions' | 'memberships' | 'qualifications' | 'services' | 'all';
15
+ /** Common fetch options forwarded to network layer. */
16
+ export type FetchOptions = {
17
+ signal?: AbortSignal;
18
+ };
19
+ /** Search parameters for expanded-search endpoint. */
20
+ export type SearchParams = {
21
+ q: string;
22
+ rows?: number;
23
+ start?: number;
24
+ };
25
+ export declare class OrcidService {
26
+ private readonly baseUrl;
27
+ constructor(_config: AppConfig, _storage: StorageService);
28
+ /** Build base request headers required by the ORCID Public API. */
29
+ private headers;
30
+ /** Detect HTML error pages masquerading as JSON responses (rate-limit or maintenance pages). */
31
+ private assertNotHtml;
32
+ /** Fetch a URL with retry and timeout, returning parsed JSON. */
33
+ private fetchJson;
34
+ /**
35
+ * Search the ORCID expanded-search endpoint.
36
+ * Returns inline name and institution data in one call.
37
+ */
38
+ expandedSearch(params: SearchParams, ctx: Context): Promise<ExpandedSearchResponse>;
39
+ /**
40
+ * Fetch the person section for an ORCID iD.
41
+ * Returns name, biography, keywords, researcher URLs, external IDs.
42
+ */
43
+ getPerson(orcidId: string, ctx: Context): Promise<NormalizedPerson>;
44
+ /**
45
+ * Fetch the works summary list for an ORCID iD.
46
+ * Returns titles, types, dates, journal names, and external IDs (DOIs, PMIDs, etc.).
47
+ */
48
+ getWorks(orcidId: string, ctx: Context): Promise<Work[]>;
49
+ /**
50
+ * Fetch activities and return affiliation sections filtered by types.
51
+ * Uses a single /activities call instead of per-section fetches.
52
+ */
53
+ getAffiliations(orcidId: string, types: AffiliationType[], ctx: Context): Promise<Affiliation[]>;
54
+ /**
55
+ * Fetch funding records for an ORCID iD.
56
+ */
57
+ getFundings(orcidId: string, ctx: Context): Promise<FundingRecord[]>;
58
+ /**
59
+ * Fetch peer review records for an ORCID iD.
60
+ */
61
+ getPeerReviews(orcidId: string, ctx: Context): Promise<PeerReview[]>;
62
+ }
63
+ export declare function initOrcidService(config: AppConfig, storage: StorageService): void;
64
+ export declare function getOrcidService(): OrcidService;
65
+ //# sourceMappingURL=orcid-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orcid-service.d.ts","sourceRoot":"","sources":["../../../src/services/orcid/orcid-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAOrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AASzD,OAAO,KAAK,EACV,WAAW,EACX,sBAAsB,EACtB,aAAa,EACb,UAAU,EAOV,IAAI,EACL,MAAM,YAAY,CAAC;AAEpB,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,iEAAiE;AACjE,MAAM,MAAM,eAAe,GACvB,YAAY,GACZ,WAAW,GACX,mBAAmB,GACnB,cAAc,GACd,aAAa,GACb,gBAAgB,GAChB,UAAU,GACV,KAAK,CAAC;AAEV,uDAAuD;AACvD,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,sDAAsD;AACtD,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc;IAIxD,mEAAmE;IACnE,OAAO,CAAC,OAAO;IAOf,gGAAgG;IAChG,OAAO,CAAC,aAAa;IAQrB,iEAAiE;IACjE,OAAO,CAAC,SAAS;IA6BjB;;;OAGG;IACG,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAUzF;;;OAGG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAQzE;;;OAGG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAQ9D;;;OAGG;IACG,eAAe,CACnB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,eAAe,EAAE,EACxB,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,WAAW,EAAE,CAAC;IAQzB;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAQ1E;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;CAO3E;AAQD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAEjF;AAED,wBAAgB,eAAe,IAAI,YAAY,CAK9C"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @fileoverview ORCID Public API v3.0 service. Provides search and record-section
3
+ * fetchers with retry, backoff, and JSON normalization. Uses init/accessor pattern.
4
+ * @module services/orcid/orcid-service
5
+ */
6
+ import { serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
7
+ import { httpErrorFromResponse, requestContextService, withRetry, } from '@cyanheads/mcp-ts-core/utils';
8
+ import { getServerConfig } from '../../config/server-config.js';
9
+ import { normalizeActivities, normalizeExpandedSearch, normalizeFundings, normalizePeerReviews, normalizePerson, normalizeWorks, } from './normalizers.js';
10
+ /** Strip https://orcid.org/ prefix to get the bare 0000-XXXX-XXXX-XXXX form. */
11
+ export function normalizeOrcidId(id) {
12
+ return id.replace(/^https?:\/\/orcid\.org\//, '').trim();
13
+ }
14
+ export class OrcidService {
15
+ baseUrl;
16
+ constructor(_config, _storage) {
17
+ this.baseUrl = getServerConfig().orcidApiBaseUrl.replace(/\/$/, '');
18
+ }
19
+ /** Build base request headers required by the ORCID Public API. */
20
+ headers() {
21
+ return {
22
+ Accept: 'application/json',
23
+ 'User-Agent': 'orcid-mcp-server/0.1.1 (https://github.com/cyanheads/orcid-mcp-server)',
24
+ };
25
+ }
26
+ /** Detect HTML error pages masquerading as JSON responses (rate-limit or maintenance pages). */
27
+ assertNotHtml(text, url) {
28
+ if (/^\s*<(!DOCTYPE\s+html|html[\s>])/i.test(text)) {
29
+ throw serviceUnavailable(`ORCID API returned HTML instead of JSON at ${url} — likely rate-limited or under maintenance.`);
30
+ }
31
+ }
32
+ /** Fetch a URL with retry and timeout, returning parsed JSON. */
33
+ fetchJson(url, ctx, options) {
34
+ const signal = options?.signal ?? ctx.signal;
35
+ // Create a RequestContext from the handler Context for withRetry's structured logging.
36
+ const reqCtx = requestContextService.createRequestContext({
37
+ operation: 'OrcidService.fetchJson',
38
+ parentContext: { requestId: ctx.requestId, tenantId: ctx.tenantId, traceId: ctx.traceId },
39
+ });
40
+ return withRetry(async () => {
41
+ const response = await fetch(url, {
42
+ headers: this.headers(),
43
+ signal,
44
+ });
45
+ if (!response.ok) {
46
+ throw await httpErrorFromResponse(response, { service: 'ORCID', data: { url } });
47
+ }
48
+ const text = await response.text();
49
+ this.assertNotHtml(text, url);
50
+ return JSON.parse(text);
51
+ }, {
52
+ operation: 'OrcidService.fetchJson',
53
+ context: reqCtx,
54
+ baseDelayMs: 1000,
55
+ signal,
56
+ });
57
+ }
58
+ /**
59
+ * Search the ORCID expanded-search endpoint.
60
+ * Returns inline name and institution data in one call.
61
+ */
62
+ async expandedSearch(params, ctx) {
63
+ const qs = new URLSearchParams({ q: params.q });
64
+ if (params.rows != null)
65
+ qs.set('rows', String(params.rows));
66
+ if (params.start != null)
67
+ qs.set('start', String(params.start));
68
+ const url = `${this.baseUrl}/expanded-search/?${qs}`;
69
+ ctx.log.debug('ORCID expanded-search', { q: params.q, rows: params.rows, start: params.start });
70
+ const raw = await this.fetchJson(url, ctx);
71
+ return normalizeExpandedSearch(raw);
72
+ }
73
+ /**
74
+ * Fetch the person section for an ORCID iD.
75
+ * Returns name, biography, keywords, researcher URLs, external IDs.
76
+ */
77
+ async getPerson(orcidId, ctx) {
78
+ const id = normalizeOrcidId(orcidId);
79
+ const url = `${this.baseUrl}/${id}/person`;
80
+ ctx.log.debug('ORCID getPerson', { orcidId: id });
81
+ const raw = await this.fetchJson(url, ctx);
82
+ return normalizePerson(raw);
83
+ }
84
+ /**
85
+ * Fetch the works summary list for an ORCID iD.
86
+ * Returns titles, types, dates, journal names, and external IDs (DOIs, PMIDs, etc.).
87
+ */
88
+ async getWorks(orcidId, ctx) {
89
+ const id = normalizeOrcidId(orcidId);
90
+ const url = `${this.baseUrl}/${id}/works`;
91
+ ctx.log.debug('ORCID getWorks', { orcidId: id });
92
+ const raw = await this.fetchJson(url, ctx);
93
+ return normalizeWorks(raw);
94
+ }
95
+ /**
96
+ * Fetch activities and return affiliation sections filtered by types.
97
+ * Uses a single /activities call instead of per-section fetches.
98
+ */
99
+ async getAffiliations(orcidId, types, ctx) {
100
+ const id = normalizeOrcidId(orcidId);
101
+ const url = `${this.baseUrl}/${id}/activities`;
102
+ ctx.log.debug('ORCID getAffiliations', { orcidId: id, types });
103
+ const raw = await this.fetchJson(url, ctx);
104
+ return normalizeActivities(raw, types);
105
+ }
106
+ /**
107
+ * Fetch funding records for an ORCID iD.
108
+ */
109
+ async getFundings(orcidId, ctx) {
110
+ const id = normalizeOrcidId(orcidId);
111
+ const url = `${this.baseUrl}/${id}/fundings`;
112
+ ctx.log.debug('ORCID getFundings', { orcidId: id });
113
+ const raw = await this.fetchJson(url, ctx);
114
+ return normalizeFundings(raw);
115
+ }
116
+ /**
117
+ * Fetch peer review records for an ORCID iD.
118
+ */
119
+ async getPeerReviews(orcidId, ctx) {
120
+ const id = normalizeOrcidId(orcidId);
121
+ const url = `${this.baseUrl}/${id}/peer-reviews`;
122
+ ctx.log.debug('ORCID getPeerReviews', { orcidId: id });
123
+ const raw = await this.fetchJson(url, ctx);
124
+ return normalizePeerReviews(raw);
125
+ }
126
+ }
127
+ // ---------------------------------------------------------------------------
128
+ // Init / accessor pattern
129
+ // ---------------------------------------------------------------------------
130
+ let _service;
131
+ export function initOrcidService(config, storage) {
132
+ _service = new OrcidService(config, storage);
133
+ }
134
+ export function getOrcidService() {
135
+ if (!_service) {
136
+ throw new Error('OrcidService not initialized — call initOrcidService() in setup()');
137
+ }
138
+ return _service;
139
+ }
140
+ //# sourceMappingURL=orcid-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orcid-service.js","sourceRoot":"","sources":["../../../src/services/orcid/orcid-service.ts"],"names":[],"mappings":"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"}