schrepa/graft
Build agent-ready APIs without splitting your server model. Define tools once, expose them as both HTTP endpoints and MCP tools.
Platform-specific configuration:
{
"mcpServers": {
"graft": {
"command": "npx",
"args": [
"-y",
"graft"
]
}
}
}Add the config above to .claude/settings.json under the mcpServers key.
Build agent-ready APIs without splitting your server model.
Define tools once, then expose them as both HTTP endpoints and MCP tools from the same server. Graft also generates discovery docs, OpenAPI, and an interactive API reference automatically.
import { createApp, z } from '@schrepa/graft'
const app = createApp({ name: 'my-docs-api' })
app.tool('search_docs', {
description: 'Search documentation by keyword',
params: z.object({
q: z.string().describe('Search query'),
limit: z.coerce.number().optional().describe('Max results'),
}),
handler: ({ q, limit }) => {
return searchIndex(q, { limit: limit ?? 10 })
},
})
export default appThat one definition gives you:
Both transports share a single pipeline:
Agent (MCP) → POST /mcp → auth → validate → middleware → handler
Browser → GET /search-docs?q= → auth → validate → middleware → handlerOne handler. Two protocols. Same auth, same validation, same middleware.
npx @schrepa/create-graft-app my-app
cd my-app
npm install
npm run devOpen the studio to browse and test your tools: npm run studio
If you have an OpenAPI spec:
npx @schrepa/graft serve --openapi ./openapi.yaml --target http://localhost:8000Or create a graft.proxy.yaml to hand-pick the endpoints you want to expose:
target: htLoading reviews...