Apache-2.0 · Node 20+ · SLSA provenance on every package
AskTurret reads the spec you already have and serves it over the Model Context Protocol. No code generation, and no second copy of your API to keep in step with the first.
runs as
No generated code, and no second copy of your API — your spec stays the single source of truth.
Quick start
Mount it into an Express app. The MCP layer is the single app.use
line.
npm install express @askturret/mcp-adapters-express
cat > petstore.yaml <<'YAML'
openapi: 3.0.0
info:
title: Petstore API
version: 1.0.0
servers:
- url: https://petstore.example.com/api/v1
paths:
/pets:
get:
operationId: listPets
description: Returns a list of all pets in the store
parameters:
- name: limit
in: query
description: Maximum number of pets to return
schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
responses:
'200':
description: A list of pets
content:
application/json:
schema:
type: object
properties:
pets:
type: array
items:
type: object
properties:
id: { type: string }
name: { type: string }
/pets/{petId}:
get:
operationId: getPetById
description: Returns a single pet
parameters:
- name: petId
in: path
required: true
description: ID of the pet to return
schema: { type: string }
responses:
'200':
description: A pet
content:
application/json:
schema:
type: object
properties:
id: { type: string }
name: { type: string }
YAML
Score the spec before you run it, to see what will be exposed:
npx @askturret/mcp-cli doctor petstore.yaml
import express from 'express';
import { mcpFromOpenApi } from '@askturret/mcp-adapters-express';
const port = Number(process.env.PORT ?? 7078);
const app = express();
app.use('/mcp', mcpFromOpenApi('./petstore.yaml'));
const server = app.listen(port);
server.on('listening', () => console.log(`MCP server on http://localhost:${port}/mcp`));
server.on('error', (err) => {
if (err.code !== 'EADDRINUSE') throw err;
console.error(`Port ${port} is already in use. Start it on another port: PORT=8078 node server.mjs`);
process.exit(1);
});
node server.mjs
Your API now exposes tools over MCP. Ask it what it has:
curl -X POST http://localhost:7078/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Point mcpFromOpenApi at your own spec to swap the sample out.
There is also an explorer UI at /mcp/explorer for browsing and
testing the tools by hand.
Deployment
The same discovery and tool-shaping runs in all three. Which one you pick is a question about your service, not about what you give up.
One app.use on a route you choose, sharing the process,
middleware and auth you already run. Express 4 and 5 are both supported,
and CI runs a matrix leg against each rather than declaring support and
testing one.
Registered as a plugin, so it inherits the encapsulation and lifecycle hooks Fastify already gives you. The model and the tool output are identical to the Express path.
A separate process in front of an API you would rather not modify — one you do not own, cannot redeploy, or simply do not want to touch. Nothing changes on the other side.
Provenance
Every published package carries SLSA build provenance, and every tarball
ships LICENSE and NOTICE inside it. Ask the
registry rather than taking it on trust:
npm view @askturret/mcp-core@0.2.0 dist.attestations
Provenance ties a published tarball to the workflow run and the commit that built it.
Status
@askturret scope.1.0.0 — under semver, 0.x carries no compatibility guarantee.No production users yet.
Read more