Skip to content

Commit dd5195e

Browse files
committed
feat: dynamically fetch content api graphql schema
1 parent 9165f0c commit dd5195e

File tree

12 files changed

+454
-246
lines changed

12 files changed

+454
-246
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
{
2-
"workspaces": [
3-
"packages/*"
4-
],
2+
"workspaces": ["packages/*"],
53
"scripts": {
64
"build": "npm run build --workspace @supabase/mcp-utils --workspace @supabase/mcp-server-supabase",
75
"test": "npm run test --workspace @supabase/mcp-utils --workspace @supabase/mcp-server-supabase",

packages/mcp-server-supabase/package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,13 @@
88
"types": "dist/index.d.ts",
99
"sideEffects": false,
1010
"scripts": {
11-
"prebuild": "npm run generate:content-api-schema",
1211
"build": "tsup --clean",
1312
"prepublishOnly": "npm run build",
14-
"pretest": "npm run generate:content-api-schema",
1513
"test": "vitest",
1614
"test:unit": "vitest --project unit",
1715
"test:e2e": "vitest --project e2e",
1816
"test:integration": "vitest --project integration",
1917
"test:coverage": "vitest --coverage",
20-
"generate:content-api-schema": "tsx scripts/fetch-content-api-schema.ts",
2118
"generate:management-api-types": "openapi-typescript https://api.supabase.com/api/v1-json -o ./src/management-api/types.ts"
2219
},
2320
"files": ["dist/**/*"],
@@ -41,6 +38,7 @@
4138
"@modelcontextprotocol/sdk": "^1.11.0",
4239
"@supabase/mcp-utils": "0.2.1",
4340
"common-tags": "^1.8.2",
41+
"graphql": "^16.11.0",
4442
"openapi-fetch": "^0.13.5",
4543
"zod": "^3.24.1"
4644
},
@@ -54,7 +52,6 @@
5452
"ai": "^4.3.4",
5553
"date-fns": "^4.1.0",
5654
"dotenv": "^16.5.0",
57-
"graphql": "^16.11.0",
5855
"msw": "^2.7.3",
5956
"nanoid": "^5.1.5",
6057
"openapi-typescript": "^7.5.0",

packages/mcp-server-supabase/scripts/fetch-content-api-schema.ts

Lines changed: 0 additions & 81 deletions
This file was deleted.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { stripIndent } from 'common-tags';
2+
import { describe, expect, it } from 'vitest';
3+
import { GraphQLClient } from './graphql.js';
4+
5+
describe('graphql client', () => {
6+
it('should load schema', async () => {
7+
const schema = stripIndent`
8+
schema {
9+
query: RootQueryType
10+
}
11+
type RootQueryType {
12+
message: String!
13+
}
14+
`;
15+
16+
const graphqlClient = new GraphQLClient({
17+
url: 'dummy-url',
18+
loadSchema: async () => schema,
19+
});
20+
21+
const { source } = await graphqlClient.schemaLoaded;
22+
23+
expect(source).toBe(schema);
24+
});
25+
26+
it('should throw error if validation requested but loadSchema not provided', async () => {
27+
const graphqlClient = new GraphQLClient({
28+
url: 'dummy-url',
29+
});
30+
31+
await expect(
32+
graphqlClient.query(
33+
{ query: '{ getHelloWorld }' },
34+
{ validateSchema: true }
35+
)
36+
).rejects.toThrow('No schema loader provided');
37+
});
38+
39+
it('should throw for invalid query regardless of schema', async () => {
40+
const graphqlClient = new GraphQLClient({
41+
url: 'dummy-url',
42+
});
43+
44+
await expect(
45+
graphqlClient.query({ query: 'invalid graphql query' })
46+
).rejects.toThrow(
47+
'Invalid GraphQL query: Syntax Error: Unexpected Name "invalid"'
48+
);
49+
});
50+
51+
it("should throw error if query doesn't match schema", async () => {
52+
const schema = stripIndent`
53+
schema {
54+
query: RootQueryType
55+
}
56+
type RootQueryType {
57+
message: String!
58+
}
59+
`;
60+
61+
const graphqlClient = new GraphQLClient({
62+
url: 'dummy-url',
63+
loadSchema: async () => schema,
64+
});
65+
66+
await expect(
67+
graphqlClient.query(
68+
{ query: '{ invalidField }' },
69+
{ validateSchema: true }
70+
)
71+
).rejects.toThrow(
72+
'Invalid GraphQL query: Cannot query field "invalidField" on type "RootQueryType"'
73+
);
74+
});
75+
76+
it('bubbles up loadSchema errors', async () => {
77+
const graphqlClient = new GraphQLClient({
78+
url: 'dummy-url',
79+
loadSchema: async () => {
80+
throw new Error('Failed to load schema');
81+
},
82+
});
83+
84+
await expect(graphqlClient.schemaLoaded).rejects.toThrow(
85+
'Failed to load schema'
86+
);
87+
});
88+
});

0 commit comments

Comments
 (0)