mnehmos.trace.mcp
静态分析引擎,用于检测数据生产者和消费者之间的模式不匹配。
它做什么
跟踪MCP发现以下各项之间不匹配:
- 后端API响应和前端期望
- MCP工具输出和使用它们的客户端代码
- 服务A的事件和服务B的处理程序
- REST端点和HTTP客户端调用
- GraphQL模式和Apollo客户端钩子
Producer returns: { characterClass: "Fighter", hitPoints: 45 }
Consumer expects: { class: "Fighter", hp: 45 }
Result: ❌ Mismatch detected before runtime特性
核心能力
| 特性 | 描述 |
|---|---|
| 模式提取 | 从MCP工具、OpenAPI、TypeScript、tRPC、REST端点、GraphQL中提取模式 |
| 使用情况跟踪 | 跟踪客户端代码如何通过属性访问模式使用模式 |
| 失配检测 | 将生产者模式与消费者期望进行比较 |
| 代码生成 | 从生产者模式构建消费者代码(反之亦然) |
| 观看模式 | 持续验证文件更改 |
第二阶段能力
| 特性 | 描述 |
|---|---|
| 模式匹配器 | 支持调用、装饰器、属性、导出和链模式的可扩展模式检测 |
| 导入分辨率 | 具有导入图构建和循环依赖处理的跨文件类型解析 |
| REST检测 | 通过验证中间件支持快速提取端点 |
| HTTP客户端跟踪 | fetch()和axios调用检测与URL提取和类型推断 |
| GraphQL支持 | SDL模式解析、Apollo服务器解析器和Apollo客户端钩子跟踪 |
第三阶段能力
| 特性 | 描述 |
|---|---|
| Python AST解析器 | 支持Pydantic模型的FastAPI、Flask和MCP工具提取 |
| Go语言分析器 | 使用Chi、Gin和stdlib HTTP处理程序检测进行结构/接口提取 |
| gRPC/Protobuf支持 | Proto3解析,包括消息、枚举、服务和流式RPC提取 |
| Python HTTP客户端 | 通过响应属性跟踪进行请求、httpx和aiohttp库检测 |
测试覆盖率
1047项测试通过 在16个测试套件中:
| 测试套件 | 测试 |
|---|---|
| 图案匹配器 | 85 |
| REST检测 | 87 |
| HTTP客户端跟踪 | 90 |
| GraphQL支持 | 109 |
| 导入分辨率 | 56 |
| 核心(适配器、OpenAPI、tRPC) | 234 |
| Python AST | 121 |
| gRPC/Protobuf | 124 |
| Go解析器 | 106 |
| Python HTTP客户端 | 35 |
安装
# Clone the repository
git clone https://github.com/Mnehmos/mnehmos.trace.mcp.git
# Navigate to the directory
cd mnehmos.trace.mcp
# Install dependencies
npm install
# Build the project
npm run build配置
添加到您的MCP客户端配置中(例如。, claude_desktop_config.json 或Roo代码设置):
{
"mcpServers": {
"trace-mcp": {
"command": "node",
"args": ["/path/to/trace-mcp/dist/index.js"],
"env": {}
}
}
}支持格式
Trace MCP通过可插拔适配器注册表支持跨多种规范格式的模式提取和比较。
支持的框架概述
| 类别 | 框架 |
|---|---|
| API规范 | OpenAPI 3.0+,Swagger |
| 远程过程调用 | MCP(Zod)、tRPC、gRPC/原蟾蜍 |
| REST服务器 | Express、Fastify、FastAPI、Flask、Chi、Gin、Go stdlib |
| HTTP客户端 | fetch()、axios、请求、httpx、aiohttp |
| 图查询语言 | SDL模式、Apollo服务器、Apollo客户端 |
| 类型系统 | TypeScript接口、Zod模式、Pydantic模型、Go结构 |
支持的语言
| 语言 | 生产者检测 | 消费者追踪 |
|---|---|---|
| TypeScript | MCP工具、tRPC、Express、Fastify、GraphQL解析器 | callTool()、fetch、axios、Apollo客户端 |
| python | FastAPI、Flask、MCP工具、Pydantic模型 | 请求、httpx、aiohttp |
| 走 | Chi、Gin、stdlib处理程序、结构体、接口 | -- |
| 协议缓冲区 | 消息、枚举、服务、流式RPC | -- |
______________________________________________________________________
MCP服务器架构(Zod)
使用Zod模式从服务器源代码中提取MCP工具定义。
server.tool(
"get_character",
"Fetch character data",
{
characterId: z.string().describe("Character ID"),
},
async (args) => {
// implementation
}
);架构ID格式: endpoint:GET:/tools/get_character@./server.ts
______________________________________________________________________
OpenAPI/Swagger规格
从OpenAPI 3.0+规范中提取模式,支持端点、请求体、响应和组件模式。
openapi: 3.0.0
info:
title: Character API
version: 1.0.0
paths:
/characters/{id}:
get:
parameters:
- name: id
in: path
schema:
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Character'
components:
schemas:
Character:
type: object
properties:
id:
type: string
name:
type: string
class:
type: string
required:
- id
- name
- class架构ID格式: endpoint:GET:/characters/{id}@./api.yaml
使用示例:
const result = await client.callTool("extract_schemas", {
rootDir: "./backend",
include: ["**/*.openapi.yaml", "**/*.swagger.json"],
});______________________________________________________________________
TypeScript接口和类型
从TypeScript源文件中提取导出的接口、类型别名和枚举。支持的实用程序类型包括 Pick, Omit, Partial, Required,以及 Record.
export interface Character {
id: string;
name: string;
class: "Fighter" | "Wizard" | "Rogue";
hitPoints: number;
stats: {
strength: number;
dexterity: number;
constitution: number;
};
}
export type ReadonlyCharacter = Readonly;
export enum CharacterClass {
Fighter = "Fighter",
Wizard = "Wizard",
Rogue = "Rogue",
}架构ID格式: interface:Character@./types.ts
支持的实用程序类型:
Pick-从界面中选择属性Omit-从界面中排除属性Partial-将所有属性设置为可选Required-将所有属性设置为必需Record-具有特定键和值类型的对象
使用示例:
const result = await client.callTool("extract_schemas", {
rootDir: "./shared",
include: ["**/*.ts", "**/*.tsx"],
});
// Returns interfaces with ID format: interface:CharacterClass@./types.ts______________________________________________________________________
tRPC路由器
从tRPC路由器中提取过程模式,包括输入/输出类型、查询、变异和订阅处理程序。处理嵌套路由器和中间件。
import { z } from "zod";
import { publicProcedure, router } from "./trpc";
export const appRouter = router({
users: router({
getById: publicProcedure
.input(z.string())
.output(z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
}))
.query(async ({ input }) => {
// implementation
}),
create: publicProcedure
.input(z.object({
name: z.string(),
email: z.string().email(),
}))
.output(z.object({
id: z.string(),
name: z.string(),
email: z.string(),
}))
.mutation(async ({ input }) => {
// implementation
}),
onChange: publicProcedure
.output(z.object({
userId: z.string(),
action: z.enum(["created", "updated", "deleted"]),
}))
.subscription(async () => {
// implementation
}),
}),
});架构ID格式: trpc:users.getById@./router.ts
检测到的元素:
- 路由器定义(
router({ ... })) - 嵌套路由器(
users: router({ ... })) - 程序(
.query(),.mutation(),.subscription()) - 输入模式(
.input(zod_schema)) - 输出模式(
.output(zod_schema))
使用示例:
const result = await client.callTool("extract_schemas", {
rootDir: "./backend/trpc",
include: ["**/*.router.ts"],
});
// Returns procedures with ID format: trpc:users.getById@./router.ts______________________________________________________________________
REST端点(快速和快速)
从Express和Fastify应用程序中提取端点模式,包括路由参数、请求体、响应类型和验证中间件。
快速
import express from "express";
import { z } from "zod";
const app = express();
// Basic route with typed response
app.get("/users/:id", (req, res) => {
const user: User = getUserById(req.params.id);
res.json(user);
});
// Route with Zod validation middleware
app.post("/users",
validate(z.object({
name: z.string(),
email: z.string().email(),
})),
(req, res) => {
res.status(201).json({ id: "123", ...req.body });
}
);
// Router-based routes
const router = express.Router();
router.get("/health", (req, res) => res.json({ status: "ok" }));
app.use("/api", router);架构ID格式: rest:GET:/users/:id@./app.ts
快车
import Fastify from "fastify";
const fastify = Fastify();
// Route with JSON Schema validation
fastify.post("/users", {
schema: {
body: {
type: "object",
properties: {
name: { type: "string" },
email: { type: "string", format: "email" },
},
required: ["name", "email"],
},
response: {
201: {
type: "object",
properties: {
id: { type: "string" },
name: { type: "string" },
},
},
},
},
}, async (request, reply) => {
return { id: "123", name: request.body.name };
});
// Shorthand methods
fastify.get("/health", async () => ({ status: "ok" }));架构ID格式: rest:POST:/users@./server.ts
检测到的元素:
- HTTP方法:GET、POST、PUT、PATCH、DELETE
- 路径参数(
:id,:userId) - 请求主体模式(Zod、Joi、celebrate、JSON模式)
- 响应类型推断
- 路由器前缀和安装
使用示例:
const result = await client.callTool("extract_schemas", {
rootDir: "./backend",
include: ["**/*.ts"],
});
// Returns endpoints with ID format: rest:GET:/users/:id@./routes.ts______________________________________________________________________
HTTP客户端(fetch和axios)
跟踪HTTP客户端调用,以检测消费者对API响应的期望。
fetch()API
// Basic fetch with type assertion
const response = await fetch("/api/users");
const users: User[] = await response.json();
// fetch with request options
const newUser = await fetch("/api/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "Alice" }),
}).then(res => res.json()) as CreateUserResponse;
// Template literal URLs
const userId = "123";
const user = await fetch(`/api/users/${userId}`).then(r => r.json());
// Property access tracking
console.log(user.name, user.email, user.profile.avatar);检测到的元素:
- URL提取(静态字符串、模板文字、变量)
- HTTP方法检测
- 类型断言和泛型
- 响应数据的属性访问模式
轴
import axios from "axios";
// Basic GET request
const { data: users } = await axios.get("/api/users");
// POST with typed response
const response = await axios.post("/api/users", {
name: "Bob",
email: "bob@example.com",
});
// Instance with base URL
const api = axios.create({ baseURL: "https://api.example.com" });
const profile = await api.get
("/me");
// Destructured property access
const { name, email } = response.data;架构ID格式: http-client:GET:/api/users@./client.ts
检测到的元素:
- axios方法:
.get(),.post(),.put(),.patch(),.delete() - 泛型类型参数(
axios.get) - 通过以下方式创建实例
axios.create() - 基本URL解析
- 响应数据属性访问
使用示例:
const result = await client.callTool("trace_usage", {
rootDir: "./frontend/src",
include: ["**/*.ts", "**/*.tsx"],
});
// Returns HTTP client calls with ID format: http-client:GET:/api/users@./api.ts______________________________________________________________________
GraphQL(SDL和Apollo)
从GraphQL SDL文件中提取模式,并跟踪Apollo服务器解析器和Apollo客户端钩子。
SDL架构文件
# schema.graphql
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
type Query {
user(id: ID!): User
users: [User!]!
post(id: ID!): Post
}
type Mutation {
createUser(name: String!, email: String!): User!
createPost(title: String!, content: String!, authorId: ID!): Post!
}架构ID格式: graphql:Query.user@./schema.graphql
Apollo服务器解析程序
import { ApolloServer } from "@apollo/server";
const resolvers = {
Query: {
user: async (_, { id }) => {
return db.users.findById(id);
},
users: async () => {
return db.users.findAll();
},
},
Mutation: {
createUser: async (_, { name, email }) => {
return db.users.create({ name, email });
},
},
User: {
posts: async (parent) => {
return db.posts.findByAuthor(parent.id);
},
},
};
const server = new ApolloServer({ typeDefs, resolvers });架构ID格式: graphql-resolver:Query.user@./resolvers.ts
阿波罗客户端挂钩
import { useQuery, useMutation, gql } from "@apollo/client";
const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
`;
const CREATE_USER = gql`
mutation CreateUser($name: String!, $email: String!) {
createUser(name: $name, email: $email) {
id
name
}
}
`;
function UserProfile({ userId }: { userId: string }) {
const { data, loading, error } = useQuery(GET_USER, {
variables: { id: userId },
});
const [createUser] = useMutation(CREATE_USER);
if (loading) return ;
if (error) return ;
return
{data.user.name}
;
}架构ID格式: graphql-client:GetUser@./UserProfile.tsx
检测到的元素:
- SDL类型:标量、对象、输入、枚举、接口、联合
- 查询和突变定义
- 字段参数和返回类型
- Apollo客户端挂钩:
useQuery,useMutation,useLazyQuery,useSubscription - 操作名称和变量
- 查询中的选定字段
使用示例:
// Extract GraphQL schemas
const schemas = await client.callTool("extract_schemas", {
rootDir: "./backend",
include: ["**/*.graphql", "**/resolvers.ts"],
});
// Trace Apollo Client usage
const usage = await client.callTool("trace_usage", {
rootDir: "./frontend/src",
include: ["**/*.tsx"],
});
// Compare for mismatches
const report = await client.callTool("compare", {
producerDir: "./backend",
consumerDir: "./frontend/src",
format: "markdown",
});______________________________________________________________________
Python(FastAPI、Flask、MCP工具)
使用完整的Pydantic模型支持从Python web框架和MCP工具定义中提取端点模式。
快速API
from fastapi import FastAPI, APIRouter
from pydantic import BaseModel
from typing import Optional, List
class Character(BaseModel):
id: str
name: str
character_class: str
level: int = 1
skills: List[str] = []
class CreateCharacterRequest(BaseModel):
name: str
character_class: str
background: Optional[str] = None
app = FastAPI()
router = APIRouter(prefix="/api/v1")
@app.get("/characters/{character_id}")
async def get_character(character_id: str) -> Character:
return Character(id=character_id, name="Hero", character_class="Fighter")
@router.post("/characters")
async def create_character(request: CreateCharacterRequest) -> Character:
return Character(id="123", name=request.name, character_class=request.character_class)
app.include_router(router)架构ID格式: python:GET:/characters/{character_id}@./main.py
烧瓶
from flask import Flask, Blueprint, request, jsonify
app = Flask(__name__)
api = Blueprint("api", __name__, url_prefix="/api")
@app.route("/health")
def health_check():
return jsonify({"status": "ok"})
@api.route("/users/", methods=["GET"])
def get_user(user_id):
return jsonify({"id": user_id, "name": "Alice"})
@api.route("/users", methods=["POST"])
def create_user():
data = request.get_json()
return jsonify({"id": "123", **data}), 201
app.register_blueprint(api)架构ID格式: python:GET:/api/users/@./app.py
MCP工具(Python)
from mcp import Server
server = Server("character-tools")
@server.tool()
async def get_character(character_id: str) -> dict:
"""Fetch character data by ID."""
return {"id": character_id, "name": "Hero", "class": "Fighter"}
@mcp.tool()
def roll_dice(dice: str, modifier: int = 0) -> dict:
"""Roll dice with optional modifier."""
return {"result": 15, "expression": dice, "modifier": modifier}架构ID格式: python-mcp:get_character@./tools.py
Pydantic模型
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Union, Literal
from enum import Enum
class CharacterClass(str, Enum):
FIGHTER = "Fighter"
WIZARD = "Wizard"
ROGUE = "Rogue"
class Stats(BaseModel):
strength: int = Field(ge=1, le=20)
dexterity: int = Field(ge=1, le=20)
constitution: int = Field(ge=1, le=20)
class Character(BaseModel):
id: str
name: str
character_class: CharacterClass
level: int = Field(default=1, ge=1, le=20)
stats: Stats
equipment: List[str] = []
metadata: Optional[Dict[str, str]] = None检测到的元素:
- 装饰人员:
@app.get(),@app.post(),@router.*,@app.route(),@blueprint.route() - MCP装饰师:
@mcp.tool(),@server.tool() - 派丹蒂克
BaseModel带字段提取的类 - 类型注释:
Optional,Union,List,Dict,Literal - 枚举类型的
使用示例:
const result = await client.callTool("extract_schemas", {
rootDir: "./backend",
include: ["**/*.py"],
});
// Returns endpoints with ID format: python:GET:/characters/{id}@./main.py______________________________________________________________________
Go语言(池、金、stdlib)
从Go源文件中提取结构定义、接口和HTTP端点模式。
带有JSON标签的结构
package models
type Character struct {
ID string `json:"id"`
Name string `json:"name"`
Class string `json:"class"`
Level int `json:"level"`
HitPoints int `json:"hp"`
Skills []string `json:"skills,omitempty"`
}
type Stats struct {
Strength int `json:"str"`
Dexterity int `json:"dex"`
Constitution int `json:"con"`
}
// Embedded struct
type CharacterWithStats struct {
Character
Stats Stats `json:"stats"`
}架构ID格式: go-struct:Character@./models/character.go
接口
package services
type CharacterService interface {
GetByID(id string) (*Character, error)
Create(req CreateRequest) (*Character, error)
Update(id string, req UpdateRequest) (*Character, error)
Delete(id string) error
}
type Repository interface {
Find(query Query) ([]Character, error)
Save(character *Character) error
}架构ID格式: go-interface:CharacterService@./services/character.go
stdlib HTTP处理程序
package main
import (
"encoding/json"
"net/http"
)
func main() {
http.HandleFunc("/health", healthHandler)
http.HandleFunc("/api/characters", charactersHandler)
http.HandleFunc("/api/characters/", characterByIDHandler)
http.ListenAndServe(":8080", nil)
}
func healthHandler(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
}
func charactersHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
// List characters
case http.MethodPost:
// Create character
}
}架构ID格式: go-http:GET:/health@./main.go
Chi路由器
package main
import (
"github.com/go-chi/chi/v5"
"net/http"
)
func main() {
r := chi.NewRouter()
r.Get("/health", healthHandler)
r.Route("/api/characters", func(r chi.Router) {
r.Get("/", listCharacters)
r.Post("/", createCharacter)
r.Get("/{id}", getCharacter) // Chi param: {id}
r.Put("/{id}", updateCharacter)
r.Delete("/{id}", deleteCharacter)
})
http.ListenAndServe(":8080", r)
}架构ID格式: go-http:GET:/api/characters/{id}@./main.go
Gin框架
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/health", healthHandler)
api := r.Group("/api")
{
api.GET("/characters", listCharacters)
api.POST("/characters", createCharacter)
api.GET("/characters/:id", getCharacter) // Gin param: :id
api.PUT("/characters/:id", updateCharacter)
api.DELETE("/characters/:id", deleteCharacter)
}
r.Run(":8080")
}架构ID格式: go-http:GET:/api/characters/:id@./main.go
检测到的元素:
- 带有JSON标签的结构定义
- 嵌入式结构
- 接口定义
http.HandleFunc()模式- Chi路由器:
r.Get(),r.Post(),r.Route(),{param}语法 - 杜松子酒框架:
r.GET(),r.POST(),r.Group(),:param语法
使用示例:
const result = await client.callTool("extract_schemas", {
rootDir: "./backend",
include: ["**/*.go"],
});
// Returns structs, interfaces, and endpoints______________________________________________________________________
gRPC/Protobuf
解析协议缓冲区定义(proto3)以提取消息类型、枚举、服务和RPC方法。
基本消息
syntax = "proto3";
package character;
message Character {
string id = 1;
string name = 2;
CharacterClass character_class = 3;
int32 level = 4;
Stats stats = 5;
repeated string skills = 6;
}
message Stats {
int32 strength = 1;
int32 dexterity = 2;
int32 constitution = 3;
}架构ID格式: proto-message:character.Character@./character.proto
枚举
enum CharacterClass {
CHARACTER_CLASS_UNSPECIFIED = 0;
CHARACTER_CLASS_FIGHTER = 1;
CHARACTER_CLASS_WIZARD = 2;
CHARACTER_CLASS_ROGUE = 3;
}
enum DamageType {
DAMAGE_TYPE_UNSPECIFIED = 0;
DAMAGE_TYPE_SLASHING = 1;
DAMAGE_TYPE_PIERCING = 2;
DAMAGE_TYPE_FIRE = 3;
}架构ID格式: proto-enum:character.CharacterClass@./character.proto
一个和地图字段
message Equipment {
string id = 1;
string name = 2;
oneof item_type {
Weapon weapon = 10;
Armor armor = 11;
Consumable consumable = 12;
}
}
message Inventory {
string character_id = 1;
map item_counts = 2;
map equipped = 3;
}架构ID格式: proto-message:character.Equipment@./equipment.proto
服务和RPC
service CharacterService {
// Unary RPC
rpc GetCharacter(GetCharacterRequest) returns (Character);
// Server streaming
rpc ListCharacters(ListRequest) returns (stream Character);
// Client streaming
rpc UploadInventory(stream Item) returns (UploadResponse);
// Bidirectional streaming
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}
message GetCharacterRequest {
string id = 1;
}
message ListRequest {
int32 page_size = 1;
string page_token = 2;
}架构ID格式: proto-service:character.CharacterService@./character.proto RPC格式: proto-rpc:CharacterService.GetCharacter@./character.proto
知名类型
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/any.proto";
import "google/protobuf/struct.proto";
message CharacterEvent {
string character_id = 1;
string event_type = 2;
google.protobuf.Timestamp created_at = 3;
google.protobuf.Duration duration = 4;
google.protobuf.Any payload = 5;
google.protobuf.Struct metadata = 6;
}检测到的元素:
- 具有所有字段类型(标量、消息、枚举、重复)的消息
- 带数值的枚举
oneof字段组map领域- 嵌套消息定义
- 所有流媒体模式的服务定义:
- Unary: rpc Method(Request) returns (Response) - 服务器流媒体: rpc Method(Request) returns (stream Response) - 客户端流媒体: rpc Method(stream Request) returns (Response) - 双向: rpc Method(stream Request) returns (stream Response)
- 众所周知的类型:
Timestamp,Duration,Any,Struct
使用示例:
const result = await client.callTool("extract_schemas", {
rootDir: "./proto",
include: ["**/*.proto"],
});
// Returns messages, enums, and services______________________________________________________________________
Python HTTP客户端(请求、httpx、aiohttp)
在Python代码中跟踪HTTP客户端调用,以检测消费者的期望。
请求库
import requests
# Basic GET
response = requests.get("https://api.example.com/characters")
characters = response.json()
# GET with path parameter
character = requests.get(f"https://api.example.com/characters/{char_id}").json()
# POST with JSON body
new_char = requests.post(
"https://api.example.com/characters",
json={"name": "Hero", "class": "Fighter"}
).json()
# Session with base URL
session = requests.Session()
session.headers.update({"Authorization": "Bearer token"})
user = session.get("https://api.example.com/me").json()
# Property access tracking
print(character["name"], character["stats"]["strength"])架构ID格式: python-http:GET:/characters@./client.py
httpx库
import httpx
# Sync client
response = httpx.get("https://api.example.com/characters")
data = response.json()
# Async client
async with httpx.AsyncClient(base_url="https://api.example.com") as client:
response = await client.get("/characters")
characters = response.json()
response = await client.post("/characters", json={"name": "Hero"})
new_char = response.json()架构ID格式: python-http:GET:/characters@./client.py
aiohttp库
import aiohttp
async with aiohttp.ClientSession() as session:
# GET request
async with session.get("https://api.example.com/characters") as response:
characters = await response.json()
# POST request
async with session.post(
"https://api.example.com/characters",
json={"name": "Hero", "class": "Fighter"}
) as response:
new_char = await response.json()
# Property access
print(new_char["id"], new_char["name"])架构ID格式: python-http:POST:/characters@./client.py
检测到的元素:
requests.get(),requests.post()等等。httpx.get(),httpx.post(),AsyncClient方法aiohttp.ClientSession方法- URL提取(静态字符串、f字符串)
- HTTP方法检测
- 响应属性访问(字典键访问)
使用示例:
const result = await client.callTool("trace_usage", {
rootDir: "./python-client",
include: ["**/*.py"],
});
// Returns HTTP client calls with property access patterns______________________________________________________________________
建筑
模式匹配器框架
模式匹配器提供了一个可扩展的系统,用于检测跨不同框架的代码模式。位于 src/patterns/:
src/patterns/
├── base.ts # BasePattern abstract class
├── types.ts # PatternMatch, PatternContext interfaces
├── registry.ts # PatternRegistry for plugin management
├── extractors.ts # Node extractors for AST traversal
├── errors.ts # Pattern-specific error types
├── rest/ # Express, Fastify patterns
├── http-clients/ # fetch, axios patterns
└── graphql/ # Apollo patterns支持的图案类型:
- 通话模式:函数/方法调用(
app.get(),fetch()) - 装饰图案:Types/Python装饰器(
@Controller()) - 房地产模式:对象属性分配
- 出口模式:模块导出(
export const router = ...) - 链式图案:方法链(
router.get().post())
导入分辨率
跨文件类型解析与导入图形构建。位于 src/languages/import-resolver.ts:
- 解决
import { Type } from "./types" - 处理桶出口(
export * from) - 通过tsconfig.json支持路径别名
- 检测和处理循环依赖关系
- 缓存解析类型以提高性能
______________________________________________________________________
工具参考
Trace MCP提供11种工具,分为三类:
岩心分析工具
| 工具 | 说明 |
|---|---|
extract_schemas | 从服务器源代码中提取MCP工具定义 |
extract_file | 从单个文件中提取模式 |
trace_usage | 跟踪客户端代码如何使用MCP工具 |
trace_file | 在单个文件中跟踪工具使用情况 |
compare | 完整管道:提取→ 痕迹→ 比较→ 报告 |
代码生成工具
| 工具 | 说明 |
|---|---|
scaffold_consumer | 从生产者模式生成客户端代码 |
scaffold_producer | 根据客户端使用情况生成服务器存根 |
comment_contract | 为已验证的配对添加交叉引用注释 |
项目管理工具
| 工具 | 说明 |
|---|---|
init_project | 使用初始化跟踪项目 .trace-mcp config |
watch | 监视文件的更改并自动重新验证 |
get_project_status | 获取项目配置、缓存状态和验证结果 |
______________________________________________________________________
工具详细信息
extract_schemas
从服务器源代码中提取MCP工具定义(ProducerSchemas)。扫描 server.tool() 调用并解析它们的Zod模式。还支持OpenAPI、TypeScript接口、tRPC路由器、REST端点和GraphQL模式。
参数:
rootDir(必填):服务器源代码根目录include:要包含的球形图案(默认值:**/*.ts)exclude:要排除的球形图案(默认值:node_modules,dist)
例子:
const result = await client.callTool("extract_schemas", {
rootDir: "./backend/src",
});
// Returns: { success: true, count: 12, schemas: [...] }______________________________________________________________________
extract_file
从单个TypeScript文件中提取MCP工具定义。
参数:
filePath(必填):TypeScript文件的路径
______________________________________________________________________
trace_usage
跟踪客户端代码如何使用MCP工具。查找 callTool() 调用、HTTP客户端调用和GraphQL挂钩,跟踪在结果上访问哪些属性。
参数:
rootDir(必填):消费者源代码的根目录include:球状图案包括exclude:要排除的球形图案
______________________________________________________________________
trace_file
在单个TypeScript文件中跟踪MCP工具的使用情况。
参数:
filePath(必填):TypeScript文件的路径
______________________________________________________________________
compare
完整的分析管道:提取生产者模式,跟踪消费者使用情况,并对其进行比较以发现不匹配。
参数:
producerDir(必需):MCP服务器源目录的路径consumerDir(必需):消费者/客户端源目录的路径format:输出格式(json,markdown,summary)strict:严格模式-将缺少的可选属性视为警告direction:数据流向(producer_to_consumer,consumer_to_producer,bidirectional)
示例输出(Markdown):
# mnehmos.trace.mcp Analysis Report
**Generated**: 2025-12-11T02:11:48.624Z
## Summary
| Metric | Count |
| ----------- | ----- |
| Total Tools | 12 |
| Total Calls | 34 |
| Matches | 31 |
| Mismatches | 3 |
## Mismatches
### get_character
- **Type**: MISSING_PROPERTY
- **Description**: Consumer expects "characterClass" but producer has "class"
- **Consumer**: ./components/CharacterSheet.tsx:45
- **Producer**: ./tools/character.ts:23______________________________________________________________________
scaffold_consumer
从生产者模式生成消费者代码。创建正确调用MCP工具的TypeScript函数、React钩子或Zustand操作。
参数:
producerDir(必需):MCP服务器源目录的路径toolName(必填):脚手架工具名称target:输出格式(typescript,javascript,react-hook,zustand-action)includeErrorHandling:包括try/catch错误处理(默认值:true)includeTypes:包括TypeScript类型定义(默认值:true)
输出示例:
/**
* Get character data
* @trace-contract CONSUMER
* Producer: ./server/character-tools.ts:23
*/
export async function getCharacter(
client: McpClient,
args: GetCharacterArgs
): Promise {
try {
const result = await client.callTool("get_character", args);
return JSON.parse(result.content[0].text);
} catch (error) {
console.error("Error calling get_character:", error);
throw error;
}
}______________________________________________________________________
scaffold_producer
根据消费者使用情况生成生产者模式存根。根据客户端代码调用MCP工具的方式创建MCP工具定义。
参数:
consumerDir(必填):消费者源目录的路径toolName(必填):脚手架工具名称includeHandler:包含处理程序存根(默认值:true)
输出示例:
import { z } from "zod";
// Tool: get_character
// Scaffolded from consumer at ./components/CharacterSheet.tsx:14
// @trace-contract PRODUCER (scaffolded)
server.tool(
"get_character",
"TODO: Add description",
{
characterId: z.string(),
},
async (args) => {
// TODO: Implement handler
// Consumer expects: name, race, level, stats, characterClass
return {
content: [
{
type: "text",
text: JSON.stringify({
name: null, // TODO
race: null, // TODO
level: null, // TODO
}),
},
],
};
}
);______________________________________________________________________
comment_contract
为已验证的生产者/消费者对添加交叉引用注释。在两个文件中记录合同关系。
参数:
producerDir(必需):MCP服务器源目录的路径consumerDir(必填):消费者源目录的路径toolName(必填):已验证工具的名称dryRun:不写预览(默认值:true)style:评论风格(jsdoc,inline,block)
示例预览:
// Producer comment:
/*
* @trace-contract PRODUCER
* Tool: get_character
* Consumer: ./components/CharacterSheet.tsx:14
* Args: characterId
* Validated: 2025-12-11
*/
// Consumer comment:
/*
* @trace-contract CONSUMER
* Tool: get_character
* Producer: ./server/character-tools.ts:23
* Required Args: characterId
* Validated: 2025-12-11
*/______________________________________________________________________
init_project
使用初始化跟踪项目 .trace-mcp 用于监视模式和缓存的配置目录。
参数:
projectDir(必需):跟踪项目的根目录producerPath(必填):生产者/服务器代码的相对路径consumerPath(必填):消费者/客户代码的相对路径producerLanguage:语言(typescript,python,go,rust,json_schema)consumerLanguage:语言(typescript,python,go,rust,json_schema)
例子:
const result = await client.callTool("init_project", {
projectDir: "./my-app",
producerPath: "./backend/src",
consumerPath: "./frontend/src",
});
// Creates: ./my-app/.trace-mcp/config.json______________________________________________________________________
watch
监视项目文件的更改并自动重新验证合同。
参数:
projectDir(必填):根目录.trace-mcp配置action:start,stop,status,或poll
行动:
start:开始监视文件更改stop:停止观看status:检查当前观察者状态poll:获取待处理事件和上次验证结果
______________________________________________________________________
get_project_status
获取跟踪项目的状态,包括配置、缓存状态和上次验证结果。
参数:
projectDir(必填):根目录.trace-mcp配置
输出示例:
{
"success": true,
"exists": true,
"projectDir": "/path/to/project",
"config": {
"producer": { "path": "./server", "language": "typescript" },
"consumer": { "path": "./client", "language": "typescript" }
},
"isWatching": true,
"watcherStatus": { "running": true, "pendingChanges": 0 }
}______________________________________________________________________
典型工作流程
1.快速一次性分析
// Compare backend vs frontend, get markdown report
const result = await client.callTool("compare", {
producerDir: "./backend/src",
consumerDir: "./frontend/src",
format: "markdown",
});2.连续验证(监视模式)
// Initialize project
await client.callTool("init_project", {
projectDir: ".",
producerPath: "./server",
consumerPath: "./client",
});
// Start watching
await client.callTool("watch", {
projectDir: ".",
action: "start",
});
// Later: poll for results
const status = await client.callTool("watch", {
projectDir: ".",
action: "poll",
});3.生成缺失代码
// Generate client code from server schema
const consumer = await client.callTool("scaffold_consumer", {
producerDir: "./server",
toolName: "get_character",
target: "react-hook",
});
// Or generate server stub from client usage
const producer = await client.callTool("scaffold_producer", {
consumerDir: "./client",
toolName: "save_settings",
});4.提取多种格式
// Extract from MCP server
const mcpSchemas = await client.callTool("extract_schemas", {
rootDir: "./backend/mcp",
include: ["**/*.ts"],
});
// Extract from OpenAPI specification
const openApiSchemas = await client.callTool("extract_schemas", {
rootDir: "./backend",
include: ["**/*.openapi.yaml"],
});
// Extract from tRPC router
const trpcSchemas = await client.callTool("extract_schemas", {
rootDir: "./backend/trpc",
include: ["**/*.router.ts"],
});
// Extract TypeScript interfaces
const interfaceSchemas = await client.callTool("extract_schemas", {
rootDir: "./shared",
include: ["**/*.types.ts"],
});
// Extract REST endpoints (Express/Fastify)
const restSchemas = await client.callTool("extract_schemas", {
rootDir: "./backend/routes",
include: ["**/*.ts"],
});
// Extract GraphQL schemas
const graphqlSchemas = await client.callTool("extract_schemas", {
rootDir: "./backend/graphql",
include: ["**/*.graphql", "**/resolvers.ts"],
});5.全栈GraphQL验证
// Extract GraphQL schema and resolvers
const producer = await client.callTool("extract_schemas", {
rootDir: "./backend",
include: ["**/*.graphql", "**/resolvers/**/*.ts"],
});
// Trace Apollo Client hooks
const consumer = await client.callTool("trace_usage", {
rootDir: "./frontend/src",
include: ["**/*.tsx"],
});
// Compare for schema drift
const report = await client.callTool("compare", {
producerDir: "./backend",
consumerDir: "./frontend/src",
format: "markdown",
});______________________________________________________________________
路线图
完成
- \[x\] MCP工具模式提取
- \[x\] 消费者使用追踪
- \[x\] 基本不匹配检测
- \[x\] 代码脚手架(消费者和生产者)
- \[x\] 合同意见
- \[x\] 具有自动重新验证功能的监视模式
- \[x\] OpenAPI/Swagger适配器支持
- \[x\] TypeScript接口提取
- \[x\] tRPC路由器支持
- \[x\] 可插拔适配器注册表
- \[x\] 模式匹配器抽象(第2阶段)
- \[x\] 跨文件导入解析(第2阶段)
- \[x\] REST端点检测-快速和快速(第2阶段)
- \[x\] HTTP客户端跟踪-获取和axios(第2阶段)
- \[x\] GraphQL支持-SDL、Apollo服务器、Apollo客户端(第2阶段)
- \[x\] Python语言支持-FastAPI、Flask、MCP工具、Pydantic(第3阶段)
- \[x\] Go语言支持-Chi、Gin、stdlib处理程序、结构(第3阶段)
- \[x\] gRPC/Protobuf支持-proto3、消息、服务、流媒体(第3阶段)
- \[x\] Python HTTP客户端跟踪-请求、httpx、aiohttp(第3阶段)
计划的
- \[\]JSON模式适配器
- \[\]WebSocket消息跟踪
- \[\]OpenTetry集成
- \[\]Rust语言支持
- \[\]Java/Kotlin语言支持
许可证
麻省理工学院
