|
| 1 | +# Copilot Instructions for `hypermcp` |
| 2 | + |
| 3 | +These instructions help AI coding agents work productively in this repository. They describe the architecture, key workflows, and project-specific patterns you should follow and extend. |
| 4 | + |
| 5 | +## Big Picture |
| 6 | + |
| 7 | +`hypermcp` is a small, reusable Go library that provides common infrastructure for building Model Context Protocol (MCP) servers. It wraps the MCP Go SDK with: |
| 8 | +- A configured HTTP client (`httpx.Client`) with retries, timeouts, and limits |
| 9 | +- A simple caching layer (`cache.Cache`) built on Ristretto |
| 10 | +- Structured logging via `zap` |
| 11 | +- Transport helpers for stdio (implemented) and Streamable HTTP (placeholder) |
| 12 | + |
| 13 | +Core types: |
| 14 | +- `Server` (`server.go`): owns `mcp.Server`, `httpx.Client`, `cache.Cache`, and `zap.Logger`; exposes helpers and registration stats. |
| 15 | +- `TransportType` + `RunWithTransport` (`transport.go`): selects and starts transport (only `stdio` implemented). |
| 16 | +- `ServerInfo` (`version.go`): simple version struct and formatter. |
| 17 | + |
| 18 | +Typical usage (from `README.md`): create a `Server` with `Config`, build providers using `srv.HTTPClient()/Cache()/Logger()`, register tools/resources, log counts, then run with stdio. |
| 19 | + |
| 20 | +## Project Conventions |
| 21 | + |
| 22 | +- Package name: `hypermcp`; import path: `github.com/rayprogramming/hypermcp`. |
| 23 | +- Prefer dependency injection via the `Server` getters over global singletons. |
| 24 | +- Register MCP features via `srv.AddTool`, `srv.AddResource`, `srv.AddResourceTemplate` on `srv.MCP()` or helpers on `Server` (see README examples). After each registration, call `srv.IncrementToolCount()` or `srv.IncrementResourceCount()` so `LogRegistrationStats()` is accurate. |
| 25 | +- Use `RunWithTransport(ctx, srv, TransportStdio, logger)` for starting servers; HTTP transport is not implemented and should return a clear error. |
| 26 | +- Logging: use the `srv.Logger()`; keep logs structured and low-noise in hot paths. Cache/HTTP helpers already log at `Debug`/`Warn` where appropriate. |
| 27 | + |
| 28 | +## httpx Client Patterns (`httpx/httpx.go`) |
| 29 | + |
| 30 | +- Use `Client.Get(ctx, url, &result)` for JSON GET requests; it sets headers and delegates to `DoJSON`. |
| 31 | +- `DoJSON` handles retries (3 max) for 429/5xx, request timeout (~6s), and caps response size at 10MB. It returns permanent errors for non-retryable statuses and JSON decode errors. |
| 32 | +- Always pass `context.Context`; cancellation/timeouts are respected and covered by tests. |
| 33 | +- Example: |
| 34 | + ```go |
| 35 | + type Payload struct { Message string `json:"message"` } |
| 36 | + var out Payload |
| 37 | + if err := srv.HTTPClient().Get(ctx, "https://api.example.com/status", &out); err != nil { /* handle */ } |
| 38 | + ``` |
| 39 | + |
| 40 | +## Cache Patterns (`cache/cache.go`) |
| 41 | + |
| 42 | +- `cache.Cache` stores arbitrary values with TTL tracking (internal map) on top of Ristretto. Methods: `Get`, `Set(key, value, ttl)`, `Delete`, `Clear`, `Metrics`, `Close`. |
| 43 | +- TTL is enforced via a background cleanup goroutine and checked on `Get`. If expired, the key is deleted lazily. |
| 44 | +- Cost is roughly estimated (constant 64). If you store large payloads, prefer storing pointers or compact structs to avoid exceeding `MaxCost`. |
| 45 | +- Example: |
| 46 | + ```go |
| 47 | + v, ok := srv.Cache().Get(cacheKey) |
| 48 | + if ok { /* use v */ } |
| 49 | + // fill and set for 1 minute |
| 50 | + srv.Cache().Set(cacheKey, data, time.Minute) |
| 51 | + ``` |
| 52 | + |
| 53 | +## Transport (`transport.go`) |
| 54 | + |
| 55 | +- Use `TransportStdio` for most MCP servers. Starting with Streamable HTTP should return `fmt.Errorf("Streamable HTTP transport not yet implemented")` — don’t attempt to wire HTTP until implemented here. |
| 56 | +- `RunWithTransport` logs selected transport, sets up `mcp.StdioTransport`, then calls `srv.Run(ctx, transport)`. |
| 57 | + |
| 58 | +## Tests & Benchmarks |
| 59 | + |
| 60 | +- Unit tests exist for `cache` and `httpx` packages: |
| 61 | + - `cache/cache_test.go`: Get/Set, expiration, delete, and basic benchmarks. |
| 62 | + - `httpx/httpx_test.go`: success path, retry behavior, context cancellation, and benchmark. |
| 63 | +- Run with: |
| 64 | + - All: `go test ./...` |
| 65 | + - Specific pkg: `go test ./cache -v` |
| 66 | + - Benchmarks: `go test -bench=. ./cache` |
| 67 | + |
| 68 | +## Developer Workflows |
| 69 | + |
| 70 | +- Build: standard `go build ./...` (no custom build tags). This library is imported by downstream MCP servers. |
| 71 | +- Logging setup: use `zap.NewProduction()` in binaries; tests use `zaptest`. |
| 72 | +- Versioning: `ServerInfo` is available for embedding version/build info in your binaries. |
| 73 | +- Error handling: return wrapped errors (`fmt.Errorf("context", %w)`) from helpers; transport selection returns explicit errors for unsupported modes. |
| 74 | + |
| 75 | +## Integration Points |
| 76 | + |
| 77 | +- MCP SDK: `github.com/modelcontextprotocol/go-sdk/mcp` — use `srv.MCP()` if you need direct access to register tools/resources beyond the helpers shown in README. |
| 78 | +- HTTP deps: `cenkalti/backoff/v4` for retries; standard `net/http`; headers pre-set in `Get`. |
| 79 | +- Cache dep: `github.com/dgraph-io/ristretto` with metrics available via `Cache.Metrics()`. |
| 80 | + |
| 81 | +## Gotchas |
| 82 | + |
| 83 | +- Cache is created even when `CacheEnabled=false` (as a minimal instance). Don’t assume `srv.Cache()` is nil. |
| 84 | +- Response bodies over 10MB will be truncated by `httpx` and cause errors. Choose APIs accordingly or stream/process incrementally. |
| 85 | +- Streamable HTTP transport is intentionally unimplemented — calling it should be treated as a configuration error. |
0 commit comments