Getting started
Add the starter for the Model Context Protocol (MCP):
<dependency>
<groupId>io.gatool</groupId>
<artifactId>gatool-mcp-spring-boot-starter</artifactId>
<version>0.1.0</version>
</dependency>
Put the query above in src/main/resources/gatool/mcp/TopRatedMovies.graphql,
and point the application at your API:
gatool:
api:
url: https://movies.example.com/graphql
schema:
location: classpath:movies.graphqls
mcp:
security:
unsafe:
allow-mcp-calls-without-authentication: true
GATool validates every operation against the schema file at startup. A query
that names a field missing from the schema stops startup. The message names the
file and the field. Once the CI check is in place, it fails the build for the
same reason. The CI check is the OperationFilesAssert test described under
"Checking your tools in CI". A test that starts the context fails the same way.
GATool builds the schema with graphql-java. graphql-java refuses one schema
shape that the GraphQL specification allows. In that shape, a type gives an
argument a different default from the one its interface declares. An example is
memberOf(limit: Int! = 150) under an interface that declares
limit: Int! = 100. Startup stops and names each such argument.
graphql-java#4480
asks graphql-java to accept such a schema. Until a release does, start the
application with a copy of the schema that gives those arguments the default of
their interface. GATool then describes the interface default to the model,
while the API applies its own.
The YAML above turns on
gatool.mcp.security.unsafe.allow-mcp-calls-without-authentication, the
unauthenticated switch. Without Spring Security on the classpath, the
unauthenticated switch is required, and startup stops while it is off. The
application logs a warning at every startup while the switch is on. Keep the
endpoint on a loopback address with server.address, or behind a gateway that
authenticates for it. The section on securing the endpoint below shows the
other way. Add the resource server starter, name the issuer, and leave the
unauthenticated switch off.
Start the application. A client that connects to /mcp reads one tool. The
entry is shortened here. The one on the wire also carries a title, the
$schema and the $id of the input schema, and the hints destructiveHint
and idempotentHint.
{
"name": "topRatedMovies",
"description": "Returns the highest-rated movies, best first.",
"inputSchema": {
"type": "object",
"properties": {
"first": {
"anyOf": [{ "type": "integer" }, { "type": "null" }],
"description": "How many movies to return.",
"default": 10
}
},
"required": [],
"additionalProperties": false
},
"annotations": { "readOnlyHint": true }
}