Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"@connectrpc/connect": "1.4.0",
"@connectrpc/connect-node": "1.4.0",
"@graphql-tools/utils": "10.2.2",
"@modelcontextprotocol/sdk": "1.9.0",
"@modelcontextprotocol/sdk": "1.26.0",
"@octokit/rest": "22.0.0",
"@wundergraph/composition": "workspace:*",
"@wundergraph/cosmo-connect": "workspace:*",
Expand Down Expand Up @@ -82,7 +82,7 @@
"tar": "7.4.3",
"trieve-ts-sdk": "0.0.80",
"undici": "6.21.2",
"zod": "^3.24.2"
"zod": "^3.25.0"
},
"devDependencies": {
"@types/bun": "1.2.3",
Expand Down
10 changes: 7 additions & 3 deletions cli/src/commands/mcp/tools/dream-query-workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ import type { BaseCommandOptions } from '../../../core/types/types.js';
* @param params.opts - Base command options.
*/
export const registerDreamQueryWorkflowTool = ({ server, opts }: { server: McpServer; opts: BaseCommandOptions }) => {
server.tool(
server.registerTool(
'dream_query_workflow',
"Use this tool to generate a list of instructions to make the necessary changes to a Supergraph to support a given GraphQL query. Ask the user to provide the Supergraph name and namespace if it's not clear.",
{ query: z.string(), supergraph: z.string(), namespace: z.string().optional() },
{
title: 'Dream Query Workflow',
description:
"Use this tool to generate a list of instructions to make the necessary changes to a Supergraph to support a given GraphQL query. Ask the user to provide the Supergraph name and namespace if it's not clear.",
inputSchema: { query: z.string(), supergraph: z.string(), namespace: z.string().optional() },
},
({ query, supergraph, namespace }) => ({
content: [
{
Expand Down
43 changes: 27 additions & 16 deletions cli/src/commands/mcp/tools/federated-graph-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ import { getBaseHeaders } from '../../../core/config.js';
import {
fetchRouterConfig,
getFederatedGraphSchemas,
getSubgraphSDL,
getSubgraphsOfFedGraph,
} from '../../graph/federated-graph/utils.js';
import { ToolContext } from './types.js';

export const registerFederatedGraphTools = ({ server, opts }: ToolContext) => {
// List federated graphs tool
server.tool(
server.registerTool(
'list_supergraphs',
'List all federated graphs / Supergraphs',
{
namespace: z.string().optional().describe('Filter to get graphs in this namespace only'),
title: 'List Supergraphs',
description: 'List all federated graphs / Supergraphs',
inputSchema: {
namespace: z.string().optional().describe('Filter to get graphs in this namespace only'),
},
},
async ({ namespace }) => {
try {
Expand Down Expand Up @@ -63,12 +65,15 @@ export const registerFederatedGraphTools = ({ server, opts }: ToolContext) => {
);

// Fetch federated graph details tool
server.tool(
server.registerTool(
'fetch_supergraph',
'Fetch the schemas and configuration of a federated graph / Supergraph',
{
name: z.string().describe('The name of the federated graph to fetch'),
namespace: z.string().optional().describe('The namespace of the federated graph'),
title: 'Fetch Supergraph',
description: 'Fetch the schemas and configuration of a federated graph / Supergraph',
inputSchema: {
name: z.string().describe('The name of the federated graph to fetch'),
namespace: z.string().optional().describe('The namespace of the federated graph'),
},
},
async ({ name, namespace }) => {
try {
Expand Down Expand Up @@ -104,12 +109,15 @@ export const registerFederatedGraphTools = ({ server, opts }: ToolContext) => {
);

// Fetch router config tool
server.tool(
server.registerTool(
'fetch_supergraph_router_config',
'Fetch the router configuration for a federated graph / Supergraph',
{
name: z.string().describe('The name of the federated graph to fetch'),
namespace: z.string().optional().describe('The namespace of the federated graph'),
title: 'Fetch Supergraph Router Config',
description: 'Fetch the router configuration for a federated graph / Supergraph',
inputSchema: {
name: z.string().describe('The name of the federated graph to fetch'),
namespace: z.string().optional().describe('The namespace of the federated graph'),
},
},
async ({ name, namespace }) => {
try {
Expand All @@ -129,12 +137,15 @@ export const registerFederatedGraphTools = ({ server, opts }: ToolContext) => {
);

// Fetch subgraphs tool
server.tool(
server.registerTool(
'fetch_supergraph_subgraphs',
'Fetch all subgraphs and their schemas for a federated graph / Supergraph',
{
name: z.string().describe('The name of the federated graph to fetch'),
namespace: z.string().optional().describe('The namespace of the federated graph'),
title: 'Fetch Supergraph Subgraphs',
description: 'Fetch all subgraphs and their schemas for a federated graph / Supergraph',
inputSchema: {
name: z.string().describe('The name of the federated graph to fetch'),
namespace: z.string().optional().describe('The namespace of the federated graph'),
},
},
async ({ name, namespace }) => {
try {
Expand Down
13 changes: 8 additions & 5 deletions cli/src/commands/mcp/tools/get-subgraphs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@ import { getBaseHeaders } from '../../../core/config.js';
import { ToolContext } from './types.js';

export const registerGetSubgraphsTool = ({ server, opts }: ToolContext) => {
server.tool(
server.registerTool(
'get_subgraphs',
'Get details for one or more subgraphs, including the SDL/GraphQL Schema for each.',
{
names: z.array(z.string()).describe('The names of the subgraphs'),
namespace: z.string().optional().describe('The namespace of the subgraphs'),
title: 'Get Subgraphs',
description: 'Get details for one or more subgraphs, including the SDL/GraphQL Schema for each.',
inputSchema: {
names: z.array(z.string()).describe('The names of the subgraphs'),
namespace: z.string().optional().describe('The namespace of the subgraphs'),
},
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
async (params) => {
const results: Array<Partial<Subgraph> & { sdl?: string }> = [];
const errors: string[] = [];

// Fetch details for all subgraphs first to potentially leverage batching if the API supports it later.
// Currently, it iterates and fetches one by one.
const subgraphDetailsPromises = params.names.map((name) =>
const subgraphDetailsPromises = params.names.map((name: string) =>
opts.client.platform
.getSubgraphs(
{
Expand Down
11 changes: 7 additions & 4 deletions cli/src/commands/mcp/tools/introspect-subgraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@ export type IntrospectSubgraphInput = z.infer<typeof introspectSubgraphInputSche
* @param config.opts - Base command options.
*/
export const registerIntrospectSubgraphTool = ({ server, opts }: { server: McpServer; opts: BaseCommandOptions }) => {
server.tool(
'introspect_subgraph', // Tool name
'Introspects a subgraph and returns its GraphQL schema (SDL).', // Tool description
introspectSubgraphInputSchema.shape, // Pass the raw shape
server.registerTool(
'introspect_subgraph',
{
title: 'Introspect Subgraph',
description: 'Introspects a subgraph and returns its GraphQL schema (SDL).',
inputSchema: introspectSubgraphInputSchema.shape,
},
async ({ routingUrl, header, useRawIntrospection }: IntrospectSubgraphInput) => {
// Destructure input fields directly
try {
Expand Down
55 changes: 31 additions & 24 deletions cli/src/commands/mcp/tools/list-subgraphs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,39 @@ import { getBaseHeaders } from '../../../core/config.js';
import { ToolContext } from './types.js';

export const registerListSubgraphsTool = ({ server, opts }: ToolContext) => {
server.tool('list_subgraphs', 'List all subgraphs', async () => {
const resp = await opts.client.platform.getSubgraphs(
{
limit: 0,
offset: 0,
},
{
headers: getBaseHeaders(),
},
);
server.registerTool(
'list_subgraphs',
{
title: 'List Subgraphs',
description: 'List all subgraphs',
},
async () => {
const resp = await opts.client.platform.getSubgraphs(
{
limit: 0,
offset: 0,
},
{
headers: getBaseHeaders(),
},
);

if (resp.response?.code !== EnumStatusCode.OK) {
throw new Error(`Could not fetch subgraphs: ${resp.response?.details || ''}`);
}
if (resp.response?.code !== EnumStatusCode.OK) {
throw new Error(`Could not fetch subgraphs: ${resp.response?.details || ''}`);
}

const out = resp.graphs.map((graph) => {
const out = resp.graphs.map((graph) => {
return {
id: graph.id,
name: graph.name,
labels: graph.labels,
routingURL: graph.routingURL,
lastUpdate: graph.lastUpdatedAt,
};
});
return {
id: graph.id,
name: graph.name,
labels: graph.labels,
routingURL: graph.routingURL,
lastUpdate: graph.lastUpdatedAt,
content: [{ type: 'text', text: JSON.stringify(out, null, 2) }],
};
});
return {
content: [{ type: 'text', text: JSON.stringify(out, null, 2) }],
};
});
},
);
};
10 changes: 7 additions & 3 deletions cli/src/commands/mcp/tools/schema-change-proposal-workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ export const registerSchemaChangeProposalWorkflowTool = ({
server: McpServer;
opts: BaseCommandOptions;
}) => {
server.tool(
server.registerTool(
'schema_change_proposal_workflow',
'Use this tool to generate a list of instructions to make a successful schema change for a Supergraph.',
{ change: z.string(), supergraph: z.string(), namespace: z.string().optional() },
{
title: 'Schema Change Proposal Workflow',
description:
'Use this tool to generate a list of instructions to make a successful schema change for a Supergraph.',
inputSchema: { change: z.string(), supergraph: z.string(), namespace: z.string().optional() },
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
({ change, supergraph, namespace }) => ({
content: [
{
Expand Down
10 changes: 7 additions & 3 deletions cli/src/commands/mcp/tools/search-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ import { ToolContext } from './types.js';
export const registerSearchDocsTool = ({ server, opts }: ToolContext) => {
let trieve: TrieveSDK;

server.tool(
server.registerTool(
'search_docs',
'Search the Cosmo docs for a given query, e.g. to understand the Router Configuration or how Cosmo works in detail.',
{ query: z.string() },
{
title: 'Search Docs',
description:
'Search the Cosmo docs for a given query, e.g. to understand the Router Configuration or how Cosmo works in detail.',
inputSchema: { query: z.string() },
},
async ({ query }) => {
try {
if (!trieve) {
Expand Down
19 changes: 11 additions & 8 deletions cli/src/commands/mcp/tools/subgraph-verify-schema-changes.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common/common_pb';
import { z } from 'zod';
import { SchemaChange } from '@wundergraph/cosmo-connect/dist/platform/v1/platform_pb';
import { getBaseHeaders } from '../../../core/config.js';
import { ToolContext } from './types.js';

export const registerSubgraphVerifySchemaChangesTool = ({ server, opts }: ToolContext) => {
server.tool(
server.registerTool(
'verify_subgraph_schema_changes',
'When making changes to a Subgraph Schema, this command can validate if the schema is valid GraphQL SDL, if it composes with all other subgraphs into a valid supergraph, and if there are any breaking changes.',
{
name: z.string().describe('The name of the subgraph'),
namespace: z.string().optional().describe('The namespace of the subgraph'),
schema: z.string().describe('The new schema SDL to check'),
delete: z.boolean().optional().describe('Run checks in case the subgraph should be deleted'),
skipTrafficCheck: z.boolean().optional().describe('Skip checking for client traffic'),
title: 'Verify Subgraph Schema Changes',
description:
'When making changes to a Subgraph Schema, this command can validate if the schema is valid GraphQL SDL, if it composes with all other subgraphs into a valid supergraph, and if there are any breaking changes.',
inputSchema: {
name: z.string().describe('The name of the subgraph'),
namespace: z.string().optional().describe('The namespace of the subgraph'),
schema: z.string().describe('The new schema SDL to check'),
delete: z.boolean().optional().describe('Run checks in case the subgraph should be deleted'),
skipTrafficCheck: z.boolean().optional().describe('Skip checking for client traffic'),
},
},
async (params) => {
const resp = await opts.client.platform.checkSubgraphSchema(
Expand Down
13 changes: 8 additions & 5 deletions cli/src/commands/mcp/tools/supergraph_changelog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,16 @@ export default async function main(opts: BaseCommandOptions, input: SupergraphCh
}

export function registerSupergraphChangelogTool({ server, opts }: ToolContext) {
server.tool(
server.registerTool(
'supergraph_changelog',
'Fetch the changelog for a federated graph / Supergraph.',
SupergraphChangelogInputSchema.shape,
async (toolInput: SupergraphChangelogInput) => {
{
title: 'Supergraph Changelog',
description: 'Fetch the changelog for a federated graph / Supergraph.',
inputSchema: SupergraphChangelogInputSchema.shape,
},
async (toolInput) => {
const mainOutput = await main(opts, toolInput);
// The .tool method expects a specific return format
// The registerTool method expects a specific return format
return { content: [{ type: 'text', text: JSON.stringify(mainOutput, null, 2) }] };
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ export const registerVerifyQueryAgainstInMemorySchemaTool = ({
server: McpServer;
opts: BaseCommandOptions;
}) => {
server.tool(
server.registerTool(
'verify_query_against_in_memory_schema',
'Verify if a GraphQL query is valid against a local in memory Supergraph or GraphQL SDL.',
{ query: z.string(), schema: z.string() },
{
title: 'Verify Query Against In Memory Schema',
description: 'Verify if a GraphQL query is valid against a local in memory Supergraph or GraphQL SDL.',
inputSchema: { query: z.string(), schema: z.string() },
},
({ query, schema: schemaString }) => {
try {
let document;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ export const registerVerifyQueryAgainstRemoteSchemaTool = ({
server: McpServer;
opts: BaseCommandOptions;
}) => {
server.tool(
server.registerTool(
'verify_query_against_remote_schema',
'Verify if a GraphQL query is valid against a remote Supergraph.',
{ query: z.string(), supergraph: z.string(), namespace: z.string().optional() },
{
title: 'Verify Query Against Remote Schema',
description: 'Verify if a GraphQL query is valid against a remote Supergraph.',
inputSchema: { query: z.string(), supergraph: z.string(), namespace: z.string().optional() },
},
async ({ query, supergraph, namespace }) => {
try {
const fedGraphSchemas = await getFederatedGraphSchemas({
Expand Down
17 changes: 12 additions & 5 deletions cli/src/commands/mcp/tools/verify-router-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,12 @@ export async function validateRouterConfig(config: string): Promise<ValidationRe
}

export const registerVerifyRouterConfigTool = ({ server }: ToolContext) => {
server.tool(
server.registerTool(
'cosmo-router-config-reference',
'Cosmo Router Configuration Reference helps you to understand how to configure the Router.',
{
title: 'Cosmo Router Configuration Reference',
description: 'Cosmo Router Configuration Reference helps you to understand how to configure the Router.',
},
async () => {
const getSchema = await axios.get(
'https://raw.githubusercontent.com/wundergraph/cosmo/refs/heads/main/router/pkg/config/config.schema.json',
Expand All @@ -112,11 +115,15 @@ export const registerVerifyRouterConfigTool = ({ server }: ToolContext) => {
},
);

server.tool(
server.registerTool(
'verify_router_config',
'Verify Cosmo Router Configurations. The config can be provided as JSON or YAML. This tool helps you to validate that a proposed configuration is valid.',
{
config: z.string().describe('The router config to verify. Can be provided as JSON or YAML.'),
title: 'Verify Router Config',
description:
'Verify Cosmo Router Configurations. The config can be provided as JSON or YAML. This tool helps you to validate that a proposed configuration is valid.',
inputSchema: {
config: z.string().describe('The router config to verify. Can be provided as JSON or YAML.'),
},
},
async ({ config }) => {
try {
Expand Down
2 changes: 1 addition & 1 deletion controlplane/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"tiny-lru": "^11.2.11",
"uid": "^2.0.2",
"uuid": "^10.0.0",
"zod": "^3.24.2",
"zod": "^3.25.0",
"zod-to-json-schema": "^3.22.4"
},
"devDependencies": {
Expand Down
Loading
Loading