Skip to content

Commit db4c72d

Browse files
author
Julien Droulez
committed
fix: relax zod strictness for mcp schema
1 parent c0dcf3d commit db4c72d

File tree

9 files changed

+241
-267
lines changed

9 files changed

+241
-267
lines changed

src/mcp-server/projects/event-tool.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { z } from 'zod'
2+
import N from './zod-schema-utils'
23
import { mcpFetch, API_BASE_URL, orgCode } from './base'
34

4-
const EVENT_OUTPUT_SCHEMA = z.object({
5-
id: z.number().describe('The ID of the event'),
6-
slug: z.string().describe('The slug of the event'),
7-
title: z.string().describe('The title of the event'),
8-
content: z.string().describe('The content of the event'),
9-
event_date: z.string().describe('The date of the event'),
10-
item_type: z.literal('event').describe('The type of the item, always event'),
5+
const EVENT_OUTPUT_SCHEMA = N.object({
6+
id: N.number().describe('The ID of the event'),
7+
slug: N.string().describe('The slug of the event'),
8+
title: N.string().describe('The title of the event'),
9+
content: N.string().describe('The content of the event'),
10+
event_date: N.string().describe('The date of the event'),
11+
item_type: N.literal('event').describe('The type of the item, always event'),
1112
})
1213

1314
const mapEvent = (e: any) => ({

src/mcp-server/projects/instruction-tool.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { z } from 'zod'
2+
import N from './zod-schema-utils'
23
import { mcpFetch, API_BASE_URL, orgCode } from './base'
34

4-
const INSTRUCTION_ARTICLE_OUTPUT_SCHEMA = z.object({
5-
id: z.number().describe('The ID of the instruction article'),
6-
slug: z.string().describe('The slug of the instruction article'),
7-
title: z.string().describe('The title of the instruction article'),
8-
content: z.string().describe('The content of the instruction article'),
9-
publication_date: z.string().describe('The publication date of the instruction article'),
5+
const INSTRUCTION_ARTICLE_OUTPUT_SCHEMA = N.object({
6+
id: N.number().describe('The ID of the instruction article'),
7+
slug: N.string().describe('The slug of the instruction article'),
8+
title: N.string().describe('The title of the instruction article'),
9+
content: N.string().describe('The content of the instruction article'),
10+
publication_date: N.string().describe('The publication date of the instruction article'),
1011
item_type: z
1112
.literal('instruction_article')
1213
.describe('The type of the item, always instruction_article'),

src/mcp-server/projects/news-tool.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { z } from 'zod'
2+
import N from './zod-schema-utils'
23
import { mcpFetch, API_BASE_URL, orgCode } from './base'
34

4-
const NEWS_ARTICLE_OUTPUT_SCHEMA = z.object({
5-
id: z.number().describe('The ID of the news article'),
6-
slug: z.string().describe('The slug of the news article'),
7-
title: z.string().describe('The title of the news article'),
8-
content: z.string().describe('The content of the news article'),
9-
publication_date: z.string().describe('The publication date of the news article'),
10-
item_type: z.literal('news_article').describe('The type of the item, always news_article'),
5+
const NEWS_ARTICLE_OUTPUT_SCHEMA = N.object({
6+
id: N.number().describe('The ID of the news article'),
7+
slug: N.string().describe('The slug of the news article'),
8+
title: N.string().describe('The title of the news article'),
9+
content: N.string().describe('The content of the news article'),
10+
publication_date: N.string().describe('The publication date of the news article'),
11+
item_type: N.literal('news_article').describe('The type of the item, always news_article'),
1112
})
1213

1314
const mapNewsArticle = (n: any) => ({

src/mcp-server/projects/organization-tool.ts

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { z } from 'zod'
2+
import N from './zod-schema-utils'
23
import { mcpFetch, API_BASE_URL, orgCode } from './base'
34
import { PROJECT_PREVIEW_OUTPUT_SCHEMA, mapProjectPreview } from './project-tool'
45

@@ -12,27 +13,17 @@ export default (server) => {
1213
'Get main general data about the platform organization such as its description, title and terms and conditions. ',
1314
inputSchema: {},
1415
outputSchema: {
15-
organization_data: z
16-
.object({
17-
id: z.number().describe('The ID of the organization'),
18-
code: z.string().describe('The code of the organization'),
19-
terms_and_conditions: z
20-
.string()
21-
.describe('The terms and conditions of the organization'),
22-
name: z.string().describe('The name of the organization'),
23-
contact_email: z.string().nullable().describe('The contact email of the organization'),
24-
dashboard_title: z
25-
.string()
26-
.nullable()
27-
.describe('The dashboard title of the organization'),
28-
dashboard_subtitle: z
29-
.string()
30-
.nullable()
31-
.describe('The dashboard subtitle of the organization'),
32-
description: z.string().nullable().describe('The description of the organization'),
33-
website_url: z.string().nullable().describe('The website URL of the organization'),
34-
})
35-
.describe('The organization general data'),
16+
organization_data: N.object({
17+
id: N.number().describe('The ID of the organization'),
18+
code: N.string().describe('The code of the organization'),
19+
terms_and_conditions: N.string().describe('The terms and conditions of the organization'),
20+
name: N.string().describe('The name of the organization'),
21+
contact_email: N.string().nullable().describe('The contact email of the organization'),
22+
dashboard_title: N.string().describe('The dashboard title of the organization'),
23+
dashboard_subtitle: N.string().describe('The dashboard subtitle of the organization'),
24+
description: N.string().describe('The description of the organization'),
25+
website_url: N.string().describe('The website URL of the organization'),
26+
}).describe('The organization general data'),
3627
},
3728
},
3829
async (_input, extras) => {

src/mcp-server/projects/people-tool.ts

Lines changed: 49 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { z } from 'zod'
2+
import N from './zod-schema-utils'
23
import { mcpFetch, API_BASE_URL, orgCode } from './base'
34
import { SDG_OUTPUT_SCHEMA, mapSDG } from './sdg-tool'
45
import { tagMapper } from './tag-schema'
@@ -9,16 +10,16 @@ export const FETCH_USER_SLUG_OR_ID =
910
export const FETCH_GROUP_SLUG_OR_ID =
1011
'If you dont have the slug (given under "slug" or "id" key in a previous tool call data) or id of the group of users, use the search tool with the group of user name, the group id or slug will be in the first result, else use the previously mentioned slug or id.'
1112

12-
export const USER_PREVIEW_OUTPUT_SCHEMA = z.object({
13-
id: z.number().optional().nullable().describe('The ID of the user'),
14-
slug: z.string().optional().nullable().describe('The slug of the user'),
15-
item_type: z.literal('user').describe('The type of the item, always user'),
16-
given_name: z.string().optional().nullable().describe('The given name of the user'),
17-
family_name: z.string().optional().nullable().describe('The family name of the user'),
18-
job: z.string().optional().nullable().nullable().describe('The job or title of the user'),
19-
email: z.string().optional().nullable().describe('The email of the user'),
20-
link_url: z.string().optional().nullable().describe('The URL link to the user profile'),
21-
item_image: z.string().optional().nullable().describe('The image URL of the user profile'),
13+
export const USER_PREVIEW_OUTPUT_SCHEMA = N.object({
14+
id: N.number().describe('The ID of the user'),
15+
slug: N.string().describe('The slug of the user'),
16+
item_type: N.literal('user').describe('The type of the item, always user'),
17+
given_name: N.string().describe('The given name of the user'),
18+
family_name: N.string().describe('The family name of the user'),
19+
job: N.string().describe('The job or title of the user'),
20+
email: N.string().describe('The email of the user'),
21+
link_url: N.string().describe('The URL link to the user profile'),
22+
item_image: N.string().describe('The image URL of the user profile'),
2223
})
2324

2425
export const mapUserPreview = (u: any) => ({
@@ -33,25 +34,17 @@ export const mapUserPreview = (u: any) => ({
3334
item_image: u.profile_picture?.variations?.small,
3435
})
3536

36-
export const PEOPLE_GROUP_PREVIEW_OUTPUT_SCHEMA = z.object({
37-
id: z.number().optional().nullable().describe('The ID of the people group'),
38-
slug: z.string().optional().nullable().describe('The slug of the people group'),
39-
item_type: z.literal('people_group').describe('The type of the item, always people_group'),
40-
name: z.string().describe('The name of the people group'),
41-
short_description: z
42-
.string()
43-
.optional()
44-
.nullable()
45-
.describe('The short description of the people group'),
46-
description: z.string().optional().nullable().describe('The description of the people group'),
47-
email: z.string().optional().nullable().describe('The email of the people group'),
48-
member_count: z
49-
.number()
50-
.optional()
51-
.nullable()
52-
.describe('The number of members in the people group'),
53-
link_url: z.string().optional().nullable().describe('The URL link to the people group'),
54-
item_image: z.string().optional().nullable().describe('The image URL of the people group'),
37+
export const PEOPLE_GROUP_PREVIEW_OUTPUT_SCHEMA = N.object({
38+
id: N.number().describe('The ID of the people group'),
39+
slug: N.string().describe('The slug of the people group'),
40+
item_type: N.literal('people_group').describe('The type of the item, always people_group'),
41+
name: N.string().describe('The name of the people group'),
42+
short_description: N.string().describe('The short description of the people group'),
43+
description: N.string().describe('The description of the people group'),
44+
email: N.string().describe('The email of the people group'),
45+
member_count: N.number().describe('The number of members in the people group'),
46+
link_url: N.string().describe('The URL link to the people group'),
47+
item_image: N.string().describe('The image URL of the people group'),
5548
})
5649

5750
export const mapPeopleGroupPreview = (g: any) => ({
@@ -79,61 +72,33 @@ export default (server) => {
7972
},
8073
outputSchema: {
8174
user_data: USER_PREVIEW_OUTPUT_SCHEMA.extend({
82-
is_superuser: z.boolean().describe('Whether the user is a superuser'),
83-
people_groups: z
84-
.array(PEOPLE_GROUP_PREVIEW_OUTPUT_SCHEMA)
85-
.optional()
86-
.nullable()
87-
.describe('The list of people groups the user belongs to'),
88-
skills: z
89-
.array(
90-
z.object({
91-
id: z.number().describe('The ID of the skill'),
92-
tag: z.object({
93-
id: z.number().optional().nullable().describe('The ID of the tag'),
94-
title: z.string().optional().nullable().describe('The title of the tag'),
95-
description: z
96-
.string()
97-
.optional()
98-
.nullable()
99-
.describe('The description of the tag'),
100-
}),
101-
level: z.number().optional().nullable().describe('The level of the skill'),
102-
level_to_reach: z
103-
.number()
104-
.optional()
105-
.nullable()
106-
.describe('The level to reach of the skill'),
107-
type: z.string().optional().nullable().describe('The type of the skill'),
108-
can_mentor: z.boolean().describe('Whether the user can mentor this skill'),
109-
needs_mentor: z
110-
.boolean()
111-
.optional()
112-
.nullable()
113-
.describe('Whether the user needs a mentor for this skill'),
114-
comment: z.string().optional().nullable().describe('The comment of the skill'),
115-
})
116-
)
117-
.describe('The list of skills of the user'),
118-
short_description: z
119-
.string()
120-
.optional()
121-
.nullable()
122-
.describe('The short description of the user'),
123-
description: z.string().optional().nullable().describe('The description of the user'),
124-
location: z.string().optional().nullable().describe('The location of the user'),
125-
facebook: z
126-
.string()
127-
.optional()
128-
.nullable()
129-
.describe('The Facebook profile URL of the user'),
130-
linkedin: z
131-
.string()
132-
.optional()
133-
.nullable()
134-
.describe('The LinkedIn profile URL of the user'),
135-
website: z.string().optional().nullable().describe('The website URL of the user'),
136-
sdgs: z.array(SDG_OUTPUT_SCHEMA).describe('The list of SDGs related to the user'),
75+
is_superuser: N.boolean().describe('Whether the user is a superuser'),
76+
people_groups: N.array(PEOPLE_GROUP_PREVIEW_OUTPUT_SCHEMA).describe(
77+
'The list of people groups the user belongs to'
78+
),
79+
skills: N.array(
80+
N.object({
81+
id: N.number().describe('The ID of the skill'),
82+
tag: N.object({
83+
id: N.number().describe('The ID of the tag'),
84+
title: N.string().describe('The title of the tag'),
85+
description: N.string().describe('The description of the tag'),
86+
}),
87+
level: N.number().describe('The level of the skill'),
88+
level_to_reach: N.number().describe('The level to reach of the skill'),
89+
type: N.string().describe('The type of the skill'),
90+
can_mentor: N.boolean().describe('Whether the user can mentor this skill'),
91+
needs_mentor: N.boolean().describe('Whether the user needs a mentor for this skill'),
92+
comment: N.string().describe('The comment of the skill'),
93+
})
94+
).describe('The list of skills of the user'),
95+
short_description: N.string().describe('The short description of the user'),
96+
description: N.string().describe('The description of the user'),
97+
location: N.string().describe('The location of the user'),
98+
facebook: N.string().describe('The Facebook profile URL of the user'),
99+
linkedin: N.string().describe('The LinkedIn profile URL of the user'),
100+
website: N.string().describe('The website URL of the user'),
101+
sdgs: N.array(SDG_OUTPUT_SCHEMA).describe('The list of SDGs related to the user'),
137102
}),
138103
},
139104
},

0 commit comments

Comments
 (0)