reuse-mcp
v0.2.0
Published
MCP server that exposes the public API surface of a TypeScript codebase to LLM coding agents
Downloads
151
Maintainers
Readme
reuse-mcp
LLM coding agents waste tokens grepping through files to discover existing code — and often duplicate logic because they never realize a helper already exists. reuse-mcp is an MCP server that gives agents a pre-computed, organized view of your TypeScript codebase's public API surface, typically less than 5 % of the source size in tokens. The name reuse is intentional: when an agent sees it in its tool list, the name nudges it toward checking what's reusable before writing something new.
Setup
Claude Code (CLI)
claude mcp add reuse-mcp -- npx -y reuse-mcpTo pass a custom config path:
claude mcp add reuse-mcp -- npx -y reuse-mcp --config path/to/config.jsonVerify with claude mcp list.
Kiro
Create or edit .kiro/settings/mcp.json in your workspace:
{
"mcpServers": {
"reuse-mcp": {
"command": "npx",
"args": ["-y", "reuse-mcp"],
"disabled": false,
"autoApprove": []
}
}
}Kiro picks up the server automatically — no restart needed.
Manual .mcp.json
If you prefer editing the config file directly:
{
"mcpServers": {
"reuse-mcp": {
"command": "npx",
"args": ["-y", "reuse-mcp"]
}
}
}Configuration
Create a reuse.config.json in your project root:
{
"groups": {
"services": {
"description": "Backend service classes",
"patterns": ["src/services/**/*.ts"]
},
"utils": {
"description": "Shared utility functions",
"patterns": ["src/utils/**/*.ts"]
}
},
"exclude": ["**/*.test.ts", "**/*.spec.ts", "**/__tests__/**"],
"respectInternalTag": true,
"annotationTag": "reuse",
"includeJsDoc": "none"
}All fields except groups are optional and shown above with their defaults.
Annotating your code
Use the @reuse JSDoc tag to surface guidance text directly to the agent:
/**
* Sends transactional emails through the configured provider.
* @reuse Prefer this over raw SMTP — handles retries, templates, and rate limits.
*/
export class EmailService {
send(to: string, template: string, vars: Record<string, string>): Promise<void>;
}The annotation text appears as a 📌 callout in the output the agent receives.
What the agent sees
When the agent calls get_reusable_surface for a group, it receives markdown like this:
# services
> Backend service classes
## EmailService — src/services/email.ts
📌 Prefer this over raw SMTP — handles retries, templates, and rate limits.
```ts
export class EmailService {
send(to: string, template: string, vars: Record<string, string>): Promise<void>;
}
```Only public signatures are included — no implementation bodies, no private members. By default, JSDoc comments are stripped to minimize token usage. Set includeJsDoc to "summary" or "full" to include them. Files with no exported declarations (e.g. barrel files) are automatically excluded from the output.
Tools
The server registers two MCP tools:
| Tool | Purpose |
|------|---------|
| list_reusable_groups | Directory of all configured groups with descriptions and file counts. |
| get_reusable_surface | Full public API surface of a named group as markdown. |
Results are cached in memory using file modification times, so repeated calls within a session are fast.
Config options
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| groups | Record<string, { description, patterns }> | (required) | Named groups of glob patterns |
| exclude | string[] | ["**/*.test.ts", "**/*.spec.ts", "**/__tests__/**"] | Glob patterns excluded from all groups |
| respectInternalTag | boolean | true | Omit exports tagged @internal |
| annotationTag | string | "reuse" | JSDoc tag name used for agent-facing annotations |
| includeJsDoc | "none" \| "summary" \| "full" | "none" | Controls JSDoc in output: "none" strips all, "summary" shows first line, "full" includes entire block |
Local development
Using a local build with Claude Code
If you're developing reuse-mcp or want to try it before publishing, point Claude Code at your local build:
# Build the project
npm run build
# Add the local server to Claude Code (use the absolute path to dist/server.js)
claude mcp add reuse-mcp -- node /absolute/path/to/reuse-mcp/dist/server.jsOr edit .mcp.json directly:
{
"mcpServers": {
"reuse-mcp": {
"command": "node",
"args": ["/absolute/path/to/reuse-mcp/dist/server.js"]
}
}
}To point it at a different project's config:
{
"mcpServers": {
"reuse-mcp": {
"command": "node",
"args": [
"/absolute/path/to/reuse-mcp/dist/server.js",
"--config", "/path/to/target-project/reuse.config.json"
]
}
}
}After making changes, run npm run build again — Claude Code will use the updated server on the next tool call.
Inspecting output manually
You can invoke the server directly from your terminal to see exactly what an agent would receive. The server speaks JSON-RPC over stdio, so you pipe requests in and read responses out.
First, build and make sure you have a reuse.config.json in the target project:
npm run buildThen send a JSON-RPC request. The server expects an MCP initialize handshake first, followed by your tool call:
# List all configured groups
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"manual","version":"1.0.0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_reusable_groups","arguments":{}}}' \
| node dist/server.js 2>/dev/null | grep '"id":2'# Get the surface for a specific group
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"manual","version":"1.0.0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_reusable_surface","arguments":{"groupName":"utils"}}}' \
| node dist/server.js 2>/dev/null | grep '"id":2'The response is a JSON-RPC message with the markdown content in result.content[0].text. Pipe through jq for readability:
... | grep '"id":2' | jq -r '.result.content[0].text'Working example with pipe
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"manual","version":"1.0.0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_reusable_surface","arguments":{"groupName":"services"}}}' \
| node /Users/alext/Projects/reuse-mcp/dist/server.js --config /Users/alext/Projects/TechWalk2/reuse.config.json | jq -r '.result.content[0].text'This is useful for verifying your config, checking what the agent will see, and debugging extraction issues.
Publishing to npm
To make the package available via npx -y reuse-mcp:
npm run build
npm login # one-time
npm publish --access publicAfter publishing, anyone can run the server without a local install:
npx -y reuse-mcpTo publish updates, bump the version in package.json and run npm publish again.
Tips
- Commit
reuse.config.jsonto your repo so every contributor gets the same surface view. The.mcp.jsonfile is local to your editor setup and generally should not be committed. - You can pass a custom config path with
--config path/to/config.jsonor theREUSE_CONFIGenvironment variable. - If a file fails to parse, the server includes a warning and continues with the rest of the group.
