feat(TRUEREF-0011): implement MCP server with stdio transport

Adds a Model Context Protocol server that exposes resolve-library-id
and query-docs tools via stdio, with tool schemas identical to context7
for drop-in compatibility with Claude Code, Cursor, and Zed.

- src/mcp/index.ts — server entry point (io.github.trueref/trueref)
- src/mcp/client.ts — HTTP client for TrueRef REST API (TRUEREF_API_URL)
- src/mcp/tools/resolve-library-id.ts — library search tool handler
- src/mcp/tools/query-docs.ts — documentation retrieval tool handler
- src/mcp/index.test.ts — integration tests spawning real server subprocess
- .claude/rules/trueref.md — Claude Code rule file for MCP usage
- package.json: mcp:start script using tsx

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Giancarmine Salucci
2026-03-22 18:32:20 +01:00
parent 956b2a3a62
commit cb253ffe98
8 changed files with 1626 additions and 31 deletions

84
src/mcp/index.ts Normal file
View File

@@ -0,0 +1,84 @@
/**
* TrueRef MCP Server — stdio transport
*
* Exposes resolve-library-id and query-docs tools, identical to context7's
* MCP interface, for drop-in compatibility with Claude Code, Cursor, and
* other MCP-aware AI coding assistants.
*
* Configuration:
* TRUEREF_API_URL Base URL for the TrueRef REST API (default: http://localhost:5173)
*
* Usage:
* npx tsx src/mcp/index.ts
*/
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema
} from '@modelcontextprotocol/sdk/types.js';
import {
RESOLVE_LIBRARY_ID_TOOL,
handleResolveLibraryId
} from './tools/resolve-library-id.js';
import { QUERY_DOCS_TOOL, handleQueryDocs } from './tools/query-docs.js';
// ---------------------------------------------------------------------------
// Server setup
// ---------------------------------------------------------------------------
const server = new Server(
{
name: 'io.github.trueref/trueref',
version: '1.0.0'
},
{
capabilities: { tools: {} }
}
);
// ---------------------------------------------------------------------------
// Tool registry
// ---------------------------------------------------------------------------
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [RESOLVE_LIBRARY_ID_TOOL, QUERY_DOCS_TOOL]
}));
// ---------------------------------------------------------------------------
// Tool dispatch
// ---------------------------------------------------------------------------
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === 'resolve-library-id') {
return handleResolveLibraryId(args);
}
if (name === 'query-docs') {
return handleQueryDocs(args);
}
return {
content: [{ type: 'text' as const, text: `Unknown tool: ${name}` }],
isError: true
};
});
// ---------------------------------------------------------------------------
// Startup
// ---------------------------------------------------------------------------
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
// Server runs until process exits
}
main().catch((err) => {
process.stderr.write(`MCP server error: ${err instanceof Error ? err.message : String(err)}\n`);
process.exit(1);
});