mcp-devtools
CLAUDE.md161 starsChanged 5 months agoApache-2.0View on GitHub
This is a modular MCP (Model Context Protocol) server built in Go that provides developer tools through a plugin-like architecture. Please read the README.md for more information, and docs/creating-new-tools.md for details on how to create new tools. Tools are organised into categories under internal/tools/, e.g: - internetsearch/ - Internet Search API integrations (web, image, news, video, local) - packageversions/ - Package version checking across ecosystems (npm, python, go, java, swift, docker, github-actions, bedrock, rust) - shadcnui/ - shadcn/ui component information…
- Reads credentials
We split this CLAUDE.md into the rules it gives an agent
29 rules. About 0 are common, 17 are distinctive, and 12 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈17
Distinctive · estimate
This author's own choices. Worth a look.
12
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 52
Create package under internal/tools/[category]/[toolname]/
- Very specific: line 55
Import the package in internal/imports/tools.go (NOT in main.go) to trigger registration
- Very specific: line 87
Use make test-fast for development to avoid external API calls.
- Distinctive: line 95
All tools follow this pattern:
- Distinctive: line 100
Use shared logger and cache for consistency
- Distinctive: line 104
CRITICAL: Before registering a new tool, verify the following:
- Very specific: line 108
Only add tool to defaultTools list in enabledByDefault() (registry.go) if the user has explicitly stated it should be enabled by default
- Distinctive: line 111
When in Doubt - Leave the tool disabled by default.
- Distinctive: line 117
When testing the docprocessing tool, unless otherwise instructed always call it with "clear_file_cache": true and do not enable …
- Distinctive: line 120
Always use British English spelling, we are not American.
- Distinctive: line 121
Follow the principle of least privileged security.
- Distinctive: line 123
Use 0600 and 0700 permissions for files and directories respectively, unless otherwise specified avoid using 0644 and 0755.
- Distinctive: line 128
When creating new MCP tools make sure descriptions are clear and concise as they are what is used as hints to the AI coding agent using the …
- Distinctive: line 136
Don't simply wrap existing API endpoints - build thoughtful, high-impact workflow tools
- Distinctive: line 139
Consider what workflows agents actually need to accomplish
- Distinctive: line 145
Default to human-readable identifiers over technical codes (names over IDs)
- Distinctive: line 146
Consider the agent's context budget as a scarce resource
- Distinctive: line 160
Create realistic evaluation scenarios early
- Distinctive: line 165
DRY Principle: No duplicated code between tools
- Distinctive: line 168
Error Handling: All external calls have error handling
- Distinctive: line 169
Documentation: Every tool has comprehensive docstrings/descriptions
- Very specific: line 193
Use any instead of interface{}
- Very specific: line 194
Use comparable for type constraints when appropriate
- Very specific: line 198
Use strings.SplitSeq() and strings.FieldsSeq() in range loops instead of strings.Split() and strings.Fields()
- Very specific: line 201
Use for range n instead of for i := 0.
- Very specific: line 202
Use min(a, b) and max(a, b) instead of if/else conditionals
- Very specific: line 205
Use slices.Contains(slice, element) instead of manual loops for searching
- Very specific: line 207
Use maps.Copy(dst, src) instead of manual for k, v := range src { dst[k] = v } loops
- Very specific: line 210
Use t.Context() instead of context.WithCancel() in tests
≈ “Common” is an estimate: at least 1 in 5 of the 25,680 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
Build and Run
make build- Build the server binary tobin/mcp-devtoolsmake run- Build and run server with stdio transport (default)make run-http- Build and run server with HTTP transport on port 18080
Testing
make test- Run all tests (includes external API tests, ~10s)make test-fast- Run tests without external API calls (~7s)make test-verbose- Show detailed per-test timingmake test-slow- Show slowest tests sorted by durationgo test -short -v ./tests/...- Run specific test suites
Code Quality
make lint- Run linting, formatting and modernisation checks
Dependencies
make deps- Install dependenciesmake update-deps- Update dependenciesgo mod tidy- Clean up go.mod
Architecture
This is a modular MCP (Model Context Protocol) server built in Go that provides developer tools through a plugin-like architecture.
Please read the README.md for more information, and docs/creating-new-tools.md for details on how to create new tools.
Core Components
- Tool Registry (
internal/registry/) - Central registry that manages tool registration and discovery - Tool Interface (
internal/tools/tools.go) - Defines the interface all tools must implement - Main Server (
main.go) - MCP server that supports multiple transports (stdio, SSE, HTTP)
Tool Categories
Tools are organised into categories under internal/tools/, e.g:
internetsearch/- Internet Search API integrations (web, image, news, video, local)packageversions/- Package version checking across ecosystems (npm, python, go, java, swift, docker, github-actions, bedrock, rust)shadcnui/- shadcn/ui component information and examplesthink/- Structured reasoning tool for AI agentswebfetch/- Web content fetching and conversion to markdownutils/- Shared utilities for tools (e.g. proxy)- etc..
Adding New Tools
- Create package under
internal/tools/[category]/[toolname]/ - Implement the
tools.Toolinterface withDefinition()andExecute()methods - Register tool in
init()function usingregistry.Register(&YourTool{}) - Import the package in
internal/imports/tools.go(NOT inmain.go) to trigger registration
Tools automatically get:
- Shared cache (
sync.Map) - Logger (
logrus.Logger) - Context and parsed arguments
Transport Support
The server supports two transport modes:
- stdio (default) - Standard input/output for MCP clients
- http - Stateless Streamable HTTP (MCP 2026-07-28) with optional bearer token or OAuth authentication
SSE was removed in MCP 2026-07-28; --transport sse exits with an error.
Important Files
main.go- Server entry point and transport configurationinternal/registry/registry.go- Tool registry implementationinternal/tools/tools.go- Tool interface definitionMakefile- Build and development commandsgo.mod- Go module dependencies
Testing Strategy
Tests are organised in tests/ directory:
testutils/- Test helpers and mockstools/- Tool-specific testsunit/- Unit tests for core components
Tests should not depend on external APIs or services unless cleared by the user as necessary.
Use make test-fast for development to avoid external API calls.
Build System
Uses Go modules with version information injected at build time through ldflags in the Makefile. The binary includes version, commit hash, and build date.
Tool Development Pattern
All tools follow this pattern:
- Define struct implementing
tools.Tool - Register in
init()withregistry.Register() - Implement
Definition()for MCP tool schema - Implement
Execute()for tool logic - Use shared logger and cache for consistency
New Tool Registration Checklist
CRITICAL: Before registering a new tool, verify the following:
Default Enablement Decision
- By default, ALL new tools are DISABLED - this is the secure default
- Only add tool to
defaultToolslist inenabledByDefault()(registry.go) if the user has explicitly stated it should be enabled by default - If tool is NOT added to defaultTools: It will require
ENABLE_ADDITIONAL_TOOLSto use (this is correct for most tools) - Tests enable the tool via
ENABLE_ADDITIONAL_TOOLSif not in defaultTools list - When in Doubt - Leave the tool disabled by default. It's safer to require explicit enablement than to accidentally expose destructive functionality.
General Guidelines
- CRITICAL: Ensure that when running in stdio mode that we NEVER log to stdout or stderr, as this will break the MCP protocol.
- Any tools we create must work on both macOS and Linux unless the user states otherwise (only add windows workarounds if they're easy to implement, don't reduce functionality for macOS/Linux and are low maintenance).
- When testing the docprocessing tool, unless otherwise instructed always call it with "clear_file_cache": true and do not enable return_inline_only
- If you're wanting to call a tool you've just made changes to directly (rather than using the command line approach), you have to let the user know to restart the conversation otherwise you'll only have access to the old version of the tool functions directly.
- When adding new tools ensure they are registered in the list of available tools in the server (within their init function), ensure they have a basic unit test, and that they have docs/tools/
<toolname>.md with concise, clear information about the tool and that they're mentioned in the main README.md and docs/tools/overview.md. - Always use British English spelling, we are not American.
- Follow the principle of least privileged security.
- Tool responses should be limited to only include information that is actually useful, there's no point in returning the information an agent provides to call the tool back to them, or any generic information or null / empty fields - these just waste tokens.
- Use 0600 and 0700 permissions for files and directories respectively, unless otherwise specified avoid using 0644 and 0755.
- Unit tests for tools should be located within the tests/tools/ directory, and should be named
<toolname>_test.go. - We should be mindful of the risks of code injection and other security risks when parsing any information from external sources.
- On occasion the user may ask you to build a new tool and provide reference code or information in a provided directory such as
tmp_repo_clones/<dirname>unless specified otherwise this should only be used for reference and learning purposes, we don't ever want to use code that directory as part of the project's codebase. - After making changes and performing a build if you need to test the MCP server with the updated changes you MUST either test it from the command line - or STOP and ask the user to restart the MCP client otherwise you won't pick up the latest changes
- When creating new MCP tools make sure descriptions are clear and concise as they are what is used as hints to the AI coding agent using the tool, you should also make good use of MCP's annotations.
- Tools use the
internal/mcpapipackage, which wraps the official https://github.com/modelcontextprotocol/go-sdk. See docs/creating-new-tools.md.
MCP Development Best Practices
Build for Workflows, Not Just API Endpoints:
- Don't simply wrap existing API endpoints - build thoughtful, high-impact workflow tools
- Consolidate related operations (e.g.,
schedule_eventthat both checks availability and creates event) - Focus on tools that enable complete tasks, not just individual API calls
- Consider what workflows agents actually need to accomplish
Optimise for Limited Context:
- Agents have constrained context windows - make every token count
- Return high-signal information, not exhaustive data dumps
- Provide "concise" vs "detailed" response format options where applicable
- Default to human-readable identifiers over technical codes (names over IDs)
- Consider the agent's context budget as a scarce resource
Design Actionable Error Messages:
- Error messages should guide agents toward correct usage patterns
- Suggest specific next steps: "Try using filter='active_only' to reduce results"
- Make errors educational, not just diagnostic
- Help agents learn proper tool usage through clear feedback
Follow Natural Task Subdivisions:
- Tool names should reflect how humans think about tasks
- Group related tools with consistent prefixes for discoverability
- Design tools around natural workflows, not just API structure
Use Evaluation-Driven Development:
- Create realistic evaluation scenarios early
- Let agent feedback drive tool improvements
- Prototype quickly and iterate based on actual agent performance
To ensure quality, review the code for:
- DRY Principle: No duplicated code between tools
- Composability: Shared logic extracted into functions
- Consistency: Similar operations return similar formats
- Error Handling: All external calls have error handling
- Documentation: Every tool has comprehensive docstrings/descriptions
Improving Tools with Tool Error Logs
If the user asks you to look at the tool call error logs, they can be found in ~/.mcp-devtools/logs/tool-errors.log (assuming the user has enabled tool error logging), looking at recent tool calling failures can be useful for improving tools that may be failing often. If looking at the tool error logs, ensure you look for the relevant date/time range when the user was experiencing issues.
Quick Debugging Tips
- You can debug the tool by running it in debug mode interactively, e.g.
rm -f debug.log; pkill -f "mcp-devtools.*" ; echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "fetch_url", "arguments": {"url": "https://go.dev", "max_length": 500, "raw": false}}}' | ./bin/mcp-devtools stdio, orBRAVE_API_KEY="ask the user if you need this" ./bin/mcp-devtools stdio <<< '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "brave_search", "arguments": {"type": "web", "query": "cat facts", "count": 1}}}'
Lint Github Actions
actionlintGo Modernisation Rules for AI Coding Agents
CRITICAL: Follow these rules when writing Go code to avoid outdated patterns that modernize would flag:
Types and Interfaces
- Use
anyinstead ofinterface{} - Use
comparablefor type constraints when appropriate
String Operations
- Use
strings.CutPrefix(s, prefix)instead ofif strings.HasPrefix(s, prefix) { s = strings.TrimPrefix(s, prefix) } - Use
strings.SplitSeq()andstrings.FieldsSeq()in range loops instead ofstrings.Split()andstrings.Fields()
Loops and Control Flow
- Use
for range ninstead offor i := 0; i < n; i++when index isn't used - Use
min(a, b)andmax(a, b)instead of if/else conditionals
Slices and Maps
- Use
slices.Contains(slice, element)instead of manual loops for searching - Use
slices.Sort(s)instead ofsort.Slice(s, func(i, j int) bool { return s[i] < s[j] }) - Use
maps.Copy(dst, src)instead of manualfor k, v := range src { dst[k] = v }loops
Testing
- Use
t.Context()instead ofcontext.WithCancel()in tests
Formatting
- Use
fmt.Appendf(nil, format, args...)instead of[]byte(fmt.Sprintf(format, args...))
OpenTelemetry Tracing Patterns
Session span parent-child relationships: Session spans in internal/telemetry/tracer.go must be ended immediately followed by ForceFlush() to ensure they export to the backend before child tool spans. Without force flush, the OTEL batch processor exports asynchronously, causing child spans to arrive before their parent, resulting in "invalid parent span IDs" warnings in Jaeger.
sessionSpan.End()
// CRITICAL: Force flush ensures parent exports before children
if tp != nil {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
_ = tp.ForceFlush(ctx)
}Tool spans inherit trace context via W3C Trace Context propagation (inject→extract pattern) in StartToolSpan().
IMPORTANT
- YOU MUST ALWAYS run
make lint && make test && make buildetc... to build the project rather than gofmt, go build or test directly, and you MUST always do this before stating you've completed your changes! - CRITICAL: If the serena tool is available to you, you must use serena for your semantic code retrieval and editing tools
In this repositoryOne other file it gives its agents.
- .github/copilot-instructions.mdCopilot instructions
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

