mnehmos.trace.mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1662 -0
- package/dist/adapters/bootstrap.d.ts +29 -0
- package/dist/adapters/bootstrap.d.ts.map +1 -0
- package/dist/adapters/bootstrap.js +46 -0
- package/dist/adapters/bootstrap.js.map +1 -0
- package/dist/adapters/errors.d.ts +94 -0
- package/dist/adapters/errors.d.ts.map +1 -0
- package/dist/adapters/errors.js +107 -0
- package/dist/adapters/errors.js.map +1 -0
- package/dist/adapters/graphql/index.d.ts +9 -0
- package/dist/adapters/graphql/index.d.ts.map +1 -0
- package/dist/adapters/graphql/index.js +9 -0
- package/dist/adapters/graphql/index.js.map +1 -0
- package/dist/adapters/graphql/sdl-parser.d.ts +74 -0
- package/dist/adapters/graphql/sdl-parser.d.ts.map +1 -0
- package/dist/adapters/graphql/sdl-parser.js +559 -0
- package/dist/adapters/graphql/sdl-parser.js.map +1 -0
- package/dist/adapters/grpc/adapter.d.ts +76 -0
- package/dist/adapters/grpc/adapter.d.ts.map +1 -0
- package/dist/adapters/grpc/adapter.js +362 -0
- package/dist/adapters/grpc/adapter.js.map +1 -0
- package/dist/adapters/grpc/index.d.ts +10 -0
- package/dist/adapters/grpc/index.d.ts.map +1 -0
- package/dist/adapters/grpc/index.js +12 -0
- package/dist/adapters/grpc/index.js.map +1 -0
- package/dist/adapters/grpc/proto-parser.d.ts +76 -0
- package/dist/adapters/grpc/proto-parser.d.ts.map +1 -0
- package/dist/adapters/grpc/proto-parser.js +523 -0
- package/dist/adapters/grpc/proto-parser.js.map +1 -0
- package/dist/adapters/grpc/type-converter.d.ts +43 -0
- package/dist/adapters/grpc/type-converter.d.ts.map +1 -0
- package/dist/adapters/grpc/type-converter.js +270 -0
- package/dist/adapters/grpc/type-converter.js.map +1 -0
- package/dist/adapters/grpc/types.d.ts +85 -0
- package/dist/adapters/grpc/types.d.ts.map +1 -0
- package/dist/adapters/grpc/types.js +7 -0
- package/dist/adapters/grpc/types.js.map +1 -0
- package/dist/adapters/index.d.ts +39 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +50 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/mcp.d.ts +23 -0
- package/dist/adapters/mcp.d.ts.map +1 -0
- package/dist/adapters/mcp.js +293 -0
- package/dist/adapters/mcp.js.map +1 -0
- package/dist/adapters/openapi/adapter.d.ts +213 -0
- package/dist/adapters/openapi/adapter.d.ts.map +1 -0
- package/dist/adapters/openapi/adapter.js +557 -0
- package/dist/adapters/openapi/adapter.js.map +1 -0
- package/dist/adapters/openapi/convert.d.ts +120 -0
- package/dist/adapters/openapi/convert.d.ts.map +1 -0
- package/dist/adapters/openapi/convert.js +363 -0
- package/dist/adapters/openapi/convert.js.map +1 -0
- package/dist/adapters/openapi/index.d.ts +39 -0
- package/dist/adapters/openapi/index.d.ts.map +1 -0
- package/dist/adapters/openapi/index.js +48 -0
- package/dist/adapters/openapi/index.js.map +1 -0
- package/dist/adapters/openapi/parser.d.ts +95 -0
- package/dist/adapters/openapi/parser.d.ts.map +1 -0
- package/dist/adapters/openapi/parser.js +171 -0
- package/dist/adapters/openapi/parser.js.map +1 -0
- package/dist/adapters/registry.d.ts +116 -0
- package/dist/adapters/registry.d.ts.map +1 -0
- package/dist/adapters/registry.js +246 -0
- package/dist/adapters/registry.js.map +1 -0
- package/dist/adapters/trpc/adapter.d.ts +159 -0
- package/dist/adapters/trpc/adapter.d.ts.map +1 -0
- package/dist/adapters/trpc/adapter.js +223 -0
- package/dist/adapters/trpc/adapter.js.map +1 -0
- package/dist/adapters/trpc/extractor.d.ts +218 -0
- package/dist/adapters/trpc/extractor.d.ts.map +1 -0
- package/dist/adapters/trpc/extractor.js +708 -0
- package/dist/adapters/trpc/extractor.js.map +1 -0
- package/dist/adapters/trpc/index.d.ts +31 -0
- package/dist/adapters/trpc/index.d.ts.map +1 -0
- package/dist/adapters/trpc/index.js +40 -0
- package/dist/adapters/trpc/index.js.map +1 -0
- package/dist/adapters/trpc/parser.d.ts +119 -0
- package/dist/adapters/trpc/parser.d.ts.map +1 -0
- package/dist/adapters/trpc/parser.js +128 -0
- package/dist/adapters/trpc/parser.js.map +1 -0
- package/dist/compare/index.d.ts +33 -0
- package/dist/compare/index.d.ts.map +1 -0
- package/dist/compare/index.js +261 -0
- package/dist/compare/index.js.map +1 -0
- package/dist/core/types.d.ts +188 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +9 -0
- package/dist/core/types.js.map +1 -0
- package/dist/extract/index.d.ts +26 -0
- package/dist/extract/index.d.ts.map +1 -0
- package/dist/extract/index.js +44 -0
- package/dist/extract/index.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +674 -0
- package/dist/index.js.map +1 -0
- package/dist/languages/base.d.ts +57 -0
- package/dist/languages/base.d.ts.map +1 -0
- package/dist/languages/base.js +6 -0
- package/dist/languages/base.js.map +1 -0
- package/dist/languages/bootstrap.d.ts +10 -0
- package/dist/languages/bootstrap.d.ts.map +1 -0
- package/dist/languages/bootstrap.js +25 -0
- package/dist/languages/bootstrap.js.map +1 -0
- package/dist/languages/go/handlers/chi.d.ts +24 -0
- package/dist/languages/go/handlers/chi.d.ts.map +1 -0
- package/dist/languages/go/handlers/chi.js +205 -0
- package/dist/languages/go/handlers/chi.js.map +1 -0
- package/dist/languages/go/handlers/gin.d.ts +24 -0
- package/dist/languages/go/handlers/gin.d.ts.map +1 -0
- package/dist/languages/go/handlers/gin.js +156 -0
- package/dist/languages/go/handlers/gin.js.map +1 -0
- package/dist/languages/go/handlers/stdlib.d.ts +19 -0
- package/dist/languages/go/handlers/stdlib.d.ts.map +1 -0
- package/dist/languages/go/handlers/stdlib.js +112 -0
- package/dist/languages/go/handlers/stdlib.js.map +1 -0
- package/dist/languages/go/index.d.ts +18 -0
- package/dist/languages/go/index.d.ts.map +1 -0
- package/dist/languages/go/index.js +20 -0
- package/dist/languages/go/index.js.map +1 -0
- package/dist/languages/go/parser.d.ts +33 -0
- package/dist/languages/go/parser.d.ts.map +1 -0
- package/dist/languages/go/parser.js +95 -0
- package/dist/languages/go/parser.js.map +1 -0
- package/dist/languages/go/struct-extractor.d.ts +59 -0
- package/dist/languages/go/struct-extractor.d.ts.map +1 -0
- package/dist/languages/go/struct-extractor.js +483 -0
- package/dist/languages/go/struct-extractor.js.map +1 -0
- package/dist/languages/go/tag-parser.d.ts +62 -0
- package/dist/languages/go/tag-parser.d.ts.map +1 -0
- package/dist/languages/go/tag-parser.js +108 -0
- package/dist/languages/go/tag-parser.js.map +1 -0
- package/dist/languages/go/type-converter.d.ts +32 -0
- package/dist/languages/go/type-converter.d.ts.map +1 -0
- package/dist/languages/go/type-converter.js +226 -0
- package/dist/languages/go/type-converter.js.map +1 -0
- package/dist/languages/go/types.d.ts +153 -0
- package/dist/languages/go/types.d.ts.map +1 -0
- package/dist/languages/go/types.js +6 -0
- package/dist/languages/go/types.js.map +1 -0
- package/dist/languages/import-resolver.d.ts +645 -0
- package/dist/languages/import-resolver.d.ts.map +1 -0
- package/dist/languages/import-resolver.js +1278 -0
- package/dist/languages/import-resolver.js.map +1 -0
- package/dist/languages/index.d.ts +34 -0
- package/dist/languages/index.d.ts.map +1 -0
- package/dist/languages/index.js +93 -0
- package/dist/languages/index.js.map +1 -0
- package/dist/languages/json-schema.d.ts +40 -0
- package/dist/languages/json-schema.d.ts.map +1 -0
- package/dist/languages/json-schema.js +188 -0
- package/dist/languages/json-schema.js.map +1 -0
- package/dist/languages/python-ast/index.d.ts +8 -0
- package/dist/languages/python-ast/index.d.ts.map +1 -0
- package/dist/languages/python-ast/index.js +7 -0
- package/dist/languages/python-ast/index.js.map +1 -0
- package/dist/languages/python-ast/parser.d.ts +174 -0
- package/dist/languages/python-ast/parser.d.ts.map +1 -0
- package/dist/languages/python-ast/parser.js +1205 -0
- package/dist/languages/python-ast/parser.js.map +1 -0
- package/dist/languages/python-ast/type-resolver.d.ts +75 -0
- package/dist/languages/python-ast/type-resolver.d.ts.map +1 -0
- package/dist/languages/python-ast/type-resolver.js +421 -0
- package/dist/languages/python-ast/type-resolver.js.map +1 -0
- package/dist/languages/python-ast/types.d.ts +216 -0
- package/dist/languages/python-ast/types.d.ts.map +1 -0
- package/dist/languages/python-ast/types.js +6 -0
- package/dist/languages/python-ast/types.js.map +1 -0
- package/dist/languages/python.d.ts +55 -0
- package/dist/languages/python.d.ts.map +1 -0
- package/dist/languages/python.js +311 -0
- package/dist/languages/python.js.map +1 -0
- package/dist/languages/typescript.d.ts +272 -0
- package/dist/languages/typescript.d.ts.map +1 -0
- package/dist/languages/typescript.js +1381 -0
- package/dist/languages/typescript.js.map +1 -0
- package/dist/patterns/base.d.ts +146 -0
- package/dist/patterns/base.d.ts.map +1 -0
- package/dist/patterns/base.js +89 -0
- package/dist/patterns/base.js.map +1 -0
- package/dist/patterns/errors.d.ts +172 -0
- package/dist/patterns/errors.d.ts.map +1 -0
- package/dist/patterns/errors.js +185 -0
- package/dist/patterns/errors.js.map +1 -0
- package/dist/patterns/extractors.d.ts +170 -0
- package/dist/patterns/extractors.d.ts.map +1 -0
- package/dist/patterns/extractors.js +305 -0
- package/dist/patterns/extractors.js.map +1 -0
- package/dist/patterns/graphql/apollo-client.d.ts +80 -0
- package/dist/patterns/graphql/apollo-client.d.ts.map +1 -0
- package/dist/patterns/graphql/apollo-client.js +800 -0
- package/dist/patterns/graphql/apollo-client.js.map +1 -0
- package/dist/patterns/graphql/apollo-server.d.ts +55 -0
- package/dist/patterns/graphql/apollo-server.d.ts.map +1 -0
- package/dist/patterns/graphql/apollo-server.js +523 -0
- package/dist/patterns/graphql/apollo-server.js.map +1 -0
- package/dist/patterns/graphql/index.d.ts +11 -0
- package/dist/patterns/graphql/index.d.ts.map +1 -0
- package/dist/patterns/graphql/index.js +12 -0
- package/dist/patterns/graphql/index.js.map +1 -0
- package/dist/patterns/graphql/types.d.ts +213 -0
- package/dist/patterns/graphql/types.d.ts.map +1 -0
- package/dist/patterns/graphql/types.js +16 -0
- package/dist/patterns/graphql/types.js.map +1 -0
- package/dist/patterns/http-clients/axios.d.ts +148 -0
- package/dist/patterns/http-clients/axios.d.ts.map +1 -0
- package/dist/patterns/http-clients/axios.js +652 -0
- package/dist/patterns/http-clients/axios.js.map +1 -0
- package/dist/patterns/http-clients/fetch.d.ts +88 -0
- package/dist/patterns/http-clients/fetch.d.ts.map +1 -0
- package/dist/patterns/http-clients/fetch.js +364 -0
- package/dist/patterns/http-clients/fetch.js.map +1 -0
- package/dist/patterns/http-clients/index.d.ts +36 -0
- package/dist/patterns/http-clients/index.d.ts.map +1 -0
- package/dist/patterns/http-clients/index.js +50 -0
- package/dist/patterns/http-clients/index.js.map +1 -0
- package/dist/patterns/http-clients/property-access.d.ts +46 -0
- package/dist/patterns/http-clients/property-access.d.ts.map +1 -0
- package/dist/patterns/http-clients/property-access.js +818 -0
- package/dist/patterns/http-clients/property-access.js.map +1 -0
- package/dist/patterns/http-clients/type-inference.d.ts +48 -0
- package/dist/patterns/http-clients/type-inference.d.ts.map +1 -0
- package/dist/patterns/http-clients/type-inference.js +293 -0
- package/dist/patterns/http-clients/type-inference.js.map +1 -0
- package/dist/patterns/http-clients/types.d.ts +168 -0
- package/dist/patterns/http-clients/types.d.ts.map +1 -0
- package/dist/patterns/http-clients/types.js +10 -0
- package/dist/patterns/http-clients/types.js.map +1 -0
- package/dist/patterns/http-clients/url-extractor.d.ts +53 -0
- package/dist/patterns/http-clients/url-extractor.d.ts.map +1 -0
- package/dist/patterns/http-clients/url-extractor.js +338 -0
- package/dist/patterns/http-clients/url-extractor.js.map +1 -0
- package/dist/patterns/index.d.ts +44 -0
- package/dist/patterns/index.d.ts.map +1 -0
- package/dist/patterns/index.js +49 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/patterns/python/aiohttp.d.ts +21 -0
- package/dist/patterns/python/aiohttp.d.ts.map +1 -0
- package/dist/patterns/python/aiohttp.js +188 -0
- package/dist/patterns/python/aiohttp.js.map +1 -0
- package/dist/patterns/python/httpx.d.ts +20 -0
- package/dist/patterns/python/httpx.d.ts.map +1 -0
- package/dist/patterns/python/httpx.js +183 -0
- package/dist/patterns/python/httpx.js.map +1 -0
- package/dist/patterns/python/index.d.ts +32 -0
- package/dist/patterns/python/index.d.ts.map +1 -0
- package/dist/patterns/python/index.js +63 -0
- package/dist/patterns/python/index.js.map +1 -0
- package/dist/patterns/python/property-access.d.ts +27 -0
- package/dist/patterns/python/property-access.d.ts.map +1 -0
- package/dist/patterns/python/property-access.js +132 -0
- package/dist/patterns/python/property-access.js.map +1 -0
- package/dist/patterns/python/requests.d.ts +19 -0
- package/dist/patterns/python/requests.d.ts.map +1 -0
- package/dist/patterns/python/requests.js +239 -0
- package/dist/patterns/python/requests.js.map +1 -0
- package/dist/patterns/python/types.d.ts +95 -0
- package/dist/patterns/python/types.d.ts.map +1 -0
- package/dist/patterns/python/types.js +43 -0
- package/dist/patterns/python/types.js.map +1 -0
- package/dist/patterns/registry.d.ts +181 -0
- package/dist/patterns/registry.d.ts.map +1 -0
- package/dist/patterns/registry.js +304 -0
- package/dist/patterns/registry.js.map +1 -0
- package/dist/patterns/rest/express.d.ts +78 -0
- package/dist/patterns/rest/express.d.ts.map +1 -0
- package/dist/patterns/rest/express.js +289 -0
- package/dist/patterns/rest/express.js.map +1 -0
- package/dist/patterns/rest/fastify.d.ts +93 -0
- package/dist/patterns/rest/fastify.d.ts.map +1 -0
- package/dist/patterns/rest/fastify.js +420 -0
- package/dist/patterns/rest/fastify.js.map +1 -0
- package/dist/patterns/rest/index.d.ts +31 -0
- package/dist/patterns/rest/index.d.ts.map +1 -0
- package/dist/patterns/rest/index.js +45 -0
- package/dist/patterns/rest/index.js.map +1 -0
- package/dist/patterns/rest/middleware.d.ts +25 -0
- package/dist/patterns/rest/middleware.d.ts.map +1 -0
- package/dist/patterns/rest/middleware.js +219 -0
- package/dist/patterns/rest/middleware.js.map +1 -0
- package/dist/patterns/rest/path-parser.d.ts +50 -0
- package/dist/patterns/rest/path-parser.d.ts.map +1 -0
- package/dist/patterns/rest/path-parser.js +137 -0
- package/dist/patterns/rest/path-parser.js.map +1 -0
- package/dist/patterns/rest/response-inference.d.ts +44 -0
- package/dist/patterns/rest/response-inference.d.ts.map +1 -0
- package/dist/patterns/rest/response-inference.js +218 -0
- package/dist/patterns/rest/response-inference.js.map +1 -0
- package/dist/patterns/rest/types.d.ts +102 -0
- package/dist/patterns/rest/types.d.ts.map +1 -0
- package/dist/patterns/rest/types.js +10 -0
- package/dist/patterns/rest/types.js.map +1 -0
- package/dist/patterns/types.d.ts +105 -0
- package/dist/patterns/types.d.ts.map +1 -0
- package/dist/patterns/types.js +11 -0
- package/dist/patterns/types.js.map +1 -0
- package/dist/report/index.d.ts +11 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +55 -0
- package/dist/report/index.js.map +1 -0
- package/dist/tools/contract-comments.d.ts +48 -0
- package/dist/tools/contract-comments.d.ts.map +1 -0
- package/dist/tools/contract-comments.js +130 -0
- package/dist/tools/contract-comments.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/scaffold.d.ts +38 -0
- package/dist/tools/scaffold.d.ts.map +1 -0
- package/dist/tools/scaffold.js +373 -0
- package/dist/tools/scaffold.js.map +1 -0
- package/dist/trace/index.d.ts +28 -0
- package/dist/trace/index.d.ts.map +1 -0
- package/dist/trace/index.js +45 -0
- package/dist/trace/index.js.map +1 -0
- package/dist/types.d.ts +135 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -0
- package/dist/watch/cache.d.ts +41 -0
- package/dist/watch/cache.d.ts.map +1 -0
- package/dist/watch/cache.js +230 -0
- package/dist/watch/cache.js.map +1 -0
- package/dist/watch/index.d.ts +9 -0
- package/dist/watch/index.d.ts.map +1 -0
- package/dist/watch/index.js +7 -0
- package/dist/watch/index.js.map +1 -0
- package/dist/watch/project.d.ts +128 -0
- package/dist/watch/project.d.ts.map +1 -0
- package/dist/watch/project.js +152 -0
- package/dist/watch/project.js.map +1 -0
- package/dist/watch/watcher.d.ts +76 -0
- package/dist/watch/watcher.d.ts.map +1 -0
- package/dist/watch/watcher.js +235 -0
- package/dist/watch/watcher.js.map +1 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,1662 @@
|
|
|
1
|
+
# mnehmos.trace.mcp
|
|
2
|
+
|
|
3
|
+
> Static analysis engine for detecting schema mismatches between data producers and consumers.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
Trace MCP finds mismatches between:
|
|
8
|
+
|
|
9
|
+
- Backend API responses and frontend expectations
|
|
10
|
+
- MCP tool outputs and client code that uses them
|
|
11
|
+
- Service A's events and Service B's handlers
|
|
12
|
+
- REST endpoints and HTTP client calls
|
|
13
|
+
- GraphQL schemas and Apollo Client hooks
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Producer returns: { characterClass: "Fighter", hitPoints: 45 }
|
|
17
|
+
Consumer expects: { class: "Fighter", hp: 45 }
|
|
18
|
+
Result: ❌ Mismatch detected before runtime
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
### Core Capabilities
|
|
24
|
+
|
|
25
|
+
| Feature | Description |
|
|
26
|
+
|---------|-------------|
|
|
27
|
+
| **Schema Extraction** | Extract schemas from MCP tools, OpenAPI, TypeScript, tRPC, REST endpoints, GraphQL |
|
|
28
|
+
| **Usage Tracing** | Track how client code consumes schemas via property access patterns |
|
|
29
|
+
| **Mismatch Detection** | Compare producer schemas against consumer expectations |
|
|
30
|
+
| **Code Generation** | Scaffold consumer code from producer schemas (and vice versa) |
|
|
31
|
+
| **Watch Mode** | Continuous validation on file changes |
|
|
32
|
+
|
|
33
|
+
### Phase 2 Capabilities
|
|
34
|
+
|
|
35
|
+
| Feature | Description |
|
|
36
|
+
|---------|-------------|
|
|
37
|
+
| **Pattern Matcher** | Extensible pattern detection supporting call, decorator, property, export, and chain patterns |
|
|
38
|
+
| **Import Resolution** | Cross-file type resolution with import graph building and circular dependency handling |
|
|
39
|
+
| **REST Detection** | Express and Fastify endpoint extraction with validation middleware support |
|
|
40
|
+
| **HTTP Client Tracing** | fetch() and axios call detection with URL extraction and type inference |
|
|
41
|
+
| **GraphQL Support** | SDL schema parsing, Apollo Server resolvers, and Apollo Client hook tracing |
|
|
42
|
+
|
|
43
|
+
### Phase 3 Capabilities
|
|
44
|
+
|
|
45
|
+
| Feature | Description |
|
|
46
|
+
|---------|-------------|
|
|
47
|
+
| **Python AST Parser** | FastAPI, Flask, and MCP tool extraction with Pydantic model support |
|
|
48
|
+
| **Go Language Parser** | Struct/interface extraction with Chi, Gin, and stdlib HTTP handler detection |
|
|
49
|
+
| **gRPC/Protobuf Support** | Proto3 parsing with message, enum, service, and streaming RPC extraction |
|
|
50
|
+
| **Python HTTP Clients** | requests, httpx, and aiohttp library detection with response property tracing |
|
|
51
|
+
|
|
52
|
+
### Test Coverage
|
|
53
|
+
|
|
54
|
+
**1047 tests passing** across 16 test suites:
|
|
55
|
+
|
|
56
|
+
| Test Suite | Tests |
|
|
57
|
+
|------------|-------|
|
|
58
|
+
| Pattern Matcher | 85 |
|
|
59
|
+
| REST Detection | 87 |
|
|
60
|
+
| HTTP Client Tracing | 90 |
|
|
61
|
+
| GraphQL Support | 109 |
|
|
62
|
+
| Import Resolution | 56 |
|
|
63
|
+
| Core (adapters, OpenAPI, tRPC) | 234 |
|
|
64
|
+
| Python AST | 121 |
|
|
65
|
+
| gRPC/Protobuf | 124 |
|
|
66
|
+
| Go Parser | 106 |
|
|
67
|
+
| Python HTTP Clients | 35 |
|
|
68
|
+
|
|
69
|
+
## Installation
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Clone the repository
|
|
73
|
+
git clone https://github.com/Mnehmos/mnehmos.trace.mcp.git
|
|
74
|
+
|
|
75
|
+
# Navigate to the directory
|
|
76
|
+
cd mnehmos.trace.mcp
|
|
77
|
+
|
|
78
|
+
# Install dependencies
|
|
79
|
+
npm install
|
|
80
|
+
|
|
81
|
+
# Build the project
|
|
82
|
+
npm run build
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Configuration
|
|
86
|
+
|
|
87
|
+
Add to your MCP client configuration (e.g., `claude_desktop_config.json` or Roo-Code settings):
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"mcpServers": {
|
|
92
|
+
"trace-mcp": {
|
|
93
|
+
"command": "node",
|
|
94
|
+
"args": ["/path/to/trace-mcp/dist/index.js"],
|
|
95
|
+
"env": {}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Supported Formats
|
|
102
|
+
|
|
103
|
+
Trace MCP supports schema extraction and comparison across multiple specification formats through a pluggable adapter registry.
|
|
104
|
+
|
|
105
|
+
### Summary of Supported Frameworks
|
|
106
|
+
|
|
107
|
+
| Category | Frameworks |
|
|
108
|
+
|----------|------------|
|
|
109
|
+
| **API Specs** | OpenAPI 3.0+, Swagger |
|
|
110
|
+
| **RPC** | MCP (Zod), tRPC, gRPC/Protobuf |
|
|
111
|
+
| **REST Servers** | Express, Fastify, FastAPI, Flask, Chi, Gin, Go stdlib |
|
|
112
|
+
| **HTTP Clients** | fetch(), axios, requests, httpx, aiohttp |
|
|
113
|
+
| **GraphQL** | SDL schemas, Apollo Server, Apollo Client |
|
|
114
|
+
| **Type Systems** | TypeScript interfaces, Zod schemas, Pydantic models, Go structs |
|
|
115
|
+
|
|
116
|
+
### Supported Languages
|
|
117
|
+
|
|
118
|
+
| Language | Producer Detection | Consumer Tracing |
|
|
119
|
+
|----------|-------------------|------------------|
|
|
120
|
+
| **TypeScript** | MCP tools, tRPC, Express, Fastify, GraphQL resolvers | callTool(), fetch, axios, Apollo Client |
|
|
121
|
+
| **Python** | FastAPI, Flask, MCP tools, Pydantic models | requests, httpx, aiohttp |
|
|
122
|
+
| **Go** | Chi, Gin, stdlib handlers, structs, interfaces | — |
|
|
123
|
+
| **Protobuf** | Messages, enums, services, streaming RPCs | — |
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### MCP Server Schemas (Zod)
|
|
128
|
+
|
|
129
|
+
Extract MCP tool definitions from server source code using Zod schemas.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
server.tool(
|
|
133
|
+
"get_character",
|
|
134
|
+
"Fetch character data",
|
|
135
|
+
{
|
|
136
|
+
characterId: z.string().describe("Character ID"),
|
|
137
|
+
},
|
|
138
|
+
async (args) => {
|
|
139
|
+
// implementation
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Schema ID Format**: `endpoint:GET:/tools/get_character@./server.ts`
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### OpenAPI / Swagger Specifications
|
|
149
|
+
|
|
150
|
+
Extract schemas from OpenAPI 3.0+ specifications, supporting endpoints, request bodies, responses, and component schemas.
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
openapi: 3.0.0
|
|
154
|
+
info:
|
|
155
|
+
title: Character API
|
|
156
|
+
version: 1.0.0
|
|
157
|
+
paths:
|
|
158
|
+
/characters/{id}:
|
|
159
|
+
get:
|
|
160
|
+
parameters:
|
|
161
|
+
- name: id
|
|
162
|
+
in: path
|
|
163
|
+
schema:
|
|
164
|
+
type: string
|
|
165
|
+
responses:
|
|
166
|
+
'200':
|
|
167
|
+
content:
|
|
168
|
+
application/json:
|
|
169
|
+
schema:
|
|
170
|
+
$ref: '#/components/schemas/Character'
|
|
171
|
+
components:
|
|
172
|
+
schemas:
|
|
173
|
+
Character:
|
|
174
|
+
type: object
|
|
175
|
+
properties:
|
|
176
|
+
id:
|
|
177
|
+
type: string
|
|
178
|
+
name:
|
|
179
|
+
type: string
|
|
180
|
+
class:
|
|
181
|
+
type: string
|
|
182
|
+
required:
|
|
183
|
+
- id
|
|
184
|
+
- name
|
|
185
|
+
- class
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Schema ID Format**: `endpoint:GET:/characters/{id}@./api.yaml`
|
|
189
|
+
|
|
190
|
+
**Usage Example:**
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
const result = await client.callTool("extract_schemas", {
|
|
194
|
+
rootDir: "./backend",
|
|
195
|
+
include: ["**/*.openapi.yaml", "**/*.swagger.json"],
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
### TypeScript Interfaces & Types
|
|
202
|
+
|
|
203
|
+
Extract exported interfaces, type aliases, and enums from TypeScript source files. Supports utility types including `Pick`, `Omit`, `Partial`, `Required`, and `Record`.
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
export interface Character {
|
|
207
|
+
id: string;
|
|
208
|
+
name: string;
|
|
209
|
+
class: "Fighter" | "Wizard" | "Rogue";
|
|
210
|
+
hitPoints: number;
|
|
211
|
+
stats: {
|
|
212
|
+
strength: number;
|
|
213
|
+
dexterity: number;
|
|
214
|
+
constitution: number;
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export type ReadonlyCharacter = Readonly<Character>;
|
|
219
|
+
|
|
220
|
+
export enum CharacterClass {
|
|
221
|
+
Fighter = "Fighter",
|
|
222
|
+
Wizard = "Wizard",
|
|
223
|
+
Rogue = "Rogue",
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Schema ID Format**: `interface:Character@./types.ts`
|
|
228
|
+
|
|
229
|
+
**Supported Utility Types:**
|
|
230
|
+
- `Pick<T, K>` - Select properties from interface
|
|
231
|
+
- `Omit<T, K>` - Exclude properties from interface
|
|
232
|
+
- `Partial<T>` - Make all properties optional
|
|
233
|
+
- `Required<T>` - Make all properties required
|
|
234
|
+
- `Record<K, T>` - Object with specific keys and value type
|
|
235
|
+
|
|
236
|
+
**Usage Example:**
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
const result = await client.callTool("extract_schemas", {
|
|
240
|
+
rootDir: "./shared",
|
|
241
|
+
include: ["**/*.ts", "**/*.tsx"],
|
|
242
|
+
});
|
|
243
|
+
// Returns interfaces with ID format: interface:CharacterClass@./types.ts
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### tRPC Routers
|
|
249
|
+
|
|
250
|
+
Extract procedure schemas from tRPC routers, including input/output types, query, mutation, and subscription handlers. Handles nested routers and middleware.
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { z } from "zod";
|
|
254
|
+
import { publicProcedure, router } from "./trpc";
|
|
255
|
+
|
|
256
|
+
export const appRouter = router({
|
|
257
|
+
users: router({
|
|
258
|
+
getById: publicProcedure
|
|
259
|
+
.input(z.string())
|
|
260
|
+
.output(z.object({
|
|
261
|
+
id: z.string(),
|
|
262
|
+
name: z.string(),
|
|
263
|
+
email: z.string().email(),
|
|
264
|
+
}))
|
|
265
|
+
.query(async ({ input }) => {
|
|
266
|
+
// implementation
|
|
267
|
+
}),
|
|
268
|
+
|
|
269
|
+
create: publicProcedure
|
|
270
|
+
.input(z.object({
|
|
271
|
+
name: z.string(),
|
|
272
|
+
email: z.string().email(),
|
|
273
|
+
}))
|
|
274
|
+
.output(z.object({
|
|
275
|
+
id: z.string(),
|
|
276
|
+
name: z.string(),
|
|
277
|
+
email: z.string(),
|
|
278
|
+
}))
|
|
279
|
+
.mutation(async ({ input }) => {
|
|
280
|
+
// implementation
|
|
281
|
+
}),
|
|
282
|
+
|
|
283
|
+
onChange: publicProcedure
|
|
284
|
+
.output(z.object({
|
|
285
|
+
userId: z.string(),
|
|
286
|
+
action: z.enum(["created", "updated", "deleted"]),
|
|
287
|
+
}))
|
|
288
|
+
.subscription(async () => {
|
|
289
|
+
// implementation
|
|
290
|
+
}),
|
|
291
|
+
}),
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Schema ID Format**: `trpc:users.getById@./router.ts`
|
|
296
|
+
|
|
297
|
+
**Detected Elements:**
|
|
298
|
+
- Router definitions (`router({ ... })`)
|
|
299
|
+
- Nested routers (`users: router({ ... })`)
|
|
300
|
+
- Procedures (`.query()`, `.mutation()`, `.subscription()`)
|
|
301
|
+
- Input schemas (`.input(zod_schema)`)
|
|
302
|
+
- Output schemas (`.output(zod_schema)`)
|
|
303
|
+
|
|
304
|
+
**Usage Example:**
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
const result = await client.callTool("extract_schemas", {
|
|
308
|
+
rootDir: "./backend/trpc",
|
|
309
|
+
include: ["**/*.router.ts"],
|
|
310
|
+
});
|
|
311
|
+
// Returns procedures with ID format: trpc:users.getById@./router.ts
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
### REST Endpoints (Express & Fastify)
|
|
317
|
+
|
|
318
|
+
Extract endpoint schemas from Express and Fastify applications, including route parameters, request bodies, response types, and validation middleware.
|
|
319
|
+
|
|
320
|
+
#### Express
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
import express from "express";
|
|
324
|
+
import { z } from "zod";
|
|
325
|
+
|
|
326
|
+
const app = express();
|
|
327
|
+
|
|
328
|
+
// Basic route with typed response
|
|
329
|
+
app.get("/users/:id", (req, res) => {
|
|
330
|
+
const user: User = getUserById(req.params.id);
|
|
331
|
+
res.json(user);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Route with Zod validation middleware
|
|
335
|
+
app.post("/users",
|
|
336
|
+
validate(z.object({
|
|
337
|
+
name: z.string(),
|
|
338
|
+
email: z.string().email(),
|
|
339
|
+
})),
|
|
340
|
+
(req, res) => {
|
|
341
|
+
res.status(201).json({ id: "123", ...req.body });
|
|
342
|
+
}
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
// Router-based routes
|
|
346
|
+
const router = express.Router();
|
|
347
|
+
router.get("/health", (req, res) => res.json({ status: "ok" }));
|
|
348
|
+
app.use("/api", router);
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**Schema ID Format**: `rest:GET:/users/:id@./app.ts`
|
|
352
|
+
|
|
353
|
+
#### Fastify
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
import Fastify from "fastify";
|
|
357
|
+
|
|
358
|
+
const fastify = Fastify();
|
|
359
|
+
|
|
360
|
+
// Route with JSON Schema validation
|
|
361
|
+
fastify.post("/users", {
|
|
362
|
+
schema: {
|
|
363
|
+
body: {
|
|
364
|
+
type: "object",
|
|
365
|
+
properties: {
|
|
366
|
+
name: { type: "string" },
|
|
367
|
+
email: { type: "string", format: "email" },
|
|
368
|
+
},
|
|
369
|
+
required: ["name", "email"],
|
|
370
|
+
},
|
|
371
|
+
response: {
|
|
372
|
+
201: {
|
|
373
|
+
type: "object",
|
|
374
|
+
properties: {
|
|
375
|
+
id: { type: "string" },
|
|
376
|
+
name: { type: "string" },
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
}, async (request, reply) => {
|
|
382
|
+
return { id: "123", name: request.body.name };
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// Shorthand methods
|
|
386
|
+
fastify.get("/health", async () => ({ status: "ok" }));
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
**Schema ID Format**: `rest:POST:/users@./server.ts`
|
|
390
|
+
|
|
391
|
+
**Detected Elements:**
|
|
392
|
+
- HTTP methods: GET, POST, PUT, PATCH, DELETE
|
|
393
|
+
- Path parameters (`:id`, `:userId`)
|
|
394
|
+
- Request body schemas (Zod, Joi, celebrate, JSON Schema)
|
|
395
|
+
- Response type inference
|
|
396
|
+
- Router prefixes and mounting
|
|
397
|
+
|
|
398
|
+
**Usage Example:**
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
const result = await client.callTool("extract_schemas", {
|
|
402
|
+
rootDir: "./backend",
|
|
403
|
+
include: ["**/*.ts"],
|
|
404
|
+
});
|
|
405
|
+
// Returns endpoints with ID format: rest:GET:/users/:id@./routes.ts
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
### HTTP Clients (fetch & axios)
|
|
411
|
+
|
|
412
|
+
Trace HTTP client calls to detect consumer expectations for API responses.
|
|
413
|
+
|
|
414
|
+
#### fetch() API
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
// Basic fetch with type assertion
|
|
418
|
+
const response = await fetch("/api/users");
|
|
419
|
+
const users: User[] = await response.json();
|
|
420
|
+
|
|
421
|
+
// fetch with request options
|
|
422
|
+
const newUser = await fetch("/api/users", {
|
|
423
|
+
method: "POST",
|
|
424
|
+
headers: { "Content-Type": "application/json" },
|
|
425
|
+
body: JSON.stringify({ name: "Alice" }),
|
|
426
|
+
}).then(res => res.json()) as CreateUserResponse;
|
|
427
|
+
|
|
428
|
+
// Template literal URLs
|
|
429
|
+
const userId = "123";
|
|
430
|
+
const user = await fetch(`/api/users/${userId}`).then(r => r.json());
|
|
431
|
+
|
|
432
|
+
// Property access tracking
|
|
433
|
+
console.log(user.name, user.email, user.profile.avatar);
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**Detected Elements:**
|
|
437
|
+
- URL extraction (static strings, template literals, variables)
|
|
438
|
+
- HTTP method detection
|
|
439
|
+
- Type assertions and generics
|
|
440
|
+
- Property access patterns on response data
|
|
441
|
+
|
|
442
|
+
#### axios
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
import axios from "axios";
|
|
446
|
+
|
|
447
|
+
// Basic GET request
|
|
448
|
+
const { data: users } = await axios.get<User[]>("/api/users");
|
|
449
|
+
|
|
450
|
+
// POST with typed response
|
|
451
|
+
const response = await axios.post<CreateUserResponse>("/api/users", {
|
|
452
|
+
name: "Bob",
|
|
453
|
+
email: "bob@example.com",
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// Instance with base URL
|
|
457
|
+
const api = axios.create({ baseURL: "https://api.example.com" });
|
|
458
|
+
const profile = await api.get<Profile>("/me");
|
|
459
|
+
|
|
460
|
+
// Destructured property access
|
|
461
|
+
const { name, email } = response.data;
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**Schema ID Format**: `http-client:GET:/api/users@./client.ts`
|
|
465
|
+
|
|
466
|
+
**Detected Elements:**
|
|
467
|
+
- axios methods: `.get()`, `.post()`, `.put()`, `.patch()`, `.delete()`
|
|
468
|
+
- Generic type parameters (`axios.get<User>`)
|
|
469
|
+
- Instance creation with `axios.create()`
|
|
470
|
+
- Base URL resolution
|
|
471
|
+
- Response data property access
|
|
472
|
+
|
|
473
|
+
**Usage Example:**
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
const result = await client.callTool("trace_usage", {
|
|
477
|
+
rootDir: "./frontend/src",
|
|
478
|
+
include: ["**/*.ts", "**/*.tsx"],
|
|
479
|
+
});
|
|
480
|
+
// Returns HTTP client calls with ID format: http-client:GET:/api/users@./api.ts
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
### GraphQL (SDL & Apollo)
|
|
486
|
+
|
|
487
|
+
Extract schemas from GraphQL SDL files and trace Apollo Server resolvers and Apollo Client hooks.
|
|
488
|
+
|
|
489
|
+
#### SDL Schema Files
|
|
490
|
+
|
|
491
|
+
```graphql
|
|
492
|
+
# schema.graphql
|
|
493
|
+
type User {
|
|
494
|
+
id: ID!
|
|
495
|
+
name: String!
|
|
496
|
+
email: String!
|
|
497
|
+
posts: [Post!]!
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
type Post {
|
|
501
|
+
id: ID!
|
|
502
|
+
title: String!
|
|
503
|
+
content: String!
|
|
504
|
+
author: User!
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
type Query {
|
|
508
|
+
user(id: ID!): User
|
|
509
|
+
users: [User!]!
|
|
510
|
+
post(id: ID!): Post
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
type Mutation {
|
|
514
|
+
createUser(name: String!, email: String!): User!
|
|
515
|
+
createPost(title: String!, content: String!, authorId: ID!): Post!
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
**Schema ID Format**: `graphql:Query.user@./schema.graphql`
|
|
520
|
+
|
|
521
|
+
#### Apollo Server Resolvers
|
|
522
|
+
|
|
523
|
+
```typescript
|
|
524
|
+
import { ApolloServer } from "@apollo/server";
|
|
525
|
+
|
|
526
|
+
const resolvers = {
|
|
527
|
+
Query: {
|
|
528
|
+
user: async (_, { id }) => {
|
|
529
|
+
return db.users.findById(id);
|
|
530
|
+
},
|
|
531
|
+
users: async () => {
|
|
532
|
+
return db.users.findAll();
|
|
533
|
+
},
|
|
534
|
+
},
|
|
535
|
+
Mutation: {
|
|
536
|
+
createUser: async (_, { name, email }) => {
|
|
537
|
+
return db.users.create({ name, email });
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
User: {
|
|
541
|
+
posts: async (parent) => {
|
|
542
|
+
return db.posts.findByAuthor(parent.id);
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
const server = new ApolloServer({ typeDefs, resolvers });
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
**Schema ID Format**: `graphql-resolver:Query.user@./resolvers.ts`
|
|
551
|
+
|
|
552
|
+
#### Apollo Client Hooks
|
|
553
|
+
|
|
554
|
+
```typescript
|
|
555
|
+
import { useQuery, useMutation, gql } from "@apollo/client";
|
|
556
|
+
|
|
557
|
+
const GET_USER = gql`
|
|
558
|
+
query GetUser($id: ID!) {
|
|
559
|
+
user(id: $id) {
|
|
560
|
+
id
|
|
561
|
+
name
|
|
562
|
+
email
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
`;
|
|
566
|
+
|
|
567
|
+
const CREATE_USER = gql`
|
|
568
|
+
mutation CreateUser($name: String!, $email: String!) {
|
|
569
|
+
createUser(name: $name, email: $email) {
|
|
570
|
+
id
|
|
571
|
+
name
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
`;
|
|
575
|
+
|
|
576
|
+
function UserProfile({ userId }: { userId: string }) {
|
|
577
|
+
const { data, loading, error } = useQuery(GET_USER, {
|
|
578
|
+
variables: { id: userId },
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
const [createUser] = useMutation(CREATE_USER);
|
|
582
|
+
|
|
583
|
+
if (loading) return <Spinner />;
|
|
584
|
+
if (error) return <Error message={error.message} />;
|
|
585
|
+
|
|
586
|
+
return <div>{data.user.name}</div>;
|
|
587
|
+
}
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
**Schema ID Format**: `graphql-client:GetUser@./UserProfile.tsx`
|
|
591
|
+
|
|
592
|
+
**Detected Elements:**
|
|
593
|
+
- SDL types: scalar, object, input, enum, interface, union
|
|
594
|
+
- Query and Mutation definitions
|
|
595
|
+
- Field arguments and return types
|
|
596
|
+
- Apollo Client hooks: `useQuery`, `useMutation`, `useLazyQuery`, `useSubscription`
|
|
597
|
+
- Operation names and variables
|
|
598
|
+
- Selected fields in queries
|
|
599
|
+
|
|
600
|
+
**Usage Example:**
|
|
601
|
+
|
|
602
|
+
```typescript
|
|
603
|
+
// Extract GraphQL schemas
|
|
604
|
+
const schemas = await client.callTool("extract_schemas", {
|
|
605
|
+
rootDir: "./backend",
|
|
606
|
+
include: ["**/*.graphql", "**/resolvers.ts"],
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
// Trace Apollo Client usage
|
|
610
|
+
const usage = await client.callTool("trace_usage", {
|
|
611
|
+
rootDir: "./frontend/src",
|
|
612
|
+
include: ["**/*.tsx"],
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
// Compare for mismatches
|
|
616
|
+
const report = await client.callTool("compare", {
|
|
617
|
+
producerDir: "./backend",
|
|
618
|
+
consumerDir: "./frontend/src",
|
|
619
|
+
format: "markdown",
|
|
620
|
+
});
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
---
|
|
624
|
+
|
|
625
|
+
### Python (FastAPI, Flask, MCP Tools)
|
|
626
|
+
|
|
627
|
+
Extract endpoint schemas from Python web frameworks and MCP tool definitions with full Pydantic model support.
|
|
628
|
+
|
|
629
|
+
#### FastAPI
|
|
630
|
+
|
|
631
|
+
```python
|
|
632
|
+
from fastapi import FastAPI, APIRouter
|
|
633
|
+
from pydantic import BaseModel
|
|
634
|
+
from typing import Optional, List
|
|
635
|
+
|
|
636
|
+
class Character(BaseModel):
|
|
637
|
+
id: str
|
|
638
|
+
name: str
|
|
639
|
+
character_class: str
|
|
640
|
+
level: int = 1
|
|
641
|
+
skills: List[str] = []
|
|
642
|
+
|
|
643
|
+
class CreateCharacterRequest(BaseModel):
|
|
644
|
+
name: str
|
|
645
|
+
character_class: str
|
|
646
|
+
background: Optional[str] = None
|
|
647
|
+
|
|
648
|
+
app = FastAPI()
|
|
649
|
+
router = APIRouter(prefix="/api/v1")
|
|
650
|
+
|
|
651
|
+
@app.get("/characters/{character_id}")
|
|
652
|
+
async def get_character(character_id: str) -> Character:
|
|
653
|
+
return Character(id=character_id, name="Hero", character_class="Fighter")
|
|
654
|
+
|
|
655
|
+
@router.post("/characters")
|
|
656
|
+
async def create_character(request: CreateCharacterRequest) -> Character:
|
|
657
|
+
return Character(id="123", name=request.name, character_class=request.character_class)
|
|
658
|
+
|
|
659
|
+
app.include_router(router)
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
**Schema ID Format**: `python:GET:/characters/{character_id}@./main.py`
|
|
663
|
+
|
|
664
|
+
#### Flask
|
|
665
|
+
|
|
666
|
+
```python
|
|
667
|
+
from flask import Flask, Blueprint, request, jsonify
|
|
668
|
+
|
|
669
|
+
app = Flask(__name__)
|
|
670
|
+
api = Blueprint("api", __name__, url_prefix="/api")
|
|
671
|
+
|
|
672
|
+
@app.route("/health")
|
|
673
|
+
def health_check():
|
|
674
|
+
return jsonify({"status": "ok"})
|
|
675
|
+
|
|
676
|
+
@api.route("/users/<user_id>", methods=["GET"])
|
|
677
|
+
def get_user(user_id):
|
|
678
|
+
return jsonify({"id": user_id, "name": "Alice"})
|
|
679
|
+
|
|
680
|
+
@api.route("/users", methods=["POST"])
|
|
681
|
+
def create_user():
|
|
682
|
+
data = request.get_json()
|
|
683
|
+
return jsonify({"id": "123", **data}), 201
|
|
684
|
+
|
|
685
|
+
app.register_blueprint(api)
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
**Schema ID Format**: `python:GET:/api/users/<user_id>@./app.py`
|
|
689
|
+
|
|
690
|
+
#### MCP Tools (Python)
|
|
691
|
+
|
|
692
|
+
```python
|
|
693
|
+
from mcp import Server
|
|
694
|
+
|
|
695
|
+
server = Server("character-tools")
|
|
696
|
+
|
|
697
|
+
@server.tool()
|
|
698
|
+
async def get_character(character_id: str) -> dict:
|
|
699
|
+
"""Fetch character data by ID."""
|
|
700
|
+
return {"id": character_id, "name": "Hero", "class": "Fighter"}
|
|
701
|
+
|
|
702
|
+
@mcp.tool()
|
|
703
|
+
def roll_dice(dice: str, modifier: int = 0) -> dict:
|
|
704
|
+
"""Roll dice with optional modifier."""
|
|
705
|
+
return {"result": 15, "expression": dice, "modifier": modifier}
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
**Schema ID Format**: `python-mcp:get_character@./tools.py`
|
|
709
|
+
|
|
710
|
+
#### Pydantic Models
|
|
711
|
+
|
|
712
|
+
```python
|
|
713
|
+
from pydantic import BaseModel, Field
|
|
714
|
+
from typing import Optional, List, Dict, Union, Literal
|
|
715
|
+
from enum import Enum
|
|
716
|
+
|
|
717
|
+
class CharacterClass(str, Enum):
|
|
718
|
+
FIGHTER = "Fighter"
|
|
719
|
+
WIZARD = "Wizard"
|
|
720
|
+
ROGUE = "Rogue"
|
|
721
|
+
|
|
722
|
+
class Stats(BaseModel):
|
|
723
|
+
strength: int = Field(ge=1, le=20)
|
|
724
|
+
dexterity: int = Field(ge=1, le=20)
|
|
725
|
+
constitution: int = Field(ge=1, le=20)
|
|
726
|
+
|
|
727
|
+
class Character(BaseModel):
|
|
728
|
+
id: str
|
|
729
|
+
name: str
|
|
730
|
+
character_class: CharacterClass
|
|
731
|
+
level: int = Field(default=1, ge=1, le=20)
|
|
732
|
+
stats: Stats
|
|
733
|
+
equipment: List[str] = []
|
|
734
|
+
metadata: Optional[Dict[str, str]] = None
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
**Detected Elements:**
|
|
738
|
+
- Decorators: `@app.get()`, `@app.post()`, `@router.*`, `@app.route()`, `@blueprint.route()`
|
|
739
|
+
- MCP decorators: `@mcp.tool()`, `@server.tool()`
|
|
740
|
+
- Pydantic `BaseModel` classes with field extraction
|
|
741
|
+
- Type annotations: `Optional`, `Union`, `List`, `Dict`, `Literal`
|
|
742
|
+
- Enum types
|
|
743
|
+
|
|
744
|
+
**Usage Example:**
|
|
745
|
+
|
|
746
|
+
```typescript
|
|
747
|
+
const result = await client.callTool("extract_schemas", {
|
|
748
|
+
rootDir: "./backend",
|
|
749
|
+
include: ["**/*.py"],
|
|
750
|
+
});
|
|
751
|
+
// Returns endpoints with ID format: python:GET:/characters/{id}@./main.py
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
### Go Language (Chi, Gin, stdlib)
|
|
757
|
+
|
|
758
|
+
Extract struct definitions, interfaces, and HTTP endpoint schemas from Go source files.
|
|
759
|
+
|
|
760
|
+
#### Structs with JSON Tags
|
|
761
|
+
|
|
762
|
+
```go
|
|
763
|
+
package models
|
|
764
|
+
|
|
765
|
+
type Character struct {
|
|
766
|
+
ID string `json:"id"`
|
|
767
|
+
Name string `json:"name"`
|
|
768
|
+
Class string `json:"class"`
|
|
769
|
+
Level int `json:"level"`
|
|
770
|
+
HitPoints int `json:"hp"`
|
|
771
|
+
Skills []string `json:"skills,omitempty"`
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
type Stats struct {
|
|
775
|
+
Strength int `json:"str"`
|
|
776
|
+
Dexterity int `json:"dex"`
|
|
777
|
+
Constitution int `json:"con"`
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// Embedded struct
|
|
781
|
+
type CharacterWithStats struct {
|
|
782
|
+
Character
|
|
783
|
+
Stats Stats `json:"stats"`
|
|
784
|
+
}
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
**Schema ID Format**: `go-struct:Character@./models/character.go`
|
|
788
|
+
|
|
789
|
+
#### Interfaces
|
|
790
|
+
|
|
791
|
+
```go
|
|
792
|
+
package services
|
|
793
|
+
|
|
794
|
+
type CharacterService interface {
|
|
795
|
+
GetByID(id string) (*Character, error)
|
|
796
|
+
Create(req CreateRequest) (*Character, error)
|
|
797
|
+
Update(id string, req UpdateRequest) (*Character, error)
|
|
798
|
+
Delete(id string) error
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
type Repository interface {
|
|
802
|
+
Find(query Query) ([]Character, error)
|
|
803
|
+
Save(character *Character) error
|
|
804
|
+
}
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
**Schema ID Format**: `go-interface:CharacterService@./services/character.go`
|
|
808
|
+
|
|
809
|
+
#### stdlib HTTP Handlers
|
|
810
|
+
|
|
811
|
+
```go
|
|
812
|
+
package main
|
|
813
|
+
|
|
814
|
+
import (
|
|
815
|
+
"encoding/json"
|
|
816
|
+
"net/http"
|
|
817
|
+
)
|
|
818
|
+
|
|
819
|
+
func main() {
|
|
820
|
+
http.HandleFunc("/health", healthHandler)
|
|
821
|
+
http.HandleFunc("/api/characters", charactersHandler)
|
|
822
|
+
http.HandleFunc("/api/characters/", characterByIDHandler)
|
|
823
|
+
http.ListenAndServe(":8080", nil)
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
func healthHandler(w http.ResponseWriter, r *http.Request) {
|
|
827
|
+
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
func charactersHandler(w http.ResponseWriter, r *http.Request) {
|
|
831
|
+
switch r.Method {
|
|
832
|
+
case http.MethodGet:
|
|
833
|
+
// List characters
|
|
834
|
+
case http.MethodPost:
|
|
835
|
+
// Create character
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
**Schema ID Format**: `go-http:GET:/health@./main.go`
|
|
841
|
+
|
|
842
|
+
#### Chi Router
|
|
843
|
+
|
|
844
|
+
```go
|
|
845
|
+
package main
|
|
846
|
+
|
|
847
|
+
import (
|
|
848
|
+
"github.com/go-chi/chi/v5"
|
|
849
|
+
"net/http"
|
|
850
|
+
)
|
|
851
|
+
|
|
852
|
+
func main() {
|
|
853
|
+
r := chi.NewRouter()
|
|
854
|
+
|
|
855
|
+
r.Get("/health", healthHandler)
|
|
856
|
+
|
|
857
|
+
r.Route("/api/characters", func(r chi.Router) {
|
|
858
|
+
r.Get("/", listCharacters)
|
|
859
|
+
r.Post("/", createCharacter)
|
|
860
|
+
r.Get("/{id}", getCharacter) // Chi param: {id}
|
|
861
|
+
r.Put("/{id}", updateCharacter)
|
|
862
|
+
r.Delete("/{id}", deleteCharacter)
|
|
863
|
+
})
|
|
864
|
+
|
|
865
|
+
http.ListenAndServe(":8080", r)
|
|
866
|
+
}
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
**Schema ID Format**: `go-http:GET:/api/characters/{id}@./main.go`
|
|
870
|
+
|
|
871
|
+
#### Gin Framework
|
|
872
|
+
|
|
873
|
+
```go
|
|
874
|
+
package main
|
|
875
|
+
|
|
876
|
+
import "github.com/gin-gonic/gin"
|
|
877
|
+
|
|
878
|
+
func main() {
|
|
879
|
+
r := gin.Default()
|
|
880
|
+
|
|
881
|
+
r.GET("/health", healthHandler)
|
|
882
|
+
|
|
883
|
+
api := r.Group("/api")
|
|
884
|
+
{
|
|
885
|
+
api.GET("/characters", listCharacters)
|
|
886
|
+
api.POST("/characters", createCharacter)
|
|
887
|
+
api.GET("/characters/:id", getCharacter) // Gin param: :id
|
|
888
|
+
api.PUT("/characters/:id", updateCharacter)
|
|
889
|
+
api.DELETE("/characters/:id", deleteCharacter)
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
r.Run(":8080")
|
|
893
|
+
}
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
**Schema ID Format**: `go-http:GET:/api/characters/:id@./main.go`
|
|
897
|
+
|
|
898
|
+
**Detected Elements:**
|
|
899
|
+
- Struct definitions with JSON tags
|
|
900
|
+
- Embedded structs
|
|
901
|
+
- Interface definitions
|
|
902
|
+
- `http.HandleFunc()` patterns
|
|
903
|
+
- Chi router: `r.Get()`, `r.Post()`, `r.Route()`, `{param}` syntax
|
|
904
|
+
- Gin framework: `r.GET()`, `r.POST()`, `r.Group()`, `:param` syntax
|
|
905
|
+
|
|
906
|
+
**Usage Example:**
|
|
907
|
+
|
|
908
|
+
```typescript
|
|
909
|
+
const result = await client.callTool("extract_schemas", {
|
|
910
|
+
rootDir: "./backend",
|
|
911
|
+
include: ["**/*.go"],
|
|
912
|
+
});
|
|
913
|
+
// Returns structs, interfaces, and endpoints
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
---
|
|
917
|
+
|
|
918
|
+
### gRPC / Protobuf
|
|
919
|
+
|
|
920
|
+
Parse Protocol Buffer definitions (proto3) to extract message types, enums, services, and RPC methods.
|
|
921
|
+
|
|
922
|
+
#### Basic Messages
|
|
923
|
+
|
|
924
|
+
```protobuf
|
|
925
|
+
syntax = "proto3";
|
|
926
|
+
|
|
927
|
+
package character;
|
|
928
|
+
|
|
929
|
+
message Character {
|
|
930
|
+
string id = 1;
|
|
931
|
+
string name = 2;
|
|
932
|
+
CharacterClass character_class = 3;
|
|
933
|
+
int32 level = 4;
|
|
934
|
+
Stats stats = 5;
|
|
935
|
+
repeated string skills = 6;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
message Stats {
|
|
939
|
+
int32 strength = 1;
|
|
940
|
+
int32 dexterity = 2;
|
|
941
|
+
int32 constitution = 3;
|
|
942
|
+
}
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
**Schema ID Format**: `proto-message:character.Character@./character.proto`
|
|
946
|
+
|
|
947
|
+
#### Enums
|
|
948
|
+
|
|
949
|
+
```protobuf
|
|
950
|
+
enum CharacterClass {
|
|
951
|
+
CHARACTER_CLASS_UNSPECIFIED = 0;
|
|
952
|
+
CHARACTER_CLASS_FIGHTER = 1;
|
|
953
|
+
CHARACTER_CLASS_WIZARD = 2;
|
|
954
|
+
CHARACTER_CLASS_ROGUE = 3;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
enum DamageType {
|
|
958
|
+
DAMAGE_TYPE_UNSPECIFIED = 0;
|
|
959
|
+
DAMAGE_TYPE_SLASHING = 1;
|
|
960
|
+
DAMAGE_TYPE_PIERCING = 2;
|
|
961
|
+
DAMAGE_TYPE_FIRE = 3;
|
|
962
|
+
}
|
|
963
|
+
```
|
|
964
|
+
|
|
965
|
+
**Schema ID Format**: `proto-enum:character.CharacterClass@./character.proto`
|
|
966
|
+
|
|
967
|
+
#### Oneof and Map Fields
|
|
968
|
+
|
|
969
|
+
```protobuf
|
|
970
|
+
message Equipment {
|
|
971
|
+
string id = 1;
|
|
972
|
+
string name = 2;
|
|
973
|
+
|
|
974
|
+
oneof item_type {
|
|
975
|
+
Weapon weapon = 10;
|
|
976
|
+
Armor armor = 11;
|
|
977
|
+
Consumable consumable = 12;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
message Inventory {
|
|
982
|
+
string character_id = 1;
|
|
983
|
+
map<string, int32> item_counts = 2;
|
|
984
|
+
map<string, Equipment> equipped = 3;
|
|
985
|
+
}
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
**Schema ID Format**: `proto-message:character.Equipment@./equipment.proto`
|
|
989
|
+
|
|
990
|
+
#### Services and RPCs
|
|
991
|
+
|
|
992
|
+
```protobuf
|
|
993
|
+
service CharacterService {
|
|
994
|
+
// Unary RPC
|
|
995
|
+
rpc GetCharacter(GetCharacterRequest) returns (Character);
|
|
996
|
+
|
|
997
|
+
// Server streaming
|
|
998
|
+
rpc ListCharacters(ListRequest) returns (stream Character);
|
|
999
|
+
|
|
1000
|
+
// Client streaming
|
|
1001
|
+
rpc UploadInventory(stream Item) returns (UploadResponse);
|
|
1002
|
+
|
|
1003
|
+
// Bidirectional streaming
|
|
1004
|
+
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
message GetCharacterRequest {
|
|
1008
|
+
string id = 1;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
message ListRequest {
|
|
1012
|
+
int32 page_size = 1;
|
|
1013
|
+
string page_token = 2;
|
|
1014
|
+
}
|
|
1015
|
+
```
|
|
1016
|
+
|
|
1017
|
+
**Schema ID Format**: `proto-service:character.CharacterService@./character.proto`
|
|
1018
|
+
**RPC Format**: `proto-rpc:CharacterService.GetCharacter@./character.proto`
|
|
1019
|
+
|
|
1020
|
+
#### Well-Known Types
|
|
1021
|
+
|
|
1022
|
+
```protobuf
|
|
1023
|
+
import "google/protobuf/timestamp.proto";
|
|
1024
|
+
import "google/protobuf/duration.proto";
|
|
1025
|
+
import "google/protobuf/any.proto";
|
|
1026
|
+
import "google/protobuf/struct.proto";
|
|
1027
|
+
|
|
1028
|
+
message CharacterEvent {
|
|
1029
|
+
string character_id = 1;
|
|
1030
|
+
string event_type = 2;
|
|
1031
|
+
google.protobuf.Timestamp created_at = 3;
|
|
1032
|
+
google.protobuf.Duration duration = 4;
|
|
1033
|
+
google.protobuf.Any payload = 5;
|
|
1034
|
+
google.protobuf.Struct metadata = 6;
|
|
1035
|
+
}
|
|
1036
|
+
```
|
|
1037
|
+
|
|
1038
|
+
**Detected Elements:**
|
|
1039
|
+
- Messages with all field types (scalar, message, enum, repeated)
|
|
1040
|
+
- Enums with numeric values
|
|
1041
|
+
- `oneof` field groups
|
|
1042
|
+
- `map<K, V>` fields
|
|
1043
|
+
- Nested message definitions
|
|
1044
|
+
- Service definitions with all streaming modes:
|
|
1045
|
+
- Unary: `rpc Method(Request) returns (Response)`
|
|
1046
|
+
- Server streaming: `rpc Method(Request) returns (stream Response)`
|
|
1047
|
+
- Client streaming: `rpc Method(stream Request) returns (Response)`
|
|
1048
|
+
- Bidirectional: `rpc Method(stream Request) returns (stream Response)`
|
|
1049
|
+
- Well-known types: `Timestamp`, `Duration`, `Any`, `Struct`
|
|
1050
|
+
|
|
1051
|
+
**Usage Example:**
|
|
1052
|
+
|
|
1053
|
+
```typescript
|
|
1054
|
+
const result = await client.callTool("extract_schemas", {
|
|
1055
|
+
rootDir: "./proto",
|
|
1056
|
+
include: ["**/*.proto"],
|
|
1057
|
+
});
|
|
1058
|
+
// Returns messages, enums, and services
|
|
1059
|
+
```
|
|
1060
|
+
|
|
1061
|
+
---
|
|
1062
|
+
|
|
1063
|
+
### Python HTTP Clients (requests, httpx, aiohttp)
|
|
1064
|
+
|
|
1065
|
+
Trace HTTP client calls in Python code to detect consumer expectations.
|
|
1066
|
+
|
|
1067
|
+
#### requests Library
|
|
1068
|
+
|
|
1069
|
+
```python
|
|
1070
|
+
import requests
|
|
1071
|
+
|
|
1072
|
+
# Basic GET
|
|
1073
|
+
response = requests.get("https://api.example.com/characters")
|
|
1074
|
+
characters = response.json()
|
|
1075
|
+
|
|
1076
|
+
# GET with path parameter
|
|
1077
|
+
character = requests.get(f"https://api.example.com/characters/{char_id}").json()
|
|
1078
|
+
|
|
1079
|
+
# POST with JSON body
|
|
1080
|
+
new_char = requests.post(
|
|
1081
|
+
"https://api.example.com/characters",
|
|
1082
|
+
json={"name": "Hero", "class": "Fighter"}
|
|
1083
|
+
).json()
|
|
1084
|
+
|
|
1085
|
+
# Session with base URL
|
|
1086
|
+
session = requests.Session()
|
|
1087
|
+
session.headers.update({"Authorization": "Bearer token"})
|
|
1088
|
+
user = session.get("https://api.example.com/me").json()
|
|
1089
|
+
|
|
1090
|
+
# Property access tracking
|
|
1091
|
+
print(character["name"], character["stats"]["strength"])
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
**Schema ID Format**: `python-http:GET:/characters@./client.py`
|
|
1095
|
+
|
|
1096
|
+
#### httpx Library
|
|
1097
|
+
|
|
1098
|
+
```python
|
|
1099
|
+
import httpx
|
|
1100
|
+
|
|
1101
|
+
# Sync client
|
|
1102
|
+
response = httpx.get("https://api.example.com/characters")
|
|
1103
|
+
data = response.json()
|
|
1104
|
+
|
|
1105
|
+
# Async client
|
|
1106
|
+
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
|
|
1107
|
+
response = await client.get("/characters")
|
|
1108
|
+
characters = response.json()
|
|
1109
|
+
|
|
1110
|
+
response = await client.post("/characters", json={"name": "Hero"})
|
|
1111
|
+
new_char = response.json()
|
|
1112
|
+
```
|
|
1113
|
+
|
|
1114
|
+
**Schema ID Format**: `python-http:GET:/characters@./client.py`
|
|
1115
|
+
|
|
1116
|
+
#### aiohttp Library
|
|
1117
|
+
|
|
1118
|
+
```python
|
|
1119
|
+
import aiohttp
|
|
1120
|
+
|
|
1121
|
+
async with aiohttp.ClientSession() as session:
|
|
1122
|
+
# GET request
|
|
1123
|
+
async with session.get("https://api.example.com/characters") as response:
|
|
1124
|
+
characters = await response.json()
|
|
1125
|
+
|
|
1126
|
+
# POST request
|
|
1127
|
+
async with session.post(
|
|
1128
|
+
"https://api.example.com/characters",
|
|
1129
|
+
json={"name": "Hero", "class": "Fighter"}
|
|
1130
|
+
) as response:
|
|
1131
|
+
new_char = await response.json()
|
|
1132
|
+
|
|
1133
|
+
# Property access
|
|
1134
|
+
print(new_char["id"], new_char["name"])
|
|
1135
|
+
```
|
|
1136
|
+
|
|
1137
|
+
**Schema ID Format**: `python-http:POST:/characters@./client.py`
|
|
1138
|
+
|
|
1139
|
+
**Detected Elements:**
|
|
1140
|
+
- `requests.get()`, `requests.post()`, etc.
|
|
1141
|
+
- `httpx.get()`, `httpx.post()`, `AsyncClient` methods
|
|
1142
|
+
- `aiohttp.ClientSession` methods
|
|
1143
|
+
- URL extraction (static strings, f-strings)
|
|
1144
|
+
- HTTP method detection
|
|
1145
|
+
- Response property access (dictionary key access)
|
|
1146
|
+
|
|
1147
|
+
**Usage Example:**
|
|
1148
|
+
|
|
1149
|
+
```typescript
|
|
1150
|
+
const result = await client.callTool("trace_usage", {
|
|
1151
|
+
rootDir: "./python-client",
|
|
1152
|
+
include: ["**/*.py"],
|
|
1153
|
+
});
|
|
1154
|
+
// Returns HTTP client calls with property access patterns
|
|
1155
|
+
```
|
|
1156
|
+
|
|
1157
|
+
---
|
|
1158
|
+
|
|
1159
|
+
## Architecture
|
|
1160
|
+
|
|
1161
|
+
### Pattern Matcher Framework
|
|
1162
|
+
|
|
1163
|
+
The pattern matcher provides an extensible system for detecting code patterns across different frameworks. Located in [`src/patterns/`](src/patterns/):
|
|
1164
|
+
|
|
1165
|
+
```
|
|
1166
|
+
src/patterns/
|
|
1167
|
+
├── base.ts # BasePattern abstract class
|
|
1168
|
+
├── types.ts # PatternMatch, PatternContext interfaces
|
|
1169
|
+
├── registry.ts # PatternRegistry for plugin management
|
|
1170
|
+
├── extractors.ts # Node extractors for AST traversal
|
|
1171
|
+
├── errors.ts # Pattern-specific error types
|
|
1172
|
+
├── rest/ # Express, Fastify patterns
|
|
1173
|
+
├── http-clients/ # fetch, axios patterns
|
|
1174
|
+
└── graphql/ # Apollo patterns
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
**Supported Pattern Types:**
|
|
1178
|
+
- **Call patterns**: Function/method calls (`app.get()`, `fetch()`)
|
|
1179
|
+
- **Decorator patterns**: TypeScript/Python decorators (`@Controller()`)
|
|
1180
|
+
- **Property patterns**: Object property assignments
|
|
1181
|
+
- **Export patterns**: Module exports (`export const router = ...`)
|
|
1182
|
+
- **Chain patterns**: Method chaining (`router.get().post()`)
|
|
1183
|
+
|
|
1184
|
+
### Import Resolution
|
|
1185
|
+
|
|
1186
|
+
Cross-file type resolution with import graph building. Located in [`src/languages/import-resolver.ts`](src/languages/import-resolver.ts):
|
|
1187
|
+
|
|
1188
|
+
- Resolves `import { Type } from "./types"`
|
|
1189
|
+
- Handles barrel exports (`export * from`)
|
|
1190
|
+
- Supports path aliases via tsconfig.json
|
|
1191
|
+
- Detects and handles circular dependencies
|
|
1192
|
+
- Caches resolved types for performance
|
|
1193
|
+
|
|
1194
|
+
---
|
|
1195
|
+
|
|
1196
|
+
## Tools Reference
|
|
1197
|
+
|
|
1198
|
+
Trace MCP provides 11 tools organized into three categories:
|
|
1199
|
+
|
|
1200
|
+
### Core Analysis Tools
|
|
1201
|
+
|
|
1202
|
+
| Tool | Description |
|
|
1203
|
+
| ----------------- | ---------------------------------------------------- |
|
|
1204
|
+
| `extract_schemas` | Extract MCP tool definitions from server source code |
|
|
1205
|
+
| `extract_file` | Extract schemas from a single file |
|
|
1206
|
+
| `trace_usage` | Trace how client code uses MCP tools |
|
|
1207
|
+
| `trace_file` | Trace tool usage in a single file |
|
|
1208
|
+
| `compare` | Full pipeline: extract → trace → compare → report |
|
|
1209
|
+
|
|
1210
|
+
### Code Generation Tools
|
|
1211
|
+
|
|
1212
|
+
| Tool | Description |
|
|
1213
|
+
| ------------------- | ----------------------------------------------- |
|
|
1214
|
+
| `scaffold_consumer` | Generate client code from producer schema |
|
|
1215
|
+
| `scaffold_producer` | Generate server stub from client usage |
|
|
1216
|
+
| `comment_contract` | Add cross-reference comments to validated pairs |
|
|
1217
|
+
|
|
1218
|
+
### Project Management Tools
|
|
1219
|
+
|
|
1220
|
+
| Tool | Description |
|
|
1221
|
+
| -------------------- | ------------------------------------------------------- |
|
|
1222
|
+
| `init_project` | Initialize a trace project with `.trace-mcp` config |
|
|
1223
|
+
| `watch` | Watch files for changes and auto-revalidate |
|
|
1224
|
+
| `get_project_status` | Get project config, cache state, and validation results |
|
|
1225
|
+
|
|
1226
|
+
---
|
|
1227
|
+
|
|
1228
|
+
## Tool Details
|
|
1229
|
+
|
|
1230
|
+
### `extract_schemas`
|
|
1231
|
+
|
|
1232
|
+
Extract MCP tool definitions (ProducerSchemas) from server source code. Scans for `server.tool()` calls and parses their Zod schemas. Also supports OpenAPI, TypeScript interfaces, tRPC routers, REST endpoints, and GraphQL schemas.
|
|
1233
|
+
|
|
1234
|
+
**Parameters:**
|
|
1235
|
+
|
|
1236
|
+
- `rootDir` (required): Root directory of server source code
|
|
1237
|
+
- `include`: Glob patterns to include (default: `**/*.ts`)
|
|
1238
|
+
- `exclude`: Glob patterns to exclude (default: `node_modules`, `dist`)
|
|
1239
|
+
|
|
1240
|
+
**Example:**
|
|
1241
|
+
|
|
1242
|
+
```typescript
|
|
1243
|
+
const result = await client.callTool("extract_schemas", {
|
|
1244
|
+
rootDir: "./backend/src",
|
|
1245
|
+
});
|
|
1246
|
+
// Returns: { success: true, count: 12, schemas: [...] }
|
|
1247
|
+
```
|
|
1248
|
+
|
|
1249
|
+
---
|
|
1250
|
+
|
|
1251
|
+
### `extract_file`
|
|
1252
|
+
|
|
1253
|
+
Extract MCP tool definitions from a single TypeScript file.
|
|
1254
|
+
|
|
1255
|
+
**Parameters:**
|
|
1256
|
+
|
|
1257
|
+
- `filePath` (required): Path to a TypeScript file
|
|
1258
|
+
|
|
1259
|
+
---
|
|
1260
|
+
|
|
1261
|
+
### `trace_usage`
|
|
1262
|
+
|
|
1263
|
+
Trace how client code uses MCP tools. Finds `callTool()` invocations, HTTP client calls, and GraphQL hooks, tracking which properties are accessed on results.
|
|
1264
|
+
|
|
1265
|
+
**Parameters:**
|
|
1266
|
+
|
|
1267
|
+
- `rootDir` (required): Root directory of consumer source code
|
|
1268
|
+
- `include`: Glob patterns to include
|
|
1269
|
+
- `exclude`: Glob patterns to exclude
|
|
1270
|
+
|
|
1271
|
+
---
|
|
1272
|
+
|
|
1273
|
+
### `trace_file`
|
|
1274
|
+
|
|
1275
|
+
Trace MCP tool usage in a single TypeScript file.
|
|
1276
|
+
|
|
1277
|
+
**Parameters:**
|
|
1278
|
+
|
|
1279
|
+
- `filePath` (required): Path to a TypeScript file
|
|
1280
|
+
|
|
1281
|
+
---
|
|
1282
|
+
|
|
1283
|
+
### `compare`
|
|
1284
|
+
|
|
1285
|
+
Full analysis pipeline: extract producer schemas, trace consumer usage, and compare them to find mismatches.
|
|
1286
|
+
|
|
1287
|
+
**Parameters:**
|
|
1288
|
+
|
|
1289
|
+
- `producerDir` (required): Path to MCP server source directory
|
|
1290
|
+
- `consumerDir` (required): Path to consumer/client source directory
|
|
1291
|
+
- `format`: Output format (`json`, `markdown`, `summary`)
|
|
1292
|
+
- `strict`: Strict mode - treat missing optional properties as warnings
|
|
1293
|
+
- `direction`: Data flow direction (`producer_to_consumer`, `consumer_to_producer`, `bidirectional`)
|
|
1294
|
+
|
|
1295
|
+
**Example Output (Markdown):**
|
|
1296
|
+
|
|
1297
|
+
```markdown
|
|
1298
|
+
# mnehmos.trace.mcp Analysis Report
|
|
1299
|
+
|
|
1300
|
+
**Generated**: 2025-12-11T02:11:48.624Z
|
|
1301
|
+
|
|
1302
|
+
## Summary
|
|
1303
|
+
|
|
1304
|
+
| Metric | Count |
|
|
1305
|
+
| ----------- | ----- |
|
|
1306
|
+
| Total Tools | 12 |
|
|
1307
|
+
| Total Calls | 34 |
|
|
1308
|
+
| Matches | 31 |
|
|
1309
|
+
| Mismatches | 3 |
|
|
1310
|
+
|
|
1311
|
+
## Mismatches
|
|
1312
|
+
|
|
1313
|
+
### get_character
|
|
1314
|
+
|
|
1315
|
+
- **Type**: MISSING_PROPERTY
|
|
1316
|
+
- **Description**: Consumer expects "characterClass" but producer has "class"
|
|
1317
|
+
- **Consumer**: ./components/CharacterSheet.tsx:45
|
|
1318
|
+
- **Producer**: ./tools/character.ts:23
|
|
1319
|
+
```
|
|
1320
|
+
|
|
1321
|
+
---
|
|
1322
|
+
|
|
1323
|
+
### `scaffold_consumer`
|
|
1324
|
+
|
|
1325
|
+
Generate consumer code from a producer schema. Creates TypeScript functions, React hooks, or Zustand actions that correctly call MCP tools.
|
|
1326
|
+
|
|
1327
|
+
**Parameters:**
|
|
1328
|
+
|
|
1329
|
+
- `producerDir` (required): Path to MCP server source directory
|
|
1330
|
+
- `toolName` (required): Name of the tool to scaffold
|
|
1331
|
+
- `target`: Output format (`typescript`, `javascript`, `react-hook`, `zustand-action`)
|
|
1332
|
+
- `includeErrorHandling`: Include try/catch error handling (default: true)
|
|
1333
|
+
- `includeTypes`: Include TypeScript type definitions (default: true)
|
|
1334
|
+
|
|
1335
|
+
**Example Output:**
|
|
1336
|
+
|
|
1337
|
+
```typescript
|
|
1338
|
+
/**
|
|
1339
|
+
* Get character data
|
|
1340
|
+
* @trace-contract CONSUMER
|
|
1341
|
+
* Producer: ./server/character-tools.ts:23
|
|
1342
|
+
*/
|
|
1343
|
+
export async function getCharacter(
|
|
1344
|
+
client: McpClient,
|
|
1345
|
+
args: GetCharacterArgs
|
|
1346
|
+
): Promise<GetCharacterResult> {
|
|
1347
|
+
try {
|
|
1348
|
+
const result = await client.callTool("get_character", args);
|
|
1349
|
+
return JSON.parse(result.content[0].text);
|
|
1350
|
+
} catch (error) {
|
|
1351
|
+
console.error("Error calling get_character:", error);
|
|
1352
|
+
throw error;
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
```
|
|
1356
|
+
|
|
1357
|
+
---
|
|
1358
|
+
|
|
1359
|
+
### `scaffold_producer`
|
|
1360
|
+
|
|
1361
|
+
Generate producer schema stub from consumer usage. Creates MCP tool definition based on how client code calls it.
|
|
1362
|
+
|
|
1363
|
+
**Parameters:**
|
|
1364
|
+
|
|
1365
|
+
- `consumerDir` (required): Path to consumer source directory
|
|
1366
|
+
- `toolName` (required): Name of the tool to scaffold
|
|
1367
|
+
- `includeHandler`: Include handler stub (default: true)
|
|
1368
|
+
|
|
1369
|
+
**Example Output:**
|
|
1370
|
+
|
|
1371
|
+
```typescript
|
|
1372
|
+
import { z } from "zod";
|
|
1373
|
+
|
|
1374
|
+
// Tool: get_character
|
|
1375
|
+
// Scaffolded from consumer at ./components/CharacterSheet.tsx:14
|
|
1376
|
+
// @trace-contract PRODUCER (scaffolded)
|
|
1377
|
+
|
|
1378
|
+
server.tool(
|
|
1379
|
+
"get_character",
|
|
1380
|
+
"TODO: Add description",
|
|
1381
|
+
{
|
|
1382
|
+
characterId: z.string(),
|
|
1383
|
+
},
|
|
1384
|
+
async (args) => {
|
|
1385
|
+
// TODO: Implement handler
|
|
1386
|
+
// Consumer expects: name, race, level, stats, characterClass
|
|
1387
|
+
return {
|
|
1388
|
+
content: [
|
|
1389
|
+
{
|
|
1390
|
+
type: "text",
|
|
1391
|
+
text: JSON.stringify({
|
|
1392
|
+
name: null, // TODO
|
|
1393
|
+
race: null, // TODO
|
|
1394
|
+
level: null, // TODO
|
|
1395
|
+
}),
|
|
1396
|
+
},
|
|
1397
|
+
],
|
|
1398
|
+
};
|
|
1399
|
+
}
|
|
1400
|
+
);
|
|
1401
|
+
```
|
|
1402
|
+
|
|
1403
|
+
---
|
|
1404
|
+
|
|
1405
|
+
### `comment_contract`
|
|
1406
|
+
|
|
1407
|
+
Add cross-reference comments to validated producer/consumer pairs. Documents the contract relationship in both files.
|
|
1408
|
+
|
|
1409
|
+
**Parameters:**
|
|
1410
|
+
|
|
1411
|
+
- `producerDir` (required): Path to MCP server source directory
|
|
1412
|
+
- `consumerDir` (required): Path to consumer source directory
|
|
1413
|
+
- `toolName` (required): Name of the validated tool
|
|
1414
|
+
- `dryRun`: Preview without writing (default: true)
|
|
1415
|
+
- `style`: Comment style (`jsdoc`, `inline`, `block`)
|
|
1416
|
+
|
|
1417
|
+
**Example Preview:**
|
|
1418
|
+
|
|
1419
|
+
```javascript
|
|
1420
|
+
// Producer comment:
|
|
1421
|
+
/*
|
|
1422
|
+
* @trace-contract PRODUCER
|
|
1423
|
+
* Tool: get_character
|
|
1424
|
+
* Consumer: ./components/CharacterSheet.tsx:14
|
|
1425
|
+
* Args: characterId
|
|
1426
|
+
* Validated: 2025-12-11
|
|
1427
|
+
*/
|
|
1428
|
+
|
|
1429
|
+
// Consumer comment:
|
|
1430
|
+
/*
|
|
1431
|
+
* @trace-contract CONSUMER
|
|
1432
|
+
* Tool: get_character
|
|
1433
|
+
* Producer: ./server/character-tools.ts:23
|
|
1434
|
+
* Required Args: characterId
|
|
1435
|
+
* Validated: 2025-12-11
|
|
1436
|
+
*/
|
|
1437
|
+
```
|
|
1438
|
+
|
|
1439
|
+
---
|
|
1440
|
+
|
|
1441
|
+
### `init_project`
|
|
1442
|
+
|
|
1443
|
+
Initialize a trace project with `.trace-mcp` config directory for watch mode and caching.
|
|
1444
|
+
|
|
1445
|
+
**Parameters:**
|
|
1446
|
+
|
|
1447
|
+
- `projectDir` (required): Root directory for the trace project
|
|
1448
|
+
- `producerPath` (required): Relative path to producer/server code
|
|
1449
|
+
- `consumerPath` (required): Relative path to consumer/client code
|
|
1450
|
+
- `producerLanguage`: Language (`typescript`, `python`, `go`, `rust`, `json_schema`)
|
|
1451
|
+
- `consumerLanguage`: Language (`typescript`, `python`, `go`, `rust`, `json_schema`)
|
|
1452
|
+
|
|
1453
|
+
**Example:**
|
|
1454
|
+
|
|
1455
|
+
```typescript
|
|
1456
|
+
const result = await client.callTool("init_project", {
|
|
1457
|
+
projectDir: "./my-app",
|
|
1458
|
+
producerPath: "./backend/src",
|
|
1459
|
+
consumerPath: "./frontend/src",
|
|
1460
|
+
});
|
|
1461
|
+
// Creates: ./my-app/.trace-mcp/config.json
|
|
1462
|
+
```
|
|
1463
|
+
|
|
1464
|
+
---
|
|
1465
|
+
|
|
1466
|
+
### `watch`
|
|
1467
|
+
|
|
1468
|
+
Watch project files for changes and auto-revalidate contracts.
|
|
1469
|
+
|
|
1470
|
+
**Parameters:**
|
|
1471
|
+
|
|
1472
|
+
- `projectDir` (required): Root directory with `.trace-mcp` config
|
|
1473
|
+
- `action`: `start`, `stop`, `status`, or `poll`
|
|
1474
|
+
|
|
1475
|
+
**Actions:**
|
|
1476
|
+
|
|
1477
|
+
- `start`: Begin watching for file changes
|
|
1478
|
+
- `stop`: Stop watching
|
|
1479
|
+
- `status`: Check current watcher state
|
|
1480
|
+
- `poll`: Get pending events and last validation result
|
|
1481
|
+
|
|
1482
|
+
---
|
|
1483
|
+
|
|
1484
|
+
### `get_project_status`
|
|
1485
|
+
|
|
1486
|
+
Get the status of a trace project including config, cache state, and last validation result.
|
|
1487
|
+
|
|
1488
|
+
**Parameters:**
|
|
1489
|
+
|
|
1490
|
+
- `projectDir` (required): Root directory with `.trace-mcp` config
|
|
1491
|
+
|
|
1492
|
+
**Example Output:**
|
|
1493
|
+
|
|
1494
|
+
```json
|
|
1495
|
+
{
|
|
1496
|
+
"success": true,
|
|
1497
|
+
"exists": true,
|
|
1498
|
+
"projectDir": "/path/to/project",
|
|
1499
|
+
"config": {
|
|
1500
|
+
"producer": { "path": "./server", "language": "typescript" },
|
|
1501
|
+
"consumer": { "path": "./client", "language": "typescript" }
|
|
1502
|
+
},
|
|
1503
|
+
"isWatching": true,
|
|
1504
|
+
"watcherStatus": { "running": true, "pendingChanges": 0 }
|
|
1505
|
+
}
|
|
1506
|
+
```
|
|
1507
|
+
|
|
1508
|
+
---
|
|
1509
|
+
|
|
1510
|
+
## Typical Workflow
|
|
1511
|
+
|
|
1512
|
+
### 1. Quick One-Off Analysis
|
|
1513
|
+
|
|
1514
|
+
```typescript
|
|
1515
|
+
// Compare backend vs frontend, get markdown report
|
|
1516
|
+
const result = await client.callTool("compare", {
|
|
1517
|
+
producerDir: "./backend/src",
|
|
1518
|
+
consumerDir: "./frontend/src",
|
|
1519
|
+
format: "markdown",
|
|
1520
|
+
});
|
|
1521
|
+
```
|
|
1522
|
+
|
|
1523
|
+
### 2. Continuous Validation (Watch Mode)
|
|
1524
|
+
|
|
1525
|
+
```typescript
|
|
1526
|
+
// Initialize project
|
|
1527
|
+
await client.callTool("init_project", {
|
|
1528
|
+
projectDir: ".",
|
|
1529
|
+
producerPath: "./server",
|
|
1530
|
+
consumerPath: "./client",
|
|
1531
|
+
});
|
|
1532
|
+
|
|
1533
|
+
// Start watching
|
|
1534
|
+
await client.callTool("watch", {
|
|
1535
|
+
projectDir: ".",
|
|
1536
|
+
action: "start",
|
|
1537
|
+
});
|
|
1538
|
+
|
|
1539
|
+
// Later: poll for results
|
|
1540
|
+
const status = await client.callTool("watch", {
|
|
1541
|
+
projectDir: ".",
|
|
1542
|
+
action: "poll",
|
|
1543
|
+
});
|
|
1544
|
+
```
|
|
1545
|
+
|
|
1546
|
+
### 3. Generate Missing Code
|
|
1547
|
+
|
|
1548
|
+
```typescript
|
|
1549
|
+
// Generate client code from server schema
|
|
1550
|
+
const consumer = await client.callTool("scaffold_consumer", {
|
|
1551
|
+
producerDir: "./server",
|
|
1552
|
+
toolName: "get_character",
|
|
1553
|
+
target: "react-hook",
|
|
1554
|
+
});
|
|
1555
|
+
|
|
1556
|
+
// Or generate server stub from client usage
|
|
1557
|
+
const producer = await client.callTool("scaffold_producer", {
|
|
1558
|
+
consumerDir: "./client",
|
|
1559
|
+
toolName: "save_settings",
|
|
1560
|
+
});
|
|
1561
|
+
```
|
|
1562
|
+
|
|
1563
|
+
### 4. Extract Multiple Formats
|
|
1564
|
+
|
|
1565
|
+
```typescript
|
|
1566
|
+
// Extract from MCP server
|
|
1567
|
+
const mcpSchemas = await client.callTool("extract_schemas", {
|
|
1568
|
+
rootDir: "./backend/mcp",
|
|
1569
|
+
include: ["**/*.ts"],
|
|
1570
|
+
});
|
|
1571
|
+
|
|
1572
|
+
// Extract from OpenAPI specification
|
|
1573
|
+
const openApiSchemas = await client.callTool("extract_schemas", {
|
|
1574
|
+
rootDir: "./backend",
|
|
1575
|
+
include: ["**/*.openapi.yaml"],
|
|
1576
|
+
});
|
|
1577
|
+
|
|
1578
|
+
// Extract from tRPC router
|
|
1579
|
+
const trpcSchemas = await client.callTool("extract_schemas", {
|
|
1580
|
+
rootDir: "./backend/trpc",
|
|
1581
|
+
include: ["**/*.router.ts"],
|
|
1582
|
+
});
|
|
1583
|
+
|
|
1584
|
+
// Extract TypeScript interfaces
|
|
1585
|
+
const interfaceSchemas = await client.callTool("extract_schemas", {
|
|
1586
|
+
rootDir: "./shared",
|
|
1587
|
+
include: ["**/*.types.ts"],
|
|
1588
|
+
});
|
|
1589
|
+
|
|
1590
|
+
// Extract REST endpoints (Express/Fastify)
|
|
1591
|
+
const restSchemas = await client.callTool("extract_schemas", {
|
|
1592
|
+
rootDir: "./backend/routes",
|
|
1593
|
+
include: ["**/*.ts"],
|
|
1594
|
+
});
|
|
1595
|
+
|
|
1596
|
+
// Extract GraphQL schemas
|
|
1597
|
+
const graphqlSchemas = await client.callTool("extract_schemas", {
|
|
1598
|
+
rootDir: "./backend/graphql",
|
|
1599
|
+
include: ["**/*.graphql", "**/resolvers.ts"],
|
|
1600
|
+
});
|
|
1601
|
+
```
|
|
1602
|
+
|
|
1603
|
+
### 5. Full-Stack GraphQL Validation
|
|
1604
|
+
|
|
1605
|
+
```typescript
|
|
1606
|
+
// Extract GraphQL schema and resolvers
|
|
1607
|
+
const producer = await client.callTool("extract_schemas", {
|
|
1608
|
+
rootDir: "./backend",
|
|
1609
|
+
include: ["**/*.graphql", "**/resolvers/**/*.ts"],
|
|
1610
|
+
});
|
|
1611
|
+
|
|
1612
|
+
// Trace Apollo Client hooks
|
|
1613
|
+
const consumer = await client.callTool("trace_usage", {
|
|
1614
|
+
rootDir: "./frontend/src",
|
|
1615
|
+
include: ["**/*.tsx"],
|
|
1616
|
+
});
|
|
1617
|
+
|
|
1618
|
+
// Compare for schema drift
|
|
1619
|
+
const report = await client.callTool("compare", {
|
|
1620
|
+
producerDir: "./backend",
|
|
1621
|
+
consumerDir: "./frontend/src",
|
|
1622
|
+
format: "markdown",
|
|
1623
|
+
});
|
|
1624
|
+
```
|
|
1625
|
+
|
|
1626
|
+
---
|
|
1627
|
+
|
|
1628
|
+
## Roadmap
|
|
1629
|
+
|
|
1630
|
+
### Completed
|
|
1631
|
+
|
|
1632
|
+
- [x] MCP tool schema extraction
|
|
1633
|
+
- [x] Consumer usage tracing
|
|
1634
|
+
- [x] Basic mismatch detection
|
|
1635
|
+
- [x] Code scaffolding (consumer & producer)
|
|
1636
|
+
- [x] Contract comments
|
|
1637
|
+
- [x] Watch mode with auto-revalidation
|
|
1638
|
+
- [x] OpenAPI/Swagger adapter support
|
|
1639
|
+
- [x] TypeScript interface extraction
|
|
1640
|
+
- [x] tRPC router support
|
|
1641
|
+
- [x] Pluggable adapter registry
|
|
1642
|
+
- [x] Pattern Matcher abstraction (Phase 2)
|
|
1643
|
+
- [x] Cross-file import resolution (Phase 2)
|
|
1644
|
+
- [x] REST endpoint detection - Express & Fastify (Phase 2)
|
|
1645
|
+
- [x] HTTP client tracing - fetch & axios (Phase 2)
|
|
1646
|
+
- [x] GraphQL support - SDL, Apollo Server, Apollo Client (Phase 2)
|
|
1647
|
+
- [x] Python language support - FastAPI, Flask, MCP tools, Pydantic (Phase 3)
|
|
1648
|
+
- [x] Go language support - Chi, Gin, stdlib handlers, structs (Phase 3)
|
|
1649
|
+
- [x] gRPC/Protobuf support - proto3, messages, services, streaming (Phase 3)
|
|
1650
|
+
- [x] Python HTTP client tracing - requests, httpx, aiohttp (Phase 3)
|
|
1651
|
+
|
|
1652
|
+
### Planned
|
|
1653
|
+
|
|
1654
|
+
- [ ] JSON Schema adapter
|
|
1655
|
+
- [ ] WebSocket message tracing
|
|
1656
|
+
- [ ] OpenTelemetry integration
|
|
1657
|
+
- [ ] Rust language support
|
|
1658
|
+
- [ ] Java/Kotlin language support
|
|
1659
|
+
|
|
1660
|
+
## License
|
|
1661
|
+
|
|
1662
|
+
MIT
|